@vmz/test 0.1.18 → 0.1.19

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/browser.d.ts CHANGED
@@ -23,6 +23,8 @@ export type BrowserResult = {
23
23
  };
24
24
  export declare function runBrowserManifest(manifest: Record<string, unknown>, ctx: {
25
25
  outDir: string;
26
+ /** Optional `profiles.*.name` hint when resolving nested delivery roots. */
27
+ deliveryName?: string | null;
26
28
  }): Promise<BrowserResult>;
27
29
  /** Resolve chrome path (for gates / diagnostics). */
28
30
  export declare function resolveBrowserExecutable(): string | null;
package/dist/browser.js CHANGED
@@ -20,6 +20,7 @@ import { resolveComponentEntries } from '@vmz/core/component-registry';
20
20
  import { resolveChunkArtifacts } from './compile.js';
21
21
  import { createArtifactsDir, writeFailureEvidence, writeTimingOnly } from './browser-evidence.js';
22
22
  import { isServeHostManifest, resolveRoutePath, startServeHost } from './browser-serve.js';
23
+ import { resolveDeliveryServeRoot } from './delivery-serve-root.js';
23
24
  import { defaultClickLocator, parseActionLocator, resolveLocatorInPage, sleep, } from './browser-protocol.js';
24
25
  const MIME = {
25
26
  '.html': 'text/html; charset=utf-8',
@@ -174,6 +175,8 @@ export async function runBrowserManifest(manifest, ctx) {
174
175
  const fail = (message, extra = {}) => {
175
176
  diagnostics.push({ severity: 'error', message, ...extra });
176
177
  };
178
+ // `--out-dir` root may nest under `profiles.*.name` (e.g. dist/cdn). Serve that root.
179
+ const outDir = resolveDeliveryServeRoot(ctx.outDir, ctx.deliveryName);
177
180
  const program = manifest.program && typeof manifest.program === 'object' ? manifest.program : {};
178
181
  const chunkId = String(program.chunkId || '');
179
182
  const programId = chunkId || null;
@@ -187,14 +190,14 @@ export async function runBrowserManifest(manifest, ctx) {
187
190
  return { status: 'error', diagnostics, planId: null, programId: null };
188
191
  }
189
192
  if (!useServe) {
190
- const arts = resolveChunkArtifacts(ctx.outDir, chunkId);
193
+ const arts = resolveChunkArtifacts(outDir, chunkId);
191
194
  if (!arts.clientPath) {
192
195
  fail(`missing ${chunkId}.client.js`);
193
196
  return { status: 'failed', diagnostics, planId: null, programId };
194
197
  }
195
198
  }
196
- else if (!fs.existsSync(path.join(ctx.outDir, 'vmz-serve-host.mjs'))) {
197
- fail(`serve host: missing vmz-serve-host.mjs under ${ctx.outDir}`);
199
+ else if (!fs.existsSync(path.join(outDir, 'vmz-serve-host.mjs'))) {
200
+ fail(`serve host: missing vmz-serve-host.mjs under ${outDir}`);
198
201
  return { status: 'failed', diagnostics, planId: null, programId };
199
202
  }
200
203
  const chrome = findChromeExecutable();
@@ -212,7 +215,7 @@ export async function runBrowserManifest(manifest, ctx) {
212
215
  const runStarted = Date.now();
213
216
  const consoleErrors = [];
214
217
  const failedRequests = [];
215
- const artifactsDir = createArtifactsDir(ctx.outDir, testId);
218
+ const artifactsDir = createArtifactsDir(outDir, testId);
216
219
  const recordStep = (phase, kind, started, ok, detail) => {
217
220
  stepTimings.push({ phase, kind, ms: Date.now() - started, ok, detail });
218
221
  };
@@ -220,11 +223,11 @@ export async function runBrowserManifest(manifest, ctx) {
220
223
  const puppeteer = await loadPuppeteerCore();
221
224
  let origin;
222
225
  if (useServe) {
223
- serveHost = await startServeHost(ctx.outDir);
226
+ serveHost = await startServeHost(outDir);
224
227
  origin = serveHost.origin;
225
228
  }
226
229
  else {
227
- server = await startStaticServer(ctx.outDir);
230
+ server = await startStaticServer(outDir);
228
231
  origin = `http://127.0.0.1:${server.port}`;
229
232
  }
230
233
  // CI: spawn+connect first (puppeteer.launch often "Connection closed" on Chrome for Testing).
@@ -335,7 +338,7 @@ export async function runBrowserManifest(manifest, ctx) {
335
338
  await page.goto(`${origin}/__vmz/harness`, { waitUntil: 'domcontentloaded' });
336
339
  const explicitComponents = program.components && typeof program.components === 'object' ? program.components : undefined;
337
340
  const registryStrict = process.env.CI === 'true' || process.env.GITHUB_ACTIONS === 'true';
338
- const registryEntries = await resolveComponentEntries(ctx.outDir, explicitComponents, {
341
+ const registryEntries = await resolveComponentEntries(outDir, explicitComponents, {
339
342
  strict: registryStrict,
340
343
  closureRoots: [chunkId.replace(/\\/g, '/')],
341
344
  });
@@ -388,7 +391,7 @@ export async function runBrowserManifest(manifest, ctx) {
388
391
  let stepOk = true;
389
392
  try {
390
393
  if (kind === 'open' || kind === 'navigate') {
391
- const pathname = resolveRoutePath(ctx.outDir, {
394
+ const pathname = resolveRoutePath(outDir, {
392
395
  routeId: a.routeId != null ? String(a.routeId) : undefined,
393
396
  path: a.path != null ? String(a.path) : undefined,
394
397
  params: a.params && typeof a.params === 'object'
@@ -583,7 +586,7 @@ export async function runBrowserManifest(manifest, ctx) {
583
586
  }, wantRouteId);
584
587
  if (!hit && loc.path) {
585
588
  try {
586
- const resolved = resolveRoutePath(ctx.outDir, { routeId: wantRouteId });
589
+ const resolved = resolveRoutePath(outDir, { routeId: wantRouteId });
587
590
  if (loc.path !== resolved && !loc.path.endsWith(resolved))
588
591
  ok = false;
589
592
  else
package/dist/compile.d.ts CHANGED
@@ -17,6 +17,8 @@ export type CreateWorkspaceFn = (opts: {
17
17
  export type BuildOptions = {
18
18
  createWorkspace?: CreateWorkspaceFn;
19
19
  repoRoot?: string;
20
+ /** Hint for nested `profiles.*.name` when resolving the serve/artifact root. */
21
+ deliveryName?: string | null;
20
22
  };
21
23
  export type BuildResult = {
22
24
  ok: true;
package/dist/compile.js CHANGED
@@ -7,8 +7,12 @@ import os from 'node:os';
7
7
  import path from 'node:path';
8
8
  import { spawnSync } from 'node:child_process';
9
9
  import { fileURLToPath } from 'node:url';
10
+ import { resolveDeliveryServeRoot } from './delivery-serve-root.js';
10
11
  const packageRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
11
12
  const repoRootGuess = path.resolve(packageRoot, '../../..');
13
+ function finishBuildOutDir(dist, deliveryName) {
14
+ return resolveDeliveryServeRoot(dist, deliveryName);
15
+ }
12
16
  /** Build project for compile/logic evidence. Prefers N-API `createWorkspace`, else Node `@vmz/vmz`. */
13
17
  export function buildForCompile(project, outDir, options = {}) {
14
18
  const dist = outDir || fs.mkdtempSync(path.join(os.tmpdir(), 'vmz-test-compile-'));
@@ -31,7 +35,7 @@ export function buildForCompile(project, outDir, options = {}) {
31
35
  error: 'workspace build reported errors',
32
36
  };
33
37
  }
34
- return { ok: true, outDir: dist, diagnostics: diags };
38
+ return { ok: true, outDir: finishBuildOutDir(dist, options.deliveryName), diagnostics: diags };
35
39
  }
36
40
  finally {
37
41
  ws.dispose();
@@ -52,7 +56,7 @@ export function buildForCompile(project, outDir, options = {}) {
52
56
  encoding: 'utf8',
53
57
  });
54
58
  if (run.status === 0) {
55
- return { ok: true, outDir: dist, diagnostics: [] };
59
+ return { ok: true, outDir: finishBuildOutDir(dist, options.deliveryName), diagnostics: [] };
56
60
  }
57
61
  return {
58
62
  ok: false,
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Resolve the delivery artifact root for Browser Host / serve-host.
3
+ *
4
+ * `vmz build --out-dir <D>` with `profiles.*.name: 'cdn'` writes under `<D>/cdn`
5
+ * (see delivery `name` contract). `@vmz/test` must serve that nested root — not
6
+ * assume HTML / `vmz-serve-host.mjs` live at `<D>/`.
7
+ */
8
+ /** True when `dir` looks like a built delivery tree (serve-host or static index). */
9
+ export declare function isDeliveryServeRoot(dir: string): boolean;
10
+ /**
11
+ * Map CLI `--out-dir` root → profile delivery root (`outDir/<name>`).
12
+ *
13
+ * Prefer `preferredName` when provided (from the selected delivery profile).
14
+ * Otherwise pick the sole nested delivery child, preferring a tree that has
15
+ * `vmz-serve-host.mjs`. If the root itself is already a delivery tree, return it.
16
+ */
17
+ export declare function resolveDeliveryServeRoot(outDirRoot: string, preferredName?: string | null): string;
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Resolve the delivery artifact root for Browser Host / serve-host.
3
+ *
4
+ * `vmz build --out-dir <D>` with `profiles.*.name: 'cdn'` writes under `<D>/cdn`
5
+ * (see delivery `name` contract). `@vmz/test` must serve that nested root — not
6
+ * assume HTML / `vmz-serve-host.mjs` live at `<D>/`.
7
+ */
8
+ import fs from 'node:fs';
9
+ import path from 'node:path';
10
+ const SERVE_HOST = 'vmz-serve-host.mjs';
11
+ const DEPLOYMENT = 'vmz-deployment.json';
12
+ /** True when `dir` looks like a built delivery tree (serve-host or static index). */
13
+ export function isDeliveryServeRoot(dir) {
14
+ if (!dir || !fs.existsSync(dir))
15
+ return false;
16
+ return (fs.existsSync(path.join(dir, SERVE_HOST)) ||
17
+ fs.existsSync(path.join(dir, 'index.html')) ||
18
+ fs.existsSync(path.join(dir, DEPLOYMENT)) ||
19
+ fs.existsSync(path.join(dir, '_vmz')));
20
+ }
21
+ /**
22
+ * Map CLI `--out-dir` root → profile delivery root (`outDir/<name>`).
23
+ *
24
+ * Prefer `preferredName` when provided (from the selected delivery profile).
25
+ * Otherwise pick the sole nested delivery child, preferring a tree that has
26
+ * `vmz-serve-host.mjs`. If the root itself is already a delivery tree, return it.
27
+ */
28
+ export function resolveDeliveryServeRoot(outDirRoot, preferredName) {
29
+ const root = path.resolve(outDirRoot);
30
+ if (isDeliveryServeRoot(root))
31
+ return root;
32
+ const preferred = typeof preferredName === 'string' ? preferredName.trim() : '';
33
+ if (preferred) {
34
+ const nested = path.join(root, preferred);
35
+ if (isDeliveryServeRoot(nested))
36
+ return nested;
37
+ }
38
+ if (!fs.existsSync(root) || !fs.statSync(root).isDirectory())
39
+ return root;
40
+ const children = fs
41
+ .readdirSync(root, { withFileTypes: true })
42
+ .filter((d) => d.isDirectory() && d.name !== 'node_modules' && !d.name.startsWith('.'))
43
+ .map((d) => path.join(root, d.name))
44
+ .filter(isDeliveryServeRoot);
45
+ if (children.length === 0)
46
+ return root;
47
+ if (children.length === 1)
48
+ return children[0];
49
+ const withHost = children.filter((d) => fs.existsSync(path.join(d, SERVE_HOST)));
50
+ const pool = withHost.length > 0 ? withHost : children;
51
+ const cdn = pool.find((d) => path.basename(d) === 'cdn');
52
+ if (cdn)
53
+ return cdn;
54
+ const staticName = pool.find((d) => path.basename(d) === 'static');
55
+ if (staticName)
56
+ return staticName;
57
+ return pool[0];
58
+ }
package/dist/index.d.ts CHANGED
@@ -10,6 +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 { isDeliveryServeRoot, resolveDeliveryServeRoot, } from './delivery-serve-root.js';
13
14
  export { BROWSER_LOCATOR_KINDS, defaultClickLocator, parseActionLocator, type BrowserActionOptions, type BrowserLocator, type LocatorResolveResult, } from './browser-protocol.js';
14
15
  export { isServeHostManifest, resolveRoutePath, startServeHost, type ServeHostHandle } from './browser-serve.js';
15
16
  export { createArtifactsDir, writeFailureEvidence, writeTimingOnly, type BrowserTiming, type EvidencePaths, type StepTiming, } from './browser-evidence.js';
package/dist/index.js CHANGED
@@ -10,6 +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 { isDeliveryServeRoot, resolveDeliveryServeRoot, } from './delivery-serve-root.js';
13
14
  export { BROWSER_LOCATOR_KINDS, defaultClickLocator, parseActionLocator, } from './browser-protocol.js';
14
15
  export { isServeHostManifest, resolveRoutePath, startServeHost } from './browser-serve.js';
15
16
  export { createArtifactsDir, writeFailureEvidence, writeTimingOnly, } from './browser-evidence.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vmz/test",
3
- "version": "0.1.18",
3
+ "version": "0.1.19",
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.1.18",
31
- "@vmz/protocol": "0.1.18",
30
+ "@vmz/core": "0.1.19",
31
+ "@vmz/protocol": "0.1.19",
32
32
  "linkedom": "^0.18.13",
33
33
  "puppeteer-core": "^24.11.2"
34
34
  },