Files
callstack__agent-device/test/ci/upload-agent-device-artifacts.test.ts
Michał Pierzchała cd9a7ce41b test(android): add comprehensive emulator E2E coverage (#1482)
* test(android): add catalog emulator smoke coverage

* test(android): use stable snapshot diff mutation

* test(android): assert actual back destination

* test(android): separate keyboard and fill IMEs

* fix(ci): keep Android timing report in one shell

* refactor(test): simplify simulator e2e coverage

* test(android): assert stable diff landmarks

* fix(android): release snapshot helper gracefully

* fix(android): fully release snapshot helper runtime

* test(android): report coverage classifications

* fix(android): stabilize accessibility root capture

* fix(android): bound UiAutomation connection

* ci: upload worktree daemon diagnostics

* fix(android): cancel stalled wait captures

* fix(android): bound helper fallback lifecycle

* fix(android): harden emulator e2e lifecycle

* fix: align e2e changes with kernel package

* test(android): prove alert helper reuse directly

* fix(android): cancel stalled settle captures

* fix(android): separate helper retirement budgets
2026-07-30 15:10:21 +02:00

76 lines
2.7 KiB
TypeScript

import fs from 'node:fs';
import path from 'node:path';
import { expect, test } from 'vitest';
import { parse } from 'yaml';
const repoRoot = path.resolve(import.meta.dirname, '../..');
const actionPath = path.join(repoRoot, '.github/actions/upload-agent-device-artifacts/action.yml');
const conformanceWorkflowPath = path.join(
repoRoot,
'.github/workflows/conformance-differential.yml',
);
type UploadStep = { uses?: unknown; with?: Record<string, unknown> };
function uploadArtifactSteps(source: unknown): UploadStep[] {
if (Array.isArray(source)) return source.flatMap(uploadArtifactSteps);
if (source === null || typeof source !== 'object') return [];
const record = source as Record<string, unknown>;
const matches =
typeof record.uses === 'string' && record.uses.startsWith('actions/upload-artifact@')
? [record as UploadStep]
: [];
return [...matches, ...Object.values(record).flatMap(uploadArtifactSteps)];
}
function paths(step: UploadStep): string[] {
return String(step.with?.path)
.trim()
.split('\n')
.map((entry) => entry.trim());
}
test('the shared diagnostics artifact includes hidden files only from its declared paths', () => {
const action = parse(fs.readFileSync(actionPath, 'utf8'));
const uploads = uploadArtifactSteps(action);
expect(uploads, 'the action must have exactly one artifact upload step').toHaveLength(1);
const [upload] = uploads;
expect(
upload?.with?.['include-hidden-files'],
'hidden daemon, session, and runner diagnostics must be included',
).toBe(true);
expect(paths(upload!)).toEqual([
'${{ inputs.agent-state-dir }}/daemon.log',
'~/.agent-device/logs/**',
'${{ inputs.agent-state-dir }}/sessions/**',
'${{ inputs.runner-derived-path }}/.agent-device-runner-cache.json',
'${{ inputs.runner-derived-path }}/Logs/**',
'test/artifacts/**',
'test/screenshots/**',
]);
expect(
paths(upload!).every((entry) =>
[
'${{ inputs.agent-state-dir }}/',
'${{ inputs.runner-derived-path }}/',
'~/.agent-device/logs/',
'test/',
].some((prefix) => entry.startsWith(prefix)),
),
).toBe(true);
});
test('the conformance trace artifact includes the hidden replay root', () => {
const workflow = parse(fs.readFileSync(conformanceWorkflowPath, 'utf8'));
const uploads = uploadArtifactSteps(workflow);
expect(uploads, 'the workflow must have exactly one artifact upload step').toHaveLength(1);
const [upload] = uploads;
expect(upload?.with?.['include-hidden-files']).toBe(true);
expect(paths(upload!)).toEqual([
'.tmp/conformance-differential/differential-report.json',
'.agent-device/**/replay-timing.ndjson',
]);
});