Files
pleno-vue/tests/unit/release-manager-i18n.spec.js
T

171 lines
5.7 KiB
JavaScript

import { join } from "node:path";
import { describe, expect, it } from "vitest";
import { readJsonFile } from "./helpers/readJsonFile";
import { readI18nRuntimeMessages } from "./helpers/readI18nRuntimeMessages";
const root = process.cwd();
const activeLocales = ["da", "en", "sv", "de", "no"];
const channelKeys = ["stable", "canary", "internal"];
const requiredReleaseAvailabilityLabels = {
channel_unavailable: [
"release_bundle",
"frontend_version",
"api_version",
"frontend_base_url",
"api_base_url",
"frontend_entry",
"release_runtime",
],
channel_selector: [
"release_bundle",
"frontend_version",
"api_version",
"frontend_base_url",
"api_base_url",
"frontend_entry",
"release_runtime",
"bundle",
"frontend",
"api",
"use_local_frontend",
],
};
const expectedNewReleaseLabels = {
da: {
frontend_base_url: "Frontend-URL",
api_base_url: "API-URL",
frontend_entry: "Frontend-entry",
release_runtime: "Release-runtime",
use_local_frontend: "Brug lokal frontend",
},
en: {
frontend_base_url: "Frontend URL",
api_base_url: "API URL",
frontend_entry: "Frontend entry",
release_runtime: "Release runtime",
use_local_frontend: "Use local frontend",
},
sv: {
frontend_base_url: "Frontend-URL",
api_base_url: "API-URL",
frontend_entry: "Frontend-entry",
release_runtime: "Release-runtime",
use_local_frontend: "Använd lokal frontend",
},
de: {
frontend_base_url: "Frontend-URL",
api_base_url: "API-URL",
frontend_entry: "Frontend-Einstiegspunkt",
release_runtime: "Release-Laufzeit",
use_local_frontend: "Lokales Frontend verwenden",
},
no: {
frontend_base_url: "Frontend-URL",
api_base_url: "API-URL",
frontend_entry: "Frontend-entry",
release_runtime: "Release-runtime",
use_local_frontend: "Bruk lokal frontend",
},
};
const sharedReleaseDetailLabels = {
bundle: "Bundle",
frontend: "Frontend",
api: "API",
};
const suspiciousTranslationArtifact =
/(?:\p{L}\?\p{L}|(?:^|[\s([{])\?\p{L}|\p{L}\?@:\{|\u00c3|\u00c2|\ufffd|\u00ef\u00bf\u00bd)/u;
const flattenStrings = (value, prefix = "") => {
if (typeof value === "string") {
return [{ key: prefix, value }];
}
if (value === null || typeof value !== "object" || Array.isArray(value)) {
return [];
}
return Object.entries(value).flatMap(([key, nestedValue]) =>
flattenStrings(nestedValue, prefix ? `${prefix}.${key}` : key)
);
};
const optionalCatalog = (name, catalog) => (catalog ? [[name, catalog]] : []);
const loadReleaseManagerCatalogs = () =>
activeLocales.flatMap((locale) => {
const source = readJsonFile(join(root, `src/i18n/source/${locale}/phrases/compat/configuration/index.json`)).compat
.configuration.release_manager;
const localeV2 = readJsonFile(join(root, `src/i18n/generated/${locale}-v2.json`));
const generatedV2 = localeV2.templates.generated.compat.configuration.release_manager;
const runtimeV2 = readI18nRuntimeMessages(locale).configuration.release_manager;
return [
...optionalCatalog(`${locale} source`, source),
[`${locale} generated v2`, generatedV2],
[`${locale} runtime v2`, runtimeV2],
];
});
describe("release manager i18n", () => {
it("does not contain replacement-character translation artifacts", () => {
const failures = [];
for (const [name, releaseManager] of loadReleaseManagerCatalogs()) {
for (const { key, value } of flattenStrings(releaseManager)) {
if (suspiciousTranslationArtifact.test(value)) {
failures.push(`${name}: ${key} = ${value}`);
}
}
}
expect(failures).toEqual([]);
});
it("defines localized names and descriptions for built-in release channels", () => {
for (const [name, releaseManager] of loadReleaseManagerCatalogs()) {
expect(Object.keys(releaseManager.channel_names ?? {}), `${name} channel_names`).toEqual(channelKeys);
expect(Object.keys(releaseManager.channel_descriptions ?? {}), `${name} channel_descriptions`).toEqual(
channelKeys
);
for (const key of channelKeys) {
expect(releaseManager.channel_names[key], `${name} channel_names.${key}`).toEqual(expect.any(String));
expect(releaseManager.channel_descriptions[key], `${name} channel_descriptions.${key}`).toEqual(
expect.any(String)
);
}
}
});
it("defines release channel readiness labels for all runtime catalogs", () => {
for (const [name, releaseManager] of loadReleaseManagerCatalogs()) {
const locale = name.split(" ")[0];
for (const [group, keys] of Object.entries(requiredReleaseAvailabilityLabels)) {
for (const key of keys) {
const value = releaseManager[group]?.[key];
expect(value, `${name} ${group}.${key}`).toEqual(expect.any(String));
expect(value, `${name} ${group}.${key}`).not.toBe("");
expect(value, `${name} ${group}.${key}`).not.toBe(key);
const expectedLabel = expectedNewReleaseLabels[locale]?.[key] ?? sharedReleaseDetailLabels[key] ?? null;
if (expectedLabel && !value.startsWith("@:")) {
expect(value, `${name} ${group}.${key}`).toBe(expectedLabel);
}
}
}
}
});
it("uses Danish copy for the internal channel guard", () => {
const danishReleaseManager = readI18nRuntimeMessages("da").configuration.release_manager;
expect(danishReleaseManager.channel_names.internal).toBe("Intern");
expect(danishReleaseManager.channel_descriptions.internal).toContain("Intern kanal");
expect(danishReleaseManager.channel_descriptions.internal).not.toBe(
"Internal staff and superuser validation channel."
);
});
});