@stag-build/phonebook 0.1.2 → 0.1.4

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 (47) hide show
  1. package/README.md +10 -1
  2. package/dist/cli.js +22 -2
  3. package/dist/cli.js.map +1 -1
  4. package/dist/commands/init.d.ts +21 -2
  5. package/dist/commands/init.js +33 -4
  6. package/dist/commands/init.js.map +1 -1
  7. package/dist/engines/android.d.ts +54 -0
  8. package/dist/engines/android.js +152 -6
  9. package/dist/engines/android.js.map +1 -1
  10. package/dist/engines/ios.d.ts +53 -4
  11. package/dist/engines/ios.js +142 -27
  12. package/dist/engines/ios.js.map +1 -1
  13. package/dist/errors.js +12 -1
  14. package/dist/errors.js.map +1 -1
  15. package/dist/ios/snapshotTestClass.d.ts +44 -0
  16. package/dist/ios/snapshotTestClass.js +115 -0
  17. package/dist/ios/snapshotTestClass.js.map +1 -1
  18. package/dist/ios/unrendered.d.ts +38 -0
  19. package/dist/ios/unrendered.js +92 -0
  20. package/dist/ios/unrendered.js.map +1 -0
  21. package/dist/manifest.d.ts +23 -2
  22. package/dist/manifest.js +58 -0
  23. package/dist/manifest.js.map +1 -1
  24. package/dist/mcp/server.d.ts +28 -0
  25. package/dist/mcp/server.js +232 -11
  26. package/dist/mcp/server.js.map +1 -1
  27. package/dist/png.d.ts +18 -0
  28. package/dist/png.js +44 -0
  29. package/dist/png.js.map +1 -0
  30. package/dist/scan/android.js +142 -16
  31. package/dist/scan/android.js.map +1 -1
  32. package/dist/scan/gaps.d.ts +52 -0
  33. package/dist/scan/gaps.js +169 -0
  34. package/dist/scan/gaps.js.map +1 -0
  35. package/dist/scan/ios.d.ts +44 -0
  36. package/dist/scan/ios.js +445 -41
  37. package/dist/scan/ios.js.map +1 -1
  38. package/dist/scan/scope.d.ts +30 -0
  39. package/dist/scan/scope.js +208 -0
  40. package/dist/scan/scope.js.map +1 -0
  41. package/dist/scan/stats.d.ts +12 -0
  42. package/dist/scan/stats.js +24 -0
  43. package/dist/scan/stats.js.map +1 -0
  44. package/dist/scan/types.d.ts +87 -1
  45. package/dist/site/build.js +0 -0
  46. package/dist/site/build.js.map +1 -1
  47. package/package.json +1 -1
@@ -2,6 +2,25 @@ import type { PhonebookConfig } from '../config.js';
2
2
  import { type Manifest, type ManifestEntry } from '../manifest.js';
3
3
  /** Builds the error/warning text for a `generate` run that exported zero snapshots. Exported for tests. */
4
4
  export declare function buildEmptySnapshotsMessage(exportDir: string, scheme: string): string;
5
+ /**
6
+ * A run that rendered some previews and did not finish, usually because a
7
+ * preview crashed. The bundle of what did render has been written.
8
+ *
9
+ * Thrown rather than returned so a caller that only knows the happy path — the
10
+ * CLI — still exits non-zero, while one that can use the partial result catches
11
+ * it. The crash list is worth more than a clean failure: every preview that traps
12
+ * costs a host-app relaunch, so it is what makes the next run shorter.
13
+ */
14
+ export declare class IncompleteRenderError extends Error {
15
+ readonly manifest: Manifest;
16
+ readonly outputDir: string;
17
+ /** Container of each preview test the runner reported failed, one per test. */
18
+ readonly failedPreviews: string[];
19
+ readonly diagnosis: string[];
20
+ constructor(manifest: Manifest, outputDir: string,
21
+ /** Container of each preview test the runner reported failed, one per test. */
22
+ failedPreviews: string[], diagnosis: string[]);
23
+ }
5
24
  /**
6
25
  * Resolves the -only-testing:Target/Class argument so `generate` runs just the
7
26
  * snapshot test class instead of the app's whole test suite — an unrelated
@@ -10,6 +29,23 @@ export declare function buildEmptySnapshotsMessage(exportDir: string, scheme: st
10
29
  * Exported for tests.
11
30
  */
12
31
  export declare function resolveOnlyTesting(config: PhonebookConfig, projectDir: string): Promise<string | undefined>;
32
+ /** Escapes a literal so it matches itself inside a regular expression. Exported for tests. */
33
+ export declare function escapeRegex(literal: string): string;
34
+ /**
35
+ * The SNAPSHOTS_ONLY_FILTER value that renders only the previews declared in
36
+ * `files`, or undefined to render everything.
37
+ *
38
+ * SnapshotPreviews filters before it creates a test method, so a pattern that
39
+ * misses is a preview that never renders — which makes a half-resolved filter
40
+ * worse than none. A file whose module cannot be read (a project that is not
41
+ * using Xcode's synchronized folders, a target xcodebuild will not describe)
42
+ * therefore drops the whole filter rather than quietly dropping that file.
43
+ *
44
+ * Each pattern is anchored against the preview's synthesized fileID,
45
+ * "<Module>/<File>.swift", because the match is a substring search: unanchored,
46
+ * "Card.swift" would also claim UserCard.swift.
47
+ */
48
+ export declare function buildSnapshotsOnlyFilter(files: string[], moduleOf: (file: string) => Promise<string | undefined>): Promise<string | undefined>;
13
49
  /**
14
50
  * Runs the SnapshotPreviews-backed XCTest target via xcodebuild on a simulator
15
51
  * and harvests the exported PNG + JSON sidecar pairs into a Phonebook bundle.
@@ -21,6 +57,10 @@ export declare function resolveOnlyTesting(config: PhonebookConfig, projectDir:
21
57
  export declare function generateIos(config: PhonebookConfig, projectDir: string, outputDir: string, options?: {
22
58
  quiet?: boolean;
23
59
  allowEmpty?: boolean;
60
+ /** Render only the previews declared in files with uncommitted changes. */
61
+ changedOnly?: boolean;
62
+ /** Render only the previews declared in these files (relative to projectDir). */
63
+ files?: string[];
24
64
  }): Promise<Manifest>;
25
65
  /** Shape of the JSON sidecar SnapshotPreviews writes next to each PNG. */
26
66
  interface SnapshotSidecar {
@@ -38,6 +78,14 @@ interface SnapshotSidecar {
38
78
  }
39
79
  /** Exported for tests. Maps one PNG + sidecar to a manifest entry (minus image path). */
40
80
  export declare function mapSidecar(png: string, sidecar: SnapshotSidecar): Omit<ManifestEntry, 'image'>;
81
+ /** How an xcodebuild run ended. */
82
+ export interface XcodebuildRun {
83
+ exitCode: number | null;
84
+ /** Container of each preview test the runner reported failed, one per test. */
85
+ failedPreviews: string[];
86
+ /** Known failure signatures found in the output; empty on success. */
87
+ diagnosis: string[];
88
+ }
41
89
  /**
42
90
  * Runs xcodebuild. When `quiet` is false (the CLI default), output streams
43
91
  * straight to this process's stdout/stderr as it arrives (so a human can
@@ -47,9 +95,10 @@ export declare function mapSidecar(png: string, sidecar: SnapshotSidecar): Omit<
47
95
  * tail is kept and nothing is echoed live; the tail is written to stderr once
48
96
  * if the build fails.
49
97
  *
50
- * On a non-zero exit, the tail is run through `diagnoseXcodebuildFailure`
51
- * any matched diagnosis lines are printed to stderr (`phonebook: `-prefixed)
52
- * and folded into the rejected Error's message, mirroring `runGradle`.
98
+ * Resolves however the run ends, and rejects only when xcodebuild cannot be
99
+ * started: a failed run can still have rendered previews, and that is for the
100
+ * caller to judge. Failed preview tests are read from the whole stream rather
101
+ * than the tail, and line by line, since a chunk can end mid-line.
53
102
  */
54
- export declare function runXcodebuild(cwd: string, args: string[], env: Record<string, string>, quiet: boolean): Promise<void>;
103
+ export declare function runXcodebuild(cwd: string, args: string[], env: Record<string, string>, quiet: boolean): Promise<XcodebuildRun>;
55
104
  export {};
@@ -2,18 +2,47 @@ import { spawn } from 'node:child_process';
2
2
  import { createHash } from 'node:crypto';
3
3
  import { copyFile, mkdir, mkdtemp, readdir, readFile, rm, writeFile } from 'node:fs/promises';
4
4
  import { tmpdir } from 'node:os';
5
- import { join, resolve } from 'node:path';
5
+ import { basename, join, resolve } from 'node:path';
6
6
  import { diagnoseXcodebuildFailure } from '../errors.js';
7
7
  import { SCHEMA_VERSION } from '../manifest.js';
8
+ import { readPngSize } from '../png.js';
8
9
  import { parsePreviewName, spaceCamelCase } from '../naming.js';
9
10
  import { gitInfo } from './git.js';
10
- import { findSnapshotTestSubclass, findSnapshottingTestsTargets, readPbxprojText } from '../ios/snapshotTestClass.js';
11
+ import { findSnapshotTestSubclass, findSnapshottingTestsTargets, moduleForFile, readPbxprojText } from '../ios/snapshotTestClass.js';
12
+ import { parseFailedPreviews } from '../ios/unrendered.js';
13
+ import { changedFiles } from '../scan/scope.js';
11
14
  /** Builds the error/warning text for a `generate` run that exported zero snapshots. Exported for tests. */
12
15
  export function buildEmptySnapshotsMessage(exportDir, scheme) {
13
16
  return (`xcodebuild succeeded but no snapshots were exported to ${exportDir}. ` +
14
17
  `Does the "${scheme}" scheme include a SnapshotPreviews test target, and are your #Preview macros not all ` +
15
18
  'filtered out (e.g. by a snapshotPreviews() override that excludes them)?');
16
19
  }
20
+ /**
21
+ * A run that rendered some previews and did not finish, usually because a
22
+ * preview crashed. The bundle of what did render has been written.
23
+ *
24
+ * Thrown rather than returned so a caller that only knows the happy path — the
25
+ * CLI — still exits non-zero, while one that can use the partial result catches
26
+ * it. The crash list is worth more than a clean failure: every preview that traps
27
+ * costs a host-app relaunch, so it is what makes the next run shorter.
28
+ */
29
+ export class IncompleteRenderError extends Error {
30
+ manifest;
31
+ outputDir;
32
+ failedPreviews;
33
+ diagnosis;
34
+ constructor(manifest, outputDir,
35
+ /** Container of each preview test the runner reported failed, one per test. */
36
+ failedPreviews, diagnosis) {
37
+ const crashed = failedPreviews.length > 0 ? `; ${failedPreviews.length} crashed (${[...new Set(failedPreviews)].join(', ')})` : '';
38
+ super([`Rendered ${manifest.entries.length} previews into ${outputDir}, but the run did not finish${crashed}.`, ...diagnosis].join('\n'));
39
+ this.manifest = manifest;
40
+ this.outputDir = outputDir;
41
+ this.failedPreviews = failedPreviews;
42
+ this.diagnosis = diagnosis;
43
+ this.name = 'IncompleteRenderError';
44
+ }
45
+ }
17
46
  /**
18
47
  * Resolves the -only-testing:Target/Class argument so `generate` runs just the
19
48
  * snapshot test class instead of the app's whole test suite — an unrelated
@@ -41,6 +70,48 @@ export async function resolveOnlyTesting(config, projectDir) {
41
70
  return undefined;
42
71
  }
43
72
  }
73
+ /** Escapes a literal so it matches itself inside a regular expression. Exported for tests. */
74
+ export function escapeRegex(literal) {
75
+ return literal.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
76
+ }
77
+ /**
78
+ * The SNAPSHOTS_ONLY_FILTER value that renders only the previews declared in
79
+ * `files`, or undefined to render everything.
80
+ *
81
+ * SnapshotPreviews filters before it creates a test method, so a pattern that
82
+ * misses is a preview that never renders — which makes a half-resolved filter
83
+ * worse than none. A file whose module cannot be read (a project that is not
84
+ * using Xcode's synchronized folders, a target xcodebuild will not describe)
85
+ * therefore drops the whole filter rather than quietly dropping that file.
86
+ *
87
+ * Each pattern is anchored against the preview's synthesized fileID,
88
+ * "<Module>/<File>.swift", because the match is a substring search: unanchored,
89
+ * "Card.swift" would also claim UserCard.swift.
90
+ */
91
+ export async function buildSnapshotsOnlyFilter(files, moduleOf) {
92
+ const swift = files.filter((file) => file.endsWith('.swift'));
93
+ if (swift.length === 0) {
94
+ console.warn('warning: no changed Swift files to narrow to; rendering every preview.');
95
+ return undefined;
96
+ }
97
+ const patterns = [];
98
+ const unresolved = [];
99
+ for (const file of swift) {
100
+ const module = await moduleOf(file);
101
+ if (!module) {
102
+ unresolved.push(file);
103
+ continue;
104
+ }
105
+ patterns.push(`^${escapeRegex(module)}/${escapeRegex(basename(file))}$`);
106
+ }
107
+ if (unresolved.length > 0) {
108
+ console.warn(`warning: could not resolve the Swift module for ${unresolved.join(', ')} — ` +
109
+ 'no filesystem-synchronized folder in the Xcode project covers it, or xcodebuild would not report its ' +
110
+ 'build settings. Rendering every preview instead.');
111
+ return undefined;
112
+ }
113
+ return patterns.join('\n');
114
+ }
44
115
  /**
45
116
  * Runs the SnapshotPreviews-backed XCTest target via xcodebuild on a simulator
46
117
  * and harvests the exported PNG + JSON sidecar pairs into a Phonebook bundle.
@@ -70,14 +141,22 @@ export async function generateIos(config, projectDir, outputDir, options = {}) {
70
141
  const onlyTesting = await resolveOnlyTesting(config, projectDir);
71
142
  if (onlyTesting)
72
143
  args.push(`-only-testing:${onlyTesting}`);
73
- await runXcodebuild(projectDir, args, {
144
+ const onlyFilter = await resolveSnapshotsOnlyFilter(config, projectDir, options);
145
+ const run = await runXcodebuild(projectDir, args, {
74
146
  TEST_RUNNER_SNAPSHOTS_EXPORT_DIR: exportDir,
75
147
  TEST_RUNNER_SNAPSHOTS_RUNNING_FOR_PREVIEWS: '1',
148
+ ...(onlyFilter ? { TEST_RUNNER_SNAPSHOTS_ONLY_FILTER: onlyFilter } : {}),
76
149
  }, options.quiet ?? false);
150
+ const finished = run.exitCode === 0;
151
+ // Read before deciding anything: a run that failed may still have rendered
152
+ // most of the gallery, and the export directory is deleted on the way out.
153
+ const pngs = (await readdir(exportDir)).filter((f) => f.endsWith('.png')).sort();
154
+ if (!finished && pngs.length === 0 && run.failedPreviews.length === 0) {
155
+ throw new Error([`xcodebuild failed (exit ${run.exitCode}) running: xcodebuild ${args.join(' ')}`, ...run.diagnosis].join('\n'));
156
+ }
77
157
  const imagesDir = join(outputDir, 'images');
78
158
  await mkdir(imagesDir, { recursive: true });
79
- const pngs = (await readdir(exportDir)).filter((f) => f.endsWith('.png')).sort();
80
- if (pngs.length === 0) {
159
+ if (finished && pngs.length === 0) {
81
160
  const message = buildEmptySnapshotsMessage(exportDir, ios.scheme);
82
161
  if (!(options.allowEmpty ?? false)) {
83
162
  throw new Error(message);
@@ -92,7 +171,8 @@ export async function generateIos(config, projectDir, outputDir, options = {}) {
92
171
  hash.update(png);
93
172
  const imageName = `${hash.digest('hex').slice(0, 16)}.png`;
94
173
  await copyFile(join(exportDir, png), join(imagesDir, imageName));
95
- entries.push({ ...meta, image: `images/${imageName}` });
174
+ const size = await readPngSize(join(imagesDir, imageName));
175
+ entries.push({ ...meta, image: `images/${imageName}`, ...(size ?? {}) });
96
176
  }
97
177
  entries.sort((a, b) => a.component.localeCompare(b.component) || a.state.localeCompare(b.state));
98
178
  const manifest = {
@@ -106,12 +186,28 @@ export async function generateIos(config, projectDir, outputDir, options = {}) {
106
186
  entries,
107
187
  };
108
188
  await writeFile(join(outputDir, 'manifest.json'), JSON.stringify(manifest, null, 2));
189
+ if (!finished) {
190
+ throw new IncompleteRenderError(manifest, outputDir, run.failedPreviews, run.diagnosis);
191
+ }
109
192
  return manifest;
110
193
  }
111
194
  finally {
112
195
  await rm(exportDir, { recursive: true, force: true });
113
196
  }
114
197
  }
198
+ /**
199
+ * Turns the `--changed`/`--files` options into a SNAPSHOTS_ONLY_FILTER value,
200
+ * reading the pbxproj once and resolving each file's module through it.
201
+ */
202
+ async function resolveSnapshotsOnlyFilter(config, projectDir, options) {
203
+ if (!options.changedOnly && !options.files)
204
+ return undefined;
205
+ const ios = config.ios;
206
+ const files = options.files ?? (await changedFiles(projectDir));
207
+ const pbxproj = await readPbxprojText(projectDir, ios.project ? join(projectDir, ios.project) : undefined);
208
+ const cache = new Map();
209
+ return buildSnapshotsOnlyFilter(files, (file) => moduleForFile(pbxproj, projectDir, file, { project: ios.project, workspace: ios.workspace, scheme: ios.scheme }, cache));
210
+ }
115
211
  async function readSidecar(path) {
116
212
  try {
117
213
  return JSON.parse(await readFile(path, 'utf8'));
@@ -120,6 +216,23 @@ async function readSidecar(path) {
120
216
  return {};
121
217
  }
122
218
  }
219
+ /**
220
+ * A stable, unique identifier for this preview within the project.
221
+ *
222
+ * Android has a fully qualified name to hand. iOS has nothing equivalent: the
223
+ * sidecar's `display_name` is a label, it usually repeats what `component` and
224
+ * `state` already say, and for an unnamed preview Xcode substitutes the
225
+ * placeholder "At line #14" — not a name, and identical for every unnamed
226
+ * preview in every other file. Qualifying whatever the sidecar gives with the
227
+ * source file makes the result unique across the project and stable between
228
+ * runs; it changes when the preview is renamed or moved, which is when its
229
+ * identity genuinely changed.
230
+ */
231
+ function previewIdentity(png, sidecar) {
232
+ const label = sidecar.display_name?.trim() || png.replace(/\.png$/, '');
233
+ const group = sidecar.group?.trim();
234
+ return group ? `${group}:${label}` : label;
235
+ }
123
236
  /** Exported for tests. Maps one PNG + sidecar to a manifest entry (minus image path). */
124
237
  export function mapSidecar(png, sidecar) {
125
238
  const container = sidecar.context?.preview?.container_display_name;
@@ -136,7 +249,7 @@ export function mapSidecar(png, sidecar) {
136
249
  state,
137
250
  module: module ?? 'app',
138
251
  sourceFile: group,
139
- previewName: rawName ?? png,
252
+ previewName: previewIdentity(png, sidecar),
140
253
  theme: scheme === 'dark' ? 'dark' : scheme === 'light' ? 'light' : undefined,
141
254
  device: sidecar.context?.simulator?.device_name,
142
255
  };
@@ -150,9 +263,10 @@ export function mapSidecar(png, sidecar) {
150
263
  * tail is kept and nothing is echoed live; the tail is written to stderr once
151
264
  * if the build fails.
152
265
  *
153
- * On a non-zero exit, the tail is run through `diagnoseXcodebuildFailure`
154
- * any matched diagnosis lines are printed to stderr (`phonebook: `-prefixed)
155
- * and folded into the rejected Error's message, mirroring `runGradle`.
266
+ * Resolves however the run ends, and rejects only when xcodebuild cannot be
267
+ * started: a failed run can still have rendered previews, and that is for the
268
+ * caller to judge. Failed preview tests are read from the whole stream rather
269
+ * than the tail, and line by line, since a chunk can end mid-line.
156
270
  */
157
271
  export function runXcodebuild(cwd, args, env, quiet) {
158
272
  return new Promise((resolvePromise, reject) => {
@@ -162,33 +276,34 @@ export function runXcodebuild(cwd, args, env, quiet) {
162
276
  env: { ...process.env, ...env },
163
277
  });
164
278
  let tail = [];
165
- const onData = (target) => (data) => {
166
- if (!quiet)
167
- target.write(data);
168
- tail.push(...data.toString('utf8').split('\n'));
279
+ const failedPreviews = [];
280
+ const partial = { stdout: '', stderr: '' };
281
+ const takeLines = (lines) => {
282
+ failedPreviews.push(...parseFailedPreviews(lines.join('\n')));
283
+ tail.push(...lines);
169
284
  if (tail.length > 200)
170
285
  tail = tail.slice(-200);
171
286
  };
172
- child.stdout?.on('data', onData(process.stdout));
173
- child.stderr?.on('data', onData(process.stderr));
287
+ const onData = (stream, target) => (data) => {
288
+ if (!quiet)
289
+ target.write(data);
290
+ const lines = (partial[stream] + data.toString('utf8')).split('\n');
291
+ partial[stream] = lines.pop() ?? '';
292
+ takeLines(lines);
293
+ };
294
+ child.stdout?.on('data', onData('stdout', process.stdout));
295
+ child.stderr?.on('data', onData('stderr', process.stderr));
174
296
  child.on('error', reject);
175
297
  child.on('close', (code) => {
176
- if (code === 0) {
177
- resolvePromise();
178
- return;
179
- }
298
+ takeLines([partial.stdout, partial.stderr].filter((l) => l.length > 0));
180
299
  const tailText = tail.join('\n');
181
- const diagnosis = diagnoseXcodebuildFailure(tailText);
300
+ const diagnosis = code === 0 ? [] : diagnoseXcodebuildFailure(tailText);
182
301
  if (diagnosis.length > 0) {
183
302
  process.stderr.write(diagnosis.map((line) => `phonebook: ${line}`).join('\n') + '\n');
184
303
  }
185
- if (quiet && tail.length > 0)
304
+ if (quiet && code !== 0 && tail.length > 0)
186
305
  process.stderr.write(tailText + '\n');
187
- const message = [
188
- `xcodebuild failed (exit ${code}) running: xcodebuild ${args.join(' ')}`,
189
- ...diagnosis,
190
- ].join('\n');
191
- reject(new Error(message));
306
+ resolvePromise({ exitCode: code, failedPreviews, diagnosis });
192
307
  });
193
308
  });
194
309
  }
@@ -1 +1 @@
1
- {"version":3,"file":"ios.js","sourceRoot":"","sources":["../../src/engines/ios.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ios.js","sourceRoot":"","sources":["../../src/engines/ios.ts"],"names":[],"mappings":"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"}
package/dist/errors.js CHANGED
@@ -50,12 +50,23 @@ export function diagnoseXcodebuildFailure(output) {
50
50
  lines.push("The SnapshotTest base class lives in the SnapshottingTests module — the snapshot test file should say " +
51
51
  '`import SnapshottingTests`. Otherwise, add the missing package product to the test target in Xcode.');
52
52
  }
53
- if (/Failed to install or launch the test runner|Mach error -308|\(ipc\/mig\) server died/.test(output)) {
53
+ // The runtime also dies with -308 after previews have been trapping for a
54
+ // while. Then the previews are the cause, and resetting the simulator
55
+ // mid-run only destroys the device the run is using.
56
+ const previewsFailed = /Test case '[^']+' failed/.test(output);
57
+ if (!previewsFailed &&
58
+ /Failed to install or launch the test runner|Mach error -308|\(ipc\/mig\) server died/.test(output)) {
54
59
  lines.push('The iOS simulator runtime died while installing the test runner — usually transient, not a setup problem.');
55
60
  lines.push('Retry once; if it persists run: xcrun simctl shutdown all (and if still failing: xcrun simctl erase ' +
56
61
  '"<device name>"). First boot of a newly installed runtime can also take minutes — let it finish in ' +
57
62
  'Simulator.app before retrying.');
58
63
  }
64
+ if (/never finished bootstrapping|before establishing connection/.test(output)) {
65
+ lines.push('The app hosting the previews was stopped before the test runner connected to it, so no preview ran: it ' +
66
+ 'hung or crashed while launching.');
67
+ lines.push('If the same app launched in an earlier run, the simulator is the difference, not the app: retry once. ' +
68
+ 'If it fails again, the app\'s own launch is what to look at, before any preview.');
69
+ }
59
70
  if (/Scheme (.+?) is not currently configured for the test action|does not contain any tests|There are no test bundles/.test(output)) {
60
71
  lines.push("The scheme's Test action has no runnable tests. Ensure the test target with your SnapshotTest subclass " +
61
72
  'is included in the scheme\'s Test action, then run `phonebook doctor`.');
@@ -1 +1 @@
1
- {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"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"}
@@ -57,3 +57,47 @@ export interface SnapshotTestClassLocation {
57
57
  * undefined if the target can't be identified or parsing fails.
58
58
  */
59
59
  export declare function findSnapshotTestClassLocation(pbxproj: string): SnapshotTestClassLocation | undefined;
60
+ /**
61
+ * A folder covered by a PBXFileSystemSynchronizedRootGroup, and the target that
62
+ * owns it. Xcode 16+ projects assign whole folders to a target this way, so a
63
+ * source file's target — and therefore its Swift module — can be read off the
64
+ * pbxproj without any per-file build-phase membership.
65
+ *
66
+ * Classic PBXGroup/PBXSourcesBuildPhase projects have no such folder mapping and
67
+ * are deliberately out of scope: they resolve to no owner at all, and callers
68
+ * fall back to rendering everything.
69
+ */
70
+ export interface SynchronizedGroupOwner {
71
+ targetName: string;
72
+ /** Folder path, relative to the project directory, "/"-joined and unquoted. */
73
+ path: string;
74
+ /** Paths (relative to the project directory) explicitly excluded from this target. */
75
+ exclusions: Set<string>;
76
+ }
77
+ /**
78
+ * Every filesystem-synchronized folder in the project, with the target it
79
+ * belongs to and the files explicitly excepted from that target.
80
+ */
81
+ export declare function synchronizedGroupOwners(pbxproj: string): SynchronizedGroupOwner[];
82
+ /**
83
+ * The target that compiles `filePath`, via the synchronized folder that covers
84
+ * it. The longest covering folder wins, so a nested folder assigned to its own
85
+ * target beats the parent that contains it; a file explicitly excepted from a
86
+ * folder's target falls through to the next-longest candidate.
87
+ */
88
+ export declare function targetForFile(pbxproj: string, filePath: string): string | undefined;
89
+ /**
90
+ * The Swift module name a source file compiles into, or undefined when the
91
+ * project structure cannot say (no synchronized folder covers it, or xcodebuild
92
+ * cannot report the target's settings).
93
+ *
94
+ * The module name is the first half of a #Preview's synthesized fileID
95
+ * ("<Module>/<File>.swift"), which is what SnapshotPreviews matches its filter
96
+ * patterns against. `cache` is keyed by target name so a run that filters a
97
+ * dozen files still shells out to xcodebuild once per target.
98
+ */
99
+ export declare function moduleForFile(pbxproj: string, projectDir: string, filePath: string, xcodebuildTarget: {
100
+ project?: string;
101
+ workspace?: string;
102
+ scheme?: string;
103
+ }, cache?: Map<string, string | undefined>): Promise<string | undefined>;
@@ -1,5 +1,8 @@
1
+ import { execFile } from 'node:child_process';
1
2
  import { readdir, readFile } from 'node:fs/promises';
2
3
  import { join, relative } from 'node:path';
4
+ import { promisify } from 'node:util';
5
+ const run = promisify(execFile);
3
6
  /**
4
7
  * Shared iOS SnapshotTest-subclass discovery: scanning project sources for an
5
8
  * existing subclass, and (heuristically) parsing a .pbxproj to find which
@@ -192,4 +195,116 @@ export function findSnapshotTestClassLocation(pbxproj) {
192
195
  return undefined;
193
196
  }
194
197
  }
198
+ function parseListItems(body, key) {
199
+ const match = body.match(new RegExp(`${key} = \\(([\\s\\S]*?)\\);`));
200
+ if (!match)
201
+ return [];
202
+ return match[1]
203
+ .split(',')
204
+ .map((item) => unquote(item.replace(/\/\*[\s\S]*?\*\//g, '').trim()))
205
+ .filter((item) => item.length > 0);
206
+ }
207
+ /**
208
+ * Every filesystem-synchronized folder in the project, with the target it
209
+ * belongs to and the files explicitly excepted from that target.
210
+ */
211
+ export function synchronizedGroupOwners(pbxproj) {
212
+ const targets = extractPbxprojObjects(pbxproj, 'PBXNativeTarget');
213
+ const syncGroups = extractPbxprojObjects(pbxproj, 'PBXFileSystemSynchronizedRootGroup');
214
+ const exceptionSets = extractPbxprojObjects(pbxproj, 'PBXFileSystemSynchronizedBuildFileExceptionSet');
215
+ const owners = [];
216
+ for (const [targetId, targetBody] of targets) {
217
+ const nameMatch = targetBody.match(/\n\t\t\tname = ([^\n;]+);/);
218
+ const targetName = nameMatch ? unquote(nameMatch[1]) : targetId;
219
+ const groupsMatch = targetBody.match(/fileSystemSynchronizedGroups = \(([\s\S]*?)\)/);
220
+ if (!groupsMatch)
221
+ continue;
222
+ for (const gid of [...groupsMatch[1].matchAll(/([0-9A-F]{24})/g)].map((m) => m[1])) {
223
+ const groupBody = syncGroups.get(gid);
224
+ if (!groupBody)
225
+ continue;
226
+ const pathMatch = groupBody.match(/\n\t\t\tpath = ([^\n;]+);/);
227
+ if (!pathMatch)
228
+ continue;
229
+ const path = unquote(pathMatch[1]).replace(/\/+$/, '');
230
+ const exclusions = new Set();
231
+ const exceptionIds = [
232
+ ...(groupBody.match(/exceptions = \(([\s\S]*?)\)/)?.[1] ?? '').matchAll(/([0-9A-F]{24})/g),
233
+ ].map((m) => m[1]);
234
+ for (const eid of exceptionIds) {
235
+ const exceptionBody = exceptionSets.get(eid);
236
+ if (!exceptionBody)
237
+ continue;
238
+ // An exception set belongs to one target; one that names another target
239
+ // says nothing about this folder's membership here.
240
+ const exceptionTarget = exceptionBody.match(/\n\t\t\ttarget = ([0-9A-F]{24})/)?.[1];
241
+ if (exceptionTarget && exceptionTarget !== targetId)
242
+ continue;
243
+ for (const member of parseListItems(exceptionBody, 'membershipExceptions')) {
244
+ exclusions.add(`${path}/${member}`);
245
+ }
246
+ }
247
+ owners.push({ targetName, path, exclusions });
248
+ }
249
+ }
250
+ return owners;
251
+ }
252
+ /**
253
+ * The target that compiles `filePath`, via the synchronized folder that covers
254
+ * it. The longest covering folder wins, so a nested folder assigned to its own
255
+ * target beats the parent that contains it; a file explicitly excepted from a
256
+ * folder's target falls through to the next-longest candidate.
257
+ */
258
+ export function targetForFile(pbxproj, filePath) {
259
+ const normalized = filePath.replace(/^\.\//, '');
260
+ const candidates = synchronizedGroupOwners(pbxproj)
261
+ .filter((owner) => normalized === owner.path || normalized.startsWith(`${owner.path}/`))
262
+ .sort((a, b) => b.path.length - a.path.length);
263
+ for (const candidate of candidates) {
264
+ if (candidate.exclusions.has(normalized))
265
+ continue;
266
+ return candidate.targetName;
267
+ }
268
+ return undefined;
269
+ }
270
+ /**
271
+ * The Swift module name a source file compiles into, or undefined when the
272
+ * project structure cannot say (no synchronized folder covers it, or xcodebuild
273
+ * cannot report the target's settings).
274
+ *
275
+ * The module name is the first half of a #Preview's synthesized fileID
276
+ * ("<Module>/<File>.swift"), which is what SnapshotPreviews matches its filter
277
+ * patterns against. `cache` is keyed by target name so a run that filters a
278
+ * dozen files still shells out to xcodebuild once per target.
279
+ */
280
+ export async function moduleForFile(pbxproj, projectDir, filePath, xcodebuildTarget, cache) {
281
+ const targetName = targetForFile(pbxproj, filePath);
282
+ if (!targetName)
283
+ return undefined;
284
+ if (cache?.has(targetName))
285
+ return cache.get(targetName);
286
+ const module = await productModuleName(projectDir, targetName, xcodebuildTarget);
287
+ cache?.set(targetName, module);
288
+ return module;
289
+ }
290
+ async function productModuleName(projectDir, targetName, xcodebuildTarget) {
291
+ const args = ['-showBuildSettings'];
292
+ if (xcodebuildTarget.workspace) {
293
+ args.push('-workspace', xcodebuildTarget.workspace);
294
+ if (xcodebuildTarget.scheme)
295
+ args.push('-scheme', xcodebuildTarget.scheme);
296
+ }
297
+ else if (xcodebuildTarget.project) {
298
+ args.push('-project', xcodebuildTarget.project);
299
+ }
300
+ args.push('-target', targetName);
301
+ try {
302
+ const { stdout } = await run('xcodebuild', args, { cwd: projectDir, maxBuffer: 32 * 1024 * 1024 });
303
+ const match = stdout.match(/^\s*PRODUCT_MODULE_NAME = (.+)$/m);
304
+ return match ? match[1].trim() : undefined;
305
+ }
306
+ catch {
307
+ return undefined;
308
+ }
309
+ }
195
310
  //# sourceMappingURL=snapshotTestClass.js.map