UNPKG

actionhero

Version:

The reusable, scalable, and quick node.js API server for stateless and stateful applications

192 lines (168 loc) 6.58 kB
import * as request from "request-promise-native"; import * as child_process from "child_process"; import { Process, config, utils, specHelper } from "../../../src/index"; const actionhero = new Process(); let url; async function exec(command) { return new Promise((resolve, reject) => { child_process.exec(command, (error, stdout, stderr) => { if (error) { return reject(error); } return resolve({ stdout, stderr }); }); }); } describe("Core", () => { describe("static file", () => { beforeAll(async () => { await actionhero.start(); url = "http://localhost:" + config.servers.web.port + "/" + config.servers.web.urlPathForFiles; }); afterAll(async () => { await actionhero.stop(); }); test("file: an HTML file", async () => { const response = await specHelper.getStaticFile("simple.html"); expect(response.mime).toEqual("text/html"); expect(response.content).toContain("<h1>Actionhero</h1>"); }); test("file: 404 pages", async () => { const response = await specHelper.getStaticFile("someRandomFile"); expect(response.error).toEqual("That file is not found"); expect(response.content).toBeNull(); }); test("I should not see files outside of the public dir", async () => { const response = await specHelper.getStaticFile("../config/config.json"); expect(response.error).toEqual("That file is not found"); expect(response.content).toBeNull(); }); test("file: sub paths should work", async () => { const response = await specHelper.getStaticFile("logo/actionhero.png"); expect(response.mime).toEqual("image/png"); expect(response.length).toEqual(59273); // wacky per-OS encoding issues I guess? expect(response.content.length).toBeGreaterThanOrEqual(50000); expect(response.content.length).toBeLessThan(60000); }); test("should send back the cache-control header", async () => { const response = await request.get(url + "/simple.html", { resolveWithFullResponse: true, }); expect(response.statusCode).toEqual(200); expect(response.headers["cache-control"]).toBeTruthy(); }); test("should send back the etag header", async () => { const response = await request.get(url + "/simple.html", { resolveWithFullResponse: true, }); expect(response.statusCode).toEqual(200); expect(response.headers.etag).toBeTruthy(); }); test('should send back a 304 if the header "if-modified-since" is present and condition matches', async () => { const response = await request.get(url + "/simple.html", { resolveWithFullResponse: true, }); expect(response.statusCode).toEqual(200); try { await request(url + "/simple.html", { headers: { "If-Modified-Since": new Date().toUTCString() }, resolveWithFullResponse: true, }); throw new Error("should not get here"); } catch (error) { expect(error.toString()).toMatch(/304/); } }); test("should send back a 304 if the ETAG header is present", async () => { const response = await request.get(url + "/simple.html", { resolveWithFullResponse: true, }); expect(response.statusCode).toEqual(200); expect(response.body).toContain("<h1>Actionhero</h1>"); expect(response.headers.etag).toBeTruthy(); const etag = response.headers.etag; const options = { headers: { "If-None-Match": etag }, resolveWithFullResponse: true, }; try { await request(url + "/simple.html", options); throw new Error("should not get here"); } catch (error) { expect(error.toString()).toMatch(/304/); } }); test("should send a different etag for other files", async () => { const response = await request.get(url + "/simple.html", { resolveWithFullResponse: true, }); expect(response.statusCode).toEqual(200); expect(response.headers.etag).toBeTruthy(); const etag = response.headers.etag; const secondResponse = await request.get(url + "/index.html", { resolveWithFullResponse: true, }); expect(secondResponse.statusCode).toEqual(200); expect(secondResponse.headers.etag).toBeTruthy(); const etagTwo = secondResponse.headers.etag; expect(etagTwo).not.toEqual(etag); }); test('should send back the file if the header "if-modified-since" is present but condition does not match', async () => { const response = await request.get(url + "/simple.html", { resolveWithFullResponse: true, }); expect(response.statusCode).toEqual(200); const lastModified = new Date(response.headers["last-modified"]); const delay = 24 * 1000 * 3600; const secondResponse = await request(url + "/simple.html", { headers: { "If-Modified-Since": new Date( lastModified.getTime() - delay ).toUTCString(), }, resolveWithFullResponse: true, }); expect(secondResponse.statusCode).toEqual(200); expect(secondResponse.body.length).toBeGreaterThan(1); }); if (process.platform === "win32") { console.log( "*** CANNOT RUN FILE DESCRIPTOR TESTS ON WINDOWS. Sorry. ***" ); } else { describe("do not leave open file descriptors ", () => { const lsofChk = async () => { //@ts-ignore const { stdout } = await exec('lsof -n -P|grep "/simple.html"|wc -l'); return stdout.trim(); }; test("closes all descriptors on statusCode 200 responses", async () => { const response = await request.get(url + "/simple.html", { resolveWithFullResponse: true, }); expect(response.statusCode).toEqual(200); await utils.sleep(100); expect(await lsofChk()).toEqual("0"); }, 30000); test("closes all descriptors on statusCode 304 responses", async () => { try { await request.get(url + "/simple.html", { headers: { "if-none-match": "*" }, resolveWithFullResponse: true, }); throw new Error("should return 304"); } catch (error) { expect(error.statusCode).toEqual(304); await utils.sleep(100); expect(await lsofChk()).toEqual("0"); } }, 30000); }); } }); });