feat(server): notification system (#10053)

closes CLOUD-52
This commit is contained in:
fengmk2
2025-03-06 15:25:05 +00:00
parent 81694a1144
commit 7302c4f954
20 changed files with 2356 additions and 14 deletions
@@ -1,5 +1,6 @@
export * from './blobs';
export * from './invite';
export * from './notification';
export * from './permission';
export * from './testing-app';
export * from './testing-module';
@@ -0,0 +1,86 @@
import { PaginationInput } from '../../base/graphql/pagination';
import type {
MentionInput,
PaginatedNotificationObjectType,
} from '../../core/notification/types';
import type { TestingApp } from './testing-app';
export async function listNotifications(
app: TestingApp,
pagination: PaginationInput
): Promise<PaginatedNotificationObjectType> {
const res = await app.gql(
`
query listNotifications($pagination: PaginationInput!) {
currentUser {
notifications(pagination: $pagination) {
totalCount
edges {
cursor
node {
id
type
level
read
createdAt
updatedAt
body
}
}
pageInfo {
startCursor
endCursor
hasNextPage
hasPreviousPage
}
}
}
}
`,
{ pagination }
);
return res.currentUser.notifications;
}
export async function getNotificationCount(app: TestingApp): Promise<number> {
const res = await app.gql(
`
query notificationCount {
currentUser {
notificationCount
}
}
`
);
return res.currentUser.notificationCount;
}
export async function mentionUser(
app: TestingApp,
input: MentionInput
): Promise<string> {
const res = await app.gql(
`
mutation mentionUser($input: MentionInput!) {
mentionUser(input: $input)
}
`,
{ input }
);
return res.mentionUser;
}
export async function readNotification(
app: TestingApp,
id: string
): Promise<boolean> {
const res = await app.gql(
`
mutation readNotification($id: String!) {
readNotification(id: $id)
}
`,
{ id }
);
return res.readNotification;
}
@@ -1,3 +1,5 @@
import { randomUUID } from 'node:crypto';
import { INestApplication, ModuleMetadata } from '@nestjs/common';
import type { NestExpressApplication } from '@nestjs/platform-express';
import { TestingModuleBuilder } from '@nestjs/testing';
@@ -182,12 +184,19 @@ export class TestingApp extends ApplyType<INestApplication>() {
return res.body.data;
}
async createUser(email: string, override?: Partial<User>): Promise<TestUser> {
private randomEmail() {
return `test-${randomUUID()}@affine.pro`;
}
async createUser(
email?: string,
override?: Partial<User>
): Promise<TestUser> {
const model = this.get(UserModel);
// TODO(@forehalo): model factories
// TestingData.user.create()
const user = await model.create({
email,
email: email ?? this.randomEmail(),
password: '1',
name: email,
emailVerifiedAt: new Date(),
@@ -200,8 +209,8 @@ export class TestingApp extends ApplyType<INestApplication>() {
return user as Omit<User, 'password'> & { password: string };
}
async signup(email: string, override?: Partial<User>) {
const user = await this.createUser(email, override);
async signup(email?: string, override?: Partial<User>) {
const user = await this.createUser(email ?? this.randomEmail(), override);
await this.login(user);
return user;
}