forked from btclock/webui
Add testing frameworks
This commit is contained in:
parent
fd492c416c
commit
a9c12c2e9f
11 changed files with 1315 additions and 189 deletions
12
.github/workflows/workflow.yml
vendored
12
.github/workflows/workflow.yml
vendored
|
@ -63,6 +63,18 @@ jobs:
|
|||
run: yarn && yarn postinstall
|
||||
- name: Run linter
|
||||
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
|
||||
run: yarn build
|
||||
|
||||
|
|
14
package.json
14
package.json
|
@ -10,19 +10,26 @@
|
|||
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
|
||||
"lint": "prettier --check . && eslint .",
|
||||
"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": {
|
||||
"@rollup/plugin-json": "^6.0.1",
|
||||
"@sveltejs/adapter-auto": "^2.0.0",
|
||||
"@sveltejs/adapter-static": "^2.0.3",
|
||||
"@sveltejs/kit": "^1.27.4",
|
||||
"@sveltejs/vite-plugin-svelte": "^3.0.1",
|
||||
"@testing-library/svelte": "^4.0.5",
|
||||
"@types/swagger-ui": "^3.52.4",
|
||||
"@typescript-eslint/eslint-plugin": "^6.0.0",
|
||||
"@typescript-eslint/parser": "^6.0.0",
|
||||
"@vitest/ui": "^0.34.6",
|
||||
"eslint": "^8.28.0",
|
||||
"eslint-config-prettier": "^9.0.0",
|
||||
"eslint-plugin-svelte": "^2.30.0",
|
||||
"jsdom": "^22.1.0",
|
||||
"prettier": "^3.0.0",
|
||||
"prettier-plugin-svelte": "^3.0.0",
|
||||
"sass": "^1.69.5",
|
||||
|
@ -31,13 +38,16 @@
|
|||
"svelte-preprocess": "^5.1.1",
|
||||
"tslib": "^2.4.1",
|
||||
"typescript": "^5.0.0",
|
||||
"vite": "^4.4.2"
|
||||
"vite": "^5.0.2",
|
||||
"vitest": "^0.34.6",
|
||||
"vitest-dom": "^0.1.1"
|
||||
},
|
||||
"type": "module",
|
||||
"dependencies": {
|
||||
"@fontsource/antonio": "^5.0.17",
|
||||
"@fontsource/oswald": "^5.0.17",
|
||||
"@fontsource/ubuntu": "^5.0.8",
|
||||
"@playwright/test": "^1.40.0",
|
||||
"bootstrap": "^5.3.2",
|
||||
"patch-package": "^8.0.0",
|
||||
"svelte-i18n": "^4.0.0",
|
||||
|
|
16
playwright.config.ts
Normal file
16
playwright.config.ts
Normal 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;
|
|
@ -12,6 +12,6 @@ init({
|
|||
initialLocale: browser
|
||||
? browser && localStorage.getItem('locale')
|
||||
? localStorage.getItem('locale')
|
||||
: window.navigator.language
|
||||
: window.navigator.language.slice(0, 2)
|
||||
: defaultLocale
|
||||
});
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
} from 'sveltestrap';
|
||||
|
||||
import { page } from '$app/stores';
|
||||
import { locale, locales } from 'svelte-i18n';
|
||||
import { locale, locales, isLoading } from 'svelte-i18n';
|
||||
|
||||
export const setLocale = (lang: string) => () => {
|
||||
locale.set(lang);
|
||||
|
@ -39,19 +39,15 @@
|
|||
}
|
||||
};
|
||||
|
||||
export const getLanguageName = (languageCode: string): string | null => {
|
||||
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' }
|
||||
};
|
||||
let languageNames = {};
|
||||
|
||||
const lowercaseCode = languageCode.toLowerCase();
|
||||
locale.subscribe(() => {
|
||||
let newLanguageNames = new Intl.DisplayNames([$locale], { type: 'language' });
|
||||
|
||||
return Object.prototype.hasOwnProperty.call(languageNames, lowercaseCode)
|
||||
? languageNames[lowercaseCode][lowercaseCode]
|
||||
: null;
|
||||
};
|
||||
for (let l: string of $locales) {
|
||||
languageNames[l] = newLanguageNames.of(l);
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<Navbar expand="md">
|
||||
|
@ -65,16 +61,18 @@
|
|||
<NavLink href="/api" active={$page.url.pathname === '/api'}>API</NavLink>
|
||||
</NavItem>
|
||||
</Nav>
|
||||
{#if !$isLoading}
|
||||
<Dropdown inNavbar>
|
||||
<DropdownToggle nav caret>{getFlagEmoji($locale)} {getLanguageName($locale)}</DropdownToggle>
|
||||
<DropdownToggle nav caret>{getFlagEmoji($locale)} {languageNames[$locale]}</DropdownToggle>
|
||||
<DropdownMenu end>
|
||||
{#each $locales as locale}
|
||||
<DropdownItem on:click={setLocale(locale)}
|
||||
>{getFlagEmoji(locale)} {getLanguageName(locale)}</DropdownItem
|
||||
>{getFlagEmoji(locale)} {languageNames[locale]}</DropdownItem
|
||||
>
|
||||
{/each}
|
||||
</DropdownMenu>
|
||||
</Dropdown>
|
||||
{/if}
|
||||
</Collapse>
|
||||
</Navbar>
|
||||
|
||||
|
|
30
src/routes/Control.spec.ts
Normal file
30
src/routes/Control.spec.ts
Normal 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');
|
||||
});
|
||||
});
|
32
src/routes/Settings.spec.ts
Normal file
32
src/routes/Settings.spec.ts
Normal 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
30
src/routes/Status.spec.ts
Normal 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
21
tests/test.ts
Normal 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();
|
||||
});
|
|
@ -1,5 +1,6 @@
|
|||
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 path from 'path';
|
||||
|
@ -68,5 +69,10 @@ export default defineConfig({
|
|||
assetFileNames: '[name][extname]'
|
||||
}
|
||||
}
|
||||
},
|
||||
test: {
|
||||
include: ['src/**/*.{test,spec}.{js,ts}'],
|
||||
globals: true,
|
||||
environment: 'jsdom'
|
||||
}
|
||||
});
|
||||
|
|
Loading…
Reference in a new issue