diff --git a/backend/src/db/seed.js b/backend/src/db/seed.js index 75671d098..82d6239c2 100644 --- a/backend/src/db/seed.js +++ b/backend/src/db/seed.js @@ -386,86 +386,98 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl'] const [p0, p1, p3, p4, p5, p6, p9, p10, p11, p13, p14, p15] = await Promise.all([ factory.create('Post', { - author: peterLustig, id: 'p0', language: sample(languages), image: faker.image.unsplash.food(300, 169), - categoryIds: ['cat16'], imageBlurred: true, imageAspectRatio: 300 / 169, + }, { + categoryIds: ['cat16'], + author: peterLustig, }), factory.create('Post', { - author: bobDerBaumeister, id: 'p1', language: sample(languages), image: faker.image.unsplash.technology(300, 1500), - categoryIds: ['cat1'], imageAspectRatio: 300 / 1500, + }, { + categoryIds: ['cat1'], + author: bobDerBaumeister, }), factory.create('Post', { - author: huey, id: 'p3', language: sample(languages), + }, { categoryIds: ['cat3'], + author: huey, }), factory.create('Post', { - author: dewey, id: 'p4', language: sample(languages), + }, { categoryIds: ['cat4'], + author: dewey, }), factory.create('Post', { - author: louie, id: 'p5', language: sample(languages), + }, { categoryIds: ['cat5'], + author: louie, }), factory.create('Post', { - authorId: 'u1', id: 'p6', language: sample(languages), image: faker.image.unsplash.buildings(300, 857), - categoryIds: ['cat6'], imageAspectRatio: 300 / 857, + }, { + categoryIds: ['cat6'], + author: peterLustig, }), factory.create('Post', { - author: huey, id: 'p9', language: sample(languages), + }, { categoryIds: ['cat9'], + author: huey, }), factory.create('Post', { - author: dewey, id: 'p10', - categoryIds: ['cat10'], imageBlurred: true, + }, { + author: dewey, + categoryIds: ['cat10'], }), factory.create('Post', { - author: louie, id: 'p11', language: sample(languages), image: faker.image.unsplash.people(300, 901), - categoryIds: ['cat11'], imageAspectRatio: 300 / 901, + }, { + categoryIds: ['cat11'], + author: louie, }), factory.create('Post', { - author: bobDerBaumeister, id: 'p13', language: sample(languages), + }, { + author: bobDerBaumeister, categoryIds: ['cat13'], }), factory.create('Post', { - author: jennyRostock, id: 'p14', language: sample(languages), image: faker.image.unsplash.objects(300, 200), - categoryIds: ['cat14'], imageAspectRatio: 300 / 450, + }, { + author: jennyRostock, + categoryIds: ['cat14'], }), factory.create('Post', { - author: huey, id: 'p15', language: sample(languages), + }, { + author: huey, categoryIds: ['cat15'], }), ]) @@ -828,8 +840,10 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl'] await Promise.all( [...Array(30).keys()].map(() => { return factory.create('Post', { - author: jennyRostock, image: faker.image.unsplash.objects(), + }, { + categoryIds: ['cat1'], + author: jennyRostock, }) }), ) @@ -864,8 +878,9 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl'] await Promise.all( [...Array(21).keys()].map(() => { return factory.create('Post', { - author: peterLustig, image: faker.image.unsplash.buildings(), + }, { + author: peterLustig, }) }), ) @@ -900,8 +915,9 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl'] await Promise.all( [...Array(11).keys()].map(() => { return factory.create('Post', { - author: dewey, image: faker.image.unsplash.food(), + }, { + author: dewey, }) }), ) @@ -936,8 +952,9 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl'] await Promise.all( [...Array(16).keys()].map(() => { return factory.create('Post', { - author: louie, image: faker.image.unsplash.technology(), + }, { + author: louie, }) }), ) @@ -945,8 +962,8 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl'] await Promise.all( [...Array(4).keys()].map(() => { return factory.create('Comment', { - author: louie, postId: 'p1', + author: louie, }) }), ) @@ -972,8 +989,9 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl'] await Promise.all( [...Array(45).keys()].map(() => { return factory.create('Post', { - author: bobDerBaumeister, image: faker.image.unsplash.people(), + }, { + author: bobDerBaumeister, }) }), ) @@ -1008,8 +1026,9 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl'] await Promise.all( [...Array(8).keys()].map(() => { return factory.create('Post', { - author: huey, image: faker.image.unsplash.nature(), + }, { + author: huey, }) }), ) diff --git a/backend/src/factories/posts.js b/backend/src/factories/posts.js index 3295665b7..2731cb60d 100644 --- a/backend/src/factories/posts.js +++ b/backend/src/factories/posts.js @@ -1,77 +1,71 @@ +import { Factory } from 'rosie' +import { getNeode } from '../db/neo4j' import faker from 'faker' import slugify from 'slug' import uuid from 'uuid/v4' +const neode = getNeode() + +Factory.define('post') + .option('categoryIds', []) + .option('categories', ['categoryIds'], (categoryIds) => { + if (categoryIds.length) return Promise.all(categoryIds.map(id => neode.find('Category', id))) + // there must be at least one category + return Promise.all([Factory.build('category')]) + }) + .option('tagIds', []) + .option('tags', ['tagIds'], (tagIds) => { + return Promise.all(tagIds.map(id => neode.find('Tag', id))) + }) + .option('authorId', null) + .option('author', ['authorId'], (authorId) => { + if (authorId) return neode.find('User', authorId) + return Factory.build('user') + }) + .option('pinnedBy', null) + .attrs({ + id: uuid, + title: faker.lorem.sentence, + content: faker.lorem.paragraphs, + image: faker.image.unsplash.imageUrl, + visibility: 'public', + deleted: false, + imageBlurred: false, + imageAspectRatio: 1.333, + }) + .attr('pinned', ['pinned'], (pinned) => { + // Convert false to null + return pinned || null + }) + .attr('contentExcerpt', ['contentExcerpt', 'content'], (contentExcerpt, content) => { + return contentExcerpt || content + }) + .attr('slug', ['slug', 'title'], (slug, title) => { + return slug || slugify(title, { lower: true }) + }) + .after(async (buildObject, options) => { + const [post, author, categories, tags] = await Promise.all([ + neode.create('Post', buildObject), + options.author, + options.categories, + options.tags, + ]) + await Promise.all([ + post.relateTo(author, 'author'), + Promise.all(categories.map(c => c.relateTo(post, 'post'))), + Promise.all(tags.map(t => t.relateTo(post, 'post'))), + ]) + if (buildObject.pinned) { + const pinnedBy = await (options.pinnedBy || Factory.build('user', { role: 'admin' })) + await pinnedBy.relateTo(post, 'pinned') + } + return post + }) + export default function create() { return { - factory: async ({ args, neodeInstance, factoryInstance }) => { - const defaults = { - id: uuid(), - title: faker.lorem.sentence(), - content: [ - faker.lorem.sentence(), - faker.lorem.sentence(), - faker.lorem.sentence(), - faker.lorem.sentence(), - faker.lorem.sentence(), - ].join('. '), - image: faker.image.unsplash.imageUrl(), - visibility: 'public', - deleted: false, - categoryIds: [], - imageBlurred: false, - imageAspectRatio: 1.333, - pinned: null, - } - args = { - ...defaults, - ...args, - } - // Convert false to null - args.pinned = args.pinned || null - - args.slug = args.slug || slugify(args.title, { lower: true }) - args.contentExcerpt = args.contentExcerpt || args.content - - let { categories, categoryIds } = args - delete args.categories - delete args.categoryIds - if (categories && categoryIds) throw new Error('You provided both categories and categoryIds') - if (categoryIds) - categories = await Promise.all(categoryIds.map(id => neodeInstance.find('Category', id))) - categories = categories || (await Promise.all([factoryInstance.create('Category')])) - const { tagIds = [] } = args - delete args.tags - const tags = await Promise.all( - tagIds.map(t => { - return neodeInstance.find('Tag', t) - }), - ) - - let { author, authorId } = args - delete args.author - delete args.authorId - if (author && authorId) throw new Error('You provided both author and authorId') - if (authorId) author = await neodeInstance.find('User', authorId) - author = author || (await factoryInstance.create('User')) - const post = await neodeInstance.create('Post', args) - await post.relateTo(author, 'author') - - if (args.pinned) { - args.pinnedAt = args.pinnedAt || new Date().toISOString() - if (!args.pinnedBy) { - const admin = await factoryInstance.create('User', { - role: 'admin', - updatedAt: new Date().toISOString(), - }) - await admin.relateTo(post, 'pinned') - args.pinnedBy = admin - } - } - - await Promise.all(categories.map(c => c.relateTo(post, 'post'))) - await Promise.all(tags.map(t => t.relateTo(post, 'post'))) - return post + factory: async ({ args, options, neodeInstance, factoryInstance }) => { + return Factory.build('post', args, options) }, } } diff --git a/backend/src/middleware/slugifyMiddleware.spec.js b/backend/src/middleware/slugifyMiddleware.spec.js index 5400d2c92..8f05fd6cd 100644 --- a/backend/src/middleware/slugifyMiddleware.spec.js +++ b/backend/src/middleware/slugifyMiddleware.spec.js @@ -92,6 +92,7 @@ describe('slugifyMiddleware', () => { title: 'Pre-existing post', slug: 'pre-existing-post', content: 'as Someone else content', + }, { categoryIds, }) }) diff --git a/backend/src/middleware/softDelete/softDeleteMiddleware.spec.js b/backend/src/middleware/softDelete/softDeleteMiddleware.spec.js index 334564582..cd6e2f726 100644 --- a/backend/src/middleware/softDelete/softDeleteMiddleware.spec.js +++ b/backend/src/middleware/softDelete/softDeleteMiddleware.spec.js @@ -51,19 +51,21 @@ beforeAll(async () => { await Promise.all([ user.relateTo(troll, 'following'), factory.create('Post', { - author: user, id: 'p1', title: 'Deleted post', slug: 'deleted-post', deleted: true, + }, { + author: user, categoryIds, }), factory.create('Post', { - author: user, id: 'p3', title: 'Publicly visible post', slug: 'publicly-visible-post', deleted: false, + }, { + author: user, categoryIds, }), ]) @@ -77,12 +79,13 @@ beforeAll(async () => { }), factory.create('Post', { id: 'p2', - author: troll, title: 'Disabled post', content: 'This is an offensive post content', contentExcerpt: 'This is an offensive post content', image: '/some/offensive/image.jpg', deleted: false, + }, { + author: troll, categoryIds, }), factory.create('Comment', { diff --git a/backend/src/middleware/validation/validationMiddleware.spec.js b/backend/src/middleware/validation/validationMiddleware.spec.js index 38cd010b4..a419c2428 100644 --- a/backend/src/middleware/validation/validationMiddleware.spec.js +++ b/backend/src/middleware/validation/validationMiddleware.spec.js @@ -121,10 +121,12 @@ beforeEach(async () => { const posts = await Promise.all([ factory.create('Post', { id: 'offensive-post', + }, { authorId: 'moderating-user', }), factory.create('Post', { id: 'post-4-commenting', + }, { authorId: 'commenting-user', }), ]) diff --git a/backend/src/models/Post.js b/backend/src/models/Post.js index 2b553232e..cbc29d814 100644 --- a/backend/src/models/Post.js +++ b/backend/src/models/Post.js @@ -42,5 +42,4 @@ export default { imageBlurred: { type: 'boolean', default: false }, imageAspectRatio: { type: 'float', default: 1.0 }, pinned: { type: 'boolean', default: null, valid: [null, true] }, - pinnedAt: { type: 'string', isoDate: true }, } diff --git a/backend/src/schema/resolvers/comments.spec.js b/backend/src/schema/resolvers/comments.spec.js index 9877161db..355074804 100644 --- a/backend/src/schema/resolvers/comments.spec.js +++ b/backend/src/schema/resolvers/comments.spec.js @@ -52,6 +52,7 @@ const setupPostAndComment = async () => { await factory.create('Post', { id: 'p1', content: 'Post to be commented', + }, { categoryIds: ['cat9'], }) newlyCreatedComment = await factory.create('Comment', { @@ -88,7 +89,7 @@ describe('CreateComment', () => { describe('given a post', () => { beforeEach(async () => { - await factory.create('Post', { categoryIds: ['cat9'], id: 'p1' }) + await factory.create('Post', { id: 'p1' }, { categoryIds: ['cat9'] } ) variables = { ...variables, postId: 'p1', diff --git a/backend/src/schema/resolvers/notifications.spec.js b/backend/src/schema/resolvers/notifications.spec.js index a5c46e930..27b8489e2 100644 --- a/backend/src/schema/resolvers/notifications.spec.js +++ b/backend/src/schema/resolvers/notifications.spec.js @@ -45,18 +45,20 @@ describe('given some notifications', () => { factory.create('Category', { id: 'cat1' }), ]) const [post1, post2, post3] = await Promise.all([ - factory.create('Post', { author, id: 'p1', categoryIds, content: 'Not for you' }), + factory.create('Post', { id: 'p1', content: 'Not for you' }, { author, categoryIds }), factory.create('Post', { - author, id: 'p2', - categoryIds, content: 'Already seen post mention', + }, { + author, + categoryIds, }), factory.create('Post', { - author, id: 'p3', - categoryIds, content: 'You have been mentioned in a post', + }, { + author, + categoryIds, }), ]) const [comment1, comment2, comment3] = await Promise.all([ diff --git a/backend/src/schema/resolvers/posts.spec.js b/backend/src/schema/resolvers/posts.spec.js index d7195be97..83dc53eea 100644 --- a/backend/src/schema/resolvers/posts.spec.js +++ b/backend/src/schema/resolvers/posts.spec.js @@ -114,10 +114,11 @@ describe('Post', () => { ), ]) ;[happyPost, cryPost] = await Promise.all([ - factory.create('Post', { id: 'happy-post', categoryIds: ['cat4'] }), - factory.create('Post', { id: 'cry-post', categoryIds: ['cat15'] }), + factory.create('Post', { id: 'happy-post' }, { categoryIds: ['cat4'] }), + factory.create('Post', { id: 'cry-post'} , { categoryIds: ['cat15'] }), factory.create('Post', { id: 'post-by-followed-user', + }, { categoryIds: ['cat9'], author: followedUser, }), @@ -352,10 +353,11 @@ describe('UpdatePost', () => { beforeEach(async () => { author = await factory.create('User', { slug: 'the-author' }) newlyCreatedPost = await factory.create('Post', { - author, id: 'p9876', title: 'Old title', content: 'Old content', + }, { + author, categoryIds, }) @@ -541,6 +543,7 @@ describe('UpdatePost', () => { beforeEach(async () => { await factory.create('Post', { id: 'created-and-pinned-by-same-admin', + }, { author: admin, }) variables = { ...variables, id: 'created-and-pinned-by-same-admin' } @@ -606,6 +609,7 @@ describe('UpdatePost', () => { authenticatedUser = await otherAdmin.toJson() await factory.create('Post', { id: 'created-by-one-admin-pinned-by-different-one', + }, { author: otherAdmin, }) }) @@ -666,6 +670,7 @@ describe('UpdatePost', () => { beforeEach(async () => { await factory.create('Post', { id: 'only-pinned-post', + }, { author: admin, }) await mutate({ mutation: pinPostMutation, variables }) @@ -887,10 +892,11 @@ describe('DeletePost', () => { author = await factory.create('User') await factory.create('Post', { id: 'p4711', - author, title: 'I will be deleted', content: 'To be deleted', image: 'path/to/some/image', + }, { + author, categoryIds, }) variables = { ...variables, id: 'p4711' } @@ -999,8 +1005,9 @@ describe('emotions', () => { beforeEach(async () => { author = await neode.create('User', { id: 'u257' }) postToEmote = await factory.create('Post', { - author, id: 'p1376', + }, { + author, categoryIds, }) diff --git a/backend/src/schema/resolvers/reports.spec.js b/backend/src/schema/resolvers/reports.spec.js index 9992da200..cc5c6dd26 100644 --- a/backend/src/schema/resolvers/reports.spec.js +++ b/backend/src/schema/resolvers/reports.spec.js @@ -357,9 +357,10 @@ describe('file a report on a resource', () => { describe('reported resource is a post', () => { beforeEach(async () => { await factory.create('Post', { - author: currentUser, id: 'post-to-report-id', title: 'This is a post that is going to be reported', + }, { + author: currentUser, categoryIds, }) }) @@ -409,15 +410,15 @@ describe('file a report on a resource', () => { }) describe('reported resource is a comment', () => { - let createPostVariables beforeEach(async () => { - createPostVariables = { + await factory.create('Post', { id: 'p1', title: 'post to comment on', content: 'please comment on me', + }, { categoryIds, - } - await factory.create('Post', { ...createPostVariables, author: currentUser }) + author: currentUser + }) await factory.create('Comment', { author: currentUser, postId: 'p1', @@ -571,22 +572,25 @@ describe('file a report on a resource', () => { await Promise.all([ factory.create('Post', { - author: abusiveUser, id: 'abusive-post-1', - categoryIds, content: 'Interesting Knowledge', + }, { + categoryIds, + author: abusiveUser, }), factory.create('Post', { - author: moderator, id: 'post-2', - categoryIds, content: 'More things to do …', + }, { + author: moderator, + categoryIds, }), factory.create('Post', { - author: currentUser, id: 'post-3', - categoryIds, content: 'I am at school …', + }, { + categoryIds, + author: currentUser, }), ]) await Promise.all([ diff --git a/backend/src/schema/resolvers/shout.spec.js b/backend/src/schema/resolvers/shout.spec.js index 50ff23687..4fb467252 100644 --- a/backend/src/schema/resolvers/shout.spec.js +++ b/backend/src/schema/resolvers/shout.spec.js @@ -91,11 +91,13 @@ describe('shout and unshout posts', () => { await factory.create('Post', { name: 'Other user post', id: 'another-user-post-id', + }, { author: postAuthor, }) await factory.create('Post', { name: 'current user post', id: 'current-user-post-id', + }, { author: currentUser, }) variables = {} @@ -157,6 +159,7 @@ describe('shout and unshout posts', () => { await factory.create('Post', { name: 'Posted By Another User', id: 'posted-by-another-user', + }, { author: postAuthor, }) await mutate({ diff --git a/backend/src/schema/resolvers/users.spec.js b/backend/src/schema/resolvers/users.spec.js index 9ead48a2b..20508774e 100644 --- a/backend/src/schema/resolvers/users.spec.js +++ b/backend/src/schema/resolvers/users.spec.js @@ -329,9 +329,10 @@ describe('DeleteUser', () => { icon: 'university', }) await factory.create('Post', { - author: user, id: 'p139', content: 'Post by user u343', + }, { + author: user, categoryIds, }) await factory.create('Comment', {