feat: add language settings management
This commit is contained in:
@@ -0,0 +1,132 @@
|
||||
import assert from "node:assert/strict";
|
||||
import Database from "better-sqlite3";
|
||||
import { drizzle } from "drizzle-orm/better-sqlite3";
|
||||
import * as schema from "../server/db/schema";
|
||||
import type { DomainActor } from "../server/domain/actor";
|
||||
import { DomainError } from "../server/domain/errors";
|
||||
import { I18nService } from "../server/i18n/service";
|
||||
|
||||
const databasePath = process.argv[2];
|
||||
assert.ok(databasePath, "Database path is required");
|
||||
|
||||
const sqlite = new Database(databasePath);
|
||||
sqlite.pragma("foreign_keys = ON");
|
||||
const db = drizzle({ client: sqlite, schema });
|
||||
|
||||
const owner: DomainActor = {
|
||||
authUserId: "i18n-owner",
|
||||
role: "freelancer",
|
||||
clientId: null,
|
||||
disabled: false,
|
||||
};
|
||||
const client: DomainActor = {
|
||||
authUserId: "i18n-client-user",
|
||||
role: "client",
|
||||
clientId: "i18n-client",
|
||||
disabled: false,
|
||||
};
|
||||
const disabledOwner: DomainActor = {
|
||||
...owner,
|
||||
authUserId: "i18n-disabled-owner",
|
||||
disabled: true,
|
||||
};
|
||||
|
||||
try {
|
||||
for (const actor of [owner, client, disabledOwner]) {
|
||||
db.insert(schema.user).values({
|
||||
id: actor.authUserId,
|
||||
name: actor.authUserId,
|
||||
email: `${actor.authUserId}@example.com`,
|
||||
emailVerified: true,
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
}).run();
|
||||
}
|
||||
|
||||
const service = new I18nService(db);
|
||||
const locales = service.listLocales(owner);
|
||||
assert.deepEqual(
|
||||
locales.map((locale) => ({
|
||||
code: locale.code,
|
||||
status: locale.status,
|
||||
builtIn: locale.builtIn,
|
||||
fallbackLocale: locale.fallbackLocale,
|
||||
})),
|
||||
[
|
||||
{ code: "tr", status: "active", builtIn: true, fallbackLocale: null },
|
||||
{ code: "en", status: "active", builtIn: true, fallbackLocale: "tr" },
|
||||
],
|
||||
);
|
||||
assert.deepEqual(service.getSettings(owner), { defaultLocale: "tr", catalogVersion: 1 });
|
||||
|
||||
assertDomainError(() => service.listLocales(client), "FORBIDDEN");
|
||||
assertDomainError(() => service.createLocale(disabledOwner, { code: "fr", name: "French" }), "FORBIDDEN");
|
||||
assertDomainError(() => service.createLocale(owner, { code: "english", name: "English" }), "VALIDATION_ERROR");
|
||||
assertDomainError(() => service.createLocale(owner, { code: "en", name: "English" }), "CONFLICT");
|
||||
assertDomainError(
|
||||
() => service.createLocale(owner, { code: "de", name: "German", fallbackLocale: "de" }),
|
||||
"VALIDATION_ERROR",
|
||||
);
|
||||
assertDomainError(
|
||||
() => service.createLocale(owner, { code: "pt", name: "Portuguese", fallbackLocale: "zz" }),
|
||||
"VALIDATION_ERROR",
|
||||
);
|
||||
|
||||
const french = service.createLocale(owner, {
|
||||
code: "fr",
|
||||
name: "French",
|
||||
nativeName: "Français",
|
||||
fallbackLocale: "en",
|
||||
});
|
||||
assert.equal(french.status, "draft");
|
||||
assert.equal(french.fallbackLocale, "en");
|
||||
|
||||
service.createLocale(owner, { code: "es", name: "Spanish", fallbackLocale: "fr" });
|
||||
assertDomainError(() => service.updateLocale(owner, "fr", { fallbackLocale: "es" }), "VALIDATION_ERROR");
|
||||
assertDomainError(() => service.setDefaultLocale(owner, "fr"), "VALIDATION_ERROR");
|
||||
|
||||
const activeFrench = service.updateLocale(owner, "fr", { status: "active" });
|
||||
assert.equal(activeFrench.status, "active");
|
||||
assert.equal(service.setDefaultLocale(owner, "fr").defaultLocale, "fr");
|
||||
assertDomainError(() => service.archiveLocale(owner, "fr"), "CONFLICT");
|
||||
assertDomainError(() => service.archiveLocale(owner, "en"), "CONFLICT");
|
||||
|
||||
service.createLocale(owner, {
|
||||
code: "it",
|
||||
name: "Italian",
|
||||
nativeName: "Italiano",
|
||||
status: "active",
|
||||
fallbackLocale: "en",
|
||||
});
|
||||
db.insert(schema.clients).values({
|
||||
id: "i18n-client",
|
||||
ownerUserId: owner.authUserId,
|
||||
name: "I18n Client",
|
||||
authUserId: client.authUserId,
|
||||
portalLocale: "it",
|
||||
}).run();
|
||||
assertDomainError(() => service.archiveLocale(owner, "it"), "CONFLICT");
|
||||
|
||||
db.insert(schema.contentTranslations).values({
|
||||
entityType: "project",
|
||||
entityId: "i18n-project",
|
||||
field: "name",
|
||||
locale: "fr",
|
||||
value: "Projet multilingue",
|
||||
}).run();
|
||||
|
||||
const persisted = db.select().from(schema.instanceLocales).all();
|
||||
assert.equal(persisted.some((locale) => locale.code === "fr" && locale.status === "active"), true);
|
||||
assert.equal(
|
||||
db.select().from(schema.contentTranslations).all()[0]?.value,
|
||||
"Projet multilingue",
|
||||
);
|
||||
|
||||
console.log("I18n phase 1 service smoke passed.");
|
||||
} finally {
|
||||
sqlite.close();
|
||||
}
|
||||
|
||||
function assertDomainError(run: () => unknown, code: DomainError["code"]): void {
|
||||
assert.throws(run, (error) => error instanceof DomainError && error.code === code);
|
||||
}
|
||||
Reference in New Issue
Block a user