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.
Files changed (45) hide show
  1. package/README.md +13 -3
  2. package/dist/command-line.js +9 -0
  3. package/dist/impl/command-line-impl.js +28 -0
  4. package/dist/impl/logger-impl.js +31 -0
  5. package/dist/impl/typescript-mock-server-impl.js +212 -0
  6. package/dist/index.js +6 -0
  7. package/dist/logger.js +2 -0
  8. package/dist/models/config.js +2 -0
  9. package/dist/models/registered-endpoint.js +2 -0
  10. package/dist/src/command-line.js +9 -0
  11. package/dist/src/impl/command-line-impl.js +28 -0
  12. package/dist/src/impl/logger-impl.js +31 -0
  13. package/dist/src/impl/typescript-mock-server-impl.js +208 -0
  14. package/dist/src/index.js +6 -0
  15. package/dist/src/logger.js +2 -0
  16. package/dist/src/models/config.js +2 -0
  17. package/dist/src/models/registered-endpoint.js +2 -0
  18. package/dist/src/types/http-verbs.js +2 -0
  19. package/dist/src/typescript-mock-server.js +2 -0
  20. package/dist/test/impl/command-line-impl.spec.js +40 -0
  21. package/dist/test/impl/typescript-mock-server-impl.spec.js +182 -0
  22. package/dist/tms-models/dash-example/get-dash-in-id.js +6 -0
  23. package/dist/tms-models/dash-example/get-test1.js +6 -0
  24. package/dist/tms-models/dash-example/get.js +20 -0
  25. package/dist/tms-models/users/delete-1.js +8 -0
  26. package/dist/tms-models/users/get-1.js +14 -0
  27. package/dist/tms-models/users/get-dynamic.js +15 -0
  28. package/dist/tms-models/users/get.js +20 -0
  29. package/dist/tms-models/users/head-1.js +4 -0
  30. package/dist/tms-models/users/options-1.js +4 -0
  31. package/dist/tms-models/users/patch-1.js +8 -0
  32. package/dist/tms-models/users/post-1.js +8 -0
  33. package/dist/tms-models/users/profile/get-1.js +12 -0
  34. package/dist/tms-models/users/put-1.js +8 -0
  35. package/dist/types/http-verbs.js +2 -0
  36. package/dist/typescript-mock-server.js +2 -0
  37. package/jest.config.js +12 -0
  38. package/package.json +9 -4
  39. package/src/impl/typescript-mock-server-impl.ts +72 -31
  40. package/src/index.ts +1 -1
  41. package/src/models/config.ts +10 -0
  42. package/test/impl/command-line-impl.spec.ts +49 -0
  43. package/test/impl/typescript-mock-server-impl.spec.ts +181 -0
  44. package/tms-models/users/get-dynamic.ts +22 -0
  45. 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
+ };
package/tsconfig.json CHANGED
@@ -15,7 +15,11 @@
15
15
 
16
16
  "skipLibCheck": true /* Skip type checking all .d.ts files. */
17
17
  },
18
+ "include": [
19
+ "src/**/*"
20
+ ],
18
21
  "exclude": [
19
- "node_modules"
22
+ "node_modules",
23
+ "test"
20
24
  ]
21
25
  }