Merge pull request 'Integration tests for API' (#53) from testing into main
Reviewed-on: #53
This commit is contained in:
commit
48b9a4c8fb
7
.gitignore
vendored
7
.gitignore
vendored
@ -20,5 +20,12 @@ Thumbs.db
|
|||||||
vite.config.js.timestamp-*
|
vite.config.js.timestamp-*
|
||||||
vite.config.ts.timestamp-*
|
vite.config.ts.timestamp-*
|
||||||
|
|
||||||
|
# Playwright
|
||||||
|
/test-results/
|
||||||
|
/playwright-report/
|
||||||
|
/blob-report/
|
||||||
|
/playwright/.cache/
|
||||||
|
/playwright/.auth
|
||||||
|
|
||||||
uploads
|
uploads
|
||||||
.direnv
|
.direnv
|
||||||
|
64
package-lock.json
generated
64
package-lock.json
generated
@ -12,6 +12,7 @@
|
|||||||
"uuid": "^10.0.0"
|
"uuid": "^10.0.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@playwright/test": "^1.46.1",
|
||||||
"@sveltejs/adapter-auto": "^3.0.0",
|
"@sveltejs/adapter-auto": "^3.0.0",
|
||||||
"@sveltejs/adapter-node": "^5.2.0",
|
"@sveltejs/adapter-node": "^5.2.0",
|
||||||
"@sveltejs/kit": "^2.0.0",
|
"@sveltejs/kit": "^2.0.0",
|
||||||
@ -734,6 +735,22 @@
|
|||||||
"node": ">=14"
|
"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": {
|
"node_modules/@polka/url": {
|
||||||
"version": "1.0.0-next.25",
|
"version": "1.0.0-next.25",
|
||||||
"resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.25.tgz",
|
"resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.25.tgz",
|
||||||
@ -3643,6 +3660,53 @@
|
|||||||
"url": "https://github.com/sponsors/jonschlinkert"
|
"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": {
|
"node_modules/postcss": {
|
||||||
"version": "8.4.41",
|
"version": "8.4.41",
|
||||||
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.41.tgz",
|
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.41.tgz",
|
||||||
|
@ -6,13 +6,16 @@
|
|||||||
"dev": "vite dev",
|
"dev": "vite dev",
|
||||||
"build": "vite build",
|
"build": "vite build",
|
||||||
"preview": "vite preview",
|
"preview": "vite preview",
|
||||||
"test": "vitest",
|
"test": "npm run test:integration && npm run test:unit",
|
||||||
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
|
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
|
||||||
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
|
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
|
||||||
"lint": "prettier --check . && eslint .",
|
"lint": "prettier --check . && eslint .",
|
||||||
"format": "prettier --write ."
|
"format": "prettier --write .",
|
||||||
|
"test:integration": "playwright test",
|
||||||
|
"test:unit": "vitest"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@playwright/test": "^1.46.1",
|
||||||
"@sveltejs/adapter-auto": "^3.0.0",
|
"@sveltejs/adapter-auto": "^3.0.0",
|
||||||
"@sveltejs/adapter-node": "^5.2.0",
|
"@sveltejs/adapter-node": "^5.2.0",
|
||||||
"@sveltejs/kit": "^2.0.0",
|
"@sveltejs/kit": "^2.0.0",
|
||||||
|
12
playwright.config.ts
Normal file
12
playwright.config.ts
Normal file
@ -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;
|
@ -1,9 +1,7 @@
|
|||||||
import { log, timedExecution } from '$lib';
|
import { log, timedExecution, requestIdHeader } from '$lib';
|
||||||
import { validate, v7 as uuidv7 } from 'uuid';
|
import { validate, v7 as uuidv7 } from 'uuid';
|
||||||
import type { Handle } from '@sveltejs/kit';
|
import type { Handle } from '@sveltejs/kit';
|
||||||
|
|
||||||
const requestIdHeader = 'x-request-id';
|
|
||||||
|
|
||||||
export const handle: Handle = async ({ event, resolve }) => {
|
export const handle: Handle = async ({ event, resolve }) => {
|
||||||
// use incoming requestId, if it is a valid uuid, else generate one
|
// use incoming requestId, if it is a valid uuid, else generate one
|
||||||
const reqIdFromRequest = event.request.headers.get(requestIdHeader);
|
const reqIdFromRequest = event.request.headers.get(requestIdHeader);
|
||||||
|
@ -29,6 +29,8 @@ if (!('STORAGE_PATH' in process.env)) {
|
|||||||
}
|
}
|
||||||
export const storagePath: string = process.env.STORAGE_PATH ?? defaultPath;
|
export const storagePath: string = process.env.STORAGE_PATH ?? defaultPath;
|
||||||
|
|
||||||
|
export const requestIdHeader = 'x-request-id';
|
||||||
|
|
||||||
export default safePath;
|
export default safePath;
|
||||||
|
|
||||||
export async function timedExecution<T>(
|
export async function timedExecution<T>(
|
||||||
|
13
tests/health.test.ts
Normal file
13
tests/health.test.ts
Normal file
@ -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');
|
||||||
|
});
|
10
tests/page.test.ts
Normal file
10
tests/page.test.ts
Normal file
@ -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');
|
||||||
|
});
|
37
tests/requestid.test.ts
Normal file
37
tests/requestid.test.ts
Normal file
@ -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);
|
||||||
|
});
|
Reference in New Issue
Block a user