@memberjunction/testing-integration 0.0.0 → 5.50.0

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.
Files changed (66) hide show
  1. package/dist/IntegrationTestDriver.d.ts +63 -0
  2. package/dist/IntegrationTestDriver.d.ts.map +1 -0
  3. package/dist/IntegrationTestDriver.js +425 -0
  4. package/dist/IntegrationTestDriver.js.map +1 -0
  5. package/dist/ai-verify.d.ts +27 -0
  6. package/dist/ai-verify.d.ts.map +1 -0
  7. package/dist/ai-verify.js +137 -0
  8. package/dist/ai-verify.js.map +1 -0
  9. package/dist/bootstrap-client.d.ts +11 -0
  10. package/dist/bootstrap-client.d.ts.map +1 -0
  11. package/dist/bootstrap-client.js +68 -0
  12. package/dist/bootstrap-client.js.map +1 -0
  13. package/dist/bootstrap-shared.d.ts +94 -0
  14. package/dist/bootstrap-shared.d.ts.map +1 -0
  15. package/dist/bootstrap-shared.js +94 -0
  16. package/dist/bootstrap-shared.js.map +1 -0
  17. package/dist/bootstrap.d.ts +14 -0
  18. package/dist/bootstrap.d.ts.map +1 -0
  19. package/dist/bootstrap.js +133 -0
  20. package/dist/bootstrap.js.map +1 -0
  21. package/dist/check-registry.d.ts +39 -0
  22. package/dist/check-registry.d.ts.map +1 -0
  23. package/dist/check-registry.js +61 -0
  24. package/dist/check-registry.js.map +1 -0
  25. package/dist/check.d.ts +531 -0
  26. package/dist/check.d.ts.map +1 -0
  27. package/dist/check.js +2 -0
  28. package/dist/check.js.map +1 -0
  29. package/dist/checks/self-test.check.d.ts +2 -0
  30. package/dist/checks/self-test.check.d.ts.map +1 -0
  31. package/dist/checks/self-test.check.js +35 -0
  32. package/dist/checks/self-test.check.js.map +1 -0
  33. package/dist/config.d.ts +35 -0
  34. package/dist/config.d.ts.map +1 -0
  35. package/dist/config.js +81 -0
  36. package/dist/config.js.map +1 -0
  37. package/dist/index.d.ts +25 -0
  38. package/dist/index.d.ts.map +1 -0
  39. package/dist/index.js +37 -0
  40. package/dist/index.js.map +1 -0
  41. package/dist/instrumented-cache.d.ts +47 -0
  42. package/dist/instrumented-cache.d.ts.map +1 -0
  43. package/dist/instrumented-cache.js +81 -0
  44. package/dist/instrumented-cache.js.map +1 -0
  45. package/dist/registry.d.ts +33 -0
  46. package/dist/registry.d.ts.map +1 -0
  47. package/dist/registry.js +37 -0
  48. package/dist/registry.js.map +1 -0
  49. package/dist/rls-fixture.d.ts +37 -0
  50. package/dist/rls-fixture.d.ts.map +1 -0
  51. package/dist/rls-fixture.js +91 -0
  52. package/dist/rls-fixture.js.map +1 -0
  53. package/dist/test-runner.d.ts +55 -0
  54. package/dist/test-runner.d.ts.map +1 -0
  55. package/dist/test-runner.js +128 -0
  56. package/dist/test-runner.js.map +1 -0
  57. package/dist/tiers.d.ts +28 -0
  58. package/dist/tiers.d.ts.map +1 -0
  59. package/dist/tiers.js +41 -0
  60. package/dist/tiers.js.map +1 -0
  61. package/dist/types.d.ts +51 -0
  62. package/dist/types.d.ts.map +1 -0
  63. package/dist/types.js +2 -0
  64. package/dist/types.js.map +1 -0
  65. package/package.json +59 -8
  66. package/README.md +0 -45
@@ -0,0 +1,63 @@
1
+ import { BaseTestDriver, DriverExecutionContext, DriverExecutionResult, SuiteFixtureContext } from '@memberjunction/testing-engine';
2
+ import type { UserInfo } from '@memberjunction/core';
3
+ export declare class IntegrationTestDriver extends BaseTestDriver {
4
+ /** The driver arms its own timeout and breaks the check loop when it fires. */
5
+ supportsCancellation(): boolean;
6
+ /**
7
+ * Suite-scoped setup (D6). Discovers the two-user RLS fixture ONCE per suite run and
8
+ * stashes it on the shared SuiteFixtureContext so every test of the suite (and the
9
+ * `rls-isolation` bundle's checks) reads the same pair. Best-effort: discovery has
10
+ * nothing to delete, so failures are non-fatal — Execute lazily re-discovers when the
11
+ * fixture is absent (e.g. the `mj test run` path has no suite). Only meaningful on the
12
+ * server transport (the user cache is a SQLServerDataProvider concept).
13
+ */
14
+ SetupSuite(context: SuiteFixtureContext, _contextUser: UserInfo): Promise<void>;
15
+ /**
16
+ * Suite-scoped teardown (D6). No-op: the RLS fixture is DISCOVERED (not created), so
17
+ * there is nothing to delete — the safest possible teardown. Present so the engine's
18
+ * suite-hook lifecycle is exercised end-to-end by this driver.
19
+ */
20
+ TeardownSuite(_context: SuiteFixtureContext, _contextUser: UserInfo): Promise<void>;
21
+ /**
22
+ * The two-user RLS fixture for the current run: the one discovered in SetupSuite when
23
+ * available, otherwise discovered lazily here (the no-suite `mj test run` path) and
24
+ * cached back onto the suite context for sibling tests.
25
+ */
26
+ private ensureRlsFixture;
27
+ Execute(context: DriverExecutionContext): Promise<DriverExecutionResult>;
28
+ /**
29
+ * Resolve a bundle and run its ordered checks. A bundle that registers a BundleLifecycle
30
+ * (runquery-cache, field-rules-bulk-update, …) has its Setup + Teardown wrapped in ONE
31
+ * try/finally so Teardown is guaranteed even on a mid-Setup crash (R4). Mutation-gated
32
+ * checks run only when `runMutation` is set.
33
+ */
34
+ private runBundle;
35
+ /**
36
+ * C6: run a single check but bound it by the remaining run budget. The between-checks `timedOut`
37
+ * flag can only stop the loop between checks — a check that hangs forever would otherwise run
38
+ * past the deadline unbounded. Racing the check against a per-check timeout makes a hang surface
39
+ * as a failed check with a clear message (caught by runCheck's try/catch) instead of a wedged
40
+ * run. The check's own promise may keep running after we move on, but the process is dedicated
41
+ * and short-lived (D1), so a dangling promise on the timeout path is harmless.
42
+ */
43
+ private runWithDeadline;
44
+ /** Run one check in try/catch and append one OracleResult + one TestOutcome. */
45
+ private runCheck;
46
+ /** client-cache / rls-isolation-client run on the GraphQL client transport; others on SQL server. */
47
+ private bundleTransport;
48
+ /**
49
+ * Obtain the run-scoped instrumented provider stack for the chosen transport.
50
+ * Prefers a stack already installed first-caller (CLI's installInstrumentedCacheFirst,
51
+ * or a prior bootstrap in this process); falls back to owning the process. Throws
52
+ * (caught upstream) when a client bundle is requested but the cache was already claimed
53
+ * by a SQL provider, or vice-versa.
54
+ */
55
+ private buildCheckContext;
56
+ /** Map the OracleResult[] to the framework result (one OracleResult per check). */
57
+ private buildResult;
58
+ /** Gated/skipped run: one passing 'gate' OracleResult, never 'Running', never thrown. */
59
+ private buildSkipResult;
60
+ /** Bootstrap/config error: one failing 'error' OracleResult, status 'Error', never thrown. */
61
+ private buildErrorResult;
62
+ }
63
+ //# sourceMappingURL=IntegrationTestDriver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"IntegrationTestDriver.d.ts","sourceRoot":"","sources":["../src/IntegrationTestDriver.ts"],"names":[],"mappings":"AAyBA,OAAO,EACH,cAAc,EACd,sBAAsB,EACtB,qBAAqB,EAErB,mBAAmB,EACtB,MAAM,gCAAgC,CAAC;AAExC,OAAO,KAAK,EAAE,QAAQ,EAAqB,MAAM,sBAAsB,CAAC;AA2BxE,qBACa,qBAAsB,SAAQ,cAAc;IACrD,+EAA+E;IAC/D,oBAAoB,IAAI,OAAO;IAI/C;;;;;;;OAOG;IACmB,UAAU,CAAC,OAAO,EAAE,mBAAmB,EAAE,YAAY,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAWrG;;;;OAIG;IACmB,aAAa,CAAC,QAAQ,EAAE,mBAAmB,EAAE,YAAY,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAIzG;;;;OAIG;IACH,OAAO,CAAC,gBAAgB;IAYX,OAAO,CAAC,OAAO,EAAE,sBAAsB,GAAG,OAAO,CAAC,qBAAqB,CAAC;IA+FrF;;;;;OAKG;YACW,SAAS;IAoFvB;;;;;;;OAOG;YACW,eAAe;IA0B7B,gFAAgF;YAClE,QAAQ;IAgCtB,qGAAqG;IACrG,OAAO,CAAC,eAAe;IAIvB;;;;;;OAMG;YACW,iBAAiB;IAqD/B,mFAAmF;IACnF,OAAO,CAAC,WAAW;IA8BnB,yFAAyF;IACzF,OAAO,CAAC,eAAe;IAcvB,8FAA8F;IAC9F,OAAO,CAAC,gBAAgB;CAe3B"}
@@ -0,0 +1,425 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ /**
8
+ * IntegrationTestDriver.ts — the TestType driver for the "Integration Test" type.
9
+ *
10
+ * Resolved by TestEngine.getDriver() from TestType.DriverClass via
11
+ * MJGlobal.ClassFactory.CreateInstance(BaseTestDriver, 'IntegrationTestDriver').
12
+ *
13
+ * Execute():
14
+ * 1) parse Configuration.checks (an ordered list of check BUNDLES) off MJTestEntity;
15
+ * 2) honor an optional env gate (skip-as-Passed with a note);
16
+ * 3) infer the transport (client-cache ⇒ GraphQL client, else SQL server) and obtain
17
+ * the run-scoped instrumented provider stack (installed first-caller by the CLI,
18
+ * or self-bootstrapped in a dedicated process);
19
+ * 4) for each selected bundle, run its registered NamedCheck[] in array order against
20
+ * ONE shared IntegrationCheckContext — skipping RequiresMutation checks unless the
21
+ * selector opts in — converting a thrown check into a failing OracleResult (never
22
+ * re-throwing; a re-throw would leave the TestRun stuck 'Running'). A bundle that
23
+ * registers a BundleLifecycle (e.g. runquery-cache, field-rules-bulk-update) has its
24
+ * Setup run and Teardown GUARANTEED inside one try/finally, so a mid-Setup crash still
25
+ * tears down whatever the Setup accumulated (R4);
26
+ * 5) map the OracleResult[] onto a DriverExecutionResult (counts computed exactly
27
+ * like AgentEvalDriver). The engine persists oracleResults verbatim to
28
+ * TestRun.ResultDetails as a BARE ARRAY. When EMIT_OUTCOMES is set, also write a
29
+ * {name,passed,durationMs,error}[] sidecar for the golden-equivalence diff.
30
+ */
31
+ import { RegisterClass } from '@memberjunction/global';
32
+ import { BaseTestDriver } from '@memberjunction/testing-engine';
33
+ import { Metadata, ProviderType } from '@memberjunction/core';
34
+ import { UserCache } from '@memberjunction/sqlserver-dataprovider';
35
+ import { getActiveIntegrationStorage, getActiveIntegrationBootstrap, getActiveIntegrationClientBootstrap, bootstrapIntegrationServer, serverProcessAlreadyClaimed } from './bootstrap.js';
36
+ import { bootstrapIntegrationClient } from './bootstrap-client.js';
37
+ import { IntegrationCheckRegistry } from './check-registry.js';
38
+ import { TIER_ENV_GATE, IsTierEnabled } from './tiers.js';
39
+ import { writeOutcomesFile } from './test-runner.js';
40
+ import { discoverRlsFixture } from './rls-fixture.js';
41
+ const TARGET_TYPE = 'Integration Check Bundle';
42
+ /** Bundles that run against the GraphQL client transport (everything else: SQL server). */
43
+ const CLIENT_BUNDLES = new Set(['client-cache', 'rls-isolation-client', 'remote-op-wire-progress']);
44
+ /** Bundles that need the discovered two-user RLS fixture threaded into the context. */
45
+ const RLS_BUNDLES = new Set(['rls-isolation', 'rls-isolation-client']);
46
+ /** Key under SuiteFixtureContext.Data where the discovered RLS fixture is stashed. */
47
+ const RLS_FIXTURE_KEY = 'rlsFixture';
48
+ let IntegrationTestDriver = class IntegrationTestDriver extends BaseTestDriver {
49
+ /** The driver arms its own timeout and breaks the check loop when it fires. */
50
+ supportsCancellation() {
51
+ return true;
52
+ }
53
+ /**
54
+ * Suite-scoped setup (D6). Discovers the two-user RLS fixture ONCE per suite run and
55
+ * stashes it on the shared SuiteFixtureContext so every test of the suite (and the
56
+ * `rls-isolation` bundle's checks) reads the same pair. Best-effort: discovery has
57
+ * nothing to delete, so failures are non-fatal — Execute lazily re-discovers when the
58
+ * fixture is absent (e.g. the `mj test run` path has no suite). Only meaningful on the
59
+ * server transport (the user cache is a SQLServerDataProvider concept).
60
+ */
61
+ async SetupSuite(context, _contextUser) {
62
+ try {
63
+ const users = UserCache.Instance.Users;
64
+ if (users && users.length > 0) {
65
+ context.Data[RLS_FIXTURE_KEY] = discoverRlsFixture(this.Provider, users);
66
+ }
67
+ }
68
+ catch (e) {
69
+ this.log(`SetupSuite RLS discovery skipped: ${e.message}`);
70
+ }
71
+ }
72
+ /**
73
+ * Suite-scoped teardown (D6). No-op: the RLS fixture is DISCOVERED (not created), so
74
+ * there is nothing to delete — the safest possible teardown. Present so the engine's
75
+ * suite-hook lifecycle is exercised end-to-end by this driver.
76
+ */
77
+ async TeardownSuite(_context, _contextUser) {
78
+ // no-op — discovery-based fixture has nothing to clean up
79
+ }
80
+ /**
81
+ * The two-user RLS fixture for the current run: the one discovered in SetupSuite when
82
+ * available, otherwise discovered lazily here (the no-suite `mj test run` path) and
83
+ * cached back onto the suite context for sibling tests.
84
+ */
85
+ ensureRlsFixture(context) {
86
+ const cached = context.fixtures?.Data?.[RLS_FIXTURE_KEY];
87
+ if (cached) {
88
+ return cached;
89
+ }
90
+ const fx = discoverRlsFixture(this.Provider, UserCache.Instance.Users);
91
+ if (context.fixtures) {
92
+ context.fixtures.Data[RLS_FIXTURE_KEY] = fx;
93
+ }
94
+ return fx;
95
+ }
96
+ async Execute(context) {
97
+ const startTime = Date.now();
98
+ this.logToTestRun(context, 'info', 'Starting integration test execution');
99
+ // 1) Parse Configuration. parseConfig throws on missing/bad JSON — convert to a
100
+ // Failed/Error result rather than re-throwing (re-throw would leave TestRun 'Running').
101
+ let config;
102
+ try {
103
+ config = this.parseConfig(context.test);
104
+ }
105
+ catch (err) {
106
+ return this.buildErrorResult(context, startTime, err.message);
107
+ }
108
+ // 2) Whole-test tier gate (gated-tier / local-dev safety net). The tier decides the
109
+ // env var via TIER_ENV_GATE; an explicit `requiresEnv` overrides it. When the gate
110
+ // is unmet, skip-as-Passed with a gate note — the driver result enum has no 'Skipped'.
111
+ const tier = config.tier ?? 'deterministic';
112
+ const explicitGate = config.requiresEnv;
113
+ const gated = explicitGate ? process.env[explicitGate] !== '1' : !IsTierEnabled(tier);
114
+ if (gated) {
115
+ const gateVar = explicitGate ?? TIER_ENV_GATE[tier];
116
+ const note = `Skipped: ${gateVar} not set (tier '${tier}')`;
117
+ this.logToTestRun(context, 'warn', note);
118
+ return this.buildSkipResult(context, startTime, note);
119
+ }
120
+ const selectors = Array.isArray(config.checks) ? config.checks : [];
121
+ const transport = config.transport ?? (selectors.some(s => this.bundleTransport(s.type) === 'client') ? 'client' : 'server');
122
+ // 2b) D1 host check. These suites must own their process — install the instrumented
123
+ // cache as the FIRST caller of LocalCacheManager.Initialize. Inside a live MJAPI
124
+ // the cache is already initialized, so they cannot run here. Fail fast with an
125
+ // actionable message (run via the CLI) instead of a confusing bootstrap stack.
126
+ if (transport === 'server' && serverProcessAlreadyClaimed()) {
127
+ return this.buildErrorResult(context, startTime, 'Integration cache suites must run in a dedicated process: run `npm run test:integration`, ' +
128
+ 'or `MJ_INTEGRATION_TEST=1 mj test suite --name "<suite>"`. They cannot run inside a live ' +
129
+ 'MJAPI — the cache is already initialized, so the instrumented cache cannot be installed ' +
130
+ 'first (plan decision D1).');
131
+ }
132
+ // 3) Arm a driver-side timeout (the engine never applies one). The timer flips `timedOut`
133
+ // to abort the loop BETWEEN checks; the `deadline` additionally bounds EACH check via a
134
+ // per-check race (C6), so a single hung check can't run past the budget forever.
135
+ const effectiveTimeout = this.getEffectiveTimeout(context.test);
136
+ const deadline = Date.now() + effectiveTimeout;
137
+ let timedOut = false;
138
+ const timer = setTimeout(() => { timedOut = true; }, effectiveTimeout);
139
+ const oracleResults = [];
140
+ const outcomes = []; // parallel array for the EMIT_OUTCOMES sidecar
141
+ try {
142
+ const checkCtx = await this.buildCheckContext(context, transport);
143
+ // 4) Run each selected bundle's checks IN ORDER against ONE shared context.
144
+ for (const sel of selectors) {
145
+ if (timedOut) {
146
+ break;
147
+ }
148
+ await this.runBundle(context, checkCtx, sel.type, sel.config, oracleResults, outcomes, () => timedOut, deadline);
149
+ }
150
+ }
151
+ catch (bootErr) {
152
+ clearTimeout(timer);
153
+ const msg = bootErr.message ?? String(bootErr);
154
+ // ENVIRONMENT GAP, not a product defect: client-transport bundles need a live MJAPI.
155
+ // When the preflight says the server is simply absent (CI runs no MJAPI), skip-as-pass
156
+ // loudly — the same contract the old per-bundle tsx dispatchers honored with exit 0.
157
+ // Any OTHER bootstrap failure (bad credentials, cache ownership, config) stays a
158
+ // hard error.
159
+ if (transport === 'client' && /MJAPI is not reachable/i.test(msg)) {
160
+ return this.buildSkipResult(context, startTime, `SKIPPED (environment gap): ${msg} Client-transport checks need a live MJAPI; start it and re-run for full coverage.`);
161
+ }
162
+ return this.buildErrorResult(context, startTime, `Bootstrap failed: ${msg}`);
163
+ }
164
+ clearTimeout(timer);
165
+ // 5a) Optional golden-diff sidecar — same shape the tsx scripts emit via EmitOutcomes.
166
+ const emitPath = process.env.EMIT_OUTCOMES;
167
+ if (emitPath) {
168
+ try {
169
+ await writeOutcomesFile(emitPath, outcomes);
170
+ }
171
+ catch (e) {
172
+ this.logToTestRun(context, 'warn', `EMIT_OUTCOMES write failed: ${e.message}`);
173
+ }
174
+ }
175
+ // 5b) Assemble the DriverExecutionResult (counts mirror AgentEvalDriver).
176
+ return this.buildResult(context, startTime, oracleResults, timedOut);
177
+ }
178
+ /**
179
+ * Resolve a bundle and run its ordered checks. A bundle that registers a BundleLifecycle
180
+ * (runquery-cache, field-rules-bulk-update, …) has its Setup + Teardown wrapped in ONE
181
+ * try/finally so Teardown is guaranteed even on a mid-Setup crash (R4). Mutation-gated
182
+ * checks run only when `runMutation` is set.
183
+ */
184
+ async runBundle(context, checkCtx, bundleType, selConfig, oracleResults, outcomes, isTimedOut, deadline) {
185
+ const bundle = IntegrationCheckRegistry.Instance.GetBundle(bundleType);
186
+ if (bundle.length === 0) {
187
+ const message = `Unknown integration check bundle '${bundleType}'. ` +
188
+ `Check bundles register via import side effects — MJ's own bundles live in the private ` +
189
+ `@memberjunction/integration-test-suite package, loaded through mj.config.cjs ` +
190
+ `\`testing.checkModules\` (or the --checks-module flag). If this bundle should exist, ` +
191
+ `verify that config key is present, the module is built, and the bundle name matches.`;
192
+ oracleResults.push({ oracleType: bundleType, passed: false, score: 0, message, details: { DurationMs: 0 } });
193
+ outcomes.push({ Name: bundleType, Passed: false, DurationMs: 0, Error: message });
194
+ this.logToTestRun(context, 'error', `✗ ${message}`);
195
+ return;
196
+ }
197
+ // Expose the selector's opaque config bag to the bundle's checks (e.g. dataset-cache
198
+ // reads `datasetName`, aggregates-cache reads `entityName`). Set per-bundle since the
199
+ // check context is shared and reused across bundles within one Execute.
200
+ checkCtx.Config = selConfig;
201
+ // The rls-isolation bundles need the discovered two-user fixture (suite-scoped via
202
+ // SetupSuite, or lazily discovered for the no-suite `mj test run` path).
203
+ if (RLS_BUNDLES.has(bundleType)) {
204
+ checkCtx.RlsFixture = this.ensureRlsFixture(context);
205
+ }
206
+ const runMutation = selConfig?.runMutationTests === true;
207
+ // Per-check tier gating routed through the shared IsTierEnabled predicate (the same
208
+ // one the tsx scripts use) so the env gate is honored identically. A selector may also
209
+ // opt mutation checks in explicitly via config.runMutationTests, independent of env.
210
+ const mutationEnabled = IsTierEnabled('mutation') || runMutation;
211
+ const liveModelEnabled = IsTierEnabled('live-model');
212
+ // A mutating bundle registers a lifecycle (setup creates a shared fixture on the context,
213
+ // teardown removes it). R4: run Setup INSIDE the same try whose finally guarantees Teardown,
214
+ // so a mid-Setup crash still runs Teardown against whatever the Setup accumulated onto the
215
+ // context so far (lifecycle Setups publish their fixture handle up-front and append created
216
+ // IDs as they go). A Setup failure short-circuits the bundle with one failing 'fixtures'
217
+ // oracle and skips the checks — but never re-throws and never leaves the fixture orphaned.
218
+ const lifecycle = IntegrationCheckRegistry.Instance.GetLifecycle(bundleType);
219
+ try {
220
+ if (lifecycle) {
221
+ await lifecycle.Setup(checkCtx);
222
+ }
223
+ for (const check of bundle) {
224
+ if (isTimedOut()) {
225
+ break;
226
+ }
227
+ if (check.RequiresMutation && !mutationEnabled) {
228
+ continue;
229
+ }
230
+ if (check.RequiresLiveModel && !liveModelEnabled) {
231
+ continue;
232
+ }
233
+ await this.runCheck(context, checkCtx, check.Id, check.Name, check.Fn, oracleResults, outcomes, deadline);
234
+ }
235
+ }
236
+ catch (fxErr) {
237
+ // The only throw reachable here is from lifecycle.Setup — runCheck swallows per-check
238
+ // errors into results. Record it as a failing 'fixtures' oracle (never re-thrown).
239
+ const message = `${bundleType} fixture setup failed: ${fxErr.message}`;
240
+ oracleResults.push({ oracleType: `${bundleType}.fixtures`, passed: false, score: 0, message, details: { DurationMs: 0 } });
241
+ outcomes.push({ Name: `${bundleType}.fixtures`, Passed: false, DurationMs: 0, Error: message });
242
+ this.logToTestRun(context, 'error', message);
243
+ }
244
+ finally {
245
+ if (lifecycle) {
246
+ // Best-effort — a teardown failure must never mask a check result or leave TestRun 'Running'.
247
+ try {
248
+ await lifecycle.Teardown(checkCtx);
249
+ }
250
+ catch (tdErr) {
251
+ this.logToTestRun(context, 'warn', `${bundleType} teardown warning: ${tdErr.message}`);
252
+ }
253
+ }
254
+ }
255
+ }
256
+ /**
257
+ * C6: run a single check but bound it by the remaining run budget. The between-checks `timedOut`
258
+ * flag can only stop the loop between checks — a check that hangs forever would otherwise run
259
+ * past the deadline unbounded. Racing the check against a per-check timeout makes a hang surface
260
+ * as a failed check with a clear message (caught by runCheck's try/catch) instead of a wedged
261
+ * run. The check's own promise may keep running after we move on, but the process is dedicated
262
+ * and short-lived (D1), so a dangling promise on the timeout path is harmless.
263
+ */
264
+ async runWithDeadline(id, fn, checkCtx, deadline) {
265
+ const remaining = deadline - Date.now();
266
+ if (remaining <= 0) {
267
+ throw new Error(`integration run budget exhausted before check '${id}' started`);
268
+ }
269
+ let timer;
270
+ const timeout = new Promise((_, reject) => {
271
+ timer = setTimeout(() => reject(new Error(`check '${id}' exceeded the ${remaining}ms remaining run budget (hung check)`)), remaining);
272
+ });
273
+ try {
274
+ await Promise.race([fn(checkCtx), timeout]);
275
+ }
276
+ finally {
277
+ if (timer) {
278
+ clearTimeout(timer);
279
+ }
280
+ }
281
+ }
282
+ /** Run one check in try/catch and append one OracleResult + one TestOutcome. */
283
+ async runCheck(context, checkCtx, id, name, fn, oracleResults, outcomes, deadline) {
284
+ const checkStart = Date.now();
285
+ try {
286
+ await this.runWithDeadline(id, fn, checkCtx, deadline);
287
+ const durationMs = Date.now() - checkStart;
288
+ oracleResults.push({
289
+ oracleType: id,
290
+ passed: true,
291
+ score: 1,
292
+ message: name,
293
+ details: { DurationMs: durationMs, runViewCacheSets: checkCtx.Storage.SetCount('RunViewCache') }
294
+ });
295
+ outcomes.push({ Name: name, Passed: true, DurationMs: durationMs });
296
+ this.logToTestRun(context, 'info', `✓ ${id}`);
297
+ }
298
+ catch (checkErr) {
299
+ const durationMs = Date.now() - checkStart;
300
+ const message = checkErr.message;
301
+ oracleResults.push({ oracleType: id, passed: false, score: 0, message, details: { DurationMs: durationMs } });
302
+ outcomes.push({ Name: name, Passed: false, DurationMs: durationMs, Error: message });
303
+ this.logToTestRun(context, 'error', `✗ ${id}: ${message}`);
304
+ }
305
+ }
306
+ /** client-cache / rls-isolation-client run on the GraphQL client transport; others on SQL server. */
307
+ bundleTransport(bundleType) {
308
+ return CLIENT_BUNDLES.has(bundleType) ? 'client' : 'server';
309
+ }
310
+ /**
311
+ * Obtain the run-scoped instrumented provider stack for the chosen transport.
312
+ * Prefers a stack already installed first-caller (CLI's installInstrumentedCacheFirst,
313
+ * or a prior bootstrap in this process); falls back to owning the process. Throws
314
+ * (caught upstream) when a client bundle is requested but the cache was already claimed
315
+ * by a SQL provider, or vice-versa.
316
+ */
317
+ async buildCheckContext(context, transport) {
318
+ if (transport === 'client') {
319
+ const client = getActiveIntegrationClientBootstrap() ?? await bootstrapIntegrationClient();
320
+ return {
321
+ User: context.contextUser,
322
+ Provider: this.Provider,
323
+ Storage: client.Storage,
324
+ Pool: undefined,
325
+ Schema: process.env.MJ_CORE_SCHEMA ?? '__mj'
326
+ };
327
+ }
328
+ let storage = getActiveIntegrationStorage();
329
+ const activeBootstrap = getActiveIntegrationBootstrap();
330
+ let pool = activeBootstrap?.Pool;
331
+ let schema = activeBootstrap?.Db.Schema;
332
+ // The REAL database provider (a DatabaseProviderBase): the bootstrap's own provider when a
333
+ // bootstrap ran in-process, else the global one installed by the CLI's initializeMJProvider.
334
+ // NOT `this.Provider` — its getter returns a `new Metadata()` FACADE when the engine injected
335
+ // no provider, and the facade lacks IRemoteOperationProvider.RouteOperation (so remote-op
336
+ // checks would fail with "No remote-operation-capable provider"). Dedicated single-provider
337
+ // process (D1), so the global is unambiguous and matches what the tsx dispatcher passes.
338
+ let provider = activeBootstrap?.Provider ?? Metadata.Provider;
339
+ if (!storage) {
340
+ const ic = await bootstrapIntegrationServer();
341
+ storage = ic.Storage;
342
+ pool = ic.Pool;
343
+ schema = ic.Db.Schema;
344
+ provider = ic.Provider;
345
+ }
346
+ // #3251: a server-transport bundle MUST resolve a DATABASE provider. If the process-global
347
+ // provider was rebound to a client (GraphQL/Network) provider — because a client-transport
348
+ // bundle ran earlier in this same process (setupGraphQLClient calls SetProvider) — then a
349
+ // server bundle would silently execute over the wire and its checks would fail in
350
+ // product-shaped ways. Fail loudly instead of degrading silently. The throw is caught by
351
+ // Execute's bootstrap try/catch → an 'Error' result, never a wedged 'Running' run. Guarded on
352
+ // ProviderType being present so a facade/unset global provider (e.g. in unit tests) is a no-op.
353
+ if (provider?.ProviderType && provider.ProviderType !== ProviderType.Database) {
354
+ throw new Error(`transport 'server' resolved a '${provider.ProviderType}' provider — the process-global ` +
355
+ `provider was rebound (a client-transport bundle ran earlier in this process). ` +
356
+ `Server-transport bundles must be sequenced BEFORE all client-transport bundles in a ` +
357
+ `suite, or run in their own process. (issue #3251)`);
358
+ }
359
+ return {
360
+ User: context.contextUser,
361
+ Provider: provider,
362
+ Storage: storage,
363
+ Pool: pool,
364
+ Schema: schema ?? (process.env.MJ_CORE_SCHEMA ?? '__mj')
365
+ };
366
+ }
367
+ /** Map the OracleResult[] to the framework result (one OracleResult per check). */
368
+ buildResult(context, startTime, oracleResults, timedOut) {
369
+ const passedChecks = oracleResults.filter(r => r.passed).length;
370
+ const totalChecks = oracleResults.length;
371
+ const failedChecks = totalChecks - passedChecks;
372
+ const status = timedOut ? 'Timeout' : (failedChecks === 0 ? 'Passed' : 'Failed');
373
+ const result = {
374
+ targetType: TARGET_TYPE,
375
+ // No external MJ log entity to link; point TargetLogID at the TestRun itself.
376
+ targetLogId: context.testRun.ID,
377
+ status,
378
+ score: totalChecks === 0 ? 0 : passedChecks / totalChecks,
379
+ oracleResults,
380
+ passedChecks,
381
+ failedChecks,
382
+ totalChecks,
383
+ durationMs: Date.now() - startTime
384
+ };
385
+ if (timedOut) {
386
+ result.errorMessage = `Integration run timed out after ${this.getEffectiveTimeout(context.test)}ms`;
387
+ }
388
+ return result;
389
+ }
390
+ /** Gated/skipped run: one passing 'gate' OracleResult, never 'Running', never thrown. */
391
+ buildSkipResult(context, startTime, note) {
392
+ return {
393
+ targetType: TARGET_TYPE,
394
+ targetLogId: context.testRun.ID,
395
+ status: 'Passed',
396
+ score: 1,
397
+ oracleResults: [{ oracleType: 'gate', passed: true, score: 1, message: note, details: { DurationMs: 0 } }],
398
+ passedChecks: 1,
399
+ failedChecks: 0,
400
+ totalChecks: 1,
401
+ durationMs: Date.now() - startTime
402
+ };
403
+ }
404
+ /** Bootstrap/config error: one failing 'error' OracleResult, status 'Error', never thrown. */
405
+ buildErrorResult(context, startTime, message) {
406
+ this.logToTestRun(context, 'error', message);
407
+ return {
408
+ targetType: TARGET_TYPE,
409
+ targetLogId: context.testRun.ID,
410
+ status: 'Error',
411
+ score: 0,
412
+ oracleResults: [{ oracleType: 'error', passed: false, score: 0, message, details: { DurationMs: 0 } }],
413
+ passedChecks: 0,
414
+ failedChecks: 1,
415
+ totalChecks: 1,
416
+ durationMs: Date.now() - startTime,
417
+ errorMessage: message
418
+ };
419
+ }
420
+ };
421
+ IntegrationTestDriver = __decorate([
422
+ RegisterClass(BaseTestDriver, 'IntegrationTestDriver')
423
+ ], IntegrationTestDriver);
424
+ export { IntegrationTestDriver };
425
+ //# sourceMappingURL=IntegrationTestDriver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"IntegrationTestDriver.js","sourceRoot":"","sources":["../src/IntegrationTestDriver.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ import type { UserInfo } from '@memberjunction/core';
2
+ type Row = Record<string, unknown>;
3
+ /**
4
+ * Verifies an `MJ: AI Prompt Runs` row finalized correctly: terminal Status, **CompletedAt set** (the
5
+ * "stuck at Running" guard the save queue prevents), and on success a non-empty Result + recorded timing.
6
+ */
7
+ export declare function verifyPromptRun(promptRunID: string, user: UserInfo): Promise<Row>;
8
+ /** Verifies an `MJ: Action Execution Logs` row finalized: **EndedAt set** + a ResultCode recorded. */
9
+ export declare function verifyActionLog(logID: string, user: UserInfo): Promise<Row>;
10
+ export interface AgentRunVerification {
11
+ run: Row;
12
+ stepCount: number;
13
+ promptRunsVerified: number;
14
+ actionLogsVerified: number;
15
+ subAgentRunsVerified: number;
16
+ }
17
+ /**
18
+ * Deep-verifies an agent run end to end: the `MJ: AI Agent Runs` header, every `MJ: AI Agent Run Steps`
19
+ * row (each terminal + CompletedAt set — never stuck at Running), and the records each step points at via
20
+ * TargetLogID — Prompt steps → AI Prompt Runs, Actions/Tool steps → Action Execution Logs, Sub-Agent steps
21
+ * → child AI Agent Runs (recursively). `expectSuccess` asserts the run reached 'Completed'.
22
+ */
23
+ export declare function verifyAgentRun(agentRunID: string, user: UserInfo, expectSuccess?: boolean, opts?: {
24
+ skipActionLogs?: boolean;
25
+ }): Promise<AgentRunVerification>;
26
+ export {};
27
+ //# sourceMappingURL=ai-verify.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ai-verify.d.ts","sourceRoot":"","sources":["../src/ai-verify.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAGrD,KAAK,GAAG,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AA8CnC;;;GAGG;AACH,wBAAsB,eAAe,CAAC,WAAW,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,CASvF;AAED,sGAAsG;AACtG,wBAAsB,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,CAKjF;AAED,MAAM,WAAW,oBAAoB;IACjC,GAAG,EAAE,GAAG,CAAC;IACT,SAAS,EAAE,MAAM,CAAC;IAClB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,kBAAkB,EAAE,MAAM,CAAC;IAC3B,oBAAoB,EAAE,MAAM,CAAC;CAChC;AAED;;;;;GAKG;AACH,wBAAsB,cAAc,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,aAAa,UAAO,EAAE,IAAI,GAAE;IAAE,cAAc,CAAC,EAAE,OAAO,CAAA;CAAO,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAqDrK"}