Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: mock service move to backend #230

Merged
merged 3 commits into from
Dec 10, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions packages/toolkits/pro/template/server/nestJs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
"class-validator": "^0.14.1",
"dotenv": "^16.4.5",
"ioredis": "^5.4.1",
"mockjs": "^1.1.0",
"mysql2": "3.4.3",
"nestjs-i18n": "^10.4.5",
"nestjs-typeorm-paginate": "^4.0.4",
Expand All @@ -50,13 +51,15 @@
"@nestjs/testing": "10.0.3",
"@types/express": "4.17.17",
"@types/jest": "29.5.3",
"@types/mockjs": "^1.0.10",
"@types/node": "20.3.3",
"@types/supertest": "2.0.12",
"@typescript-eslint/eslint-plugin": "5.60.1",
"@typescript-eslint/parser": "5.60.1",
"eslint": "8.42.0",
"eslint-config-prettier": "8.8.0",
"eslint-plugin-import": "2.27.5",
"express": "^4.21.2",
"jest": "29.6.1",
"prettier": "2.8.8",
"source-map-support": "^0.5.20",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import {
HeaderResolver,
I18nModule,
} from 'nestjs-i18n';
import { MockModule } from './mock/mock.module';

@Module({
imports: [
Expand All @@ -54,6 +55,7 @@ import {
resolvers: [new HeaderResolver(['x-lang'])],
typesOutputPath: join(__dirname, '../src/.generate/i18n.generated.ts'),
}),
MockModule,
],
providers: [
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import { mock } from 'mockjs';
import { successResponseWrap } from '../utils';

const initData = mock({
options: [
{
value: '1',
label: 'work.mock.employees',
},
{
value: '2',
label: 'work.mock.onboard',
},
{
value: '3',
label: 'work.mock.Test',
},
],
});

const initData1 = mock({
options: [
{
value: '1',
label: 'work.mock.week1',
},
{
value: '2',
label: 'work.mock.week2',
},
{
value: '3',
label: 'work.mock.week3',
},
],
});

const initData2 = mock({
options: [
{
value: '1',
label: 'work.mock.network',
},
{
value: '2',
label: 'work.mock.centralized',
},
{
value: '3',
label: 'work.mock.hardware',
},
],
});

const changeDate = mock({
options1: [101, 212, 122, 232],
options2: [323, 555, 425, 2221],
options3: [23234, 234, 989, 122],
});

export default [
{
url: '/api/user/getdata',
method: 'get',
response: () => {
return successResponseWrap(initData);
},
},
{
url: '/api/user/getrpractic',
method: 'get',
response: () => {
return successResponseWrap(initData1);
},
},
{
url: '/api/user/getrtrain',
method: 'get',
response: () => {
return successResponseWrap(initData2);
},
},
{
url: '/api/user/getselect',
method: 'post',
response: (data: any) => {
let result = null;
Comment on lines +86 to +87
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Add type safety and error handling to the POST endpoint

The POST endpoint /api/user/getselect lacks proper type safety and error handling:

  1. Uses any type for the data parameter
  2. No validation for data.body
  3. Missing error handling for invalid input

Consider implementing this improvement:

-    response: (data: any) => {
+    response: (data: { body: number }) => {
+      if (typeof data.body !== 'number' || ![1, 2, 3].includes(data.body)) {
+        throw new Error('Invalid body value. Expected 1, 2, or 3');
+      }
       let result = null;
       if (data.body === 1) {
         result = successResponseWrap(changeDate.options1);
       } else if (data.body === 2) {
         result = successResponseWrap(changeDate.options2);
       } else {
         result = successResponseWrap(changeDate.options3);
       }
-      return result;
+      return result!;
     },

Also applies to: 95-96

if (data.body === 1) {
result = successResponseWrap(changeDate.options1);
} else if (data.body === 2) {
result = successResponseWrap(changeDate.options2);
} else {
result = successResponseWrap(changeDate.options3);
}
return result;
},
},
] as const;
118 changes: 118 additions & 0 deletions packages/toolkits/pro/template/server/nestJs/src/mock/data/forms.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
import { mock } from 'mockjs';
import { successResponseWrap } from '../utils';

const initBase = mock({
Project: [
'baseForm.form.label.projectone',
'baseForm.form.label.projecttwo',
'baseForm.form.label.projectthree',
],
rank: [
{
value: '1',
label: '01',
},
{
value: '2',
label: '02',
},
{
value: '3',
label: '03',
},
{
value: '4',
label: '04',
},
{
value: '5',
label: '05',
},
],
person: [
{
value: 'local',
label: 'baseForm.form.label.personone',
},
{
value: 'noemployees',
label: 'baseForm.form.label.persontwo',
},
{
value: 'chineseemployees',
label: 'baseForm.form.label.personthree',
},
],
frequency: [
'baseForm.form.label.frequencyone',
'baseForm.form.label.frequencytwo',
'baseForm.form.label.frequencythree',
'baseForm.form.label.frequencyfour',
],
});

const initStep = mock({
position: [
{
value: '1',
label: 'position1',
},
{
value: '2',
label: 'position2',
},
{
value: '3',
label: 'position3',
},
{
value: '4',
label: 'position4',
},
],
HR: [
{
value: '1',
label: 'test01',
},
{
value: '2',
label: 'test01',
},
{
value: '3',
label: 'test03',
},
],
Comment on lines +73 to +86
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix duplicate label in HR mock data

The HR mock data contains duplicate labels ('test01' appears twice with different values).

   HR: [
     {
       value: '1',
       label: 'test01',
     },
     {
       value: '2',
-      label: 'test01',
+      label: 'test02',
     },
     {
       value: '3',
       label: 'test03',
     },
   ],
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
HR: [
{
value: '1',
label: 'test01',
},
{
value: '2',
label: 'test01',
},
{
value: '3',
label: 'test03',
},
],
HR: [
{
value: '1',
label: 'test01',
},
{
value: '2',
label: 'test02',
},
{
value: '3',
label: 'test03',
},
],

mentor: ['Teacher1', 'Teacher2', 'Teacher3', 'Teacher4'],
director: ['Director1', 'Director2', 'Director3', 'Director4'],
});

export default [
// init-base
{
url: '/api/base/getdata',
method: 'get',
response: () => {
return successResponseWrap(initBase);
},
},

// init-step
{
url: '/api/step/getdata',
method: 'get',
response: () => {
return successResponseWrap(initStep);
},
},

// submit
{
url: '/api/channel-form/submit',
method: 'post',
response: () => {
return successResponseWrap('ok');
},
},
] as any;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Remove as any type assertion

Using as any bypasses TypeScript's type checking. This could lead to runtime errors.

Define proper types for the mock endpoints:

interface MockEndpoint {
  url: string;
  method: 'get' | 'post';
  response: () => ReturnType<typeof successResponseWrap>;
}

export default [
  // ... existing implementation
] satisfies MockEndpoint[];

Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import board from './board';
import forms from './forms';
import list from './list';
import profile from './profile';
import user from './user';

export default [...board, ...list, ...profile, ...user, ...forms] as const;
50 changes: 50 additions & 0 deletions packages/toolkits/pro/template/server/nestJs/src/mock/data/list.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { mock } from 'mockjs';
import { successResponseWrap } from '../utils';
const taskList = mock({
'list|60': [
{
id: '@id',
name: 'xiaoming',
rank: '初级',
description: '一段描述文字',
createTime: '@datetime',
'status|1': ['0', '1', '2'],
type: 'Tiny Design',
roles: '前端',
employeeNo: '00022456',
department: '公共服务',
departmentLevel: '中级',
workbenchName: 'work',
project: 'TinyDesign',
address: '西安研究所',
lastUpdateUser: '张三',
},
],
});
Comment on lines +3 to +23
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Enhance mock data variety and type safety

The mock data generation could be improved in several ways:

  1. Use @name template instead of hardcoded 'xiaoming'
  2. Define status values as constants/enum instead of magic strings
  3. Add more variety to fields like 'roles', 'department', etc.
 const taskList = mock({
   'list|60': [
     {
       id: '@id',
-      name: 'xiaoming',
+      name: '@cname',
-      rank: '初级',
+      'rank|1': ['初级', '中级', '高级'],
       description: '@sentence(3, 10)',
       createTime: '@datetime',
-      'status|1': ['0', '1', '2'],
+      'status|1': ['ACTIVE', 'INACTIVE', 'PENDING'],
-      roles: '前端',
+      'roles|1': ['前端', '后端', '全栈', 'UI设计', '产品'],
-      department: '公共服务',
+      'department|1': ['研发部', '产品部', '设计部', '测试部', '运维部'],

Committable suggestion skipped: line range outside the PR's diff.


let treeData = [];
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Avoid using global variables for request handling

Using a global treeData variable for handling paginated data is not thread-safe and could lead to race conditions in concurrent requests.

-let treeData = [];
-
 export default [
   {
     url: '/api/employee/getEmployee',
     method: 'post',
     response: (params: { body: any }) => {
       const { pageIndex = 1, pageSize = 10 } = JSON.parse(
         JSON.stringify(params.body)
       );
       const index = pageIndex as number;
       const size = pageSize as number;
       const offset = (index - 1) * size;
       const count = index * size;
-      treeData = taskList.list.slice(offset, count);
+      const paginatedData = taskList.list.slice(offset, count);

Also applies to: 40-41


export default [
// list
{
url: '/api/employee/getEmployee',
method: 'post',
response: (params: { body: any }) => {
const { pageIndex = 1, pageSize = 10 } = JSON.parse(
JSON.stringify(params.body)
);
const index = pageIndex as number;
const size = pageSize as number;
const offset = (index - 1) * size;
const count = index * size;
treeData = taskList.list.slice(offset, count);

const data = mock({
total: 60,
data: treeData,
});

return successResponseWrap(data);
},
Comment on lines +32 to +48
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Add input validation and error handling

The request handler needs validation for pagination parameters and proper error handling.

     response: (params: { body: any }) => {
+      try {
         const { pageIndex = 1, pageSize = 10 } = JSON.parse(
           JSON.stringify(params.body)
         );
+        if (pageIndex < 1 || pageSize < 1) {
+          throw new Error('Invalid pagination parameters');
+        }
         const index = pageIndex as number;
         const size = pageSize as number;
         const offset = (index - 1) * size;
         const count = index * size;
-        treeData = taskList.list.slice(offset, count);
+        const paginatedData = taskList.list.slice(offset, count);
 
         const data = mock({
           total: 60,
-          data: treeData,
+          data: paginatedData,
         });
 
         return successResponseWrap(data);
+      } catch (error) {
+        throw new Error(`Failed to process request: ${error.message}`);
+      }
     },
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
response: (params: { body: any }) => {
const { pageIndex = 1, pageSize = 10 } = JSON.parse(
JSON.stringify(params.body)
);
const index = pageIndex as number;
const size = pageSize as number;
const offset = (index - 1) * size;
const count = index * size;
treeData = taskList.list.slice(offset, count);
const data = mock({
total: 60,
data: treeData,
});
return successResponseWrap(data);
},
response: (params: { body: any }) => {
try {
const { pageIndex = 1, pageSize = 10 } = JSON.parse(
JSON.stringify(params.body)
);
if (pageIndex < 1 || pageSize < 1) {
throw new Error('Invalid pagination parameters');
}
const index = pageIndex as number;
const size = pageSize as number;
const offset = (index - 1) * size;
const count = index * size;
const paginatedData = taskList.list.slice(offset, count);
const data = mock({
total: 60,
data: paginatedData,
});
return successResponseWrap(data);
} catch (error) {
throw new Error(`Failed to process request: ${error.message}`);
}
},

},
] as const;
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import { successResponseWrap } from '../utils';
import { mock } from 'mockjs';

const initData = mock({
Project: [
'baseForm.form.label.projectone',
'baseForm.form.label.projecttwo',
'baseForm.form.label.projectthree',
],
tableData: [
{
id: '1',
version: 'version1',
operation: 'offline',
updated: 'person1',
time: '2022-10-11',
},
{
id: '2',
version: 'version2',
operation: 'offline',
updated: 'person2',
time: '2022-10-12',
},
{
id: '3',
version: 'version3',
operation: 'online',
updated: 'person3',
time: '2022-10-13',
},
{
id: '4',
version: 'version4',
operation: 'online',
updated: 'person4',
time: '2022-10-14',
},
{
id: '5',
version: 'version5',
operation: 'online',
updated: 'person5',
time: '2022-10-15',
},
{
id: '6',
version: 'version6',
operation: 'online',
updated: 'person6',
time: '2022-10-16',
},
],
});

export default [
{
url: '/api/detail/getdata',
method: 'get',
response: () => {
return successResponseWrap(initData);
},
},
] as const;
Loading