Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test(pf5): fix broken tests after PF5 upgrades #1347

Merged
merged 27 commits into from
Sep 13, 2024
Merged
Show file tree
Hide file tree
Changes from 25 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
879b2dc
chore: update snapshots
tthvo Sep 9, 2024
42c1870
chore:apply prettier
tthvo Sep 9, 2024
6a58fdf
test: fix broken dashboard itest
tthvo Sep 9, 2024
8217654
fix: fix broken About tests
tthvo Sep 9, 2024
65fa404
fix: fix broken Agent template action menu & fix broken tests
tthvo Sep 9, 2024
1b488a1
fix: fix broken AgentLiveProbe tests
tthvo Sep 9, 2024
a2f5db6
fix: fix broken Events tests
tthvo Sep 9, 2024
d341fd8
fix: fix broken Rule tests
tthvo Sep 10, 2024
50cb194
chore: apply eslint
tthvo Sep 10, 2024
71f1a8c
Fix dashboard itest (#92)
maxcao13 Sep 10, 2024
e79f101
fix: fix broken TargetView tests
tthvo Sep 10, 2024
ab69956
fix: fix broken recording itest
tthvo Sep 10, 2024
0477781
fix: fix broke Setting tests
tthvo Sep 10, 2024
db007da
fix: fix broken datetime picker tests
tthvo Sep 10, 2024
8fb7bf9
fix: fix broken RecordingMetadata tests
tthvo Sep 10, 2024
bf7a91c
fix: fix broken Archive tests
tthvo Sep 11, 2024
fa57316
fixup: fix broken archives snapshot tests
tthvo Sep 11, 2024
45ceb38
fix: fix broken recording tests (filters excluded)
tthvo Sep 11, 2024
29668a9
fix: more snapshot test fixes (dashboard)
tthvo Sep 11, 2024
24f57ba
fix: more tests fixed for automated analysis
tthvo Sep 11, 2024
ab393d9
fix: fixes for all dashboard tests
tthvo Sep 11, 2024
1a4d2d8
fix: some fixes for recording filter tests
tthvo Sep 11, 2024
db1e9ce
fix: fix Duration filter tests
tthvo Sep 11, 2024
99c331d
fix: fix remaining tests
tthvo Sep 11, 2024
8b93b4b
chore: apply eslint
tthvo Sep 12, 2024
aa958ec
chore: remove unused components
tthvo Sep 12, 2024
53ad3fb
chore: remove unused tests
tthvo Sep 12, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion TESTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ In order to render the component under test into its HTML DOM representation and

* To search for a localized text, for example, with `getByText`, use `testTranslate` function from `@test/Common.tsx` to return a translated text. Tests are configued to use `en` locale as default.

* If any of the test codes cause the changes in React states (e.g. open/close a action menu or modal), wrap them in [`act`](https://testing-library.com/docs/react-testing-library/api/#act) function, imported from `@testing-library/react`. The `act` function allows flushing all pending state changes.

## MOCKING

### Overview
Expand Down Expand Up @@ -83,6 +85,8 @@ Where the `-u` flag tells Jest to update the snapshot and the `-t` flag specifie

* Some PatternFly components use random, dynamic strings as `ids` which will then be displayed as elements in the rendered React virtual DOM. These strings change upon every render, causing snapshots to fail even though the component under test is still functionally the same. This can be remedied by supplying [custom `ids` as props](https://github.com/patternfly/patternfly-react/issues/3518) to the culprit PatternFly child components inside the source file of the component under test.

* Since `react-test-renderer` does not support the use of `ref` (see [reference](https://github.com/facebook/react/issues/7740)), the tests might fail if any third-party codes use `ref` unsafely (without checking `null`). To workaround that, use [`createNodeMock`](https://legacy.reactjs.org/docs/test-renderer.html#ideas) to construct a mock `ref` when calling `renderSnapshot`.


## INTEGRATION TESTING

Expand All @@ -107,6 +111,7 @@ This will automatically start a Mirage dev server, run the integration tests on

### Tips
* Running the integration tests will open a Firefox browser and simulate any actions that you instruct the browser to perform. That means we must first navigate to the local Cryostat Web page, before performing any useful testing.

* In our `beforeAll` jest declaration, we setup our web driver with the [default configurations](src/itest/util.ts)), and then use that driver to create our first **Page Object**. A Page Object is an abstraction that acts as an interface to your web pages. For more info on the **Page Object Model** in Selenium, see https://www.selenium.dev/documentation/test_practices/encouraged/page_object_models/.
```ts
beforeAll(async function () {
Expand Down Expand Up @@ -135,4 +140,4 @@ Add more methods to each PO, to test more actions. The point is, we want to abst
In the code, we first tell the driver to wait, until an element is located by the css selector ('button[data-action="skip"]'), and assign it to a variable. If not found, we assign null. Then if the variable is non-null, we click it. To find a good query to use, it is recommended to use the [Selenium IDE](https://addons.mozilla.org/en-CA/firefox/addon/selenium-ide/) extension on your browser. The extension allows you to easily see queries that can be used to select an element you want.
* Integration tests are found in [src/itest](src/itest).
* All code is asynchronous which entails the use of the `async/await` pattern.
* Follow the Selenium testing practices when writing integration tests: https://www.selenium.dev/documentation/test_practices/.
* Follow the Selenium testing practices when writing integration tests: https://www.selenium.dev/documentation/test_practices/.
4 changes: 3 additions & 1 deletion jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,9 @@ module.exports = {

// An array of regexp pattern strings that are matched against all source file paths before transformation.
// If the file path matches any of the patterns, it will not be transformed.
transformIgnorePatterns: ["/node_modules/(?!@patternfly)"],
transformIgnorePatterns: [
"/node_modules/(?!@patternfly|d3|d3-array|internmap|delaunator|robust-predicates)",
],

roots: ['<rootDir>/src']
};
38 changes: 34 additions & 4 deletions locales/en/public.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@
}
},
"AgentProbeTemplates": {
"ARIA_LABELS": {
"ROW_ACTION": "agent-probe-template-action-menu",
"SEARCH_INPUT": "agent-probe-template-search"
},
"SEARCH_PLACEHOLDER": "Find by name or XML content..."
},
"AllArchivedRecordingsTable": {
Expand Down Expand Up @@ -345,9 +349,15 @@
"EVENT_TEMPLATES": "Error retrieving Event Templates"
},
"EventTemplates": {
"ARIA_LABELS": {
"SEARCH_INPUT": "event-template-search-input"
},
"SEARCH_PLACEHOLDER": "Find by name, description, or provider..."
},
"EventTypes": {
"ARIA_LABELS": {
"SEARCH_INPUT": "event-type-search-input"
},
"SEARCH_PLACEHOLDER": "Find by name, description, typeId, or description..."
},
"ImportCertificate": {
Expand Down Expand Up @@ -416,7 +426,15 @@
"TITLE": "Quick starts"
}
},
"RecordingActions": {
"ARIA_LABELS": {
"MENU_TOGGLE": "recording-action-toggle"
}
},
"RecordingFilters": {
"ARIA_LABELS": {
"MENU_TOGGLE": "recording-filters-toggle"
},
"FILTER_CHIP": {
"DURATION_CONTINUOUS": "Continuous",
"DURATION_EXACT": "{{value}}{{unit}}",
Expand All @@ -437,6 +455,13 @@
"RecordingsTable": {
"NO_ARCHIVES": "No Archived Recordings"
},
"RecordingStateFilter": {
"ARIA_LABELS": {
"MENU_TOGGLE": "recording-state-toggle",
"SELECT": "select-by-state"
},
"FILTER_BY_STATE": "Filter by state"
},
"RuleDeleteWarningModal": {
"CLEAN_DESCRIPTION": "Clean will stop any Active Recordings that {{ruleName}} created."
},
Expand Down Expand Up @@ -495,7 +520,8 @@
},
"DATETIME_CONTROL": {
"ARIA_LABELS": {
"LOCALE_SELECT": "Select a datetime locale"
"LOCALE_SELECT": "Select a datetime locale",
"MENU_TOGGLE": "datetime-locale-setting-toggle"
},
"DESCRIPTION": "",
"LOCALE_SELECT_DESCRIPTION": "Select current date locale.",
Expand All @@ -513,11 +539,13 @@
"BETA_DESCRIPTION": "Experimental features",
"DESCRIPTION": "Control which graphical features appear in the application.",
"DEVELOPMENT_DESCRIPTION": "Under development features",
"MENU_TOGGLE": "feature-level-setting-toggle",
"PRODUCTION_DESCRIPTION": "Stable production-ready features",
"TITLE": "Feature level"
},
"LANGUAGE": {
"ARIA_LABELS": {
"MENU_TOGGLE": "language-setting-toggle",
"SELECT": "Select a language"
},
"DESCRIPTION": "Set the current language for web console.",
Expand All @@ -531,13 +559,14 @@
"TITLE": "Notifications"
},
"THEME": {
"ARIA_LABELS": {
"MENU_TOGGLE": "theme-setting-toggle",
"SELECT": "Select a theme"
},
"AUTO": "Auto",
"DARK": "Dark",
"DESCRIPTION": "Set the current theme for web console.",
"LIGHT": "Light",
"SELECT": {
"LABEL": "Select a theme"
},
"TITLE": "Theme"
},
"WEBSOCKET_CONNECTION_DEBOUNCE": {
Expand Down Expand Up @@ -608,6 +637,7 @@
},
"TimezonePicker": {
"ARIA_LABELS": {
"MENU_TOGGLE": "timezone-select-toggle",
"SELECT": "Select a timezone",
"TYPE_AHEAD": "Search a timezone"
},
Expand Down
64 changes: 41 additions & 23 deletions src/app/Agent/AgentProbeTemplates.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ import {
ModalVariant,
Stack,
StackItem,
TextInput,
Toolbar,
ToolbarContent,
ToolbarGroup,
Expand All @@ -45,6 +44,8 @@ import {
DropdownList,
MenuToggleElement,
MenuToggle,
SearchInput,
Divider,
} from '@patternfly/react-core';
import { SearchIcon, EllipsisVIcon, UploadIcon } from '@patternfly/react-icons';
import {
Expand Down Expand Up @@ -291,7 +292,7 @@ export const AgentProbeTemplates: React.FC<AgentProbeTemplatesProps> = ({ agentD
} else {
return (
<>
<Stack hasGutter style={{ marginTop: '1em', marginBottom: '1.5em' }}>
<Stack hasGutter style={{ marginTop: '1em' }}>
<StackItem>
<AboutAgentCard />
</StackItem>
Expand All @@ -300,13 +301,13 @@ export const AgentProbeTemplates: React.FC<AgentProbeTemplatesProps> = ({ agentD
<ToolbarContent>
<ToolbarGroup variant="filter-group">
<ToolbarItem>
<TextInput
<SearchInput
style={{ minWidth: '30ch' }}
name="templateFilter"
id="templateFilter"
type="search"
placeholder={t('AgentProbeTemplates.SEARCH_PLACEHOLDER')}
aria-label="Probe Template filter"
aria-label={t('AgentProbeTemplates.ARIA_LABELS.SEARCH_INPUT')}
onChange={handleFilterTextChange}
value={filterText}
/>
Expand Down Expand Up @@ -339,7 +340,7 @@ export const AgentProbeTemplates: React.FC<AgentProbeTemplatesProps> = ({ agentD
))}
</Tr>
</Thead>
<Tbody>{...templateRows}</Tbody>
<Tbody>{templateRows}</Tbody>
</Table>
) : (
<EmptyState>
Expand All @@ -364,6 +365,7 @@ export interface AgentProbeTemplateUploadModalProps {
}

export const AgentProbeTemplateUploadModal: React.FC<AgentProbeTemplateUploadModalProps> = ({ onClose, isOpen }) => {
const { t } = useTranslation();
const addSubscription = useSubscriptions();
const context = React.useContext(ServiceContext);
const submitRef = React.useRef<HTMLDivElement>(null); // Use ref to refer to submit trigger div
Expand Down Expand Up @@ -476,7 +478,7 @@ export const AgentProbeTemplateUploadModal: React.FC<AgentProbeTemplateUploadMod
<ActionGroup>
{allOks && numOfFiles ? (
<Button variant="primary" onClick={handleClose}>
Close
{t('CLOSE', { ns: 'common' })}
</Button>
) : (
<>
Expand All @@ -486,10 +488,10 @@ export const AgentProbeTemplateUploadModal: React.FC<AgentProbeTemplateUploadMod
isDisabled={!numOfFiles || uploading}
{...submitButtonLoadingProps}
>
Submit
{t('SUBMIT', { ns: 'common' })}
</Button>
<Button variant="link" onClick={handleClose}>
Cancel
{t('CANCEL', { ns: 'common' })}
</Button>
</>
)}
Expand All @@ -506,6 +508,7 @@ export interface AgentTemplateActionProps {
}

export const AgentTemplateAction: React.FC<AgentTemplateActionProps> = ({ onInsert, onDelete, template }) => {
const { t } = useTranslation();
const [isOpen, setIsOpen] = React.useState(false);

const actionItems = React.useMemo(() => {
Expand All @@ -516,9 +519,13 @@ export const AgentTemplateAction: React.FC<AgentTemplateActionProps> = ({ onInse
onClick: () => onInsert && onInsert(template),
isDisabled: !onInsert,
},
{
isSeparator: true,
},
{
key: 'delete-template',
title: 'Delete',
isDanger: true,
onClick: () => onDelete(template),
},
];
Expand All @@ -528,32 +535,43 @@ export const AgentTemplateAction: React.FC<AgentTemplateActionProps> = ({ onInse

const dropdownItems = React.useMemo(
() =>
actionItems.map((action) => (
<DropdownItem
key={action.key}
onClick={() => {
setIsOpen(false);
action.onClick();
}}
isDisabled={action.isDisabled}
>
{action.title}
</DropdownItem>
)),
actionItems.map((action, idx) =>
action.isSeparator ? (
<Divider key={`separator-${idx}`} />
) : (
<DropdownItem
aria-label={action.key}
key={action.key}
onClick={() => {
setIsOpen(false);
action.onClick && action.onClick();
}}
isAriaDisabled={action.isDisabled}
isDanger={action.isDanger}
>
{action.title}
</DropdownItem>
),
),
[actionItems, setIsOpen],
);

return (
<Dropdown
isPlain
toggle={(toggleRef: React.Ref<MenuToggleElement>) => (
<MenuToggle ref={toggleRef} onClick={(event) => handleToggle(event, !isOpen)}>
<MenuToggle
aria-label={t('AgentProbeTemplates.ARIA_LABELS.ROW_ACTION')}
variant="plain"
ref={toggleRef}
onClick={(event) => handleToggle(event, !isOpen)}
>
<EllipsisVIcon />
</MenuToggle>
)}
onOpenChange={setIsOpen}
onOpenChangeKeys={['Escape']}
isOpen={isOpen}
popperProps={{
appendTo: document.body,
position: 'right',
enableFlip: true,
}}
Expand Down
1 change: 1 addition & 0 deletions src/app/AppLayout/AppLayout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -398,6 +398,7 @@ export const AppLayout: React.FC<AppLayoutProps> = ({ children }) => {
<ToolbarGroup variant="icon-button-group">
<ToolbarItem>
<NotificationBadge
id="notification-badge"
count={unreadNotificationsCount}
variant={
errorNotificationsCount > 0 ? 'attention' : unreadNotificationsCount === 0 ? 'read' : 'unread'
Expand Down
4 changes: 4 additions & 0 deletions src/app/CreateRecording/CustomRecordingForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -509,6 +509,8 @@ export const CustomRecordingForm: React.FC = () => {
toggleTextExpanded="Hide metadata options"
toggleTextCollapsed="Show metadata options"
data-quickstart-id="crf-metadata-opt"
toggleId="metadata-option-toggle"
contentId="metadata-options"
>
<FormGroup
label="Labels"
Expand Down Expand Up @@ -548,6 +550,8 @@ export const CustomRecordingForm: React.FC = () => {
toggleTextExpanded="Hide advanced options"
toggleTextCollapsed="Show advanced options"
data-quickstart-id="crf-advanced-opt"
toggleId="advanced-option-toggle"
contentId="advanced-options"
>
<Text component={TextVariants.small}>A value of 0 for maximum size or age means unbounded.</Text>
<FormGroup fieldId="To Disk">
Expand Down
5 changes: 4 additions & 1 deletion src/app/Dashboard/AddCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,7 @@ export const AddCard: React.FC<AddCardProps> = ({ variant }) => {
appendTo={() => document.getElementById('dashboard-catalog-btn-wrapper') || document.body}
>
<Button
id="dashboard-add-btn"
aria-label="Add card"
data-quickstart-id={'dashboard-add-btn'}
variant="plain"
Expand Down Expand Up @@ -248,6 +249,7 @@ export const AddCard: React.FC<AddCardProps> = ({ variant }) => {
!getCardDescriptorByTitle(selection, t).advancedConfig
? 'Finish'
: 'Next',
nextButtonProps: { id: 'card-props-config-next' },
}}
>
<Stack>
Expand All @@ -264,6 +266,7 @@ export const AddCard: React.FC<AddCardProps> = ({ variant }) => {
name="Configuration"
footer={{
nextButtonText: selection && !getCardDescriptorByTitle(selection, t).advancedConfig ? 'Finish' : 'Next',
nextButtonProps: { id: 'card-props-config-next' },
}}
isHidden={!selection || !getCardDescriptorByTitle(selection, t).propControls.length}
>
Expand All @@ -279,7 +282,7 @@ export const AddCard: React.FC<AddCardProps> = ({ variant }) => {
<WizardStep
id="card-adv-config"
name="Advanced Configuration"
footer={{ nextButtonText: 'Finish' }}
footer={{ nextButtonText: 'Finish', nextButtonProps: { id: 'card-props-config-next' } }}
isHidden={!selection || !getCardDescriptorByTitle(selection, t).advancedConfig}
>
<Title headingLevel="h5">Provide advanced configuration for the {selection} card</Title>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ export const ClickableAutomatedAnalysisLabel: React.FC<ClickableAutomatedAnalysi
const handleNonHoveredOrFocused = React.useCallback(() => setIsHoveredOrFocused(false), [setIsHoveredOrFocused]);

const alertStyle = {
custom: popoverStyles.modifiers.custom,
info: popoverStyles.modifiers.info,
success: popoverStyles.modifiers.success,
warning: popoverStyles.modifiers.warning,
Expand All @@ -60,7 +61,7 @@ export const ClickableAutomatedAnalysisLabel: React.FC<ClickableAutomatedAnalysi

const alertPopoverVariant = React.useMemo(() => {
return result.score == AutomatedAnalysisScore.NA_SCORE
? 'info'
? 'custom'
: result.score < AutomatedAnalysisScore.ORANGE_SCORE_THRESHOLD
? 'success'
: result.score < AutomatedAnalysisScore.RED_SCORE_THRESHOLD
Expand Down
Loading
Loading