Add testing frameworks

This commit is contained in:
Djuri Baars 2023-11-23 02:04:20 +01:00
parent fd492c416c
commit a9c12c2e9f
11 changed files with 1315 additions and 189 deletions

View file

@ -63,6 +63,18 @@ jobs:
run: yarn && yarn postinstall run: yarn && yarn postinstall
- name: Run linter - name: Run linter
run: yarn lint run: yarn lint
- name: Run vitest tests
run: yarn vitest run --reporter=json
- name: Install Playwright Browsers
run: npx playwright install --with-deps
- name: Run Playwright tests
run: npx playwright test
- uses: actions/upload-artifact@v3
if: always()
with:
name: playwright-report
path: playwright-report/
retention-days: 30
- name: Build WebUI - name: Build WebUI
run: yarn build run: yarn build

View file

@ -10,19 +10,26 @@
"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 .",
"postinstall": "patch-package" "postinstall": "patch-package",
"test": "npm run test:integration && npm run test:unit",
"test:integration": "playwright test",
"test:unit": "vitest"
}, },
"devDependencies": { "devDependencies": {
"@rollup/plugin-json": "^6.0.1", "@rollup/plugin-json": "^6.0.1",
"@sveltejs/adapter-auto": "^2.0.0", "@sveltejs/adapter-auto": "^2.0.0",
"@sveltejs/adapter-static": "^2.0.3", "@sveltejs/adapter-static": "^2.0.3",
"@sveltejs/kit": "^1.27.4", "@sveltejs/kit": "^1.27.4",
"@sveltejs/vite-plugin-svelte": "^3.0.1",
"@testing-library/svelte": "^4.0.5",
"@types/swagger-ui": "^3.52.4", "@types/swagger-ui": "^3.52.4",
"@typescript-eslint/eslint-plugin": "^6.0.0", "@typescript-eslint/eslint-plugin": "^6.0.0",
"@typescript-eslint/parser": "^6.0.0", "@typescript-eslint/parser": "^6.0.0",
"@vitest/ui": "^0.34.6",
"eslint": "^8.28.0", "eslint": "^8.28.0",
"eslint-config-prettier": "^9.0.0", "eslint-config-prettier": "^9.0.0",
"eslint-plugin-svelte": "^2.30.0", "eslint-plugin-svelte": "^2.30.0",
"jsdom": "^22.1.0",
"prettier": "^3.0.0", "prettier": "^3.0.0",
"prettier-plugin-svelte": "^3.0.0", "prettier-plugin-svelte": "^3.0.0",
"sass": "^1.69.5", "sass": "^1.69.5",
@ -31,13 +38,16 @@
"svelte-preprocess": "^5.1.1", "svelte-preprocess": "^5.1.1",
"tslib": "^2.4.1", "tslib": "^2.4.1",
"typescript": "^5.0.0", "typescript": "^5.0.0",
"vite": "^4.4.2" "vite": "^5.0.2",
"vitest": "^0.34.6",
"vitest-dom": "^0.1.1"
}, },
"type": "module", "type": "module",
"dependencies": { "dependencies": {
"@fontsource/antonio": "^5.0.17", "@fontsource/antonio": "^5.0.17",
"@fontsource/oswald": "^5.0.17", "@fontsource/oswald": "^5.0.17",
"@fontsource/ubuntu": "^5.0.8", "@fontsource/ubuntu": "^5.0.8",
"@playwright/test": "^1.40.0",
"bootstrap": "^5.3.2", "bootstrap": "^5.3.2",
"patch-package": "^8.0.0", "patch-package": "^8.0.0",
"svelte-i18n": "^4.0.0", "svelte-i18n": "^4.0.0",

16
playwright.config.ts Normal file
View file

@ -0,0 +1,16 @@
import type { PlaywrightTestConfig } from '@playwright/test';
const config: PlaywrightTestConfig = {
use: {
locale: 'en-GB',
timezoneId: 'Europe/Amsterdam'
},
webServer: {
command: 'npm run build && npm run preview',
port: 4173
},
testDir: 'tests',
testMatch: /(.+\.)?(test|spec)\.[jt]s/
};
export default config;

View file

@ -12,6 +12,6 @@ init({
initialLocale: browser initialLocale: browser
? browser && localStorage.getItem('locale') ? browser && localStorage.getItem('locale')
? localStorage.getItem('locale') ? localStorage.getItem('locale')
: window.navigator.language : window.navigator.language.slice(0, 2)
: defaultLocale : defaultLocale
}); });

View file

@ -13,7 +13,7 @@
} from 'sveltestrap'; } from 'sveltestrap';
import { page } from '$app/stores'; import { page } from '$app/stores';
import { locale, locales } from 'svelte-i18n'; import { locale, locales, isLoading } from 'svelte-i18n';
export const setLocale = (lang: string) => () => { export const setLocale = (lang: string) => () => {
locale.set(lang); locale.set(lang);
@ -39,19 +39,15 @@
} }
}; };
export const getLanguageName = (languageCode: string): string | null => { let languageNames = {};
const languageNames: { [key: string]: { [key: string]: string } } = {
en: { en: 'English', nl: 'English', es: 'English' },
nl: { en: 'Nederlands', nl: 'Nederlands', es: 'Neerlandés' },
es: { en: 'Español', nl: 'Spaans', es: 'Español' }
};
const lowercaseCode = languageCode.toLowerCase(); locale.subscribe(() => {
let newLanguageNames = new Intl.DisplayNames([$locale], { type: 'language' });
return Object.prototype.hasOwnProperty.call(languageNames, lowercaseCode) for (let l: string of $locales) {
? languageNames[lowercaseCode][lowercaseCode] languageNames[l] = newLanguageNames.of(l);
: null; }
}; });
</script> </script>
<Navbar expand="md"> <Navbar expand="md">
@ -65,16 +61,18 @@
<NavLink href="/api" active={$page.url.pathname === '/api'}>API</NavLink> <NavLink href="/api" active={$page.url.pathname === '/api'}>API</NavLink>
</NavItem> </NavItem>
</Nav> </Nav>
{#if !$isLoading}
<Dropdown inNavbar> <Dropdown inNavbar>
<DropdownToggle nav caret>{getFlagEmoji($locale)} {getLanguageName($locale)}</DropdownToggle> <DropdownToggle nav caret>{getFlagEmoji($locale)} {languageNames[$locale]}</DropdownToggle>
<DropdownMenu end> <DropdownMenu end>
{#each $locales as locale} {#each $locales as locale}
<DropdownItem on:click={setLocale(locale)} <DropdownItem on:click={setLocale(locale)}
>{getFlagEmoji(locale)} {getLanguageName(locale)}</DropdownItem >{getFlagEmoji(locale)} {languageNames[locale]}</DropdownItem
> >
{/each} {/each}
</DropdownMenu> </DropdownMenu>
</Dropdown> </Dropdown>
{/if}
</Collapse> </Collapse>
</Navbar> </Navbar>

View file

@ -0,0 +1,30 @@
import { writable } from 'svelte/store';
import Control from './Control.svelte';
import { render } from '@testing-library/svelte';
import { describe, test, expect, beforeEach } from 'vitest';
import { addMessages, init, locale } from 'svelte-i18n';
import '$lib/i18n/index.ts';
import en from '$lib/locales/en.json';
addMessages('en', en);
describe('Control Component', () => {
beforeEach(() => {
init({
fallbackLocale: 'en',
initialLocale: 'en'
});
locale.set('en');
});
test('should render the component', () => {
const host = document.createElement('div');
document.body.appendChild(host);
const instance = render(Control, {
target: host,
props: { status: writable([]), settings: writable([]) }
});
expect(instance).toBeTruthy();
expect(host.innerHTML).toContain('Control');
});
});

View file

@ -0,0 +1,32 @@
import { writable } from 'svelte/store';
import Settings from './Settings.svelte';
import { render } from '@testing-library/svelte';
import { describe, test, expect, beforeEach } from 'vitest';
import { addMessages, init, locale } from 'svelte-i18n';
import '$lib/i18n/index.ts';
import en from '$lib/locales/en.json';
addMessages('en', en);
describe('Settings Component', () => {
beforeEach(() => {
init({
fallbackLocale: 'en',
initialLocale: 'en'
});
locale.set('en');
});
test('should render the component', () => {
locale.set('en');
const host = document.createElement('div');
document.body.appendChild(host);
const instance = render(Settings, {
target: host,
props: { settings: writable([]) }
});
expect(instance).toBeTruthy();
expect(host.innerHTML).toContain('Settings');
});
});

30
src/routes/Status.spec.ts Normal file
View file

@ -0,0 +1,30 @@
import { writable } from 'svelte/store';
import Status from './Status.svelte';
import { render } from '@testing-library/svelte';
import { describe, test, expect, beforeEach } from 'vitest';
import { locale, init, addMessages } from 'svelte-i18n';
import '$lib/i18n/index.ts';
import en from '$lib/locales/en.json';
addMessages('en', en);
describe('Status Component', () => {
beforeEach(() => {
init({
fallbackLocale: 'en',
initialLocale: 'en'
});
locale.set('en');
});
test('should render the component', () => {
const host = document.createElement('div');
document.body.appendChild(host);
const instance = render(Status, {
target: host,
props: { status: writable([]), settings: writable([]) }
});
expect(instance).toBeTruthy();
expect(host.innerHTML).toContain('Status');
});
});

21
tests/test.ts Normal file
View file

@ -0,0 +1,21 @@
import { expect, test } from '@playwright/test';
test('index page has expected status', async ({ page }) => {
await page.goto('/');
await expect(page.getByRole('heading', { name: 'Status' })).toBeVisible();
});
test('index page has expected settings', async ({ page }) => {
await page.goto('/');
await expect(page.getByRole('heading', { name: 'Settings' })).toBeVisible();
});
test('index page has expected control', async ({ page }) => {
await page.goto('/');
await expect(page.getByRole('heading', { name: 'Control' })).toBeVisible();
});
test('api page has expected load button', async ({ page }) => {
await page.goto('/api');
await expect(page.getByRole('button', { name: 'Load' })).toBeVisible();
});

View file

@ -1,5 +1,6 @@
import { sveltekit } from '@sveltejs/kit/vite'; import { sveltekit } from '@sveltejs/kit/vite';
import { defineConfig } from 'vite'; //import { defineConfig } from 'vite';
import { defineConfig } from 'vitest/config';
import * as fs from 'fs'; import * as fs from 'fs';
import * as path from 'path'; import * as path from 'path';
@ -68,5 +69,10 @@ export default defineConfig({
assetFileNames: '[name][extname]' assetFileNames: '[name][extname]'
} }
} }
},
test: {
include: ['src/**/*.{test,spec}.{js,ts}'],
globals: true,
environment: 'jsdom'
} }
}); });

1313
yarn.lock

File diff suppressed because it is too large Load diff