test(git-sync): add reviewer-requested coverage across engine, server, client
Implements the test cases called out in the PR #119 review threads (code-review, test-strategy report, red-team) — TESTS ONLY, no production code changes. packages/git-sync (vitest): - lib converter/markdown gaps: pageBreak data-loss (it.fails repro), subpages lossy round-trip, nested/fenced callouts, ol->taskList bridge, column.width number<->string drift, empty details. - engine units: parentFolderFile, planReconciliation swap/chained move, buildVaultLayout last-resort-by-id, firstDivergence, applyPushActions / applyPullActions failure isolation. - real temp-git integration: diffNameStatus -z rename+add/modify alignment, copy-line behavior, per-invocation committer identity (no leak into repo/global config). - ENFORCED type-level GitSyncClient contract via vitest typecheck over a *.test-d.ts file (tsconfig.vitest.json; build tsconfig untouched). apps/server (jest): - orchestrator: delete-cap neutralization + fail-safe, Redis lock / mutex skip ladder + release-on-throw, merge guard, pull/push order, remote template substitution, poll lifecycle. - page-change listener: loop-guard, debounce coalescing, id resolution, error swallowing. - vault registry, controller authz (trigger + status), env validation/getters, page.service git-sync provenance stamping, persistence precedence (agent > git-sync > user) + no boundary snapshot, space.service audit-delta, space.repo jsonb-merge, converter-gate corpus extension (mention/math/details/marks). apps/client (vitest + testing-library): - history-item git-sync badge: render gating + non-clickable. - edit-space-form toggle: initial state, optimistic payload, rollback on error, disabled states. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
committed by
claude code agent 227
parent
eb0aa12c83
commit
ba15fde809
@@ -0,0 +1,74 @@
|
||||
import { plainToInstance } from 'class-transformer';
|
||||
import { validateSync } from 'class-validator';
|
||||
import { EnvironmentVariables } from './environment.validation';
|
||||
|
||||
/**
|
||||
* Validation-layer coverage for the git-sync env contract (test-strategy Module
|
||||
* 4 / item #4). We drive the decorated class with `validateSync` directly — the
|
||||
* exported `validate()` helper calls `process.exit(1)` on failure and so cannot
|
||||
* be asserted in-process. We only assert the git-sync rules, providing the
|
||||
* minimal always-required fields so unrelated validators do not add noise.
|
||||
*/
|
||||
describe('EnvironmentVariables — git-sync validation', () => {
|
||||
// A baseline config that satisfies the unconditionally-required fields
|
||||
// (DATABASE_URL, REDIS_URL, APP_SECRET) so the only errors we ever see come
|
||||
// from the git-sync rules under test.
|
||||
const baseConfig = {
|
||||
DATABASE_URL: 'postgres://user:pass@localhost:5432/docmost',
|
||||
REDIS_URL: 'redis://localhost:6379',
|
||||
APP_SECRET: 'x'.repeat(32),
|
||||
};
|
||||
|
||||
const validate = (extra: Record<string, unknown>) => {
|
||||
const instance = plainToInstance(EnvironmentVariables, {
|
||||
...baseConfig,
|
||||
...extra,
|
||||
});
|
||||
return validateSync(instance);
|
||||
};
|
||||
|
||||
const errorFor = (errors: ReturnType<typeof validateSync>, property: string) =>
|
||||
errors.find((e) => e.property === property);
|
||||
|
||||
it('flags GIT_SYNC_SERVICE_USER_ID when GIT_SYNC_ENABLED="true" and the id is absent', () => {
|
||||
const errors = validate({ GIT_SYNC_ENABLED: 'true' });
|
||||
|
||||
const err = errorFor(errors, 'GIT_SYNC_SERVICE_USER_ID');
|
||||
expect(err).toBeDefined();
|
||||
// @IsNotEmpty is the failing constraint (sync is on but no attributable
|
||||
// author was configured).
|
||||
expect(err?.constraints).toHaveProperty('isNotEmpty');
|
||||
});
|
||||
|
||||
it('accepts GIT_SYNC_ENABLED="true" once GIT_SYNC_SERVICE_USER_ID is present', () => {
|
||||
const errors = validate({
|
||||
GIT_SYNC_ENABLED: 'true',
|
||||
GIT_SYNC_SERVICE_USER_ID: 'service-user-1',
|
||||
});
|
||||
|
||||
expect(errorFor(errors, 'GIT_SYNC_SERVICE_USER_ID')).toBeUndefined();
|
||||
});
|
||||
|
||||
it('does not require the service user id when git-sync is disabled (unset)', () => {
|
||||
const errors = validate({});
|
||||
|
||||
// The @ValidateIf gate (GIT_SYNC_ENABLED === "true") is not met, so the
|
||||
// required-if-enabled rule is skipped entirely.
|
||||
expect(errorFor(errors, 'GIT_SYNC_SERVICE_USER_ID')).toBeUndefined();
|
||||
});
|
||||
|
||||
it('does not require the service user id when git-sync is explicitly "false"', () => {
|
||||
const errors = validate({ GIT_SYNC_ENABLED: 'false' });
|
||||
|
||||
expect(errorFor(errors, 'GIT_SYNC_SERVICE_USER_ID')).toBeUndefined();
|
||||
expect(errorFor(errors, 'GIT_SYNC_ENABLED')).toBeUndefined();
|
||||
});
|
||||
|
||||
it('rejects a GIT_SYNC_ENABLED value outside the {true,false} set via @IsIn', () => {
|
||||
const errors = validate({ GIT_SYNC_ENABLED: 'maybe' });
|
||||
|
||||
const err = errorFor(errors, 'GIT_SYNC_ENABLED');
|
||||
expect(err).toBeDefined();
|
||||
expect(err?.constraints).toHaveProperty('isIn');
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user