Skip to content

Commit

Permalink
Merge pull request #118 from zhumeisongsong/feature/get-all-tasks-use…
Browse files Browse the repository at this point in the history
…-case

feat: ✨ add GetAllTasksUseCase
  • Loading branch information
zhumeisongsong authored Dec 13, 2024
2 parents db7d0d8 + c81e7e5 commit db302a5
Show file tree
Hide file tree
Showing 24 changed files with 360 additions and 19 deletions.
1 change: 1 addition & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"cSpell.words": [
"compodoc",
"maxlength",
"nestjs",
"pnpx",
"supergraph"
Expand Down
4 changes: 3 additions & 1 deletion libs/tasks/application/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
export * from './lib/tasks.service';
export * from './lib/user-tasks.service';
export * from './lib/use-cases/get-all-tasks.use-case';

export * from './lib/user-tasks.service';
21 changes: 12 additions & 9 deletions libs/tasks/application/src/lib/tasks.service.spec.ts
Original file line number Diff line number Diff line change
@@ -1,26 +1,29 @@
import { Test, TestingModule } from '@nestjs/testing';

import { TasksService } from './tasks.service';
import { GetAllTasksUseCase } from './use-cases/get-all-tasks.use-case';

describe('TasksService', () => {
let service: TasksService;
let getAllTasksUseCase: GetAllTasksUseCase;

beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [TasksService],
providers: [
TasksService,
{
provide: GetAllTasksUseCase,
useValue: {
execute: jest.fn(),
},
},
],
}).compile();

service = module.get<TasksService>(TasksService);
getAllTasksUseCase = module.get<GetAllTasksUseCase>(GetAllTasksUseCase);
});

it('should be defined', () => {
expect(service).toBeDefined();
});

describe('findAll', () => {
it('should return an array of tasks', async () => {
const result = await service.findAll();
expect(Array.isArray(result)).toBe(true);
});
});
});
7 changes: 5 additions & 2 deletions libs/tasks/application/src/lib/tasks.service.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
import { Injectable } from '@nestjs/common';
import { Task } from '@tasks/domain';

import { GetAllTasksUseCase } from './use-cases/get-all-tasks.use-case';

@Injectable()
export class TasksService {
constructor(private readonly getAllTasksUseCase: GetAllTasksUseCase) {}

async findAll(): Promise<Task[]> {
// TODO: Implement this
return [];
return await this.getAllTasksUseCase.execute();
}
}
14 changes: 14 additions & 0 deletions libs/tasks/application/src/lib/use-cases/get-all-tasks.use-case.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { Inject, Injectable } from '@nestjs/common';
import { Task, TASKS_REPOSITORY, TasksRepository } from '@tasks/domain';

@Injectable()
export class GetAllTasksUseCase {
constructor(
@Inject(TASKS_REPOSITORY)
private readonly tasksRepository: TasksRepository,
) {}

async execute(): Promise<Task[]> {
return await this.tasksRepository.findAll();
}
}
7 changes: 7 additions & 0 deletions libs/tasks/infrastructure/mongoose/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# tasks-infrastructure-mongoose

This library was generated with [Nx](https://nx.dev).

## Running unit tests

Run `nx test tasks-infrastructure-mongoose` to execute the unit tests via [Jest](https://jestjs.io).
3 changes: 3 additions & 0 deletions libs/tasks/infrastructure/mongoose/eslint.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
const baseConfig = require('../../../../eslint.config.js');

module.exports = [...baseConfig];
10 changes: 10 additions & 0 deletions libs/tasks/infrastructure/mongoose/jest.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
export default {
displayName: 'tasks-infrastructure-mongoose',
preset: '../../../../jest.preset.js',
testEnvironment: 'node',
transform: {
'^.+\\.[tj]s$': ['ts-jest', { tsconfig: '<rootDir>/tsconfig.spec.json' }],
},
moduleFileExtensions: ['ts', 'js', 'html'],
coverageDirectory: '../../../../coverage/libs/users/infrastructure/mongoose',
};
9 changes: 9 additions & 0 deletions libs/tasks/infrastructure/mongoose/project.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"name": "tasks-infrastructure-mongoose",
"$schema": "../../../../node_modules/nx/schemas/project-schema.json",
"sourceRoot": "libs/users/infrastructure/mongoose/src",
"projectType": "library",
"tags": [],
"// targets": "to see all targets run: nx show project tasks-infrastructure-mongoose --web",
"targets": {}
}
2 changes: 2 additions & 0 deletions libs/tasks/infrastructure/mongoose/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from './lib/mongoose-tasks.repository';
export * from './lib/task.schema';
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import { Test, TestingModule } from '@nestjs/testing';
import { getModelToken } from '@nestjs/mongoose';
import { Model } from 'mongoose';
import { Task } from '@tasks/domain';

import { TaskDocument } from './task.schema';
import { MongooseTasksRepository } from './mongoose-tasks.repository';

describe('MongooseTasksRepository', () => {
let repository: MongooseTasksRepository;
let taskModel: Model<TaskDocument>;

beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [
MongooseTasksRepository,
{
provide: getModelToken(TaskDocument.name),
useValue: {
find: jest.fn(),
},
},
],
}).compile();

repository = module.get<MongooseTasksRepository>(MongooseTasksRepository);
taskModel = module.get<Model<TaskDocument>>(getModelToken(TaskDocument.name));
});

it('should be defined', () => {
expect(repository).toBeDefined();
});

describe('findAll', () => {
it('should return empty array when no tasks exist', async () => {
jest.spyOn(taskModel, 'find').mockReturnValue({
exec: jest.fn().mockResolvedValue(null),
} as any);

const result = await repository.findAll();
expect(result).toEqual([]);
});

it('should return array of Tasks when found', async () => {
const mockTasks = [
{
id: '123',
title: 'Test Task',
description: 'Test Description',
categories: ['test'],
},
{
id: '456',
title: 'Another Task',
description: null,
categories: ['test', 'another'],
},
];

jest.spyOn(taskModel, 'find').mockReturnValue({
exec: jest.fn().mockResolvedValue(mockTasks),
} as any);

const result = await repository.findAll();
expect(result).toHaveLength(2);
expect(result[0]).toBeInstanceOf(Task);
expect(result[0].id).toBe(mockTasks[0].id);
expect(result[0].title).toBe(mockTasks[0].title);
expect(result[0].description).toBe(mockTasks[0].description);
expect(result[0].categories).toEqual(mockTasks[0].categories);

expect(result[1]).toBeInstanceOf(Task);
expect(result[1].id).toBe(mockTasks[1].id);
expect(result[1].title).toBe(mockTasks[1].title);
expect(result[1].description).toBe(mockTasks[1].description);
expect(result[1].categories).toEqual(mockTasks[1].categories);
});
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { Injectable } from '@nestjs/common';
import { InjectModel } from '@nestjs/mongoose';
import { Task, TasksRepository } from '@tasks/domain';
import { Model } from 'mongoose';

import { TaskDocument } from './task.schema';

@Injectable()
export class MongooseTasksRepository implements TasksRepository {
constructor(
@InjectModel(TaskDocument.name) private taskModel: Model<TaskDocument>,
) {}

async findAll(): Promise<Task[]> {
const tasks = await this.taskModel.find().exec();

if (!tasks) {
return [];
}

return tasks.map((task) =>
Task.create(task.id, task.title, task.description, task.categories),
);
}
}
27 changes: 27 additions & 0 deletions libs/tasks/infrastructure/mongoose/src/lib/task.schema.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { Test, TestingModule } from '@nestjs/testing';
import { getModelToken } from '@nestjs/mongoose';
import { Model } from 'mongoose';
import { TaskDocument } from './task.schema';

describe('TaskDocument', () => {
let taskModel: Model<TaskDocument>;

beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [
{
provide: getModelToken(TaskDocument.name),
useValue: Model,
},
],
}).compile();

taskModel = module.get<Model<TaskDocument>>(
getModelToken(TaskDocument.name),
);
});

it('should be defined', () => {
expect(taskModel).toBeDefined();
});
});
16 changes: 16 additions & 0 deletions libs/tasks/infrastructure/mongoose/src/lib/task.schema.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose';
import { Document } from 'mongoose';

@Schema()
export class TaskDocument extends Document {
@Prop({ required: true, maxlength: 200 })
title!: string;

@Prop({ required: false, default: null, maxlength: 1000 })
description!: string;

@Prop({ required: true, index: true, maxlength: 100 })
categories!: string[];
}

export const TaskSchema = SchemaFactory.createForClass(TaskDocument);
22 changes: 22 additions & 0 deletions libs/tasks/infrastructure/mongoose/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"extends": "../../../../tsconfig.base.json",
"compilerOptions": {
"module": "commonjs",
"forceConsistentCasingInFileNames": true,
"strict": true,
"noImplicitOverride": true,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true,
"noPropertyAccessFromIndexSignature": true
},
"files": [],
"include": [],
"references": [
{
"path": "./tsconfig.lib.json"
},
{
"path": "./tsconfig.spec.json"
}
]
}
11 changes: 11 additions & 0 deletions libs/tasks/infrastructure/mongoose/tsconfig.lib.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"module": "commonjs",
"outDir": "../../../../dist/out-tsc",
"declaration": true,
"types": ["node"]
},
"exclude": ["jest.config.ts", "src/**/*.spec.ts", "src/**/*.test.ts"],
"include": ["src/**/*.ts"]
}
14 changes: 14 additions & 0 deletions libs/tasks/infrastructure/mongoose/tsconfig.spec.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "../../../../dist/out-tsc",
"module": "commonjs",
"types": ["jest", "node"]
},
"include": [
"jest.config.ts",
"src/**/*.test.ts",
"src/**/*.spec.ts",
"src/**/*.d.ts"
]
}
33 changes: 30 additions & 3 deletions libs/tasks/interface-adapters/src/lib/tasks.module.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,39 @@
import { Module } from '@nestjs/common';
import { TasksService, UserTasksService } from '@tasks/application';
import { DatabaseModule } from '@shared/infrastructure-mongoose';
import {
TasksService,
UserTasksService,
GetAllTasksUseCase,
} from '@tasks/application';
import {
MongooseTasksRepository,
TaskDocument,
TaskSchema,
} from '@tasks/infrastructure-mongoose';
import { MongooseModule } from '@nestjs/mongoose';
import { TASKS_REPOSITORY } from '@tasks/domain';

import { TasksResolver } from './resolver/tasks.resolver';
import { UserTasksResolver } from './resolver/user-tasks.resolver';

@Module({
imports: [],
providers: [TasksResolver, TasksService, UserTasksResolver, UserTasksService],
providers: [
TasksResolver,
TasksService,
UserTasksResolver,
UserTasksService,
GetAllTasksUseCase,
{
provide: TASKS_REPOSITORY,
useClass: MongooseTasksRepository,
},
],
imports: [
DatabaseModule,
MongooseModule.forFeature([
{ name: TaskDocument.name, schema: TaskSchema },
]),
],
exports: [TasksService, UserTasksService],
})
export class TasksModule {}
1 change: 1 addition & 0 deletions libs/users/application/src/lib/users.service.spec.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Test, TestingModule } from '@nestjs/testing';

import { UsersService } from './users.service';
import { GetUserByIdUseCase } from './use-cases/get-user-by-id.use-case';
import { GetUserByEmailUseCase } from './use-cases/get-user-by-email.use-case';
Expand Down
2 changes: 1 addition & 1 deletion libs/users/infrastructure/mongoose/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
export * from './lib/mongoose-users.repository';
export * from './lib/user.schema';
export * from './lib/user.schema';
Loading

0 comments on commit db302a5

Please sign in to comment.