terminalhire 0.42.33 → 0.42.34

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.
@@ -6,8 +6,8 @@
6
6
  * repository's. The repository's code has already run: its build wrote files into the
7
7
  * clone, or its serve script is listening in a container this one shares a network
8
8
  * namespace with. This process serves or reaches that app over loopback, drives a
9
- * headless Chromium through each route × viewport × colour scheme, and writes PNGs
10
- * plus `manifest.json` to /out.
9
+ * headless Chromium through each planned shot (with no spec, one per route: desktop,
10
+ * light), and writes PNGs plus `manifest.json` to /out.
11
11
  *
12
12
  * No network in either mode: static capture runs under `--network=none`, and server
13
13
  * capture joins an app container that itself has `--network=none`. Whatever the page
@@ -27,7 +27,16 @@ export const VIEWPORTS = {
27
27
  desktop: { width: 1280, height: 800, isMobile: false },
28
28
  mobile: { width: 390, height: 844, isMobile: true },
29
29
  };
30
- const SCHEMES = ['light', 'dark'];
30
+ export const SCHEMES = ['light', 'dark'];
31
+ /**
32
+ * What gets shot. With no spec, one picture per route at desktop size in light mode
33
+ * (TERM-1272). The desktop/mobile × light/dark matrix this replaces suited one claim
34
+ * and cost every other one three more renders of the same screen, most often a
35
+ * loading state; mobile and dark are for a spec to ask for, shot by shot.
36
+ */
37
+ export function plannedShots(req) {
38
+ return req.routes.map((route) => ({ route, viewport: 'desktop', scheme: 'light' }));
39
+ }
31
40
  // ---- which directory is the site -------------------------------------------
32
41
  /**
33
42
  * When the build started, read off the marker the build step wrote. Taken from the
@@ -287,53 +296,49 @@ async function shoot(origin, basePath, req, out) {
287
296
  const items = [];
288
297
  const failures = [];
289
298
  try {
290
- for (const route of req.routes) {
299
+ for (const { route, viewport, scheme } of plannedShots(req)) {
291
300
  const url = `${origin}${basePath.replace(/\/$/, '')}${route.startsWith('/') ? route : `/${route}`}`;
292
- for (const viewport of Object.keys(VIEWPORTS)) {
293
- for (const scheme of SCHEMES) {
294
- const v = VIEWPORTS[viewport];
295
- const context = await browser.newContext({
296
- viewport: { width: v.width, height: v.height },
297
- isMobile: v.isMobile,
298
- hasTouch: v.isMobile,
299
- colorScheme: scheme,
300
- deviceScaleFactor: 1,
301
- });
302
- try {
303
- const page = await context.newPage();
304
- await page.goto(url, { waitUntil: 'load', timeout: 20_000 });
305
- // A page with no backend may keep retrying forever, so idle is
306
- // waited for briefly and never required.
307
- await page.waitForLoadState('networkidle', { timeout: 5_000 }).catch(() => undefined);
308
- await page.waitForTimeout(300);
309
- // Frozen, so two shots of the same page are the same bytes: a spinner
310
- // caught on different frames would otherwise hide that light and dark
311
- // render identically, which is the one comparison the notes rely on.
312
- const png = await page.screenshot({ animations: 'disabled', caret: 'hide' });
313
- const file = shotName(route, viewport, scheme);
314
- writeFileSync(join(out, file), png);
315
- items.push({
316
- route,
317
- viewport,
318
- scheme,
319
- file,
320
- sha256: createHash('sha256').update(png).digest('hex'),
321
- bytes: png.length,
322
- ...PNG_SIZE(png),
323
- });
324
- }
325
- catch (err) {
326
- failures.push({
327
- route,
328
- viewport,
329
- scheme,
330
- error: String(err?.message ?? err).slice(0, 300),
331
- });
332
- }
333
- finally {
334
- await context.close();
335
- }
336
- }
301
+ const v = VIEWPORTS[viewport];
302
+ const context = await browser.newContext({
303
+ viewport: { width: v.width, height: v.height },
304
+ isMobile: v.isMobile,
305
+ hasTouch: v.isMobile,
306
+ colorScheme: scheme,
307
+ deviceScaleFactor: 1,
308
+ });
309
+ try {
310
+ const page = await context.newPage();
311
+ await page.goto(url, { waitUntil: 'load', timeout: 20_000 });
312
+ // A page with no backend may keep retrying forever, so idle is
313
+ // waited for briefly and never required.
314
+ await page.waitForLoadState('networkidle', { timeout: 5_000 }).catch(() => undefined);
315
+ await page.waitForTimeout(300);
316
+ // Frozen, so two shots of the same page are the same bytes: a spinner
317
+ // caught on different frames would otherwise hide that light and dark
318
+ // render identically, which is the one comparison the notes rely on.
319
+ const png = await page.screenshot({ animations: 'disabled', caret: 'hide' });
320
+ const file = shotName(route, viewport, scheme);
321
+ writeFileSync(join(out, file), png);
322
+ items.push({
323
+ route,
324
+ viewport,
325
+ scheme,
326
+ file,
327
+ sha256: createHash('sha256').update(png).digest('hex'),
328
+ bytes: png.length,
329
+ ...PNG_SIZE(png),
330
+ });
331
+ }
332
+ catch (err) {
333
+ failures.push({
334
+ route,
335
+ viewport,
336
+ scheme,
337
+ error: String(err?.message ?? err).slice(0, 300),
338
+ });
339
+ }
340
+ finally {
341
+ await context.close();
337
342
  }
338
343
  }
339
344
  }