diff --git a/.github/workflows/v3.x.code_validation.yml b/.github/workflows/v3.x.code_validation.yml index efd400e3..77f83e5a 100644 --- a/.github/workflows/v3.x.code_validation.yml +++ b/.github/workflows/v3.x.code_validation.yml @@ -70,7 +70,7 @@ jobs: matrix: # Add Windows when https://github.com/oven-sh/bun/issues/43 is complete os: [ubuntu-latest, macos-latest] - node-version: [16.x, 18.x, 20.x] + node-version: [18.x, 20.x] runs-on: ${{ matrix.os }} steps: @@ -103,7 +103,7 @@ jobs: strategy: matrix: os: [ubuntu-latest, windows-latest, macos-latest] - node-version: [16.x, 18.x, 20.x] + node-version: [18.x, 20.x] runs-on: ${{ matrix.os }} steps: @@ -159,7 +159,7 @@ jobs: strategy: matrix: os: [ubuntu-latest, windows-latest, macos-latest] - node-version: [16.x, 18.x, 20.x] + node-version: [18.x, 20.x] runs-on: ${{ matrix.os }} steps: @@ -192,7 +192,7 @@ jobs: strategy: matrix: os: [ubuntu-latest, windows-latest, macos-latest] - node-version: [16.x, 18.x, 20.x] + node-version: [18.x, 20.x] runs-on: ${{ matrix.os }} steps: diff --git a/tests/compat/node/node-v16.x/modules/RequestChain/polyfill/node-http-in-context-object/app.test.ts b/tests/compat/node/node-v16.x/modules/RequestChain/polyfill/node-http-in-context-object/app.test.ts deleted file mode 100644 index 2e9470c4..00000000 --- a/tests/compat/node/node-v16.x/modules/RequestChain/polyfill/node-http-in-context-object/app.test.ts +++ /dev/null @@ -1,154 +0,0 @@ -/** - * Drash - A microframework for building JavaScript/TypeScript HTTP systems. - * Copyright (C) 2023 Drash authors. The Drash authors are listed in the - * AUTHORS file at . This notice - * applies to Drash version 3.X.X and any later version. - * - * This file is part of Drash. See . - * - * Drash is free software: you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation, either version 3 of the License, or (at your option) any later - * version. - * - * Drash is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along with - * Drash. If not, see . - */ - -import { Socket } from "node:net"; -import { IncomingMessage, ServerResponse } from "node:http"; - -import { handleRequest } from "./app"; - -describe("Polyfill - Using IncomingMessage/ServerResponse in context object", () => { - describe.each(testCases())( - "Home / paths = /", - ({ method, expected }) => { - it(`${method} returns ${expected.status}`, async () => { - const req = new IncomingMessage(new Socket()); - req.method = method; - const res = new ServerResponse(req); - - await handleRequest(req, res); - const body = getBody(res); - - expect(body).toBe(expected.body); - expect(res.statusCode).toBe(expected.status); - }); - }, - ); - - describe.each(testCasesNotFound())( - "Non-existent endpoints / path = test", - ({ method, expected }) => { - it(`${method} returns ${expected.status}`, async () => { - const req = new IncomingMessage(new Socket()); - req.url = `/test`; - req.method = method; - const res = new ServerResponse(req); - - await handleRequest(req, res); - const body = getBody(res); - - expect(body).toBe(expected.body); - expect(res.statusCode).toBe(expected.status); - }); - }, - ); -}); - -function getBody(response: ServerResponse) { - const json = JSON.parse(JSON.stringify(response)); - - const body: string[] = []; - - for (const output of json.outputData) { - body.push(output.data.replace(json._header, "")); - } - - return body.join(""); -} - -function testCases() { - return [ - { - method: "GET", - expected: { - status: 200, - body: "Hello from GET.", - }, - }, - { - method: "POST", - expected: { - status: 200, - body: "Hello from POST.", - }, - }, - { - method: "PUT", - expected: { - status: 501, - body: "Not Implemented", - }, - }, - { - method: "DELETE", - expected: { - status: 500, - body: "Hey, I'm the DELETE endpoint. Errrr.", - }, - }, - { - method: "PATCH", - expected: { - status: 405, - body: "Method Not Allowed", - }, - }, - ]; -} - -function testCasesNotFound() { - return [ - { - method: "GET", - expected: { - status: 404, - body: "Not Found", - }, - }, - { - method: "POST", - expected: { - status: 404, - body: "Not Found", - }, - }, - { - method: "PUT", - expected: { - status: 404, - body: "Not Found", - }, - }, - { - method: "DELETE", - expected: { - status: 404, - body: "Not Found", - }, - }, - { - method: "PATCH", - expected: { - status: 404, - body: "Not Found", - }, - }, - ]; -} diff --git a/tests/compat/node/node-v16.x/modules/RequestChain/polyfill/node-http-in-context-object/app.ts b/tests/compat/node/node-v16.x/modules/RequestChain/polyfill/node-http-in-context-object/app.ts deleted file mode 100644 index b0f2a1b3..00000000 --- a/tests/compat/node/node-v16.x/modules/RequestChain/polyfill/node-http-in-context-object/app.ts +++ /dev/null @@ -1,105 +0,0 @@ -/** - * Drash - A microframework for building JavaScript/TypeScript HTTP systems. - * Copyright (C) 2023 Drash authors. The Drash authors are listed in the - * AUTHORS file at . This notice - * applies to Drash version 3.X.X and any later version. - * - * This file is part of Drash. See . - * - * Drash is free software: you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation, either version 3 of the License, or (at your option) any later - * version. - * - * Drash is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along with - * Drash. If not, see . - */ - -import { IncomingMessage, ServerResponse } from "node:http"; - -import { HTTPError } from "../../../../../../../../dist/core/errors/HTTPError"; -import { StatusCode } from "../../../../../../../../dist/core/http/response/StatusCode"; -import { StatusDescription } from "../../../../../../../../dist/core/http/response/StatusDescription"; -import * as Chain from "../../../../../../../../dist/modules/chains/RequestChain/mod.polyfill"; -import { Status } from "../../../../../../../../dist/core/http/response/Status"; - -export const protocol = "http"; -export const hostname = "localhost"; -export const port = 1447; - -type NodeContext = { - url: string; - method?: string; - request: IncomingMessage; - response: ServerResponse; -}; - -class Home extends Chain.Resource { - public paths = ["/"]; - - public GET(context: NodeContext) { - context.response.setHeader("x-drash", "Home.GET()"); - context.response.write("Hello from GET."); - return context; - } - - public POST(context: NodeContext) { - context.response.setHeader("x-drash", "Home.POST()"); - context.response.write("Hello from POST."); - } - - public DELETE(context: NodeContext) { - context.response.setHeader("x-drash", "Home.DELETE()"); - throw new Error("Hey, I'm the DELETE endpoint. Errrr."); - } - - public PATCH(context: NodeContext) { - context.response.setHeader("x-drash", "Home.PATCH()"); - throw new HTTPError(Status.MethodNotAllowed); - } -} - -const chain = Chain - .builder() - .resources(Home) - .build(); - -export const handleRequest = ( - request: IncomingMessage, - response: ServerResponse, -): Promise => { - // We will keep the IncomingMessage and ServerResponse objects intact and just - // provide url and method to let the chain know how to route the request - const context = { - url: `${protocol}://${hostname}:${port}${request.url}`, - method: request.method, - request, - response, - }; - - return chain - .handle(context) - // There is no `.then((response) => { ... })` block here because resources - // use `context.response.end()` which tells Node the ServerResponse ended - .catch((error: Error | HTTPError) => { - if ( - (error.name === "HTTPError" || error instanceof HTTPError) && - "status_code" in error && - "status_code_description" in error - ) { - context.response.statusCode = error.status_code; - context.response.statusMessage = error.status_code_description; - context.response.end(error.message); - } else { - context.response.statusCode = StatusCode.InternalServerError; - context.response.statusMessage = StatusDescription.InternalServerError; - context.response.end(error.message); - } - - return context; - }); -};