diff options
| author | Leitwolf11 | 2026-09-26 16:57:36 +0300 |
|---|---|---|
| committer | Leitwolf11 | 2026-09-26 16:57:36 +0300 |
| commit | 07b91c2966ffe5daa9501f41436b3a45b3a2d774 (patch) | |
| tree | 4a8771a38cbd7bc61735c3ae59b8b440f03d0d42 /apps | |
| parent | 1855533fa44547e568471303530c67e5d2fa69c5 (diff) | |
| download | progmaweb-07b91c2966ffe5daa9501f41436b3a45b3a2d774.tar.gz | |
Add Progmaweb frontend tests and full-stack security and coverage workflows
Diffstat (limited to 'apps')
| -rw-r--r-- | apps/api-tests/Progmaweb.Api.Tests.csproj | 1 | ||||
| -rw-r--r-- | apps/api-tests/packages.lock.json | 11 | ||||
| -rw-r--r-- | apps/api/packages.lock.json | 2 | ||||
| -rw-r--r-- | apps/web/package.json | 3 | ||||
| -rw-r--r-- | apps/web/tests/localization.test.mjs | 62 |
5 files changed, 78 insertions, 1 deletions
diff --git a/apps/api-tests/Progmaweb.Api.Tests.csproj b/apps/api-tests/Progmaweb.Api.Tests.csproj index 63b5f6c..efb6a2f 100644 --- a/apps/api-tests/Progmaweb.Api.Tests.csproj +++ b/apps/api-tests/Progmaweb.Api.Tests.csproj @@ -11,6 +11,7 @@ </PropertyGroup> <ItemGroup> <PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="10.0.11" /> + <PackageReference Include="coverlet.MTP" Version="8.0.0" /> <!-- xUnit's MTP-v2 package is the native .NET 10 test host. Keeping the VSTest adapter here would make the solution mix incompatible runners. --> <PackageReference Include="xunit.v3.mtp-v2" Version="4.0.0" /> diff --git a/apps/api-tests/packages.lock.json b/apps/api-tests/packages.lock.json index 38c06e7..ca4dbb9 100644 --- a/apps/api-tests/packages.lock.json +++ b/apps/api-tests/packages.lock.json @@ -2,6 +2,17 @@ "version": 1, "dependencies": { "net10.0": { + "coverlet.MTP": { + "type": "Direct", + "requested": "[8.0.0, )", + "resolved": "8.0.0", + "contentHash": "r3+GPhzJd8G/qlw8UFOYGECZSFvpg0j+yRTGbSr8ikk1ed4Hui+Y56ghPcBT43S3DWYKEzZLGmZ/KFS28k1zHg==", + "dependencies": { + "Microsoft.Extensions.Configuration": "10.0.1", + "Microsoft.Extensions.DependencyInjection": "8.0.1", + "Microsoft.Testing.Platform": "2.0.2" + } + }, "Microsoft.AspNetCore.Mvc.Testing": { "type": "Direct", "requested": "[10.0.11, )", diff --git a/apps/api/packages.lock.json b/apps/api/packages.lock.json index d134eda..b7d7ff4 100644 --- a/apps/api/packages.lock.json +++ b/apps/api/packages.lock.json @@ -10,4 +10,4 @@ } } } -} +}
\ No newline at end of file diff --git a/apps/web/package.json b/apps/web/package.json index ba3bcf5..fef38d7 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -12,6 +12,8 @@ "build": "next build", "start": "next start", "check": "next typegen && tsc --noEmit", + "test": "node --experimental-strip-types --test tests/*.test.mjs", + "test:coverage": "c8 --reporter=lcov --reporter=text npm test", "lint": "eslint . --max-warnings=0", "format": "prettier --write ." }, @@ -21,6 +23,7 @@ "react-dom": "19.2.8" }, "devDependencies": { + "c8": "12.0.0", "@types/node": "24.10.1", "@types/react": "19.2.14", "@types/react-dom": "19.2.3", diff --git a/apps/web/tests/localization.test.mjs b/apps/web/tests/localization.test.mjs new file mode 100644 index 0000000..3d499ed --- /dev/null +++ b/apps/web/tests/localization.test.mjs @@ -0,0 +1,62 @@ +// SPDX-FileCopyrightText: 2026 Progmasoft <support@progmasoft.com> +// SPDX-License-Identifier: AGPL-3.0-or-later WITH AdditionRef-Progmasoft-Patent-Grant-1.1 + +import assert from "node:assert/strict"; +import { test } from "node:test"; +import { + getMessages, + isLocale, + messages, + supportedLocales, +} from "../lib/localization.ts"; + +test("only the two published locales are accepted", () => { + assert.deepEqual(supportedLocales, ["en-US", "de-DE"]); + assert.equal(isLocale("en-US"), true); + assert.equal(isLocale("de-DE"), true); + for (const value of ["en", "de", "en-us", "tr-TR", "", undefined]) { + assert.equal(isLocale(value), false, `unexpected locale: ${value}`); + } +}); + +test("both locales give the account and ViGet routes distinct page metadata", () => { + const english = messages["en-US"].metadata; + const german = messages["de-DE"].metadata; + for (const key of [ + "homeTitle", + "accountTitle", + "loginTitle", + "registerTitle", + "vigetTitle", + "dslPluginsTitle", + ]) { + assert.equal(typeof english[key], "string"); + assert.equal(typeof german[key], "string"); + assert.notEqual(english[key].trim(), ""); + assert.notEqual(german[key].trim(), ""); + } + assert.notEqual(english.loginTitle, german.loginTitle); + assert.notEqual(english.registerTitle, german.registerTitle); + assert.match(english.vigetTitle, /ViGet/); + assert.match(german.vigetTitle, /ViGet/); +}); + +test("each supported locale resolves to its own complete message tree", () => { + for (const locale of supportedLocales) { + assert.strictEqual(getMessages(locale), messages[locale]); + } + + function shape(value) { + if (Array.isArray(value)) return value.map(shape); + if (value !== null && typeof value === "object") { + return Object.fromEntries( + Object.entries(value).map(([key, child]) => [key, shape(child)]), + ); + } + assert.equal(typeof value, "string"); + assert.notEqual(value.trim(), ""); + return "text"; + } + + assert.deepEqual(shape(messages["de-DE"]), shape(messages["en-US"])); +}); |