@@ -10,7 +10,7 @@ import {BulkOperationRunMutationMutation} from '../../api/graphql/bulk-operation
1010import { OrganizationApp , OrganizationSource , OrganizationStore } from '../../models/organization.js'
1111import { renderSuccess , renderWarning , renderError , renderInfo } from '@shopify/cli-kit/node/ui'
1212import { ensureAuthenticatedAdminAsApp } from '@shopify/cli-kit/node/session'
13- import { inTemporaryDirectory , writeFile } from '@shopify/cli-kit/node/fs'
13+ import { inTemporaryDirectory , writeFile , readFile } from '@shopify/cli-kit/node/fs'
1414import { joinPath } from '@shopify/cli-kit/node/path'
1515import { mockAndCaptureOutput } from '@shopify/cli-kit/node/testing/output'
1616import { describe , test , expect , vi , beforeEach , afterEach } from 'vitest'
@@ -39,7 +39,6 @@ vi.mock('@shopify/cli-kit/node/ui', async () => {
3939 renderInfo : vi . fn ( ) ,
4040 }
4141} )
42- vi . mock ( '@shopify/cli-kit/node/fs' )
4342vi . mock ( '@shopify/cli-kit/node/session' , async ( ) => {
4443 const actual = await vi . importActual ( '@shopify/cli-kit/node/session' )
4544 return {
@@ -276,6 +275,7 @@ describe('executeBulkOperation', () => {
276275 adminSession : mockAdminSession ,
277276 query : mutation ,
278277 variablesJsonl : variables . join ( '\n' ) ,
278+ version : BULK_OPERATIONS_MIN_API_VERSION ,
279279 } )
280280 } )
281281 } )
@@ -552,36 +552,39 @@ describe('executeBulkOperation', () => {
552552 )
553553
554554 test ( 'writes results to file when --output-file flag is provided' , async ( ) => {
555- const query = '{ products { edges { node { id } } } }'
556- const outputFile = '/tmp/results.jsonl'
557- const resultsContent =
558- '{"data":{"productCreate":{"product":{"id":"gid://shopify/Product/123"},"userErrors":[]}},"__lineNumber":0}\n{"data":{"productCreate":{"product":{"id":"gid://shopify/Product/456"},"userErrors":[]}},"__lineNumber":1}'
555+ await inTemporaryDirectory ( async ( tmpDir ) => {
556+ const query = '{ products { edges { node { id } } } }'
557+ const outputFile = joinPath ( tmpDir , 'results.jsonl' )
558+ const resultsContent =
559+ '{"data":{"productCreate":{"product":{"id":"gid://shopify/Product/123"},"userErrors":[]}},"__lineNumber":0}\n{"data":{"productCreate":{"product":{"id":"gid://shopify/Product/456"},"userErrors":[]}},"__lineNumber":1}'
559560
560- const initialResponse : BulkOperationRunQueryMutation [ 'bulkOperationRunQuery' ] = {
561- bulkOperation : createdBulkOperation ,
562- userErrors : [ ] ,
563- }
564- const completedOperation = {
565- ...createdBulkOperation ,
566- status : 'COMPLETED' as const ,
567- url : 'https://example.com/download' ,
568- objectCount : '2' ,
569- }
561+ const initialResponse : BulkOperationRunQueryMutation [ 'bulkOperationRunQuery' ] = {
562+ bulkOperation : createdBulkOperation ,
563+ userErrors : [ ] ,
564+ }
565+ const completedOperation = {
566+ ...createdBulkOperation ,
567+ status : 'COMPLETED' as const ,
568+ url : 'https://example.com/download' ,
569+ objectCount : '2' ,
570+ }
570571
571- vi . mocked ( runBulkOperationQuery ) . mockResolvedValue ( initialResponse )
572- vi . mocked ( watchBulkOperation ) . mockResolvedValue ( completedOperation )
573- vi . mocked ( downloadBulkOperationResults ) . mockResolvedValue ( resultsContent )
572+ vi . mocked ( runBulkOperationQuery ) . mockResolvedValue ( initialResponse )
573+ vi . mocked ( watchBulkOperation ) . mockResolvedValue ( completedOperation )
574+ vi . mocked ( downloadBulkOperationResults ) . mockResolvedValue ( resultsContent )
574575
575- await executeBulkOperation ( {
576- organization : mockOrganization ,
577- remoteApp : mockRemoteApp ,
578- store : mockStore ,
579- query,
580- watch : true ,
581- outputFile,
582- } )
576+ await executeBulkOperation ( {
577+ organization : mockOrganization ,
578+ remoteApp : mockRemoteApp ,
579+ store : mockStore ,
580+ query,
581+ watch : true ,
582+ outputFile,
583+ } )
583584
584- expect ( writeFile ) . toHaveBeenCalledWith ( outputFile , resultsContent )
585+ const content = await readFile ( outputFile )
586+ expect ( content ) . toBe ( resultsContent )
587+ } )
585588 } )
586589
587590 test ( 'writes results to stdout when --output-file flag is not provided' , async ( ) => {
@@ -615,7 +618,6 @@ describe('executeBulkOperation', () => {
615618 } )
616619
617620 expect ( mockOutput . info ( ) ) . toContain ( resultsContent )
618- expect ( writeFile ) . not . toHaveBeenCalled ( )
619621 } )
620622
621623 test . each ( [ 'FAILED' , 'CANCELED' , 'EXPIRED' ] as const ) (
@@ -748,41 +750,45 @@ describe('executeBulkOperation', () => {
748750 } )
749751
750752 test ( 'renders warning when results written to file contain userErrors' , async ( ) => {
751- const query = '{ products { edges { node { id } } } }'
752- const outputFile = '/tmp/results.jsonl'
753- const resultsWithErrors = '{"data":{"productUpdate":{"userErrors":[{"message":"invalid input"}]}},"__lineNumber":0}'
753+ await inTemporaryDirectory ( async ( tmpDir ) => {
754+ const query = '{ products { edges { node { id } } } }'
755+ const outputFile = joinPath ( tmpDir , 'results.jsonl' )
756+ const resultsWithErrors =
757+ '{"data":{"productUpdate":{"userErrors":[{"message":"invalid input"}]}},"__lineNumber":0}'
754758
755- const initialResponse : BulkOperationRunQueryMutation [ 'bulkOperationRunQuery' ] = {
756- bulkOperation : createdBulkOperation ,
757- userErrors : [ ] ,
758- }
759- const completedOperation = {
760- ...createdBulkOperation ,
761- status : 'COMPLETED' as const ,
762- url : 'https://example.com/download' ,
763- objectCount : '1' ,
764- }
759+ const initialResponse : BulkOperationRunQueryMutation [ 'bulkOperationRunQuery' ] = {
760+ bulkOperation : createdBulkOperation ,
761+ userErrors : [ ] ,
762+ }
763+ const completedOperation = {
764+ ...createdBulkOperation ,
765+ status : 'COMPLETED' as const ,
766+ url : 'https://example.com/download' ,
767+ objectCount : '1' ,
768+ }
765769
766- vi . mocked ( runBulkOperationQuery ) . mockResolvedValue ( initialResponse )
767- vi . mocked ( watchBulkOperation ) . mockResolvedValue ( completedOperation )
768- vi . mocked ( downloadBulkOperationResults ) . mockResolvedValue ( resultsWithErrors )
770+ vi . mocked ( runBulkOperationQuery ) . mockResolvedValue ( initialResponse )
771+ vi . mocked ( watchBulkOperation ) . mockResolvedValue ( completedOperation )
772+ vi . mocked ( downloadBulkOperationResults ) . mockResolvedValue ( resultsWithErrors )
769773
770- await executeBulkOperation ( {
771- organization : mockOrganization ,
772- remoteApp : mockRemoteApp ,
773- store : mockStore ,
774- query,
775- watch : true ,
776- outputFile,
777- } )
774+ await executeBulkOperation ( {
775+ organization : mockOrganization ,
776+ remoteApp : mockRemoteApp ,
777+ store : mockStore ,
778+ query,
779+ watch : true ,
780+ outputFile,
781+ } )
778782
779- expect ( writeFile ) . toHaveBeenCalledWith ( outputFile , resultsWithErrors )
780- expect ( renderWarning ) . toHaveBeenCalledWith (
781- expect . objectContaining ( {
782- headline : 'Bulk operation completed with errors.' ,
783- body : `Results written to ${ outputFile } . Check file for error details.` ,
784- } ) ,
785- )
783+ const content = await readFile ( outputFile )
784+ expect ( content ) . toBe ( resultsWithErrors )
785+ expect ( renderWarning ) . toHaveBeenCalledWith (
786+ expect . objectContaining ( {
787+ headline : 'Bulk operation completed with errors.' ,
788+ body : `Results written to ${ outputFile } . Check file for error details.` ,
789+ } ) ,
790+ )
791+ } )
786792 } )
787793
788794 test ( 'calls resolveApiVersion with minimum API version constant' , async ( ) => {
0 commit comments