change repo snapshot step to repeatable builds
This commit is contained in:
parent
a4034e8787
commit
38458810a0
15 changed files with 51 additions and 24 deletions
|
|
@ -444,7 +444,7 @@ const CreateImageWizard = ({ isEdit }: CreateImageWizardProps) => {
|
|||
</FileSystemContext.Provider>
|
||||
</WizardStep>,
|
||||
<WizardStep
|
||||
name="Repository snapshot"
|
||||
name="Repeatable build"
|
||||
id="wizard-repository-snapshot"
|
||||
key="wizard-repository-snapshot"
|
||||
navItem={customStatusNavItem}
|
||||
|
|
|
|||
|
|
@ -498,7 +498,7 @@ export const ContentList = () => {
|
|||
component={TextListItemVariants.dt}
|
||||
className="pf-v5-u-min-width"
|
||||
>
|
||||
Repository snapshot
|
||||
Repeatable build
|
||||
</TextListItem>
|
||||
<TextListItem
|
||||
component={TextListItemVariants.dd}
|
||||
|
|
@ -508,7 +508,7 @@ export const ContentList = () => {
|
|||
position="bottom"
|
||||
headerContent={
|
||||
useLatest
|
||||
? 'Repositories as of today'
|
||||
? 'Use the latest repository content'
|
||||
: `Repositories as of ${yyyyMMddFormat(
|
||||
new Date(snapshotDate)
|
||||
)}`
|
||||
|
|
|
|||
|
|
@ -18,11 +18,13 @@ import {
|
|||
changeUseLatest,
|
||||
changeSnapshotDate,
|
||||
} from '../../../../store/wizardSlice';
|
||||
import { yyyyMMddFormat } from '../../../../Utilities/time';
|
||||
import { isSnapshotDateValid } from '../../validators';
|
||||
|
||||
export default function Snapshot() {
|
||||
const dispatch = useAppDispatch();
|
||||
const snapshotDate = useAppSelector(selectSnapshotDate);
|
||||
|
||||
const useLatest = useAppSelector(selectUseLatest);
|
||||
return (
|
||||
<>
|
||||
|
|
@ -31,8 +33,8 @@ export default function Snapshot() {
|
|||
id="use latest snapshot radio"
|
||||
ouiaId="use-latest-snapshot-radio"
|
||||
name="use-latest-snapshot"
|
||||
label="Use latest content"
|
||||
description="Use the newest repository state available when building this image."
|
||||
label="Disable repeatable build."
|
||||
description="Use the newest repository content available when building this image."
|
||||
isChecked={useLatest}
|
||||
onChange={() => !useLatest && dispatch(changeUseLatest(true))}
|
||||
/>
|
||||
|
|
@ -40,8 +42,8 @@ export default function Snapshot() {
|
|||
id="use snapshot date radio"
|
||||
ouiaId="use-snapshot-date-radio"
|
||||
name="use-snapshot-date"
|
||||
label="Use a snapshot"
|
||||
description="Target a date and build images with repository information from this date."
|
||||
label="Enable repeatable build"
|
||||
description="Build this image with the repository content of a selected date."
|
||||
isChecked={!useLatest}
|
||||
onChange={() => useLatest && dispatch(changeUseLatest(false))}
|
||||
/>
|
||||
|
|
@ -85,9 +87,17 @@ export default function Snapshot() {
|
|||
]}
|
||||
onChange={(_, val) => dispatch(changeSnapshotDate(val))}
|
||||
/>
|
||||
|
||||
<Button
|
||||
variant="link"
|
||||
onClick={() => dispatch(changeSnapshotDate(''))}
|
||||
onClick={async () => {
|
||||
//Patternfly DatePicker seems to only clear error text if value is reset to '',
|
||||
// if you have an invalid date (2000-01-010000) and try to reset it, it must be set to '' first
|
||||
dispatch(changeSnapshotDate(''));
|
||||
setTimeout(() => {
|
||||
dispatch(changeSnapshotDate(yyyyMMddFormat(new Date())));
|
||||
}, 1);
|
||||
}}
|
||||
>
|
||||
Reset
|
||||
</Button>
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ export default function SnapshotStep() {
|
|||
return (
|
||||
<Form>
|
||||
<Title headingLevel="h1" size="xl">
|
||||
Repository snapshot
|
||||
Repeatable build
|
||||
</Title>
|
||||
<Grid>
|
||||
<Text>
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ import type {
|
|||
import type { V1ListSourceResponseItem } from '../Components/CreateImageWizard/types';
|
||||
import { generateDefaultName } from '../Components/CreateImageWizard/utilities/useGenerateDefaultName';
|
||||
import { RHEL_9, X86_64 } from '../constants';
|
||||
import { yyyyMMddFormat } from '../Utilities/time';
|
||||
|
||||
import type { RootState } from '.';
|
||||
|
||||
|
|
@ -737,13 +738,17 @@ export const wizardSlice = createSlice({
|
|||
}
|
||||
},
|
||||
changeUseLatest: (state, action: PayloadAction<boolean>) => {
|
||||
if (!action.payload && state.snapshotting.snapshotDate === '') {
|
||||
state.snapshotting.snapshotDate = yyyyMMddFormat(new Date());
|
||||
}
|
||||
|
||||
state.snapshotting.useLatest = action.payload;
|
||||
},
|
||||
changeSnapshotDate: (state, action: PayloadAction<string>) => {
|
||||
const yyyyMMDDRegex = /^\d{4}-\d{2}-\d{2}$/;
|
||||
const date = new Date(action.payload);
|
||||
if (action.payload === '') {
|
||||
state.snapshotting.snapshotDate = action.payload;
|
||||
state.snapshotting.snapshotDate = '';
|
||||
} else if (yyyyMMDDRegex.test(action.payload) && !isNaN(date.getTime())) {
|
||||
state.snapshotting.snapshotDate = date.toISOString();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -427,7 +427,7 @@ describe('Import modal', () => {
|
|||
});
|
||||
expect(sizeValue).toBeInTheDocument();
|
||||
|
||||
// Repository snapshot
|
||||
// Repository snapshot/Repeatable builds
|
||||
await clickNext();
|
||||
|
||||
// Custom Repos step
|
||||
|
|
|
|||
|
|
@ -81,7 +81,7 @@ describe('Create Image Wizard', () => {
|
|||
if (!process.env.IS_ON_PREMISE) {
|
||||
await screen.findByRole('button', { name: 'Register' });
|
||||
await screen.findByRole('button', { name: 'OpenSCAP' });
|
||||
await screen.findByRole('button', { name: 'Repository snapshot' });
|
||||
await screen.findByRole('button', { name: 'Repeatable build' });
|
||||
await screen.findByRole('button', { name: 'Custom repositories' });
|
||||
await screen.findByRole('button', {
|
||||
name: 'First boot script configuration',
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ import {
|
|||
export const goToDetailsStep = async () => {
|
||||
await clickNext(); // OpenSCAP
|
||||
await clickNext(); // File system configuration
|
||||
await clickNext(); // Repository snapshot
|
||||
await clickNext(); // Repository snapshot/Repeatable builds
|
||||
await clickNext(); // Custom repositories
|
||||
await clickNext(); // Additional packages
|
||||
await clickNext(); // Users
|
||||
|
|
|
|||
|
|
@ -105,7 +105,7 @@ const changePartitionUnitsToMiB = async () => {
|
|||
|
||||
const goToReviewStep = async () => {
|
||||
await clickNext(); // File system configuration
|
||||
await clickNext(); // Repository snapshot
|
||||
await clickNext(); // Repository snapshot/Repeatable builds
|
||||
await clickNext(); // Custom repositories
|
||||
await clickNext(); // Additional packages
|
||||
await clickNext(); // Users
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ const goToFirstBootStep = async (): Promise<void> => {
|
|||
await clickRegisterLater();
|
||||
await clickNext(); // OpenSCAP
|
||||
await clickNext(); // File system configuration
|
||||
await clickNext(); // Repository snapshot
|
||||
await clickNext(); // Repository snapshot/Repeatable builds
|
||||
await clickNext(); // Custom repositories
|
||||
await clickNext(); // Additional packages
|
||||
await clickNext(); // Users
|
||||
|
|
@ -69,7 +69,7 @@ const selectSimplifiedOscapProfile = async () => {
|
|||
|
||||
const goFromOscapToFirstBoot = async () => {
|
||||
await clickNext(); // File system configuration
|
||||
await clickNext(); // Repository snapshot
|
||||
await clickNext(); // Repository snapshot/Repeatable builds
|
||||
await clickNext(); // Custom repositories
|
||||
await clickNext(); // Additional packages
|
||||
await clickNext(); // Users
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ const goToPackagesStep = async () => {
|
|||
await clickRegisterLater();
|
||||
await clickNext(); // OpenSCAP
|
||||
await clickNext(); // File system configuration
|
||||
await clickNext(); // Repository snapshot
|
||||
await clickNext(); // Repository snapshot/Repeatable builds
|
||||
await clickNext(); // Custom repositories
|
||||
await clickNext(); // Additional packages
|
||||
};
|
||||
|
|
|
|||
|
|
@ -92,7 +92,7 @@ const goToReviewStep = async () => {
|
|||
await clickNext(); // Registration
|
||||
await clickNext(); // OpenSCAP
|
||||
await clickNext(); // File system configuration
|
||||
await clickNext(); // Repository snapshot
|
||||
await clickNext(); // Repository snapshot/Repeatable builds
|
||||
await clickNext(); // Custom repositories
|
||||
await clickNext(); // Additional packages
|
||||
await clickNext(); // Users
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ const goToRepositoriesStep = async () => {
|
|||
await clickRegisterLater();
|
||||
await clickNext(); // OpenSCAP
|
||||
await clickNext(); // File system configuration
|
||||
await clickNext(); // Repository snapshot
|
||||
await clickNext(); // Repository snapshot/Repeatable builds
|
||||
await clickNext(); // Custom repositories
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ const handleRegistration = async () => {
|
|||
const goToReviewStep = async () => {
|
||||
await clickNext(); // OpenSCAP
|
||||
await clickNext(); // File system configuration
|
||||
await clickNext(); // Repository snapshot
|
||||
await clickNext(); // Repository snapshot/Repeatable builds
|
||||
await clickNext(); // Custom repositories
|
||||
await clickNext(); // Additional packages
|
||||
await clickNext(); // Users
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ import { userEvent } from '@testing-library/user-event';
|
|||
|
||||
import { CREATE_BLUEPRINT, EDIT_BLUEPRINT } from '../../../../../constants';
|
||||
import { CreateBlueprintRequest } from '../../../../../store/imageBuilderApi';
|
||||
import { yyyyMMddFormat } from '../../../../../Utilities/time';
|
||||
import { mockBlueprintIds } from '../../../../fixtures/blueprints';
|
||||
import {
|
||||
expectedCustomRepositories,
|
||||
|
|
@ -84,7 +85,7 @@ const clickBulkSelect = async () => {
|
|||
const selectUseSnapshot = async () => {
|
||||
const user = userEvent.setup();
|
||||
const snapshotRadio = await screen.findByRole('radio', {
|
||||
name: /Use a snapshot/i,
|
||||
name: /Enable repeatable build/i,
|
||||
});
|
||||
await waitFor(async () => user.click(snapshotRadio));
|
||||
};
|
||||
|
|
@ -94,9 +95,17 @@ const updateDatePickerWithValue = async (date: string) => {
|
|||
const dateTextbox = await screen.findByRole('textbox', {
|
||||
name: /Date picker/i,
|
||||
});
|
||||
await waitFor(async () => user.clear(dateTextbox));
|
||||
await waitFor(async () => user.type(dateTextbox, date));
|
||||
};
|
||||
|
||||
const datePickerValue = async () => {
|
||||
const dateTextbox = await screen.findByRole('textbox', {
|
||||
name: /Date picker/i,
|
||||
});
|
||||
return (dateTextbox as HTMLInputElement).value;
|
||||
};
|
||||
|
||||
const clickContentDropdown = async () => {
|
||||
const user = userEvent.setup();
|
||||
const contentExpandable = await screen.findByTestId('content-expandable');
|
||||
|
|
@ -143,6 +152,7 @@ describe('repository snapshot tab - ', () => {
|
|||
await goToSnapshotStep();
|
||||
await selectUseSnapshot();
|
||||
await updateDatePickerWithValue('2024-04-22');
|
||||
|
||||
await clickNext(); // To repositories step
|
||||
await selectFirstRepository();
|
||||
await goToReviewStep();
|
||||
|
|
@ -222,12 +232,14 @@ describe('repository snapshot tab - ', () => {
|
|||
await waitFor(() => {
|
||||
expect(nextBtn).toHaveAttribute('aria-disabled', 'false');
|
||||
});
|
||||
// Check the Next button is disabled after resetting the date
|
||||
// reset fills in the current date, so it should not be disabled
|
||||
await clickReset();
|
||||
await waitFor(() => {
|
||||
expect(nextBtn).toHaveAttribute('aria-disabled', 'true');
|
||||
expect(nextBtn).toHaveAttribute('aria-disabled', 'false');
|
||||
});
|
||||
await screen.findByText(/Date cannot be blank/i);
|
||||
|
||||
const dateStr = yyyyMMddFormat(new Date());
|
||||
expect(await datePickerValue()).toBe(dateStr);
|
||||
});
|
||||
|
||||
test('select using bulk select works ', async () => {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue