@herdctl/core 0.0.1 → 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/config/__tests__/agent.test.js +31 -13
- package/dist/config/__tests__/agent.test.js.map +1 -1
- package/dist/config/__tests__/merge.test.js +9 -2
- package/dist/config/__tests__/merge.test.js.map +1 -1
- package/dist/config/__tests__/schema.test.js +350 -1
- package/dist/config/__tests__/schema.test.js.map +1 -1
- package/dist/config/index.d.ts +1 -1
- package/dist/config/index.d.ts.map +1 -1
- package/dist/config/index.js +3 -1
- package/dist/config/index.js.map +1 -1
- package/dist/config/schema.d.ts +828 -24
- package/dist/config/schema.d.ts.map +1 -1
- package/dist/config/schema.js +118 -6
- package/dist/config/schema.js.map +1 -1
- package/dist/fleet-manager/__tests__/coverage.test.js +11 -332
- package/dist/fleet-manager/__tests__/coverage.test.js.map +1 -1
- package/dist/fleet-manager/__tests__/errors.test.js +1 -49
- package/dist/fleet-manager/__tests__/errors.test.js.map +1 -1
- package/dist/fleet-manager/__tests__/integration.test.js +109 -0
- package/dist/fleet-manager/__tests__/integration.test.js.map +1 -1
- package/dist/fleet-manager/__tests__/reload.test.js +1 -1
- package/dist/fleet-manager/__tests__/reload.test.js.map +1 -1
- package/dist/fleet-manager/config-reload.d.ts +164 -0
- package/dist/fleet-manager/config-reload.d.ts.map +1 -0
- package/dist/fleet-manager/config-reload.js +445 -0
- package/dist/fleet-manager/config-reload.js.map +1 -0
- package/dist/fleet-manager/context.d.ts +76 -0
- package/dist/fleet-manager/context.d.ts.map +1 -0
- package/dist/fleet-manager/context.js +11 -0
- package/dist/fleet-manager/context.js.map +1 -0
- package/dist/fleet-manager/errors.d.ts +0 -25
- package/dist/fleet-manager/errors.d.ts.map +1 -1
- package/dist/fleet-manager/errors.js +0 -38
- package/dist/fleet-manager/errors.js.map +1 -1
- package/dist/fleet-manager/event-emitters.d.ts +123 -0
- package/dist/fleet-manager/event-emitters.d.ts.map +1 -0
- package/dist/fleet-manager/event-emitters.js +136 -0
- package/dist/fleet-manager/event-emitters.js.map +1 -0
- package/dist/fleet-manager/event-types.d.ts +0 -15
- package/dist/fleet-manager/event-types.d.ts.map +1 -1
- package/dist/fleet-manager/fleet-manager.d.ts +40 -653
- package/dist/fleet-manager/fleet-manager.d.ts.map +1 -1
- package/dist/fleet-manager/fleet-manager.js +95 -1720
- package/dist/fleet-manager/fleet-manager.js.map +1 -1
- package/dist/fleet-manager/index.d.ts +13 -2
- package/dist/fleet-manager/index.d.ts.map +1 -1
- package/dist/fleet-manager/index.js +19 -6
- package/dist/fleet-manager/index.js.map +1 -1
- package/dist/fleet-manager/job-control.d.ts +64 -0
- package/dist/fleet-manager/job-control.d.ts.map +1 -0
- package/dist/fleet-manager/job-control.js +296 -0
- package/dist/fleet-manager/job-control.js.map +1 -0
- package/dist/fleet-manager/log-streaming.d.ts +171 -0
- package/dist/fleet-manager/log-streaming.d.ts.map +1 -0
- package/dist/fleet-manager/log-streaming.js +503 -0
- package/dist/fleet-manager/log-streaming.js.map +1 -0
- package/dist/fleet-manager/schedule-executor.d.ts +63 -0
- package/dist/fleet-manager/schedule-executor.d.ts.map +1 -0
- package/dist/fleet-manager/schedule-executor.js +209 -0
- package/dist/fleet-manager/schedule-executor.js.map +1 -0
- package/dist/fleet-manager/schedule-management.d.ts +71 -0
- package/dist/fleet-manager/schedule-management.d.ts.map +1 -0
- package/dist/fleet-manager/schedule-management.js +171 -0
- package/dist/fleet-manager/schedule-management.js.map +1 -0
- package/dist/fleet-manager/status-queries.d.ts +105 -0
- package/dist/fleet-manager/status-queries.d.ts.map +1 -0
- package/dist/fleet-manager/status-queries.js +247 -0
- package/dist/fleet-manager/status-queries.js.map +1 -0
- package/dist/fleet-manager/types.d.ts +0 -39
- package/dist/fleet-manager/types.d.ts.map +1 -1
- package/dist/runner/__tests__/job-executor.test.js +206 -1
- package/dist/runner/__tests__/job-executor.test.js.map +1 -1
- package/dist/runner/job-executor.d.ts +9 -0
- package/dist/runner/job-executor.d.ts.map +1 -1
- package/dist/runner/job-executor.js +78 -4
- package/dist/runner/job-executor.js.map +1 -1
- package/dist/runner/types.d.ts +2 -0
- package/dist/runner/types.d.ts.map +1 -1
- package/dist/scheduler/__tests__/cron.test.d.ts +2 -0
- package/dist/scheduler/__tests__/cron.test.d.ts.map +1 -0
- package/dist/scheduler/__tests__/cron.test.js +867 -0
- package/dist/scheduler/__tests__/cron.test.js.map +1 -0
- package/dist/scheduler/__tests__/scheduler.test.js +164 -5
- package/dist/scheduler/__tests__/scheduler.test.js.map +1 -1
- package/dist/scheduler/cron.d.ts +126 -0
- package/dist/scheduler/cron.d.ts.map +1 -0
- package/dist/scheduler/cron.js +390 -0
- package/dist/scheduler/cron.js.map +1 -0
- package/dist/scheduler/errors.d.ts +81 -1
- package/dist/scheduler/errors.d.ts.map +1 -1
- package/dist/scheduler/errors.js +81 -6
- package/dist/scheduler/errors.js.map +1 -1
- package/dist/scheduler/index.d.ts +1 -0
- package/dist/scheduler/index.d.ts.map +1 -1
- package/dist/scheduler/index.js +2 -0
- package/dist/scheduler/index.js.map +1 -1
- package/dist/scheduler/schedule-runner.d.ts +2 -2
- package/dist/scheduler/schedule-runner.d.ts.map +1 -1
- package/dist/scheduler/schedule-runner.js +20 -8
- package/dist/scheduler/schedule-runner.js.map +1 -1
- package/dist/scheduler/scheduler.d.ts +4 -4
- package/dist/scheduler/scheduler.d.ts.map +1 -1
- package/dist/scheduler/scheduler.js +86 -20
- package/dist/scheduler/scheduler.js.map +1 -1
- package/dist/scheduler/types.d.ts +1 -1
- package/dist/scheduler/types.d.ts.map +1 -1
- package/dist/state/schemas/job-metadata.d.ts +2 -2
- package/package.json +33 -8
- package/.turbo/turbo-build.log +0 -4
- package/.turbo/turbo-test.log +0 -219
- package/.turbo/turbo-typecheck.log +0 -4
- package/coverage/base.css +0 -224
- package/coverage/block-navigation.js +0 -87
- package/coverage/coverage-final.json +0 -51
- package/coverage/favicon.png +0 -0
- package/coverage/index.html +0 -251
- package/coverage/prettify.css +0 -1
- package/coverage/prettify.js +0 -2
- package/coverage/sort-arrow-sprite.png +0 -0
- package/coverage/sorter.js +0 -210
- package/coverage/src/config/index.html +0 -191
- package/coverage/src/config/index.ts.html +0 -442
- package/coverage/src/config/interpolate.ts.html +0 -652
- package/coverage/src/config/loader.ts.html +0 -1501
- package/coverage/src/config/merge.ts.html +0 -823
- package/coverage/src/config/parser.ts.html +0 -1213
- package/coverage/src/config/schema.ts.html +0 -1123
- package/coverage/src/fleet-manager/errors.ts.html +0 -2326
- package/coverage/src/fleet-manager/event-types.ts.html +0 -1219
- package/coverage/src/fleet-manager/fleet-manager.ts.html +0 -7030
- package/coverage/src/fleet-manager/index.html +0 -206
- package/coverage/src/fleet-manager/index.ts.html +0 -469
- package/coverage/src/fleet-manager/job-manager.ts.html +0 -2074
- package/coverage/src/fleet-manager/job-queue.ts.html +0 -2479
- package/coverage/src/fleet-manager/types.ts.html +0 -2602
- package/coverage/src/index.html +0 -116
- package/coverage/src/index.ts.html +0 -181
- package/coverage/src/runner/errors.ts.html +0 -1006
- package/coverage/src/runner/index.html +0 -191
- package/coverage/src/runner/index.ts.html +0 -256
- package/coverage/src/runner/job-executor.ts.html +0 -1429
- package/coverage/src/runner/message-processor.ts.html +0 -1150
- package/coverage/src/runner/sdk-adapter.ts.html +0 -658
- package/coverage/src/runner/types.ts.html +0 -559
- package/coverage/src/scheduler/errors.ts.html +0 -388
- package/coverage/src/scheduler/index.html +0 -206
- package/coverage/src/scheduler/index.ts.html +0 -244
- package/coverage/src/scheduler/interval.ts.html +0 -652
- package/coverage/src/scheduler/schedule-runner.ts.html +0 -1411
- package/coverage/src/scheduler/schedule-state.ts.html +0 -718
- package/coverage/src/scheduler/scheduler.ts.html +0 -1795
- package/coverage/src/scheduler/types.ts.html +0 -733
- package/coverage/src/state/directory.ts.html +0 -736
- package/coverage/src/state/errors.ts.html +0 -376
- package/coverage/src/state/fleet-state.ts.html +0 -937
- package/coverage/src/state/index.html +0 -221
- package/coverage/src/state/index.ts.html +0 -322
- package/coverage/src/state/job-metadata.ts.html +0 -1420
- package/coverage/src/state/job-output.ts.html +0 -1033
- package/coverage/src/state/schemas/fleet-state.ts.html +0 -445
- package/coverage/src/state/schemas/index.html +0 -176
- package/coverage/src/state/schemas/index.ts.html +0 -286
- package/coverage/src/state/schemas/job-metadata.ts.html +0 -628
- package/coverage/src/state/schemas/job-output.ts.html +0 -616
- package/coverage/src/state/schemas/session-info.ts.html +0 -361
- package/coverage/src/state/session.ts.html +0 -844
- package/coverage/src/state/types.ts.html +0 -262
- package/coverage/src/state/utils/atomic.ts.html +0 -748
- package/coverage/src/state/utils/index.html +0 -146
- package/coverage/src/state/utils/index.ts.html +0 -103
- package/coverage/src/state/utils/reads.ts.html +0 -1621
- package/coverage/src/work-sources/adapters/github.ts.html +0 -3583
- package/coverage/src/work-sources/adapters/index.html +0 -131
- package/coverage/src/work-sources/adapters/index.ts.html +0 -277
- package/coverage/src/work-sources/errors.ts.html +0 -298
- package/coverage/src/work-sources/index.html +0 -176
- package/coverage/src/work-sources/index.ts.html +0 -529
- package/coverage/src/work-sources/manager.ts.html +0 -1324
- package/coverage/src/work-sources/registry.ts.html +0 -619
- package/coverage/src/work-sources/types.ts.html +0 -568
- package/dist/fleet-manager/__tests__/event-helpers.test.d.ts +0 -7
- package/dist/fleet-manager/__tests__/event-helpers.test.d.ts.map +0 -1
- package/dist/fleet-manager/__tests__/event-helpers.test.js +0 -368
- package/dist/fleet-manager/__tests__/event-helpers.test.js.map +0 -1
- package/src/config/__tests__/agent.test.ts +0 -864
- package/src/config/__tests__/interpolate.test.ts +0 -644
- package/src/config/__tests__/loader.test.ts +0 -784
- package/src/config/__tests__/merge.test.ts +0 -751
- package/src/config/__tests__/parser.test.ts +0 -533
- package/src/config/__tests__/schema.test.ts +0 -873
- package/src/config/index.ts +0 -119
- package/src/config/interpolate.ts +0 -189
- package/src/config/loader.ts +0 -472
- package/src/config/merge.ts +0 -246
- package/src/config/parser.ts +0 -376
- package/src/config/schema.ts +0 -346
- package/src/fleet-manager/__tests__/coverage.test.ts +0 -2869
- package/src/fleet-manager/__tests__/errors.test.ts +0 -660
- package/src/fleet-manager/__tests__/event-helpers.test.ts +0 -448
- package/src/fleet-manager/__tests__/integration.test.ts +0 -1209
- package/src/fleet-manager/__tests__/job-control.test.ts +0 -283
- package/src/fleet-manager/__tests__/job-manager.test.ts +0 -869
- package/src/fleet-manager/__tests__/job-queue.test.ts +0 -401
- package/src/fleet-manager/__tests__/reload.test.ts +0 -751
- package/src/fleet-manager/__tests__/status-queries.test.ts +0 -595
- package/src/fleet-manager/__tests__/trigger.test.ts +0 -601
- package/src/fleet-manager/errors.ts +0 -747
- package/src/fleet-manager/event-types.ts +0 -378
- package/src/fleet-manager/fleet-manager.ts +0 -2315
- package/src/fleet-manager/index.ts +0 -128
- package/src/fleet-manager/job-manager.ts +0 -663
- package/src/fleet-manager/job-queue.ts +0 -798
- package/src/fleet-manager/types.ts +0 -839
- package/src/index.ts +0 -32
- package/src/runner/__tests__/errors.test.ts +0 -382
- package/src/runner/__tests__/job-executor.test.ts +0 -1708
- package/src/runner/__tests__/message-processor.test.ts +0 -960
- package/src/runner/__tests__/sdk-adapter.test.ts +0 -626
- package/src/runner/errors.ts +0 -307
- package/src/runner/index.ts +0 -57
- package/src/runner/job-executor.ts +0 -448
- package/src/runner/message-processor.ts +0 -355
- package/src/runner/sdk-adapter.ts +0 -191
- package/src/runner/types.ts +0 -158
- package/src/scheduler/__tests__/errors.test.ts +0 -159
- package/src/scheduler/__tests__/interval.test.ts +0 -515
- package/src/scheduler/__tests__/schedule-runner.test.ts +0 -798
- package/src/scheduler/__tests__/schedule-state.test.ts +0 -671
- package/src/scheduler/__tests__/scheduler.test.ts +0 -1280
- package/src/scheduler/errors.ts +0 -101
- package/src/scheduler/index.ts +0 -53
- package/src/scheduler/interval.ts +0 -189
- package/src/scheduler/schedule-runner.ts +0 -442
- package/src/scheduler/schedule-state.ts +0 -211
- package/src/scheduler/scheduler.ts +0 -570
- package/src/scheduler/types.ts +0 -216
- package/src/state/__tests__/directory.test.ts +0 -595
- package/src/state/__tests__/fleet-state.test.ts +0 -868
- package/src/state/__tests__/job-metadata-schema.test.ts +0 -414
- package/src/state/__tests__/job-metadata.test.ts +0 -831
- package/src/state/__tests__/job-output.test.ts +0 -856
- package/src/state/__tests__/session-schema.test.ts +0 -378
- package/src/state/__tests__/session.test.ts +0 -604
- package/src/state/directory.ts +0 -217
- package/src/state/errors.ts +0 -97
- package/src/state/fleet-state.ts +0 -284
- package/src/state/index.ts +0 -79
- package/src/state/job-metadata.ts +0 -445
- package/src/state/job-output.ts +0 -316
- package/src/state/schemas/__tests__/job-output.test.ts +0 -338
- package/src/state/schemas/fleet-state.ts +0 -120
- package/src/state/schemas/index.ts +0 -67
- package/src/state/schemas/job-metadata.ts +0 -181
- package/src/state/schemas/job-output.ts +0 -177
- package/src/state/schemas/session-info.ts +0 -92
- package/src/state/session.ts +0 -253
- package/src/state/types.ts +0 -59
- package/src/state/utils/__tests__/atomic.test.ts +0 -723
- package/src/state/utils/__tests__/reads.test.ts +0 -1071
- package/src/state/utils/atomic.ts +0 -221
- package/src/state/utils/index.ts +0 -6
- package/src/state/utils/reads.ts +0 -512
- package/src/work-sources/__tests__/github.test.ts +0 -1800
- package/src/work-sources/__tests__/manager.test.ts +0 -529
- package/src/work-sources/__tests__/registry.test.ts +0 -477
- package/src/work-sources/__tests__/types.test.ts +0 -479
- package/src/work-sources/adapters/github.ts +0 -1166
- package/src/work-sources/adapters/index.ts +0 -64
- package/src/work-sources/errors.ts +0 -71
- package/src/work-sources/index.ts +0 -148
- package/src/work-sources/manager.ts +0 -413
- package/src/work-sources/registry.ts +0 -178
- package/src/work-sources/types.ts +0 -161
- package/tsconfig.json +0 -9
- package/vitest.config.ts +0 -19
|
@@ -1,477 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect, beforeEach, afterEach } from "vitest";
|
|
2
|
-
import type { WorkSourceAdapter, WorkSourceConfig, WorkSourceFactory } from "../index.js";
|
|
3
|
-
import {
|
|
4
|
-
registerWorkSource,
|
|
5
|
-
getWorkSource,
|
|
6
|
-
getRegisteredTypes,
|
|
7
|
-
isWorkSourceRegistered,
|
|
8
|
-
unregisterWorkSource,
|
|
9
|
-
clearWorkSourceRegistry,
|
|
10
|
-
UnknownWorkSourceError,
|
|
11
|
-
DuplicateWorkSourceError,
|
|
12
|
-
} from "../index.js";
|
|
13
|
-
|
|
14
|
-
// =============================================================================
|
|
15
|
-
// Test Fixtures
|
|
16
|
-
// =============================================================================
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* Create a mock work source adapter for testing
|
|
20
|
-
*/
|
|
21
|
-
function createMockAdapter(type: string): WorkSourceAdapter {
|
|
22
|
-
return {
|
|
23
|
-
type,
|
|
24
|
-
async fetchAvailableWork() {
|
|
25
|
-
return { items: [] };
|
|
26
|
-
},
|
|
27
|
-
async claimWork() {
|
|
28
|
-
return { success: true };
|
|
29
|
-
},
|
|
30
|
-
async completeWork() {},
|
|
31
|
-
async releaseWork() {
|
|
32
|
-
return { success: true };
|
|
33
|
-
},
|
|
34
|
-
async getWork() {
|
|
35
|
-
return undefined;
|
|
36
|
-
},
|
|
37
|
-
};
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* Create a mock factory that returns a configured adapter
|
|
42
|
-
*/
|
|
43
|
-
function createMockFactory(type: string): WorkSourceFactory {
|
|
44
|
-
return (_config: WorkSourceConfig) => createMockAdapter(type);
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
// =============================================================================
|
|
48
|
-
// Test Setup/Teardown
|
|
49
|
-
// =============================================================================
|
|
50
|
-
|
|
51
|
-
describe("Work Source Registry", () => {
|
|
52
|
-
// Store originally registered types to restore after tests
|
|
53
|
-
let originalTypes: string[] = [];
|
|
54
|
-
|
|
55
|
-
beforeEach(() => {
|
|
56
|
-
// Capture what was registered before the test
|
|
57
|
-
originalTypes = getRegisteredTypes();
|
|
58
|
-
// Clear for isolated testing
|
|
59
|
-
clearWorkSourceRegistry();
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
afterEach(() => {
|
|
63
|
-
// Restore original registrations after each test
|
|
64
|
-
clearWorkSourceRegistry();
|
|
65
|
-
// Re-import to trigger auto-registration of built-in adapters
|
|
66
|
-
// Note: In real tests, the module is already loaded so we manually
|
|
67
|
-
// restore the github adapter
|
|
68
|
-
if (originalTypes.includes("github")) {
|
|
69
|
-
registerWorkSource("github", createMockFactory("github"));
|
|
70
|
-
}
|
|
71
|
-
});
|
|
72
|
-
|
|
73
|
-
// ===========================================================================
|
|
74
|
-
// registerWorkSource tests
|
|
75
|
-
// ===========================================================================
|
|
76
|
-
|
|
77
|
-
describe("registerWorkSource", () => {
|
|
78
|
-
it("registers a new work source factory", () => {
|
|
79
|
-
const factory = createMockFactory("test");
|
|
80
|
-
registerWorkSource("test", factory);
|
|
81
|
-
|
|
82
|
-
expect(isWorkSourceRegistered("test")).toBe(true);
|
|
83
|
-
expect(getRegisteredTypes()).toContain("test");
|
|
84
|
-
});
|
|
85
|
-
|
|
86
|
-
it("allows registering multiple different types", () => {
|
|
87
|
-
registerWorkSource("type-a", createMockFactory("type-a"));
|
|
88
|
-
registerWorkSource("type-b", createMockFactory("type-b"));
|
|
89
|
-
registerWorkSource("type-c", createMockFactory("type-c"));
|
|
90
|
-
|
|
91
|
-
const types = getRegisteredTypes();
|
|
92
|
-
expect(types).toContain("type-a");
|
|
93
|
-
expect(types).toContain("type-b");
|
|
94
|
-
expect(types).toContain("type-c");
|
|
95
|
-
expect(types).toHaveLength(3);
|
|
96
|
-
});
|
|
97
|
-
|
|
98
|
-
it("throws DuplicateWorkSourceError when registering same type twice", () => {
|
|
99
|
-
registerWorkSource("duplicate", createMockFactory("duplicate"));
|
|
100
|
-
|
|
101
|
-
expect(() => {
|
|
102
|
-
registerWorkSource("duplicate", createMockFactory("duplicate"));
|
|
103
|
-
}).toThrow(DuplicateWorkSourceError);
|
|
104
|
-
});
|
|
105
|
-
|
|
106
|
-
it("DuplicateWorkSourceError contains the source type", () => {
|
|
107
|
-
registerWorkSource("my-source", createMockFactory("my-source"));
|
|
108
|
-
|
|
109
|
-
try {
|
|
110
|
-
registerWorkSource("my-source", createMockFactory("my-source"));
|
|
111
|
-
expect.fail("Should have thrown DuplicateWorkSourceError");
|
|
112
|
-
} catch (error) {
|
|
113
|
-
expect(error).toBeInstanceOf(DuplicateWorkSourceError);
|
|
114
|
-
const dupError = error as DuplicateWorkSourceError;
|
|
115
|
-
expect(dupError.sourceType).toBe("my-source");
|
|
116
|
-
expect(dupError.message).toContain("my-source");
|
|
117
|
-
expect(dupError.message).toContain("already registered");
|
|
118
|
-
}
|
|
119
|
-
});
|
|
120
|
-
});
|
|
121
|
-
|
|
122
|
-
// ===========================================================================
|
|
123
|
-
// getWorkSource tests
|
|
124
|
-
// ===========================================================================
|
|
125
|
-
|
|
126
|
-
describe("getWorkSource", () => {
|
|
127
|
-
it("returns a configured adapter instance", () => {
|
|
128
|
-
const factory = createMockFactory("test");
|
|
129
|
-
registerWorkSource("test", factory);
|
|
130
|
-
|
|
131
|
-
const adapter = getWorkSource({ type: "test" });
|
|
132
|
-
|
|
133
|
-
expect(adapter).toBeDefined();
|
|
134
|
-
expect(adapter.type).toBe("test");
|
|
135
|
-
});
|
|
136
|
-
|
|
137
|
-
it("calls factory with the provided config", () => {
|
|
138
|
-
let capturedConfig: WorkSourceConfig | undefined;
|
|
139
|
-
const factory: WorkSourceFactory = (config) => {
|
|
140
|
-
capturedConfig = config;
|
|
141
|
-
return createMockAdapter("custom");
|
|
142
|
-
};
|
|
143
|
-
registerWorkSource("custom", factory);
|
|
144
|
-
|
|
145
|
-
const config: WorkSourceConfig = {
|
|
146
|
-
type: "custom",
|
|
147
|
-
labels: { ready: "ready-label", in_progress: "wip-label" },
|
|
148
|
-
customOption: "custom-value",
|
|
149
|
-
};
|
|
150
|
-
getWorkSource(config);
|
|
151
|
-
|
|
152
|
-
expect(capturedConfig).toEqual(config);
|
|
153
|
-
expect(capturedConfig?.customOption).toBe("custom-value");
|
|
154
|
-
});
|
|
155
|
-
|
|
156
|
-
it("throws UnknownWorkSourceError for unregistered type", () => {
|
|
157
|
-
expect(() => {
|
|
158
|
-
getWorkSource({ type: "unknown" });
|
|
159
|
-
}).toThrow(UnknownWorkSourceError);
|
|
160
|
-
});
|
|
161
|
-
|
|
162
|
-
it("UnknownWorkSourceError contains type and available types", () => {
|
|
163
|
-
registerWorkSource("available-a", createMockFactory("available-a"));
|
|
164
|
-
registerWorkSource("available-b", createMockFactory("available-b"));
|
|
165
|
-
|
|
166
|
-
try {
|
|
167
|
-
getWorkSource({ type: "missing" });
|
|
168
|
-
expect.fail("Should have thrown UnknownWorkSourceError");
|
|
169
|
-
} catch (error) {
|
|
170
|
-
expect(error).toBeInstanceOf(UnknownWorkSourceError);
|
|
171
|
-
const unknownError = error as UnknownWorkSourceError;
|
|
172
|
-
expect(unknownError.sourceType).toBe("missing");
|
|
173
|
-
expect(unknownError.availableTypes).toContain("available-a");
|
|
174
|
-
expect(unknownError.availableTypes).toContain("available-b");
|
|
175
|
-
expect(unknownError.message).toContain("missing");
|
|
176
|
-
expect(unknownError.message).toContain("available-a");
|
|
177
|
-
}
|
|
178
|
-
});
|
|
179
|
-
|
|
180
|
-
it("UnknownWorkSourceError shows 'none' when no types registered", () => {
|
|
181
|
-
try {
|
|
182
|
-
getWorkSource({ type: "any" });
|
|
183
|
-
expect.fail("Should have thrown UnknownWorkSourceError");
|
|
184
|
-
} catch (error) {
|
|
185
|
-
expect(error).toBeInstanceOf(UnknownWorkSourceError);
|
|
186
|
-
const unknownError = error as UnknownWorkSourceError;
|
|
187
|
-
expect(unknownError.availableTypes).toEqual([]);
|
|
188
|
-
expect(unknownError.message).toContain("none");
|
|
189
|
-
}
|
|
190
|
-
});
|
|
191
|
-
|
|
192
|
-
it("returns different instances for different configs", () => {
|
|
193
|
-
let callCount = 0;
|
|
194
|
-
const factory: WorkSourceFactory = (config) => {
|
|
195
|
-
callCount++;
|
|
196
|
-
return createMockAdapter("instance");
|
|
197
|
-
};
|
|
198
|
-
registerWorkSource("instance", factory);
|
|
199
|
-
|
|
200
|
-
const adapter1 = getWorkSource({ type: "instance" });
|
|
201
|
-
const adapter2 = getWorkSource({ type: "instance" });
|
|
202
|
-
|
|
203
|
-
// Factory should be called each time
|
|
204
|
-
expect(callCount).toBe(2);
|
|
205
|
-
// Each call creates a new instance
|
|
206
|
-
expect(adapter1).not.toBe(adapter2);
|
|
207
|
-
});
|
|
208
|
-
});
|
|
209
|
-
|
|
210
|
-
// ===========================================================================
|
|
211
|
-
// getRegisteredTypes tests
|
|
212
|
-
// ===========================================================================
|
|
213
|
-
|
|
214
|
-
describe("getRegisteredTypes", () => {
|
|
215
|
-
it("returns empty array when no types registered", () => {
|
|
216
|
-
expect(getRegisteredTypes()).toEqual([]);
|
|
217
|
-
});
|
|
218
|
-
|
|
219
|
-
it("returns all registered types", () => {
|
|
220
|
-
registerWorkSource("alpha", createMockFactory("alpha"));
|
|
221
|
-
registerWorkSource("beta", createMockFactory("beta"));
|
|
222
|
-
|
|
223
|
-
const types = getRegisteredTypes();
|
|
224
|
-
expect(types).toHaveLength(2);
|
|
225
|
-
expect(types).toContain("alpha");
|
|
226
|
-
expect(types).toContain("beta");
|
|
227
|
-
});
|
|
228
|
-
|
|
229
|
-
it("returns a copy, not the internal state", () => {
|
|
230
|
-
registerWorkSource("test", createMockFactory("test"));
|
|
231
|
-
|
|
232
|
-
const types1 = getRegisteredTypes();
|
|
233
|
-
const types2 = getRegisteredTypes();
|
|
234
|
-
|
|
235
|
-
expect(types1).not.toBe(types2);
|
|
236
|
-
expect(types1).toEqual(types2);
|
|
237
|
-
});
|
|
238
|
-
});
|
|
239
|
-
|
|
240
|
-
// ===========================================================================
|
|
241
|
-
// isWorkSourceRegistered tests
|
|
242
|
-
// ===========================================================================
|
|
243
|
-
|
|
244
|
-
describe("isWorkSourceRegistered", () => {
|
|
245
|
-
it("returns false for unregistered type", () => {
|
|
246
|
-
expect(isWorkSourceRegistered("not-registered")).toBe(false);
|
|
247
|
-
});
|
|
248
|
-
|
|
249
|
-
it("returns true for registered type", () => {
|
|
250
|
-
registerWorkSource("registered", createMockFactory("registered"));
|
|
251
|
-
expect(isWorkSourceRegistered("registered")).toBe(true);
|
|
252
|
-
});
|
|
253
|
-
|
|
254
|
-
it("returns false after type is unregistered", () => {
|
|
255
|
-
registerWorkSource("temp", createMockFactory("temp"));
|
|
256
|
-
expect(isWorkSourceRegistered("temp")).toBe(true);
|
|
257
|
-
|
|
258
|
-
unregisterWorkSource("temp");
|
|
259
|
-
expect(isWorkSourceRegistered("temp")).toBe(false);
|
|
260
|
-
});
|
|
261
|
-
});
|
|
262
|
-
|
|
263
|
-
// ===========================================================================
|
|
264
|
-
// unregisterWorkSource tests
|
|
265
|
-
// ===========================================================================
|
|
266
|
-
|
|
267
|
-
describe("unregisterWorkSource", () => {
|
|
268
|
-
it("removes a registered type", () => {
|
|
269
|
-
registerWorkSource("removable", createMockFactory("removable"));
|
|
270
|
-
expect(isWorkSourceRegistered("removable")).toBe(true);
|
|
271
|
-
|
|
272
|
-
const result = unregisterWorkSource("removable");
|
|
273
|
-
|
|
274
|
-
expect(result).toBe(true);
|
|
275
|
-
expect(isWorkSourceRegistered("removable")).toBe(false);
|
|
276
|
-
});
|
|
277
|
-
|
|
278
|
-
it("returns false for unregistered type", () => {
|
|
279
|
-
const result = unregisterWorkSource("never-existed");
|
|
280
|
-
expect(result).toBe(false);
|
|
281
|
-
});
|
|
282
|
-
|
|
283
|
-
it("allows re-registering after unregister", () => {
|
|
284
|
-
registerWorkSource("reuse", createMockFactory("reuse"));
|
|
285
|
-
unregisterWorkSource("reuse");
|
|
286
|
-
|
|
287
|
-
// Should not throw
|
|
288
|
-
registerWorkSource("reuse", createMockFactory("reuse"));
|
|
289
|
-
expect(isWorkSourceRegistered("reuse")).toBe(true);
|
|
290
|
-
});
|
|
291
|
-
});
|
|
292
|
-
|
|
293
|
-
// ===========================================================================
|
|
294
|
-
// clearWorkSourceRegistry tests
|
|
295
|
-
// ===========================================================================
|
|
296
|
-
|
|
297
|
-
describe("clearWorkSourceRegistry", () => {
|
|
298
|
-
it("removes all registered types", () => {
|
|
299
|
-
registerWorkSource("one", createMockFactory("one"));
|
|
300
|
-
registerWorkSource("two", createMockFactory("two"));
|
|
301
|
-
registerWorkSource("three", createMockFactory("three"));
|
|
302
|
-
|
|
303
|
-
clearWorkSourceRegistry();
|
|
304
|
-
|
|
305
|
-
expect(getRegisteredTypes()).toEqual([]);
|
|
306
|
-
expect(isWorkSourceRegistered("one")).toBe(false);
|
|
307
|
-
expect(isWorkSourceRegistered("two")).toBe(false);
|
|
308
|
-
expect(isWorkSourceRegistered("three")).toBe(false);
|
|
309
|
-
});
|
|
310
|
-
|
|
311
|
-
it("is idempotent", () => {
|
|
312
|
-
registerWorkSource("test", createMockFactory("test"));
|
|
313
|
-
|
|
314
|
-
clearWorkSourceRegistry();
|
|
315
|
-
clearWorkSourceRegistry();
|
|
316
|
-
clearWorkSourceRegistry();
|
|
317
|
-
|
|
318
|
-
expect(getRegisteredTypes()).toEqual([]);
|
|
319
|
-
});
|
|
320
|
-
});
|
|
321
|
-
|
|
322
|
-
// ===========================================================================
|
|
323
|
-
// Factory pattern tests
|
|
324
|
-
// ===========================================================================
|
|
325
|
-
|
|
326
|
-
describe("Factory Pattern", () => {
|
|
327
|
-
it("factory receives full config for customization", () => {
|
|
328
|
-
interface CustomConfig extends WorkSourceConfig {
|
|
329
|
-
apiToken?: string;
|
|
330
|
-
baseUrl?: string;
|
|
331
|
-
}
|
|
332
|
-
|
|
333
|
-
let receivedToken: string | undefined;
|
|
334
|
-
let receivedUrl: string | undefined;
|
|
335
|
-
|
|
336
|
-
const factory: WorkSourceFactory = (config) => {
|
|
337
|
-
const customConfig = config as CustomConfig;
|
|
338
|
-
receivedToken = customConfig.apiToken;
|
|
339
|
-
receivedUrl = customConfig.baseUrl;
|
|
340
|
-
return createMockAdapter("custom");
|
|
341
|
-
};
|
|
342
|
-
|
|
343
|
-
registerWorkSource("custom", factory);
|
|
344
|
-
|
|
345
|
-
getWorkSource({
|
|
346
|
-
type: "custom",
|
|
347
|
-
apiToken: "secret-token",
|
|
348
|
-
baseUrl: "https://api.example.com",
|
|
349
|
-
});
|
|
350
|
-
|
|
351
|
-
expect(receivedToken).toBe("secret-token");
|
|
352
|
-
expect(receivedUrl).toBe("https://api.example.com");
|
|
353
|
-
});
|
|
354
|
-
|
|
355
|
-
it("factory can create different adapters based on config", () => {
|
|
356
|
-
const factory: WorkSourceFactory = (config) => {
|
|
357
|
-
const adapter = createMockAdapter("conditional");
|
|
358
|
-
// Override fetchAvailableWork based on config
|
|
359
|
-
if (config.labels?.ready === "special") {
|
|
360
|
-
adapter.fetchAvailableWork = async () => ({
|
|
361
|
-
items: [],
|
|
362
|
-
totalCount: 999,
|
|
363
|
-
});
|
|
364
|
-
}
|
|
365
|
-
return adapter;
|
|
366
|
-
};
|
|
367
|
-
|
|
368
|
-
registerWorkSource("conditional", factory);
|
|
369
|
-
|
|
370
|
-
const normalAdapter = getWorkSource({ type: "conditional" });
|
|
371
|
-
const specialAdapter = getWorkSource({
|
|
372
|
-
type: "conditional",
|
|
373
|
-
labels: { ready: "special" },
|
|
374
|
-
});
|
|
375
|
-
|
|
376
|
-
// Both are valid adapters with different behavior
|
|
377
|
-
expect(normalAdapter.type).toBe("conditional");
|
|
378
|
-
expect(specialAdapter.type).toBe("conditional");
|
|
379
|
-
});
|
|
380
|
-
});
|
|
381
|
-
|
|
382
|
-
// ===========================================================================
|
|
383
|
-
// Module singleton behavior tests
|
|
384
|
-
// ===========================================================================
|
|
385
|
-
|
|
386
|
-
describe("Singleton Behavior", () => {
|
|
387
|
-
it("registry state persists across function calls", () => {
|
|
388
|
-
registerWorkSource("persistent", createMockFactory("persistent"));
|
|
389
|
-
|
|
390
|
-
// Multiple calls to check registration all see the same state
|
|
391
|
-
expect(isWorkSourceRegistered("persistent")).toBe(true);
|
|
392
|
-
expect(getRegisteredTypes()).toContain("persistent");
|
|
393
|
-
expect(() => getWorkSource({ type: "persistent" })).not.toThrow();
|
|
394
|
-
});
|
|
395
|
-
|
|
396
|
-
it("modifications are visible to subsequent operations", () => {
|
|
397
|
-
// Register
|
|
398
|
-
registerWorkSource("visible", createMockFactory("visible"));
|
|
399
|
-
expect(getRegisteredTypes()).toContain("visible");
|
|
400
|
-
|
|
401
|
-
// Unregister
|
|
402
|
-
unregisterWorkSource("visible");
|
|
403
|
-
expect(getRegisteredTypes()).not.toContain("visible");
|
|
404
|
-
|
|
405
|
-
// Re-register
|
|
406
|
-
registerWorkSource("visible", createMockFactory("visible"));
|
|
407
|
-
expect(getRegisteredTypes()).toContain("visible");
|
|
408
|
-
});
|
|
409
|
-
});
|
|
410
|
-
});
|
|
411
|
-
|
|
412
|
-
// =============================================================================
|
|
413
|
-
// Built-in Adapter Registration Tests
|
|
414
|
-
// =============================================================================
|
|
415
|
-
|
|
416
|
-
describe("Built-in Adapters", () => {
|
|
417
|
-
it("github adapter is pre-registered at module load", async () => {
|
|
418
|
-
// The adapters/index.js module auto-registers when imported.
|
|
419
|
-
// Since ESM modules are cached, we need to manually register
|
|
420
|
-
// after clearing for tests.
|
|
421
|
-
clearWorkSourceRegistry();
|
|
422
|
-
|
|
423
|
-
// Import the factory directly and register it
|
|
424
|
-
const { createGitHubAdapter } = await import("../adapters/github.js");
|
|
425
|
-
registerWorkSource("github", createGitHubAdapter);
|
|
426
|
-
|
|
427
|
-
expect(isWorkSourceRegistered("github")).toBe(true);
|
|
428
|
-
expect(getRegisteredTypes()).toContain("github");
|
|
429
|
-
});
|
|
430
|
-
|
|
431
|
-
it("github adapter can be retrieved via getWorkSource", async () => {
|
|
432
|
-
clearWorkSourceRegistry();
|
|
433
|
-
const { createGitHubAdapter } = await import("../adapters/github.js");
|
|
434
|
-
registerWorkSource("github", createGitHubAdapter);
|
|
435
|
-
|
|
436
|
-
const adapter = getWorkSource({ type: "github" });
|
|
437
|
-
|
|
438
|
-
expect(adapter).toBeDefined();
|
|
439
|
-
expect(adapter.type).toBe("github");
|
|
440
|
-
});
|
|
441
|
-
|
|
442
|
-
it("github adapter respects config labels", async () => {
|
|
443
|
-
clearWorkSourceRegistry();
|
|
444
|
-
const { createGitHubAdapter } = await import("../adapters/github.js");
|
|
445
|
-
registerWorkSource("github", createGitHubAdapter);
|
|
446
|
-
|
|
447
|
-
// Should not throw - config is passed to factory
|
|
448
|
-
const adapter = getWorkSource({
|
|
449
|
-
type: "github",
|
|
450
|
-
labels: {
|
|
451
|
-
ready: "custom-ready",
|
|
452
|
-
in_progress: "custom-wip",
|
|
453
|
-
},
|
|
454
|
-
});
|
|
455
|
-
|
|
456
|
-
expect(adapter.type).toBe("github");
|
|
457
|
-
});
|
|
458
|
-
|
|
459
|
-
it("GitHubWorkSourceAdapter implements WorkSourceAdapter interface", async () => {
|
|
460
|
-
const { GitHubWorkSourceAdapter } = await import("../adapters/github.js");
|
|
461
|
-
|
|
462
|
-
const adapter = new GitHubWorkSourceAdapter({
|
|
463
|
-
type: "github",
|
|
464
|
-
owner: "testowner",
|
|
465
|
-
repo: "testrepo",
|
|
466
|
-
labels: { ready: "ready", in_progress: "wip" },
|
|
467
|
-
});
|
|
468
|
-
|
|
469
|
-
// Verify the interface
|
|
470
|
-
expect(adapter.type).toBe("github");
|
|
471
|
-
expect(typeof adapter.fetchAvailableWork).toBe("function");
|
|
472
|
-
expect(typeof adapter.claimWork).toBe("function");
|
|
473
|
-
expect(typeof adapter.completeWork).toBe("function");
|
|
474
|
-
expect(typeof adapter.releaseWork).toBe("function");
|
|
475
|
-
expect(typeof adapter.getWork).toBe("function");
|
|
476
|
-
});
|
|
477
|
-
});
|