Skip to content

Commit

Permalink
chore: reset cognito after each test
Browse files Browse the repository at this point in the history
  • Loading branch information
solufa committed Dec 30, 2024
1 parent c1b6d98 commit e5a2980
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 13 deletions.
2 changes: 1 addition & 1 deletion compose.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
services:
magnito:
image: frourio/magnito:0.19.0
image: frourio/magnito:0.20.0
ports:
- 5050:5050
- 5051:5051
Expand Down
6 changes: 3 additions & 3 deletions server/tests/api/apiClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import {
COGNITO_USER_POOL_ID,
} from 'service/envValues';
import { ulid } from 'ulid';
import { TEST_PORT } from './utils';
import { TEST_PORT, TEST_USERNAME_PREFIX } from './utils';

const baseURL = `http://127.0.0.1:${TEST_PORT}${API_BASE_PATH}`;

Expand All @@ -27,7 +27,7 @@ export const noCookieClient = api(
type Tokens = { idToken: string; accessToken: string };

export const createCognitoUser = async (): Promise<Tokens> => {
const userName = `test-${ulid()}`;
const userName = `${TEST_USERNAME_PREFIX}-${ulid()}`;
const password = `Test-user-${ulid()}`;
const command1 = new AdminCreateUserCommand({
UserPoolId: COGNITO_USER_POOL_ID,
Expand Down Expand Up @@ -56,7 +56,7 @@ export const createCognitoUser = async (): Promise<Tokens> => {
};

export const createGoogleUser = async (): Promise<Tokens> => {
const userName = `test-${ulid()}`;
const userName = `${TEST_USERNAME_PREFIX}-${ulid()}`;
const codeVerifier = ulid();
const user = await fetch(`${COGNITO_POOL_ENDPOINT}/public/socialUsers`, {
method: 'POST',
Expand Down
2 changes: 2 additions & 0 deletions server/tests/api/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import { SERVER_PORT } from 'service/envValues';

export const TEST_PORT = SERVER_PORT - 1;

export const TEST_USERNAME_PREFIX = 'test-username-prefix';

export const GET = (api: { get: unknown; $path: () => string }): string => `GET: ${api.$path()}`;

export const POST = (api: { post: unknown; $path: () => string }): string => `POST: ${api.$path()}`;
Expand Down
51 changes: 42 additions & 9 deletions server/tests/setup.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
import {
AdminDeleteUserCommand,
ListUsersCommand,
} from '@aws-sdk/client-cognito-identity-provider';
import { DeleteObjectsCommand, ListObjectsV2Command } from '@aws-sdk/client-s3';
import { exec } from 'child_process';
import type { FastifyInstance } from 'fastify';
import { init } from 'service/app';
import { S3_BUCKET } from 'service/envValues';
import { cognitoClient } from 'service/cognito';
import { COGNITO_USER_POOL_ID, S3_BUCKET } from 'service/envValues';
import { prismaClient } from 'service/prismaClient';
import { s3Client } from 'service/s3Client';
import util from 'util';
import { afterAll, afterEach, beforeAll, beforeEach } from 'vitest';
import { TEST_PORT } from './api/utils';
import { TEST_PORT, TEST_USERNAME_PREFIX } from './api/utils';

let server: FastifyInstance;

Expand All @@ -27,21 +32,49 @@ beforeEach(async (info) => {
await util.promisify(exec)('npx prisma migrate reset --force');
});

const resetS3 = async (): Promise<void> => {
const objects = await s3Client.send(new ListObjectsV2Command({ Bucket: S3_BUCKET }));
const keys = objects.Contents?.map(({ Key }) => ({ Key })) ?? [];

if (keys.length === 0) return;

await s3Client.send(new DeleteObjectsCommand({ Bucket: S3_BUCKET, Delete: { Objects: keys } }));
};

const resetCognito = async (): Promise<void> => {
const { Users } = await cognitoClient.send(
new ListUsersCommand({ UserPoolId: COGNITO_USER_POOL_ID }),
);

if (!Users) return;

const testUsers = Users.filter((u) => u.Username?.startsWith(TEST_USERNAME_PREFIX));

for (let i = 0; ; i += 1) {
const targets = testUsers.slice(i * 10, (i + 1) * 10);

if (targets.length === 0) return;

await Promise.all(

Check failure on line 58 in server/tests/setup.ts

View workflow job for this annotation

GitHub Actions / Test

tests/api/private/di.test.ts > Dependency Injection

403: UnknownError ❯ throwDefaultError node_modules/@smithy/smithy-client/dist-cjs/index.js:836:20 ❯ node_modules/@smithy/smithy-client/dist-cjs/index.js:845:5 ❯ de_CommandError node_modules/@aws-sdk/client-cognito-identity-provider/dist-cjs/index.js:3911:14 ❯ node_modules/@smithy/middleware-serde/dist-cjs/index.js:35:20 ❯ node_modules/@smithy/core/dist-cjs/index.js:168:18 ❯ node_modules/@smithy/middleware-retry/dist-cjs/index.js:320:38 ❯ node_modules/@aws-sdk/middleware-logger/dist-cjs/index.js:34:22 ❯ resetCognito tests/setup.ts:58:5 ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯ Serialized Error: { '$fault': 'client', '$metadata': { httpStatusCode: 403, requestId: undefined, extendedRequestId: undefined, cfId: undefined, attempts: 1, totalRetryDelay: +0 }, '$response': { statusCode: 403, reason: 'Forbidden', headers: { vary: 'Origin', 'access-control-allow-credentials': 'true', 'content-type': 'application/json; charset=utf-8', 'content-length': '2', date: 'Mon, 30 Dec 2024 07:47:17 GMT', connection: 'keep-alive', 'keep-alive': 'timeout=72' }, body: { _events: { close: undefined, error: 'Function<anonymous>', data: undefined, end: 'Function<responseOnEnd>', readable: undefined }, _readableState: { highWaterMark: 16384, buffer: [], bufferIndex: +0, length: +0, pipes: [], awaitDrainWriters: null, constructor: 'Function<ReadableState>', objectMode: false, ended: true, endEmitted: true, reading: false, constructed: true, sync: true, needReadable: false, emittedReadable: false, readableListening: false, resumeScheduled: false, errorEmitted: false, emitClose: true, autoDestroy: true, destroyed: true, closed: true, closeEmitted: true, multiAwaitDrain: false, readingMore: true, dataEmitted: true, errored: null, defaultEncoding: 'utf8', decoder: null, encoding: null, flowing: false, pipesCount: +0, paused: true }, _maxListeners: undefined, socket: null, httpVersionMajor: 1, httpVersionMinor: 1, httpVersion: '1.1', complete: true, rawHeaders: [ 'vary', 'Origin', 'access-control-allow-credentials', 'true', 'content-type', 'application/json; charset=utf-8', 'content-length', '2', 'Date', 'Mon, 30 Dec 2024 07:47:17 GMT', 'Connection', 'keep-alive', 'Keep-Alive', 'timeout=72' ], rawTrailers: [], joinDuplicateHeaders: undefined, aborted: false, upgrade: false, url: '', method: null, statusCode: 403, statusMessage: 'Forbidden', client: { connecting: false, _hadError: false, _parent: null, _host: 'localhost', _closeAfterHandlingError: false, _events: { close: 'Function<onClose>', error: 'Function<bound onceWrapper>', prefinish: undefined, finish: undefined, drain: undefined, data: undefined, end: 'Function<onReadableStreamEnd>', readable: undefined, connect: undefined, free: 'Function<onFree>', timeout: 'Function<onTimeout>', agentRemove: 'Function<onRemove>' }, _readableState: { highWaterMark: 16384, buffer: [], bufferIndex: +0, length: +0, pipes: [], awaitDrainWriters: null, constructor: 'Function<ReadableState>', objectMode: false, ended: false, endEmitted: false, reading: true, constructed: true, sync: false, needReadable: true, emittedReadable: false, readableListening: false, resumeScheduled: false, errorEmitted: false, emitClose: false, autoDestroy: true, destroyed: false, closed: false, closeEmitted: false, multiAwaitDrain: false, readingMore: false, dataEmitted: true, errored: null, defaultEncoding: 'utf8', decoder: null, encoding: null, flowing: true, pipesCount: +0, paused: false }, _writableState: { highWaterMark: 16384, length: +0, corked: +0, onwrite: 'Function<bound onwrite>', writelen: +0, bufferedIndex: +0, pendingcb: +0, constructor: 'Function<WritableState>', objectMode: false, finalCalled: false, needDrain: false, ending: false, ended: false, finished: false, destroyed: false, decodeStrings: false, writing: false, sync: false, bufferProcessing: false, constructed: true, prefinished: false, errorEmitted: false, emitClose: false, autoDestroy: true, closed: false, closeEmitted: false, allBuffers: true, allNoop: true, errored: null, writable: undefined, defaultEncoding: 'utf8', writecb: 'Function<nop>', afterWriteTickInfo: nul

Check failure on line 58 in server/tests/setup.ts

View workflow job for this annotation

GitHub Actions / Test

tests/api/private/index.test.ts > GET: http://127.0.0.1:31576/api/private

403: UnknownError ❯ throwDefaultError node_modules/@smithy/smithy-client/dist-cjs/index.js:836:20 ❯ node_modules/@smithy/smithy-client/dist-cjs/index.js:845:5 ❯ de_CommandError node_modules/@aws-sdk/client-cognito-identity-provider/dist-cjs/index.js:3911:14 ❯ node_modules/@smithy/middleware-serde/dist-cjs/index.js:35:20 ❯ node_modules/@smithy/core/dist-cjs/index.js:168:18 ❯ node_modules/@smithy/middleware-retry/dist-cjs/index.js:320:38 ❯ node_modules/@aws-sdk/middleware-logger/dist-cjs/index.js:34:22 ❯ resetCognito tests/setup.ts:58:5 ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯ Serialized Error: { '$fault': 'client', '$metadata': { httpStatusCode: 403, requestId: undefined, extendedRequestId: undefined, cfId: undefined, attempts: 1, totalRetryDelay: +0 }, '$response': { statusCode: 403, reason: 'Forbidden', headers: { vary: 'Origin', 'access-control-allow-credentials': 'true', 'content-type': 'application/json; charset=utf-8', 'content-length': '2', date: 'Mon, 30 Dec 2024 07:47:14 GMT', connection: 'keep-alive', 'keep-alive': 'timeout=72' }, body: { _events: { close: undefined, error: 'Function<anonymous>', data: undefined, end: 'Function<responseOnEnd>', readable: undefined }, _readableState: { highWaterMark: 16384, buffer: [], bufferIndex: +0, length: +0, pipes: [], awaitDrainWriters: null, constructor: 'Function<ReadableState>', objectMode: false, ended: true, endEmitted: true, reading: false, constructed: true, sync: true, needReadable: false, emittedReadable: false, readableListening: false, resumeScheduled: false, errorEmitted: false, emitClose: true, autoDestroy: true, destroyed: true, closed: true, closeEmitted: true, multiAwaitDrain: false, readingMore: true, dataEmitted: true, errored: null, defaultEncoding: 'utf8', decoder: null, encoding: null, flowing: false, pipesCount: +0, paused: true }, _maxListeners: undefined, socket: null, httpVersionMajor: 1, httpVersionMinor: 1, httpVersion: '1.1', complete: true, rawHeaders: [ 'vary', 'Origin', 'access-control-allow-credentials', 'true', 'content-type', 'application/json; charset=utf-8', 'content-length', '2', 'Date', 'Mon, 30 Dec 2024 07:47:14 GMT', 'Connection', 'keep-alive', 'Keep-Alive', 'timeout=72' ], rawTrailers: [], joinDuplicateHeaders: undefined, aborted: false, upgrade: false, url: '', method: null, statusCode: 403, statusMessage: 'Forbidden', client: { connecting: false, _hadError: false, _parent: null, _host: 'localhost', _closeAfterHandlingError: false, _events: { close: 'Function<onClose>', error: 'Function<bound onceWrapper>', prefinish: undefined, finish: undefined, drain: undefined, data: undefined, end: 'Function<onReadableStreamEnd>', readable: undefined, connect: undefined, free: 'Function<onFree>', timeout: 'Function<onTimeout>', agentRemove: 'Function<onRemove>' }, _readableState: { highWaterMark: 16384, buffer: [], bufferIndex: +0, length: +0, pipes: [], awaitDrainWriters: null, constructor: 'Function<ReadableState>', objectMode: false, ended: false, endEmitted: false, reading: true, constructed: true, sync: false, needReadable: true, emittedReadable: false, readableListening: false, resumeScheduled: false, errorEmitted: false, emitClose: false, autoDestroy: true, destroyed: false, closed: false, closeEmitted: false, multiAwaitDrain: false, readingMore: false, dataEmitted: true, errored: null, defaultEncoding: 'utf8', decoder: null, encoding: null, flowing: true, pipesCount: +0, paused: false }, _writableState: { highWaterMark: 16384, length: +0, corked: +0, onwrite: 'Function<bound onwrite>', writelen: +0, bufferedIndex: +0, pendingcb: +0, constructor: 'Function<WritableState>', objectMode: false, finalCalled: false, needDrain: false, ending: false, ended: false, finished: false, destroyed: false, decodeStrings: false, writing: false, sync: false, bufferProcessing: false, constructed: true, prefinished: false, errorEmitted: false, emitClose: false, autoDestroy: true, closed: false, closeEmitted: false, allBuffers: true, allNoop: true, errored: null, writable: undefined, defaultEncoding: 'utf8', writecb: 'Function<nop>', afterWriteTickInfo: nul

Check failure on line 58 in server/tests/setup.ts

View workflow job for this annotation

GitHub Actions / Test

tests/api/private/index.test.ts > GET: http://127.0.0.1:31576/api/private/me

403: UnknownError ❯ throwDefaultError node_modules/@smithy/smithy-client/dist-cjs/index.js:836:20 ❯ node_modules/@smithy/smithy-client/dist-cjs/index.js:845:5 ❯ de_CommandError node_modules/@aws-sdk/client-cognito-identity-provider/dist-cjs/index.js:3911:14 ❯ node_modules/@smithy/middleware-serde/dist-cjs/index.js:35:20 ❯ node_modules/@smithy/core/dist-cjs/index.js:168:18 ❯ node_modules/@smithy/middleware-retry/dist-cjs/index.js:320:38 ❯ node_modules/@aws-sdk/middleware-logger/dist-cjs/index.js:34:22 ❯ resetCognito tests/setup.ts:58:5 ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯ Serialized Error: { '$fault': 'client', '$metadata': { httpStatusCode: 403, requestId: undefined, extendedRequestId: undefined, cfId: undefined, attempts: 1, totalRetryDelay: +0 }, '$response': { statusCode: 403, reason: 'Forbidden', headers: { vary: 'Origin', 'access-control-allow-credentials': 'true', 'content-type': 'application/json; charset=utf-8', 'content-length': '2', date: 'Mon, 30 Dec 2024 07:47:15 GMT', connection: 'keep-alive', 'keep-alive': 'timeout=72' }, body: { _events: { close: undefined, error: 'Function<anonymous>', data: undefined, end: 'Function<responseOnEnd>', readable: undefined }, _readableState: { highWaterMark: 16384, buffer: [], bufferIndex: +0, length: +0, pipes: [], awaitDrainWriters: null, constructor: 'Function<ReadableState>', objectMode: false, ended: true, endEmitted: true, reading: false, constructed: true, sync: true, needReadable: false, emittedReadable: false, readableListening: false, resumeScheduled: false, errorEmitted: false, emitClose: true, autoDestroy: true, destroyed: true, closed: true, closeEmitted: true, multiAwaitDrain: false, readingMore: true, dataEmitted: true, errored: null, defaultEncoding: 'utf8', decoder: null, encoding: null, flowing: false, pipesCount: +0, paused: true }, _maxListeners: undefined, socket: null, httpVersionMajor: 1, httpVersionMinor: 1, httpVersion: '1.1', complete: true, rawHeaders: [ 'vary', 'Origin', 'access-control-allow-credentials', 'true', 'content-type', 'application/json; charset=utf-8', 'content-length', '2', 'Date', 'Mon, 30 Dec 2024 07:47:15 GMT', 'Connection', 'keep-alive', 'Keep-Alive', 'timeout=72' ], rawTrailers: [], joinDuplicateHeaders: undefined, aborted: false, upgrade: false, url: '', method: null, statusCode: 403, statusMessage: 'Forbidden', client: { connecting: false, _hadError: false, _parent: null, _host: 'localhost', _closeAfterHandlingError: false, _events: { close: 'Function<onClose>', error: 'Function<bound onceWrapper>', prefinish: undefined, finish: undefined, drain: undefined, data: undefined, end: 'Function<onReadableStreamEnd>', readable: undefined, connect: undefined, free: 'Function<onFree>', timeout: 'Function<onTimeout>', agentRemove: 'Function<onRemove>' }, _readableState: { highWaterMark: 16384, buffer: [], bufferIndex: +0, length: +0, pipes: [], awaitDrainWriters: null, constructor: 'Function<ReadableState>', objectMode: false, ended: false, endEmitted: false, reading: true, constructed: true, sync: false, needReadable: true, emittedReadable: false, readableListening: false, resumeScheduled: false, errorEmitted: false, emitClose: false, autoDestroy: true, destroyed: false, closed: false, closeEmitted: false, multiAwaitDrain: false, readingMore: false, dataEmitted: true, errored: null, defaultEncoding: 'utf8', decoder: null, encoding: null, flowing: true, pipesCount: +0, paused: false }, _writableState: { highWaterMark: 16384, length: +0, corked: +0, onwrite: 'Function<bound onwrite>', writelen: +0, bufferedIndex: +0, pendingcb: +0, constructor: 'Function<WritableState>', objectMode: false, finalCalled: false, needDrain: false, ending: false, ended: false, finished: false, destroyed: false, decodeStrings: false, writing: false, sync: false, bufferProcessing: false, constructed: true, prefinished: false, errorEmitted: false, emitClose: false, autoDestroy: true, closed: false, closeEmitted: false, allBuffers: true, allNoop: true, errored: null, writable: undefined, defaultEncoding: 'utf8', writecb: 'Function<nop>', afterWriteTickInfo: nul
targets.map((u) =>
cognitoClient.send(
new AdminDeleteUserCommand({ Username: u.Username, UserPoolId: COGNITO_USER_POOL_ID }),
),
),
);
}
};

afterEach(async (info) => {
if (unneededServer(info.task.file)) return;

await prismaClient.$disconnect();
await resetS3();
await resetCognito();
});

afterAll(async (info) => {
if (unneededServer(info.file)) return;

await server.close();

const objects = await s3Client.send(new ListObjectsV2Command({ Bucket: S3_BUCKET }));
const keys = objects.Contents?.map(({ Key }) => ({ Key })) ?? [];

if (keys.length === 0) return;

await s3Client.send(new DeleteObjectsCommand({ Bucket: S3_BUCKET, Delete: { Objects: keys } }));
});

0 comments on commit e5a2980

Please sign in to comment.