0z2i6v3u5t 1.0.0

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 (211) hide show
  1. package/.devcontainer/devcontainer.json +4 -0
  2. package/.devcontainer/setup.sh +11 -0
  3. package/.dockerignore +2 -0
  4. package/.github/CONTRIBUTING.md +52 -0
  5. package/.github/FUNDING.yml +3 -0
  6. package/.github/ISSUE_TEMPLATE/bug_report.yml +59 -0
  7. package/.github/ISSUE_TEMPLATE/config.yml +5 -0
  8. package/.github/ISSUE_TEMPLATE/feature_request.yml +43 -0
  9. package/.github/dependabot.yml +17 -0
  10. package/.github/workflows/codeql.yml +76 -0
  11. package/.github/workflows/publish_docs.yml +25 -0
  12. package/.github/workflows/test.yml +78 -0
  13. package/.nvmrc +1 -0
  14. package/.prettierignore +1 -0
  15. package/.prettierrc +1 -0
  16. package/.vscode/launch.json +42 -0
  17. package/CODE_OF_CONDUCT.md +76 -0
  18. package/Dockerfile +17 -0
  19. package/LICENSE +21 -0
  20. package/README.md +3 -0
  21. package/SECURITY.md +5 -0
  22. package/__tests__/actions/cacheTest.ts +58 -0
  23. package/__tests__/actions/randomNumber.ts +26 -0
  24. package/__tests__/actions/recursiveAction.ts +16 -0
  25. package/__tests__/actions/sleepTest.ts +24 -0
  26. package/__tests__/actions/status.ts +17 -0
  27. package/__tests__/actions/swagger.ts +76 -0
  28. package/__tests__/actions/validationTest.ts +63 -0
  29. package/__tests__/cli/cli.ts +126 -0
  30. package/__tests__/core/api.ts +632 -0
  31. package/__tests__/core/cache.ts +400 -0
  32. package/__tests__/core/chatRoom.ts +589 -0
  33. package/__tests__/core/cli.ts +349 -0
  34. package/__tests__/core/cluster.ts +132 -0
  35. package/__tests__/core/config.ts +78 -0
  36. package/__tests__/core/errors.ts +112 -0
  37. package/__tests__/core/log.ts +23 -0
  38. package/__tests__/core/middleware.ts +427 -0
  39. package/__tests__/core/plugins/partialPlugin.ts +94 -0
  40. package/__tests__/core/plugins/withPlugin.ts +88 -0
  41. package/__tests__/core/plugins/withoutPlugin.ts +81 -0
  42. package/__tests__/core/process.ts +42 -0
  43. package/__tests__/core/specHelper.ts +330 -0
  44. package/__tests__/core/staticFile/compression.ts +99 -0
  45. package/__tests__/core/staticFile/staticFile.ts +180 -0
  46. package/__tests__/core/tasks/customQueueFunction.ts +67 -0
  47. package/__tests__/core/tasks/fullWorkerFlow.ts +199 -0
  48. package/__tests__/core/tasks/tasks.ts +605 -0
  49. package/__tests__/integration/browser.ts +133 -0
  50. package/__tests__/integration/ioredis-mock.ts +194 -0
  51. package/__tests__/integration/sendBuffer.ts +97 -0
  52. package/__tests__/integration/sendFile.ts +24 -0
  53. package/__tests__/integration/sharedFingerprint.ts +82 -0
  54. package/__tests__/integration/taskFlow.ts +110 -0
  55. package/__tests__/jest.ts +5 -0
  56. package/__tests__/modules/action.ts +103 -0
  57. package/__tests__/modules/config.ts +19 -0
  58. package/__tests__/modules/utils/ensureNoTsHeaderOrSpecFiles.ts +24 -0
  59. package/__tests__/servers/web/allowedRequestHosts.ts +88 -0
  60. package/__tests__/servers/web/enableMultiples.ts +83 -0
  61. package/__tests__/servers/web/fileUpload.ts +79 -0
  62. package/__tests__/servers/web/jsonp.ts +57 -0
  63. package/__tests__/servers/web/nonMultiples.ts +83 -0
  64. package/__tests__/servers/web/rawBody.ts +208 -0
  65. package/__tests__/servers/web/returnErrorCodes.ts +55 -0
  66. package/__tests__/servers/web/routes/deepRoutes.ts +96 -0
  67. package/__tests__/servers/web/routes/routes.ts +579 -0
  68. package/__tests__/servers/web/routes/veryDeepRoutes.ts +92 -0
  69. package/__tests__/servers/web/web.ts +1031 -0
  70. package/__tests__/servers/websocket.ts +795 -0
  71. package/__tests__/tasks/runAction.ts +37 -0
  72. package/__tests__/template.ts.example +20 -0
  73. package/__tests__/testCliCommands/hello.ts +44 -0
  74. package/__tests__/testPlugin/public/plugin.html +1 -0
  75. package/__tests__/testPlugin/src/actions/pluginAction.ts +14 -0
  76. package/__tests__/testPlugin/src/bin/hello.ts +22 -0
  77. package/__tests__/testPlugin/src/initializers/pluginInitializer.ts +17 -0
  78. package/__tests__/testPlugin/src/tasks/pluginTask.ts +15 -0
  79. package/__tests__/testPlugin/tsconfig.json +10 -0
  80. package/__tests__/utils/utils.ts +492 -0
  81. package/app.json +23 -0
  82. package/bin/deploy-docs +39 -0
  83. package/client/ActionheroWebsocketClient.js +277 -0
  84. package/docker-compose.yml +73 -0
  85. package/package.json +24 -0
  86. package/public/chat.html +194 -0
  87. package/public/css/cosmo.css +12 -0
  88. package/public/favicon.ico +0 -0
  89. package/public/index.html +115 -0
  90. package/public/javascript/.gitkeep +0 -0
  91. package/public/linkedSession.html +80 -0
  92. package/public/logo/actionhero-small.png +0 -0
  93. package/public/logo/actionhero.png +0 -0
  94. package/public/pixel.gif +0 -0
  95. package/public/simple.html +2 -0
  96. package/public/swagger.html +32 -0
  97. package/public/websocketLoadTest.html +322 -0
  98. package/src/actions/cacheTest.ts +58 -0
  99. package/src/actions/createChatRoom.ts +20 -0
  100. package/src/actions/randomNumber.ts +17 -0
  101. package/src/actions/recursiveAction.ts +13 -0
  102. package/src/actions/sendFile.ts +12 -0
  103. package/src/actions/sleepTest.ts +40 -0
  104. package/src/actions/status.ts +73 -0
  105. package/src/actions/swagger.ts +155 -0
  106. package/src/actions/validationTest.ts +36 -0
  107. package/src/bin/actionhero.ts +225 -0
  108. package/src/bin/methods/actions/list.ts +30 -0
  109. package/src/bin/methods/console.ts +26 -0
  110. package/src/bin/methods/generate/action.ts +58 -0
  111. package/src/bin/methods/generate/cli.ts +51 -0
  112. package/src/bin/methods/generate/initializer.ts +54 -0
  113. package/src/bin/methods/generate/plugin.ts +57 -0
  114. package/src/bin/methods/generate/server.ts +38 -0
  115. package/src/bin/methods/generate/task.ts +68 -0
  116. package/src/bin/methods/generate.ts +176 -0
  117. package/src/bin/methods/task/enqueue.ts +35 -0
  118. package/src/classes/action.ts +98 -0
  119. package/src/classes/actionProcessor.ts +463 -0
  120. package/src/classes/api.ts +51 -0
  121. package/src/classes/cli.ts +67 -0
  122. package/src/classes/config.ts +15 -0
  123. package/src/classes/connection.ts +321 -0
  124. package/src/classes/exceptionReporter.ts +9 -0
  125. package/src/classes/initializer.ts +59 -0
  126. package/src/classes/initializers.ts +5 -0
  127. package/src/classes/input.ts +9 -0
  128. package/src/classes/inputs.ts +34 -0
  129. package/src/classes/process/actionheroVersion.ts +15 -0
  130. package/src/classes/process/env.ts +16 -0
  131. package/src/classes/process/id.ts +34 -0
  132. package/src/classes/process/pid.ts +32 -0
  133. package/src/classes/process/projectRoot.ts +16 -0
  134. package/src/classes/process/typescript.ts +47 -0
  135. package/src/classes/process.ts +479 -0
  136. package/src/classes/server.ts +251 -0
  137. package/src/classes/task.ts +87 -0
  138. package/src/config/api.ts +107 -0
  139. package/src/config/errors.ts +162 -0
  140. package/src/config/logger.ts +113 -0
  141. package/src/config/plugins.ts +37 -0
  142. package/src/config/redis.ts +78 -0
  143. package/src/config/routes.ts +44 -0
  144. package/src/config/tasks.ts +84 -0
  145. package/src/config/web.ts +136 -0
  146. package/src/config/websocket.ts +62 -0
  147. package/src/index.ts +46 -0
  148. package/src/initializers/actions.ts +125 -0
  149. package/src/initializers/chatRoom.ts +214 -0
  150. package/src/initializers/connections.ts +124 -0
  151. package/src/initializers/exceptions.ts +155 -0
  152. package/src/initializers/params.ts +52 -0
  153. package/src/initializers/redis.ts +191 -0
  154. package/src/initializers/resque.ts +248 -0
  155. package/src/initializers/routes.ts +229 -0
  156. package/src/initializers/servers.ts +134 -0
  157. package/src/initializers/specHelper.ts +195 -0
  158. package/src/initializers/staticFile.ts +253 -0
  159. package/src/initializers/tasks.ts +188 -0
  160. package/src/modules/action.ts +89 -0
  161. package/src/modules/cache.ts +326 -0
  162. package/src/modules/chatRoom.ts +321 -0
  163. package/src/modules/config.ts +246 -0
  164. package/src/modules/log.ts +62 -0
  165. package/src/modules/redis.ts +93 -0
  166. package/src/modules/route.ts +59 -0
  167. package/src/modules/specHelper.ts +182 -0
  168. package/src/modules/task.ts +527 -0
  169. package/src/modules/utils/argv.ts +3 -0
  170. package/src/modules/utils/arrayStartingMatch.ts +21 -0
  171. package/src/modules/utils/arrayUnique.ts +15 -0
  172. package/src/modules/utils/collapseObjectToArray.ts +33 -0
  173. package/src/modules/utils/deepCopy.ts +3 -0
  174. package/src/modules/utils/ensureNoTsHeaderOrSpecFiles.ts +19 -0
  175. package/src/modules/utils/eventLoopDelay.ts +34 -0
  176. package/src/modules/utils/fileUtils.ts +119 -0
  177. package/src/modules/utils/filterObjectForLogging.ts +51 -0
  178. package/src/modules/utils/filterResponseForLogging.ts +53 -0
  179. package/src/modules/utils/getExternalIPAddress.ts +17 -0
  180. package/src/modules/utils/hashMerge.ts +63 -0
  181. package/src/modules/utils/isPlainObject.ts +45 -0
  182. package/src/modules/utils/isRunning.ts +7 -0
  183. package/src/modules/utils/parseCookies.ts +20 -0
  184. package/src/modules/utils/parseHeadersForClientAddress.ts +53 -0
  185. package/src/modules/utils/parseIPv6URI.ts +24 -0
  186. package/src/modules/utils/replaceDistWithSrc.ts +9 -0
  187. package/src/modules/utils/safeGlob.ts +6 -0
  188. package/src/modules/utils/sleep.ts +8 -0
  189. package/src/modules/utils/sortGlobalMiddleware.ts +17 -0
  190. package/src/modules/utils/sourceRelativeLinkPath.ts +29 -0
  191. package/src/modules/utils.ts +66 -0
  192. package/src/server.ts +20 -0
  193. package/src/servers/web.ts +894 -0
  194. package/src/servers/websocket.ts +304 -0
  195. package/src/tasks/runAction.ts +29 -0
  196. package/tea.yaml +9 -0
  197. package/templates/README.md.template +17 -0
  198. package/templates/action.ts.template +15 -0
  199. package/templates/boot.js.template +9 -0
  200. package/templates/cli.ts.template +15 -0
  201. package/templates/gitignore.template +23 -0
  202. package/templates/initializer.ts.template +17 -0
  203. package/templates/package-plugin.json.template +12 -0
  204. package/templates/package.json.template +45 -0
  205. package/templates/projectMap.txt +39 -0
  206. package/templates/projectServer.ts.template +20 -0
  207. package/templates/server.ts.template +37 -0
  208. package/templates/task.ts.template +16 -0
  209. package/templates/test/action.ts.template +13 -0
  210. package/templates/test/task.ts.template +20 -0
  211. package/tsconfig.json +11 -0
@@ -0,0 +1,208 @@
1
+ import { PassThrough } from "stream";
2
+ import axios, { AxiosError } from "axios";
3
+ import { api, Process, config } from "./../../../src/index";
4
+
5
+ const actionhero = new Process();
6
+ let url: string;
7
+
8
+ jest.mock("./../../../src/config/web.ts", () => ({
9
+ __esModule: true,
10
+ test: {
11
+ web: () => {
12
+ return {
13
+ enabled: true,
14
+ saveRawBody: true,
15
+ automaticRoutes: ["post"],
16
+ secure: false,
17
+ urlPathForActions: "api",
18
+ urlPathForFiles: "public",
19
+ rootEndpointType: "file",
20
+ port: 18080 + parseInt(process.env.JEST_WORKER_ID || "0"),
21
+ matchExtensionMime: true,
22
+ metadataOptions: {
23
+ serverInformation: true,
24
+ requesterInformation: false,
25
+ },
26
+ fingerprintOptions: {
27
+ cookieKey: "sessionID",
28
+ },
29
+ };
30
+ },
31
+ },
32
+ }));
33
+
34
+ describe("Server: Web", () => {
35
+ beforeAll(async () => {
36
+ await actionhero.start();
37
+ url = "http://localhost:" + config.web!.port;
38
+ });
39
+
40
+ afterAll(async () => await actionhero.stop());
41
+
42
+ describe("connection.rawConnection.rawBody", () => {
43
+ beforeAll(() => {
44
+ api.actions.versions.paramTestAction = [1];
45
+ api.actions.actions.paramTestAction = {
46
+ // @ts-ignore
47
+ 1: {
48
+ name: "paramTestAction",
49
+ description: "I return connection.rawConnection.params",
50
+ version: 1,
51
+ run: async (data) => {
52
+ data.response = data.connection!.rawConnection.params;
53
+ if (data.connection!.rawConnection.params.rawBody) {
54
+ data.response!.rawBody =
55
+ data.connection!.rawConnection.params.rawBody.toString();
56
+ }
57
+ },
58
+ },
59
+ };
60
+
61
+ api.routes.loadRoutes();
62
+ });
63
+
64
+ afterAll(() => {
65
+ delete api.actions.actions.paramTestAction;
66
+ delete api.actions.versions.paramTestAction;
67
+ });
68
+
69
+ test(".rawBody will contain the raw POST body without parsing", async () => {
70
+ const requestBody = '{"key": "value"}';
71
+ const response = await axios.post(
72
+ url + "/api/paramTestAction",
73
+ requestBody,
74
+ {
75
+ headers: { "Content-type": "application/json" },
76
+ },
77
+ );
78
+ expect(response.data.body.key).toEqual("value");
79
+ expect(response.data.rawBody).toEqual('{"key": "value"}');
80
+ });
81
+
82
+ describe("invalid/improper mime types", () => {
83
+ test(".body will be empty if the content-type cannot be handled by formidable and not crash", async () => {
84
+ const requestBody = "<texty>this is like xml</texty>";
85
+ const response = await axios.post(
86
+ url + "/api/paramTestAction",
87
+ requestBody,
88
+ {
89
+ headers: { "Content-type": "text/xml" },
90
+ },
91
+ );
92
+ expect(response.data.body).toEqual({});
93
+ expect(response.data.rawBody).toEqual(requestBody);
94
+ });
95
+
96
+ // TODO: mime types with axios are too strong
97
+ test.skip("will set the body properly if mime type is wrong (bad header)", async () => {
98
+ const requestBody = "<texty>this is like xml</texty>";
99
+ const response = await axios.post(
100
+ url + "/api/paramTestAction",
101
+ requestBody,
102
+ {
103
+ headers: { "Content-type": "application/json" },
104
+ },
105
+ );
106
+ expect(response.data.body).toEqual({});
107
+ expect(response.data.rawBody).toEqual(requestBody);
108
+ });
109
+
110
+ test("will set the body properly if mime type is wrong (text)", async () => {
111
+ const requestBody = "I am normal \r\n text with \r\n line breaks";
112
+ const response = await axios.post(
113
+ url + "/api/paramTestAction",
114
+ requestBody,
115
+ {
116
+ headers: { "Content-type": "text/plain" },
117
+ },
118
+ );
119
+ expect(response.data.body).toEqual({});
120
+ expect(response.data.rawBody).toEqual(requestBody);
121
+ });
122
+
123
+ // TODO Axios doesn't pipe
124
+ test.skip("rawBody will exist if the content-type cannot be handled by formidable", async () => {
125
+ const requestPart1 = "<texty><innerNode>more than";
126
+ const requestPart2 = " two words</innerNode></texty>";
127
+
128
+ const bufferStream = new PassThrough();
129
+ const req = axios.post(url + "/api/paramTestAction", {
130
+ headers: { "Content-type": "text/xml" },
131
+ });
132
+ bufferStream.write(Buffer.from(requestPart1)); // write the first part
133
+ // @ts-ignore (we are not await-ing)
134
+ bufferStream.pipe(req);
135
+
136
+ setTimeout(() => {
137
+ bufferStream.end(Buffer.from(requestPart2)); // end signals no more is coming
138
+ }, 50);
139
+
140
+ await new Promise((resolve, reject) => {
141
+ bufferStream.on("finish", resolve);
142
+ });
143
+
144
+ const { data } = await req;
145
+ expect(data.error).toBeUndefined();
146
+ expect(data.body).toEqual({});
147
+ expect(data.rawBody).toEqual(requestPart1 + requestPart2);
148
+ });
149
+
150
+ // TODO Axios doesn't pipe
151
+ test.skip("rawBody and form will process JSON with odd stream testing", async () => {
152
+ const requestJson = { a: 1, b: "two" };
153
+ const requestString = JSON.stringify(requestJson);
154
+ const middleIdx = Math.floor(requestString.length / 2);
155
+ const requestPart1 = requestString.substring(0, middleIdx);
156
+ const requestPart2 = requestString.substring(middleIdx);
157
+
158
+ const bufferStream = new PassThrough();
159
+ const req = axios.post(url + "/api/paramTestAction", {
160
+ headers: { "Content-type": "application/json" },
161
+ });
162
+ bufferStream.write(Buffer.from(requestPart1)); // write the first part
163
+ // @ts-ignore (we are not await-ing)
164
+ bufferStream.pipe(req);
165
+
166
+ setTimeout(() => {
167
+ bufferStream.end(Buffer.from(requestPart2)); // end signals no more is coming
168
+ }, 50);
169
+
170
+ await new Promise((resolve, reject) => {
171
+ bufferStream.on("finish", resolve);
172
+ });
173
+
174
+ const { data } = await req;
175
+ expect(data.error).toBeUndefined();
176
+ expect(data.body).toEqual(requestJson);
177
+ expect(data.rawBody).toEqual(requestString);
178
+ });
179
+
180
+ // TODO Axios doesn't pipe
181
+ test.skip("rawBody processing will not hang on writable error", async () => {
182
+ const requestPart1 = "<texty><innerNode>more than";
183
+
184
+ const bufferStream = new PassThrough();
185
+ const req = axios.post(url + "/api/paramTestAction", {
186
+ headers: { "Content-type": "text/xml" },
187
+ });
188
+ bufferStream.write(Buffer.from(requestPart1)); // write the first part
189
+ // @ts-ignore (we are not await-ing)
190
+ bufferStream.pipe(req);
191
+
192
+ setTimeout(() => {
193
+ // bufferStream.destroy(new Error('This stream is broken.')) // sends an error and closes the stream
194
+ bufferStream.end();
195
+ }, 50);
196
+
197
+ await new Promise((resolve, reject) => {
198
+ bufferStream.on("finish", resolve);
199
+ });
200
+
201
+ const { data } = await req;
202
+ expect(data.error).toBeUndefined();
203
+ expect(data.body).toEqual({});
204
+ expect(data.rawBody).toEqual(requestPart1); // stream ends with only one part processed
205
+ });
206
+ });
207
+ });
208
+ });
@@ -0,0 +1,55 @@
1
+ import axios, { AxiosError } from "axios";
2
+ import { Process, config } from "./../../../src/index";
3
+
4
+ const actionhero = new Process();
5
+ let url: string;
6
+
7
+ const toJson = async (string: string) => {
8
+ try {
9
+ return JSON.parse(string);
10
+ } catch (error) {
11
+ return error;
12
+ }
13
+ };
14
+
15
+ jest.mock("./../../../src/config/web.ts", () => ({
16
+ __esModule: true,
17
+ test: {
18
+ web: () => {
19
+ return {
20
+ returnErrorCodes: false,
21
+ enabled: true,
22
+ secure: false,
23
+ urlPathForActions: "api",
24
+ urlPathForFiles: "public",
25
+ rootEndpointType: "file",
26
+ port: 18080 + parseInt(process.env.JEST_WORKER_ID || "0"),
27
+ matchExtensionMime: true,
28
+ metadataOptions: {
29
+ serverInformation: true,
30
+ requesterInformation: false,
31
+ },
32
+ fingerprintOptions: {
33
+ cookieKey: "sessionID",
34
+ },
35
+ };
36
+ },
37
+ },
38
+ }));
39
+
40
+ describe("Server: Web", () => {
41
+ beforeAll(async () => {
42
+ await actionhero.start();
43
+ url = "http://localhost:" + config.web!.port;
44
+ });
45
+
46
+ afterAll(async () => await actionhero.stop());
47
+
48
+ describe("errorCodes", () => {
49
+ test("returnErrorCodes false should still have a status of 200", async () => {
50
+ config.web!.returnErrorCodes = false;
51
+ const response = await axios.delete(url + "/api/");
52
+ expect(response.status).toEqual(200);
53
+ });
54
+ });
55
+ });
@@ -0,0 +1,96 @@
1
+ import axios, { AxiosError } from "axios";
2
+ import { Process, config } from "./../../../../src/index";
3
+
4
+ const actionhero = new Process();
5
+ let url: string;
6
+
7
+ jest.mock("./../../../../src/config/web.ts", () => ({
8
+ __esModule: true,
9
+ test: {
10
+ web: () => {
11
+ return {
12
+ enabled: true,
13
+ secure: false,
14
+ urlPathForActions: "namespace/actions",
15
+ urlPathForFiles: "namespace/files",
16
+ rootEndpointType: "file",
17
+ port: 18080 + parseInt(process.env.JEST_WORKER_ID || "0"),
18
+ matchExtensionMime: true,
19
+ metadataOptions: {
20
+ serverInformation: true,
21
+ requesterInformation: false,
22
+ },
23
+ fingerprintOptions: {
24
+ cookieKey: "sessionID",
25
+ },
26
+ };
27
+ },
28
+ },
29
+ }));
30
+
31
+ describe("Server: Web", () => {
32
+ describe("Routes", () => {
33
+ beforeAll(async () => {
34
+ await actionhero.start();
35
+ url = "http://localhost:" + config.web!.port;
36
+ });
37
+
38
+ afterAll(async () => {
39
+ await actionhero.stop();
40
+ });
41
+
42
+ describe("simple routing", () => {
43
+ describe("deep routes", () => {
44
+ test("old action routes stop working", async () => {
45
+ try {
46
+ await axios.get(url + "/api/randomNumber");
47
+ throw new Error("should not get here");
48
+ } catch (error) {
49
+ if (error instanceof AxiosError) {
50
+ expect(error.response?.status).toEqual(404);
51
+ } else throw error;
52
+ }
53
+ });
54
+
55
+ test("can ask for nested URL actions", async () => {
56
+ const response = await axios.get(
57
+ url + "/namespace/actions/randomNumber",
58
+ );
59
+ expect(response.status).toEqual(200);
60
+ });
61
+
62
+ test("old file routes stop working", async () => {
63
+ try {
64
+ await axios.get(url + "/public/simple.html");
65
+ throw new Error("should not get here");
66
+ } catch (error) {
67
+ if (error instanceof AxiosError) {
68
+ expect(error.response?.status).toEqual(404);
69
+ } else throw error;
70
+ }
71
+ });
72
+
73
+ test("can ask for nested URL files", async () => {
74
+ const response = await axios.get(
75
+ url + "/namespace/files/simple.html",
76
+ );
77
+ expect(response.status).toEqual(200);
78
+ expect(response.data).toContain("<h1>Actionhero</h1>");
79
+ });
80
+
81
+ test("can ask for nested URL files with depth", async () => {
82
+ const response = await axios.get(
83
+ url + "/namespace/files/css/cosmo.css",
84
+ );
85
+ expect(response.status).toEqual(200);
86
+ });
87
+
88
+ test("root route files still work", async () => {
89
+ const response = await axios.get(url + "/simple.html");
90
+ expect(response.status).toEqual(200);
91
+ expect(response.data).toContain("<h1>Actionhero</h1>");
92
+ });
93
+ });
94
+ });
95
+ });
96
+ });