From 7c26f8189cd777436184e38a3c726b21bfbbf0d3 Mon Sep 17 00:00:00 2001 From: Nathan Houle Date: Mon, 24 Mar 2025 11:08:20 -0700 Subject: [PATCH] test: remove certs script We currently have a `certs` npm script that generates self-signed certificates for use in a single zisi test. This script must be run before running tests, otherwise the zisi test in question will fail. This changeset moves this certificate generation into a test helper function, ensuring that a certificate will always be available when needed by a test. It would probably be simpler to instead generate a certificate that never expires and inline it into the fixture (eliminating the need for an available `openssl` binary), but this works fine. --- .github/workflows/integration-tests.yml | 10 --- certconf | 8 --- package-lock.json | 23 +++++++ package.json | 4 +- .../integration/commands/dev/dev.zisi.test.ts | 62 ++++++++++++++++--- 5 files changed, 80 insertions(+), 27 deletions(-) delete mode 100644 certconf diff --git a/.github/workflows/integration-tests.yml b/.github/workflows/integration-tests.yml index b66c6b2acc2..5a879908d0c 100644 --- a/.github/workflows/integration-tests.yml +++ b/.github/workflows/integration-tests.yml @@ -77,11 +77,6 @@ jobs: - name: Build project run: npm run build - - name: Generate self-signed certificates - run: npm run certs - if: '${{!steps.release-check.outputs.IS_RELEASE}}' - shell: bash - - name: Prepare tests run: npm run test:init if: '${{ !steps.release-check.outputs.IS_RELEASE }}' @@ -192,11 +187,6 @@ jobs: - name: Build project run: npm run build - - name: Generate self-signed certificates - run: npm run certs - if: '${{!steps.release-check.outputs.IS_RELEASE}}' - shell: bash - - name: Prepare tests run: npm run test:init if: '${{ !steps.release-check.outputs.IS_RELEASE }}' diff --git a/certconf b/certconf deleted file mode 100644 index a2d9eb4fa24..00000000000 --- a/certconf +++ /dev/null @@ -1,8 +0,0 @@ -[dn] -CN=localhost -[req] -distinguished_name = dn -[EXT] -subjectAltName=DNS:localhost -keyUsage=digitalSignature -extendedKeyUsage=serverAuth \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index e3617311e1b..30e4f33f026 100644 --- a/package-lock.json +++ b/package-lock.json @@ -154,6 +154,7 @@ "@vitest/eslint-plugin": "^1.1.36", "c8": "10.1.3", "cheerio": "1.0.0", + "dedent": "^1.5.3", "eslint": "^9.21.0", "eslint-config-prettier": "^10.0.2", "eslint-plugin-n": "^17.16.1", @@ -10069,6 +10070,21 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/dedent": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.3.tgz", + "integrity": "sha512-NHQtfOOW68WD8lgypbLA5oT+Bt0xXJhiYvoR6SmmNXZfpzOGXwdKWmcwG8N7PwVVWV3eF/68nmD9BaJSsTBhyQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "babel-plugin-macros": "^3.1.0" + }, + "peerDependenciesMeta": { + "babel-plugin-macros": { + "optional": true + } + } + }, "node_modules/deep-eql": { "version": "4.1.4", "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.4.tgz", @@ -27302,6 +27318,13 @@ } } }, + "dedent": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.3.tgz", + "integrity": "sha512-NHQtfOOW68WD8lgypbLA5oT+Bt0xXJhiYvoR6SmmNXZfpzOGXwdKWmcwG8N7PwVVWV3eF/68nmD9BaJSsTBhyQ==", + "dev": true, + "requires": {} + }, "deep-eql": { "version": "4.1.4", "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.4.tgz", diff --git a/package.json b/package.json index f5fce029c8c..1b4ac687e17 100644 --- a/package.json +++ b/package.json @@ -33,7 +33,6 @@ "scripts": { "_format": "prettier --loglevel=warn \"{src,tools,scripts,tests,.github}/**/*.{mjs,cjs,js,mts,md,yml,json,html,ts}\" \"*.{mjs,cjs,js,mts,yml,json,html,ts}\" \".*.{mjs,cjs,js,yml,json,html,ts}\" \"!CHANGELOG.md\" \"!**/*/package-lock.json\" \"!.github/**/*.md\"", "build": "tsc --project tsconfig.build.json", - "certs": "openssl req -x509 -out localhost.crt -keyout localhost.key -newkey rsa:2048 -nodes -sha256 -subj \"/CN=localhost\" -extensions EXT -config certconf", "clean": "rm -rf dist/", "dev": "tsc --project tsconfig.build.json --watch", "docs": "npm run --prefix=site build", @@ -44,7 +43,7 @@ "test": "npm run test:dev", "lint": "eslint --cache \"{src,scripts,tests,.github}/**/*.{mjs,cjs,js,md,html}\" \"*.{mjs,cjs,js,md,html}\"", "lint:fix": "npm run lint --fix", - "test:dev": "run-s certs test:init:* test:dev:*", + "test:dev": "run-s test:init:* test:dev:*", "test:dev:vitest": "vitest run tests/unit/ && vitest run tests/integration", "test:init": "run-s test:init:*", "test:init:cli-help": "npm run start -- --help", @@ -202,6 +201,7 @@ "@vitest/eslint-plugin": "^1.1.36", "c8": "10.1.3", "cheerio": "1.0.0", + "dedent": "^1.5.3", "eslint": "^9.21.0", "eslint-config-prettier": "^10.0.2", "eslint-plugin-n": "^17.16.1", diff --git a/tests/integration/commands/dev/dev.zisi.test.ts b/tests/integration/commands/dev/dev.zisi.test.ts index e345dd326d0..6c62181fd06 100644 --- a/tests/integration/commands/dev/dev.zisi.test.ts +++ b/tests/integration/commands/dev/dev.zisi.test.ts @@ -1,14 +1,16 @@ // Handlers are meant to be async outside tests -import { Buffer } from 'buffer' -import fs, { copyFile } from 'fs/promises' +import { Buffer } from 'node:buffer' +import fs from 'node:fs/promises' import { Agent } from 'node:https' -import os from 'os' -import path from 'path' -import { fileURLToPath } from 'url' +import os from 'node:os' +import path from 'node:path' +import { fileURLToPath } from 'node:url' import type { HandlerEvent } from '@netlify/functions' import { describe, test } from 'vitest' import nodeFetch from 'node-fetch' +import execa from 'execa' +import dedent from 'dedent' import { curl } from '../../utils/curl.js' import { withDevServer } from '../../utils/dev-server.js' @@ -19,6 +21,51 @@ const __dirname = path.dirname(fileURLToPath(import.meta.url)) const testMatrix = [{ args: [] }] +const generateSSLCertificate = async () => { + const tmpdir = await fs.mkdtemp(path.join(os.tmpdir(), 'certs-')) + + await fs.writeFile( + path.join(tmpdir, 'certconf'), + dedent` + [dn] + CN=localhost + [req] + distinguished_name = dn + [EXT] + subjectAltName=DNS:localhost + keyUsage=digitalSignature + extendedKeyUsage=serverAuth + `, + ) + await execa( + 'openssl', + [ + 'req', + '-x509', + '-out', + 'localhost.crt', + '-keyout', + 'localhost.key', + '-newkey', + 'rsa:2048', + '-nodes', + '-sha256', + '-subj', + '/CN=localhost', + '-extensions', + 'EXT', + '-config', + 'certconf', + ], + { cwd: tmpdir }, + ) + + return { + cert: path.join(tmpdir, 'localhost.crt'), + key: path.join(tmpdir, 'localhost.key'), + } +} + describe.concurrent.each(testMatrix)('withSiteBuilder with args: $args', ({ args }) => { test('should handle query params in redirects', async (t) => { await withSiteBuilder(t, async (builder) => { @@ -257,9 +304,10 @@ export const handler = async function () { }) .build() + const certificatePaths = await generateSSLCertificate() await Promise.all([ - copyFile(path.join(__dirname, '../../../../localhost.crt'), path.join(builder.directory, 'localhost.crt')), - copyFile(path.join(__dirname, '../../../../localhost.key'), path.join(builder.directory, 'localhost.key')), + fs.copyFile(certificatePaths.cert, path.join(builder.directory, 'localhost.crt')), + fs.copyFile(certificatePaths.key, path.join(builder.directory, 'localhost.key')), ]) await withDevServer({ cwd: builder.directory, args }, async ({ port }) => { const options = {