Skip to content

Commit 647dbca

Browse files
authored
Merge pull request #5155 from Shopify/catlee/theme_notfound
Handle missing themes in fetchTheme()
2 parents 9da5aca + 0287491 commit 647dbca

File tree

2 files changed

+71
-11
lines changed

2 files changed

+71
-11
lines changed

packages/cli-kit/src/public/node/themes/api.test.ts

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import {
22
createTheme,
33
themeDelete,
4+
fetchTheme,
45
fetchThemes,
56
ThemeParams,
67
themeUpdate,
@@ -18,9 +19,11 @@ import {GetThemeFileChecksums} from '../../../cli/api/graphql/admin/generated/ge
1819
import {ThemeFilesUpsert} from '../../../cli/api/graphql/admin/generated/theme_files_upsert.js'
1920
import {OnlineStoreThemeFileBodyInputType} from '../../../cli/api/graphql/admin/generated/types.js'
2021
import {GetThemes} from '../../../cli/api/graphql/admin/generated/get_themes.js'
22+
import {GetTheme} from '../../../cli/api/graphql/admin/generated/get_theme.js'
2123
import {test, vi, expect, describe} from 'vitest'
2224
import {adminRequestDoc, restRequest, supportedApiVersions} from '@shopify/cli-kit/node/api/admin'
2325
import {AbortError} from '@shopify/cli-kit/node/error'
26+
import {ClientError} from 'graphql-request'
2427

2528
vi.mock('@shopify/cli-kit/node/api/admin')
2629
vi.mock('@shopify/cli-kit/node/system')
@@ -29,6 +32,52 @@ const session = {token: 'token', storeFqdn: 'my-shop.myshopify.com', refresh: as
2932
const themeAccessSession = {...session, token: 'shptka_token'}
3033
const sessions = {CLI: session, 'Theme Access': themeAccessSession}
3134

35+
describe('fetchTheme', () => {
36+
test('returns a store theme', async () => {
37+
vi.mocked(adminRequestDoc).mockResolvedValue({
38+
theme: {id: 'gid://shopify/OnlineStoreTheme/123', name: 'store theme 1', role: 'MAIN', processing: false},
39+
})
40+
41+
// When
42+
const theme = await fetchTheme(123, session)
43+
44+
// Then
45+
expect(adminRequestDoc).toHaveBeenCalledWith(
46+
GetTheme,
47+
session,
48+
{id: 'gid://shopify/OnlineStoreTheme/123'},
49+
undefined,
50+
{handleErrors: false},
51+
)
52+
53+
expect(theme).not.toBeNull()
54+
expect(theme!.id).toEqual(123)
55+
expect(theme!.name).toEqual('store theme 1')
56+
expect(theme!.processing).toBeFalsy()
57+
})
58+
59+
test('returns undefined when a theme is not found', async () => {
60+
const errorResponse = {
61+
status: 200,
62+
errors: [{message: 'Theme does not exist'} as any],
63+
}
64+
vi.mocked(adminRequestDoc).mockRejectedValue(new ClientError(errorResponse, {query: ''}))
65+
66+
// When
67+
const theme = await fetchTheme(123, session)
68+
69+
// Then
70+
expect(theme).toBeUndefined()
71+
expect(adminRequestDoc).toHaveBeenCalledWith(
72+
GetTheme,
73+
session,
74+
{id: 'gid://shopify/OnlineStoreTheme/123'},
75+
undefined,
76+
{handleErrors: false},
77+
)
78+
})
79+
})
80+
3281
describe('fetchThemes', () => {
3382
test('returns store themes', async () => {
3483
// Given

packages/cli-kit/src/public/node/themes/api.ts

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -25,23 +25,34 @@ import {buildTheme} from '@shopify/cli-kit/node/themes/factories'
2525
import {Result, Checksum, Key, Theme, ThemeAsset, Operation} from '@shopify/cli-kit/node/themes/types'
2626
import {outputDebug} from '@shopify/cli-kit/node/output'
2727
import {sleep} from '@shopify/cli-kit/node/system'
28+
import {ClientError} from 'graphql-request'
2829

2930
export type ThemeParams = Partial<Pick<Theme, 'name' | 'role' | 'processing' | 'src'>>
3031
export type AssetParams = Pick<ThemeAsset, 'key'> & Partial<Pick<ThemeAsset, 'value' | 'attachment'>>
3132

3233
export async function fetchTheme(id: number, session: AdminSession): Promise<Theme | undefined> {
33-
const response = await adminRequestDoc(GetTheme, session, {id: composeThemeGid(id)})
34-
35-
const {theme} = response
36-
if (!theme) {
37-
return undefined
34+
try {
35+
const response = await adminRequestDoc(GetTheme, session, {id: composeThemeGid(id)}, undefined, {
36+
handleErrors: false,
37+
})
38+
const {theme} = response
39+
if (!theme) {
40+
return undefined
41+
}
42+
return buildTheme({
43+
id: parseGid(theme.id),
44+
processing: theme.processing,
45+
role: theme.role.toLowerCase(),
46+
name: theme.name,
47+
})
48+
} catch (error) {
49+
if (error instanceof ClientError) {
50+
if (error.response?.errors?.[0]?.message === 'Theme does not exist') {
51+
return undefined
52+
}
53+
}
54+
throw new AbortError(`Failed to fetch theme: ${id}`)
3855
}
39-
return buildTheme({
40-
id: parseGid(theme.id),
41-
processing: theme.processing,
42-
role: theme.role.toLowerCase(),
43-
name: theme.name,
44-
})
4556
}
4657

4758
export async function fetchThemes(session: AdminSession): Promise<Theme[]> {

0 commit comments

Comments
 (0)