131 lines
5.2 KiB
JavaScript
131 lines
5.2 KiB
JavaScript
import assert from "node:assert/strict";
|
|
import { readFileSync } from "node:fs";
|
|
import path from "node:path";
|
|
|
|
import * as dictionaries from "../src/utils/dictionaries.js";
|
|
|
|
const root = process.cwd();
|
|
|
|
function readSource(relativePath) {
|
|
return readFileSync(path.join(root, relativePath), "utf8");
|
|
}
|
|
|
|
function assertFormatter(name, samples) {
|
|
assert.equal(typeof dictionaries[name], "function", `${name} should be exported`);
|
|
samples.forEach(([value, expected]) => {
|
|
assert.equal(dictionaries[name](value), expected, `${name} should translate ${value}`);
|
|
});
|
|
}
|
|
|
|
function assertNoRawEnumFallback(name) {
|
|
const rawCode = "UNTRANSLATED_SAMPLE_ENUM";
|
|
assert.notEqual(dictionaries[name](rawCode), rawCode, `${name} must not render raw English enum fallbacks`);
|
|
assert.match(dictionaries[name](rawCode), /未识别/, `${name} fallback should be Chinese`);
|
|
}
|
|
|
|
assertFormatter("formatInventoryTxnTypeLabel", [
|
|
["OPENING_IN", "期初入库"],
|
|
["PRODUCTION_SURPLUS_IN", "生产余料入库"],
|
|
["OUTSOURCING_SURPLUS_IN", "委外余料入库"],
|
|
["WIP_IN", "产中入库"],
|
|
["WIP_OUT", "产中出库"],
|
|
["PRODUCTION_FINISHED_IN", "生产入库"],
|
|
["STOCKTAKE_GAIN", "盘库盘盈"],
|
|
["STOCKTAKE_LOSS", "盘库盘亏"],
|
|
["STOCKTAKE_NEW_LOT", "盘库新增批次"]
|
|
]);
|
|
assertNoRawEnumFallback("formatInventoryTxnTypeLabel");
|
|
|
|
assertFormatter("formatSourceDocTypeLabel", [
|
|
["OPENING_STOCK", "期初入库"],
|
|
["STOCKTAKE", "盘库"],
|
|
["PRODUCTION_OUT", "生产出库"],
|
|
["OUTSOURCING_OUT", "委外出库"],
|
|
["RETURN_OUT", "返工出库"]
|
|
]);
|
|
assertNoRawEnumFallback("formatSourceDocTypeLabel");
|
|
|
|
assertFormatter("formatWarehouseTypeLabel", [
|
|
["RAW", "原材料库"],
|
|
["SEMI", "半成品库"],
|
|
["FINISHED", "成品库"],
|
|
["AUX", "辅料库"],
|
|
["SCRAP", "废料库"],
|
|
["RETURN", "退货库"]
|
|
]);
|
|
assertNoRawEnumFallback("formatWarehouseTypeLabel");
|
|
|
|
assertFormatter("formatItemTypeLabel", [
|
|
["RAW_MATERIAL", "原材料"],
|
|
["FINISHED_GOOD", "成品"],
|
|
["PRODUCT", "产品"]
|
|
]);
|
|
assertNoRawEnumFallback("formatItemTypeLabel");
|
|
|
|
assertFormatter("formatPurchaseSourceTypeLabel", [
|
|
["SALES_ORDER", "销售订单采购"],
|
|
["STOCKING", "备料采购"]
|
|
]);
|
|
assertNoRawEnumFallback("formatPurchaseSourceTypeLabel");
|
|
|
|
assertFormatter("formatMiniappRoleLabel", [
|
|
["worker", "员工"],
|
|
["manager", "经理"],
|
|
["admin", "管理员"]
|
|
]);
|
|
assertNoRawEnumFallback("formatMiniappRoleLabel");
|
|
|
|
assertFormatter("formatMaintenanceTypeLabel", [
|
|
["PERIODIC", "周期保养"],
|
|
["REPAIR", "维修保养"],
|
|
["INSPECTION", "点检保养"]
|
|
]);
|
|
assertNoRawEnumFallback("formatMaintenanceTypeLabel");
|
|
|
|
assertFormatter("formatStocktakeRowStatusLabel", [
|
|
["READY", "可确认"],
|
|
["ERROR", "异常"],
|
|
["IGNORED", "已忽略"]
|
|
]);
|
|
assertNoRawEnumFallback("formatStocktakeRowStatusLabel");
|
|
|
|
const dictionarySource = readSource("src/utils/dictionaries.js");
|
|
assert.match(dictionarySource, /function normalizeDictionaryKey/, "dictionary lookup should normalize keys");
|
|
assert.match(dictionarySource, /function isEnumLikeValue/, "dictionary lookup should identify enum-like fallbacks");
|
|
assert.match(dictionarySource, /未识别/, "dictionary fallback should be Chinese");
|
|
|
|
const tableControlsSource = readSource("src/utils/tableControls.js");
|
|
[
|
|
"WAREHOUSE_TYPE_LABELS",
|
|
"ITEM_TYPE_LABELS",
|
|
"PURCHASE_SOURCE_TYPE_LABELS",
|
|
"MAINTENANCE_TYPE_LABELS",
|
|
"MINIAPP_ROLE_LABELS",
|
|
"STOCKTAKE_ROW_STATUS_LABELS"
|
|
].forEach((mapName) => {
|
|
assert.match(tableControlsSource, new RegExp(mapName), `TableControls search should include ${mapName}`);
|
|
});
|
|
|
|
const inventorySource = readSource("src/views/InventoryLedgerView.vue");
|
|
assert.match(inventorySource, /formatWarehouseTypeLabel/, "inventory view should use warehouse type formatter");
|
|
assert.match(inventorySource, /formatItemTypeLabel/, "inventory view should use item type formatter");
|
|
assert.doesNotMatch(inventorySource, /placeholder="如 SALES_OUT、RETURN_IN"/, "inventory ledger filter should not show English examples");
|
|
|
|
const equipmentSource = readSource("src/views/EquipmentManagementView.vue");
|
|
assert.match(equipmentSource, /formatMaintenanceTypeLabel/, "equipment view should translate maintenance types");
|
|
assert.doesNotMatch(equipmentSource, /\{\{\s*order\.maintenance_type\s*\}\}/, "equipment view must not render raw maintenance_type");
|
|
|
|
const employeeSource = readSource("src/views/EmployeeManagementView.vue");
|
|
assert.match(employeeSource, /formatPersonRoles/, "employee view should centralize role display formatting");
|
|
assert.match(employeeSource, /formatMiniappRoleLabel/, "employee view should translate miniapp role codes");
|
|
assert.doesNotMatch(employeeSource, /personnel \/ person_roles/, "employee view should not show raw table names");
|
|
|
|
const stocktakeSource = readSource("src/components/StocktakeDialog.vue");
|
|
assert.match(stocktakeSource, /formatStocktakeRowStatusLabel/, "stocktake dialog should have row status formatter available");
|
|
|
|
const purchaseSource = readSource("src/views/PurchaseOrderView.vue");
|
|
assert.match(purchaseSource, /formatPurchaseSourceTypeLabel/, "purchase order view should translate source_type");
|
|
assert.doesNotMatch(purchaseSource, /"source_type",\s*$/m, "purchase order search should not rely on raw source_type only");
|
|
|
|
console.log("dictionary localization checks passed");
|