typescript-mock-server 1.10.0 → 1.11.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +13 -3
- package/dist/command-line.js +9 -0
- package/dist/impl/command-line-impl.js +28 -0
- package/dist/impl/logger-impl.js +31 -0
- package/dist/impl/typescript-mock-server-impl.js +212 -0
- package/dist/index.js +6 -0
- package/dist/logger.js +2 -0
- package/dist/models/config.js +2 -0
- package/dist/models/registered-endpoint.js +2 -0
- package/dist/src/command-line.js +9 -0
- package/dist/src/impl/command-line-impl.js +28 -0
- package/dist/src/impl/logger-impl.js +31 -0
- package/dist/src/impl/typescript-mock-server-impl.js +208 -0
- package/dist/src/index.js +6 -0
- package/dist/src/logger.js +2 -0
- package/dist/src/models/config.js +2 -0
- package/dist/src/models/registered-endpoint.js +2 -0
- package/dist/src/types/http-verbs.js +2 -0
- package/dist/src/typescript-mock-server.js +2 -0
- package/dist/test/impl/command-line-impl.spec.js +40 -0
- package/dist/test/impl/typescript-mock-server-impl.spec.js +182 -0
- package/dist/tms-models/dash-example/get-dash-in-id.js +6 -0
- package/dist/tms-models/dash-example/get-test1.js +6 -0
- package/dist/tms-models/dash-example/get.js +20 -0
- package/dist/tms-models/users/delete-1.js +8 -0
- package/dist/tms-models/users/get-1.js +14 -0
- package/dist/tms-models/users/get-dynamic.js +15 -0
- package/dist/tms-models/users/get.js +20 -0
- package/dist/tms-models/users/head-1.js +4 -0
- package/dist/tms-models/users/options-1.js +4 -0
- package/dist/tms-models/users/patch-1.js +8 -0
- package/dist/tms-models/users/post-1.js +8 -0
- package/dist/tms-models/users/profile/get-1.js +12 -0
- package/dist/tms-models/users/put-1.js +8 -0
- package/dist/types/http-verbs.js +2 -0
- package/dist/typescript-mock-server.js +2 -0
- package/jest.config.js +12 -0
- package/package.json +9 -4
- package/src/impl/typescript-mock-server-impl.ts +72 -31
- package/src/index.ts +1 -1
- package/src/models/config.ts +10 -0
- package/test/impl/command-line-impl.spec.ts +49 -0
- package/test/impl/typescript-mock-server-impl.spec.ts +181 -0
- package/tms-models/users/get-dynamic.ts +22 -0
- package/tsconfig.json +5 -1
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { CommandLineImpl } from '../../src/impl/command-line-impl';
|
|
2
|
+
import { Command } from '../../src/command-line';
|
|
3
|
+
|
|
4
|
+
describe('CommandLineImpl', () => {
|
|
5
|
+
const originalArgv = process.argv;
|
|
6
|
+
|
|
7
|
+
beforeEach(() => {
|
|
8
|
+
jest.resetModules();
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
afterEach(() => {
|
|
12
|
+
process.argv = originalArgv;
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
it('should parse command line arguments correctly', () => {
|
|
16
|
+
process.argv = ['node', 'index.js', '--port=4000', '--path=./test-models', '--cors=http://localhost:3000'];
|
|
17
|
+
const commandLine = new CommandLineImpl();
|
|
18
|
+
|
|
19
|
+
expect(commandLine.getCommand(Command.PORT)).toBe('4000');
|
|
20
|
+
expect(commandLine.getCommand(Command.PATH)).toBe('./test-models');
|
|
21
|
+
expect(commandLine.getCommand(Command.CORS)).toBe('http://localhost:3000');
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
it('should handle arguments with quotes', () => {
|
|
25
|
+
process.argv = ['node', 'index.js', '--path="C:/Program Files/Models"', "--cors='*'", '--port=5000'];
|
|
26
|
+
const commandLine = new CommandLineImpl();
|
|
27
|
+
|
|
28
|
+
expect(commandLine.getCommand(Command.PATH)).toBe('C:/Program Files/Models');
|
|
29
|
+
expect(commandLine.getCommand(Command.CORS)).toBe('*');
|
|
30
|
+
expect(commandLine.getCommand(Command.PORT)).toBe('5000');
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
it('should return undefined for missing commands', () => {
|
|
34
|
+
process.argv = ['node', 'index.js'];
|
|
35
|
+
const commandLine = new CommandLineImpl();
|
|
36
|
+
|
|
37
|
+
expect(commandLine.getCommand(Command.PORT)).toBeUndefined();
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
it('should return all commands', () => {
|
|
41
|
+
process.argv = ['node', 'index.js', '--port=4000', '--path=./models'];
|
|
42
|
+
const commandLine = new CommandLineImpl();
|
|
43
|
+
const commands = commandLine.getCommands();
|
|
44
|
+
|
|
45
|
+
expect(commands.size).toBe(2);
|
|
46
|
+
expect(commands.get(Command.PORT)).toBe('4000');
|
|
47
|
+
expect(commands.get(Command.PATH)).toBe('./models');
|
|
48
|
+
});
|
|
49
|
+
});
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
import request from 'supertest';
|
|
2
|
+
import express, { Express } from 'express';
|
|
3
|
+
import { TypescriptMockServerImpl } from '../../src/impl/typescript-mock-server-impl';
|
|
4
|
+
import * as fsPromises from 'fs/promises';
|
|
5
|
+
import { Command } from '../../src/command-line';
|
|
6
|
+
import path from 'path';
|
|
7
|
+
|
|
8
|
+
jest.mock('fs/promises');
|
|
9
|
+
|
|
10
|
+
describe('TypescriptMockServerImpl', () => {
|
|
11
|
+
let server: TypescriptMockServerImpl;
|
|
12
|
+
let app: Express;
|
|
13
|
+
|
|
14
|
+
beforeEach(() => {
|
|
15
|
+
jest.clearAllMocks();
|
|
16
|
+
app = express();
|
|
17
|
+
// Spy on listen to prevent it from actually starting
|
|
18
|
+
jest.spyOn(app, 'listen').mockImplementation((port: any, callback: any) => {
|
|
19
|
+
if (callback) callback();
|
|
20
|
+
return {} as any;
|
|
21
|
+
});
|
|
22
|
+
// Reset process.argv
|
|
23
|
+
process.argv = ['node', 'index.js'];
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
it('should start and have the state endpoint', async () => {
|
|
27
|
+
(fsPromises.opendir as jest.Mock).mockResolvedValue(async function* () {
|
|
28
|
+
// yield nothing
|
|
29
|
+
}());
|
|
30
|
+
|
|
31
|
+
server = new TypescriptMockServerImpl(app);
|
|
32
|
+
await server.start();
|
|
33
|
+
|
|
34
|
+
const response = await request(app).get('/state');
|
|
35
|
+
expect(response.status).toBe(200);
|
|
36
|
+
expect(response.body).toEqual({ status: 'started' });
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it('should have the state endpoint even if other routes are loaded', async () => {
|
|
40
|
+
(fsPromises.opendir as jest.Mock).mockResolvedValue(async function* () {
|
|
41
|
+
// yield nothing
|
|
42
|
+
}());
|
|
43
|
+
|
|
44
|
+
server = new TypescriptMockServerImpl(app);
|
|
45
|
+
await server.start();
|
|
46
|
+
|
|
47
|
+
const response = await request(app).get('/state');
|
|
48
|
+
expect(response.status).toBe(200);
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
it('should load routes from directory', async () => {
|
|
52
|
+
const mockFiles = [
|
|
53
|
+
{ name: 'get-test.ts', isDirectory: () => false },
|
|
54
|
+
{ name: 'post-data.ts', isDirectory: () => false }
|
|
55
|
+
];
|
|
56
|
+
|
|
57
|
+
(fsPromises.opendir as jest.Mock).mockResolvedValue(async function* () {
|
|
58
|
+
for (const file of mockFiles) {
|
|
59
|
+
yield file;
|
|
60
|
+
}
|
|
61
|
+
}());
|
|
62
|
+
|
|
63
|
+
// Mock loadModule
|
|
64
|
+
const loadModuleSpy = jest.spyOn(TypescriptMockServerImpl as any, 'loadModule');
|
|
65
|
+
loadModuleSpy.mockImplementation(async (...args: any[]) => {
|
|
66
|
+
const path = args[0] as string;
|
|
67
|
+
if (path.includes('get-test')) {
|
|
68
|
+
return { data: { message: 'get success' } };
|
|
69
|
+
}
|
|
70
|
+
if (path.includes('post-data')) {
|
|
71
|
+
return { data: { message: 'post success' } };
|
|
72
|
+
}
|
|
73
|
+
return {};
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
server = new TypescriptMockServerImpl(app);
|
|
77
|
+
await server.start();
|
|
78
|
+
|
|
79
|
+
const getResponse = await request(app).get('/test');
|
|
80
|
+
expect(getResponse.status).toBe(200);
|
|
81
|
+
expect(getResponse.body).toEqual({ message: 'get success' });
|
|
82
|
+
|
|
83
|
+
const postResponse = await request(app).post('/data');
|
|
84
|
+
expect(postResponse.status).toBe(200);
|
|
85
|
+
expect(postResponse.body).toEqual({ message: 'post success' });
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
it('should handle status codes and delay from config', async () => {
|
|
89
|
+
const mockFiles = [
|
|
90
|
+
{ name: 'get-config.ts', isDirectory: () => false }
|
|
91
|
+
];
|
|
92
|
+
|
|
93
|
+
(fsPromises.opendir as jest.Mock).mockResolvedValue(async function* () {
|
|
94
|
+
yield mockFiles[0];
|
|
95
|
+
}());
|
|
96
|
+
|
|
97
|
+
const loadModuleSpy = jest.spyOn(TypescriptMockServerImpl as any, 'loadModule');
|
|
98
|
+
loadModuleSpy.mockImplementation(async () => {
|
|
99
|
+
return {
|
|
100
|
+
data: { message: 'custom' },
|
|
101
|
+
config: { statusCode: 201, delay: 10 }
|
|
102
|
+
} as any;
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
server = new TypescriptMockServerImpl(app);
|
|
106
|
+
await server.start();
|
|
107
|
+
|
|
108
|
+
const response = await request(app).get('/config');
|
|
109
|
+
expect(response.status).toBe(201);
|
|
110
|
+
expect(response.body).toEqual({ message: 'custom' });
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
it('should resolve absolute paths correctly', async () => {
|
|
114
|
+
(fsPromises.opendir as jest.Mock).mockResolvedValue(async function* () {
|
|
115
|
+
// yield nothing
|
|
116
|
+
}());
|
|
117
|
+
|
|
118
|
+
const absolutePath = path.resolve('/absolute/path/to/models');
|
|
119
|
+
process.argv = ['node', 'index.js', `--path=${absolutePath}`];
|
|
120
|
+
|
|
121
|
+
server = new TypescriptMockServerImpl(app);
|
|
122
|
+
// @ts-ignore
|
|
123
|
+
expect(server.basePath).toBe(absolutePath);
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
it('should resolve relative paths from process.cwd()', async () => {
|
|
127
|
+
(fsPromises.opendir as jest.Mock).mockResolvedValue(async function* () {
|
|
128
|
+
// yield nothing
|
|
129
|
+
}());
|
|
130
|
+
|
|
131
|
+
const relativePath = 'custom-models';
|
|
132
|
+
process.argv = ['node', 'index.js', `--path=${relativePath}`];
|
|
133
|
+
|
|
134
|
+
server = new TypescriptMockServerImpl(app);
|
|
135
|
+
// @ts-ignore
|
|
136
|
+
expect(server.basePath).toBe(path.join(process.cwd(), relativePath));
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
it('should use custom default path from config', async () => {
|
|
140
|
+
(fsPromises.opendir as jest.Mock).mockResolvedValue(async function* () {
|
|
141
|
+
// yield nothing
|
|
142
|
+
}());
|
|
143
|
+
|
|
144
|
+
const customDefault = 'my-custom-models';
|
|
145
|
+
server = new TypescriptMockServerImpl({ path: customDefault, app });
|
|
146
|
+
// @ts-ignore
|
|
147
|
+
expect(server.basePath).toBe(path.join(process.cwd(), customDefault));
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
it('should support dynamic data as a function receiving req and res', async () => {
|
|
151
|
+
const mockFiles = [
|
|
152
|
+
{ name: 'get-dynamic.ts', isDirectory: () => false }
|
|
153
|
+
];
|
|
154
|
+
|
|
155
|
+
(fsPromises.opendir as jest.Mock).mockResolvedValue(async function* () {
|
|
156
|
+
yield mockFiles[0];
|
|
157
|
+
}());
|
|
158
|
+
|
|
159
|
+
const loadModuleSpy = jest.spyOn(TypescriptMockServerImpl as any, 'loadModule');
|
|
160
|
+
loadModuleSpy.mockImplementation(async () => {
|
|
161
|
+
return {
|
|
162
|
+
data: (req: any, res: any) => {
|
|
163
|
+
return {
|
|
164
|
+
query: req.query.q,
|
|
165
|
+
method: req.method
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
};
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
server = new TypescriptMockServerImpl(app);
|
|
172
|
+
await server.start();
|
|
173
|
+
|
|
174
|
+
const response = await request(app).get('/dynamic?q=test');
|
|
175
|
+
expect(response.status).toBe(200);
|
|
176
|
+
expect(response.body).toEqual({
|
|
177
|
+
query: 'test',
|
|
178
|
+
method: 'GET'
|
|
179
|
+
});
|
|
180
|
+
});
|
|
181
|
+
});
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { Request, Response } from 'express';
|
|
2
|
+
import { MockModel, RequestConfig } from '../../src/models/config';
|
|
3
|
+
|
|
4
|
+
export interface User {
|
|
5
|
+
id: number;
|
|
6
|
+
username: string;
|
|
7
|
+
email: string;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export const data = (req: Request, res: Response): User => {
|
|
11
|
+
const userId = req.query.id ? parseInt(req.query.id as string) : 1;
|
|
12
|
+
|
|
13
|
+
return {
|
|
14
|
+
id: userId,
|
|
15
|
+
username: `user_${userId}`,
|
|
16
|
+
email: `user_${userId}@example.com`
|
|
17
|
+
};
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export const config: RequestConfig = {
|
|
21
|
+
statusCode: 200
|
|
22
|
+
};
|