diff --git a/sqlalchemy_jsonapi/tests/app.py b/sqlalchemy_jsonapi/tests/app.py index 7624994..cbf9663 100644 --- a/sqlalchemy_jsonapi/tests/app.py +++ b/sqlalchemy_jsonapi/tests/app.py @@ -9,7 +9,7 @@ from flask import Flask, request from flask_sqlalchemy import SQLAlchemy -from sqlalchemy import Boolean, Column, ForeignKey, Unicode, UnicodeText +from sqlalchemy import Boolean, Column, ForeignKey, Unicode, UnicodeText, Table from sqlalchemy.ext.hybrid import hybrid_property from sqlalchemy.orm import backref, relationship, validates from sqlalchemy_jsonapi import ( @@ -92,6 +92,10 @@ def allow_delete(self): """ Just like a popular social media site, we won't delete users. """ return False +PostTags = Table('post_tag', db.Model.metadata, + Column('post_id', UUIDType, ForeignKey('posts.id')), + Column('tag_id', UUIDType, ForeignKey('tags.id')) + ) class BlogPost(Timestamp, db.Model): """Post model, as if this is a blog.""" @@ -110,6 +114,10 @@ class BlogPost(Timestamp, db.Model): backref=backref('posts', lazy='dynamic')) + tags = relationship("BlogTag", + secondary=PostTags, + back_populates="posts") + @validates('title') def validate_title(self, key, title): """Keep titles from getting too long.""" @@ -126,6 +134,18 @@ def allow_view(self): def prevent_altering_of_logs(self): return False +class BlogTag(Timestamp, db.Model): + """Blogs can have tags now""" + + __tablename__ = 'tags' + + id = Column(UUIDType, default=uuid4, primary_key=True) + slug = Column(Unicode(100), unique=True) + description = Column(UnicodeText) + + posts = relationship("BlogPost", + secondary=PostTags, + back_populates="tags") class BlogComment(Timestamp, db.Model): """Comment for each Post.""" diff --git a/sqlalchemy_jsonapi/tests/conftest.py b/sqlalchemy_jsonapi/tests/conftest.py index 7ab0b43..58994b3 100644 --- a/sqlalchemy_jsonapi/tests/conftest.py +++ b/sqlalchemy_jsonapi/tests/conftest.py @@ -12,7 +12,7 @@ from flask.testing import FlaskClient from sqlalchemy.orm import sessionmaker from app import db as db_ -from app import app, User, BlogPost, BlogComment, Log +from app import app, User, BlogPost, BlogComment, BlogTag, Log from faker import Faker Session = sessionmaker() @@ -116,6 +116,13 @@ def bunch_of_posts(user, session): BlogComment(author=user, content=fake.paragraph())) session.commit() +@pytest.fixture +def bunch_of_tags(session): + tags = [BlogTag(slug=fake.word(), description=fake.text()) for x in range(3)] + for tag in tags: + session.add(tag) + session.commit() + return tags @pytest.fixture def comment(user, post, session): diff --git a/sqlalchemy_jsonapi/tests/test_collection_post.py b/sqlalchemy_jsonapi/tests/test_collection_post.py index ebacbcb..e904fc5 100644 --- a/sqlalchemy_jsonapi/tests/test_collection_post.py +++ b/sqlalchemy_jsonapi/tests/test_collection_post.py @@ -57,6 +57,43 @@ def test_200_resource_creation_with_relationships(user, client): 'id' ] == str(user.id) +def test_200_resource_creation_with_relationship_array(user, bunch_of_tags, client): + payload = { + 'data': { + 'type': 'blog-posts', + 'attributes': { + 'title': 'Some title', + 'content': 'Hello, World!', + 'is-published': True + }, + 'relationships': { + 'author': { + 'data': { + 'type': 'users', + 'id': str(user.id) + } + }, + 'tags': { + 'data': [{ + 'type': 'blog-tags', + 'id': str(tag.id) + } for tag in bunch_of_tags + ] + } + } + } + } + response = client.post( + '/api/blog-posts/', data=json.dumps(payload), + content_type='application/vnd.api+json').validate(201) + assert response.json_data['data']['type'] == 'blog-posts' + post_id = response.json_data['data']['id'] + response = client.get( + '/api/blog-posts/{}/?include=author'.format(post_id)).validate(200) + assert response.json_data['data']['relationships']['author']['data'][ + 'id' + ] == str(user.id) + def test_403_when_access_is_denied(client): payload = {'data': {'type': 'logs'}}