mirror of
https://github.com/toeverything/AFFiNE.git
synced 2024-12-24 20:41:49 +03:00
test(server): use mock PrismaService in tests (#4101)
This commit is contained in:
parent
3d5e1d2f3d
commit
dfa5fefa7f
@ -1,10 +1,11 @@
|
||||
import { equal, ok } from 'node:assert';
|
||||
import { ok } from 'node:assert';
|
||||
import { randomUUID } from 'node:crypto';
|
||||
|
||||
import { Transformer } from '@napi-rs/image';
|
||||
import type { INestApplication } from '@nestjs/common';
|
||||
import { Test } from '@nestjs/testing';
|
||||
import { hash } from '@node-rs/argon2';
|
||||
import { PrismaClient } from '@prisma/client';
|
||||
import { hashSync } from '@node-rs/argon2';
|
||||
import { User } from '@prisma/client';
|
||||
import test from 'ava';
|
||||
import { Express } from 'express';
|
||||
// @ts-expect-error graphql-upload is not typed
|
||||
@ -12,30 +13,46 @@ import graphqlUploadExpress from 'graphql-upload/graphqlUploadExpress.mjs';
|
||||
import request from 'supertest';
|
||||
|
||||
import { AppModule } from '../app';
|
||||
import { PrismaService } from '../prisma/service';
|
||||
|
||||
const gql = '/graphql';
|
||||
|
||||
let app: INestApplication;
|
||||
|
||||
// cleanup database before each test
|
||||
test.beforeEach(async () => {
|
||||
const client = new PrismaClient();
|
||||
await client.$connect();
|
||||
await client.user.deleteMany({});
|
||||
await client.user.create({
|
||||
data: {
|
||||
class FakePrisma {
|
||||
fakeUser: User = {
|
||||
id: randomUUID(),
|
||||
name: 'Alex Yang',
|
||||
avatarUrl: '',
|
||||
email: 'alex.yang@example.org',
|
||||
password: await hash('123456'),
|
||||
password: hashSync('123456'),
|
||||
emailVerified: new Date(),
|
||||
createdAt: new Date(),
|
||||
};
|
||||
get user() {
|
||||
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
||||
const prisma = this;
|
||||
return {
|
||||
async findFirst() {
|
||||
return prisma.fakeUser;
|
||||
},
|
||||
});
|
||||
await client.$disconnect();
|
||||
});
|
||||
async findUnique() {
|
||||
return this.findFirst();
|
||||
},
|
||||
async update() {
|
||||
return this.findFirst();
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
test.beforeEach(async () => {
|
||||
const module = await Test.createTestingModule({
|
||||
imports: [AppModule],
|
||||
}).compile();
|
||||
})
|
||||
.overrideProvider(PrismaService)
|
||||
.useClass(FakePrisma)
|
||||
.compile();
|
||||
app = module.createNestApplication({
|
||||
cors: true,
|
||||
bodyParser: true,
|
||||
@ -53,8 +70,8 @@ test.afterEach(async () => {
|
||||
await app.close();
|
||||
});
|
||||
|
||||
test('should init app', async () => {
|
||||
ok(typeof app === 'object');
|
||||
test('should init app', async t => {
|
||||
t.is(typeof app, 'object');
|
||||
await request(app.getHttpServer())
|
||||
.post(gql)
|
||||
.send({
|
||||
@ -80,11 +97,11 @@ test('should init app', async () => {
|
||||
})
|
||||
.expect(200)
|
||||
.expect(res => {
|
||||
ok(res.body.data.__typename === 'Query');
|
||||
t.is(res.body.data.__typename, 'Query');
|
||||
});
|
||||
});
|
||||
|
||||
test('should find default user', async () => {
|
||||
test('should find default user', async t => {
|
||||
const { token } = await createToken(app);
|
||||
await request(app.getHttpServer())
|
||||
.post(gql)
|
||||
@ -101,11 +118,11 @@ test('should find default user', async () => {
|
||||
})
|
||||
.expect(200)
|
||||
.expect(res => {
|
||||
equal(res.body.data.user.email, 'alex.yang@example.org');
|
||||
t.is(res.body.data.user.email, 'alex.yang@example.org');
|
||||
});
|
||||
});
|
||||
|
||||
test('should be able to upload avatar', async () => {
|
||||
test('should be able to upload avatar', async t => {
|
||||
const { token, id } = await createToken(app);
|
||||
const png = await Transformer.fromRgbaPixels(
|
||||
Buffer.alloc(400 * 400 * 4).fill(255),
|
||||
@ -136,7 +153,7 @@ test('should be able to upload avatar', async () => {
|
||||
.attach('0', png, 'avatar.png')
|
||||
.expect(200)
|
||||
.expect(res => {
|
||||
equal(res.body.data.uploadAvatar.id, id);
|
||||
t.is(res.body.data.uploadAvatar.id, id);
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -1,6 +1,4 @@
|
||||
/// <reference types="../global.d.ts" />
|
||||
import { equal } from 'node:assert';
|
||||
|
||||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { PrismaClient } from '@prisma/client';
|
||||
import test from 'ava';
|
||||
@ -69,20 +67,19 @@ test('should be able to verify', async t => {
|
||||
{
|
||||
const token = await auth.sign(user);
|
||||
const claim = await auth.verify(token);
|
||||
equal(claim.id, '1');
|
||||
equal(claim.name, 'Alex Yang');
|
||||
equal(claim.email, 'alexyang@example.org');
|
||||
equal(claim.emailVerified?.toISOString(), date.toISOString());
|
||||
equal(claim.createdAt.toISOString(), date.toISOString());
|
||||
t.is(claim.id, '1');
|
||||
t.is(claim.name, 'Alex Yang');
|
||||
t.is(claim.email, 'alexyang@example.org');
|
||||
t.is(claim.emailVerified?.toISOString(), date.toISOString());
|
||||
t.is(claim.createdAt.toISOString(), date.toISOString());
|
||||
}
|
||||
{
|
||||
const token = await auth.refresh(user);
|
||||
const claim = await auth.verify(token);
|
||||
equal(claim.id, '1');
|
||||
equal(claim.name, 'Alex Yang');
|
||||
equal(claim.email, 'alexyang@example.org');
|
||||
equal(claim.emailVerified?.toISOString(), date.toISOString());
|
||||
equal(claim.createdAt.toISOString(), date.toISOString());
|
||||
t.is(claim.id, '1');
|
||||
t.is(claim.name, 'Alex Yang');
|
||||
t.is(claim.email, 'alexyang@example.org');
|
||||
t.is(claim.emailVerified?.toISOString(), date.toISOString());
|
||||
t.is(claim.createdAt.toISOString(), date.toISOString());
|
||||
}
|
||||
t.pass();
|
||||
});
|
||||
|
@ -1,5 +1,3 @@
|
||||
import { ok } from 'node:assert';
|
||||
|
||||
import { Test } from '@nestjs/testing';
|
||||
import test from 'ava';
|
||||
|
||||
@ -28,6 +26,5 @@ test('should be able to override config', async t => {
|
||||
}).compile();
|
||||
const config = module.get(Config);
|
||||
|
||||
ok(config.host, 'testing');
|
||||
t.pass();
|
||||
t.is(config.host, 'testing');
|
||||
});
|
||||
|
@ -1,4 +1,3 @@
|
||||
import { deepEqual, equal, ok } from 'node:assert';
|
||||
import { mock } from 'node:test';
|
||||
|
||||
import { INestApplication } from '@nestjs/common';
|
||||
@ -54,10 +53,9 @@ test('should setup update poll interval', async t => {
|
||||
|
||||
await m.createNestApplication().init();
|
||||
|
||||
equal(fake.mock.callCount(), 1);
|
||||
t.is(fake.mock.callCount(), 1);
|
||||
// @ts-expect-error private member
|
||||
ok(manager.job);
|
||||
t.pass();
|
||||
t.truthy(manager.job);
|
||||
});
|
||||
|
||||
test('should be able to stop poll', async t => {
|
||||
@ -66,10 +64,9 @@ test('should be able to stop poll', async t => {
|
||||
|
||||
await app.close();
|
||||
|
||||
equal(fake.mock.callCount(), 1);
|
||||
t.is(fake.mock.callCount(), 1);
|
||||
// @ts-expect-error private member
|
||||
equal(manager.job, null);
|
||||
t.pass();
|
||||
t.is(manager.job, null);
|
||||
});
|
||||
|
||||
test('should poll when intervel due', async t => {
|
||||
@ -84,22 +81,21 @@ test('should poll when intervel due', async t => {
|
||||
});
|
||||
|
||||
timer.tick(interval);
|
||||
equal(fake.mock.callCount(), 1);
|
||||
t.is(fake.mock.callCount(), 1);
|
||||
|
||||
// busy
|
||||
timer.tick(interval);
|
||||
// @ts-expect-error private member
|
||||
equal(manager.busy, true);
|
||||
equal(fake.mock.callCount(), 1);
|
||||
t.is(manager.busy, true);
|
||||
t.is(fake.mock.callCount(), 1);
|
||||
|
||||
resolve();
|
||||
await timer.tickAsync(1);
|
||||
|
||||
// @ts-expect-error private member
|
||||
equal(manager.busy, false);
|
||||
t.is(manager.busy, false);
|
||||
timer.tick(interval);
|
||||
equal(fake.mock.callCount(), 2);
|
||||
t.pass();
|
||||
t.is(fake.mock.callCount(), 2);
|
||||
});
|
||||
|
||||
test('should merge update when intervel due', async t => {
|
||||
@ -135,7 +131,10 @@ test('should merge update when intervel due', async t => {
|
||||
|
||||
await manager.apply();
|
||||
|
||||
deepEqual(await manager.getLatestUpdate(ws.id, '1'), update);
|
||||
t.deepEqual(
|
||||
(await manager.getLatestUpdate(ws.id, '1'))?.toString('hex'),
|
||||
Buffer.from(update.buffer).toString('hex')
|
||||
);
|
||||
|
||||
let appendUpdate = Buffer.from([]);
|
||||
doc.on('update', update => {
|
||||
@ -153,9 +152,8 @@ test('should merge update when intervel due', async t => {
|
||||
|
||||
await manager.apply();
|
||||
|
||||
deepEqual(
|
||||
await manager.getLatestUpdate(ws.id, '1'),
|
||||
encodeStateAsUpdate(doc)
|
||||
t.deepEqual(
|
||||
(await manager.getLatestUpdate(ws.id, '1'))?.toString('hex'),
|
||||
Buffer.from(encodeStateAsUpdate(doc)).toString('hex')
|
||||
);
|
||||
t.pass();
|
||||
});
|
||||
|
@ -1,36 +1,107 @@
|
||||
import { ok } from 'node:assert';
|
||||
import { randomUUID } from 'node:crypto';
|
||||
|
||||
import type { INestApplication } from '@nestjs/common';
|
||||
import { Test } from '@nestjs/testing';
|
||||
import { PrismaClient } from '@prisma/client';
|
||||
import { hashSync } from '@node-rs/argon2';
|
||||
import { User } from '@prisma/client';
|
||||
import test from 'ava';
|
||||
// @ts-expect-error graphql-upload is not typed
|
||||
import graphqlUploadExpress from 'graphql-upload/graphqlUploadExpress.mjs';
|
||||
|
||||
import { AppModule } from '../app';
|
||||
import { MailService } from '../modules/auth/mailer';
|
||||
import { PrismaService } from '../prisma';
|
||||
import { createWorkspace, getInviteInfo, inviteUser, signUp } from './utils';
|
||||
|
||||
let app: INestApplication;
|
||||
|
||||
const client = new PrismaClient();
|
||||
|
||||
let mail: MailService;
|
||||
|
||||
// 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();
|
||||
});
|
||||
const FakePrisma = {
|
||||
fakeUser: {
|
||||
id: randomUUID(),
|
||||
name: 'Alex Yang',
|
||||
avatarUrl: '',
|
||||
email: 'alex.yang@example.org',
|
||||
password: hashSync('123456'),
|
||||
emailVerified: new Date(),
|
||||
createdAt: new Date(),
|
||||
} satisfies User,
|
||||
|
||||
get user() {
|
||||
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
||||
const prisma = this;
|
||||
return {
|
||||
async findFirst() {
|
||||
return null;
|
||||
},
|
||||
async create({ data }: any) {
|
||||
return {
|
||||
...prisma.fakeUser,
|
||||
...data,
|
||||
};
|
||||
},
|
||||
async findUnique() {
|
||||
return prisma.fakeUser;
|
||||
},
|
||||
};
|
||||
},
|
||||
get workspace() {
|
||||
return {
|
||||
id: randomUUID(),
|
||||
async create({ data }: any) {
|
||||
return {
|
||||
id: this.id,
|
||||
public: data.public ?? false,
|
||||
createdAt: new Date(),
|
||||
};
|
||||
},
|
||||
};
|
||||
},
|
||||
snapshot: {
|
||||
id: randomUUID(),
|
||||
async create() {},
|
||||
async findFirstOrThrow() {
|
||||
return { id: this.id, blob: Buffer.from([0, 0]) };
|
||||
},
|
||||
},
|
||||
get userWorkspacePermission() {
|
||||
return {
|
||||
id: randomUUID(),
|
||||
prisma: this,
|
||||
async count() {
|
||||
return 1;
|
||||
},
|
||||
async create() {
|
||||
return { id: this.id };
|
||||
},
|
||||
async findUniqueOrThrow() {
|
||||
return { id: this.id, workspaceId: this.prisma.workspace.id };
|
||||
},
|
||||
async findFirst() {
|
||||
return { id: this.id };
|
||||
},
|
||||
async findFirstOrThrow() {
|
||||
return { id: this.id, user: this.prisma.fakeUser };
|
||||
},
|
||||
async userWorkspacePermission() {
|
||||
return {
|
||||
id: randomUUID(),
|
||||
createdAt: new Date(),
|
||||
};
|
||||
},
|
||||
};
|
||||
},
|
||||
};
|
||||
|
||||
test.beforeEach(async () => {
|
||||
const module = await Test.createTestingModule({
|
||||
imports: [AppModule],
|
||||
}).compile();
|
||||
})
|
||||
.overrideProvider(PrismaService)
|
||||
.useValue(FakePrisma)
|
||||
.compile();
|
||||
app = module.createNestApplication();
|
||||
app.use(
|
||||
graphqlUploadExpress({
|
||||
|
@ -1,5 +1,3 @@
|
||||
import { ok } from 'node:assert';
|
||||
|
||||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import test from 'ava';
|
||||
import { register } from 'prom-client';
|
||||
@ -27,10 +25,10 @@ test('should be able to increment counter', async t => {
|
||||
metrics.socketIOEventCounter(1, { event: 'client-handshake' });
|
||||
const socketIOCounterMetric =
|
||||
await register.getSingleMetric('socket_io_counter');
|
||||
ok(socketIOCounterMetric);
|
||||
t.truthy(socketIOCounterMetric);
|
||||
|
||||
ok(
|
||||
JSON.stringify((await socketIOCounterMetric.get()).values) ===
|
||||
t.truthy(
|
||||
JSON.stringify((await socketIOCounterMetric!.get()).values) ===
|
||||
'[{"value":1,"labels":{"event":"client-handshake"}}]'
|
||||
);
|
||||
t.pass();
|
||||
@ -58,20 +56,20 @@ test('should be able to timer', async t => {
|
||||
}
|
||||
|
||||
const socketIOTimerMetric = register.getSingleMetric('socket_io_timer');
|
||||
ok(socketIOTimerMetric);
|
||||
t.truthy(socketIOTimerMetric);
|
||||
|
||||
const observations = (await socketIOTimerMetric.get()).values;
|
||||
const observations = (await socketIOTimerMetric!.get()).values;
|
||||
|
||||
for (const observation of observations) {
|
||||
if (
|
||||
observation.labels.event === 'client-handshake' &&
|
||||
'quantile' in observation.labels
|
||||
) {
|
||||
ok(
|
||||
t.truthy(
|
||||
observation.value >= minimum / 1000,
|
||||
'observation.value should be greater than minimum'
|
||||
);
|
||||
ok(
|
||||
t.truthy(
|
||||
observation.value <= maximum / 1000,
|
||||
'observation.value should be less than maximum'
|
||||
);
|
||||
|
@ -1,5 +1,4 @@
|
||||
/// <reference types="../global.d.ts" />
|
||||
import { equal } from 'node:assert';
|
||||
|
||||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { PrismaClient } from '@prisma/client';
|
||||
@ -31,14 +30,12 @@ test.afterEach(async () => {
|
||||
|
||||
test('should be able to set session', async t => {
|
||||
await session.set('test', 'value');
|
||||
equal(await session.get('test'), 'value');
|
||||
t.pass();
|
||||
t.is(await session.get('test'), 'value');
|
||||
});
|
||||
|
||||
test('should be expired by ttl', async t => {
|
||||
await session.set('test', 'value', 100);
|
||||
equal(await session.get('test'), 'value');
|
||||
t.is(await session.get('test'), 'value');
|
||||
await new Promise(resolve => setTimeout(resolve, 500));
|
||||
equal(await session.get('test'), undefined);
|
||||
t.pass();
|
||||
t.is(await session.get('test'), undefined);
|
||||
});
|
||||
|
@ -1,5 +1,3 @@
|
||||
import { ok, rejects } from 'node:assert';
|
||||
|
||||
import type { INestApplication } from '@nestjs/common';
|
||||
import { Test } from '@nestjs/testing';
|
||||
import { PrismaClient } from '@prisma/client';
|
||||
@ -41,20 +39,18 @@ test.afterEach(async () => {
|
||||
|
||||
test('should register a user', async t => {
|
||||
const user = await signUp(app, 'u1', 'u1@affine.pro', '123456');
|
||||
ok(typeof user.id === 'string', 'user.id is not a string');
|
||||
ok(user.name === 'u1', 'user.name is not valid');
|
||||
ok(user.email === 'u1@affine.pro', 'user.email is not valid');
|
||||
t.pass();
|
||||
t.is(typeof user.id, 'string', 'user.id is not a string');
|
||||
t.is(user.name, 'u1', 'user.name is not valid');
|
||||
t.is(user.email, 'u1@affine.pro', 'user.email is not valid');
|
||||
});
|
||||
|
||||
test('should get current user', async t => {
|
||||
const user = await signUp(app, 'u1', 'u1@affine.pro', '123456');
|
||||
const currUser = await currentUser(app, user.token.token);
|
||||
ok(currUser.id === user.id, 'user.id is not valid');
|
||||
ok(currUser.name === user.name, 'user.name is not valid');
|
||||
ok(currUser.email === user.email, 'user.email is not valid');
|
||||
ok(currUser.hasPassword, 'currUser.hasPassword is not valid');
|
||||
t.pass();
|
||||
t.is(currUser.id, user.id, 'user.id is not valid');
|
||||
t.is(currUser.name, user.name, 'user.name is not valid');
|
||||
t.is(currUser.email, user.email, 'user.email is not valid');
|
||||
t.true(currUser.hasPassword, 'currUser.hasPassword is not valid');
|
||||
});
|
||||
|
||||
test('should be able to delete user', async t => {
|
||||
@ -72,6 +68,6 @@ test('should be able to delete user', async t => {
|
||||
`,
|
||||
})
|
||||
.expect(200);
|
||||
await rejects(currentUser(app, user.token.token));
|
||||
await t.throwsAsync(() => currentUser(app, user.token.token));
|
||||
t.pass();
|
||||
});
|
||||
|
@ -1,5 +1,3 @@
|
||||
import { deepEqual, ok } from 'node:assert';
|
||||
|
||||
import type { INestApplication } from '@nestjs/common';
|
||||
import { Test } from '@nestjs/testing';
|
||||
import { PrismaClient } from '@prisma/client';
|
||||
@ -67,15 +65,14 @@ test('should set blobs', async t => {
|
||||
.auth(u1.token.token, { type: 'bearer' })
|
||||
.buffer();
|
||||
|
||||
deepEqual(response1.body, buffer1, 'failed to get blob');
|
||||
t.deepEqual(response1.body, buffer1, 'failed to get blob');
|
||||
|
||||
const response2 = await request(server)
|
||||
.get(`/api/workspaces/${workspace.id}/blobs/${hash2}`)
|
||||
.auth(u1.token.token, { type: 'bearer' })
|
||||
.buffer();
|
||||
|
||||
deepEqual(response2.body, buffer2, 'failed to get blob');
|
||||
t.pass();
|
||||
t.deepEqual(response2.body, buffer2, 'failed to get blob');
|
||||
});
|
||||
|
||||
test('should list blobs', async t => {
|
||||
@ -83,7 +80,7 @@ test('should list blobs', async t => {
|
||||
|
||||
const workspace = await createWorkspace(app, u1.token.token);
|
||||
const blobs = await listBlobs(app, u1.token.token, workspace.id);
|
||||
ok(blobs.length === 0, 'failed to list blobs');
|
||||
t.is(blobs.length, 0, 'failed to list blobs');
|
||||
|
||||
const buffer1 = Buffer.from([0, 0]);
|
||||
const hash1 = await setBlob(app, u1.token.token, workspace.id, buffer1);
|
||||
@ -91,10 +88,9 @@ test('should list blobs', async t => {
|
||||
const hash2 = await setBlob(app, u1.token.token, workspace.id, buffer2);
|
||||
|
||||
const ret = await listBlobs(app, u1.token.token, workspace.id);
|
||||
ok(ret.length === 2, 'failed to list blobs');
|
||||
ok(ret[0] === hash1, 'failed to list blobs');
|
||||
ok(ret[1] === hash2, 'failed to list blobs');
|
||||
t.pass();
|
||||
t.is(ret.length, 2, 'failed to list blobs');
|
||||
t.is(ret[0], hash1, 'failed to list blobs');
|
||||
t.is(ret[1], hash2, 'failed to list blobs');
|
||||
});
|
||||
|
||||
test('should calc blobs size', async t => {
|
||||
@ -108,8 +104,7 @@ test('should calc blobs size', async t => {
|
||||
await setBlob(app, u1.token.token, workspace.id, buffer2);
|
||||
|
||||
const size = await collectBlobSizes(app, u1.token.token, workspace.id);
|
||||
ok(size === 4, 'failed to collect blob sizes');
|
||||
t.pass();
|
||||
t.is(size, 4, 'failed to collect blob sizes');
|
||||
});
|
||||
|
||||
test('should calc all blobs size', async t => {
|
||||
@ -130,6 +125,5 @@ test('should calc all blobs size', async t => {
|
||||
await setBlob(app, u1.token.token, workspace2.id, buffer4);
|
||||
|
||||
const size = await collectAllBlobSizes(app, u1.token.token);
|
||||
ok(size === 8, 'failed to collect all blob sizes');
|
||||
t.pass();
|
||||
t.is(size, 8, 'failed to collect all blob sizes');
|
||||
});
|
||||
|
@ -1,5 +1,3 @@
|
||||
import { ok } from 'node:assert';
|
||||
|
||||
import type { INestApplication } from '@nestjs/common';
|
||||
import { Test } from '@nestjs/testing';
|
||||
import { PrismaClient } from '@prisma/client';
|
||||
@ -72,8 +70,7 @@ test('should invite a user', async t => {
|
||||
u2.email,
|
||||
'Admin'
|
||||
);
|
||||
ok(!!invite, 'failed to invite user');
|
||||
t.pass();
|
||||
t.truthy(invite, 'failed to invite user');
|
||||
});
|
||||
|
||||
test('should accept an invite', async t => {
|
||||
@ -84,13 +81,13 @@ test('should accept an invite', async t => {
|
||||
await inviteUser(app, u1.token.token, workspace.id, u2.email, 'Admin');
|
||||
|
||||
const accept = await acceptInvite(app, u2.token.token, workspace.id);
|
||||
ok(accept === true, 'failed to accept invite');
|
||||
t.is(accept, true, 'failed to accept invite');
|
||||
|
||||
const currWorkspace = await getWorkspace(app, u1.token.token, workspace.id);
|
||||
const currMember = currWorkspace.members.find(u => u.email === u2.email);
|
||||
ok(currMember !== undefined, 'failed to invite user');
|
||||
ok(currMember.id === u2.id, 'failed to invite user');
|
||||
ok(!currMember.accepted, 'failed to invite user');
|
||||
t.not(currMember, undefined, 'failed to invite user');
|
||||
t.is(currMember!.id, u2.id, 'failed to invite user');
|
||||
t.true(!currMember!.accepted, 'failed to invite user');
|
||||
t.pass();
|
||||
});
|
||||
|
||||
@ -103,8 +100,7 @@ test('should leave a workspace', async t => {
|
||||
await acceptInvite(app, u2.token.token, workspace.id);
|
||||
|
||||
const leave = await leaveWorkspace(app, u2.token.token, workspace.id);
|
||||
ok(leave === true, 'failed to leave workspace');
|
||||
t.pass();
|
||||
t.true(leave, 'failed to leave workspace');
|
||||
});
|
||||
|
||||
test('should revoke a user', async t => {
|
||||
@ -115,11 +111,10 @@ test('should revoke a user', async t => {
|
||||
await inviteUser(app, u1.token.token, workspace.id, u2.email, 'Admin');
|
||||
|
||||
const currWorkspace = await getWorkspace(app, u1.token.token, workspace.id);
|
||||
ok(currWorkspace.members.length === 2, 'failed to invite user');
|
||||
t.is(currWorkspace.members.length, 2, 'failed to invite user');
|
||||
|
||||
const revoke = await revokeUser(app, u1.token.token, workspace.id, u2.id);
|
||||
ok(revoke === true, 'failed to revoke user');
|
||||
t.pass();
|
||||
t.true(revoke, 'failed to revoke user');
|
||||
});
|
||||
|
||||
test('should create user if not exist', async t => {
|
||||
@ -130,9 +125,8 @@ test('should create user if not exist', async t => {
|
||||
await inviteUser(app, u1.token.token, workspace.id, 'u2@affine.pro', 'Admin');
|
||||
|
||||
const user = await auth.getUserByEmail('u2@affine.pro');
|
||||
ok(user !== undefined, 'failed to create user');
|
||||
ok(user?.name === 'Unnamed', 'failed to create user');
|
||||
t.pass();
|
||||
t.not(user, undefined, 'failed to create user');
|
||||
t.is(user?.name, 'Unnamed', 'failed to create user');
|
||||
});
|
||||
|
||||
test('should invite a user by link', async t => {
|
||||
@ -150,7 +144,7 @@ test('should invite a user by link', async t => {
|
||||
);
|
||||
|
||||
const accept = await acceptInviteById(app, workspace.id, invite);
|
||||
ok(accept === true, 'failed to accept invite');
|
||||
t.true(accept, 'failed to accept invite');
|
||||
|
||||
const invite1 = await inviteUser(
|
||||
app,
|
||||
@ -160,13 +154,12 @@ test('should invite a user by link', async t => {
|
||||
'Admin'
|
||||
);
|
||||
|
||||
ok(invite === invite1, 'repeat the invitation must return same id');
|
||||
t.is(invite, invite1, 'repeat the invitation must return same id');
|
||||
|
||||
const currWorkspace = await getWorkspace(app, u1.token.token, workspace.id);
|
||||
const currMember = currWorkspace.members.find(u => u.email === u2.email);
|
||||
ok(currMember !== undefined, 'failed to invite user');
|
||||
ok(currMember.inviteId === invite, 'failed to check invite id');
|
||||
t.pass();
|
||||
t.not(currMember, undefined, 'failed to invite user');
|
||||
t.is(currMember?.inviteId, invite, 'failed to check invite id');
|
||||
});
|
||||
|
||||
test('should send invite email', async t => {
|
||||
|
@ -1,5 +1,3 @@
|
||||
import { deepEqual, ok, rejects } from 'node:assert';
|
||||
|
||||
import type { INestApplication } from '@nestjs/common';
|
||||
import { Test } from '@nestjs/testing';
|
||||
import { PrismaClient } from '@prisma/client';
|
||||
@ -56,9 +54,9 @@ test.afterEach(async () => {
|
||||
|
||||
test('should register a user', async t => {
|
||||
const user = await signUp(app, 'u1', 'u1@affine.pro', '123456');
|
||||
t.true(typeof user.id === 'string', 'user.id is not a string');
|
||||
t.true(user.name === 'u1', 'user.name is not valid');
|
||||
t.true(user.email === 'u1@affine.pro', 'user.email is not valid');
|
||||
t.is(typeof user.id, 'string', 'user.id is not a string');
|
||||
t.is(user.name, 'u1', 'user.name is not valid');
|
||||
t.is(user.email, 'u1@affine.pro', 'user.email is not valid');
|
||||
});
|
||||
|
||||
test.skip('should be throttled at call signUp', async t => {
|
||||
@ -69,17 +67,15 @@ test.skip('should be throttled at call signUp', async t => {
|
||||
// throttles are applied to each endpoint separately
|
||||
await currentUser(app, token);
|
||||
}
|
||||
await rejects(signUp(app, 'u11', 'u11@affine.pro', '11'));
|
||||
await rejects(currentUser(app, token));
|
||||
t.pass();
|
||||
await t.throwsAsync(() => signUp(app, 'u11', 'u11@affine.pro', '11'));
|
||||
await t.throwsAsync(() => currentUser(app, token));
|
||||
});
|
||||
|
||||
test('should create a workspace', async t => {
|
||||
const user = await signUp(app, 'u1', 'u1@affine.pro', '1');
|
||||
|
||||
const workspace = await createWorkspace(app, user.token.token);
|
||||
ok(typeof workspace.id === 'string', 'workspace.id is not a string');
|
||||
t.pass();
|
||||
t.is(typeof workspace.id, 'string', 'workspace.id is not a string');
|
||||
});
|
||||
|
||||
test('should can publish workspace', async t => {
|
||||
@ -92,7 +88,7 @@ test('should can publish workspace', async t => {
|
||||
workspace.id,
|
||||
true
|
||||
);
|
||||
ok(isPublic === true, 'failed to publish workspace');
|
||||
t.true(isPublic, 'failed to publish workspace');
|
||||
|
||||
const isPrivate = await updateWorkspace(
|
||||
app,
|
||||
@ -100,28 +96,20 @@ test('should can publish workspace', async t => {
|
||||
workspace.id,
|
||||
false
|
||||
);
|
||||
ok(isPrivate === false, 'failed to unpublish workspace');
|
||||
t.pass();
|
||||
t.false(isPrivate, 'failed to unpublish workspace');
|
||||
});
|
||||
|
||||
test('should can read published workspace', async t => {
|
||||
const user = await signUp(app, 'u1', 'u1@affine.pro', '1');
|
||||
const workspace = await createWorkspace(app, user.token.token);
|
||||
|
||||
await rejects(
|
||||
getPublicWorkspace(app, 'not_exists_ws'),
|
||||
'must not get not exists workspace'
|
||||
);
|
||||
await rejects(
|
||||
getPublicWorkspace(app, workspace.id),
|
||||
'must not get private workspace'
|
||||
);
|
||||
await t.throwsAsync(() => getPublicWorkspace(app, 'not_exists_ws'));
|
||||
await t.throwsAsync(() => getPublicWorkspace(app, workspace.id));
|
||||
|
||||
await updateWorkspace(app, user.token.token, workspace.id, true);
|
||||
|
||||
const publicWorkspace = await getPublicWorkspace(app, workspace.id);
|
||||
ok(publicWorkspace.id === workspace.id, 'failed to get public workspace');
|
||||
t.pass();
|
||||
t.is(publicWorkspace.id, workspace.id, 'failed to get public workspace');
|
||||
});
|
||||
|
||||
test('should share a page', async t => {
|
||||
@ -131,46 +119,46 @@ test('should share a page', async t => {
|
||||
const workspace = await createWorkspace(app, u1.token.token);
|
||||
|
||||
const share = await sharePage(app, u1.token.token, workspace.id, 'page1');
|
||||
t.true(share === true, 'failed to share page');
|
||||
t.true(share, 'failed to share page');
|
||||
const pages = await getWorkspaceSharedPages(
|
||||
app,
|
||||
u1.token.token,
|
||||
workspace.id
|
||||
);
|
||||
t.true(pages.length === 1, 'failed to get shared pages');
|
||||
t.true(pages[0] === 'page1', 'failed to get shared page: page1');
|
||||
t.is(pages.length, 1, 'failed to get shared pages');
|
||||
t.is(pages[0], 'page1', 'failed to get shared page: page1');
|
||||
|
||||
const msg1 = await sharePage(app, u2.token.token, workspace.id, 'page2');
|
||||
t.true(msg1 === 'Permission denied', 'unauthorized user can share page');
|
||||
t.is(msg1, 'Permission denied', 'unauthorized user can share page');
|
||||
const msg2 = await revokePage(app, u2.token.token, 'not_exists_ws', 'page2');
|
||||
t.true(msg2 === 'Permission denied', 'unauthorized user can share page');
|
||||
t.is(msg2, 'Permission denied', 'unauthorized user can share page');
|
||||
|
||||
await inviteUser(app, u1.token.token, workspace.id, u2.email, 'Admin');
|
||||
await acceptInvite(app, u2.token.token, workspace.id);
|
||||
const invited = await sharePage(app, u2.token.token, workspace.id, 'page2');
|
||||
t.true(invited === true, 'failed to share page');
|
||||
t.true(invited, 'failed to share page');
|
||||
|
||||
const revoke = await revokePage(app, u1.token.token, workspace.id, 'page1');
|
||||
t.true(revoke === true, 'failed to revoke page');
|
||||
t.true(revoke, 'failed to revoke page');
|
||||
const pages2 = await getWorkspaceSharedPages(
|
||||
app,
|
||||
u1.token.token,
|
||||
workspace.id
|
||||
);
|
||||
t.true(pages2.length === 1, 'failed to get shared pages');
|
||||
t.true(pages2[0] === 'page2', 'failed to get shared page: page2');
|
||||
t.is(pages2.length, 1, 'failed to get shared pages');
|
||||
t.is(pages2[0], 'page2', 'failed to get shared page: page2');
|
||||
|
||||
const msg3 = await revokePage(app, u1.token.token, workspace.id, 'page3');
|
||||
t.true(msg3 === false, 'can revoke non-exists page');
|
||||
t.false(msg3, 'can revoke non-exists page');
|
||||
|
||||
const msg4 = await revokePage(app, u1.token.token, workspace.id, 'page2');
|
||||
t.true(msg4 === true, 'failed to revoke page');
|
||||
t.true(msg4, 'failed to revoke page');
|
||||
const page3 = await getWorkspaceSharedPages(
|
||||
app,
|
||||
u1.token.token,
|
||||
workspace.id
|
||||
);
|
||||
t.true(page3.length === 0, 'failed to get shared pages');
|
||||
t.is(page3.length, 0, 'failed to get shared pages');
|
||||
});
|
||||
|
||||
test('should can get workspace doc', async t => {
|
||||
@ -184,7 +172,11 @@ test('should can get workspace doc', async t => {
|
||||
.expect(200)
|
||||
.type('application/octet-stream');
|
||||
|
||||
deepEqual(res1.body, Buffer.from([0, 0]), 'failed to get doc with u1 token');
|
||||
t.deepEqual(
|
||||
res1.body,
|
||||
Buffer.from([0, 0]),
|
||||
'failed to get doc with u1 token'
|
||||
);
|
||||
|
||||
await request(app.getHttpServer())
|
||||
.get(`/api/workspaces/${workspace.id}/docs/${workspace.id}`)
|
||||
@ -207,8 +199,11 @@ test('should can get workspace doc', async t => {
|
||||
.expect(200)
|
||||
.type('application/octet-stream');
|
||||
|
||||
deepEqual(res2.body, Buffer.from([0, 0]), 'failed to get doc with u2 token');
|
||||
t.pass();
|
||||
t.deepEqual(
|
||||
res2.body,
|
||||
Buffer.from([0, 0]),
|
||||
'failed to get doc with u2 token'
|
||||
);
|
||||
});
|
||||
|
||||
test('should be able to get public workspace doc', async t => {
|
||||
@ -222,13 +217,12 @@ test('should be able to get public workspace doc', async t => {
|
||||
true
|
||||
);
|
||||
|
||||
ok(isPublic === true, 'failed to publish workspace');
|
||||
t.true(isPublic, 'failed to publish workspace');
|
||||
|
||||
const res = await request(app.getHttpServer())
|
||||
.get(`/api/workspaces/${workspace.id}/docs/${workspace.id}`)
|
||||
.expect(200)
|
||||
.type('application/octet-stream');
|
||||
|
||||
deepEqual(res.body, Buffer.from([0, 0]), 'failed to get public doc');
|
||||
t.pass();
|
||||
t.deepEqual(res.body, Buffer.from([0, 0]), 'failed to get public doc');
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user