diff --git a/src/Components/ImagesTable/ImagesTable.tsx b/src/Components/ImagesTable/ImagesTable.tsx index 4dbc9e55..37641cf4 100644 --- a/src/Components/ImagesTable/ImagesTable.tsx +++ b/src/Components/ImagesTable/ImagesTable.tsx @@ -89,6 +89,7 @@ const ImagesTable = ({ selectedBlueprint }: ImageTableProps) => { data: blueprintsComposes, isSuccess: isBlueprintsSuccess, isLoading: isLoadingBlueprintsCompose, + isFetching: isFetchingBlueprintsCompose, isError: isBlueprintsError, } = useGetBlueprintComposesQuery( { @@ -126,6 +127,8 @@ const ImagesTable = ({ selectedBlueprint }: ImageTableProps) => { : isLoadingComposes; const isBlueprintOutSync = + selectedBlueprint && + !isFetchingBlueprintsCompose && blueprintsComposes?.data[0]?.blueprint_version !== selectedBlueprintVersion; if (isLoading) { @@ -199,7 +202,7 @@ const ImagesTable = ({ selectedBlueprint }: ImageTableProps) => { - {itemCount === 0 && ( + {itemCount === 0 ? ( @@ -207,19 +210,21 @@ const ImagesTable = ({ selectedBlueprint }: ImageTableProps) => { - )} - {experimentalFlag && isBlueprintOutSync && ( - - - - - - - + ) : ( + experimentalFlag && + isBlueprintOutSync && ( + + + + + + + + ) )} {composes?.map((compose, rowIndex) => { diff --git a/src/test/Components/Blueprints/Blueprints.test.js b/src/test/Components/Blueprints/Blueprints.test.js index b8e3c2df..72bc7570 100644 --- a/src/test/Components/Blueprints/Blueprints.test.js +++ b/src/test/Components/Blueprints/Blueprints.test.js @@ -38,6 +38,7 @@ describe('Blueprints', () => { const blueprintIdWithComposes = '677b010b-e95e-4694-9813-d11d847f1bfc'; const blueprintNameEmptyComposes = 'Milk Chocolate'; const blueprintIdEmptyComposes = '193482e4-4bd0-4898-a8bc-dc8c33ed669f'; + const blueprintIdOutOfSync = '51243667-8d87-4aef-8dd1-84fc58261b05'; test('renders blueprints page', async () => { renderWithReduxRouter('', {}); @@ -72,8 +73,9 @@ describe('Blueprints', () => { await user.click(elementById); const table = await screen.findByTestId('images-table'); - const { findByText } = within(table); - await findByText(blueprintNameWithComposes); + const { findAllByText } = within(table); + const images = await findAllByText(blueprintNameWithComposes); + expect(images).toHaveLength(2); }); test('renders blueprint composes empty state', async () => { renderWithReduxRouter('', {}); @@ -112,6 +114,34 @@ describe('Blueprints', () => { expect(buildImageBtn).toBeEnabled(); }); + test('blueprint is out of sync', async () => { + renderWithReduxRouter('', {}); + + const nameMatcher = (_, element) => + element.getAttribute('name') === 'blueprints'; + + const radioButtons = await screen.findAllByRole('radio', { + name: nameMatcher, + }); + const outSyncBlueprintCard = radioButtons.find( + (button) => button.getAttribute('id') === blueprintIdOutOfSync + ); + await user.click(outSyncBlueprintCard); + await screen.findByText( + "You haven't built new images for this version of your blueprint yet" + ); + + const blueprintWithComposes = radioButtons.find( + (button) => button.getAttribute('id') === blueprintIdWithComposes + ); + await user.click(blueprintWithComposes); + expect( + screen.queryByText( + "You haven't built new images for this version of your blueprint yet" + ) + ).not.toBeInTheDocument(); + }); + describe('edit blueprint', () => { const editedBlueprintName = 'Dark Chocolate'; const routes = [ diff --git a/src/test/fixtures/blueprints.ts b/src/test/fixtures/blueprints.ts index b6da6c1f..795c2c5e 100644 --- a/src/test/fixtures/blueprints.ts +++ b/src/test/fixtures/blueprints.ts @@ -14,7 +14,7 @@ export const mockBlueprintsCreation: CreateBlueprintResponse[] = [ export const mockGetBlueprints: GetBlueprintsApiResponse = { links: { first: 'first', last: 'last' }, - meta: { count: 2 }, + meta: { count: 3 }, data: [ { id: '677b010b-e95e-4694-9813-d11d847f1bfc', @@ -30,6 +30,13 @@ export const mockGetBlueprints: GetBlueprintsApiResponse = { version: 1, last_modified_at: '2021-09-08T14:38:00.000Z', }, + { + id: '51243667-8d87-4aef-8dd1-84fc58261b05', + name: 'Lemon Pie', + description: 'Crusted lemon pie with meringue topping', + version: 2, + last_modified_at: '2021-09-08T14:38:00.000Z', + }, ], }; @@ -39,6 +46,34 @@ export const emptyGetBlueprints: GetBlueprintsApiResponse = { data: [], }; +export const mockBlueprintComposesOutOfSync: GetBlueprintComposesApiResponse = { + meta: { count: 1 }, + data: [ + { + id: 'edbae1c2-62bc-42c1-ae0c-3110ab718f58', + image_name: 'Lemon Pie', + created_at: '2021-09-08T14:38:00.000Z', + blueprint_version: 1, + request: { + distribution: RHEL_9, + image_requests: [ + { + architecture: 'x86_64', + image_type: 'aws', + upload_request: { + type: 'aws', + options: { + share_with_accounts: ['123123123123'], + }, + }, + }, + ], + }, + }, + ], + links: { first: 'first', last: 'last' }, +}; + export const mockBlueprintComposes: GetBlueprintComposesApiResponse = { meta: { count: 2 }, data: [ @@ -65,6 +100,7 @@ export const mockBlueprintComposes: GetBlueprintComposesApiResponse = { }, { id: 'c1cfa347-4c37-49b5-8e73-6aa1d1746cfa', + image_name: 'Dark Chocolate', created_at: '2021-04-27T12:31:12Z', blueprint_version: 1, request: { diff --git a/src/test/mocks/handlers.js b/src/test/mocks/handlers.js index 7159ffcd..c0589978 100644 --- a/src/test/mocks/handlers.js +++ b/src/test/mocks/handlers.js @@ -14,6 +14,7 @@ import { import { mockArchitecturesByDistro } from '../fixtures/architectures'; import { mockBlueprintComposes, + mockBlueprintComposesOutOfSync, mockBlueprintDetail, mockEmptyBlueprintsComposes, mockGetBlueprints, @@ -148,11 +149,17 @@ export const handlers = [ rest.get( `${IMAGE_BUILDER_API}/experimental/blueprints/:id/composes`, (req, res, ctx) => { - const MilkChocolateBlueprint = mockGetBlueprints.data[1].id; - if (req.params.id === MilkChocolateBlueprint) { - return res(ctx.status(200), ctx.json(mockEmptyBlueprintsComposes)); + const emptyBlueprintId = mockGetBlueprints.data[1].id; + const outOfSyncBlueprintId = mockGetBlueprints.data[2].id; + + switch (req.params.id) { + case emptyBlueprintId: + return res(ctx.status(200), ctx.json(mockEmptyBlueprintsComposes)); + case outOfSyncBlueprintId: + return res(ctx.status(200), ctx.json(mockBlueprintComposesOutOfSync)); + default: + return res(ctx.status(200), ctx.json(mockBlueprintComposes)); } - return res(ctx.status(200), ctx.json(mockBlueprintComposes)); } ), rest.get(