From da92ed625853e97dcd521cee8433e2697f32cd8f Mon Sep 17 00:00:00 2001 From: Valentin Brandl Date: Sun, 18 Aug 2024 15:33:56 +0200 Subject: [PATCH 1/5] Move request-id header name to $lib --- src/hooks.server.ts | 4 +--- src/lib/index.ts | 2 ++ 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/hooks.server.ts b/src/hooks.server.ts index 4c99ccb..17372c1 100644 --- a/src/hooks.server.ts +++ b/src/hooks.server.ts @@ -1,9 +1,7 @@ -import { log, timedExecution } from '$lib'; +import { log, timedExecution, requestIdHeader } from '$lib'; import { validate, v7 as uuidv7 } from 'uuid'; import type { Handle } from '@sveltejs/kit'; -const requestIdHeader = 'x-request-id'; - export const handle: Handle = async ({ event, resolve }) => { // use incoming requestId, if it is a valid uuid, else generate one const reqIdFromRequest = event.request.headers.get(requestIdHeader); diff --git a/src/lib/index.ts b/src/lib/index.ts index 7cee25d..c2c405a 100644 --- a/src/lib/index.ts +++ b/src/lib/index.ts @@ -29,6 +29,8 @@ if (!('STORAGE_PATH' in process.env)) { } export const storagePath: string = process.env.STORAGE_PATH ?? defaultPath; +export const requestIdHeader = 'x-request-id'; + export default safePath; export async function timedExecution( From 0fd1f178be230621f9f604dda4740d0dae59d747 Mon Sep 17 00:00:00 2001 From: Valentin Brandl Date: Sun, 18 Aug 2024 15:34:19 +0200 Subject: [PATCH 2/5] Add playwright --- .gitignore | 7 +++++ package-lock.json | 64 ++++++++++++++++++++++++++++++++++++++++++++ package.json | 7 +++-- playwright.config.ts | 12 +++++++++ 4 files changed, 88 insertions(+), 2 deletions(-) create mode 100644 playwright.config.ts diff --git a/.gitignore b/.gitignore index 8a052ce..6da40df 100644 --- a/.gitignore +++ b/.gitignore @@ -20,5 +20,12 @@ Thumbs.db vite.config.js.timestamp-* vite.config.ts.timestamp-* +# Playwright +/test-results/ +/playwright-report/ +/blob-report/ +/playwright/.cache/ +/playwright/.auth + uploads .direnv diff --git a/package-lock.json b/package-lock.json index dcec71b..98189f5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,6 +12,7 @@ "uuid": "^10.0.0" }, "devDependencies": { + "@playwright/test": "^1.46.1", "@sveltejs/adapter-auto": "^3.0.0", "@sveltejs/adapter-node": "^5.2.0", "@sveltejs/kit": "^2.0.0", @@ -734,6 +735,22 @@ "node": ">=14" } }, + "node_modules/@playwright/test": { + "version": "1.46.1", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.46.1.tgz", + "integrity": "sha512-Fq6SwLujA/DOIvNC2EL/SojJnkKf/rAwJ//APpJJHRyMi1PdKrY3Az+4XNQ51N4RTbItbIByQ0jgd1tayq1aeA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "playwright": "1.46.1" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/@polka/url": { "version": "1.0.0-next.25", "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.25.tgz", @@ -3643,6 +3660,53 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/playwright": { + "version": "1.46.1", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.46.1.tgz", + "integrity": "sha512-oPcr1yqoXLCkgKtD5eNUPLiN40rYEM39odNpIb6VE6S7/15gJmA1NzVv6zJYusV0e7tzvkU/utBFNa/Kpxmwng==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "playwright-core": "1.46.1" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "fsevents": "2.3.2" + } + }, + "node_modules/playwright-core": { + "version": "1.46.1", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.46.1.tgz", + "integrity": "sha512-h9LqIQaAv+CYvWzsZ+h3RsrqCStkBHlgo6/TJlFst3cOTlLghBQlJwPOZKQJTKNaD3QIB7aAVQ+gfWbN3NXB7A==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "playwright-core": "cli.js" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/playwright/node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, "node_modules/postcss": { "version": "8.4.41", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.41.tgz", diff --git a/package.json b/package.json index 503fd76..549b63a 100644 --- a/package.json +++ b/package.json @@ -6,13 +6,16 @@ "dev": "vite dev", "build": "vite build", "preview": "vite preview", - "test": "vitest", + "test": "npm run test:integration && npm run test:unit", "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json", "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch", "lint": "prettier --check . && eslint .", - "format": "prettier --write ." + "format": "prettier --write .", + "test:integration": "playwright test", + "test:unit": "vitest" }, "devDependencies": { + "@playwright/test": "^1.46.1", "@sveltejs/adapter-auto": "^3.0.0", "@sveltejs/adapter-node": "^5.2.0", "@sveltejs/kit": "^2.0.0", diff --git a/playwright.config.ts b/playwright.config.ts new file mode 100644 index 0000000..770c7ff --- /dev/null +++ b/playwright.config.ts @@ -0,0 +1,12 @@ +import type { PlaywrightTestConfig } from '@playwright/test'; + +const config: PlaywrightTestConfig = { + webServer: { + command: 'npm run build && npm run preview', + port: 4173, + }, + testDir: 'tests', + testMatch: /(.+\.)?(test|spec)\.[jt]s/, +}; + +export default config; From 56f568634e94884a649b741e0f4f7f79fd403c22 Mon Sep 17 00:00:00 2001 From: Valentin Brandl Date: Sun, 18 Aug 2024 15:34:36 +0200 Subject: [PATCH 3/5] Implement first integration tests --- tests/health.test.ts | 13 +++++++++++++ tests/requestid.test.ts | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+) create mode 100644 tests/health.test.ts create mode 100644 tests/requestid.test.ts diff --git a/tests/health.test.ts b/tests/health.test.ts new file mode 100644 index 0000000..a096349 --- /dev/null +++ b/tests/health.test.ts @@ -0,0 +1,13 @@ +import { expect, test } from '@playwright/test'; + +test('healthy test', async ({ playwright }) => { + const context = await playwright.request.newContext(); + const response = await context.get('health'); + await expect(response.status()).toBe(200); + await expect(response.headers()).toHaveProperty('healthy'); + await expect(response.headers()['healthy']).toBe('true'); + + const body = await response.json(); + await expect(body).toHaveProperty('status'); + await expect(body['status']).toBe('OK'); +}); \ No newline at end of file diff --git a/tests/requestid.test.ts b/tests/requestid.test.ts new file mode 100644 index 0000000..1e12338 --- /dev/null +++ b/tests/requestid.test.ts @@ -0,0 +1,37 @@ +import { expect, test } from '@playwright/test'; +import { validate, NIL } from 'uuid'; +import { requestIdHeader } from '$lib'; + +test('response contains request-id header', async ({playwright}) => { + const context = await playwright.request.newContext(); + const response = await context.get('health'); + const headers = response.headers(); + await expect(headers).toHaveProperty(requestIdHeader); +}); + +test('request-id is valid uuid', async ({playwright}) => { + const context = await playwright.request.newContext(); + const response = await context.get('health'); + const headers = response.headers(); + const requestId = headers[requestIdHeader]; + await expect(validate(requestId)).toBe(true); +}); + +test('reuse valid incoming uuid', async ({playwright}) => { + const context = await playwright.request.newContext(); + + const response = await context.get('health', { headers: { [requestIdHeader]: NIL }}); + const headers = response.headers(); + const requestId = headers[requestIdHeader]; + await expect(requestId).toBe(NIL); +}); + +test('ignore invalid incoming uuid', async ({playwright}) => { + const invalid = '00000000-0000-0000-0000-00000000000z'; + const context = await playwright.request.newContext(); + + const response = await context.get('health', { headers: { [requestIdHeader]: invalid }}); + const headers = response.headers(); + const requestId = headers[requestIdHeader]; + await expect(requestId).not.toBe(invalid); +}); \ No newline at end of file From 20920586e07d067ad0d1aaccea2b5d1e74cf89d8 Mon Sep 17 00:00:00 2001 From: Valentin Brandl Date: Sun, 18 Aug 2024 15:38:03 +0200 Subject: [PATCH 4/5] Formatting --- tests/health.test.ts | 12 ++++++------ tests/requestid.test.ts | 38 +++++++++++++++++++------------------- 2 files changed, 25 insertions(+), 25 deletions(-) diff --git a/tests/health.test.ts b/tests/health.test.ts index a096349..73ba5a5 100644 --- a/tests/health.test.ts +++ b/tests/health.test.ts @@ -4,10 +4,10 @@ test('healthy test', async ({ playwright }) => { const context = await playwright.request.newContext(); const response = await context.get('health'); await expect(response.status()).toBe(200); - await expect(response.headers()).toHaveProperty('healthy'); - await expect(response.headers()['healthy']).toBe('true'); + await expect(response.headers()).toHaveProperty('healthy'); + await expect(response.headers()['healthy']).toBe('true'); - const body = await response.json(); - await expect(body).toHaveProperty('status'); - await expect(body['status']).toBe('OK'); -}); \ No newline at end of file + const body = await response.json(); + await expect(body).toHaveProperty('status'); + await expect(body['status']).toBe('OK'); +}); diff --git a/tests/requestid.test.ts b/tests/requestid.test.ts index 1e12338..03fc5ac 100644 --- a/tests/requestid.test.ts +++ b/tests/requestid.test.ts @@ -2,36 +2,36 @@ import { expect, test } from '@playwright/test'; import { validate, NIL } from 'uuid'; import { requestIdHeader } from '$lib'; -test('response contains request-id header', async ({playwright}) => { +test('response contains request-id header', async ({ playwright }) => { const context = await playwright.request.newContext(); const response = await context.get('health'); - const headers = response.headers(); - await expect(headers).toHaveProperty(requestIdHeader); + const headers = response.headers(); + await expect(headers).toHaveProperty(requestIdHeader); }); -test('request-id is valid uuid', async ({playwright}) => { +test('request-id is valid uuid', async ({ playwright }) => { const context = await playwright.request.newContext(); const response = await context.get('health'); - const headers = response.headers(); - const requestId = headers[requestIdHeader]; - await expect(validate(requestId)).toBe(true); + const headers = response.headers(); + const requestId = headers[requestIdHeader]; + await expect(validate(requestId)).toBe(true); }); -test('reuse valid incoming uuid', async ({playwright}) => { +test('reuse valid incoming uuid', async ({ playwright }) => { const context = await playwright.request.newContext(); - const response = await context.get('health', { headers: { [requestIdHeader]: NIL }}); - const headers = response.headers(); - const requestId = headers[requestIdHeader]; - await expect(requestId).toBe(NIL); + const response = await context.get('health', { headers: { [requestIdHeader]: NIL } }); + const headers = response.headers(); + const requestId = headers[requestIdHeader]; + await expect(requestId).toBe(NIL); }); -test('ignore invalid incoming uuid', async ({playwright}) => { - const invalid = '00000000-0000-0000-0000-00000000000z'; +test('ignore invalid incoming uuid', async ({ playwright }) => { + const invalid = '00000000-0000-0000-0000-00000000000z'; const context = await playwright.request.newContext(); - const response = await context.get('health', { headers: { [requestIdHeader]: invalid }}); - const headers = response.headers(); - const requestId = headers[requestIdHeader]; - await expect(requestId).not.toBe(invalid); -}); \ No newline at end of file + const response = await context.get('health', { headers: { [requestIdHeader]: invalid } }); + const headers = response.headers(); + const requestId = headers[requestIdHeader]; + await expect(requestId).not.toBe(invalid); +}); From 25ef50f35885e79a1fd297c45309109d2134c6ba Mon Sep 17 00:00:00 2001 From: Valentin Brandl Date: Sun, 18 Aug 2024 15:46:46 +0200 Subject: [PATCH 5/5] Add test for page --- tests/page.test.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 tests/page.test.ts diff --git a/tests/page.test.ts b/tests/page.test.ts new file mode 100644 index 0000000..7ffec07 --- /dev/null +++ b/tests/page.test.ts @@ -0,0 +1,10 @@ +import { expect, test } from '@playwright/test'; + +test('contains header text', async ({ playwright }) => { + const context = await playwright.request.newContext(); + const response = await context.get(''); + await expect(response.status()).toBe(200); + + const body = (await response.body()).toString(); + await expect(body).toContain('Gabi und Hannes Fotochallenge'); +});