2023-04-19 02:14:25 +03:00
|
|
|
import { equal, ok } from 'node:assert';
|
|
|
|
import { afterEach, beforeEach, describe, test } from 'node:test';
|
|
|
|
|
2023-06-21 09:08:32 +03:00
|
|
|
import { Transformer } from '@napi-rs/image';
|
2023-06-08 20:42:58 +03:00
|
|
|
import type { INestApplication } from '@nestjs/common';
|
2023-04-19 02:14:25 +03:00
|
|
|
import { Test } from '@nestjs/testing';
|
2023-06-21 09:08:32 +03:00
|
|
|
import { hash } from '@node-rs/argon2';
|
2023-04-28 06:49:44 +03:00
|
|
|
import { PrismaClient } from '@prisma/client';
|
2023-06-21 09:08:32 +03:00
|
|
|
import { Express } from 'express';
|
|
|
|
// @ts-expect-error graphql-upload is not typed
|
|
|
|
import graphqlUploadExpress from 'graphql-upload/graphqlUploadExpress.mjs';
|
2023-04-19 02:14:25 +03:00
|
|
|
import request from 'supertest';
|
|
|
|
|
|
|
|
import { AppModule } from '../app';
|
|
|
|
import { getDefaultAFFiNEConfig } from '../config/default';
|
|
|
|
|
|
|
|
const gql = '/graphql';
|
|
|
|
|
|
|
|
globalThis.AFFiNE = getDefaultAFFiNEConfig();
|
|
|
|
|
|
|
|
describe('AppModule', () => {
|
|
|
|
let app: INestApplication;
|
|
|
|
|
2023-04-28 06:49:44 +03:00
|
|
|
// cleanup database before each test
|
|
|
|
beforeEach(async () => {
|
|
|
|
const client = new PrismaClient();
|
|
|
|
await client.$connect();
|
|
|
|
await client.user.deleteMany({});
|
|
|
|
await client.user.create({
|
|
|
|
data: {
|
|
|
|
name: 'Alex Yang',
|
|
|
|
email: 'alex.yang@example.org',
|
2023-05-12 21:48:38 +03:00
|
|
|
password: await hash('123456'),
|
2023-04-28 06:49:44 +03:00
|
|
|
},
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2023-04-19 02:14:25 +03:00
|
|
|
beforeEach(async () => {
|
|
|
|
const module = await Test.createTestingModule({
|
|
|
|
imports: [AppModule],
|
|
|
|
}).compile();
|
2023-06-21 09:08:32 +03:00
|
|
|
app = module.createNestApplication({
|
|
|
|
cors: true,
|
|
|
|
bodyParser: true,
|
|
|
|
});
|
|
|
|
app.use(
|
|
|
|
graphqlUploadExpress({
|
|
|
|
maxFileSize: 10 * 1024 * 1024,
|
|
|
|
maxFiles: 5,
|
|
|
|
})
|
|
|
|
);
|
2023-04-19 02:14:25 +03:00
|
|
|
await app.init();
|
|
|
|
});
|
|
|
|
|
|
|
|
afterEach(async () => {
|
|
|
|
await app.close();
|
|
|
|
});
|
|
|
|
|
|
|
|
test('should init app', async () => {
|
|
|
|
ok(typeof app === 'object');
|
|
|
|
await request(app.getHttpServer())
|
|
|
|
.post(gql)
|
|
|
|
.send({
|
|
|
|
query: `
|
2023-04-28 02:02:05 +03:00
|
|
|
query {
|
|
|
|
error
|
|
|
|
}
|
|
|
|
`,
|
2023-04-19 02:14:25 +03:00
|
|
|
})
|
|
|
|
.expect(400);
|
2023-04-28 02:02:05 +03:00
|
|
|
|
2023-06-21 09:08:32 +03:00
|
|
|
const { token } = await createToken(app);
|
2023-04-28 02:02:05 +03:00
|
|
|
|
|
|
|
await request(app.getHttpServer())
|
|
|
|
.post(gql)
|
2023-06-21 09:08:32 +03:00
|
|
|
.auth(token, { type: 'bearer' })
|
2023-04-19 02:14:25 +03:00
|
|
|
.send({
|
|
|
|
query: `
|
|
|
|
mutation {
|
|
|
|
createWorkspace {
|
|
|
|
id
|
|
|
|
public
|
2023-04-28 02:02:05 +03:00
|
|
|
createdAt
|
2023-04-19 02:14:25 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
`,
|
|
|
|
})
|
|
|
|
.expect(200)
|
|
|
|
.expect(res => {
|
|
|
|
ok(
|
|
|
|
typeof res.body.data.createWorkspace === 'object',
|
|
|
|
'res.body.data.createWorkspace is not an object'
|
|
|
|
);
|
|
|
|
ok(
|
|
|
|
typeof res.body.data.createWorkspace.id === 'string',
|
|
|
|
'res.body.data.createWorkspace.id is not a string'
|
|
|
|
);
|
|
|
|
ok(
|
|
|
|
typeof res.body.data.createWorkspace.public === 'boolean',
|
|
|
|
'res.body.data.createWorkspace.public is not a boolean'
|
|
|
|
);
|
|
|
|
ok(
|
2023-04-28 02:02:05 +03:00
|
|
|
typeof res.body.data.createWorkspace.createdAt === 'string',
|
2023-04-19 02:14:25 +03:00
|
|
|
'res.body.data.createWorkspace.created_at is not a string'
|
|
|
|
);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
test('should find default user', async () => {
|
2023-06-21 09:08:32 +03:00
|
|
|
const { token } = await createToken(app);
|
2023-04-19 02:14:25 +03:00
|
|
|
await request(app.getHttpServer())
|
|
|
|
.post(gql)
|
2023-06-21 09:08:32 +03:00
|
|
|
.auth(token, { type: 'bearer' })
|
2023-04-19 02:14:25 +03:00
|
|
|
.send({
|
|
|
|
query: `
|
|
|
|
query {
|
|
|
|
user(email: "alex.yang@example.org") {
|
|
|
|
email
|
2023-04-28 02:02:05 +03:00
|
|
|
avatarUrl
|
2023-04-19 02:14:25 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
`,
|
|
|
|
})
|
|
|
|
.expect(200)
|
|
|
|
.expect(res => {
|
|
|
|
equal(res.body.data.user.email, 'alex.yang@example.org');
|
|
|
|
});
|
|
|
|
});
|
2023-06-21 09:08:32 +03:00
|
|
|
|
|
|
|
test('should be able to upload avatar', async () => {
|
|
|
|
const { token, id } = await createToken(app);
|
|
|
|
const png = await Transformer.fromRgbaPixels(
|
|
|
|
Buffer.alloc(400 * 400 * 4).fill(255),
|
|
|
|
400,
|
|
|
|
400
|
|
|
|
).png();
|
|
|
|
|
|
|
|
await request(app.getHttpServer())
|
|
|
|
.post(gql)
|
|
|
|
.auth(token, { type: 'bearer' })
|
|
|
|
.field(
|
|
|
|
'operations',
|
|
|
|
JSON.stringify({
|
|
|
|
name: 'uploadAvatar',
|
|
|
|
query: `mutation uploadAvatar($id: String!, $avatar: Upload!) {
|
|
|
|
uploadAvatar(id: $id, avatar: $avatar) {
|
|
|
|
id
|
|
|
|
name
|
|
|
|
avatarUrl
|
|
|
|
email
|
|
|
|
}
|
|
|
|
}
|
|
|
|
`,
|
|
|
|
variables: { id, avatar: null },
|
|
|
|
})
|
|
|
|
)
|
|
|
|
|
|
|
|
.field('map', JSON.stringify({ '0': ['variables.avatar'] }))
|
|
|
|
.attach('0', png, 'avatar.png')
|
|
|
|
.expect(200)
|
|
|
|
.expect(res => {
|
|
|
|
equal(res.body.data.uploadAvatar.id, id);
|
|
|
|
});
|
|
|
|
});
|
2023-04-19 02:14:25 +03:00
|
|
|
});
|
2023-06-21 09:08:32 +03:00
|
|
|
|
|
|
|
async function createToken(app: INestApplication<Express>): Promise<{
|
|
|
|
id: string;
|
|
|
|
token: string;
|
|
|
|
}> {
|
|
|
|
let token;
|
|
|
|
let id;
|
|
|
|
await request(app.getHttpServer())
|
|
|
|
.post(gql)
|
|
|
|
.send({
|
|
|
|
query: `
|
|
|
|
mutation {
|
|
|
|
signIn(email: "alex.yang@example.org", password: "123456") {
|
|
|
|
id
|
|
|
|
token {
|
|
|
|
token
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
`,
|
|
|
|
})
|
|
|
|
.expect(200)
|
|
|
|
.expect(res => {
|
|
|
|
id = res.body.data.signIn.id;
|
|
|
|
ok(
|
|
|
|
typeof res.body.data.signIn.token.token === 'string',
|
|
|
|
'res.body.data.signIn.token.token is not a string'
|
|
|
|
);
|
|
|
|
token = res.body.data.signIn.token.token;
|
|
|
|
});
|
|
|
|
return { token: token!, id: id! };
|
|
|
|
}
|