Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export type BulkOperationRunMutationMutationVariables = Types.Exact<{
export type BulkOperationRunMutationMutation = {
bulkOperationRunMutation?: {
bulkOperation?: {
type: Types.BulkOperationType
completedAt?: unknown | null
createdAt: unknown
errorCode?: Types.BulkOperationErrorCode | null
Expand Down Expand Up @@ -81,6 +82,7 @@ export const BulkOperationRunMutation = {
selectionSet: {
kind: 'SelectionSet',
selections: [
{kind: 'Field', name: {kind: 'Name', value: 'type'}},
{kind: 'Field', name: {kind: 'Name', value: 'completedAt'}},
{kind: 'Field', name: {kind: 'Name', value: 'createdAt'}},
{kind: 'Field', name: {kind: 'Name', value: 'errorCode'}},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ export type BulkOperationRunQueryMutationVariables = Types.Exact<{
export type BulkOperationRunQueryMutation = {
bulkOperationRunQuery?: {
bulkOperation?: {
type: Types.BulkOperationType
completedAt?: unknown | null
createdAt: unknown
errorCode?: Types.BulkOperationErrorCode | null
Expand Down Expand Up @@ -59,6 +60,7 @@ export const BulkOperationRunQuery = {
selectionSet: {
kind: 'SelectionSet',
selections: [
{kind: 'Field', name: {kind: 'Name', value: 'type'}},
{kind: 'Field', name: {kind: 'Name', value: 'completedAt'}},
{kind: 'Field', name: {kind: 'Name', value: 'createdAt'}},
{kind: 'Field', name: {kind: 'Name', value: 'errorCode'}},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export type GetBulkOperationByIdQueryVariables = Types.Exact<{

export type GetBulkOperationByIdQuery = {
bulkOperation?: {
type: Types.BulkOperationType
completedAt?: unknown | null
createdAt: unknown
errorCode?: Types.BulkOperationErrorCode | null
Expand Down Expand Up @@ -50,6 +51,7 @@ export const GetBulkOperationById = {
selectionSet: {
kind: 'SelectionSet',
selections: [
{kind: 'Field', name: {kind: 'Name', value: 'type'}},
{kind: 'Field', name: {kind: 'Name', value: 'completedAt'}},
{kind: 'Field', name: {kind: 'Name', value: 'createdAt'}},
{kind: 'Field', name: {kind: 'Name', value: 'errorCode'}},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,13 @@ export type BulkOperationStatus =
/** The bulk operation is runnning. */
| 'RUNNING'

/** The valid values for the bulk operation's type. */
export type BulkOperationType =
/** The bulk operation is a mutation. */
| 'MUTATION'
/** The bulk operation is a query. */
| 'QUERY'

/** Possible error codes that can be returned by `BulkOperationUserError`. */
export type BulkOperationUserErrorCode =
/** The input value is invalid. */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ mutation BulkOperationRunMutation(
clientIdentifier: $clientIdentifier
) {
bulkOperation {
type
completedAt
createdAt
errorCode
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ mutation BulkOperationRunQuery($query: String!) {
query: $query
) {
bulkOperation {
type
completedAt
createdAt
errorCode
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
query GetBulkOperationById($id: ID!) {
bulkOperation(id: $id) {
type
completedAt
createdAt
errorCode
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ describe('getBulkOperationStatus', () => {
return {
bulkOperation: {
id: operationId,
type: 'QUERY',
status: 'RUNNING',
errorCode: null,
objectCount: 100,
Expand Down Expand Up @@ -75,8 +76,8 @@ describe('getBulkOperationStatus', () => {
const output = mockAndCaptureOutput()
await getBulkOperationStatus({storeFqdn, operationId, remoteApp})

expect(output.info()).toContain('Bulk operation in progress...')
expect(output.info()).toContain('500 objects')
expect(output.info()).toContain('Bulk operation in progress')
expect(output.info()).toContain('500 objects read')
expect(output.info()).toContain('Started')
})

Expand Down Expand Up @@ -114,7 +115,7 @@ describe('getBulkOperationStatus', () => {
const output = mockAndCaptureOutput()
await getBulkOperationStatus({storeFqdn, operationId, remoteApp})

expect(output.info()).toContain('Starting...')
expect(output.info()).toContain('Starting')
})

test('renders info banner for canceled operation', async () => {
Expand Down Expand Up @@ -160,6 +161,7 @@ describe('listBulkOperations', () => {
bulkOperations: {
nodes: operations.map((op) => ({
id: 'gid://shopify/BulkOperation/123',
type: 'QUERY',
status: 'RUNNING',
errorCode: null,
objectCount: 100,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ describe('executeBulkOperation', () => {
NonNullable<BulkOperationRunQueryMutation['bulkOperationRunQuery']>['bulkOperation']
> = {
id: 'gid://shopify/BulkOperation/123',
type: 'QUERY',
status: 'CREATED',
errorCode: null,
createdAt: '2024-01-01T00:00:00Z',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,54 +8,66 @@ function createMockOperation(overrides: Partial<BulkOperation> = {}): BulkOperat
return {
id: 'gid://shopify/BulkOperation/123',
status: 'CREATED',
type: 'QUERY',
errorCode: null,
createdAt: '2024-01-01T00:00:00Z',
completedAt: null,
objectCount: '0',
url: null,
partialDataUrl: null,
...overrides,
}
}

describe('formatBulkOperationStatus', () => {
test('formats RUNNING status with object count', () => {
const result = formatBulkOperationStatus(createMockOperation({status: 'RUNNING', objectCount: 42}))
expect(result.value).toContain('Bulk operation in progress...')
expect(result.value).toContain('(42 objects)')
test('formats RUNNING status for query with object count', () => {
const result = formatBulkOperationStatus(createMockOperation({status: 'RUNNING', type: 'QUERY', objectCount: '42'}))
expect(result.value).toContain('Bulk operation in progress')
expect(result.value).toContain('(42 objects read)')
})

test('formats RUNNING status for mutation with object count', () => {
const result = formatBulkOperationStatus(
createMockOperation({status: 'RUNNING', type: 'MUTATION', objectCount: '42'}),
)
expect(result.value).toContain('Bulk operation in progress')
expect(result.value).toContain('(42 objects written)')
})

test('formats CREATED status', () => {
const result = formatBulkOperationStatus(createMockOperation({status: 'CREATED'}))
expect(result.value).toBe('Starting...')
expect(result.value).toBe('Starting')
})

test('formats COMPLETED status', () => {
const result = formatBulkOperationStatus(createMockOperation({status: 'COMPLETED', objectCount: 100}))
const result = formatBulkOperationStatus(createMockOperation({status: 'COMPLETED', objectCount: '100'}))
expect(result.value).toContain('Bulk operation succeeded:')
expect(result.value).toContain('100 objects')
})

test('formats FAILED status with error code', () => {
const result = formatBulkOperationStatus(
createMockOperation({status: 'FAILED', objectCount: 10, errorCode: 'ACCESS_DENIED'}),
createMockOperation({status: 'FAILED', objectCount: '10', errorCode: 'ACCESS_DENIED'}),
)
expect(result.value).toContain('Bulk operation failed.')
expect(result.value).toContain('Error: ACCESS_DENIED')
})

test('formats FAILED status without error code', () => {
const result = formatBulkOperationStatus(createMockOperation({status: 'FAILED', objectCount: 10, errorCode: null}))
const result = formatBulkOperationStatus(
createMockOperation({status: 'FAILED', objectCount: '10', errorCode: null}),
)
expect(result.value).toContain('Bulk operation failed.')
expect(result.value).toContain('Error: unknown')
})

test('formats CANCELING status', () => {
const result = formatBulkOperationStatus(createMockOperation({status: 'CANCELING', objectCount: 5}))
const result = formatBulkOperationStatus(createMockOperation({status: 'CANCELING', objectCount: '5'}))
expect(result.value).toBe('Bulk operation canceling...')
})

test('formats CANCELED status', () => {
const result = formatBulkOperationStatus(createMockOperation({status: 'CANCELED', objectCount: 5}))
const result = formatBulkOperationStatus(createMockOperation({status: 'CANCELED', objectCount: '5'}))
expect(result.value).toBe('Bulk operation canceled.')
})

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@ export function formatBulkOperationStatus(
): TokenizedString {
switch (operation.status) {
case 'RUNNING':
return outputContent`Bulk operation in progress... ${outputToken.gray(
`(${String(operation.objectCount)} objects)`,
return outputContent`Bulk operation in progress ${outputToken.gray(
`(${String(operation.objectCount)} objects ${operation.type === 'MUTATION' ? 'written' : 'read'})`,
)}`
case 'CREATED':
return outputContent`Starting...`
return outputContent`Starting`
case 'COMPLETED':
return outputContent`Bulk operation succeeded: ${outputToken.gray(`${String(operation.objectCount)} objects`)}`
case 'FAILED':
Expand Down