import React from 'react'; import type { Router as RemixRouter } from '@remix-run/router'; import { screen, waitFor } from '@testing-library/react'; import { userEvent } from '@testing-library/user-event'; import ImageWizard from '../../../Components/CreateImageWizard'; import { RHEL_9 } from '../../../constants'; import { CreateBlueprintRequest, ImageRequest, } from '../../../store/imageBuilderApi'; import { server } from '../../mocks/server'; import { renderCustomRoutesWithReduxRouter } from '../../testUtils'; type RequestTypes = 'GET' | 'PUT' | 'POST' | 'DELETE'; export function spyOnRequest(pathname: string, method: RequestTypes) { return new Promise((resolve) => { const listener = async ({ request: req }: { request: Request }) => { const url = new URL(req.url); if (url.pathname === pathname && req.method === method) { const requestData = await req.clone().json(); resolve(requestData); // Cleanup listener after successful intercept server.events.removeListener('request:match', listener); } }; server.events.on('request:match', listener); }); } const routes = [ { path: 'insights/image-builder/*', element:
, }, { path: 'insights/image-builder/imagewizard/:composeId?', element: , }, ]; export const imageRequest: ImageRequest = { architecture: 'x86_64', image_type: 'guest-image', upload_request: { options: {}, type: 'aws.s3', }, }; export const blueprintRequest: CreateBlueprintRequest = { name: 'Red Velvet', description: '', distribution: RHEL_9, image_requests: [imageRequest], customizations: {}, }; /** * @example * // returns 'imageWizard?release=rhel8&architecture=aarch64' * preparePathname({ release: 'rhel8', architecture: 'aarch64' }); * @example * // returns 'imageWizard' * preparePathname({}); */ function preparePathname(searchParams: { [key: string]: string } = {}): string { let pathName = 'imageWizard'; const params = Object.entries(searchParams).map( ([param, value]) => `${param}=${value}` ); if (params.length > 0) { pathName += `?${params.join('&')}`; } return pathName; } export const renderCreateMode = async (searchParams = {}) => { const pathName = preparePathname(searchParams); await renderCustomRoutesWithReduxRouter(pathName, {}, routes); }; export const renderEditMode = async (id: string) => { await renderCustomRoutesWithReduxRouter(`imagewizard/${id}`, {}, routes); }; export const selectGuestImageTarget = async () => { const user = userEvent.setup(); const guestImageCheckBox = await screen.findByTestId('checkbox-guest-image'); await waitFor(() => user.click(guestImageCheckBox)); }; export const goToRegistrationStep = async () => { await selectGuestImageTarget(); await clickNext(); }; export const clickRegisterLater = async () => { const user = userEvent.setup(); await screen.findByRole('heading', { name: /Register systems using this image/, }); const registrationCheckbox = await screen.findByRole('checkbox', { name: /automatically register and enable advanced capabilities/i, }); await waitFor(() => user.click(registrationCheckbox)); }; export const goToOscapStep = async () => { await clickNext(); // Registration await clickRegisterLater(); await clickNext(); // OpenSCAP }; export const selectCustomRepo = async () => { const user = userEvent.setup(); await clickBack(); const customRepoCheckbox = await screen.findByRole('checkbox', { name: /select row 0/i, }); user.click(customRepoCheckbox); await clickNext(); }; export const enterBlueprintName = async (name: string = 'Red Velvet') => { const user = userEvent.setup({ delay: null }); const blueprintName = await screen.findByRole('textbox', { name: /blueprint name/i, }); await waitFor(() => user.clear(blueprintName)); await waitFor(() => expect(blueprintName).toHaveValue('')); await waitFor(() => user.type(blueprintName, name)); }; export const openAndDismissSaveAndBuildModal = async () => { const user = userEvent.setup(); const createBlueprintBtn = await screen.findByRole('button', { name: 'Create blueprint', }); await waitFor(async () => user.click(createBlueprintBtn)); const saveAndBuildModal = await screen.findByTestId( 'close-button-saveandbuild-modal' ); await waitFor(() => user.click(saveAndBuildModal)); }; export const interceptBlueprintRequest = async (requestPathname: string) => { const user = userEvent.setup(); const receivedRequestPromise = spyOnRequest(requestPathname, 'POST'); const saveButton = await screen.findByRole('button', { name: 'Create blueprint', }); await waitFor(() => user.click(saveButton)); return await receivedRequestPromise; }; export const interceptEditBlueprintRequest = async ( requestPathname: string ) => { const user = userEvent.setup(); const receivedRequestPromise = spyOnRequest(requestPathname, 'PUT'); const saveButton = await screen.findByRole('button', { name: 'Save changes to blueprint', }); await waitFor(() => user.click(saveButton)); return await receivedRequestPromise; }; export const clickBack = async () => { const user = userEvent.setup(); const backBtn = await screen.findByRole('button', { name: /Back/ }); await waitFor(() => user.click(backBtn)); }; export const clickNext = async () => { const user = userEvent.setup(); const nextBtn = await screen.findByRole('button', { name: /Next/ }); await waitFor(() => user.click(nextBtn)); }; export const clickCancel = async () => { const user = userEvent.setup(); const cancelBtn = await screen.findByRole('button', { name: /Cancel/ }); await waitFor(() => user.click(cancelBtn)); }; export const clickReviewAndFinish = async () => { const user = userEvent.setup(); const reviewAndFinishBtn = await screen.findByRole('button', { name: /Review and finish/, }); await waitFor(() => user.click(reviewAndFinishBtn)); }; export const getNextButton = async () => { const next = await screen.findByRole('button', { name: /Next/ }); return next; }; export const verifyCancelButton = async (router: RemixRouter | undefined) => { await clickCancel(); if (router) { expect(router.state.location.pathname).toBe('/insights/image-builder'); } };