@vmz/test 0.0.3 → 0.1.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.
package/dist/compile.js CHANGED
@@ -248,8 +248,13 @@ export function runCompileManifest(manifest, ctx) {
248
248
  if (expect.create === true && !clientJs.includes('__vmzCreate')) {
249
249
  fail('missing __vmzCreate');
250
250
  }
251
- if (expect.plan === true && !clientJs.includes('__vmzPlan')) {
252
- fail('missing __vmzPlan');
251
+ if (expect.plan === true) {
252
+ // Plan identity is *.program.json; client `__vmzPlan` embed is opt-in (VMZ_EMIT_PLAN).
253
+ const hasClientPlan = clientJs.includes('__vmzPlan');
254
+ const hasProgramPlan = typeof prog.schema === 'string' || Boolean(arts.programPath) || Boolean(plan);
255
+ if (!hasClientPlan && !hasProgramPlan) {
256
+ fail('missing plan (client __vmzPlan or *.program.json)');
257
+ }
253
258
  }
254
259
  if (expect.serialize === true && !clientJs.includes('__vmzSerialize')) {
255
260
  fail('missing __vmzSerialize');
@@ -384,20 +389,91 @@ export function runCompileManifest(manifest, ctx) {
384
389
  }
385
390
  }
386
391
  if (expect.hasDisposeRegion === true) {
387
- const nodes = (plan?.nodes || []).filter((n) => n.kind === 'dispose_region');
392
+ const nodes = (plan?.nodes || []).filter((n) => n.kind === 'dispose-region');
388
393
  if (!nodes.length)
389
- fail('plan missing dispose_region nodes');
394
+ fail('plan missing dispose-region nodes');
390
395
  for (const d of nodes) {
391
396
  if (d.region == null)
392
- fail(`dispose_region missing region: ${JSON.stringify(d)}`);
397
+ fail(`dispose-region missing region: ${JSON.stringify(d)}`);
393
398
  }
394
399
  }
395
400
  if (expect.disposeTag != null) {
396
- const nodes = (plan?.nodes || []).filter((n) => n.kind === 'dispose_region');
397
- if (!nodes.some((n) => n.tag === expect.disposeTag)) {
398
- fail(`dispose_region missing tag=${expect.disposeTag}: ${JSON.stringify(nodes)}`);
401
+ const nodes = (plan?.nodes || []).filter((n) => n.kind === 'dispose-region');
402
+ // Wire field is `source` (`if` | `each`); accept legacy `tag` if present.
403
+ if (!nodes.some((n) => n.source === expect.disposeTag || n.tag === expect.disposeTag)) {
404
+ fail(`dispose-region missing source=${expect.disposeTag}: ${JSON.stringify(nodes)}`);
405
+ }
406
+ }
407
+ continue;
408
+ }
409
+ if (kind === 'motion') {
410
+ const motion = unit.motion || null;
411
+ const transitions = motion?.transitions || [];
412
+ const edges = unit.graph?.edges || [];
413
+ if (expect.status != null) {
414
+ if (!motion || motion.status !== expect.status) {
415
+ fail(`motion.status want ${expect.status}, got ${motion?.status}`);
416
+ }
417
+ }
418
+ if (expect.nonEmpty === true && transitions.length === 0) {
419
+ fail('motion.transitions empty');
420
+ }
421
+ if (Array.isArray(expect.kinds)) {
422
+ const have = new Set(transitions.map((t) => String(t.kind || '')));
423
+ for (const k of expect.kinds) {
424
+ if (!have.has(String(k)))
425
+ fail(`motion missing kind=${k}: ${[...have]}`);
399
426
  }
400
427
  }
428
+ if (typeof expect.token === 'string') {
429
+ if (!transitions.some((t) => t.token === expect.token)) {
430
+ fail(`motion missing token=${expect.token}: ${JSON.stringify(transitions)}`);
431
+ }
432
+ }
433
+ if (Array.isArray(expect.tokens)) {
434
+ for (const tok of expect.tokens) {
435
+ if (!transitions.some((t) => t.token === tok)) {
436
+ fail(`motion missing token=${tok}: ${JSON.stringify(transitions)}`);
437
+ }
438
+ }
439
+ }
440
+ if (expect.cancelable === true) {
441
+ if (!transitions.some((t) => t.cancelable === true)) {
442
+ fail(`motion missing cancelable transition: ${JSON.stringify(transitions)}`);
443
+ }
444
+ }
445
+ if (expect.generation === true) {
446
+ if (!transitions.some((t) => t.generation === true)) {
447
+ fail(`motion missing generation transition: ${JSON.stringify(transitions)}`);
448
+ }
449
+ }
450
+ if (typeof expect.reducedMotion === 'string') {
451
+ if (!transitions.every((t) => t.reduced_motion === expect.reducedMotion)) {
452
+ fail(`motion.reduced_motion want ${expect.reducedMotion}: ${JSON.stringify(transitions)}`);
453
+ }
454
+ }
455
+ if (expect.hasRegion === true) {
456
+ if (!transitions.some((t) => t.region != null)) {
457
+ fail(`motion missing region on transitions: ${JSON.stringify(transitions)}`);
458
+ }
459
+ }
460
+ if (expect.affectsRegion === true) {
461
+ const hit = edges.some((e) => e.kind === 'affects' && String(e.from).startsWith('motion:') && String(e.to).startsWith('region:'));
462
+ if (!hit)
463
+ fail(`missing motion→region affects edges: ${JSON.stringify(edges.filter((e) => String(e.from).startsWith('motion:')))}`);
464
+ }
465
+ if (Array.isArray(expect.cancelsFrom)) {
466
+ for (const from of expect.cancelsFrom) {
467
+ const hit = edges.some((e) => e.kind === 'cancels' && e.from === from && String(e.to).startsWith('motion:'));
468
+ if (!hit)
469
+ fail(`missing cancels from ${from}: ${JSON.stringify(edges.filter((e) => e.kind === 'cancels'))}`);
470
+ }
471
+ }
472
+ if (expect.planMotionTransition === true) {
473
+ const nodes = (plan?.nodes || []).filter((n) => n.kind === 'motion_transition');
474
+ if (!nodes.length)
475
+ fail('plan missing motion_transition nodes');
476
+ }
401
477
  continue;
402
478
  }
403
479
  if (kind === 'deployment') {
@@ -157,7 +157,7 @@ export function runDeploymentManifest(manifest, ctx) {
157
157
  }
158
158
  continue;
159
159
  }
160
- if (kind === 'graph' || kind === 'plan' || kind === 'diagnostic') {
160
+ if (kind === 'graph' || kind === 'plan' || kind === 'diagnostic' || kind === 'motion') {
161
161
  continue;
162
162
  }
163
163
  fail(`unknown deployment assertion ${JSON.stringify(kind)}`);
package/dist/index.d.ts CHANGED
@@ -10,4 +10,7 @@ export { runSsrManifest, type SsrResult } from './ssr.js';
10
10
  export { runResumeManifest, type ResumeResult } from './resume.js';
11
11
  export { runDeploymentManifest, type DeploymentResult } from './deployment.js';
12
12
  export { runBrowserManifest, resolveBrowserExecutable, type BrowserResult, } from './browser.js';
13
+ export { BROWSER_LOCATOR_KINDS, defaultClickLocator, parseActionLocator, type BrowserActionOptions, type BrowserLocator, type LocatorResolveResult, } from './browser-protocol.js';
14
+ export { isServeHostManifest, resolveRoutePath, startServeHost, type ServeHostHandle } from './browser-serve.js';
15
+ export { createArtifactsDir, writeFailureEvidence, writeTimingOnly, type BrowserTiming, type EvidencePaths, type StepTiming, } from './browser-evidence.js';
13
16
  export { runManifest, resultsToReport, type ManifestRunResult, type RunManifestOptions, } from './run.js';
package/dist/index.js CHANGED
@@ -10,4 +10,7 @@ export { runSsrManifest } from './ssr.js';
10
10
  export { runResumeManifest } from './resume.js';
11
11
  export { runDeploymentManifest } from './deployment.js';
12
12
  export { runBrowserManifest, resolveBrowserExecutable, } from './browser.js';
13
+ export { BROWSER_LOCATOR_KINDS, defaultClickLocator, parseActionLocator, } from './browser-protocol.js';
14
+ export { isServeHostManifest, resolveRoutePath, startServeHost } from './browser-serve.js';
15
+ export { createArtifactsDir, writeFailureEvidence, writeTimingOnly, } from './browser-evidence.js';
13
16
  export { runManifest, resultsToReport, } from './run.js';
package/dist/logic.js CHANGED
@@ -206,8 +206,19 @@ function runOneAssertion(a, host, fail) {
206
206
  return;
207
207
  }
208
208
  if (kind === 'domKeys') {
209
- const attr = String(expect.attr || 'data-vmz-key');
210
- const keys = [...host.app.querySelectorAll(`[${attr}]`)].map((el) => el.getAttribute(attr));
209
+ // Client Direct: `__vmzKey` expando. SSR HTML: `data-vmz-key` attr (expect.attr).
210
+ const attr = expect.attr != null ? String(expect.attr) : null;
211
+ const expando = expect.expando != null ? String(expect.expando) : attr ? null : '__vmzKey';
212
+ let keys = [];
213
+ if (attr) {
214
+ keys = [...host.app.querySelectorAll(`[${attr}]`)].map((el) => String(el.getAttribute(attr)));
215
+ }
216
+ else if (expando) {
217
+ keys = [...host.app.querySelectorAll('*')]
218
+ .map((el) => el[expando])
219
+ .filter((k) => k != null)
220
+ .map((k) => String(k));
221
+ }
211
222
  if (Array.isArray(expect.includes)) {
212
223
  for (const k of expect.includes) {
213
224
  if (!keys.includes(String(k)))
@@ -234,7 +245,7 @@ function runOneAssertion(a, host, fail) {
234
245
  }
235
246
  return;
236
247
  }
237
- if (kind === 'graph' || kind === 'plan' || kind === 'diagnostic' || kind === 'view') {
248
+ if (kind === 'graph' || kind === 'plan' || kind === 'diagnostic' || kind === 'view' || kind === 'motion') {
238
249
  return;
239
250
  }
240
251
  if (kind === 'assert') {
package/dist/resume.js CHANGED
@@ -138,7 +138,7 @@ export async function runResumeManifest(manifest, ctx) {
138
138
  }
139
139
  island = el;
140
140
  el.click();
141
- // EventEntry resume is async via Promise.resolve(fn).
141
+ // EventEntry resume is async via Promise.resolve(fn()).
142
142
  await Promise.resolve();
143
143
  await Promise.resolve();
144
144
  await new Promise((r) => setTimeout(r, Number(a.waitMs ?? 10)));
@@ -241,7 +241,7 @@ export async function runResumeManifest(manifest, ctx) {
241
241
  }
242
242
  continue;
243
243
  }
244
- if (kind === 'graph' || kind === 'plan' || kind === 'deployment' || kind === 'diagnostic') {
244
+ if (kind === 'graph' || kind === 'plan' || kind === 'deployment' || kind === 'diagnostic' || kind === 'motion') {
245
245
  continue;
246
246
  }
247
247
  fail(`unknown resume assertion ${JSON.stringify(kind)}`);
package/dist/ssr.js CHANGED
@@ -234,7 +234,7 @@ export async function runSsrManifest(manifest, ctx) {
234
234
  }
235
235
  continue;
236
236
  }
237
- if (kind === 'graph' || kind === 'plan' || kind === 'view' || kind === 'diagnostic') {
237
+ if (kind === 'graph' || kind === 'plan' || kind === 'view' || kind === 'diagnostic' || kind === 'motion') {
238
238
  continue;
239
239
  }
240
240
  fail(`unknown ssr assertion ${JSON.stringify(kind)}`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vmz/test",
3
- "version": "0.0.3",
3
+ "version": "0.1.0",
4
4
  "type": "module",
5
5
  "description": "VMZ native test protocol + Compile/Logic/Browser/SSR/Resume/Deployment hosts",
6
6
  "main": "./dist/index.js",
@@ -27,8 +27,8 @@
27
27
  "build": "tsc -p tsconfig.json"
28
28
  },
29
29
  "dependencies": {
30
- "@vmz/core": "0.0.3",
31
- "@vmz/protocol": "0.0.3",
30
+ "@vmz/core": "0.1.0",
31
+ "@vmz/protocol": "0.1.0",
32
32
  "linkedom": "^0.18.13",
33
33
  "puppeteer-core": "^24.11.2"
34
34
  },