From 388de2305ce195138000b738584580ba22b3c543 Mon Sep 17 00:00:00 2001 From: Eric Lee Date: Tue, 25 Nov 2025 13:37:09 -0800 Subject: [PATCH] BugError added for unexpected response from BulkOps API --- packages/app/src/cli/commands/app/execute.ts | 4 ++-- .../execute-bulk-operation.test.ts | 23 +++++++++++++++++++ .../bulk-operations/execute-bulk-operation.ts | 6 +++++ .../cli-kit/src/public/node/system.test.ts | 6 ++--- packages/cli-kit/src/public/node/system.ts | 2 +- 5 files changed, 35 insertions(+), 6 deletions(-) diff --git a/packages/app/src/cli/commands/app/execute.ts b/packages/app/src/cli/commands/app/execute.ts index 90957b1a05..64e5cf0f8d 100644 --- a/packages/app/src/cli/commands/app/execute.ts +++ b/packages/app/src/cli/commands/app/execute.ts @@ -4,7 +4,7 @@ import {linkedAppContext} from '../../services/app-context.js' import {storeContext} from '../../services/store-context.js' import {executeBulkOperation} from '../../services/bulk-operations/execute-bulk-operation.js' import {globalFlags} from '@shopify/cli-kit/node/cli' -import {readStdin} from '@shopify/cli-kit/node/system' +import {readStdinString} from '@shopify/cli-kit/node/system' import {AbortError} from '@shopify/cli-kit/node/error' export default class Execute extends AppLinkedCommand { @@ -23,7 +23,7 @@ export default class Execute extends AppLinkedCommand { async run(): Promise { const {flags} = await this.parse(Execute) - const query = flags.query ?? (await readStdin()) + const query = flags.query ?? (await readStdinString()) if (!query) { throw new AbortError( 'No query provided. Use the --query flag or pipe input via stdin.', diff --git a/packages/app/src/cli/services/bulk-operations/execute-bulk-operation.test.ts b/packages/app/src/cli/services/bulk-operations/execute-bulk-operation.test.ts index 5eef4e3e6f..7b22761862 100644 --- a/packages/app/src/cli/services/bulk-operations/execute-bulk-operation.test.ts +++ b/packages/app/src/cli/services/bulk-operations/execute-bulk-operation.test.ts @@ -459,4 +459,27 @@ describe('executeBulkOperation', () => { ) }, ) + test('throws BugError and renders warning when bulk operation response returns null with no errors', async () => { + const query = '{ products { edges { node { id } } } }' + const mockResponse = { + bulkOperation: null, + userErrors: [], + } + vi.mocked(runBulkOperationQuery).mockResolvedValue(mockResponse) + + await expect( + executeBulkOperation({ + remoteApp: mockRemoteApp, + storeFqdn, + query, + }), + ).rejects.toThrow('Bulk operation response returned null with no error message.') + + expect(renderWarning).toHaveBeenCalledWith({ + headline: 'Bulk operation not created succesfully.', + body: 'This is an unexpected error. Please try again later.', + }) + + expect(renderSuccess).not.toHaveBeenCalled() + }) }) diff --git a/packages/app/src/cli/services/bulk-operations/execute-bulk-operation.ts b/packages/app/src/cli/services/bulk-operations/execute-bulk-operation.ts index f68709c93e..28929a5acd 100644 --- a/packages/app/src/cli/services/bulk-operations/execute-bulk-operation.ts +++ b/packages/app/src/cli/services/bulk-operations/execute-bulk-operation.ts @@ -81,6 +81,12 @@ export async function executeBulkOperation(input: ExecuteBulkOperationInput): Pr } else { await renderBulkOperationResult(createdOperation, outputFile) } + } else { + renderWarning({ + headline: 'Bulk operation not created succesfully.', + body: 'This is an unexpected error. Please try again later.', + }) + throw new BugError('Bulk operation response returned null with no error message.') } } diff --git a/packages/cli-kit/src/public/node/system.test.ts b/packages/cli-kit/src/public/node/system.test.ts index ae1c0530bc..6019d294ae 100644 --- a/packages/cli-kit/src/public/node/system.test.ts +++ b/packages/cli-kit/src/public/node/system.test.ts @@ -88,13 +88,13 @@ describe('isStdinPiped', () => { }) }) -describe('readStdin', () => { +describe('readStdinString', () => { test('returns undefined when stdin is not piped', async () => { // Given vi.mocked(fs.fstatSync).mockReturnValue({isFIFO: () => false, isFile: () => false} as fs.Stats) // When - const got = await system.readStdin() + const got = await system.readStdinString() // Then expect(got).toBeUndefined() @@ -107,7 +107,7 @@ describe('readStdin', () => { vi.spyOn(process, 'stdin', 'get').mockReturnValue(mockStdin as unknown as typeof process.stdin) // When - const got = await system.readStdin() + const got = await system.readStdinString() // Then expect(got).toBe('hello world') diff --git a/packages/cli-kit/src/public/node/system.ts b/packages/cli-kit/src/public/node/system.ts index ffeab2a6b5..b906417431 100644 --- a/packages/cli-kit/src/public/node/system.ts +++ b/packages/cli-kit/src/public/node/system.ts @@ -229,7 +229,7 @@ export function isStdinPiped(): boolean { * * @returns A promise that resolves with the stdin content, or undefined if stdin is a TTY. */ -export async function readStdin(): Promise { +export async function readStdinString(): Promise { if (!isStdinPiped()) { return undefined }