File size: 5,106 Bytes
d197cf3 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 | import { describe, expect, it } from "vitest";
const { assertNativeGeneratedArtifactsIsolated, shouldRunNativeI18n, shouldStrictNativeI18n } =
await import("../../scripts/ci-changed-scope.mjs");
describe("native i18n changed scope", () => {
it.each([
"scripts/android-app-i18n.ts",
"scripts/apple-app-i18n.ts",
"scripts/native-app-i18n.ts",
"scripts/native-i18n-locales.ts",
])("routes native locale source %s without requiring generated parity", (sourcePath) => {
expect(shouldRunNativeI18n([sourcePath])).toBe(true);
expect(shouldStrictNativeI18n([sourcePath])).toBe(false);
});
it("routes Android flavor sources through native i18n", () => {
expect(
shouldRunNativeI18n([
"apps/android/app/src/play/java/ai/openclaw/app/PlayBilling.kt",
"apps/android/app/src/thirdParty/res/values/accessibility_strings.xml",
]),
).toBe(true);
});
it("keeps generated artifacts in isolated automation PRs", () => {
const generatedCompanionPaths = [
"apps/android/app/src/main/res/values/strings.xml",
"apps/android/app/src/main/res/values/assistant.xml",
];
const generatedPaths = [
"apps/.i18n/native/sv.json",
"apps/android/app/src/main/java/ai/openclaw/app/i18n/NativeStringResources.kt",
"apps/android/app/src/main/res/values-sv/strings.xml",
"apps/android/app/src/thirdParty/res/values-sv/accessibility_strings.xml",
"apps/android/wear/src/main/res/values-sv/strings.xml",
"apps/ios/Resources/Localizable.xcstrings",
"apps/macos/Sources/OpenClaw/Resources/Localizable.xcstrings",
"apps/ios/WatchApp/sv.lproj/InfoPlist.strings",
];
expect(() => assertNativeGeneratedArtifactsIsolated(generatedPaths)).not.toThrow();
expect(() =>
assertNativeGeneratedArtifactsIsolated([...generatedPaths, ...generatedCompanionPaths]),
).not.toThrow();
expect(() =>
assertNativeGeneratedArtifactsIsolated([...generatedPaths, "apps/.i18n/native-source.json"]),
).toThrow("Native generated locale artifacts must be isolated from source changes");
expect(() =>
assertNativeGeneratedArtifactsIsolated(
[...generatedPaths, "apps/ios/Sources/RootTabs.swift"],
"main",
),
).not.toThrow();
expect(() =>
assertNativeGeneratedArtifactsIsolated([
...generatedCompanionPaths,
"apps/.i18n/native-source.json",
]),
).not.toThrow();
expect(() =>
assertNativeGeneratedArtifactsIsolated([
...generatedPaths,
...generatedCompanionPaths,
"apps/.i18n/native-source.json",
]),
).toThrow("Native generated locale artifacts must be isolated from source changes");
expect(() =>
assertNativeGeneratedArtifactsIsolated([
...generatedPaths,
...generatedCompanionPaths,
"apps/android/app/src/main/java/ai/openclaw/app/MainActivity.kt",
]),
).toThrow("Native generated locale artifacts must be isolated from source changes");
});
it("allows only the owner-complete one-time native v2 artifact migration", () => {
const owners = [
".gitattributes",
"scripts/ci-changed-scope.mjs",
"scripts/native-app-i18n.ts",
"scripts/android-app-i18n.ts",
"scripts/apple-app-i18n.ts",
"test/scripts/native-app-i18n.test.ts",
"test/scripts/apple-app-i18n.test.ts",
"src/scripts/ci-changed-scope.native-i18n.test.ts",
];
const generated = [
"apps/.i18n/native/sv.json",
"apps/android/app/src/main/res/values-sv/strings.xml",
"apps/android/wear/src/main/res/values-sv/strings.xml",
"apps/ios/Resources/Localizable.xcstrings",
"apps/macos/Sources/OpenClaw/Resources/Localizable.xcstrings",
];
const migration = [...owners, "apps/.i18n/native-source.json", ...generated];
expect(() => assertNativeGeneratedArtifactsIsolated(migration)).not.toThrow();
expect(() => assertNativeGeneratedArtifactsIsolated(migration.slice(1))).toThrow(
"Native generated locale artifacts must be isolated from source changes",
);
expect(() =>
assertNativeGeneratedArtifactsIsolated([
...migration,
"apps/android/app/src/main/java/ai/openclaw/app/i18n/NativeStringResources.kt",
]),
).toThrow("Native generated locale artifacts must be isolated from source changes");
});
it("runs strict parity only for manual or generated-artifact checks", () => {
expect(shouldStrictNativeI18n(null)).toBe(true);
expect(shouldStrictNativeI18n(["apps/.i18n/native/sv.json"])).toBe(true);
expect(
shouldStrictNativeI18n([
"apps/android/app/src/thirdParty/res/values-sv/accessibility_strings.xml",
]),
).toBe(true);
expect(shouldStrictNativeI18n(["apps/ios/Resources/Localizable.xcstrings"])).toBe(true);
expect(
shouldStrictNativeI18n(["apps/macos/Sources/OpenClaw/Resources/Localizable.xcstrings"]),
).toBe(true);
expect(
shouldStrictNativeI18n(["apps/ios/Sources/RootTabs.swift", "apps/.i18n/native-source.json"]),
).toBe(false);
});
});
|