mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-11 20:08:37 +00:00
test(server): make server testing utils (#5544)
This commit is contained in:
@@ -3,17 +3,16 @@ import { randomUUID } from 'node:crypto';
|
||||
|
||||
import { Transformer } from '@napi-rs/image';
|
||||
import type { INestApplication } from '@nestjs/common';
|
||||
import { Test } from '@nestjs/testing';
|
||||
import { hashSync } from '@node-rs/argon2';
|
||||
import { type User } from '@prisma/client';
|
||||
import ava, { type TestFn } from 'ava';
|
||||
import type { Express } from 'express';
|
||||
import graphqlUploadExpress from 'graphql-upload/graphqlUploadExpress.mjs';
|
||||
import request from 'supertest';
|
||||
|
||||
import { AppModule } from '../src/app';
|
||||
import { FeatureManagementService } from '../src/modules/features';
|
||||
import { PrismaService } from '../src/prisma/service';
|
||||
import { createTestingApp } from './utils';
|
||||
|
||||
const gql = '/graphql';
|
||||
|
||||
@@ -49,25 +48,18 @@ class FakePrisma {
|
||||
}
|
||||
|
||||
test.beforeEach(async t => {
|
||||
const module = await Test.createTestingModule({
|
||||
const { app } = await createTestingApp({
|
||||
imports: [AppModule],
|
||||
})
|
||||
.overrideProvider(PrismaService)
|
||||
.useClass(FakePrisma)
|
||||
.overrideProvider(FeatureManagementService)
|
||||
.useValue({ canEarlyAccess: () => true })
|
||||
.compile();
|
||||
t.context.app = module.createNestApplication({
|
||||
cors: true,
|
||||
bodyParser: true,
|
||||
tapModule(builder) {
|
||||
builder
|
||||
.overrideProvider(PrismaService)
|
||||
.useClass(FakePrisma)
|
||||
.overrideProvider(FeatureManagementService)
|
||||
.useValue({ canEarlyAccess: () => true });
|
||||
},
|
||||
});
|
||||
t.context.app.use(
|
||||
graphqlUploadExpress({
|
||||
maxFileSize: 10 * 1024 * 1024,
|
||||
maxFiles: 5,
|
||||
})
|
||||
);
|
||||
await t.context.app.init();
|
||||
|
||||
t.context.app = app;
|
||||
});
|
||||
|
||||
test.afterEach.always(async t => {
|
||||
|
||||
@@ -3,19 +3,13 @@ import {
|
||||
getLatestMailMessage,
|
||||
} from '@affine-test/kit/utils/cloud';
|
||||
import type { INestApplication } from '@nestjs/common';
|
||||
import { Test } from '@nestjs/testing';
|
||||
import { PrismaClient } from '@prisma/client';
|
||||
import ava, { type TestFn } from 'ava';
|
||||
import graphqlUploadExpress from 'graphql-upload/graphqlUploadExpress.mjs';
|
||||
|
||||
import { AppModule } from '../src/app';
|
||||
import { RevertCommand, RunCommand } from '../src/data/commands/run';
|
||||
import { MailService } from '../src/modules/auth/mailer';
|
||||
import { AuthService } from '../src/modules/auth/service';
|
||||
import {
|
||||
changeEmail,
|
||||
createWorkspace,
|
||||
initFeatureConfigs,
|
||||
createTestingApp,
|
||||
sendChangeEmail,
|
||||
sendVerifyChangeEmail,
|
||||
signUp,
|
||||
@@ -23,44 +17,20 @@ import {
|
||||
|
||||
const test = ava as TestFn<{
|
||||
app: INestApplication;
|
||||
client: PrismaClient;
|
||||
auth: AuthService;
|
||||
mail: MailService;
|
||||
}>;
|
||||
|
||||
test.beforeEach(async t => {
|
||||
const client = new PrismaClient();
|
||||
t.context.client = client;
|
||||
await client.$connect();
|
||||
await client.user.deleteMany({});
|
||||
await client.snapshot.deleteMany({});
|
||||
await client.update.deleteMany({});
|
||||
await client.workspace.deleteMany({});
|
||||
await client.$disconnect();
|
||||
const module = await Test.createTestingModule({
|
||||
imports: [AppModule],
|
||||
providers: [RevertCommand, RunCommand],
|
||||
}).compile();
|
||||
const app = module.createNestApplication();
|
||||
app.use(
|
||||
graphqlUploadExpress({
|
||||
maxFileSize: 10 * 1024 * 1024,
|
||||
maxFiles: 5,
|
||||
})
|
||||
);
|
||||
await app.init();
|
||||
|
||||
const auth = module.get(AuthService);
|
||||
const mail = module.get(MailService);
|
||||
const { app } = await createTestingApp();
|
||||
const auth = app.get(AuthService);
|
||||
const mail = app.get(MailService);
|
||||
t.context.app = app;
|
||||
t.context.auth = auth;
|
||||
t.context.mail = mail;
|
||||
|
||||
// init features
|
||||
await initFeatureConfigs(module);
|
||||
});
|
||||
|
||||
test.afterEach(async t => {
|
||||
test.afterEach.always(async t => {
|
||||
await t.context.app.close();
|
||||
});
|
||||
|
||||
@@ -73,8 +43,6 @@ test('change email', async t => {
|
||||
|
||||
const u1 = await signUp(app, 'u1', u1Email, '1');
|
||||
|
||||
await createWorkspace(app, u1.token.token);
|
||||
|
||||
const primitiveMailCount = await getCurrentMailMessageCount();
|
||||
|
||||
await sendChangeEmail(app, u1.token.token, u1Email, 'affine.pro');
|
||||
|
||||
@@ -1,34 +1,19 @@
|
||||
/// <reference types="../src/global.d.ts" />
|
||||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { PrismaClient } from '@prisma/client';
|
||||
import { TestingModule } from '@nestjs/testing';
|
||||
import test from 'ava';
|
||||
|
||||
import { CacheModule } from '../src/cache';
|
||||
import { ConfigModule } from '../src/config';
|
||||
import { RevertCommand, RunCommand } from '../src/data/commands/run';
|
||||
import { GqlModule } from '../src/graphql.module';
|
||||
import { AuthModule } from '../src/modules/auth';
|
||||
import { AuthResolver } from '../src/modules/auth/resolver';
|
||||
import { AuthService } from '../src/modules/auth/service';
|
||||
import { PrismaModule } from '../src/prisma';
|
||||
import { mintChallengeResponse, verifyChallengeResponse } from '../src/storage';
|
||||
import { RateLimiterModule } from '../src/throttler';
|
||||
import { initFeatureConfigs } from './utils';
|
||||
import { createTestingModule } from './utils';
|
||||
|
||||
let authService: AuthService;
|
||||
let authResolver: AuthResolver;
|
||||
let module: TestingModule;
|
||||
|
||||
// cleanup database before each test
|
||||
test.beforeEach(async () => {
|
||||
const client = new PrismaClient();
|
||||
await client.$connect();
|
||||
await client.user.deleteMany({});
|
||||
await client.$disconnect();
|
||||
});
|
||||
|
||||
test.beforeEach(async () => {
|
||||
module = await Test.createTestingModule({
|
||||
module = await createTestingModule({
|
||||
imports: [
|
||||
ConfigModule.forRoot({
|
||||
auth: {
|
||||
@@ -39,20 +24,11 @@ test.beforeEach(async () => {
|
||||
host: 'example.org',
|
||||
https: true,
|
||||
}),
|
||||
PrismaModule,
|
||||
CacheModule,
|
||||
GqlModule,
|
||||
AuthModule,
|
||||
RateLimiterModule,
|
||||
RevertCommand,
|
||||
RunCommand,
|
||||
],
|
||||
}).compile();
|
||||
});
|
||||
|
||||
authService = module.get(AuthService);
|
||||
authResolver = module.get(AuthResolver);
|
||||
|
||||
// init features
|
||||
await initFeatureConfigs(module);
|
||||
});
|
||||
|
||||
test.afterEach.always(async () => {
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
import { mock } from 'node:test';
|
||||
|
||||
import type { INestApplication } from '@nestjs/common';
|
||||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { TestingModule } from '@nestjs/testing';
|
||||
import test from 'ava';
|
||||
import { register } from 'prom-client';
|
||||
import * as Sinon from 'sinon';
|
||||
import {
|
||||
applyUpdate,
|
||||
@@ -12,37 +10,19 @@ import {
|
||||
encodeStateAsUpdate,
|
||||
} from 'yjs';
|
||||
|
||||
import { CacheModule } from '../src/cache';
|
||||
import { Config, ConfigModule } from '../src/config';
|
||||
import {
|
||||
collectMigrations,
|
||||
RevertCommand,
|
||||
RunCommand,
|
||||
} from '../src/data/commands/run';
|
||||
import { EventModule } from '../src/event';
|
||||
import { Config } from '../src/config';
|
||||
import { DocManager, DocModule } from '../src/modules/doc';
|
||||
import { QuotaModule } from '../src/modules/quota';
|
||||
import { StorageModule } from '../src/modules/storage';
|
||||
import { PrismaModule, PrismaService } from '../src/prisma';
|
||||
import { flushDB } from './utils';
|
||||
import { PrismaService } from '../src/prisma';
|
||||
import { createTestingModule, initTestingDB } from './utils';
|
||||
|
||||
const createModule = () => {
|
||||
return Test.createTestingModule({
|
||||
imports: [
|
||||
PrismaModule,
|
||||
CacheModule,
|
||||
EventModule,
|
||||
QuotaModule,
|
||||
StorageModule,
|
||||
ConfigModule.forRoot(),
|
||||
DocModule,
|
||||
RevertCommand,
|
||||
RunCommand,
|
||||
],
|
||||
}).compile();
|
||||
return createTestingModule({
|
||||
imports: [QuotaModule, StorageModule, DocModule],
|
||||
});
|
||||
};
|
||||
|
||||
let app: INestApplication;
|
||||
let m: TestingModule;
|
||||
let timer: Sinon.SinonFakeTimers;
|
||||
|
||||
@@ -51,44 +31,34 @@ test.beforeEach(async () => {
|
||||
timer = Sinon.useFakeTimers({
|
||||
toFake: ['setInterval'],
|
||||
});
|
||||
await flushDB();
|
||||
m = await createModule();
|
||||
app = m.createNestApplication();
|
||||
app.enableShutdownHooks();
|
||||
await app.init();
|
||||
|
||||
// init features
|
||||
const run = m.get(RunCommand);
|
||||
const revert = m.get(RevertCommand);
|
||||
const migrations = await collectMigrations();
|
||||
await Promise.allSettled(migrations.map(m => revert.run([m.name])));
|
||||
await run.run();
|
||||
await m.init();
|
||||
await initTestingDB(m.get(PrismaService));
|
||||
});
|
||||
|
||||
test.afterEach.always(async () => {
|
||||
await app.close();
|
||||
await m.close();
|
||||
timer.restore();
|
||||
});
|
||||
|
||||
test('should setup update poll interval', async t => {
|
||||
register.clear();
|
||||
const m = await createModule();
|
||||
const manager = m.get(DocManager);
|
||||
const fake = mock.method(manager, 'setup');
|
||||
|
||||
await m.createNestApplication().init();
|
||||
await m.init();
|
||||
|
||||
t.is(fake.mock.callCount(), 1);
|
||||
// @ts-expect-error private member
|
||||
t.truthy(manager.job);
|
||||
m.close();
|
||||
});
|
||||
|
||||
test('should be able to stop poll', async t => {
|
||||
const manager = m.get(DocManager);
|
||||
const fake = mock.method(manager, 'destroy');
|
||||
|
||||
await app.close();
|
||||
await m.close();
|
||||
|
||||
t.is(fake.mock.callCount(), 1);
|
||||
// @ts-expect-error private member
|
||||
|
||||
@@ -1,14 +1,9 @@
|
||||
/// <reference types="../src/global.d.ts" />
|
||||
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { PrismaClient } from '@prisma/client';
|
||||
import { INestApplication, Injectable } from '@nestjs/common';
|
||||
import ava, { type TestFn } from 'ava';
|
||||
|
||||
import { CacheModule } from '../src/cache';
|
||||
import { ConfigModule } from '../src/config';
|
||||
import { RevertCommand, RunCommand } from '../src/data/commands/run';
|
||||
import { AuthModule } from '../src/modules/auth';
|
||||
import { AuthService } from '../src/modules/auth/service';
|
||||
import {
|
||||
FeatureManagementService,
|
||||
@@ -19,9 +14,8 @@ import {
|
||||
import { UserType } from '../src/modules/users/types';
|
||||
import { WorkspaceResolver } from '../src/modules/workspaces/resolvers';
|
||||
import { Permission } from '../src/modules/workspaces/types';
|
||||
import { PrismaModule, PrismaService } from '../src/prisma';
|
||||
import { RateLimiterModule } from '../src/throttler';
|
||||
import { initFeatureConfigs } from './utils';
|
||||
import { PrismaService } from '../src/prisma';
|
||||
import { createTestingApp } from './utils';
|
||||
|
||||
@Injectable()
|
||||
class WorkspaceResolverMock {
|
||||
@@ -53,20 +47,11 @@ const test = ava as TestFn<{
|
||||
feature: FeatureService;
|
||||
workspace: WorkspaceResolver;
|
||||
management: FeatureManagementService;
|
||||
app: TestingModule;
|
||||
app: INestApplication;
|
||||
}>;
|
||||
|
||||
// cleanup database before each test
|
||||
test.beforeEach(async () => {
|
||||
const client = new PrismaClient();
|
||||
await client.$connect();
|
||||
await client.user.deleteMany({});
|
||||
await client.workspace.deleteMany({});
|
||||
await client.$disconnect();
|
||||
});
|
||||
|
||||
test.beforeEach(async t => {
|
||||
const module = await Test.createTestingModule({
|
||||
const { app } = await createTestingApp({
|
||||
imports: [
|
||||
ConfigModule.forRoot({
|
||||
auth: {
|
||||
@@ -80,28 +65,21 @@ test.beforeEach(async t => {
|
||||
earlyAccessPreview: true,
|
||||
},
|
||||
}),
|
||||
PrismaModule,
|
||||
CacheModule,
|
||||
AuthModule,
|
||||
FeatureModule,
|
||||
RateLimiterModule,
|
||||
RevertCommand,
|
||||
RunCommand,
|
||||
],
|
||||
providers: [WorkspaceResolver],
|
||||
})
|
||||
.overrideProvider(WorkspaceResolver)
|
||||
.useClass(WorkspaceResolverMock)
|
||||
.compile();
|
||||
tapModule: module => {
|
||||
module
|
||||
.overrideProvider(WorkspaceResolver)
|
||||
.useClass(WorkspaceResolverMock);
|
||||
},
|
||||
});
|
||||
|
||||
t.context.app = module;
|
||||
t.context.auth = module.get(AuthService);
|
||||
t.context.feature = module.get(FeatureService);
|
||||
t.context.workspace = module.get(WorkspaceResolver);
|
||||
t.context.management = module.get(FeatureManagementService);
|
||||
|
||||
// init features
|
||||
await initFeatureConfigs(module);
|
||||
t.context.app = app;
|
||||
t.context.auth = app.get(AuthService);
|
||||
t.context.feature = app.get(FeatureService);
|
||||
t.context.workspace = app.get(WorkspaceResolver);
|
||||
t.context.management = app.get(FeatureManagementService);
|
||||
});
|
||||
|
||||
test.afterEach.always(async t => {
|
||||
|
||||
@@ -1,40 +1,26 @@
|
||||
import { INestApplication } from '@nestjs/common';
|
||||
import { ScheduleModule } from '@nestjs/schedule';
|
||||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { TestingModule } from '@nestjs/testing';
|
||||
import type { Snapshot } from '@prisma/client';
|
||||
import test from 'ava';
|
||||
import * as Sinon from 'sinon';
|
||||
|
||||
import { ConfigModule } from '../src/config';
|
||||
import { EventModule, type EventPayload } from '../src/event';
|
||||
import { type EventPayload } from '../src/event';
|
||||
import { DocHistoryManager } from '../src/modules/doc';
|
||||
import { QuotaModule } from '../src/modules/quota';
|
||||
import { StorageModule } from '../src/modules/storage';
|
||||
import { PrismaModule, PrismaService } from '../src/prisma';
|
||||
import { flushDB } from './utils';
|
||||
import { PrismaService } from '../src/prisma';
|
||||
import { createTestingModule } from './utils';
|
||||
|
||||
let app: INestApplication;
|
||||
let m: TestingModule;
|
||||
let manager: DocHistoryManager;
|
||||
let db: PrismaService;
|
||||
|
||||
// cleanup database before each test
|
||||
test.beforeEach(async () => {
|
||||
await flushDB();
|
||||
m = await Test.createTestingModule({
|
||||
imports: [
|
||||
PrismaModule,
|
||||
QuotaModule,
|
||||
EventModule,
|
||||
StorageModule,
|
||||
ScheduleModule.forRoot(),
|
||||
ConfigModule.forRoot(),
|
||||
],
|
||||
m = await createTestingModule({
|
||||
imports: [StorageModule, QuotaModule],
|
||||
providers: [DocHistoryManager],
|
||||
}).compile();
|
||||
});
|
||||
|
||||
app = m.createNestApplication();
|
||||
await app.init();
|
||||
manager = m.get(DocHistoryManager);
|
||||
Sinon.stub(manager, 'getExpiredDateFromNow').resolves(
|
||||
new Date(Date.now() + 1000)
|
||||
@@ -42,8 +28,7 @@ test.beforeEach(async () => {
|
||||
db = m.get(PrismaService);
|
||||
});
|
||||
|
||||
test.afterEach(async () => {
|
||||
await app.close();
|
||||
test.afterEach.always(async () => {
|
||||
await m.close();
|
||||
Sinon.restore();
|
||||
});
|
||||
|
||||
@@ -6,19 +6,13 @@ import {
|
||||
getCurrentMailMessageCount,
|
||||
getLatestMailMessage,
|
||||
} from '@affine-test/kit/utils/cloud';
|
||||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { TestingModule } from '@nestjs/testing';
|
||||
import { PrismaClient } from '@prisma/client';
|
||||
import ava, { type TestFn } from 'ava';
|
||||
|
||||
import { CacheModule } from '../src/cache';
|
||||
import { ConfigModule } from '../src/config';
|
||||
import { RevertCommand, RunCommand } from '../src/data/commands/run';
|
||||
import { GqlModule } from '../src/graphql.module';
|
||||
import { AuthModule } from '../src/modules/auth';
|
||||
import { AuthService } from '../src/modules/auth/service';
|
||||
import { PrismaModule } from '../src/prisma';
|
||||
import { RateLimiterModule } from '../src/throttler';
|
||||
import { initFeatureConfigs } from './utils';
|
||||
import { createTestingModule } from './utils';
|
||||
|
||||
const test = ava as TestFn<{
|
||||
auth: AuthService;
|
||||
@@ -34,7 +28,7 @@ test.beforeEach(async () => {
|
||||
});
|
||||
|
||||
test.beforeEach(async t => {
|
||||
t.context.module = await Test.createTestingModule({
|
||||
t.context.module = await createTestingModule({
|
||||
imports: [
|
||||
ConfigModule.forRoot({
|
||||
auth: {
|
||||
@@ -43,18 +37,9 @@ test.beforeEach(async t => {
|
||||
leeway: 1,
|
||||
},
|
||||
}),
|
||||
PrismaModule,
|
||||
GqlModule,
|
||||
AuthModule,
|
||||
CacheModule,
|
||||
RateLimiterModule,
|
||||
],
|
||||
providers: [RevertCommand, RunCommand],
|
||||
}).compile();
|
||||
});
|
||||
t.context.auth = t.context.module.get(AuthService);
|
||||
|
||||
// init features
|
||||
await initFeatureConfigs(t.context.module);
|
||||
});
|
||||
|
||||
test.afterEach.always(async t => {
|
||||
|
||||
@@ -1,18 +1,22 @@
|
||||
import { randomUUID } from 'node:crypto';
|
||||
|
||||
import type { INestApplication } from '@nestjs/common';
|
||||
import { Test } from '@nestjs/testing';
|
||||
import { hashSync } from '@node-rs/argon2';
|
||||
import { type User } from '@prisma/client';
|
||||
import ava, { type TestFn } from 'ava';
|
||||
import graphqlUploadExpress from 'graphql-upload/graphqlUploadExpress.mjs';
|
||||
|
||||
import { AppModule } from '../src/app';
|
||||
import { MailService } from '../src/modules/auth/mailer';
|
||||
import { FeatureKind, FeatureManagementService } from '../src/modules/features';
|
||||
import { Quotas } from '../src/modules/quota';
|
||||
import { PrismaService } from '../src/prisma';
|
||||
import { createWorkspace, getInviteInfo, inviteUser, signUp } from './utils';
|
||||
import {
|
||||
createTestingApp,
|
||||
createWorkspace,
|
||||
getInviteInfo,
|
||||
inviteUser,
|
||||
signUp,
|
||||
} from './utils';
|
||||
|
||||
const FakePrisma = {
|
||||
fakeUser: {
|
||||
@@ -123,26 +127,20 @@ const test = ava as TestFn<{
|
||||
}>;
|
||||
|
||||
test.beforeEach(async t => {
|
||||
const module = await Test.createTestingModule({
|
||||
const { module, app } = await createTestingApp({
|
||||
imports: [AppModule],
|
||||
})
|
||||
.overrideProvider(PrismaService)
|
||||
.useValue(FakePrisma)
|
||||
.overrideProvider(FeatureManagementService)
|
||||
.useValue({
|
||||
hasWorkspaceFeature() {
|
||||
return false;
|
||||
},
|
||||
})
|
||||
.compile();
|
||||
const app = module.createNestApplication();
|
||||
app.use(
|
||||
graphqlUploadExpress({
|
||||
maxFileSize: 10 * 1024 * 1024,
|
||||
maxFiles: 5,
|
||||
})
|
||||
);
|
||||
await app.init();
|
||||
tapModule: module => {
|
||||
module
|
||||
.overrideProvider(PrismaService)
|
||||
.useValue(FakePrisma)
|
||||
.overrideProvider(FeatureManagementService)
|
||||
.useValue({
|
||||
hasWorkspaceFeature() {
|
||||
return false;
|
||||
},
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
const mail = module.get(MailService);
|
||||
t.context.app = app;
|
||||
|
||||
@@ -1,14 +1,8 @@
|
||||
/// <reference types="../src/global.d.ts" />
|
||||
|
||||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { PrismaClient } from '@prisma/client';
|
||||
import { TestingModule } from '@nestjs/testing';
|
||||
import ava, { type TestFn } from 'ava';
|
||||
|
||||
import { CacheModule } from '../src/cache';
|
||||
import { ConfigModule } from '../src/config';
|
||||
import { RevertCommand, RunCommand } from '../src/data/commands/run';
|
||||
import { EventModule } from '../src/event';
|
||||
import { AuthModule } from '../src/modules/auth';
|
||||
import { AuthService } from '../src/modules/auth/service';
|
||||
import {
|
||||
QuotaManagementService,
|
||||
@@ -18,64 +12,32 @@ import {
|
||||
QuotaType,
|
||||
} from '../src/modules/quota';
|
||||
import { StorageModule } from '../src/modules/storage';
|
||||
import { PrismaModule } from '../src/prisma';
|
||||
import { RateLimiterModule } from '../src/throttler';
|
||||
import { initFeatureConfigs } from './utils';
|
||||
import { createTestingModule } from './utils';
|
||||
|
||||
const test = ava as TestFn<{
|
||||
auth: AuthService;
|
||||
quota: QuotaService;
|
||||
storageQuota: QuotaManagementService;
|
||||
app: TestingModule;
|
||||
module: TestingModule;
|
||||
}>;
|
||||
|
||||
// cleanup database before each test
|
||||
test.beforeEach(async () => {
|
||||
const client = new PrismaClient();
|
||||
await client.$connect();
|
||||
await client.user.deleteMany({});
|
||||
await client.$disconnect();
|
||||
});
|
||||
|
||||
test.beforeEach(async t => {
|
||||
const module = await Test.createTestingModule({
|
||||
imports: [
|
||||
ConfigModule.forRoot({
|
||||
auth: {
|
||||
accessTokenExpiresIn: 1,
|
||||
refreshTokenExpiresIn: 1,
|
||||
leeway: 1,
|
||||
},
|
||||
host: 'example.org',
|
||||
https: true,
|
||||
}),
|
||||
PrismaModule,
|
||||
CacheModule,
|
||||
AuthModule,
|
||||
EventModule,
|
||||
QuotaModule,
|
||||
StorageModule,
|
||||
RateLimiterModule,
|
||||
RevertCommand,
|
||||
RunCommand,
|
||||
],
|
||||
}).compile();
|
||||
const module = await createTestingModule({
|
||||
imports: [StorageModule, QuotaModule],
|
||||
});
|
||||
|
||||
const quota = module.get(QuotaService);
|
||||
const storageQuota = module.get(QuotaManagementService);
|
||||
const auth = module.get(AuthService);
|
||||
|
||||
t.context.app = module;
|
||||
t.context.module = module;
|
||||
t.context.quota = quota;
|
||||
t.context.storageQuota = storageQuota;
|
||||
t.context.auth = auth;
|
||||
|
||||
// init features
|
||||
await initFeatureConfigs(module);
|
||||
});
|
||||
|
||||
test.afterEach.always(async t => {
|
||||
await t.context.app.close();
|
||||
await t.context.module.close();
|
||||
});
|
||||
|
||||
test('should be able to set quota', async t => {
|
||||
|
||||
@@ -1,19 +1,20 @@
|
||||
/// <reference types="../src/global.d.ts" />
|
||||
|
||||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { TestingModule } from '@nestjs/testing';
|
||||
import ava, { type TestFn } from 'ava';
|
||||
|
||||
import { CacheModule } from '../src/cache';
|
||||
import { ConfigModule } from '../src/config';
|
||||
import { SessionModule, SessionService } from '../src/session';
|
||||
import { createTestingModule } from './utils';
|
||||
|
||||
const test = ava as TestFn<{
|
||||
session: SessionService;
|
||||
app: TestingModule;
|
||||
module: TestingModule;
|
||||
}>;
|
||||
|
||||
test.beforeEach(async t => {
|
||||
const module = await Test.createTestingModule({
|
||||
const module = await createTestingModule({
|
||||
imports: [
|
||||
ConfigModule.forRoot({
|
||||
redis: {
|
||||
@@ -23,14 +24,14 @@ test.beforeEach(async t => {
|
||||
CacheModule,
|
||||
SessionModule,
|
||||
],
|
||||
}).compile();
|
||||
});
|
||||
const session = module.get(SessionService);
|
||||
t.context.app = module;
|
||||
t.context.module = module;
|
||||
t.context.session = session;
|
||||
});
|
||||
|
||||
test.afterEach.always(async t => {
|
||||
await t.context.app.close();
|
||||
await t.context.module.close();
|
||||
});
|
||||
|
||||
test('should be able to set session', async t => {
|
||||
|
||||
@@ -1,40 +1,17 @@
|
||||
import type { INestApplication } from '@nestjs/common';
|
||||
import { Test } from '@nestjs/testing';
|
||||
import { PrismaClient } from '@prisma/client';
|
||||
import test from 'ava';
|
||||
import graphqlUploadExpress from 'graphql-upload/graphqlUploadExpress.mjs';
|
||||
import request from 'supertest';
|
||||
|
||||
import { AppModule } from '../src/app';
|
||||
import { RevertCommand, RunCommand } from '../src/data/commands/run';
|
||||
import { currentUser, initFeatureConfigs, signUp } from './utils';
|
||||
import { createTestingApp, currentUser, signUp } from './utils';
|
||||
|
||||
let app: INestApplication;
|
||||
|
||||
// cleanup database before each test
|
||||
test.beforeEach(async () => {
|
||||
const client = new PrismaClient();
|
||||
await client.$connect();
|
||||
await client.user.deleteMany({});
|
||||
await client.$disconnect();
|
||||
});
|
||||
|
||||
test.beforeEach(async () => {
|
||||
const module = await Test.createTestingModule({
|
||||
const { app: testApp } = await createTestingApp({
|
||||
imports: [AppModule],
|
||||
providers: [RevertCommand, RunCommand],
|
||||
}).compile();
|
||||
app = module.createNestApplication();
|
||||
app.use(
|
||||
graphqlUploadExpress({
|
||||
maxFileSize: 10 * 1024 * 1024,
|
||||
maxFiles: 5,
|
||||
})
|
||||
);
|
||||
await app.init();
|
||||
|
||||
// init features
|
||||
await initFeatureConfigs(module);
|
||||
});
|
||||
app = testApp;
|
||||
});
|
||||
|
||||
test.afterEach.always(async () => {
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
import { randomUUID } from 'node:crypto';
|
||||
import { INestApplication, ModuleMetadata } from '@nestjs/common';
|
||||
import { Query, Resolver } from '@nestjs/graphql';
|
||||
import { Test, TestingModuleBuilder } from '@nestjs/testing';
|
||||
import { PrismaClient } from '@prisma/client';
|
||||
import graphqlUploadExpress from 'graphql-upload/graphqlUploadExpress.mjs';
|
||||
|
||||
import { TestingModule } from '@nestjs/testing';
|
||||
import { hashSync } from '@node-rs/argon2';
|
||||
import { PrismaClient, type User } from '@prisma/client';
|
||||
import { AppModule, FunctionalityModules } from '../../src/app';
|
||||
import { UserFeaturesInit1698652531198 } from '../../src/data/migrations/1698652531198-user-features-init';
|
||||
import { GqlModule } from '../../src/graphql.module';
|
||||
|
||||
import { RevertCommand, RunCommand } from '../../src/data/commands/run';
|
||||
|
||||
export async function flushDB() {
|
||||
const client = new PrismaClient();
|
||||
await client.$connect();
|
||||
async function flushDB(client: PrismaClient) {
|
||||
const result: { tablename: string }[] =
|
||||
await client.$queryRaw`SELECT tablename
|
||||
FROM pg_catalog.pg_tables
|
||||
@@ -22,41 +22,99 @@ export async function flushDB() {
|
||||
.filter(name => !name.includes('migrations'))
|
||||
.join(', ')}`
|
||||
);
|
||||
|
||||
await client.$disconnect();
|
||||
}
|
||||
|
||||
export class FakePrisma {
|
||||
fakeUser: User = {
|
||||
id: randomUUID(),
|
||||
name: 'Alex Yang',
|
||||
avatarUrl: '',
|
||||
email: 'alex.yang@example.org',
|
||||
password: hashSync('123456'),
|
||||
emailVerified: new Date(),
|
||||
createdAt: new Date(),
|
||||
};
|
||||
async function initFeatureConfigs(db: PrismaClient) {
|
||||
await UserFeaturesInit1698652531198.up(db);
|
||||
}
|
||||
|
||||
get user() {
|
||||
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
||||
const prisma = this;
|
||||
return {
|
||||
async findFirst() {
|
||||
return prisma.fakeUser;
|
||||
},
|
||||
async findUnique() {
|
||||
return this.findFirst();
|
||||
},
|
||||
async update() {
|
||||
return this.findFirst();
|
||||
},
|
||||
};
|
||||
export async function initTestingDB(db: PrismaClient) {
|
||||
await flushDB(db);
|
||||
await initFeatureConfigs(db);
|
||||
}
|
||||
|
||||
interface TestingModuleMeatdata extends ModuleMetadata {
|
||||
tapModule?(m: TestingModuleBuilder): void;
|
||||
tapApp?(app: INestApplication): void;
|
||||
}
|
||||
|
||||
function dedupeModules(modules: NonNullable<ModuleMetadata['imports']>) {
|
||||
const map = new Map();
|
||||
|
||||
modules.forEach(m => {
|
||||
if ('module' in m) {
|
||||
map.set(m.module, m);
|
||||
} else {
|
||||
map.set(m, m);
|
||||
}
|
||||
});
|
||||
|
||||
return Array.from(map.values());
|
||||
}
|
||||
|
||||
@Resolver(() => String)
|
||||
class MockResolver {
|
||||
@Query(() => String)
|
||||
hello() {
|
||||
return 'hello world';
|
||||
}
|
||||
}
|
||||
|
||||
export async function initFeatureConfigs(module: TestingModule) {
|
||||
const run = module.get(RunCommand);
|
||||
const revert = module.get(RevertCommand);
|
||||
await Promise.allSettled([revert.run(['UserFeaturesInit1698652531198'])]);
|
||||
await run.runOne('UserFeaturesInit1698652531198');
|
||||
export async function createTestingModule(
|
||||
moduleDef: TestingModuleMeatdata = {}
|
||||
) {
|
||||
// setting up
|
||||
let imports = moduleDef.imports ?? [];
|
||||
imports =
|
||||
imports[0] === AppModule
|
||||
? [AppModule]
|
||||
: dedupeModules([...FunctionalityModules, GqlModule, ...imports]);
|
||||
|
||||
const builder = Test.createTestingModule({
|
||||
imports,
|
||||
providers: [MockResolver, ...(moduleDef.providers ?? [])],
|
||||
controllers: moduleDef.controllers,
|
||||
});
|
||||
|
||||
if (moduleDef.tapModule) {
|
||||
moduleDef.tapModule(builder);
|
||||
}
|
||||
|
||||
const m = await builder.compile();
|
||||
|
||||
const prisma = m.get(PrismaClient);
|
||||
if (prisma instanceof PrismaClient) {
|
||||
await flushDB(prisma);
|
||||
await initFeatureConfigs(prisma);
|
||||
}
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
export async function createTestingApp(moduleDef: TestingModuleMeatdata = {}) {
|
||||
const m = await createTestingModule(moduleDef);
|
||||
|
||||
const app = m.createNestApplication({
|
||||
cors: true,
|
||||
bodyParser: true,
|
||||
rawBody: true,
|
||||
});
|
||||
|
||||
app.use(
|
||||
graphqlUploadExpress({
|
||||
maxFileSize: 10 * 1024 * 1024,
|
||||
maxFiles: 5,
|
||||
})
|
||||
);
|
||||
|
||||
if (moduleDef.tapApp) {
|
||||
moduleDef.tapApp(app);
|
||||
}
|
||||
|
||||
await app.init();
|
||||
|
||||
return {
|
||||
module: m,
|
||||
app,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,19 +1,15 @@
|
||||
import type { INestApplication } from '@nestjs/common';
|
||||
import { Test } from '@nestjs/testing';
|
||||
import { PrismaClient } from '@prisma/client';
|
||||
import test from 'ava';
|
||||
import graphqlUploadExpress from 'graphql-upload/graphqlUploadExpress.mjs';
|
||||
import request from 'supertest';
|
||||
|
||||
import { AppModule } from '../src/app';
|
||||
import { RevertCommand, RunCommand } from '../src/data/commands/run';
|
||||
import { QuotaService, QuotaType } from '../src/modules/quota';
|
||||
import {
|
||||
checkBlobSize,
|
||||
collectAllBlobSizes,
|
||||
createTestingApp,
|
||||
createWorkspace,
|
||||
getWorkspaceBlobsSize,
|
||||
initFeatureConfigs,
|
||||
listBlobs,
|
||||
setBlob,
|
||||
signUp,
|
||||
@@ -22,36 +18,13 @@ import {
|
||||
let app: INestApplication;
|
||||
let quota: QuotaService;
|
||||
|
||||
const client = new PrismaClient();
|
||||
|
||||
// cleanup database before each test
|
||||
test.beforeEach(async () => {
|
||||
await client.$connect();
|
||||
await client.user.deleteMany({});
|
||||
await client.snapshot.deleteMany({});
|
||||
await client.update.deleteMany({});
|
||||
await client.workspace.deleteMany({});
|
||||
await client.$disconnect();
|
||||
});
|
||||
|
||||
test.beforeEach(async () => {
|
||||
const module = await Test.createTestingModule({
|
||||
const { app: testApp } = await createTestingApp({
|
||||
imports: [AppModule],
|
||||
providers: [RevertCommand, RunCommand],
|
||||
}).compile();
|
||||
app = module.createNestApplication();
|
||||
app.use(
|
||||
graphqlUploadExpress({
|
||||
maxFileSize: 10 * 1024 * 1024,
|
||||
maxFiles: 5,
|
||||
})
|
||||
);
|
||||
quota = module.get(QuotaService);
|
||||
});
|
||||
|
||||
// init features
|
||||
await initFeatureConfigs(module);
|
||||
|
||||
await app.init();
|
||||
app = testApp;
|
||||
quota = app.get(QuotaService);
|
||||
});
|
||||
|
||||
test.afterEach.always(async () => {
|
||||
|
||||
@@ -3,20 +3,18 @@ import {
|
||||
getLatestMailMessage,
|
||||
} from '@affine-test/kit/utils/cloud';
|
||||
import type { INestApplication } from '@nestjs/common';
|
||||
import { Test } from '@nestjs/testing';
|
||||
import { PrismaClient } from '@prisma/client';
|
||||
import ava, { type TestFn } from 'ava';
|
||||
import graphqlUploadExpress from 'graphql-upload/graphqlUploadExpress.mjs';
|
||||
|
||||
import { AppModule } from '../src/app';
|
||||
import { RevertCommand, RunCommand } from '../src/data/commands/run';
|
||||
import { MailService } from '../src/modules/auth/mailer';
|
||||
import { AuthService } from '../src/modules/auth/service';
|
||||
import { PrismaService } from '../src/prisma';
|
||||
import {
|
||||
acceptInviteById,
|
||||
createTestingApp,
|
||||
createWorkspace,
|
||||
getWorkspace,
|
||||
initFeatureConfigs,
|
||||
inviteUser,
|
||||
leaveWorkspace,
|
||||
revokeUser,
|
||||
@@ -31,36 +29,13 @@ const test = ava as TestFn<{
|
||||
}>;
|
||||
|
||||
test.beforeEach(async t => {
|
||||
const client = new PrismaClient();
|
||||
t.context.client = client;
|
||||
await client.$connect();
|
||||
await client.user.deleteMany({});
|
||||
await client.snapshot.deleteMany({});
|
||||
await client.update.deleteMany({});
|
||||
await client.workspace.deleteMany({});
|
||||
await client.$disconnect();
|
||||
const module = await Test.createTestingModule({
|
||||
const { app } = await createTestingApp({
|
||||
imports: [AppModule],
|
||||
providers: [RevertCommand, RunCommand],
|
||||
}).compile();
|
||||
const app = module.createNestApplication();
|
||||
app.use(
|
||||
graphqlUploadExpress({
|
||||
maxFileSize: 10 * 1024 * 1024,
|
||||
maxFiles: 5,
|
||||
})
|
||||
);
|
||||
await app.init();
|
||||
|
||||
const auth = module.get(AuthService);
|
||||
const mail = module.get(MailService);
|
||||
|
||||
});
|
||||
t.context.app = app;
|
||||
t.context.auth = auth;
|
||||
t.context.mail = mail;
|
||||
|
||||
// init features
|
||||
await initFeatureConfigs(module);
|
||||
t.context.client = app.get(PrismaService);
|
||||
t.context.auth = app.get(AuthService);
|
||||
t.context.mail = app.get(MailService);
|
||||
});
|
||||
|
||||
test.afterEach.always(async t => {
|
||||
|
||||
@@ -1,19 +1,17 @@
|
||||
import type { INestApplication } from '@nestjs/common';
|
||||
import { Test } from '@nestjs/testing';
|
||||
import { PrismaClient } from '@prisma/client';
|
||||
import ava, { type TestFn } from 'ava';
|
||||
import graphqlUploadExpress from 'graphql-upload/graphqlUploadExpress.mjs';
|
||||
import request from 'supertest';
|
||||
|
||||
import { AppModule } from '../src/app';
|
||||
import { RevertCommand, RunCommand } from '../src/data/commands/run';
|
||||
import { PrismaService } from '../src/prisma';
|
||||
import {
|
||||
acceptInviteById,
|
||||
createTestingApp,
|
||||
createWorkspace,
|
||||
currentUser,
|
||||
getPublicWorkspace,
|
||||
getWorkspacePublicPages,
|
||||
initFeatureConfigs,
|
||||
inviteUser,
|
||||
publishPage,
|
||||
revokePublicPage,
|
||||
@@ -27,30 +25,12 @@ const test = ava as TestFn<{
|
||||
}>;
|
||||
|
||||
test.beforeEach(async t => {
|
||||
const client = new PrismaClient();
|
||||
await client.$connect();
|
||||
await client.user.deleteMany({});
|
||||
await client.update.deleteMany({});
|
||||
await client.snapshot.deleteMany({});
|
||||
await client.workspace.deleteMany({});
|
||||
await client.$disconnect();
|
||||
const module = await Test.createTestingModule({
|
||||
const { app } = await createTestingApp({
|
||||
imports: [AppModule],
|
||||
providers: [RevertCommand, RunCommand],
|
||||
}).compile();
|
||||
const app = module.createNestApplication();
|
||||
app.use(
|
||||
graphqlUploadExpress({
|
||||
maxFileSize: 10 * 1024 * 1024,
|
||||
maxFiles: 5,
|
||||
})
|
||||
);
|
||||
await app.init();
|
||||
t.context.client = client;
|
||||
t.context.app = app;
|
||||
});
|
||||
|
||||
// init features
|
||||
await initFeatureConfigs(module);
|
||||
t.context.client = app.get(PrismaService);
|
||||
t.context.app = app;
|
||||
});
|
||||
|
||||
test.afterEach.always(async t => {
|
||||
|
||||
Reference in New Issue
Block a user