Files
windmill/cli/test/gitsync_converter_unit.test.ts
Ruben Fiszel bfc3f5242a feat: sync data table migrations to git, gated by a new object type (#10436)
* fix: auto-sync data table migrations to the linked git repo

* fix: deploy data table migrations when a data table is renamed or deleted

* fix: hold new data table names to the git-sync-safe charset

* fix: reject leading-dot data table names and warn on unsyncable legacy names

* chore: update ee-repo-ref to 15c9eef2a4f867eb90d841aee1ce762f4b725589

This commit updates the EE repository reference after PR #702 was merged in windmill-ee-private.

Previous ee-repo-ref: e2fb073a3d0057683666424e463b2ce423664caa

New ee-repo-ref: 15c9eef2a4f867eb90d841aee1ce762f4b725589

Automated by sync-ee-ref workflow.

* feat: make data table migrations a git-sync object type with its own toggle

* fix: never let an untracked checkout delete data table migrations on push

* fix: confirm ambiguous data table migration deletions instead of dropping them

* fix: settle ambiguous migration deletions before the dry-run preview prints

* fix: restore the split shared-UI comment and count migration records in prompts

* chore: keep the deletion-safety doc block attached to its function

* fix: trust git history, not the working tree, for migration deletions

* fix: scope migration history to HEAD, detect shallow clones and subdir roots

* chore: give the unattested-history case a remedy that applies to it

* chore: pair each unattested-history cause with its own remedy

* fix: treat a sparse checkout as unattested history for migration deletions

* fix: normalize the sparse-checkout boolean and give it a remedy that works

* chore: describe both shapes of unattested migration history

* chore: update ee-repo-ref to a786cd42b5aaf0aa6789fbb723d956560f93b1b3

This commit updates the EE repository reference after PR #703 was merged in windmill-ee-private.

Previous ee-repo-ref: 4f312642b5d8fd37ab5e20473a011d6f1d299cf6

New ee-repo-ref: a786cd42b5aaf0aa6789fbb723d956560f93b1b3

Automated by sync-ee-ref workflow.

---------

Co-authored-by: windmill-internal-app[bot] <windmill-internal-app[bot]@users.noreply.github.com>
2026-07-31 23:33:47 +02:00

261 lines
9.9 KiB
TypeScript

/**
* Unit tests for GitSyncSettingsConverter.
* Tests conversion between backend format (include_type array) and
* SyncOptions format (boolean flags like skipWorkspaceDependencies).
*/
import { expect, test, describe } from "bun:test";
import { GitSyncSettingsConverter } from "../src/commands/gitsync-settings/converter.ts";
// =============================================================================
// fromBackendFormat - converts backend include_type array to SyncOptions
// =============================================================================
describe("GitSyncSettingsConverter.fromBackendFormat", () => {
test("converts workspacedependencies in include_type to skipWorkspaceDependencies: false", () => {
const backend = {
include_path: ["f/**"],
include_type: ["script", "flow", "workspacedependencies"],
};
const result = GitSyncSettingsConverter.fromBackendFormat(backend);
expect(result.skipWorkspaceDependencies).toBe(false);
});
test("converts datatablemigration in include_type to skipDatatableMigrations: false", () => {
const backend = {
include_path: ["f/**"],
include_type: ["script", "flow", "datatablemigration"],
};
const result = GitSyncSettingsConverter.fromBackendFormat(backend);
expect(result.skipDatatableMigrations).toBe(false);
});
test("sets skipDatatableMigrations: true when datatablemigration is absent", () => {
const backend = {
include_path: ["f/**"],
include_type: ["script", "flow"],
};
const result = GitSyncSettingsConverter.fromBackendFormat(backend);
expect(result.skipDatatableMigrations).toBe(true);
});
test("sets skipWorkspaceDependencies: true when workspacedependencies is absent", () => {
const backend = {
include_path: ["f/**"],
include_type: ["script", "flow"],
};
const result = GitSyncSettingsConverter.fromBackendFormat(backend);
expect(result.skipWorkspaceDependencies).toBe(true);
});
test("handles empty include_type array", () => {
const backend = {
include_path: [],
include_type: [],
};
const result = GitSyncSettingsConverter.fromBackendFormat(backend);
expect(result.skipWorkspaceDependencies).toBe(true);
expect(result.skipScripts).toBe(true);
expect(result.skipFlows).toBe(true);
});
test("converts all standard types correctly", () => {
const backend = {
include_path: ["f/**"],
include_type: ["script", "flow", "app", "folder", "variable", "resource", "resourcetype", "secret", "schedule", "trigger", "user", "group", "settings", "key", "workspacedependencies"],
};
const result = GitSyncSettingsConverter.fromBackendFormat(backend);
expect(result.skipScripts).toBe(false);
expect(result.skipFlows).toBe(false);
expect(result.skipApps).toBe(false);
expect(result.skipFolders).toBe(false);
expect(result.skipVariables).toBe(false);
expect(result.skipResources).toBe(false);
expect(result.skipResourceTypes).toBe(false);
expect(result.skipSecrets).toBe(false);
expect(result.includeSchedules).toBe(true);
expect(result.includeTriggers).toBe(true);
expect(result.includeUsers).toBe(true);
expect(result.includeGroups).toBe(true);
expect(result.includeSettings).toBe(true);
expect(result.includeKey).toBe(true);
expect(result.skipWorkspaceDependencies).toBe(false);
});
});
// =============================================================================
// toBackendFormat - converts SyncOptions to backend include_type array
// =============================================================================
describe("GitSyncSettingsConverter.toBackendFormat", () => {
test("adds datatablemigration when skipDatatableMigrations is false", () => {
expect(
GitSyncSettingsConverter.toBackendFormat({
includes: ["f/**"],
skipDatatableMigrations: false,
}).include_type,
).toContain("datatablemigration");
expect(
GitSyncSettingsConverter.toBackendFormat({
includes: ["f/**"],
skipDatatableMigrations: true,
}).include_type,
).not.toContain("datatablemigration");
});
test("adds workspacedependencies when skipWorkspaceDependencies is false", () => {
const opts = {
includes: ["f/**"],
skipWorkspaceDependencies: false,
};
const result = GitSyncSettingsConverter.toBackendFormat(opts);
expect(result.include_type).toContain("workspacedependencies");
});
test("does not add workspacedependencies when skipWorkspaceDependencies is true", () => {
const opts = {
includes: ["f/**"],
skipWorkspaceDependencies: true,
};
const result = GitSyncSettingsConverter.toBackendFormat(opts);
expect(result.include_type).not.toContain("workspacedependencies");
});
test("adds workspacedependencies when skipWorkspaceDependencies is undefined (defaults to false)", () => {
const opts = {
includes: ["f/**"],
// skipWorkspaceDependencies not set
};
const normalized = GitSyncSettingsConverter.normalize(opts);
const result = GitSyncSettingsConverter.toBackendFormat(normalized);
expect(result.include_type).toContain("workspacedependencies");
});
test("converts all boolean flags to include_type correctly", () => {
const opts = {
includes: ["f/**"],
skipScripts: false,
skipFlows: false,
skipApps: false,
skipFolders: false,
skipVariables: false,
skipResources: false,
skipResourceTypes: false,
skipSecrets: false,
includeSchedules: true,
includeTriggers: true,
includeUsers: true,
includeGroups: true,
includeSettings: true,
includeKey: true,
skipWorkspaceDependencies: false,
};
const result = GitSyncSettingsConverter.toBackendFormat(opts);
expect(result.include_type).toContain("script");
expect(result.include_type).toContain("flow");
expect(result.include_type).toContain("app");
expect(result.include_type).toContain("folder");
expect(result.include_type).toContain("variable");
expect(result.include_type).toContain("resource");
expect(result.include_type).toContain("resourcetype");
expect(result.include_type).toContain("secret");
expect(result.include_type).toContain("schedule");
expect(result.include_type).toContain("trigger");
expect(result.include_type).toContain("user");
expect(result.include_type).toContain("group");
expect(result.include_type).toContain("settings");
expect(result.include_type).toContain("key");
expect(result.include_type).toContain("workspacedependencies");
});
});
// =============================================================================
// normalize - applies defaults for undefined fields
// =============================================================================
describe("GitSyncSettingsConverter.normalize", () => {
test("defaults skipWorkspaceDependencies to false", () => {
const opts = { includes: ["f/**"] };
const result = GitSyncSettingsConverter.normalize(opts);
expect(result.skipWorkspaceDependencies).toBe(false);
});
test("preserves explicit skipWorkspaceDependencies: true", () => {
const opts = { includes: ["f/**"], skipWorkspaceDependencies: true };
const result = GitSyncSettingsConverter.normalize(opts);
expect(result.skipWorkspaceDependencies).toBe(true);
});
test("preserves explicit skipWorkspaceDependencies: false", () => {
const opts = { includes: ["f/**"], skipWorkspaceDependencies: false };
const result = GitSyncSettingsConverter.normalize(opts);
expect(result.skipWorkspaceDependencies).toBe(false);
});
});
// =============================================================================
// Round-trip conversion tests
// =============================================================================
describe("GitSyncSettingsConverter round-trip", () => {
test("backend -> SyncOptions -> backend preserves workspacedependencies", () => {
const original = {
include_path: ["f/**"],
include_type: ["script", "flow", "workspacedependencies"],
};
const syncOpts = GitSyncSettingsConverter.fromBackendFormat(original);
const backAgain = GitSyncSettingsConverter.toBackendFormat(syncOpts);
expect(backAgain.include_type).toContain("workspacedependencies");
expect(backAgain.include_type).toContain("script");
expect(backAgain.include_type).toContain("flow");
});
test("backend without workspacedependencies -> SyncOptions -> backend still excludes it", () => {
const original = {
include_path: ["f/**"],
include_type: ["script", "flow"],
};
const syncOpts = GitSyncSettingsConverter.fromBackendFormat(original);
const backAgain = GitSyncSettingsConverter.toBackendFormat(syncOpts);
expect(backAgain.include_type).not.toContain("workspacedependencies");
expect(backAgain.include_type).toContain("script");
expect(backAgain.include_type).toContain("flow");
});
test("SyncOptions with defaults -> backend includes workspacedependencies", () => {
const opts = {
includes: ["f/**"],
skipScripts: false,
skipFlows: false,
// skipWorkspaceDependencies not set - should default to false
};
const normalized = GitSyncSettingsConverter.normalize(opts);
const backend = GitSyncSettingsConverter.toBackendFormat(normalized);
expect(backend.include_type).toContain("workspacedependencies");
});
});
// =============================================================================
// extractGitSyncFields
// =============================================================================
describe("GitSyncSettingsConverter.extractGitSyncFields", () => {
test("includes skipWorkspaceDependencies in extracted fields", () => {
const opts = {
includes: ["f/**"],
skipWorkspaceDependencies: true,
someOtherField: "ignored",
};
const result = GitSyncSettingsConverter.extractGitSyncFields(opts);
expect(result.skipWorkspaceDependencies).toBe(true);
});
});