Skip to content

Commit 0579c16

Browse files
committed
♻️ Tighten visual context dogfood paths
Simplify the Swift SDK E2E handoff cleanup and make agent context evidence classification resilient to status-only failed comparisons.
1 parent e743ef7 commit 0579c16

3 files changed

Lines changed: 96 additions & 36 deletions

File tree

clients/swift/scripts/run-e2e.js

Lines changed: 35 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,36 @@ let swiftTestCommand = [
2727
'VizzlyE2ETests',
2828
].join(' ');
2929

30+
function cleanupAndExit(code = 1) {
31+
rmSync(tempDir, { recursive: true, force: true });
32+
process.exit(code);
33+
}
34+
35+
function printLocalContext() {
36+
let contextResult = spawnSync(
37+
process.execPath,
38+
[cliPath, 'context', 'build', 'current', '--source', 'local', '--agent'],
39+
{
40+
cwd: tempDir,
41+
encoding: 'utf8',
42+
env: {
43+
...process.env,
44+
VIZZLY_HOME: vizzlyHome,
45+
},
46+
}
47+
);
48+
49+
if (contextResult.stdout) {
50+
process.stdout.write(contextResult.stdout);
51+
}
52+
53+
if (contextResult.stderr) {
54+
process.stderr.write(contextResult.stderr);
55+
}
56+
57+
return contextResult.status ?? 1;
58+
}
59+
3060
let child = spawn(
3161
process.execPath,
3262
[cliPath, 'tdd', 'run', swiftTestCommand, '--no-color'],
@@ -42,40 +72,15 @@ let child = spawn(
4272
);
4373

4474
child.on('exit', code => {
45-
if (code === 0) {
46-
let contextResult = spawnSync(
47-
process.execPath,
48-
[cliPath, 'context', 'build', 'current', '--source', 'local', '--agent'],
49-
{
50-
cwd: tempDir,
51-
encoding: 'utf8',
52-
env: {
53-
...process.env,
54-
VIZZLY_HOME: vizzlyHome,
55-
},
56-
}
57-
);
58-
59-
if (contextResult.stdout) {
60-
process.stdout.write(contextResult.stdout);
61-
}
62-
63-
if (contextResult.stderr) {
64-
process.stderr.write(contextResult.stderr);
65-
}
66-
67-
if (contextResult.status !== 0) {
68-
rmSync(tempDir, { recursive: true, force: true });
69-
process.exit(contextResult.status ?? 1);
70-
}
75+
if (code !== 0) {
76+
cleanupAndExit(code ?? 1);
7177
}
7278

73-
rmSync(tempDir, { recursive: true, force: true });
74-
process.exit(code ?? 1);
79+
let contextStatus = printLocalContext();
80+
cleanupAndExit(contextStatus);
7581
});
7682

7783
child.on('error', error => {
78-
rmSync(tempDir, { recursive: true, force: true });
7984
console.error(error);
80-
process.exit(1);
85+
cleanupAndExit(1);
8186
});

src/commands/context.js

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,16 @@ function getComparisonDisplayState(comparison = {}) {
247247
return comparison.result || comparison.status || 'unknown';
248248
}
249249

250+
function isChangedComparison(comparison = {}) {
251+
return ['changed', 'failed', 'pending'].includes(
252+
getComparisonDisplayState(comparison)
253+
);
254+
}
255+
256+
function isNewComparison(comparison = {}) {
257+
return getComparisonDisplayState(comparison) === 'new';
258+
}
259+
250260
function getComparisonName(comparison = {}) {
251261
return (
252262
comparison.screenshot_name ||
@@ -421,12 +431,8 @@ function displayBuildContext(output, context) {
421431

422432
function formatAgentBuildContext(context) {
423433
let comparisons = context.comparisons || [];
424-
let changed = comparisons.filter(
425-
comparison => getComparisonDisplayState(comparison) === 'changed'
426-
);
427-
let fresh = comparisons.filter(
428-
comparison => getComparisonDisplayState(comparison) === 'new'
429-
);
434+
let changed = comparisons.filter(isChangedComparison);
435+
let fresh = comparisons.filter(isNewComparison);
430436
let needsReview = comparisons.filter(comparison => comparison.needs_review);
431437
let baseline = context.baseline?.selected;
432438
let lines = [

tests/commands/context.test.js

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -455,6 +455,55 @@ describe('commands/context', () => {
455455
assert.ok(agentOutput.includes('Dashboard: identical'));
456456
assert.ok(agentOutput.includes('Settings: identical'));
457457
});
458+
459+
it('includes status-only failed comparisons in agent evidence', async () => {
460+
let output = createMockOutput();
461+
462+
await contextBuildCommand(
463+
'build-1',
464+
{ agent: true },
465+
{},
466+
{
467+
loadConfig: async () => ({
468+
apiKey: 'token',
469+
apiUrl: 'https://api.test',
470+
}),
471+
createApiClient: () => ({}),
472+
getBuildContext: async () => ({
473+
resource: 'build_context',
474+
scope: {
475+
organization: { slug: 'acme' },
476+
project: { slug: 'web' },
477+
},
478+
build: {
479+
id: 'build-1',
480+
name: 'build-1',
481+
status: 'completed',
482+
},
483+
status: { needs_review: true, pending_comparisons: 1 },
484+
comparisons: [
485+
{
486+
screenshot_name: 'Checkout',
487+
status: 'failed',
488+
needs_review: true,
489+
diff_percentage: 0.8,
490+
},
491+
],
492+
}),
493+
output,
494+
exit: () => {},
495+
}
496+
);
497+
498+
let agentOutput = output.calls
499+
.filter(call => call.method === 'print')
500+
.map(call => call.args[0])
501+
.join('\n');
502+
503+
assert.ok(agentOutput.includes('## Evidence To Inspect'));
504+
assert.ok(agentOutput.includes('Checkout: failed'));
505+
assert.ok(agentOutput.includes('0.8% diff'));
506+
});
458507
});
459508

460509
describe('contextComparisonCommand', () => {

0 commit comments

Comments
 (0)