|
1 | 1 | import {themesDelete as executeDelete} from './delete.js' |
2 | 2 | import {renderThemeDeleteResult} from './delete/result.js' |
| 3 | +import {removeDevelopmentTheme} from './local-storage.js' |
3 | 4 | import {findOrSelectTheme, findThemes} from '../utilities/theme-selector.js' |
4 | 5 | import {themeDelete} from '@shopify/cli-kit/node/themes/api' |
5 | 6 | import {Theme} from '@shopify/cli-kit/node/themes/types' |
6 | 7 | import {test, describe, expect, vi} from 'vitest' |
7 | 8 | import {renderConfirmationPrompt, renderSuccess} from '@shopify/cli-kit/node/ui' |
| 9 | +import {AbortError} from '@shopify/cli-kit/node/error' |
| 10 | +import {mockAndCaptureOutput} from '@shopify/cli-kit/node/testing/output' |
8 | 11 |
|
9 | 12 | vi.mock('@shopify/cli-kit/node/ui') |
10 | 13 | vi.mock('@shopify/cli-kit/node/themes/api') |
| 14 | +vi.mock('./local-storage.js') |
11 | 15 | vi.mock('../utilities/theme-selector.js') |
12 | 16 | vi.mock('../utilities/development-theme-manager.js', () => { |
13 | 17 | const DevelopmentThemeManager = vi.fn() |
@@ -167,6 +171,36 @@ test('does not prompt again for multiple environments', async () => { |
167 | 171 | expect(themeDelete).toHaveBeenCalledWith(1, session) |
168 | 172 | }) |
169 | 173 |
|
| 174 | +test.each([false, true])('preserves remote deletions when local cleanup fails (multiple: %s)', async (multiple) => { |
| 175 | + const output = mockAndCaptureOutput() |
| 176 | + const developmentTheme = {...theme1, role: 'development'} |
| 177 | + const themes = multiple ? [developmentTheme, theme2] : [developmentTheme] |
| 178 | + vi.mocked(findThemes).mockResolvedValue(themes) |
| 179 | + vi.mocked(removeDevelopmentTheme).mockImplementation(() => { |
| 180 | + throw new AbortError('Local storage is not writable') |
| 181 | + }) |
| 182 | + |
| 183 | + const result = await executeDelete(session, {...options, themes: ['1', '2'], force: true}) |
| 184 | + |
| 185 | + expect(result).toEqual({ |
| 186 | + status: 'success', |
| 187 | + themes: themes.map((theme) => ({...theme, shop: session.storeFqdn})), |
| 188 | + }) |
| 189 | + expect(output.warn()).toContain( |
| 190 | + 'Theme #1 was deleted, but its local development theme reference could not be removed', |
| 191 | + ) |
| 192 | + expect(output.warn()).toContain('Local storage is not writable') |
| 193 | +}) |
| 194 | + |
| 195 | +test('does not remove local state when remote deletion fails', async () => { |
| 196 | + vi.mocked(findThemes).mockResolvedValue([{...theme1, role: 'development'}]) |
| 197 | + vi.mocked(themeDelete).mockRejectedValue(new Error('Deletion failed')) |
| 198 | + |
| 199 | + await expect(executeDelete(session, {...options, themes: ['1'], force: true})).rejects.toThrow('Deletion failed') |
| 200 | + |
| 201 | + expect(removeDevelopmentTheme).not.toHaveBeenCalled() |
| 202 | +}) |
| 203 | + |
170 | 204 | test('preserves the environment label in terminal output', () => { |
171 | 205 | renderThemeDeleteResult({status: 'success', themes: [{...theme1, shop: session.storeFqdn}]}, 'text', { |
172 | 206 | store: session.storeFqdn, |
|
0 commit comments