diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml index 8248de182..01daf2a74 100644 --- a/.github/workflows/checks.yml +++ b/.github/workflows/checks.yml @@ -67,4 +67,6 @@ jobs: run: yarn lint - name: run tests + env: + TEST_THREADS: 4 run: yarn test diff --git a/app/app.js b/app/app.js index 71c7a687c..c7ad36b3b 100644 --- a/app/app.js +++ b/app/app.js @@ -41,8 +41,10 @@ export async function getSingleton() { _app.context.pubsub = new PubsubListener(server, _app); - const port = process.env.PEPYATKA_SERVER_PORT || process.env.PORT || _app.context.config.port; + const port = getListeningPort(_app); await listen(port); + // The actual port + _app.context.port = server.address().port; const log = createDebug('freefeed:init'); @@ -56,3 +58,25 @@ export async function getSingleton() { lock.release(); } } + +function getListeningPort(_app) { + let port = validPortValue(process.env.PEPYATKA_SERVER_PORT); + + if (port === undefined) { + port = validPortValue(process.env.PORT); + } + + if (port === undefined) { + port = validPortValue(_app.context.config.port); + } + + return port ?? 0; +} + +function validPortValue(port) { + if (typeof port === 'number' && port >= 0 && port < 65536) { + return port; + } + + return undefined; +} diff --git a/app/freefeed-app.ts b/app/freefeed-app.ts index f795a9d54..9daf649f9 100644 --- a/app/freefeed-app.ts +++ b/app/freefeed-app.ts @@ -38,7 +38,7 @@ class FreefeedApp extends Application { } this.context.config = config; - this.context.port = process.env.PORT ? parseInt(process.env.PORT) : config.port; + this.context.port = 0; // to be configured on listen this.use(asyncContextMiddleware); diff --git a/app/setup/postgres.js b/app/setup/postgres.js index 1673469f9..3c6467a59 100644 --- a/app/setup/postgres.js +++ b/app/setup/postgres.js @@ -2,31 +2,47 @@ import knexjs from 'knex'; import createDebug from 'debug'; import config from 'config'; +import { uniq } from 'lodash'; import { stylize } from '../support/debugLogger'; +import { getDbSchemaName } from '../support/parallel-testing'; + +/** @type {import("knex").Knex.Config} */ +const pgConfig = { ...config.postgres }; + +const schemaName = getDbSchemaName(); + +if (schemaName !== 'public') { + pgConfig.searchPath = uniq([schemaName, 'public', ...(pgConfig.searchPath || [])]); +} -const knex = knexjs(config.postgres); const log = createDebug('freefeed:sql'); const errLog = createDebug('freefeed:sql:error'); -knex.on('start', (builder) => { - const q = builder.toString(); - const start = new Date().getTime(); +let knex = null; +export function connect() { + if (knex) { + return knex; + } - builder.on('end', () => { - log('%s %s', q, stylize(`[took ${new Date().getTime() - start}ms]`, 'green')); - }); + knex = knexjs(pgConfig); + knex.on('start', (builder) => { + const q = builder.toString(); + const start = new Date().getTime(); - builder.on('error', () => { - errLog('%s %s', stylize('ERROR', 'red'), q); + builder.on('end', () => { + log('%s %s', q, stylize(`[took ${new Date().getTime() - start}ms]`, 'green')); + }); + + builder.on('error', () => { + errLog('%s %s', stylize('ERROR', 'red'), q); + }); }); -}); -export function connect() { return knex; } -export function setSearchConfig() { - const { textSearchConfigName } = config.postgres; - return knex.raw(`SET default_text_search_config TO '${textSearchConfigName}'`); +export async function setSearchConfig() { + const { textSearchConfigName } = pgConfig; + await knex.raw(`SET default_text_search_config TO '${textSearchConfigName}'`); } diff --git a/app/support/parallel-testing.ts b/app/support/parallel-testing.ts new file mode 100644 index 000000000..adb7bb586 --- /dev/null +++ b/app/support/parallel-testing.ts @@ -0,0 +1,18 @@ +export function getWorkerId(): number { + if (process.env.NODE_ENV !== 'test') { + return 0; + } + + let id = Number.parseInt(process.env.MOCHA_WORKER_ID || '0'); + + if (!Number.isFinite(id)) { + id = 0; + } + + return id; +} + +export function getDbSchemaName(): 'public' | string { + const workerId = getWorkerId(); + return workerId === 0 ? 'public' : `test${workerId}`; +} diff --git a/bin/clean_test_db.js b/bin/clean_test_db.js deleted file mode 100755 index 8067e6df8..000000000 --- a/bin/clean_test_db.js +++ /dev/null @@ -1,33 +0,0 @@ -#!/usr/bin/env babel-node -import knexLib from 'knex'; - -// Forcefully set the NODE_ENV to 'test' -const prevEnv = process.env.NODE_ENV; -process.env.NODE_ENV = 'test'; - -const config = require('../knexfile'); - -process.env.NODE_ENV = prevEnv; - -if (!('test' in config)) { - process.stderr.write(`Error: no "test" section in knexfile`); - process.exit(1); -} - -const knex = knexLib(config.test); - -async function run() { - await knex.raw('drop schema public cascade'); - await knex.raw('create schema public'); -} - -run() - .then(() => { - knex.destroy(); - process.exit(0); - }) - .catch((e) => { - process.stderr.write(`Error: ${e}\n`); - knex.destroy(); - process.exit(1); - }); diff --git a/bin/reset_test_db.js b/bin/reset_test_db.js new file mode 100644 index 000000000..8d0793a7e --- /dev/null +++ b/bin/reset_test_db.js @@ -0,0 +1,61 @@ +/* eslint-disable no-await-in-loop */ +import knexLib from 'knex'; +import parseArgs from 'minimist'; + +import { getDbSchemaName } from '../app/support/parallel-testing'; + +const args = parseArgs(process.argv.slice(2)); +let nSchemas = Number.parseInt(args['schemas']); + +if (!Number.isFinite(nSchemas) || nSchemas < 1) { + nSchemas = 1; +} + +// Forcefully set the NODE_ENV to 'test' +process.env.NODE_ENV = 'test'; + +const config = require('../knexfile'); + +if (!('test' in config)) { + process.stderr.write(`Error: no "test" section in knexfile`); + process.exit(1); +} + +const knex = knexLib(config.test); + +async function resetSchema(schemaName) { + console.log(`Resetting the ${schemaName} schema`); + await knex.raw(`drop schema if exists :schemaName: cascade`, { schemaName }); + await knex.raw(`create schema :schemaName:`, { schemaName }); +} + +async function run() { + // Public schema + await resetSchema('public'); + console.log(`Running migrations`); + await knex.migrate.latest(); + console.log(`Migration completed`); + + // Other schemas + for (let i = 1; i < nSchemas; i++) { + // Emulating MOCHA_WORKER_ID for proper schema name generation + process.env.MOCHA_WORKER_ID = i.toString(10); + const schemaName = getDbSchemaName(); + await resetSchema(schemaName); + console.log(`Running migrations on ${schemaName} schema`); + await knex.migrate.latest({ schemaName }); + console.log(`Migration completed on ${schemaName} schema`); + } +} + +run() + .then(() => { + knex.destroy(); + console.log(`All done.`); + process.exit(0); + }) + .catch((e) => { + process.stderr.write(`Error: ${e}\n`); + knex.destroy(); + process.exit(1); + }); diff --git a/config/default.js b/config/default.js index af17a071b..f5e18d6c3 100644 --- a/config/default.js +++ b/config/default.js @@ -503,4 +503,11 @@ config.translation = { apiKey: 'OVERRIDE_IT', }; +config.tests = { + realtime: { + eventTimeout: 2000, + silenceTimeout: 500, + }, +}; + module.exports = config; diff --git a/config/test.js b/config/test.js index c602f4384..8832e540a 100644 --- a/config/test.js +++ b/config/test.js @@ -2,9 +2,11 @@ import { resolve } from 'path'; import stubTransport from 'nodemailer-stub-transport'; +import { getWorkerId } from '../app/support/parallel-testing'; + module.exports = { - port: 31337, - database: 3, + port: 31337 + getWorkerId(), + database: 3 + getWorkerId(), monitorPrefix: 'tests', application: { EXTRA_STOP_LIST: ['thatcreepyguy', 'nicegirlnextdoor', 'perfectstranger'] }, @@ -48,6 +50,8 @@ module.exports = { registrationsLimit: { maxCount: 10 }, + maintenance: { messageFile: `tmp/MAINTENANCE${getWorkerId()}.txt` }, + userPreferences: { defaults: { // User does't want to view banned comments by default (for compatibility diff --git a/migrations/20160405133637_initial.js b/migrations/20160405133637_initial.js index 402a822a8..253c3674f 100644 --- a/migrations/20160405133637_initial.js +++ b/migrations/20160405133637_initial.js @@ -1,18 +1,27 @@ +const { getDbSchemaName } = require('../app/support/parallel-testing'); + exports.up = function (knex) { + const schemaName = getDbSchemaName(); + const isPublicSchema = !schemaName || schemaName === 'public'; + return Promise.all([ - knex.raw('SET statement_timeout = 0'), - knex.raw('SET lock_timeout = 0'), - knex.raw("SET client_encoding = 'UTF8'"), - knex.raw('SET standard_conforming_strings = on'), - knex.raw('SET check_function_bodies = false'), - knex.raw('SET client_min_messages = warning'), - knex.raw('SET row_security = off'), - knex.raw('CREATE EXTENSION IF NOT EXISTS plpgsql WITH SCHEMA pg_catalog'), - knex.raw('CREATE EXTENSION IF NOT EXISTS pgcrypto WITH SCHEMA public'), - knex.raw('CREATE EXTENSION IF NOT EXISTS intarray WITH SCHEMA public'), - knex.raw('SET search_path = public, pg_catalog'), - knex.raw("SET default_tablespace = ''"), - knex.raw('SET default_with_oids = false'), + ...(isPublicSchema + ? [ + knex.raw('SET statement_timeout = 0'), + knex.raw('SET lock_timeout = 0'), + knex.raw("SET client_encoding = 'UTF8'"), + knex.raw('SET standard_conforming_strings = on'), + knex.raw('SET check_function_bodies = false'), + knex.raw('SET client_min_messages = warning'), + knex.raw('SET row_security = off'), + knex.raw('CREATE EXTENSION IF NOT EXISTS plpgsql WITH SCHEMA pg_catalog'), + knex.raw('CREATE EXTENSION IF NOT EXISTS pgcrypto WITH SCHEMA public'), + knex.raw('CREATE EXTENSION IF NOT EXISTS intarray WITH SCHEMA public'), + knex.raw('SET search_path = public, pg_catalog'), + knex.raw("SET default_tablespace = ''"), + knex.raw('SET default_with_oids = false'), + ] + : [knex.raw('SET search_path = :schemaName:, public, pg_catalog', { schemaName })]), knex.schema.createTable('users', function (table) { table.increments().notNullable().primary(); diff --git a/migrations/20161215174952_posts_privacy_flags.js b/migrations/20161215174952_posts_privacy_flags.js index c70e1b83e..f45f17076 100644 --- a/migrations/20161215174952_posts_privacy_flags.js +++ b/migrations/20161215174952_posts_privacy_flags.js @@ -7,7 +7,7 @@ export function up(knex) { }) .raw( `CREATE INDEX feeds_id_array_idx - ON public.feeds + ON feeds USING gin ((ARRAY[id]) gin__int_ops); `, @@ -15,7 +15,7 @@ export function up(knex) { // Trigger function for individual posts .raw( ` - CREATE OR REPLACE FUNCTION public.trgfun_set_post_privacy_on_insert_update() + CREATE OR REPLACE FUNCTION trgfun_set_post_privacy_on_insert_update() RETURNS trigger AS $BODY$ -- Set proper is_private and is_protected flags on post insert or update @@ -46,7 +46,7 @@ export function up(knex) { // Trigger function for users/groups .raw( ` - CREATE OR REPLACE FUNCTION public.trgfun_set_posts_privacy_on_user_update() + CREATE OR REPLACE FUNCTION trgfun_set_posts_privacy_on_user_update() RETURNS trigger AS $BODY$ -- Set proper is_private and is_protected flags on all user's posts when the user changes his privacy @@ -107,17 +107,17 @@ export function up(knex) { .raw( `CREATE TRIGGER trg_set_post_privacy_on_insert_update BEFORE INSERT OR UPDATE OF destination_feed_ids - ON public.posts + ON posts FOR EACH ROW - EXECUTE PROCEDURE public.trgfun_set_post_privacy_on_insert_update();`, + EXECUTE PROCEDURE trgfun_set_post_privacy_on_insert_update();`, ) .raw( `CREATE TRIGGER trg_set_posts_privacy_on_user_update AFTER UPDATE OF is_private, is_protected - ON public.users + ON users FOR EACH ROW WHEN (((old.is_protected <> new.is_protected) OR (old.is_private <> new.is_private))) - EXECUTE PROCEDURE public.trgfun_set_posts_privacy_on_user_update();`, + EXECUTE PROCEDURE trgfun_set_posts_privacy_on_user_update();`, ) // Data migration .raw('update posts set destination_feed_ids = destination_feed_ids') diff --git a/migrations/20171205142923_post_is_propagable.js b/migrations/20171205142923_post_is_propagable.js index a4d10e741..fe07f2387 100644 --- a/migrations/20171205142923_post_is_propagable.js +++ b/migrations/20171205142923_post_is_propagable.js @@ -10,7 +10,7 @@ export async function up(knex) { // Trigger function to update 'is_propagable' flag .raw( ` - CREATE OR REPLACE FUNCTION public.trgfun_set_post_is_propagable_on_insert_update() + CREATE OR REPLACE FUNCTION trgfun_set_post_is_propagable_on_insert_update() RETURNS trigger AS $BODY$ -- Set 'is_propagable' post flag on insert or update. @@ -36,9 +36,9 @@ export async function up(knex) { .raw( `CREATE TRIGGER trg_set_post_is_propagable_on_insert_update BEFORE INSERT OR UPDATE OF destination_feed_ids - ON public.posts + ON posts FOR EACH ROW - EXECUTE PROCEDURE public.trgfun_set_post_is_propagable_on_insert_update();`, + EXECUTE PROCEDURE trgfun_set_post_is_propagable_on_insert_update();`, ) // Data migration .raw( diff --git a/package.json b/package.json index 6eaf0cef8..b413ad048 100644 --- a/package.json +++ b/package.json @@ -6,21 +6,21 @@ "version": "2.20.0", "private": true, "scripts": { - "start": "cross-env TZ=UTC yarn babel index.js", + "start": "TZ=UTC yarn babel index.js", "travis": "run-s -c typecheck test lint", - "test": "run-s typecheck reset-test-db test-rollback mocha", + "test": "run-s typecheck reset-test-db test-rollback test-all", "coverage": "run-s reset-test-db nyc", "lint": "run-s eslint ejslint", "ejslint": "ejslint app", "eslint": "eslint . --ext \".js,.jsx,.ts\"", "babel": "node -r './esm/register.cjs'", "typecheck": "tsc", - "reset-test-db": "run-s \"babel bin/clean_test_db.js\" && knex --env test migrate:latest", + "reset-test-db": "run-s \"babel bin/reset_test_db.js --schemas ${TEST_THREADS:-1}\"", "test-rollback": "knex --env test migrate:rollback && knex --env test migrate:latest", - "test-just": "cross-env NODE_ENV=test FRFS_SECRET=test-secret mocha", - "mocha": "cross-env TZ=UTC run-s \"test-just -b test/unit test/integration test/functional test/cleanup.js\"", + "test-just": "NODE_ENV=test FRFS_SECRET=test-secret mocha -p -j ${TEST_THREADS:-1}", + "test-all": "TZ=UTC run-s \"test-just -b test/unit test/integration test/functional test/cleanup.js\"", "console": "yarn babel bin/console", - "nyc": "nyc yarn mocha", + "nyc": "nyc yarn test-all", "data_transfer": "yarn babel bin/data_transfer", "reindex_hashtags": "yarn babel bin/reindex_hashtags", "notification_emails": "yarn babel bin/notification_emails", @@ -131,6 +131,7 @@ "@types/koa-static": "~4.0.4", "@types/koa__router": "~12.0.4", "@types/lodash": "~4.17.0", + "@types/minimist": "^1", "@types/mocha": "~10.0.6", "@types/n3": "~1.16.4", "@types/node": "~18.19.31", @@ -144,7 +145,6 @@ "@typescript-eslint/parser": "~6.19.1", "chai": "5.1.0", "chai-fs": "~2.0.0", - "cross-env": "~7.0.3", "ejs-lint": "~2.0.0", "esbuild": "~0.20.2", "eslint": "~8.56.0", @@ -156,6 +156,7 @@ "eslint-plugin-promise": "~6.1.1", "eslint-plugin-you-dont-need-lodash-underscore": "~6.14.0", "mailparser": "~3.7.0", + "minimist": "~1.2.8", "mkdirp": "~3.0.1", "mocha": "~10.4.0", "npm-run-all": "~4.1.5", diff --git a/test/dbCleaner.ts b/test/dbCleaner.ts index 01cabc25a..a57ce063d 100644 --- a/test/dbCleaner.ts +++ b/test/dbCleaner.ts @@ -1,10 +1,13 @@ import pgFormat from 'pg-format'; import { type Knex } from 'knex'; +import { getDbSchemaName } from '../app/support/parallel-testing'; + const tablesToKeep = ['admin_roles', 'event_types']; -export default function cleanDB(knex: Knex) { - return knex.raw( +export default async function cleanDB(knex: Knex) { + const schemaName = getDbSchemaName(); + await knex.raw( ` do $$ declare @@ -14,7 +17,7 @@ export default function cleanDB(knex: Knex) { set session_replication_role = replica; for row in select tablename from pg_tables - where schemaname = 'public' + where schemaname = '${schemaName}' and tablename not in (${pgFormat(`%L`, tablesToKeep)}) loop execute format('delete from %I', row.tablename); diff --git a/test/functional/backlinks.js b/test/functional/backlinks.js index 3bb8a1c79..214641767 100644 --- a/test/functional/backlinks.js +++ b/test/functional/backlinks.js @@ -9,12 +9,12 @@ import { PubSubAdapter } from '../../app/support/PubSubAdapter'; import { authHeaders, - createAndReturnPost, createCommentAsync, createTestUsers, deletePostAsync, goPrivate, goPublic, + justCreatePost, performJSONRequest, removeCommentAsync, updateCommentAsync, @@ -30,11 +30,10 @@ describe('Backlinks in API output', () => { await cleanDB($pg_database); [luna, mars] = await createTestUsers(['luna', 'mars']); - ({ id: lunaPostId, shortId: lunaPostShortId } = await createAndReturnPost(luna, 'Luna post')); - ({ id: marsPostId } = await createAndReturnPost( - mars, - `As Luna said, example.com/${lunaPostId}`, - )); + const lunaPost = await justCreatePost(luna, 'Luna post'); + lunaPostId = lunaPost.id; + lunaPostShortId = await lunaPost.getShortId(); + ({ id: marsPostId } = await justCreatePost(mars, `As Luna said, example.com/${lunaPostId}`)); }); it(`should return Luna post with 1 backlink`, async () => { @@ -104,7 +103,7 @@ describe('Backlinks in API output', () => { describe('Counting backlinks in posts and comments', () => { before(async () => { - mars.post = await createAndReturnPost(mars, `As Luna said, example.com/${lunaPostId}`); + mars.post = await justCreatePost(mars, `As Luna said, example.com/${lunaPostId}`); }); after(() => deletePostAsync(mars, mars.post.id)); @@ -147,7 +146,8 @@ describe('Backlinks in realtime', () => { await lunaSession.sendAsync('subscribe', { timeline: [lunaTimeline.id] }); // Luna created post - luna.post = await createAndReturnPost(luna, 'Luna post'); + luna.post = await justCreatePost(luna, 'Luna post'); + luna.post.shortId = await luna.post.getShortId(); }); describe('Mars is public', () => { @@ -155,10 +155,7 @@ describe('Backlinks in realtime', () => { const test = lunaSession.receiveWhile( 'post:update', async () => - (mars.post = await createAndReturnPost( - mars, - `As Luna said, example.com/${luna.post.id}`, - )), + (mars.post = await justCreatePost(mars, `As Luna said, example.com/${luna.post.id}`)), ); await expect(test, 'when fulfilled', 'to satisfy', { posts: { id: luna.post.id, backlinksCount: 1 }, @@ -205,7 +202,7 @@ describe('Backlinks in realtime', () => { const test = lunaSession.receiveWhile( 'post:update', async () => - (mars.post = await createAndReturnPost(mars, `As Luna said, /luna/${luna.post.shortId}`)), + (mars.post = await justCreatePost(mars, `As Luna said, /luna/${luna.post.shortId}`)), ); await expect(test, 'when fulfilled', 'to satisfy', { posts: { id: luna.post.id, backlinksCount: 1 }, @@ -255,10 +252,7 @@ describe('Backlinks in realtime', () => { const test = lunaSession.notReceiveWhile( 'post:update', async () => - (mars.post = await createAndReturnPost( - mars, - `As Luna said, example.com/${luna.post.id}`, - )), + (mars.post = await justCreatePost(mars, `As Luna said, example.com/${luna.post.id}`)), ); await expect(test, 'to be fulfilled'); }); @@ -293,7 +287,7 @@ describe('Backlinks in realtime', () => { }); describe('Backlinks in comments', () => { - before(async () => (mars.post = await createAndReturnPost(mars, `Just a post`))); + before(async () => (mars.post = await justCreatePost(mars, `Just a post`))); after(() => deletePostAsync(mars, mars.post.id)); describe('Mars is public', () => { diff --git a/test/functional/comment_likes.js b/test/functional/comment_likes.js index 6287a4235..c46cd9362 100644 --- a/test/functional/comment_likes.js +++ b/test/functional/comment_likes.js @@ -13,10 +13,7 @@ import { acceptRequestToJoinGroup, banUser, createAndReturnPost, - createAndReturnPostToFeed, - createCommentAsync, likeComment, - createGroupAsync, createUserAsync, unlikeComment, getCommentLikes, @@ -25,6 +22,12 @@ import { sendRequestToJoinGroup, performSearch, updateUserAsync, + createTestUsers, + justCreatePost, + createTestUser, + justCreateComment, + justCreateGroup, + justLikeComment, } from './functional_test_helper'; import * as schema from './schemaV2-helper'; @@ -32,11 +35,10 @@ const expect = unexpected.clone().use(schema.freefeedAssertions); describe('Comment likes', () => { let app; - let writeComment, getPost, getFeed; + let getPost, getFeed; before(async () => { app = await getSingleton(); - writeComment = createComment(); getPost = fetchPost(app); getFeed = fetchTimeline(app); PubSub.setPublisher(new DummyPublisher()); @@ -57,14 +59,10 @@ describe('Comment likes', () => { let lunaPost, marsPost; beforeEach(async () => { - [luna, mars, jupiter] = await Promise.all([ - createUserAsync('luna', 'pw'), - createUserAsync('mars', 'pw'), - createUserAsync('jupiter', 'pw'), - ]); + [luna, mars, jupiter] = await createTestUsers(['luna', 'mars', 'jupiter']); [lunaPost, marsPost] = await Promise.all([ - createAndReturnPost(luna, 'Luna post'), - createAndReturnPost(mars, 'Mars post'), + justCreatePost(luna, 'Luna post'), + justCreatePost(mars, 'Mars post'), ]); await mutualSubscriptions([luna, mars]); }); @@ -75,37 +73,37 @@ describe('Comment likes', () => { }); it('should not allow to like own comments to own post', async () => { - const lunaComment = await writeComment(luna, lunaPost.id, 'Luna comment'); + const lunaComment = await justCreateComment(luna, lunaPost.id, 'Luna comment'); const res = await likeComment(lunaComment.id, luna); expect(res, 'to be an API error', 403, "You can't like your own comment"); }); it('should not allow to like own comments to other user post', async () => { - const lunaComment = await writeComment(luna, marsPost.id, 'Luna comment'); + const lunaComment = await justCreateComment(luna, marsPost.id, 'Luna comment'); const res = await likeComment(lunaComment.id, luna); expect(res, 'to be an API error', 403, "You can't like your own comment"); }); it("should allow Luna to like Mars' comment to Luna's post", async () => { - const marsComment = await writeComment(mars, lunaPost.id, 'Mars comment'); + const marsComment = await justCreateComment(mars, lunaPost.id, 'Mars comment'); const res = await likeComment(marsComment.id, luna); expect(res, 'to have 1 like by', luna); }); it("should allow Luna to like Mars' comment to Mars' post", async () => { - const marsComment = await writeComment(mars, marsPost.id, 'Mars comment'); + const marsComment = await justCreateComment(mars, marsPost.id, 'Mars comment'); const res = await likeComment(marsComment.id, luna); expect(res, 'to have 1 like by', luna); }); it("should allow Jupiter to like Mars' comment to Luna's post", async () => { - const marsComment = await writeComment(mars, lunaPost.id, 'Mars comment'); + const marsComment = await justCreateComment(mars, lunaPost.id, 'Mars comment'); const res = await likeComment(marsComment.id, jupiter); expect(res, 'to have 1 like by', jupiter); }); it('should not allow to like comment more than one time', async () => { - const marsComment = await writeComment(mars, lunaPost.id, 'Mars comment'); + const marsComment = await justCreateComment(mars, lunaPost.id, 'Mars comment'); const res1 = await likeComment(marsComment.id, luna); expect(res1.status, 'to be', 200); @@ -122,11 +120,11 @@ describe('Comment likes', () => { let pluto; beforeEach(async () => { - pluto = await createUserAsync('pluto', 'pw'); + pluto = await createTestUser('pluto'); }); it('should sort comment likes chronologically descending (except viewer)', async () => { - const lunaComment = await writeComment(luna, lunaPost.id, 'Luna comment'); + const lunaComment = await justCreateComment(luna, lunaPost.id, 'Luna comment'); let res = await likeComment(lunaComment.id, mars); expect(res, 'to have 1 like by', mars); await likeComment(lunaComment.id, jupiter); @@ -151,50 +149,58 @@ describe('Comment likes', () => { let plutoPost; beforeEach(async () => { - pluto = await createUserAsync('pluto', 'pw'); - plutoPost = await createAndReturnPost(pluto, 'Pluto post'); + pluto = await createTestUser('pluto'); + plutoPost = await justCreatePost(pluto, 'Pluto post'); await Promise.all([banUser(luna, mars), banUser(luna, pluto)]); }); it("should not allow Luna to like Mars' comment to Mars' post", async () => { - const marsComment = await writeComment(mars, marsPost.id, 'Mars comment'); + const marsComment = await justCreateComment(mars, marsPost.id, 'Mars comment'); const res = await likeComment(marsComment.id, luna); expect(res, 'to be an API error', 403, 'You can not see this post'); }); it("should not allow Luna to like Pluto's comment to Pluto's post", async () => { - const plutoComment = await writeComment(pluto, plutoPost.id, 'Pluto comment'); + const plutoComment = await justCreateComment(pluto, plutoPost.id, 'Pluto comment'); const res = await likeComment(plutoComment.id, luna); expect(res, 'to be an API error', 403, 'You can not see this post'); }); it("should not allow Luna to like Pluto's comment to Mars' post", async () => { - const plutoComment = await writeComment(pluto, marsPost.id, 'Pluto comment'); + const plutoComment = await justCreateComment(pluto, marsPost.id, 'Pluto comment'); const res = await likeComment(plutoComment.id, luna); expect(res, 'to be an API error', 403, 'You can not see this post'); }); it("should not allow Mars to like Luna's comment to Luna's post", async () => { - const lunaComment = await writeComment(luna, lunaPost.id, 'Luna comment'); + const lunaComment = await justCreateComment(luna, lunaPost.id, 'Luna comment'); const res = await likeComment(lunaComment.id, mars); expect(res, 'to be an API error', 403, 'You can not see this post'); }); it("should not allow Pluto to like Luna's comment to Luna's post", async () => { - const lunaComment = await writeComment(luna, lunaPost.id, 'Luna comment'); + const lunaComment = await justCreateComment(luna, lunaPost.id, 'Luna comment'); const res = await likeComment(lunaComment.id, pluto); expect(res, 'to be an API error', 403, 'You can not see this post'); }); it("should not allow Pluto to like Jupiter's comment to Luna's post", async () => { - const jupiterComment = await writeComment(jupiter, lunaPost.id, 'Jupiter comment'); + const jupiterComment = await justCreateComment( + jupiter, + lunaPost.id, + 'Jupiter comment', + ); const res = await likeComment(jupiterComment.id, pluto); expect(res, 'to be an API error', 403, 'You can not see this post'); }); it('should not display Luna comment likes of Pluto and Mars', async () => { - const jupiterPost = await createAndReturnPost(jupiter, 'Jupiter post'); - const jupiterComment = await writeComment(jupiter, jupiterPost.id, 'Jupiter comment'); + const jupiterPost = await justCreatePost(jupiter, 'Jupiter post'); + const jupiterComment = await justCreateComment( + jupiter, + jupiterPost.id, + 'Jupiter comment', + ); let res = await likeComment(jupiterComment.id, pluto); expect(res, 'to have 1 like by', pluto); await likeComment(jupiterComment.id, mars); @@ -208,56 +214,60 @@ describe('Comment likes', () => { let dubhePost, merakPost, phadPost, alkaidPost; beforeEach(async () => { [dubhe, merak, phad, alkaid] = await Promise.all([ - createGroupAsync(luna, 'dubhe', 'Dubhe', false, false), - createGroupAsync(luna, 'merak', 'Merak', false, true), - createGroupAsync(luna, 'phad', 'Phad', true, false), - createGroupAsync(luna, 'alkaid', 'Alkaid', true, true), + justCreateGroup(luna, 'dubhe', 'Dubhe'), + justCreateGroup(luna, 'merak', 'Merak', { isRestricted: true }), + justCreateGroup(luna, 'phad', 'Phad', { isPrivate: true }), + justCreateGroup(luna, 'alkaid', 'Alkaid', { isPrivate: true, isRestricted: true }), ]); [dubhePost, merakPost, phadPost, alkaidPost] = await Promise.all([ - createAndReturnPostToFeed(dubhe, luna, 'Dubhe post'), - createAndReturnPostToFeed(merak, luna, 'Merak post'), - createAndReturnPostToFeed(phad, luna, 'Phad post'), - createAndReturnPostToFeed(alkaid, luna, 'Alkaid post'), + justCreatePost(luna, 'Dubhe post', [dubhe.username]), + justCreatePost(luna, 'Merak post', [merak.username]), + justCreatePost(luna, 'Phad post', [phad.username]), + justCreatePost(luna, 'Alkaid post', [alkaid.username]), + ]); + await Promise.all([ + sendRequestToJoinGroup(mars, phad), + sendRequestToJoinGroup(mars, alkaid), + ]); + await Promise.all([ + acceptRequestToJoinGroup(luna, mars, phad), + acceptRequestToJoinGroup(luna, mars, alkaid), ]); - await sendRequestToJoinGroup(mars, phad); - await acceptRequestToJoinGroup(luna, mars, phad); - await sendRequestToJoinGroup(mars, alkaid); - await acceptRequestToJoinGroup(luna, mars, alkaid); }); it('should allow any user to like comment in a public group', async () => { - const marsComment = await writeComment(mars, dubhePost.id, 'Mars comment'); + const marsComment = await justCreateComment(mars, dubhePost.id, 'Mars comment'); const res = await likeComment(marsComment.id, jupiter); expect(res, 'to have 1 like by', jupiter); }); it('should allow any user to like comment in a public restricted group', async () => { - const marsComment = await writeComment(mars, merakPost.id, 'Mars comment'); + const marsComment = await justCreateComment(mars, merakPost.id, 'Mars comment'); const res = await likeComment(marsComment.id, jupiter); expect(res, 'to have 1 like by', jupiter); }); it('should allow members to like comment in a private group', async () => { - const marsComment = await writeComment(mars, phadPost.id, 'Mars comment'); + const marsComment = await justCreateComment(mars, phadPost.id, 'Mars comment'); const res = await likeComment(marsComment.id, luna); expect(res, 'to have 1 like by', luna); }); it('should not allow non-members to like comment in a private group', async () => { - const marsComment = await writeComment(mars, phadPost.id, 'Mars comment'); + const marsComment = await justCreateComment(mars, phadPost.id, 'Mars comment'); const res = await likeComment(marsComment.id, jupiter); expect(res, 'to be an API error', 403, 'You can not see this post'); }); it('should allow members to like comment in a private restricted group', async () => { - const marsComment = await writeComment(mars, alkaidPost.id, 'Mars comment'); + const marsComment = await justCreateComment(mars, alkaidPost.id, 'Mars comment'); const res = await likeComment(marsComment.id, luna); expect(res, 'to have 1 like by', luna); }); it('should not allow non-members to like comment in a private restricted group', async () => { - const marsComment = await writeComment(mars, alkaidPost.id, 'Mars comment'); + const marsComment = await justCreateComment(mars, alkaidPost.id, 'Mars comment'); const res = await likeComment(marsComment.id, jupiter); expect(res, 'to be an API error', 403, 'You can not see this post'); }); @@ -278,14 +288,10 @@ describe('Comment likes', () => { let lunaPost, marsPost; beforeEach(async () => { - [luna, mars, jupiter] = await Promise.all([ - createUserAsync('luna', 'pw'), - createUserAsync('mars', 'pw'), - createUserAsync('jupiter', 'pw'), - ]); + [luna, mars, jupiter] = await createTestUsers(['luna', 'mars', 'jupiter']); [lunaPost, marsPost] = await Promise.all([ - createAndReturnPost(luna, 'Luna post'), - createAndReturnPost(mars, 'Mars post'), + justCreatePost(luna, 'Luna post'), + justCreatePost(mars, 'Mars post'), ]); await mutualSubscriptions([luna, mars]); }); @@ -296,40 +302,40 @@ describe('Comment likes', () => { }); it('should not allow to unlike own comments to own post', async () => { - const lunaComment = await writeComment(luna, lunaPost.id, 'Luna comment'); + const lunaComment = await justCreateComment(luna, lunaPost.id, 'Luna comment'); const res = await unlikeComment(lunaComment.id, luna); expect(res, 'to be an API error', 403, "You can't un-like your own comment"); }); it('should not allow to unlike own comments to other user post', async () => { - const lunaComment = await writeComment(luna, marsPost.id, 'Luna comment'); + const lunaComment = await justCreateComment(luna, marsPost.id, 'Luna comment'); const res = await unlikeComment(lunaComment.id, luna); expect(res, 'to be an API error', 403, "You can't un-like your own comment"); }); it("should allow Luna to unlike Mars' comment to Luna's post", async () => { - const marsComment = await writeComment(mars, lunaPost.id, 'Mars comment'); + const marsComment = await justCreateComment(mars, lunaPost.id, 'Mars comment'); await likeComment(marsComment.id, luna); const res = await unlikeComment(marsComment.id, luna); expect(res, 'to have no likes'); }); it("should allow Luna to unlike Mars' comment to Mars' post", async () => { - const marsComment = await writeComment(mars, marsPost.id, 'Mars comment'); + const marsComment = await justCreateComment(mars, marsPost.id, 'Mars comment'); await likeComment(marsComment.id, luna); const res = await unlikeComment(marsComment.id, luna); expect(res, 'to have no likes'); }); it("should allow Jupiter to unlike Mars' comment to Luna's post", async () => { - const marsComment = await writeComment(mars, lunaPost.id, 'Mars comment'); + const marsComment = await justCreateComment(mars, lunaPost.id, 'Mars comment'); await likeComment(marsComment.id, jupiter); const res = await unlikeComment(marsComment.id, jupiter); expect(res, 'to have no likes'); }); it("should not allow to unlike comment that haven't been liked", async () => { - const marsComment = await writeComment(mars, lunaPost.id, 'Mars comment'); + const marsComment = await justCreateComment(mars, lunaPost.id, 'Mars comment'); const res = await unlikeComment(marsComment.id, luna); expect( res, @@ -340,7 +346,7 @@ describe('Comment likes', () => { }); it('should not allow to unlike comment more than one time', async () => { - const marsComment = await writeComment(mars, lunaPost.id, 'Mars comment'); + const marsComment = await justCreateComment(mars, lunaPost.id, 'Mars comment'); await likeComment(marsComment.id, luna); const res1 = await unlikeComment(marsComment.id, luna); expect(res1, 'to have no likes'); @@ -358,11 +364,11 @@ describe('Comment likes', () => { let pluto; beforeEach(async () => { - pluto = await createUserAsync('pluto', 'pw'); + pluto = await createTestUser('pluto'); }); it('should sort comment likes chronologically descending', async () => { - const lunaComment = await writeComment(luna, lunaPost.id, 'Luna comment'); + const lunaComment = await justCreateComment(luna, lunaPost.id, 'Luna comment'); await likeComment(lunaComment.id, mars); await likeComment(lunaComment.id, jupiter); await likeComment(lunaComment.id, pluto); @@ -386,53 +392,61 @@ describe('Comment likes', () => { let plutoPost; beforeEach(async () => { - pluto = await createUserAsync('pluto', 'pw'); - plutoPost = await createAndReturnPost(pluto, 'Pluto post'); + pluto = await createTestUser('pluto'); + plutoPost = await justCreatePost(pluto, 'Pluto post'); await Promise.all([banUser(luna, mars), banUser(luna, pluto)]); }); it("should not allow Luna to unlike Mars' comment to Mars' post", async () => { - const marsComment = await writeComment(mars, marsPost.id, 'Mars comment'); + const marsComment = await justCreateComment(mars, marsPost.id, 'Mars comment'); const res = await unlikeComment(marsComment.id, luna); expect(res, 'to be an API error', 403, 'You can not see this post'); }); it("should not allow Luna to unlike Pluto's comment to Pluto's post", async () => { - const plutoComment = await writeComment(pluto, plutoPost.id, 'Pluto comment'); + const plutoComment = await justCreateComment(pluto, plutoPost.id, 'Pluto comment'); const res = await unlikeComment(plutoComment.id, luna); expect(res, 'to be an API error', 403, 'You can not see this post'); }); it("should not allow Luna to unlike Pluto's comment to Mars' post", async () => { - const plutoComment = await writeComment(pluto, marsPost.id, 'Pluto comment'); + const plutoComment = await justCreateComment(pluto, marsPost.id, 'Pluto comment'); const res = await unlikeComment(plutoComment.id, luna); expect(res, 'to be an API error', 403, 'You can not see this post'); }); it("should not allow Mars to unlike Luna's comment to Luna's post", async () => { - const lunaComment = await writeComment(luna, lunaPost.id, 'Luna comment'); + const lunaComment = await justCreateComment(luna, lunaPost.id, 'Luna comment'); await likeComment(lunaComment.id, mars); const res = await unlikeComment(lunaComment.id, mars); expect(res, 'to be an API error', 403, 'You can not see this post'); }); it("should not allow Pluto to unlike Luna's comment to Luna's post", async () => { - const lunaComment = await writeComment(luna, lunaPost.id, 'Luna comment'); + const lunaComment = await justCreateComment(luna, lunaPost.id, 'Luna comment'); await likeComment(lunaComment.id, pluto); const res = await unlikeComment(lunaComment.id, pluto); expect(res, 'to be an API error', 403, 'You can not see this post'); }); it("should not allow Pluto to unlike Jupiter's comment to Luna's post", async () => { - const jupiterComment = await writeComment(jupiter, lunaPost.id, 'Jupiter comment'); + const jupiterComment = await justCreateComment( + jupiter, + lunaPost.id, + 'Jupiter comment', + ); await likeComment(jupiterComment.id, pluto); const res = await unlikeComment(jupiterComment.id, pluto); expect(res, 'to be an API error', 403, 'You can not see this post'); }); it('should not display Luna comment likes of Pluto and Mars', async () => { - const jupiterPost = await createAndReturnPost(jupiter, 'Jupiter post'); - const jupiterComment = await writeComment(jupiter, jupiterPost.id, 'Jupiter comment'); + const jupiterPost = await justCreatePost(jupiter, 'Jupiter post'); + const jupiterComment = await justCreateComment( + jupiter, + jupiterPost.id, + 'Jupiter comment', + ); await likeComment(jupiterComment.id, pluto); await likeComment(jupiterComment.id, mars); await likeComment(jupiterComment.id, luna); @@ -442,8 +456,8 @@ describe('Comment likes', () => { describe('when Luna bans Jupiter after liking his comment', () => { it("should not allow Luna to unlike Jupiter's comment to Jupiter's post", async () => { - const jupiterPost = await createAndReturnPost(jupiter, 'Jupiter post'); - const jupiterComment = await writeComment( + const jupiterPost = await justCreatePost(jupiter, 'Jupiter post'); + const jupiterComment = await justCreateComment( jupiter, jupiterPost.id, 'Jupiter comment', @@ -463,60 +477,65 @@ describe('Comment likes', () => { let dubhePost, merakPost, phadPost, alkaidPost; beforeEach(async () => { [dubhe, merak, phad, alkaid] = await Promise.all([ - createGroupAsync(luna, 'dubhe', 'Dubhe', false, false), - createGroupAsync(luna, 'merak', 'Merak', false, true), - createGroupAsync(luna, 'phad', 'Phad', true, false), - createGroupAsync(luna, 'alkaid', 'Alkaid', true, true), + justCreateGroup(luna, 'dubhe', 'Dubhe'), + justCreateGroup(luna, 'merak', 'Merak', { isRestricted: true }), + justCreateGroup(luna, 'phad', 'Phad', { isPrivate: true }), + justCreateGroup(luna, 'alkaid', 'Alkaid', { isPrivate: true, isRestricted: true }), ]); [dubhePost, merakPost, phadPost, alkaidPost] = await Promise.all([ - createAndReturnPostToFeed(dubhe, luna, 'Dubhe post'), - createAndReturnPostToFeed(merak, luna, 'Merak post'), - createAndReturnPostToFeed(phad, luna, 'Phad post'), - createAndReturnPostToFeed(alkaid, luna, 'Alkaid post'), + justCreatePost(luna, 'Dubhe post', [dubhe.username]), + justCreatePost(luna, 'Merak post', [merak.username]), + justCreatePost(luna, 'Phad post', [phad.username]), + justCreatePost(luna, 'Alkaid post', [alkaid.username]), + ]); + + await Promise.all([ + sendRequestToJoinGroup(mars, phad), + sendRequestToJoinGroup(mars, alkaid), + ]); + await Promise.all([ + acceptRequestToJoinGroup(luna, mars, phad), + acceptRequestToJoinGroup(luna, mars, alkaid), ]); - await sendRequestToJoinGroup(mars, phad); - await acceptRequestToJoinGroup(luna, mars, phad); - await sendRequestToJoinGroup(mars, alkaid); - await acceptRequestToJoinGroup(luna, mars, alkaid); }); it('should allow any user to unlike comment in a public group', async () => { - const marsComment = await writeComment(mars, dubhePost.id, 'Mars comment'); + const marsComment = await justCreateComment(mars, dubhePost.id, 'Mars comment'); await likeComment(marsComment.id, jupiter); const res = await unlikeComment(marsComment.id, jupiter); expect(res, 'to have no likes'); }); it('should allow any user to unlike comment in a public restricted group', async () => { - const marsComment = await writeComment(mars, merakPost.id, 'Mars comment'); + const marsComment = await justCreateComment(mars, merakPost.id, 'Mars comment'); await likeComment(marsComment.id, jupiter); const res = await unlikeComment(marsComment.id, jupiter); expect(res, 'to have no likes'); }); it('should allow members to unlike comment in a private group', async () => { - const marsComment = await writeComment(mars, phadPost.id, 'Mars comment'); + const marsComment = await justCreateComment(mars, phadPost.id, 'Mars comment'); await likeComment(marsComment.id, luna); const res = await unlikeComment(marsComment.id, luna); expect(res, 'to have no likes'); }); it('should not allow non-members to unlike comment in a private group', async () => { - const marsComment = await writeComment(mars, phadPost.id, 'Mars comment'); + const marsComment = await justCreateComment(mars, phadPost.id, 'Mars comment'); const res = await unlikeComment(marsComment.id, jupiter); expect(res, 'to be an API error', 403, 'You can not see this post'); }); it('should allow members to unlike comment in a private restricted group', async () => { - const marsComment = await writeComment(mars, alkaidPost.id, 'Mars comment'); + const marsComment = await justCreateComment(mars, alkaidPost.id, 'Mars comment'); await likeComment(marsComment.id, luna); const res = await unlikeComment(marsComment.id, luna); expect(res, 'to have no likes'); }); it('should not allow non-members to unlike comment in a private restricted group', async () => { - const marsComment = await writeComment(mars, alkaidPost.id, 'Mars comment'); + const marsComment = await justCreateComment(mars, alkaidPost.id, 'Mars comment'); const res = await unlikeComment(marsComment.id, jupiter); expect(res, 'to be an API error', 403, 'You can not see this post'); }); @@ -531,19 +550,17 @@ describe('Comment likes', () => { let marsComment, lunaComment; beforeEach(async () => { - [luna, mars, jupiter] = await Promise.all([ - createUserAsync('luna', 'pw'), - createUserAsync('mars', 'pw'), - createUserAsync('jupiter', 'pw'), - ]); + [luna, mars, jupiter] = await createTestUsers(['luna', 'mars', 'jupiter']); [lunaPost, marsPost] = await Promise.all([ - createAndReturnPost(luna, 'Luna post'), - createAndReturnPost(mars, 'Mars post'), + justCreatePost(luna, 'Luna post'), + justCreatePost(mars, 'Mars post'), ]); await mutualSubscriptions([luna, mars]); - marsComment = await writeComment(mars, lunaPost.id, 'Mars comment'); - lunaComment = await writeComment(luna, marsPost.id, 'Luna comment'); - await likeComment(marsComment.id, luna); + [marsComment, lunaComment] = await Promise.all([ + justCreateComment(mars, lunaPost.id, 'Mars comment'), + justCreateComment(luna, marsPost.id, 'Luna comment'), + ]); + await justLikeComment(marsComment, luna); }); it('should not allow to show likes of nonexisting comment', async () => { @@ -615,9 +632,9 @@ describe('Comment likes', () => { let pluto; beforeEach(async () => { - pluto = await createUserAsync('pluto', 'pw'); - await likeComment(marsComment.id, jupiter); - await likeComment(marsComment.id, pluto); + pluto = await createTestUser('pluto'); + await justLikeComment(marsComment, jupiter); + await justLikeComment(marsComment, pluto); }); it('should sort comment likes chronologically descending (except viewer)', async () => { @@ -670,12 +687,12 @@ describe('Comment likes', () => { let pluto, plutoPost, plutoComment, jupiterComment; beforeEach(async () => { - pluto = await createUserAsync('pluto', 'pw'); - plutoPost = await createAndReturnPost(pluto, 'Pluto post'); - plutoComment = await writeComment(pluto, plutoPost.id, 'Pluto comment'); - jupiterComment = await writeComment(jupiter, plutoPost.id, 'Jupiter comment'); - await likeComment(plutoComment.id, jupiter); - await likeComment(jupiterComment.id, pluto); + pluto = await createTestUser('pluto'); + plutoPost = await justCreatePost(pluto, 'Pluto post'); + plutoComment = await justCreateComment(pluto, plutoPost.id, 'Pluto comment'); + jupiterComment = await justCreateComment(jupiter, plutoPost.id, 'Jupiter comment'); + await justLikeComment(plutoComment, jupiter); + await justLikeComment(jupiterComment, pluto); await Promise.all([banUser(luna, mars), banUser(luna, pluto)]); }); @@ -710,8 +727,12 @@ describe('Comment likes', () => { }); it('should not display Luna comment likes of Pluto and Mars', async () => { - const jupiterPost = await createAndReturnPost(jupiter, 'Jupiter post'); - const jupiterComment2 = await writeComment(jupiter, jupiterPost.id, 'Jupiter comment'); + const jupiterPost = await justCreatePost(jupiter, 'Jupiter post'); + const jupiterComment2 = await justCreateComment( + jupiter, + jupiterPost.id, + 'Jupiter comment', + ); await likeComment(jupiterComment2.id, pluto); await likeComment(jupiterComment2.id, mars); @@ -766,13 +787,8 @@ describe('Comment likes', () => { }; beforeEach(async () => { - [luna, mars, jupiter, pluto] = await Promise.all([ - createUserAsync('luna', 'pw'), - createUserAsync('mars', 'pw'), - createUserAsync('jupiter', 'pw'), - createUserAsync('pluto', 'pw'), - ]); - lunaPost = await createAndReturnPost(luna, 'Luna post'); + [luna, mars, jupiter, pluto] = await createTestUsers(['luna', 'mars', 'jupiter', 'pluto']); + lunaPost = await justCreatePost(luna, 'Luna post'); await mutualSubscriptions([luna, mars]); }); @@ -796,10 +812,10 @@ describe('Comment likes', () => { describe('should contain actual comment likes count for post with', () => { describe('1 comment', () => { beforeEach(async () => { - const comment = await writeComment(jupiter, lunaPost.id, 'Jupiter comment'); - await likeComment(comment.id, pluto); - await likeComment(comment.id, mars); - await likeComment(comment.id, luna); + const comment = await justCreateComment(jupiter, lunaPost.id, 'Jupiter comment'); + await justLikeComment(comment, pluto); + await justLikeComment(comment, mars); + await justLikeComment(comment, luna); }); it('for anonymous user', async () => @@ -812,13 +828,13 @@ describe('Comment likes', () => { describe('2 comments', () => { beforeEach(async () => { - const comment1 = await writeComment(jupiter, lunaPost.id, 'Jupiter comment'); - const comment2 = await writeComment(luna, lunaPost.id, 'Luna comment'); - await likeComment(comment1.id, pluto); - await likeComment(comment1.id, mars); - await likeComment(comment1.id, luna); - await likeComment(comment2.id, pluto); - await likeComment(comment2.id, mars); + const comment1 = await justCreateComment(jupiter, lunaPost.id, 'Jupiter comment'); + const comment2 = await justCreateComment(luna, lunaPost.id, 'Luna comment'); + await justLikeComment(comment1, pluto); + await justLikeComment(comment1, mars); + await justLikeComment(comment1, luna); + await justLikeComment(comment2, pluto); + await justLikeComment(comment2, mars); }); it('for anonymous user', async () => @@ -833,14 +849,14 @@ describe('Comment likes', () => { describe('3 comments', () => { beforeEach(async () => { - const comment1 = await writeComment(jupiter, lunaPost.id, 'Jupiter comment'); - await writeComment(luna, lunaPost.id, 'Luna comment'); - const comment3 = await writeComment(mars, lunaPost.id, 'Mars comment'); - await likeComment(comment1.id, pluto); - await likeComment(comment1.id, mars); - await likeComment(comment1.id, luna); - await likeComment(comment3.id, pluto); - await likeComment(comment3.id, luna); + const comment1 = await justCreateComment(jupiter, lunaPost.id, 'Jupiter comment'); + await justCreateComment(luna, lunaPost.id, 'Luna comment'); + const comment3 = await justCreateComment(mars, lunaPost.id, 'Mars comment'); + await justLikeComment(comment1, pluto); + await justLikeComment(comment1, mars); + await justLikeComment(comment1, luna); + await justLikeComment(comment3, pluto); + await justLikeComment(comment3, luna); }); it('for anonymous user', async () => @@ -857,14 +873,14 @@ describe('Comment likes', () => { describe('4 comments', () => { beforeEach(async () => { - const comment1 = await writeComment(jupiter, lunaPost.id, 'Jupiter comment'); - const comment2 = await writeComment(luna, lunaPost.id, 'Luna comment'); - const comment3 = await writeComment(mars, lunaPost.id, 'Mars comment'); - const comment4 = await writeComment(mars, lunaPost.id, 'Mars comment'); - await likeComment(comment1.id, pluto); - await likeComment(comment2.id, mars); - await likeComment(comment3.id, jupiter); - await likeComment(comment4.id, luna); + const comment1 = await justCreateComment(jupiter, lunaPost.id, 'Jupiter comment'); + const comment2 = await justCreateComment(luna, lunaPost.id, 'Luna comment'); + const comment3 = await justCreateComment(mars, lunaPost.id, 'Mars comment'); + const comment4 = await justCreateComment(mars, lunaPost.id, 'Mars comment'); + await justLikeComment(comment1, pluto); + await justLikeComment(comment2, mars); + await justLikeComment(comment3, jupiter); + await justLikeComment(comment4, luna); }); describe('with comment folding', () => { @@ -896,15 +912,15 @@ describe('Comment likes', () => { describe('5 comments', () => { beforeEach(async () => { - const comment1 = await writeComment(jupiter, lunaPost.id, 'Jupiter comment'); - const comment2 = await writeComment(luna, lunaPost.id, 'Luna comment'); - const comment3 = await writeComment(mars, lunaPost.id, 'Mars comment'); - await writeComment(mars, lunaPost.id, 'Mars comment'); - const comment5 = await writeComment(pluto, lunaPost.id, 'Pluto comment'); - await likeComment(comment1.id, pluto); - await likeComment(comment2.id, mars); - await likeComment(comment3.id, jupiter); - await likeComment(comment5.id, luna); + const comment1 = await justCreateComment(jupiter, lunaPost.id, 'Jupiter comment'); + const comment2 = await justCreateComment(luna, lunaPost.id, 'Luna comment'); + const comment3 = await justCreateComment(mars, lunaPost.id, 'Mars comment'); + await justCreateComment(mars, lunaPost.id, 'Mars comment'); + const comment5 = await justCreateComment(pluto, lunaPost.id, 'Pluto comment'); + await justLikeComment(comment1, pluto); + await justLikeComment(comment2, mars); + await justLikeComment(comment3, jupiter); + await justLikeComment(comment5, luna); }); describe('with comment folding', () => { @@ -937,15 +953,15 @@ describe('Comment likes', () => { describe("should exclude banned user's comment likes", () => { beforeEach(async () => { - const comment1 = await writeComment(jupiter, lunaPost.id, 'Jupiter comment'); - const comment2 = await writeComment(luna, lunaPost.id, 'Luna comment'); - const comment3 = await writeComment(mars, lunaPost.id, 'Mars comment'); - await writeComment(mars, lunaPost.id, 'Mars comment'); - const comment5 = await writeComment(pluto, lunaPost.id, 'Pluto comment'); - await likeComment(comment1.id, pluto); - await likeComment(comment2.id, mars); - await likeComment(comment3.id, jupiter); - await likeComment(comment5.id, luna); + const comment1 = await justCreateComment(jupiter, lunaPost.id, 'Jupiter comment'); + const comment2 = await justCreateComment(luna, lunaPost.id, 'Luna comment'); + const comment3 = await justCreateComment(mars, lunaPost.id, 'Mars comment'); + await justCreateComment(mars, lunaPost.id, 'Mars comment'); + const comment5 = await justCreateComment(pluto, lunaPost.id, 'Pluto comment'); + await justLikeComment(comment1, pluto); + await justLikeComment(comment2, mars); + await justLikeComment(comment3, jupiter); + await justLikeComment(comment5, luna); await Promise.all([banUser(luna, jupiter), banUser(luna, pluto)]); }); @@ -971,10 +987,10 @@ describe('Comment likes', () => { describe('should be present in comment payload', () => { beforeEach(async () => { - const comment = await writeComment(jupiter, lunaPost.id, 'Jupiter comment'); - await likeComment(comment.id, pluto); - await likeComment(comment.id, mars); - await likeComment(comment.id, luna); + const comment = await justCreateComment(jupiter, lunaPost.id, 'Jupiter comment'); + await justLikeComment(comment, pluto); + await justLikeComment(comment, mars); + await justLikeComment(comment, luna); }); it('for anonymous user', async () => { @@ -1097,18 +1113,13 @@ describe('Comment likes', () => { }; beforeEach(async () => { - [luna, mars, jupiter, pluto] = await Promise.all([ - createUserAsync('luna', 'pw'), - createUserAsync('mars', 'pw'), - createUserAsync('jupiter', 'pw'), - createUserAsync('pluto', 'pw'), - ]); - lunaPost = await createAndReturnPost(luna, 'Luna post'); + [luna, mars, jupiter, pluto] = await createTestUsers(['luna', 'mars', 'jupiter', 'pluto']); + lunaPost = await justCreatePost(luna, 'Luna post'); await mutualSubscriptions([luna, mars]); - comment = await writeComment(jupiter, lunaPost.id, 'Jupiter comment'); - await likeComment(comment.id, pluto); - await likeComment(comment.id, mars); + comment = await justCreateComment(jupiter, lunaPost.id, 'Jupiter comment'); + await justLikeComment(comment, pluto); + await justLikeComment(comment, mars); }); describe('comment likes fields should be present', () => { @@ -1131,7 +1142,7 @@ describe('Comment likes', () => { { username: 'mars', authToken: luna.authToken }, 'Luna direct', ); - const directComment = await writeComment( + const directComment = await justCreateComment( mars, luna2marsDirectPost.id, 'Mars direct comment', @@ -1149,10 +1160,10 @@ describe('Comment likes', () => { describe('comments likes fields should contain correct counts', () => { let comment2, comment3, comment4, comment5; beforeEach(async () => { - comment2 = await writeComment(mars, lunaPost.id, 'Mars comment'); - comment3 = await writeComment(pluto, lunaPost.id, 'Pluto comment'); - comment4 = await writeComment(luna, lunaPost.id, 'Luna comment'); - comment5 = await writeComment(jupiter, lunaPost.id, 'Jupiter comment'); + comment2 = await justCreateComment(mars, lunaPost.id, 'Mars comment'); + comment3 = await justCreateComment(pluto, lunaPost.id, 'Pluto comment'); + comment4 = await justCreateComment(luna, lunaPost.id, 'Luna comment'); + comment5 = await justCreateComment(jupiter, lunaPost.id, 'Jupiter comment'); }); it('when only first comment is liked', async () => await expectFeedCommentLikesCountsToBe('home', luna, 2, 0, 0, 0)); @@ -1227,7 +1238,7 @@ describe('Comment likes', () => { }); it(`and last (and liked) comment's author is banned by viewer [negative OmittedCommentLikes]`, async () => { - const comment6 = await writeComment(pluto, lunaPost.id, 'Pluto comment 2'); + const comment6 = await justCreateComment(pluto, lunaPost.id, 'Pluto comment 2'); await likeComment(comment6.id, mars); await likeComment(comment6.id, jupiter); await banUser(luna, pluto); @@ -1239,23 +1250,23 @@ describe('Comment likes', () => { describe('#bestOf', () => { beforeEach(async () => { - const neptune = await createUserAsync('neptune', 'pw'); + const neptune = await createTestUser('neptune'); await Promise.all([ - writeComment(jupiter, lunaPost.id, 'Jupiter comment2'), - writeComment(jupiter, lunaPost.id, 'Jupiter comment3'), - writeComment(pluto, lunaPost.id, 'Pluto comment1'), - writeComment(pluto, lunaPost.id, 'Pluto comment2'), - writeComment(pluto, lunaPost.id, 'Pluto comment3'), - writeComment(mars, lunaPost.id, 'Mars comment1'), - writeComment(mars, lunaPost.id, 'Mars comment2'), - writeComment(mars, lunaPost.id, 'Mars comment3'), - writeComment(luna, lunaPost.id, 'Luna comment1'), - writeComment(luna, lunaPost.id, 'Luna comment2'), - writeComment(luna, lunaPost.id, 'Luna comment3'), - writeComment(neptune, lunaPost.id, 'Neptune comment1'), - writeComment(neptune, lunaPost.id, 'Neptune comment2'), - writeComment(neptune, lunaPost.id, 'Neptune comment3'), + justCreateComment(jupiter, lunaPost.id, 'Jupiter comment2'), + justCreateComment(jupiter, lunaPost.id, 'Jupiter comment3'), + justCreateComment(pluto, lunaPost.id, 'Pluto comment1'), + justCreateComment(pluto, lunaPost.id, 'Pluto comment2'), + justCreateComment(pluto, lunaPost.id, 'Pluto comment3'), + justCreateComment(mars, lunaPost.id, 'Mars comment1'), + justCreateComment(mars, lunaPost.id, 'Mars comment2'), + justCreateComment(mars, lunaPost.id, 'Mars comment3'), + justCreateComment(luna, lunaPost.id, 'Luna comment1'), + justCreateComment(luna, lunaPost.id, 'Luna comment2'), + justCreateComment(luna, lunaPost.id, 'Luna comment3'), + justCreateComment(neptune, lunaPost.id, 'Neptune comment1'), + justCreateComment(neptune, lunaPost.id, 'Neptune comment2'), + justCreateComment(neptune, lunaPost.id, 'Neptune comment3'), ]); const promises = []; @@ -1313,18 +1324,13 @@ describe('Comment likes', () => { }; beforeEach(async () => { - [luna, mars, jupiter, pluto] = await Promise.all([ - createUserAsync('luna', 'pw'), - createUserAsync('mars', 'pw'), - createUserAsync('jupiter', 'pw'), - createUserAsync('pluto', 'pw'), - ]); - lunaPost = await createAndReturnPost(luna, 'Luna post cliked'); + [luna, mars, jupiter, pluto] = await createTestUsers(['luna', 'mars', 'jupiter', 'pluto']); + lunaPost = await justCreatePost(luna, 'Luna post cliked'); await mutualSubscriptions([luna, mars]); - comment = await writeComment(jupiter, lunaPost.id, 'Jupiter comment'); - await likeComment(comment.id, pluto); - await likeComment(comment.id, mars); + comment = await justCreateComment(jupiter, lunaPost.id, 'Jupiter comment'); + await justLikeComment(comment, pluto); + await justLikeComment(comment, mars); }); describe('comment likes fields should be present', () => { @@ -1340,10 +1346,10 @@ describe('Comment likes', () => { describe('comments likes fields should contain correct counts', () => { let comment2, comment3, comment4, comment5; beforeEach(async () => { - comment2 = await writeComment(mars, lunaPost.id, 'Mars comment'); - comment3 = await writeComment(pluto, lunaPost.id, 'Pluto comment'); - comment4 = await writeComment(luna, lunaPost.id, 'Luna comment'); - comment5 = await writeComment(jupiter, lunaPost.id, 'Jupiter comment'); + comment2 = await justCreateComment(mars, lunaPost.id, 'Mars comment'); + comment3 = await justCreateComment(pluto, lunaPost.id, 'Pluto comment'); + comment4 = await justCreateComment(luna, lunaPost.id, 'Luna comment'); + comment5 = await justCreateComment(jupiter, lunaPost.id, 'Jupiter comment'); }); it('when only first comment is liked', async () => await expectSearchResultsCommentLikesCountsToBe('cliked', luna, 2, 0, 0, 0)); @@ -1418,7 +1424,7 @@ describe('Comment likes', () => { }); it(`and last (and liked) comment's author is banned by viewer [negative OmittedCommentLikes]`, async () => { - const comment6 = await writeComment(pluto, lunaPost.id, 'Pluto comment 2'); + const comment6 = await justCreateComment(pluto, lunaPost.id, 'Pluto comment 2'); await likeComment(comment6.id, mars); await likeComment(comment6.id, jupiter); await banUser(luna, pluto); @@ -1430,12 +1436,6 @@ describe('Comment likes', () => { }); }); -const createComment = () => async (userContext, postId, body) => { - const response = await createCommentAsync(userContext, postId, body); - const commentData = await response.json(); - return commentData.comments; -}; - const fetchPost = (app) => async (postId, viewerContext = null, allComments = false) => { diff --git a/test/functional/comments.js b/test/functional/comments.js index 6cf14bdd0..5c03e30c9 100644 --- a/test/functional/comments.js +++ b/test/functional/comments.js @@ -26,7 +26,7 @@ describe('CommentsController', () => { let context = {}; beforeEach(async () => { context = await funcTestHelper.createUserAsync('Luna', 'password'); - context.post = await funcTestHelper.createAndReturnPost(context, 'Post body'); + context.post = await funcTestHelper.justCreatePost(context, 'Post body'); }); describe('in a group', () => { @@ -154,7 +154,7 @@ describe('CommentsController', () => { beforeEach(async () => { mars = await funcTestHelper.createUserAsync('Mars', 'password'); - postOfMars = await funcTestHelper.createAndReturnPost(mars, 'I am mars!'); + postOfMars = await funcTestHelper.justCreatePost(mars, 'I am mars!'); await funcTestHelper.banUser(context, mars); }); @@ -181,11 +181,8 @@ describe('CommentsController', () => { funcTestHelper.createUserAsync('yole', 'pw'), ]); - const post = await funcTestHelper.createAndReturnPost(lunaContext, 'post body'); - const response = await funcTestHelper.createCommentAsync(lunaContext, post.id, 'comment'); - const commentData = await response.json(); - - comment = commentData.comments; + const post = await funcTestHelper.justCreatePost(lunaContext, 'post body'); + comment = await funcTestHelper.justCreateComment(lunaContext, post.id, 'comment'); }); it('should update a comment with a valid user', (done) => { @@ -258,33 +255,39 @@ describe('CommentsController', () => { ]); const [lunaPost, marsPost] = await Promise.all([ - funcTestHelper.createAndReturnPost(lunaContext, 'Post body 1'), - funcTestHelper.createAndReturnPost(marsContext, 'Post body 2'), + funcTestHelper.justCreatePost(lunaContext, 'Post body 1'), + funcTestHelper.justCreatePost(marsContext, 'Post body 2'), ]); - let response = await funcTestHelper.createCommentAsync( + ({ id: lunaPostLunaComment } = await funcTestHelper.justCreateComment( lunaContext, lunaPost.id, 'Comment 1-1', - ); - let data = await response.json(); - lunaPostLunaComment = data.comments.id; + )); - response = await funcTestHelper.createCommentAsync(marsContext, lunaPost.id, 'Comment 1-2'); - data = await response.json(); - lunaPostMarsComment = data.comments.id; - - response = await funcTestHelper.createCommentAsync(marsContext, marsPost.id, 'Comment 2-1'); - data = await response.json(); - marsPostMarsComment = data.comments.id; + ({ id: lunaPostMarsComment } = await funcTestHelper.justCreateComment( + marsContext, + lunaPost.id, + 'Comment 1-2', + )); - response = await funcTestHelper.createCommentAsync(lunaContext, marsPost.id, 'Comment 2-2'); - data = await response.json(); - marsPostLunaComment = data.comments.id; + ({ id: marsPostMarsComment } = await funcTestHelper.justCreateComment( + marsContext, + marsPost.id, + 'Comment 2-1', + )); - response = await funcTestHelper.createCommentAsync(ceresContext, marsPost.id, 'Comment 2-3'); - data = await response.json(); - marsPostCeresComment = data.comments.id; + ({ id: marsPostLunaComment } = await funcTestHelper.justCreateComment( + lunaContext, + marsPost.id, + 'Comment 2-2', + )); + + ({ id: marsPostCeresComment } = await funcTestHelper.justCreateComment( + ceresContext, + marsPost.id, + 'Comment 2-3', + )); }); it('should remove comment (your own comment in your own post)', async () => { @@ -330,19 +333,17 @@ describe('CommentsController', () => { let luna, mars, venus, postId, commentIds; beforeEach(async () => { [luna, mars, venus] = await funcTestHelper.createTestUsers(['luna', 'mars', 'venus']); - ({ id: postId } = await funcTestHelper.createAndReturnPost(luna, 'post')); + ({ id: postId } = await funcTestHelper.justCreatePost(luna, 'post')); commentIds = []; for (let i = 0; i < 3; i++) { // eslint-disable-next-line no-await-in-loop - const resp = await funcTestHelper.createCommentAsync( + const data = await funcTestHelper.justCreateComment( [luna, mars, luna][i], postId, `Comment ${i + 1}`, ); - // eslint-disable-next-line no-await-in-loop - const data = await resp.json(); - commentIds.push(data.comments.id); + commentIds.push(data.id); } }); @@ -572,25 +573,15 @@ describe('CommentsController', () => { const nComments = 10; let luna, mars, venus, comments; beforeEach(async () => { - luna = await funcTestHelper.createUserAsync('luna', 'password'); - mars = await funcTestHelper.createUserAsync('mars', 'password'); - venus = await funcTestHelper.createUserAsync('venus', 'password'); - const post = await funcTestHelper.createAndReturnPost(venus, 'Post body'); + [luna, mars, venus] = await funcTestHelper.createTestUsers(['luna', 'mars', 'venus']); + const post = await funcTestHelper.justCreatePost(venus, 'Post body'); comments = []; for (let n = 0; n < nComments; n++) { comments.push( - // eslint-disable-next-line prettier/prettier - ( - // eslint-disable-next-line no-await-in-loop - await funcTestHelper.performJSONRequest( - 'POST', - `/v2/comments`, - { comment: { body: 'Comment', postId: post.id } }, - funcTestHelper.authHeaders(n % 2 == 0 ? luna : mars), - ) - ).comments, + // eslint-disable-next-line no-await-in-loop + await funcTestHelper.justCreateComment(n % 2 == 0 ? luna : mars, post.id, 'Comment'), ); } diff --git a/test/functional/events.js b/test/functional/events.js index ee0b2ae27..8706906e9 100644 --- a/test/functional/events.js +++ b/test/functional/events.js @@ -44,6 +44,8 @@ import { performJSONRequest, authHeaders, createTestUsers, + justCreateComment, + justCreatePost, } from '../functional/functional_test_helper'; import * as schema from './schemaV2-helper'; @@ -82,15 +84,14 @@ describe('EventService', () => { }; beforeEach(async () => { - [luna, mars, jupiter, pluto] = await Promise.all([ - createUserAsync('luna', 'pw'), - createUserAsync('mars', 'pw'), - createUserAsync('jupiter', 'pw'), - createUserAsync('pluto', 'pw'), - ]); + [luna, mars, jupiter, pluto] = await createTestUsers(['luna', 'mars', 'jupiter', 'pluto']); - [lunaUserModel, marsUserModel, jupiterUserModel, plutoUserModel] = - await dbAdapter.getUsersByIds([luna.user.id, mars.user.id, jupiter.user.id, pluto.user.id]); + [lunaUserModel, marsUserModel, jupiterUserModel, plutoUserModel] = [ + luna.user, + mars.user, + jupiter.user, + pluto.user, + ]; await mutualSubscriptions([luna, mars]); await subscribeToAsync(jupiter, luna); @@ -212,12 +213,8 @@ describe('EventService', () => { }; beforeEach(async () => { - [luna, mars] = await Promise.all([ - createUserAsync('luna', 'pw'), - createUserAsync('mars', 'pw'), - ]); - - [lunaUserModel, marsUserModel] = await dbAdapter.getUsersByIds([luna.user.id, mars.user.id]); + [luna, mars] = await createTestUsers(['luna', 'mars']); + [lunaUserModel, marsUserModel] = [luna.user, mars.user]; }); it('should create user_subscribed event when user subscribed', async () => { @@ -363,9 +360,8 @@ describe('EventService', () => { let luna, mars, lunasPost, marsesComment; beforeEach(async () => { [luna, mars] = await createTestUsers(['luna', 'mars']); - lunasPost = await createAndReturnPost(luna, 'Post'); - const resp = await createCommentAsync(mars, lunasPost.id, 'Comment'); - ({ comments: marsesComment } = await resp.json()); + lunasPost = await justCreatePost(luna, 'Post'); + marsesComment = await justCreateComment(mars, lunasPost.id, 'Comment'); }); it(`should create comment_moderated event for Mars when Luna removes Mars'es comment`, async () => { @@ -397,12 +393,8 @@ describe('EventService', () => { }; beforeEach(async () => { - [luna, mars] = await Promise.all([ - createUserAsync('luna', 'pw'), - createUserAsync('mars', 'pw'), - ]); - - [lunaUserModel, marsUserModel] = await dbAdapter.getUsersByIds([luna.user.id, mars.user.id]); + [luna, mars] = await createTestUsers(['luna', 'mars']); + [lunaUserModel, marsUserModel] = [luna.user, mars.user]; await goPrivate(luna); }); @@ -537,15 +529,14 @@ describe('EventService', () => { }; beforeEach(async () => { - [luna, mars, jupiter, pluto] = await Promise.all([ - createUserAsync('luna', 'pw'), - createUserAsync('mars', 'pw'), - createUserAsync('jupiter', 'pw'), - createUserAsync('pluto', 'pw'), - ]); + [luna, mars, jupiter, pluto] = await createTestUsers(['luna', 'mars', 'jupiter', 'pluto']); - [lunaUserModel, marsUserModel, jupiterUserModel, plutoUserModel] = - await dbAdapter.getUsersByIds([luna.user.id, mars.user.id, jupiter.user.id, pluto.user.id]); + [lunaUserModel, marsUserModel, jupiterUserModel, plutoUserModel] = [ + luna.user, + mars.user, + jupiter.user, + pluto.user, + ]; }); describe('creation', () => { @@ -1012,15 +1003,14 @@ describe('EventService', () => { }; beforeEach(async () => { - [luna, mars, jupiter, pluto] = await Promise.all([ - createUserAsync('luna', 'pw'), - createUserAsync('mars', 'pw'), - createUserAsync('jupiter', 'pw'), - createUserAsync('pluto', 'pw'), - ]); + [luna, mars, jupiter, pluto] = await createTestUsers(['luna', 'mars', 'jupiter', 'pluto']); - [lunaUserModel, marsUserModel, jupiterUserModel, plutoUserModel] = - await dbAdapter.getUsersByIds([luna.user.id, mars.user.id, jupiter.user.id, pluto.user.id]); + [lunaUserModel, marsUserModel, jupiterUserModel, plutoUserModel] = [ + luna.user, + mars.user, + jupiter.user, + pluto.user, + ]; await mutualSubscriptions([luna, mars, jupiter, pluto]); }); @@ -1224,15 +1214,14 @@ describe('EventService', () => { }; beforeEach(async () => { - [luna, mars, jupiter, pluto] = await Promise.all([ - createUserAsync('luna', 'pw'), - createUserAsync('mars', 'pw'), - createUserAsync('jupiter', 'pw'), - createUserAsync('pluto', 'pw'), - ]); - - [lunaUserModel, marsUserModel, jupiterUserModel, plutoUserModel] = - await dbAdapter.getUsersByIds([luna.user.id, mars.user.id, jupiter.user.id, pluto.user.id]); + [luna, mars, jupiter, pluto] = await createTestUsers(['luna', 'mars', 'jupiter', 'pluto']); + + [lunaUserModel, marsUserModel, jupiterUserModel, plutoUserModel] = [ + luna.user, + mars.user, + jupiter.user, + pluto.user, + ]; await mutualSubscriptions([luna, jupiter]); await goPrivate(jupiter); }); @@ -1420,7 +1409,7 @@ describe('EventService', () => { let post; beforeEach(async () => { - post = await createAndReturnPostToFeed(luna, luna, 'Test post'); + post = await justCreatePost(luna, 'Test post'); }); it('should create mention_in_comment event for mentioned user', async () => { @@ -1705,12 +1694,8 @@ describe('EventService', () => { let lunaUserModel, marsUserModel; beforeEach(async () => { - [luna, mars] = await Promise.all([ - createUserAsync('luna', 'pw'), - createUserAsync('mars', 'pw'), - ]); - - [lunaUserModel, marsUserModel] = await dbAdapter.getUsersByIds([luna.user.id, mars.user.id]); + [luna, mars] = await createTestUsers(['luna', 'mars']); + [lunaUserModel, marsUserModel] = [luna.user, mars.user]; }); describe("event shouldn't be deleted when", () => { @@ -1811,12 +1796,8 @@ describe('EventsController', () => { let luna, mars, lunaUserModel, marsUserModel; beforeEach(async () => { - [luna, mars] = await Promise.all([ - createUserAsync('luna', 'pw'), - createUserAsync('mars', 'pw'), - ]); - - [lunaUserModel, marsUserModel] = await dbAdapter.getUsersByIds([luna.user.id, mars.user.id]); + [luna, mars] = await createTestUsers(['luna', 'mars']); + [lunaUserModel, marsUserModel] = [luna.user, mars.user]; await mutualSubscriptions([luna, mars]); }); @@ -2252,12 +2233,8 @@ describe('Unread events counter', () => { beforeEach(async () => { await cleanDB($pg_database); - [luna, mars] = await Promise.all([ - createUserAsync('luna', 'pw'), - createUserAsync('mars', 'pw'), - ]); - - [lunaUserModel] = await dbAdapter.getUsersByIds([luna.user.id]); + [luna, mars] = await createTestUsers(['luna', 'mars']); + lunaUserModel = luna.user; }); const getUnreadEventsCountFromWhoAmI = async (user) => { @@ -2371,10 +2348,7 @@ describe('Unread events counter realtime updates for ', () => { beforeEach(async () => { await cleanDB($pg_database); - [luna, mars] = await Promise.all([ - createUserAsync('luna', 'pw'), - createUserAsync('mars', 'pw'), - ]); + [luna, mars] = await createTestUsers(['luna', 'mars']); }); describe('user_subscribed event', () => { @@ -2876,10 +2850,7 @@ describe('eventById', () => { beforeEach(async () => { await cleanDB($pg_database); - [luna, mars] = await Promise.all([ - createUserAsync('luna', 'pw'), - createUserAsync('mars', 'pw'), - ]); + [luna, mars] = await createTestUsers(['luna', 'mars']); // To create some records in events history await mutualSubscriptions([luna, mars]); }); diff --git a/test/functional/functional_test_helper.d.ts b/test/functional/functional_test_helper.d.ts index edb21e4a4..2d0dd847b 100644 --- a/test/functional/functional_test_helper.d.ts +++ b/test/functional/functional_test_helper.d.ts @@ -1,4 +1,5 @@ -import { User } from '../../app/models'; +import { Comment, Group, Post, User } from '../../app/models'; +import { UUID } from '../../app/support/types'; export type UserCtx = { authToken: string; @@ -28,3 +29,24 @@ export function authHeaders(userCtx: Pick | null): { }; export function cmpBy(key: keyof T): (a: T, b: T) => number; + +export function justCreatePost( + authorCtx: UserCtx, + body: string, + destNames?: string[], +): Promise; + +export function justCreateComment(authorCtx: UserCtx, postId: UUID, body: string): Promise; + +export function justCreateGroup( + creatorCtx: UserCtx, + username: string, + screenName?: string, + opts?: { + isPrivate?: boolean; + isProtected?: boolean; + isRestricted?: boolean; + }, +): Promise; + +export function justLikeComment(commentObj: Comment, userCtx: UserCtx): Promise; diff --git a/test/functional/functional_test_helper.js b/test/functional/functional_test_helper.js index 237b89b18..c13ff06a6 100644 --- a/test/functional/functional_test_helper.js +++ b/test/functional/functional_test_helper.js @@ -10,10 +10,11 @@ import socketIO from 'socket.io-client'; import expect from 'unexpected'; import Application from 'koa'; -import { dbAdapter, sessionTokenV1Store, User } from '../../app/models'; +import { dbAdapter, sessionTokenV1Store, User, Group } from '../../app/models'; import { getSingleton as initApp } from '../../app/app'; import { addMailListener } from '../../lib/mailer'; import { API_VERSION_ACTUAL } from '../../app/api-versions'; +import { createPost as iCreatePost } from '../integration/helpers/posts-and-comments'; import * as schema from './schemaV2-helper'; @@ -22,57 +23,6 @@ const apiUrl = async (relativeUrl) => { return `${app.context.config.host}${relativeUrl}`; }; -export function createUser(username, password, attributes, callback) { - return function (done) { - if (typeof attributes === 'function') { - callback = attributes; - attributes = {}; - } - - if (typeof attributes === 'undefined') { - attributes = {}; - } - - const user = { - username, - password, - }; - - if (attributes.email) { - user.email = attributes.email; - } - - apiUrl('/v1/users') - .then((url) => { - request - .post(url) - .send(user) - .end((err, res) => { - if (callback) { - const luna = res.body.users; - luna.password = user.password; - callback(res.body.authToken, luna); - } - - done(); - }); - }) - .catch((e) => { - done(e); - }); - }; -} - -export function createUserCtx(context, username, password, attrs) { - return createUser(username, password, attrs, (token, user) => { - context.user = user; - context.authToken = token; - context.username = username.toLowerCase(); - context.password = password; - context.attributes = attrs; - }); -} - export function subscribeToCtx(context, username) { return function (done) { apiUrl(`/v1/users/${username}/subscribe`) @@ -160,6 +110,42 @@ export async function getSummary(context, params = {}) { return await response.json(); } +// The just* functions create objects using the model API (without HTTP +// requests) and without any checks. Use them to speed up test setup (for +// example, in beforeEach) when object creation is not the purpose of the test. + +export async function justCreatePost(authorCtx, body, destNames = [authorCtx.username]) { + const destAccounts = await dbAdapter.getFeedOwnersByUsernames(destNames); + return await iCreatePost(authorCtx.user, body, destAccounts); +} + +export async function justCreateComment(authorCtx, postId, body) { + const comment = authorCtx.user.newComment({ body, postId }); + await comment.create(); + return comment; +} + +export async function justCreateGroup( + creatorCtx, + username, + screenName = username, + { isPrivate = false, isProtected = isPrivate, isRestricted = false } = {}, +) { + const g = new Group({ + username, + screenName, + isPrivate: isPrivate ? '1' : '0', + isProtected: isProtected ? '1' : '0', + isRestricted: isRestricted ? '1' : '0', + }); + await g.create(creatorCtx.user.id); + return g; +} + +export async function justLikeComment(commentObj, userCtx) { + await commentObj.addLike(userCtx.user); +} + export function createPost(context, body, callback) { return function (done) { apiUrl('/v1/posts') @@ -593,8 +579,19 @@ export function groupToProtected(group, userContext) { return updateGroupAsync(group, userContext, { isPrivate: '0', isProtected: '1' }); } -export function subscribeToAsync(subscriber, victim) { - return postJson(`/v1/users/${victim.username}/subscribe`, { authToken: subscriber.authToken }); +export async function subscribeToAsync(subscriber, victim) { + let victimObj; + + if (victim instanceof User) { + victimObj = victim; + } else if (victim.user) { + victimObj = victim.user; + } else { + // Old-fashion group or user context + victimObj = await dbAdapter.getFeedOwnerById(victim.id ?? victim.group.id); + } + + await subscriber.user.subscribeTo(victimObj); } export function unsubscribeFromAsync(unsubscriber, victim) { @@ -628,7 +625,7 @@ export async function mutualSubscriptions(userContexts) { continue; } - promises.push(subscribeToAsync(ctx1, ctx2)); + promises.push(ctx1.user.subscribeTo(ctx2.user)); } } @@ -1019,8 +1016,7 @@ const PromisifiedIO = (host, options, events) => { export async function createRealtimeConnection(context, callbacks) { const app = await initApp(); - - const port = process.env.PEPYATKA_SERVER_PORT || app.context.port; + const { port } = app.context; const options = { transports: ['websocket'], forceNew: true, diff --git a/test/functional/local-bumps.js b/test/functional/local-bumps.js index 432126e8d..467f229a9 100644 --- a/test/functional/local-bumps.js +++ b/test/functional/local-bumps.js @@ -28,7 +28,7 @@ describe('Local bumps', () => { marsPosts = []; for (let i = 0; i < nPosts; i++) { - const { id } = await helper.createAndReturnPost(mars, 'post'); // eslint-disable-line no-await-in-loop + const { id } = await helper.justCreatePost(mars, 'post'); // eslint-disable-line no-await-in-loop marsPosts.push(id); } @@ -38,7 +38,7 @@ describe('Local bumps', () => { lunaPosts = []; for (let i = 0; i < nPosts; i++) { - const { id } = await helper.createAndReturnPost(luna, 'post'); // eslint-disable-line no-await-in-loop + const { id } = await helper.justCreatePost(luna, 'post'); // eslint-disable-line no-await-in-loop lunaPosts.push(id); } @@ -52,7 +52,7 @@ describe('Local bumps', () => { marsPostsInGroup = []; for (let i = 0; i < nPosts; i++) { - const { id } = await helper.createAndReturnPostToFeed(celestials, mars, 'post'); // eslint-disable-line no-await-in-loop + const { id } = await helper.justCreatePost(mars, 'post', [celestials.username]); // eslint-disable-line no-await-in-loop marsPostsInGroup.push(id); } diff --git a/test/functional/posts/edit-destinations.js b/test/functional/posts/edit-destinations.js index 576e14030..2992a118f 100644 --- a/test/functional/posts/edit-destinations.js +++ b/test/functional/posts/edit-destinations.js @@ -6,11 +6,11 @@ import cleanDB from '../../dbCleaner'; import { createTestUsers, mutualSubscriptions, - createAndReturnPostToFeed, performJSONRequest, authHeaders, - createGroupAsync, groupToPrivate, + justCreatePost, + justCreateGroup, } from '../functional_test_helper'; import { GONE_SUSPENDED } from '../../../app/models/user'; @@ -29,7 +29,7 @@ describe('Update destinations of existing post', () => { await mutualSubscriptions([luna, mars]); // Luna sent direct message to Mars - post = await createAndReturnPostToFeed([mars], luna, 'Hello, Mars!'); + post = await justCreatePost(luna, 'Hello, Mars!', [mars.username, luna.username]); // Mars decide to delete his account await mars.user.setGoneStatus(GONE_SUSPENDED); @@ -72,10 +72,10 @@ describe('Update destinations of existing post', () => { describe('Luna wrote post to group, group became private', () => { let celestials; beforeEach(async () => { - celestials = await createGroupAsync(mars, 'celestials', 'Celestials'); + celestials = await justCreateGroup(mars, 'celestials', 'Celestials'); - post = await createAndReturnPostToFeed([celestials, luna], luna, 'Hello, world!'); - await groupToPrivate(celestials.group, mars); + post = await justCreatePost(luna, 'Hello, world!', [celestials.username, luna.username]); + await groupToPrivate(celestials, mars); }); it(`should allow Luna to update the post without 'feeds' field`, async () => { diff --git a/test/functional/posts/leave-direct.js b/test/functional/posts/leave-direct.js index 0ff6ca0aa..1266c3d3e 100644 --- a/test/functional/posts/leave-direct.js +++ b/test/functional/posts/leave-direct.js @@ -8,8 +8,8 @@ import { PubSubAdapter } from '../../../app/support/PubSubAdapter'; import { dbAdapter, PubSub } from '../../../app/models'; import { authHeaders, - createAndReturnPostToFeed, createTestUsers, + justCreatePost, mutualSubscriptions, performJSONRequest, } from '../functional_test_helper'; @@ -20,7 +20,7 @@ import { getEventText } from '../../../app/mailers/NotificationDigestMailer'; describe('POST /v2/posts/:postId/leave', () => { let luna, mars, venus, jupiter; - beforeEach(async () => { + before(async () => { await cleanDB($pg_database); [luna, mars, venus, jupiter] = await createTestUsers(['luna', 'mars', 'venus', 'jupiter']); @@ -30,7 +30,10 @@ describe('POST /v2/posts/:postId/leave', () => { describe('Luna create direct with Mars and Venus', () => { let post; beforeEach(async () => { - post = await createAndReturnPostToFeed([mars.user, venus.user], luna, 'Hello'); + post = await justCreatePost(luna, 'Hello', [luna.username, mars.username, venus.username]); + }); + afterEach(async () => { + await post.destroy(); }); it('should allow Mars to leave direct', async () => { @@ -59,7 +62,10 @@ describe('POST /v2/posts/:postId/leave', () => { }); describe('Mars leaving direct', () => { - beforeEach(() => leave(post, mars)); + beforeEach(async () => { + await clearAllEvents(); + await leave(post, mars); + }); it('should not allow Mars to see post', async () => { const resp = await getPost(post, mars); @@ -166,7 +172,7 @@ describe('POST /v2/posts/:postId/leave', () => { before(async () => { const app = await getSingleton(); - port = process.env.PEPYATKA_SERVER_PORT || app.context.config.port; + ({ port } = app.context); const pubsubAdapter = new PubSubAdapter($database); PubSub.setPublisher(pubsubAdapter); }); @@ -237,6 +243,10 @@ async function getSerializedEvents(userId) { return serializeEvents(events, userId); } +async function clearAllEvents() { + await dbAdapter.database.raw(`delete from events`); +} + function stripHTML(str) { return str.replace(/<.+?>/g, ''); } diff --git a/test/functional/posts/posts.js b/test/functional/posts/posts.js index 848f87644..bcd0d9dfe 100644 --- a/test/functional/posts/posts.js +++ b/test/functional/posts/posts.js @@ -191,7 +191,7 @@ describe('PostsController', () => { beforeEach(async () => { [zeusCtx, post] = await Promise.all([ funcTestHelper.createUserAsync('zeus', 'password'), - funcTestHelper.createAndReturnPostToFeed(marsCtx, ctx, 'body'), + funcTestHelper.justCreatePost(ctx, 'body', [ctx.username, marsCtx.username]), ]); }); @@ -379,7 +379,7 @@ describe('PostsController', () => { beforeEach(async () => { const screenName = 'Pepyatka Developers'; - await funcTestHelper.createGroupAsync(ctx, groupName, screenName); + await funcTestHelper.justCreateGroup(ctx, groupName, screenName); const yole = await funcTestHelper.createUserAsync(otherUserName, 'pw'); otherUserAuthToken = yole.authToken; @@ -638,7 +638,7 @@ describe('PostsController', () => { [marsCtx, post] = await Promise.all([ funcTestHelper.createUserAsync('mars', 'password2'), - funcTestHelper.createAndReturnPost(context, 'Post body'), + funcTestHelper.justCreatePost(context, 'Post body'), ]); context.post = post; @@ -650,7 +650,7 @@ describe('PostsController', () => { beforeEach(async () => { const screenName = 'Pepyatka Developers'; - await funcTestHelper.createGroupAsync(context, groupName, screenName); + await funcTestHelper.justCreateGroup(context, groupName, screenName); }); it("should not update group's last activity", (done) => { @@ -752,7 +752,7 @@ describe('PostsController', () => { let postOfMars; beforeEach(async () => { - postOfMars = await funcTestHelper.createAndReturnPost(marsCtx, 'I am mars!'); + postOfMars = await funcTestHelper.justCreatePost(marsCtx, 'I am mars!'); await funcTestHelper.banUser(context, marsCtx); }); @@ -777,7 +777,7 @@ describe('PostsController', () => { const [marsCtx, post] = await Promise.all([ funcTestHelper.createUserAsync('mars', 'password2'), - funcTestHelper.createAndReturnPost(context, 'Post body'), + funcTestHelper.justCreatePost(context, 'Post body'), ]); context.post = post; @@ -850,7 +850,7 @@ describe('PostsController', () => { const [marsCtx, post] = await Promise.all([ funcTestHelper.createUserAsync('mars', 'password2'), - funcTestHelper.createAndReturnPost(context, 'Post body'), + funcTestHelper.justCreatePost(context, 'Post body'), ]); context.post = post; @@ -899,14 +899,14 @@ describe('PostsController', () => { beforeEach(async () => { context = await funcTestHelper.createUserAsync('Luna', 'password'); - const [marsCtx, response] = await Promise.all([ + const [marsCtx, post] = await Promise.all([ funcTestHelper.createUserAsync('mars', 'password2'), - funcTestHelper.createPostWithCommentsDisabled(context, 'Post body', true), + funcTestHelper.justCreatePost(context, 'Post body'), ]); - const data = await response.json(); + await post.setCommentsDisabled('1'); - context.post = data.posts; + context.post = post; otherUserAuthToken = marsCtx.authToken; }); @@ -954,7 +954,7 @@ describe('PostsController', () => { const [yoleCtx, post] = await Promise.all([ funcTestHelper.createUserAsync('yole', 'pw'), - funcTestHelper.createAndReturnPost(context, 'Post body'), + funcTestHelper.justCreatePost(context, 'Post body'), ]); context.post = post; @@ -1068,8 +1068,8 @@ describe('PostsController', () => { [luna, mars, yole] = await funcTestHelper.createTestUsers(3); await funcTestHelper.mutualSubscriptions([luna, mars]); await funcTestHelper.mutualSubscriptions([luna, yole]); - celestials = await funcTestHelper.createGroupAsync(luna, 'celestials'); - evilmartians = await funcTestHelper.createGroupAsync(mars, 'evilmartians'); + celestials = await funcTestHelper.justCreateGroup(luna, 'celestials'); + evilmartians = await funcTestHelper.justCreateGroup(mars, 'evilmartians'); }); const updatePost = async (postObj, userContext, parameters) => { @@ -1100,7 +1100,7 @@ describe('PostsController', () => { describe('Luna creates post in their feed', () => { beforeEach(async () => { - post = await funcTestHelper.createAndReturnPostToFeed([luna], luna, 'Post body'); + post = await funcTestHelper.justCreatePost(luna, 'Post body'); }); it('should be able to change destinations of regular post', async () => { @@ -1131,7 +1131,10 @@ describe('PostsController', () => { describe('Luna creates direct post', () => { beforeEach(async () => { - post = await funcTestHelper.createAndReturnPostToFeed([mars], luna, 'Post body'); + post = await funcTestHelper.justCreatePost(luna, 'Post body', [ + mars.username, + luna.username, + ]); }); it('should be able to add recipient to direct post', async () => { @@ -1146,7 +1149,11 @@ describe('PostsController', () => { describe('Luna creates direct post with two recipients', () => { beforeEach(async () => { - post = await funcTestHelper.createAndReturnPostToFeed([mars, yole], luna, 'Post body'); + post = await funcTestHelper.justCreatePost(luna, 'Post body', [ + mars.username, + yole.username, + luna.username, + ]); }); it('should not be able to remove recipient from direct post', async () => { @@ -1169,7 +1176,7 @@ describe('PostsController', () => { beforeEach(async () => { context = await funcTestHelper.createUserAsync('Luna', 'password'); - context.post = await funcTestHelper.createAndReturnPost(context, 'Post body'); + context.post = await funcTestHelper.justCreatePost(context, 'Post body'); }); it('should show a post', (done) => { @@ -1244,7 +1251,7 @@ describe('PostsController', () => { beforeEach(async () => { context = await funcTestHelper.createUserAsync('Luna', 'password'); - context.post = await funcTestHelper.createAndReturnPost(context, 'Post body'); + context.post = await funcTestHelper.justCreatePost(context, 'Post body'); }); it('should hide and unhide post', (done) => { @@ -1300,7 +1307,7 @@ describe('PostsController', () => { const [yoleCtx, post] = await Promise.all([ funcTestHelper.createUserAsync('yole', 'pw'), - funcTestHelper.createAndReturnPost(context, 'Post body'), + funcTestHelper.justCreatePost(context, 'Post body'), ]); context.post = post; diff --git a/test/functional/posts/postsV2.js b/test/functional/posts/postsV2.js index 4f91ce254..45269b88f 100644 --- a/test/functional/posts/postsV2.js +++ b/test/functional/posts/postsV2.js @@ -9,7 +9,6 @@ import { PubSub } from '../../../app/models'; import { createUserAsync, createAndReturnPost, - createCommentAsync, like, goPrivate, goProtected, @@ -27,6 +26,8 @@ import { acceptRequestToSubscribe, banUser, createTestUser, + justCreatePost, + justCreateComment, } from '../functional_test_helper'; import { postsByIdsResponse } from '../schemaV2-helper'; @@ -46,21 +47,21 @@ describe('TimelinesControllerV2', () => { let luna, mars, venus; let lunaPost; beforeEach(async () => { - [luna, mars, venus] = await Promise.all([ - createUserAsync('luna', 'pw'), - createUserAsync('mars', 'pw'), - createUserAsync('venus', 'pw'), - ]); - lunaPost = await createAndReturnPost(luna, 'Luna post'); + [luna, mars, venus] = await createTestUsers(['luna', 'mars', 'venus']); + lunaPost = await justCreatePost(luna, 'Luna post'); await mutualSubscriptions([luna, mars]); }); describe('Comments folding test', () => { const expectFolding = async (nComments, expComments, expOmitted, allComments = false) => { + const promises = []; + for (let n = 0; n < nComments; n++) { - await createCommentAsync(luna, lunaPost.id, `Comment ${n + 1}`); // eslint-disable-line no-await-in-loop + promises.push(justCreateComment(luna, lunaPost.id, `Comment ${n + 1}`)); } + await Promise.all(promises); + const post = await fetchPost(lunaPost.id, null, { allComments }); expect(post.posts.comments, 'to have length', expComments); expect(post.posts.omittedComments, 'to equal', expOmitted); @@ -217,8 +218,10 @@ describe('TimelinesControllerV2', () => { let lunaPostWithSpecialCharacters, lunaPostWithNewLines; beforeEach(async () => { - lunaPostWithSpecialCharacters = await createAndReturnPost(luna, 'Test with tags
'); - lunaPostWithNewLines = await createAndReturnPost(luna, 'A\nB\nC'); + [lunaPostWithSpecialCharacters, lunaPostWithNewLines] = await Promise.all([ + justCreatePost(luna, 'Test with tags
'), + justCreatePost(luna, 'A\nB\nC'), + ]); }); describe('Luna is a public user', () => { @@ -230,7 +233,8 @@ describe('TimelinesControllerV2', () => { }); it('should return information for a public post by its short id', async () => { - const response = await fetchPostOpenGraph(lunaPost.shortId); + const shortId = await lunaPost.getShortId(); + const response = await fetchPostOpenGraph(shortId); response.should.include('og:title'); response.should.include('luna'); response.should.include(''); @@ -273,7 +277,7 @@ describe('TimelinesControllerV2', () => { let attId1, attId2, attId3; beforeEach(async () => { luna = await createUserAsync('luna', 'pw'); - luna.post = await createAndReturnPost(luna, 'Luna post'); + luna.post = await justCreatePost(luna, 'Luna post'); attId1 = (await createMockAttachmentAsync(luna)).id; attId2 = (await createMockAttachmentAsync(luna)).id; attId3 = (await createMockAttachmentAsync(luna)).id; @@ -340,7 +344,7 @@ describe('TimelinesControllerV2', () => { let post1, post2; beforeEach(async () => { post1 = luna.post; - post2 = await createAndReturnPost(luna, 'Luna post 2'); + post2 = await justCreatePost(luna, 'Luna post 2'); }); it('should not allow to rebind attachment from post1 to post2', async () => { @@ -356,7 +360,7 @@ describe('TimelinesControllerV2', () => { let mars; beforeEach(async () => { mars = await createUserAsync('mars', 'pw'); - mars.post = await createAndReturnPost(mars, 'Mars post'); + mars.post = await justCreatePost(mars, 'Mars post'); }); it('should not allow Mars to steal Luna attachments', async () => { @@ -374,7 +378,7 @@ describe('TimelinesControllerV2', () => { let luna; beforeEach(async () => { luna = await createUserAsync('luna', 'pw'); - luna.post = await createAndReturnPost(luna, 'Luna post'); + luna.post = await justCreatePost(luna, 'Luna post'); await hidePost(luna.post.id, luna); }); @@ -388,7 +392,7 @@ describe('TimelinesControllerV2', () => { let luna; beforeEach(async () => { luna = await createUserAsync('luna', 'pw'); - luna.post = await createAndReturnPost(luna, 'Luna post'); + luna.post = await justCreatePost(luna, 'Luna post'); await savePost(luna.post.id, luna); }); @@ -419,7 +423,7 @@ describe('TimelinesControllerV2', () => { for (let n = 0; n < nPosts; n++) { // eslint-disable-next-line no-await-in-loop - posts.push(await createAndReturnPost(n % 2 == 0 ? luna : mars, 'post')); + posts.push(await justCreatePost(n % 2 == 0 ? luna : mars, 'post')); } }); diff --git a/test/functional/private_groups.js b/test/functional/private_groups.js index 91a25f68a..028c0ccc3 100644 --- a/test/functional/private_groups.js +++ b/test/functional/private_groups.js @@ -23,7 +23,7 @@ describe('PrivateGroups', () => { let context = {}; beforeEach(async () => { - context = await funcTestHelper.createUserAsync('Luna', 'password'); + context = await funcTestHelper.createTestUser('luna'); }); it('should create a public not-restricted group by default', (done) => { @@ -151,15 +151,12 @@ describe('PrivateGroups', () => { let group = {}; beforeEach(async () => { - [adminContext, nonAdminContext] = await Promise.all([ - funcTestHelper.createUserAsync('Luna', 'password'), - funcTestHelper.createUserAsync('yole', 'wordpass'), - ]); - group = await funcTestHelper.createGroupAsync( + [adminContext, nonAdminContext] = await funcTestHelper.createTestUsers(['Luna', 'yole']); + group = await funcTestHelper.justCreateGroup( adminContext, 'pepyatka-dev', 'Pepyatka Developers', - true, + { private: true }, ); }); @@ -177,22 +174,14 @@ describe('PrivateGroups', () => { }); describe('#update', () => { - const context = {}; + let context; let group; - beforeEach(funcTestHelper.createUserCtx(context, 'Luna', 'password')); - - beforeEach((done) => { - request - .post(`${app.context.config.host}/v1/groups`) - .send({ - group: { username: 'pepyatka-dev', screenName: 'Pepyatka Developers', isPrivate: '1' }, - authToken: context.authToken, - }) - .end((err, res) => { - group = res.body.groups; - done(); - }); + beforeEach(async () => { + context = await funcTestHelper.createTestUser('luna'); + group = await funcTestHelper.justCreateGroup(context, 'pepyatka-dev', 'pepyatka-dev', { + isPrivate: true, + }); }); it('should update private group settings', (done) => { @@ -296,22 +285,13 @@ describe('PrivateGroups', () => { }); describe('#unadmin', () => { - const adminContext = {}; - const nonAdminContext = {}; - - beforeEach(funcTestHelper.createUserCtx(adminContext, 'Luna', 'password')); - beforeEach(funcTestHelper.createUserCtx(nonAdminContext, 'yole', 'wordpass')); + let adminContext; - beforeEach((done) => { - request - .post(`${app.context.config.host}/v1/groups`) - .send({ - group: { username: 'pepyatka-dev', screenName: 'Pepyatka Developers', isPrivate: '1' }, - authToken: adminContext.authToken, - }) - .end(() => { - done(); - }); + beforeEach(async () => { + [adminContext] = await funcTestHelper.createTestUsers(['luna', 'yole']); + await funcTestHelper.justCreateGroup(adminContext, 'pepyatka-dev', 'pepyatka-dev', { + isPrivate: true, + }); }); beforeEach((done) => { @@ -340,18 +320,10 @@ describe('PrivateGroups', () => { let group; beforeEach(async () => { - [adminContext, nonAdminContext] = await Promise.all([ - funcTestHelper.createUserAsync('Luna', 'password'), - funcTestHelper.createUserAsync('yole', 'wordpass'), - ]); - - const response = await funcTestHelper.createGroupAsync( - adminContext, - 'pepyatka-dev', - 'Pepyatka Developers', - true, - ); - ({ group } = response); + [adminContext, nonAdminContext] = await funcTestHelper.createTestUsers(['Luna', 'yole']); + group = await funcTestHelper.justCreateGroup(adminContext, 'pepyatka-dev', 'pepyatka-dev', { + isPrivate: true, + }); }); it('should reject unauthenticated users', (done) => { @@ -464,19 +436,9 @@ describe('PrivateGroups', () => { let group; beforeEach(async () => { - [adminContext, secondAdminContext, nonAdminContext, groupMemberContext] = await Promise.all([ - funcTestHelper.createUserAsync('Luna', 'password'), - funcTestHelper.createUserAsync('Neptune', 'password'), - funcTestHelper.createUserAsync('yole', 'wordpass'), - funcTestHelper.createUserAsync('Pluto', 'wordpass'), - ]); - - const response = await funcTestHelper.createGroupAsync( - adminContext, - 'pepyatka-dev', - 'Pepyatka Developers', - ); - ({ group } = response); + [adminContext, secondAdminContext, nonAdminContext, groupMemberContext] = + await funcTestHelper.createTestUsers(['Luna', 'Neptune', 'yole', 'Pluto']); + group = await funcTestHelper.justCreateGroup(adminContext, 'pepyatka-dev'); await Promise.all([ funcTestHelper.subscribeToAsync(secondAdminContext, group), @@ -486,7 +448,7 @@ describe('PrivateGroups', () => { await funcTestHelper.promoteToAdmin(group, adminContext, secondAdminContext); await funcTestHelper.groupToPrivate(group, adminContext); - await funcTestHelper.createAndReturnPostToFeed(group, adminContext, 'Post body'); + await funcTestHelper.justCreatePost(adminContext, 'Post body', [group.username]); await funcTestHelper.sendRequestToJoinGroup(nonAdminContext, group); }); @@ -1077,24 +1039,19 @@ describe('PrivateGroups', () => { let group; beforeEach(async () => { - [adminContext, marsContext, plutoContext] = await Promise.all([ - funcTestHelper.createUserAsync('Luna', 'password'), - funcTestHelper.createUserAsync('Mars', 'wordpass'), - funcTestHelper.createUserAsync('Pluto', 'wordpass'), + [adminContext, marsContext, plutoContext] = await funcTestHelper.createTestUsers([ + 'Luna', + 'Mars', + 'Pluto', ]); - const response = await funcTestHelper.createGroupAsync( - adminContext, - 'pepyatka-dev', - 'Pepyatka Developers', - ); - ({ group } = response); + group = await funcTestHelper.justCreateGroup(adminContext, 'pepyatka-dev'); await funcTestHelper.subscribeToAsync(plutoContext, group); await funcTestHelper.groupToPrivate(group, adminContext); - await funcTestHelper.createAndReturnPostToFeed(group, adminContext, 'Post body'); + await funcTestHelper.justCreatePost(adminContext, 'Post body', [group.username]); }); it('anonymous users should have no access to private group subscribers', async () => { @@ -1125,34 +1082,25 @@ describe('PrivateGroups', () => { let nonMemberContext = {}; beforeEach(async () => { - [adminContext, nonAdminContext, nonMemberContext] = await Promise.all([ - funcTestHelper.createUserAsync('Luna', 'password'), - funcTestHelper.createUserAsync('yole', 'wordpass'), - funcTestHelper.createUserAsync('Pluto', 'wordpass'), + [adminContext, nonAdminContext, nonMemberContext] = await funcTestHelper.createTestUsers([ + 'Luna', + 'yole', + 'Pluto', ]); const [group1, group2, group3] = await Promise.all([ - funcTestHelper.createGroupAsync( - adminContext, - 'pepyatka-dev', - 'Pepyatka Developers', - true, - true, - ), - funcTestHelper.createGroupAsync( - adminContext, - 'pepyatka-dev-2', - 'Pepyatka Developers 2', - true, - false, - ), - funcTestHelper.createGroupAsync( - adminContext, - 'pepyatka-dev-3', - 'Pepyatka Developers 3', - false, - true, - ), + funcTestHelper.justCreateGroup(adminContext, 'pepyatka-dev', 'Pepyatka Developers', { + isPrivate: true, + isRestricted: true, + }), + funcTestHelper.justCreateGroup(adminContext, 'pepyatka-dev-2', 'Pepyatka Developers 2', { + isPrivate: true, + isRestricted: false, + }), + funcTestHelper.justCreateGroup(adminContext, 'pepyatka-dev-3', 'Pepyatka Developers 3', { + isPrivate: false, + isRestricted: true, + }), ]); await Promise.all([ diff --git a/test/functional/privates.js b/test/functional/privates.js index 63219fc4b..4f38ef8af 100644 --- a/test/functional/privates.js +++ b/test/functional/privates.js @@ -35,15 +35,15 @@ describe('Privates', () => { }); describe('publish private post to public feed', () => { - const group = 'group'; + let group; beforeEach(async () => { - await Promise.all([ + [, group] = await Promise.all([ funcTestHelper.mutualSubscriptions([marsContext, lunaContext]), - funcTestHelper.createGroupAsync(lunaContext, group), + funcTestHelper.createGroupAsync(lunaContext, 'group'), ]); - await funcTestHelper.subscribeToAsync(zeusContext, { username: group }); + await funcTestHelper.subscribeToAsync(zeusContext, group); }); it('should send private post to public feed', (done) => { @@ -52,7 +52,7 @@ describe('Privates', () => { .post(`${app.context.config.host}/v1/posts`) .send({ post: { body: post }, - meta: { feeds: [group, lunaContext.user.username] }, + meta: { feeds: [group.username, lunaContext.user.username] }, authToken: lunaContext.authToken, }) .end(() => { @@ -1155,13 +1155,16 @@ describe('Privates', () => { }); describe('Checking, that private posts are correctly propagated', () => { - const lunaContext = {}; - const marsContext = {}; - const zeusContext = {}; + let lunaContext, marsContext, zeusContext; + + beforeEach(async () => { + [lunaContext, marsContext, zeusContext] = await funcTestHelper.createTestUsers([ + 'luna', + 'mars', + 'zeus', + ]); + }); - beforeEach(funcTestHelper.createUserCtx(lunaContext, 'luna', 'pw')); - beforeEach(funcTestHelper.createUserCtx(marsContext, 'mars', 'pw')); - beforeEach(funcTestHelper.createUserCtx(zeusContext, 'zeus', 'pw')); beforeEach(() => funcTestHelper.mutualSubscriptions([lunaContext, marsContext, zeusContext])); beforeEach(() => funcTestHelper.goPrivate(lunaContext)); diff --git a/test/functional/realtime-session.js b/test/functional/realtime-session.js index 821074807..09a848cd7 100644 --- a/test/functional/realtime-session.js +++ b/test/functional/realtime-session.js @@ -1,11 +1,10 @@ import socketIO from 'socket.io-client'; import socketIOModern from 'socket.io-client-modern'; +import config from 'config'; import { API_VERSION_ACTUAL } from '../../app/api-versions'; -const eventTimeout = 2000; -const silenceTimeout = 500; - +const { eventTimeout, silenceTimeout } = config.tests.realtime; /** * Session is a helper class * for the realtime testing diff --git a/test/functional/realtime_assertions.js b/test/functional/realtime_assertions.js index 24237192d..e010b1bb0 100644 --- a/test/functional/realtime_assertions.js +++ b/test/functional/realtime_assertions.js @@ -1,12 +1,12 @@ import socketIO from 'socket.io-client'; +import config from 'config'; import { API_VERSION_ACTUAL } from '../../app/api-versions'; import { getSingleton as initApp } from '../../app/app'; import * as funcTestHelper from './functional_test_helper'; -const eventTimeout = 2000; -const silenceTimeout = 600; +const { eventTimeout, silenceTimeout } = config.tests.realtime; class Session { socket = null; diff --git a/test/functional/timelines-rss.js b/test/functional/timelines-rss.js index d01b2eabd..0640ec07e 100644 --- a/test/functional/timelines-rss.js +++ b/test/functional/timelines-rss.js @@ -233,7 +233,7 @@ describe('TimelinesAsRSS', () => { createUserAsync('mars', 'pw'), ]); celestials = await createGroupAsync(luna, 'celestials', 'Celestials'); - await subscribeToAsync(mars, { username: 'celestials' }); + await subscribeToAsync(mars, celestials); post1 = await createAndReturnPostToFeed(celestials, luna, 'Luna post'); post2 = await createAndReturnPostToFeed(celestials, mars, 'Mars post'); }); diff --git a/test/functional/timelinesV2.js b/test/functional/timelinesV2.js index 8a3e81d90..8dbde83ab 100644 --- a/test/functional/timelinesV2.js +++ b/test/functional/timelinesV2.js @@ -33,6 +33,8 @@ import { savePost, createTestUsers, unsavePost, + justCreatePost, + justCreateComment, } from './functional_test_helper'; describe('TimelinesControllerV2', () => { @@ -311,23 +313,15 @@ describe('TimelinesControllerV2', () => { }); describe('Luna subscribed to Selenites group and not subscribed to Celestials group', () => { - let selenitesPost, celestialsPost; + let selenitesPost, celestialsPost, celestials; beforeEach(async () => { - await createGroupAsync(venus, 'selenites'); - await createGroupAsync(venus, 'celestials'); - await subscribeToAsync(luna, { username: 'selenites' }); + const selenites = await createGroupAsync(venus, 'selenites'); + celestials = await createGroupAsync(venus, 'celestials'); + await subscribeToAsync(luna, selenites); - selenitesPost = await createAndReturnPostToFeed( - { username: 'selenites' }, - venus, - 'Post', - ); - celestialsPost = await createAndReturnPostToFeed( - { username: 'celestials' }, - venus, - 'Post', - ); + selenitesPost = await justCreatePost(venus, 'Post', ['selenites']); + celestialsPost = await justCreatePost(venus, 'Post', ['celestials']); }); it('should return timeline without posts from Celestials group', async () => { @@ -348,7 +342,7 @@ describe('TimelinesControllerV2', () => { }); it('should return timeline with Mars posts from Celestials group in "friends-all-activity" mode', async () => { - await subscribeToAsync(mars, { username: 'celestials' }); + await subscribeToAsync(mars, celestials); const marsCelestialsPost = await createAndReturnPostToFeed( { username: 'celestials' }, mars, @@ -367,9 +361,9 @@ describe('TimelinesControllerV2', () => { beforeEach(async () => { mars = await createUserAsync('mars', 'pw'); venus = await createUserAsync('venus', 'pw'); - await createGroupAsync(venus, 'selenites'); - await subscribeToAsync(luna, { username: 'selenites' }); - await subscribeToAsync(mars, { username: 'selenites' }); + const selenites = await createGroupAsync(venus, 'selenites'); + await subscribeToAsync(luna, selenites); + await subscribeToAsync(mars, selenites); await banUser(mars, luna); }); @@ -404,10 +398,10 @@ describe('TimelinesControllerV2', () => { beforeEach(async () => { luna = await createUserAsync('luna', 'pw'); mars = await createUserAsync('mars', 'pw'); - marsPostLikedByLuna = await createAndReturnPost(mars, 'Mars post 1'); - marsPostCommentedByLuna = await createAndReturnPost(mars, 'Mars post 2'); - lunaPost = await createAndReturnPost(luna, 'Luna post'); - await createCommentAsync(luna, marsPostCommentedByLuna.id, 'Comment'); + marsPostLikedByLuna = await justCreatePost(mars, 'Mars post 1'); + marsPostCommentedByLuna = await justCreatePost(mars, 'Mars post 2'); + lunaPost = await justCreatePost(luna, 'Luna post'); + await justCreateComment(luna, marsPostCommentedByLuna.id, 'Comment'); await like(marsPostLikedByLuna.id, luna.authToken); }); @@ -461,8 +455,8 @@ describe('TimelinesControllerV2', () => { luna = await createUserAsync('luna', 'pw'); mars = await createUserAsync('mars', 'pw'); await mutualSubscriptions([luna, mars]); - postLunaToMars = await createAndReturnPostToFeed({ username: 'mars' }, luna, 'Post'); - postMarsToLuna = await createAndReturnPostToFeed({ username: 'luna' }, mars, 'Post'); + postLunaToMars = await justCreatePost(luna, 'Post', ['luna', 'mars']); + postMarsToLuna = await justCreatePost(mars, 'Post', ['luna', 'mars']); }); it('should return timeline with directs from Luna and to Luna', async () => { @@ -496,10 +490,10 @@ describe('TimelinesControllerV2', () => { createUserAsync('venus', 'pw'), ]); await subscribeToAsync(venus, mars); - postCreatedByMars = await createAndReturnPost(mars, 'Post'); - postCommentedByMars = await createAndReturnPost(venus, 'Post'); - postLikedByMars = await createAndReturnPost(venus, 'Post'); - await createCommentAsync(mars, postCommentedByMars.id, 'Comment'); + postCreatedByMars = await justCreatePost(mars, 'Post'); + postCommentedByMars = await justCreatePost(venus, 'Post'); + postLikedByMars = await justCreatePost(venus, 'Post'); + await justCreateComment(mars, postCommentedByMars.id, 'Comment'); await like(postLikedByMars.id, mars.authToken); await hidePost(postCreatedByMars.id, luna); }); @@ -606,8 +600,8 @@ describe('TimelinesControllerV2', () => { let post1, post2; beforeEach(async () => { luna = await createUserAsync('luna', 'pw'); - post1 = await createAndReturnPost(luna, 'Post'); - post2 = await createAndReturnPost(luna, 'Post'); + post1 = await justCreatePost(luna, 'Post'); + post2 = await justCreatePost(luna, 'Post'); }); it('should return uncommented Luna posts in creation order', async () => { @@ -631,7 +625,7 @@ describe('TimelinesControllerV2', () => { beforeEach(async () => { luna = await createUserAsync('luna', 'pw'); // Luna creates 10 posts - await Promise.all([...new Array(10)].map(() => createAndReturnPost(luna, 'Post'))); + await Promise.all([...new Array(10)].map(() => justCreatePost(luna, 'Post'))); }); it('should return first page with isLastPage = false', async () => { @@ -655,9 +649,9 @@ describe('TimelinesControllerV2', () => { let post1, post2, post3; beforeEach(async () => { luna = await createUserAsync('luna', 'pw'); - post1 = await createAndReturnPost(luna, 'Post'); - post2 = await createAndReturnPost(luna, 'Post'); - post3 = await createAndReturnPost(luna, 'Post'); + post1 = await justCreatePost(luna, 'Post'); + post2 = await justCreatePost(luna, 'Post'); + post3 = await justCreatePost(luna, 'Post'); await dbAdapter .database('posts') .where('uid', post1.id) @@ -700,8 +694,8 @@ describe('TimelinesControllerV2', () => { let post1, post2; beforeEach(async () => { [luna, mars] = await createTestUsers(2); - post1 = await createAndReturnPost(luna, 'Post'); - post2 = await createAndReturnPost(mars, 'Post'); + post1 = await justCreatePost(luna, 'Post'); + post2 = await justCreatePost(mars, 'Post'); }); it('should not return Saves timeline to anonymous', async () => { diff --git a/test/unit/support/rss-text-parser.ts b/test/unit/support/rss-text-parser.ts index 464393e6a..429c02968 100644 --- a/test/unit/support/rss-text-parser.ts +++ b/test/unit/support/rss-text-parser.ts @@ -1,4 +1,5 @@ /* eslint-env node, mocha */ +import config from 'config'; import expect from 'unexpected'; import { extractTitle, textToHTML } from '../../../app/support/rss-text-parser'; @@ -50,10 +51,10 @@ describe('textToHTML function', () => { In the forests of the night,
What immortal.com hand or eye Dare frame thy fearful #symmetry?`; - const expected = `

Tiger, @tiger, burning bright
+ const expected = `

Tiger, @tiger, burning bright
In the forests of the night,<br>
What immortal.com hand or eye
-Dare frame thy fearful #symmetry?

`; +Dare frame thy fearful #symmetry?

`; expect(textToHTML(input), 'to be', expected); }); }); diff --git a/yarn.lock b/yarn.lock index 528a49b1f..dcfe908ba 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2424,6 +2424,13 @@ __metadata: languageName: node linkType: hard +"@types/minimist@npm:^1": + version: 1.2.5 + resolution: "@types/minimist@npm:1.2.5" + checksum: 3f791258d8e99a1d7d0ca2bda1ca6ea5a94e5e7b8fc6cde84dd79b0552da6fb68ade750f0e17718f6587783c24254bbca0357648dd59dc3812c150305cabdc46 + languageName: node + linkType: hard + "@types/mocha@npm:~10.0.6": version: 10.0.6 resolution: "@types/mocha@npm:10.0.6" @@ -4231,18 +4238,6 @@ __metadata: languageName: node linkType: hard -"cross-env@npm:~7.0.3": - version: 7.0.3 - resolution: "cross-env@npm:7.0.3" - dependencies: - cross-spawn: "npm:^7.0.1" - bin: - cross-env: src/bin/cross-env.js - cross-env-shell: src/bin/cross-env-shell.js - checksum: f3765c25746c69fcca369655c442c6c886e54ccf3ab8c16847d5ad0e91e2f337d36eedc6599c1227904bf2a228d721e690324446876115bc8e7b32a866735ecf - languageName: node - linkType: hard - "cross-spawn@npm:^4.0.0": version: 4.0.2 resolution: "cross-spawn@npm:4.0.2" @@ -4277,7 +4272,7 @@ __metadata: languageName: node linkType: hard -"cross-spawn@npm:^7.0.0, cross-spawn@npm:^7.0.1, cross-spawn@npm:^7.0.2, cross-spawn@npm:^7.0.3": +"cross-spawn@npm:^7.0.0, cross-spawn@npm:^7.0.2, cross-spawn@npm:^7.0.3": version: 7.0.3 resolution: "cross-spawn@npm:7.0.3" dependencies: @@ -6178,6 +6173,7 @@ __metadata: "@types/koa-static": "npm:~4.0.4" "@types/koa__router": "npm:~12.0.4" "@types/lodash": "npm:~4.17.0" + "@types/minimist": "npm:^1" "@types/mocha": "npm:~10.0.6" "@types/n3": "npm:~1.16.4" "@types/node": "npm:~18.19.31" @@ -6205,7 +6201,6 @@ __metadata: commander: "npm:~11.1.0" config: "npm:~3.3.11" console-stamp: "npm:~3.1.2" - cross-env: "npm:~7.0.3" debug: "npm:~4.3.4" ejs: "npm:~3.1.10" ejs-lint: "npm:~2.0.0" @@ -6246,6 +6241,7 @@ __metadata: mailparser: "npm:~3.7.0" media-type: "npm:~0.3.1" mime-types: "npm:~2.1.35" + minimist: "npm:~1.2.8" mkdirp: "npm:~3.0.1" mmmagic: "npm:~0.5.3" mocha: "npm:~10.4.0" @@ -8743,7 +8739,7 @@ __metadata: languageName: node linkType: hard -"minimist@npm:^1.1.0, minimist@npm:^1.1.3, minimist@npm:^1.2.0, minimist@npm:^1.2.6": +"minimist@npm:^1.1.0, minimist@npm:^1.1.3, minimist@npm:^1.2.0, minimist@npm:^1.2.6, minimist@npm:~1.2.8": version: 1.2.8 resolution: "minimist@npm:1.2.8" checksum: 19d3fcdca050087b84c2029841a093691a91259a47def2f18222f41e7645a0b7c44ef4b40e88a1e58a40c84d2ef0ee6047c55594d298146d0eb3f6b737c20ce6