@@ -10,7 +10,7 @@ import {
1010 listDownloadableArtifacts ,
1111 trackDownloadableArtifact ,
1212} from '../../resources/artifact-tracking.ts' ;
13- import { runCmdSync } from '@agent-device/host-kit/command' ;
13+ import { runCmdSync , withCommandExecutorOverride } from '@agent-device/host-kit/command' ;
1414import {
1515 closeLoopbackServer ,
1616 listenOnLoopback ,
@@ -61,15 +61,21 @@ test(ANDROID_ARTIFACTS_CONTRACT_EVIDENCE.testName, async () => {
6161
6262 try {
6363 assert . deepEqual (
64- ( await listDownloadableArtifacts ( undefined ) ) . map ( ( artifact ) => artifact . filename ) ,
64+ ( await listDownloadableArtifacts ( undefined , process . env ) ) . map (
65+ ( artifact ) => artifact . filename ,
66+ ) ,
6567 [ 'public.txt' ] ,
6668 ) ;
6769 assert . deepEqual (
68- ( await listDownloadableArtifacts ( 'tenant-a' ) ) . map ( ( artifact ) => artifact . filename ) ,
70+ ( await listDownloadableArtifacts ( 'tenant-a' , process . env ) ) . map (
71+ ( artifact ) => artifact . filename ,
72+ ) ,
6973 [ 'public.txt' , 'tenant-a.txt' ] ,
7074 ) ;
7175 assert . deepEqual (
72- ( await listDownloadableArtifacts ( 'tenant-b' ) ) . map ( ( artifact ) => artifact . filename ) ,
76+ ( await listDownloadableArtifacts ( 'tenant-b' , process . env ) ) . map (
77+ ( artifact ) => artifact . filename ,
78+ ) ,
7379 [ 'public.txt' , 'tenant-b.txt' ] ,
7480 ) ;
7581 } finally {
@@ -80,6 +86,46 @@ test(ANDROID_ARTIFACTS_CONTRACT_EVIDENCE.testName, async () => {
8086 }
8187} ) ;
8288
89+ test ( 'downloadable artifact inventory skips directory artifacts that fail to archive' , async ( ) => {
90+ const tempDir = mkdtempForTestSync ( 'agent-device-artifacts-archive-error-' ) ;
91+ const filePath = path . join ( tempDir , 'report.json' ) ;
92+ const tracePath = path . join ( tempDir , '--profile.trace' ) ;
93+ fs . writeFileSync ( filePath , '{}\n' ) ;
94+ fs . mkdirSync ( tracePath , { recursive : true } ) ;
95+ fs . writeFileSync ( path . join ( tracePath , 'metadata.json' ) , '{}\n' ) ;
96+ const artifactIds = [
97+ trackDownloadableArtifact ( {
98+ artifactPath : filePath ,
99+ artifactType : 'test-report' ,
100+ fileName : 'report.json' ,
101+ } ) ,
102+ trackDownloadableArtifact ( {
103+ artifactPath : tracePath ,
104+ artifactType : 'trace-log' ,
105+ fileName : 'profile.trace' ,
106+ } ) ,
107+ ] ;
108+
109+ try {
110+ const artifacts = await withCommandExecutorOverride (
111+ ( cmd ) => {
112+ if ( cmd !== 'tar' ) return undefined ;
113+ throw new Error ( 'tar unavailable' ) ;
114+ } ,
115+ async ( ) => await listDownloadableArtifacts ( undefined , process . env ) ,
116+ ) ;
117+ assert . deepEqual (
118+ artifacts . map ( ( artifact ) => artifact . filename ) ,
119+ [ 'report.json' ] ,
120+ ) ;
121+ } finally {
122+ for ( const artifactId of artifactIds ) {
123+ cleanupDownloadableArtifact ( artifactId ) ;
124+ }
125+ fs . rmSync ( tempDir , { recursive : true , force : true } ) ;
126+ }
127+ } ) ;
128+
83129test ( 'daemon artifact inventory exposes directory artifacts as tar.gz downloads' , async ( t ) => {
84130 if ( await skipWhenLoopbackUnavailable ( t ) ) return ;
85131
@@ -111,8 +157,7 @@ test('daemon artifact inventory exposes directory artifacts as tar.gz downloads'
111157 assert . ok ( artifact , `expected ${ artifactId } in artifact inventory` ) ;
112158 assert . equal ( artifact . filename , 'profile.trace.tar.gz' ) ;
113159 assert . equal ( artifact . mimeType , 'application/gzip' ) ;
114- // The archive is built on the first download, so the listing cannot know its size yet.
115- assert . equal ( artifact . sizeBytes , undefined ) ;
160+ assert . ok ( artifact . sizeBytes > 0 ) ;
116161
117162 const consumingDownload = await fetch (
118163 `${ baseUrl } /artifacts/${ encodeURIComponent ( artifactId ) } ?download=1` ,
@@ -122,7 +167,7 @@ test('daemon artifact inventory exposes directory artifacts as tar.gz downloads'
122167 ) ;
123168 assert . equal ( consumingDownload . status , 200 ) ;
124169 assert . equal ( consumingDownload . headers . get ( 'content-type' ) , 'application/gzip' ) ;
125- assert . ok ( Number ( consumingDownload . headers . get ( 'content-length' ) ) > 0 ) ;
170+ assert . equal ( consumingDownload . headers . get ( 'content-length' ) , String ( artifact . sizeBytes ) ) ;
126171 assert . match (
127172 consumingDownload . headers . get ( 'content-disposition' ) ?? '' ,
128173 / p r o f i l e \. t r a c e \. t a r \. g z / ,
@@ -386,7 +431,7 @@ test('downloadable artifact inventory reports a screenshot display rotation only
386431 } ) ;
387432
388433 try {
389- const inventory = await listDownloadableArtifacts ( undefined ) ;
434+ const inventory = await listDownloadableArtifacts ( undefined , process . env ) ;
390435 const rotated = inventory . find ( ( entry ) => entry . id === rotatedId ) ;
391436 const plain = inventory . find ( ( entry ) => entry . id === plainId ) ;
392437 assert . equal ( rotated ?. displayRotation , 'landscape-right' ) ;
0 commit comments