| 1 |
import { getSitePlugins } from '@launch/api/DataApi'; |
| 2 |
|
| 3 |
const mockUseUserSelectionStore = { |
| 4 |
getState: jest.fn(), |
| 5 |
}; |
| 6 |
const originalFetch = global.fetch; |
| 7 |
|
| 8 |
describe('getSitePlugins', () => { |
| 9 |
beforeEach(() => { |
| 10 |
global.fetch = jest.fn(); |
| 11 |
|
| 12 |
window.extSharedData = Object.assign({}, window.extSharedData, { |
| 13 |
wpLanguage: 'en', |
| 14 |
partnerId: 'partner-123', |
| 15 |
pluginGroupId: 'group-xyz', |
| 16 |
}); |
| 17 |
mockUseUserSelectionStore.getState.mockReturnValue({ |
| 18 |
businessInformation: { description: 'My business' }, |
| 19 |
siteObjective: 'Grow', |
| 20 |
}); |
| 21 |
}); |
| 22 |
|
| 23 |
afterEach(() => { |
| 24 |
jest.clearAllMocks(); |
| 25 |
global.fetch = originalFetch; |
| 26 |
}); |
| 27 |
|
| 28 |
it('returns merged plugins on successful fetch with valid JSON', async () => { |
| 29 |
const apiSelected = ['a', 'b']; |
| 30 |
global.fetch.mockResolvedValueOnce({ |
| 31 |
ok: true, |
| 32 |
json: () => ({ selectedPlugins: apiSelected }), |
| 33 |
}); |
| 34 |
|
| 35 |
const result = await getSitePlugins({ siteProfile: { id: 1 }, siteQA: [] }); |
| 36 |
|
| 37 |
const expected = apiSelected; |
| 38 |
expect(result).toEqual(expected); |
| 39 |
expect(global.fetch).toHaveBeenCalledTimes(1); |
| 40 |
}); |
| 41 |
|
| 42 |
it('returns fallback when siteProfile is falsy (no fetch)', async () => { |
| 43 |
const result = await getSitePlugins({ siteProfile: null, siteQA: [] }); |
| 44 |
|
| 45 |
const expectedFallback = []; |
| 46 |
expect(result).toEqual(expectedFallback); |
| 47 |
expect(global.fetch).not.toHaveBeenCalled(); |
| 48 |
}); |
| 49 |
|
| 50 |
it('retries when first fetch throws (network) and second returns ok -> returns merged plugins', async () => { |
| 51 |
const apiSelected = ['x']; |
| 52 |
global.fetch |
| 53 |
.mockRejectedValueOnce(new Error('Network error')) |
| 54 |
.mockResolvedValueOnce({ |
| 55 |
ok: true, |
| 56 |
json: () => ({ selectedPlugins: apiSelected }), |
| 57 |
}); |
| 58 |
|
| 59 |
const result = await getSitePlugins({ siteProfile: { id: 1 }, siteQA: [] }); |
| 60 |
|
| 61 |
expect(result).toEqual(apiSelected); |
| 62 |
expect(global.fetch).toHaveBeenCalledTimes(2); |
| 63 |
}); |
| 64 |
|
| 65 |
it('retries when first response is not ok; returns merged plugins if second is ok', async () => { |
| 66 |
const apiSelected = ['p']; |
| 67 |
global.fetch.mockResolvedValueOnce({ ok: false }).mockResolvedValueOnce({ |
| 68 |
ok: true, |
| 69 |
json: () => ({ selectedPlugins: apiSelected }), |
| 70 |
}); |
| 71 |
|
| 72 |
const result = await getSitePlugins({ siteProfile: { id: 1 }, siteQA: [] }); |
| 73 |
expect(result).toEqual(apiSelected); |
| 74 |
expect(global.fetch).toHaveBeenCalledTimes(2); |
| 75 |
}); |
| 76 |
|
| 77 |
it('returns fallback when both fetch attempts throw', async () => { |
| 78 |
global.fetch |
| 79 |
.mockRejectedValueOnce(new Error('Network error')) |
| 80 |
.mockRejectedValueOnce(new Error('Still failing')); |
| 81 |
|
| 82 |
const result = await getSitePlugins({ siteProfile: { id: 1 }, siteQA: [] }); |
| 83 |
|
| 84 |
expect(result).toEqual([]); |
| 85 |
expect(global.fetch).toHaveBeenCalledTimes(2); |
| 86 |
}); |
| 87 |
|
| 88 |
it('returns fallback when second fetch resolves but not ok', async () => { |
| 89 |
global.fetch |
| 90 |
.mockRejectedValueOnce(new Error('Network error')) |
| 91 |
.mockResolvedValueOnce({ ok: false }); |
| 92 |
|
| 93 |
const result = await getSitePlugins({ siteProfile: { id: 1 }, siteQA: [] }); |
| 94 |
|
| 95 |
expect(result).toEqual([]); |
| 96 |
expect(global.fetch).toHaveBeenCalledTimes(2); |
| 97 |
}); |
| 98 |
|
| 99 |
it('returns fallback when response is ok but JSON parsing fails', async () => { |
| 100 |
global.fetch.mockResolvedValueOnce({ |
| 101 |
ok: true, |
| 102 |
json: () => { |
| 103 |
throw new Error('Invalid JSON'); |
| 104 |
}, |
| 105 |
}); |
| 106 |
|
| 107 |
const result = await getSitePlugins({ siteProfile: { id: 1 }, siteQA: [] }); |
| 108 |
|
| 109 |
expect(result).toEqual([]); |
| 110 |
expect(global.fetch).toHaveBeenCalledTimes(1); |
| 111 |
}); |
| 112 |
|
| 113 |
it('returns fallback when response ok=true but payload has no selectedPlugins', async () => { |
| 114 |
global.fetch.mockResolvedValueOnce({ |
| 115 |
ok: true, |
| 116 |
json: () => ({}), |
| 117 |
}); |
| 118 |
|
| 119 |
const result = await getSitePlugins({ siteProfile: { id: 1 }, siteQA: [] }); |
| 120 |
|
| 121 |
expect(result).toEqual([]); |
| 122 |
expect(global.fetch).toHaveBeenCalledTimes(1); |
| 123 |
}); |
| 124 |
|
| 125 |
it('returns fallback when first fetch resolves undefined (retries by design)', async () => { |
| 126 |
global.fetch |
| 127 |
.mockResolvedValueOnce(undefined) |
| 128 |
.mockResolvedValueOnce({ ok: false }); |
| 129 |
|
| 130 |
const result = await getSitePlugins({ siteProfile: { id: 1 }, siteQA: [] }); |
| 131 |
|
| 132 |
expect(result).toEqual([]); |
| 133 |
expect(global.fetch).toHaveBeenCalledTimes(2); |
| 134 |
}); |
| 135 |
}); |
| 136 |
|