Fix locale-related bugs and test it with screenshots
This commit is contained in:
parent
23529dbd4b
commit
924be8fc2e
6 changed files with 102 additions and 25 deletions
|
@ -34,9 +34,17 @@ export default defineConfig({
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'MacBook Pro 14 inch',
|
name: 'MacBook Pro 14 inch NL locale',
|
||||||
use: {
|
use: {
|
||||||
viewport: { width: 1512, height: 982 }
|
viewport: { width: 1512, height: 982 },
|
||||||
|
locale: 'nl'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'MacBook Pro 14 inch nl-NL locale',
|
||||||
|
use: {
|
||||||
|
viewport: { width: 1512, height: 982 },
|
||||||
|
locale: 'nl-NL'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
@ -8,11 +8,23 @@ register('nl', () => import('../locales/nl.json'));
|
||||||
register('es', () => import('../locales/es.json'));
|
register('es', () => import('../locales/es.json'));
|
||||||
register('de', () => import('../locales/de.json'));
|
register('de', () => import('../locales/de.json'));
|
||||||
|
|
||||||
|
const getInitialLocale = () => {
|
||||||
|
if (!browser) return defaultLocale;
|
||||||
|
|
||||||
|
// Check localStorage first
|
||||||
|
const storedLocale = localStorage.getItem('locale');
|
||||||
|
if (storedLocale) return storedLocale;
|
||||||
|
|
||||||
|
// Get browser locale and normalize it
|
||||||
|
const browserLocale = window.navigator.language;
|
||||||
|
const normalizedLocale = browserLocale.split('-')[0].toLowerCase();
|
||||||
|
|
||||||
|
// Check if we support this locale
|
||||||
|
const supportedLocales = ['en', 'nl', 'es', 'de'];
|
||||||
|
return supportedLocales.includes(normalizedLocale) ? normalizedLocale : defaultLocale;
|
||||||
|
};
|
||||||
|
|
||||||
init({
|
init({
|
||||||
fallbackLocale: defaultLocale,
|
fallbackLocale: defaultLocale,
|
||||||
initialLocale: browser
|
initialLocale: getInitialLocale()
|
||||||
? browser && localStorage.getItem('locale')
|
|
||||||
? localStorage.getItem('locale')
|
|
||||||
: window.navigator.language.slice(0, 2)
|
|
||||||
: defaultLocale
|
|
||||||
});
|
});
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
import { page } from '$app/stores';
|
import { page } from '$app/stores';
|
||||||
import { locale, locales, isLoading } from 'svelte-i18n';
|
import { locale, locales, isLoading } from 'svelte-i18n';
|
||||||
import { ColorSchemeSwitcher } from '$lib/components';
|
import { ColorSchemeSwitcher } from '$lib/components';
|
||||||
|
import { derived } from 'svelte/store';
|
||||||
|
|
||||||
export const setLocale = (lang: string) => () => {
|
export const setLocale = (lang: string) => () => {
|
||||||
locale.set(lang);
|
locale.set(lang);
|
||||||
|
@ -45,13 +46,14 @@
|
||||||
|
|
||||||
let languageNames = {};
|
let languageNames = {};
|
||||||
|
|
||||||
|
const currentLocale = derived(locale, ($locale) => $locale || 'en');
|
||||||
|
|
||||||
locale.subscribe(() => {
|
locale.subscribe(() => {
|
||||||
if ($locale) {
|
const localeToUse = $locale || 'en';
|
||||||
let newLanguageNames = new Intl.DisplayNames([$locale], { type: 'language' });
|
let newLanguageNames = new Intl.DisplayNames([localeToUse], { type: 'language' });
|
||||||
|
|
||||||
for (let l of $locales) {
|
for (let l of $locales) {
|
||||||
languageNames[l] = newLanguageNames.of(l);
|
languageNames[l] = newLanguageNames.of(l) || l;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -95,7 +97,10 @@
|
||||||
</Nav>
|
</Nav>
|
||||||
{#if !$isLoading}
|
{#if !$isLoading}
|
||||||
<Dropdown id="nav-language-dropdown" inNavbar class="me-3">
|
<Dropdown id="nav-language-dropdown" inNavbar class="me-3">
|
||||||
<DropdownToggle nav caret>{getFlagEmoji($locale)} {languageNames[$locale]}</DropdownToggle>
|
<DropdownToggle nav caret
|
||||||
|
>{getFlagEmoji($currentLocale)}
|
||||||
|
{languageNames[$currentLocale] || 'English'}</DropdownToggle
|
||||||
|
>
|
||||||
<DropdownMenu end>
|
<DropdownMenu end>
|
||||||
{#each $locales as locale}
|
{#each $locales as locale}
|
||||||
<DropdownItem on:click={setLocale(locale)}
|
<DropdownItem on:click={setLocale(locale)}
|
||||||
|
|
|
@ -6,10 +6,15 @@ import { locale, waitLocale } from 'svelte-i18n';
|
||||||
import type { LayoutLoad } from './$types';
|
import type { LayoutLoad } from './$types';
|
||||||
|
|
||||||
export const load: LayoutLoad = async () => {
|
export const load: LayoutLoad = async () => {
|
||||||
if (browser && localStorage.getItem('locale')) {
|
if (browser) {
|
||||||
|
if (localStorage.getItem('locale')) {
|
||||||
locale.set(localStorage.getItem('locale'));
|
locale.set(localStorage.getItem('locale'));
|
||||||
} else if (browser) {
|
} else {
|
||||||
locale.set(window.navigator.language);
|
// Normalize the browser locale
|
||||||
|
const browserLocale = window.navigator.language.split('-')[0].toLowerCase();
|
||||||
|
const supportedLocales = ['en', 'nl', 'es', 'de'];
|
||||||
|
locale.set(supportedLocales.includes(browserLocale) ? browserLocale : 'en');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
await waitLocale();
|
await waitLocale();
|
||||||
};
|
};
|
||||||
|
|
|
@ -4,11 +4,47 @@ import { initMock, settingsJson, statusJson } from '../shared';
|
||||||
|
|
||||||
test.beforeEach(initMock);
|
test.beforeEach(initMock);
|
||||||
|
|
||||||
|
// Define the translations for the headings
|
||||||
|
const headings = {
|
||||||
|
en: {
|
||||||
|
control: 'Control',
|
||||||
|
status: 'Status',
|
||||||
|
settings: 'Settings',
|
||||||
|
language: 'English'
|
||||||
|
},
|
||||||
|
de: {
|
||||||
|
control: 'Steuerung',
|
||||||
|
status: 'Status',
|
||||||
|
settings: 'Einstellungen',
|
||||||
|
language: 'Deutsch'
|
||||||
|
},
|
||||||
|
nl: {
|
||||||
|
control: 'Besturing',
|
||||||
|
status: 'Status',
|
||||||
|
settings: 'Instellingen',
|
||||||
|
language: 'Nederlands'
|
||||||
|
},
|
||||||
|
es: {
|
||||||
|
control: 'Control',
|
||||||
|
status: 'Estado',
|
||||||
|
settings: 'Ajustes',
|
||||||
|
language: 'Español'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
test('capture screenshots across devices', async ({ page }, testInfo) => {
|
test('capture screenshots across devices', async ({ page }, testInfo) => {
|
||||||
|
// Get the locale from the browser or default to 'en'
|
||||||
|
const locale = testInfo.project.use?.locale?.split('-')[0].toLowerCase() || 'en';
|
||||||
|
const translations = headings[locale] || headings.en;
|
||||||
|
|
||||||
await page.goto('/');
|
await page.goto('/');
|
||||||
await expect(page.getByRole('heading', { name: 'Control' })).toBeVisible();
|
await expect(page.getByRole('heading', { name: translations.control })).toBeVisible();
|
||||||
await expect(page.getByRole('heading', { name: 'Status' })).toBeVisible();
|
await expect(page.getByRole('heading', { name: translations.status })).toBeVisible();
|
||||||
await expect(page.getByRole('heading', { name: 'Settings' })).toBeVisible();
|
await expect(page.getByRole('heading', { name: translations.settings })).toBeVisible();
|
||||||
|
|
||||||
|
if (await page.locator('#nav-language-dropdown').isVisible()) {
|
||||||
|
await expect(page.getByRole('link', { name: translations.language })).toBeVisible();
|
||||||
|
}
|
||||||
|
|
||||||
const screenshot = await page.screenshot({
|
const screenshot = await page.screenshot({
|
||||||
path: `./test-results/screenshots/default-${test.info().project.name.toLowerCase().replace(' ', '_')}.png`
|
path: `./test-results/screenshots/default-${test.info().project.name.toLowerCase().replace(' ', '_')}.png`
|
||||||
|
@ -21,6 +57,9 @@ test('capture screenshots across devices', async ({ page }, testInfo) => {
|
||||||
});
|
});
|
||||||
|
|
||||||
test('capture screenshots across devices with bitaxe screens', async ({ page }, testInfo) => {
|
test('capture screenshots across devices with bitaxe screens', async ({ page }, testInfo) => {
|
||||||
|
const locale = testInfo.project.use?.locale?.split('-')[0].toLowerCase() || 'en';
|
||||||
|
const translations = headings[locale] || headings.en;
|
||||||
|
|
||||||
settingsJson.screens = [
|
settingsJson.screens = [
|
||||||
{
|
{
|
||||||
id: 0,
|
id: 0,
|
||||||
|
@ -73,9 +112,14 @@ test('capture screenshots across devices with bitaxe screens', async ({ page },
|
||||||
statusJson.rendered = ['mdi:bitaxe', '', 'mdi:pickaxe', '6', '3', '7', 'GH/S'];
|
statusJson.rendered = ['mdi:bitaxe', '', 'mdi:pickaxe', '6', '3', '7', 'GH/S'];
|
||||||
|
|
||||||
await page.goto('/');
|
await page.goto('/');
|
||||||
await expect(page.getByRole('heading', { name: 'Control' })).toBeVisible();
|
|
||||||
await expect(page.getByRole('heading', { name: 'Status' })).toBeVisible();
|
await expect(page.getByRole('heading', { name: translations.control })).toBeVisible();
|
||||||
await expect(page.getByRole('heading', { name: 'Settings' })).toBeVisible();
|
await expect(page.getByRole('heading', { name: translations.status })).toBeVisible();
|
||||||
|
await expect(page.getByRole('heading', { name: translations.settings })).toBeVisible();
|
||||||
|
|
||||||
|
if (await page.locator('#nav-language-dropdown').isVisible()) {
|
||||||
|
await expect(page.getByRole('link', { name: translations.language })).toBeVisible();
|
||||||
|
}
|
||||||
|
|
||||||
await page.screenshot({
|
await page.screenshot({
|
||||||
path: `./test-results/screenshots/bitaxe-${test.info().project.name.toLowerCase().replace(' ', '_')}.png`
|
path: `./test-results/screenshots/bitaxe-${test.info().project.name.toLowerCase().replace(' ', '_')}.png`
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { sveltekit } from '@sveltejs/kit/vite';
|
import { sveltekit } from '@sveltejs/kit/vite';
|
||||||
import { defineConfig } from 'vitest/config';
|
import { defineConfig } from 'vite';
|
||||||
import GithubActionsReporter from 'vitest-github-actions-reporter';
|
import GithubActionsReporter from 'vitest-github-actions-reporter';
|
||||||
// import { visualizer } from 'rollup-plugin-visualizer';
|
// import { visualizer } from 'rollup-plugin-visualizer';
|
||||||
|
|
||||||
|
@ -102,5 +102,8 @@ export default defineConfig({
|
||||||
globals: true,
|
globals: true,
|
||||||
environment: 'jsdom',
|
environment: 'jsdom',
|
||||||
reporters: process.env.GITHUB_ACTIONS ? ['default', new GithubActionsReporter()] : 'default'
|
reporters: process.env.GITHUB_ACTIONS ? ['default', new GithubActionsReporter()] : 'default'
|
||||||
|
},
|
||||||
|
define: {
|
||||||
|
'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in a new issue