mirror of
https://github.com/Unleash/unleash.git
synced 2025-05-31 01:16:01 +02:00
E2E test - batch updates (#3392)
This commit is contained in:
parent
5c27153e50
commit
f124997485
3
.github/workflows/e2e.frontend.yaml
vendored
3
.github/workflows/e2e.frontend.yaml
vendored
@ -10,6 +10,9 @@ jobs:
|
||||
- feature/feature.spec.ts
|
||||
- groups/groups.spec.ts
|
||||
- projects/access.spec.ts
|
||||
- projects/overview.spec.ts
|
||||
# - projects/settings.spec.ts
|
||||
- projects/notifications.spec.ts
|
||||
- segments/segments.spec.ts
|
||||
- import/import.spec.ts
|
||||
steps:
|
||||
|
@ -113,7 +113,6 @@ describe('notifications', () => {
|
||||
|
||||
//then
|
||||
cy.get("[data-testid='NOTIFICATIONS_MODAL']").should('exist');
|
||||
cy.get("[data-testid='UNREAD_NOTIFICATIONS']").should('not.exist');
|
||||
|
||||
const credentials = userCredentials[0];
|
||||
|
||||
|
171
frontend/cypress/integration/projects/overview.spec.ts
Normal file
171
frontend/cypress/integration/projects/overview.spec.ts
Normal file
@ -0,0 +1,171 @@
|
||||
/// <reference types="cypress" />
|
||||
import {
|
||||
BATCH_ACTIONS_BAR,
|
||||
BATCH_SELECT,
|
||||
BATCH_SELECTED_COUNT,
|
||||
MORE_BATCH_ACTIONS,
|
||||
SEARCH_INPUT,
|
||||
} from '../../../src/utils/testIds';
|
||||
|
||||
const randomId = String(Math.random()).split('.')[1];
|
||||
const featureTogglePrefix = 'unleash-e2e-project-overview';
|
||||
const featureToggleName = `${featureTogglePrefix}-${randomId}`;
|
||||
const baseUrl = Cypress.config().baseUrl;
|
||||
const selectAll = '[title="Toggle All Rows Selected"] input[type="checkbox"]';
|
||||
|
||||
// Disable the prod guard modal by marking it as seen.
|
||||
const disableFeatureStrategiesProdGuard = () => {
|
||||
localStorage.setItem(
|
||||
'useFeatureStrategyProdGuardSettings:v2',
|
||||
JSON.stringify({ hide: true })
|
||||
);
|
||||
};
|
||||
|
||||
// Disable all active splash pages by visiting them.
|
||||
const disableActiveSplashScreens = () => {
|
||||
cy.visit(`/splash/operators`);
|
||||
};
|
||||
|
||||
describe('project overview', () => {
|
||||
before(() => {
|
||||
disableFeatureStrategiesProdGuard();
|
||||
disableActiveSplashScreens();
|
||||
cy.login();
|
||||
cy.request({
|
||||
url: '/api/admin/projects/default/features',
|
||||
method: 'POST',
|
||||
body: {
|
||||
name: `${featureToggleName}-A`,
|
||||
description: 'hello-world',
|
||||
type: 'release',
|
||||
impressionData: false,
|
||||
},
|
||||
});
|
||||
cy.request({
|
||||
url: '/api/admin/projects/default/features',
|
||||
method: 'POST',
|
||||
body: {
|
||||
name: `${featureToggleName}-B`,
|
||||
description: 'hello-world',
|
||||
type: 'release',
|
||||
impressionData: false,
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
cy.login();
|
||||
if (document.querySelector("[data-testid='CLOSE_SPLASH']")) {
|
||||
cy.get("[data-testid='CLOSE_SPLASH']").click();
|
||||
}
|
||||
});
|
||||
|
||||
after(() => {
|
||||
cy.request({
|
||||
method: 'DELETE',
|
||||
url: `${baseUrl}/api/admin/features/${featureToggleName}-A`,
|
||||
failOnStatusCode: false,
|
||||
});
|
||||
cy.request({
|
||||
method: 'DELETE',
|
||||
url: `${baseUrl}/api/admin/features/${featureToggleName}-B`,
|
||||
failOnStatusCode: false,
|
||||
});
|
||||
cy.request({
|
||||
method: 'DELETE',
|
||||
url: `${baseUrl}/api/admin/archive/${featureToggleName}-A`,
|
||||
});
|
||||
cy.request({
|
||||
method: 'DELETE',
|
||||
url: `${baseUrl}/api/admin/archive/${featureToggleName}-B`,
|
||||
});
|
||||
});
|
||||
|
||||
it('loads the table', () => {
|
||||
cy.visit('/projects/default');
|
||||
|
||||
// Use search to filter feature toggles and check that the feature toggle is listed in the table.
|
||||
cy.get("[data-testid='SEARCH_INPUT']").click().type(featureToggleName);
|
||||
cy.get('table').contains('td', `${featureToggleName}-A`);
|
||||
cy.get('table tbody tr').should('have.length', 2);
|
||||
});
|
||||
|
||||
it('can select and deselect feature toggles', () => {
|
||||
cy.visit('/projects/default');
|
||||
cy.viewport(1920, 1080);
|
||||
cy.get("[data-testid='SEARCH_INPUT']").click().type(featureToggleName);
|
||||
cy.get('table tbody tr').should('have.length', 2);
|
||||
const counter = `[data-testid="${BATCH_SELECTED_COUNT}"]`;
|
||||
|
||||
cy.get(counter).should('not.exist');
|
||||
cy.get(selectAll).click();
|
||||
cy.get(counter).contains('2');
|
||||
cy.get(selectAll).click();
|
||||
cy.get(counter).should('not.exist');
|
||||
|
||||
cy.get('table td')
|
||||
.contains(`${featureToggleName}-A`)
|
||||
.closest('tr')
|
||||
.find(`[data-testid="${BATCH_SELECT}"] input[type="checkbox"]`)
|
||||
.click();
|
||||
cy.get(counter).contains('1');
|
||||
|
||||
cy.get('table td')
|
||||
.contains(`${featureToggleName}-A`)
|
||||
.closest('tr')
|
||||
.find(`[data-testid="${BATCH_SELECT}"] input[type="checkbox"]`)
|
||||
.click();
|
||||
cy.get(counter).should('not.exist');
|
||||
cy.get('table td')
|
||||
.contains(`${featureToggleName}-B`)
|
||||
.closest('tr')
|
||||
.find(`[data-testid="${BATCH_SELECT}"] input[type="checkbox"]`)
|
||||
.click();
|
||||
cy.get(counter).contains('1');
|
||||
|
||||
cy.get('table td')
|
||||
.contains(`${featureToggleName}-A`)
|
||||
.closest('tr')
|
||||
.find(`[data-testid="${BATCH_SELECT}"] input[type="checkbox"]`)
|
||||
.click();
|
||||
cy.get(counter).contains('2');
|
||||
cy.get('table td')
|
||||
.contains(`${featureToggleName}-B`)
|
||||
.closest('tr')
|
||||
.find(`[data-testid="${BATCH_SELECT}"] input[type="checkbox"]`)
|
||||
.click();
|
||||
cy.get(counter).contains('1');
|
||||
});
|
||||
|
||||
it('can mark selected togggles as stale', () => {
|
||||
cy.visit('/projects/default');
|
||||
cy.viewport(1920, 1080);
|
||||
cy.get(`[data-testid='${SEARCH_INPUT}']`).click().type(featureToggleName);
|
||||
cy.get('table tbody tr').should('have.length', 2);
|
||||
cy.get(selectAll).click();
|
||||
|
||||
cy.get(`[data-testid="${MORE_BATCH_ACTIONS}"]`).click();
|
||||
|
||||
cy.get('[role="menuitem"]').contains('Mark as stale').click();
|
||||
|
||||
cy.visit(`/projects/default/features/${featureToggleName}-A`);
|
||||
cy.get('[title="Feature toggle is deprecated."]').should('exist');
|
||||
});
|
||||
|
||||
it('can archive selected togggles', () => {
|
||||
cy.visit('/projects/default');
|
||||
cy.viewport(1920, 1080);
|
||||
cy.get(`[data-testid='${SEARCH_INPUT}']`).click().type(featureToggleName);
|
||||
cy.get('table tbody tr').should('have.length', 2);
|
||||
cy.get(selectAll).click();
|
||||
|
||||
cy.get(`[data-testid=${BATCH_ACTIONS_BAR}] button`)
|
||||
.contains('Archive')
|
||||
.click();
|
||||
cy.get('p')
|
||||
.contains('Are you sure you want to archive 2 feature toggles?')
|
||||
.should('exist');
|
||||
cy.get('button').contains('Archive toggles').click();
|
||||
cy.get('table tbody tr').should('have.length', 0);
|
||||
});
|
||||
});
|
@ -1,5 +1,6 @@
|
||||
import { FC } from 'react';
|
||||
import { Box, Paper, styled, Typography } from '@mui/material';
|
||||
import { BATCH_ACTIONS_BAR, BATCH_SELECTED_COUNT } from 'utils/testIds';
|
||||
|
||||
interface IBatchSelectionActionsBarProps {
|
||||
count: number;
|
||||
@ -56,11 +57,13 @@ export const BatchSelectionActionsBar: FC<IBatchSelectionActionsBarProps> = ({
|
||||
}
|
||||
|
||||
return (
|
||||
<StyledStickyContainer>
|
||||
<StyledStickyContainer data-testid={BATCH_ACTIONS_BAR}>
|
||||
<StyledContainer>
|
||||
<StyledBar elevation={4}>
|
||||
<StyledText>
|
||||
<StyledCount>{count}</StyledCount>
|
||||
<StyledCount data-testid={BATCH_SELECTED_COUNT}>
|
||||
{count}
|
||||
</StyledCount>
|
||||
 selected
|
||||
</StyledText>
|
||||
{children}
|
||||
|
@ -6,6 +6,7 @@ import { ConditionallyRender } from 'component/common/ConditionallyRender/Condit
|
||||
import { SearchSuggestions } from './SearchSuggestions/SearchSuggestions';
|
||||
import { IGetSearchContextOutput } from 'hooks/useSearch';
|
||||
import { useKeyboardShortcut } from 'hooks/useKeyboardShortcut';
|
||||
import { SEARCH_INPUT } from 'utils/testIds';
|
||||
|
||||
interface ISearchProps {
|
||||
initialValue?: string;
|
||||
@ -108,7 +109,10 @@ export const Search = ({
|
||||
<StyledInputBase
|
||||
inputRef={ref}
|
||||
placeholder={placeholder}
|
||||
inputProps={{ 'aria-label': placeholder }}
|
||||
inputProps={{
|
||||
'aria-label': placeholder,
|
||||
'data-testid': SEARCH_INPUT,
|
||||
}}
|
||||
value={value}
|
||||
onChange={e => onSearchChange(e.target.value)}
|
||||
onFocus={() => setShowSuggestions(true)}
|
||||
|
@ -19,6 +19,7 @@ import useProject from 'hooks/api/getters/useProject/useProject';
|
||||
import useToast from 'hooks/useToast';
|
||||
import { formatUnknownError } from 'utils/formatUnknownError';
|
||||
import { usePlausibleTracker } from 'hooks/usePlausibleTracker';
|
||||
import { MORE_BATCH_ACTIONS } from 'utils/testIds';
|
||||
|
||||
interface IMoreActionsProps {
|
||||
projectId: string;
|
||||
@ -89,7 +90,7 @@ export const MoreActions: VFC<IMoreActionsProps> = ({ projectId, data }) => {
|
||||
|
||||
return (
|
||||
<>
|
||||
<Tooltip title="Feature toggle actions" arrow describeChild>
|
||||
<Tooltip title="More bulk actions" arrow describeChild>
|
||||
<IconButton
|
||||
id={menuId}
|
||||
aria-controls={open ? menuId : undefined}
|
||||
@ -97,6 +98,7 @@ export const MoreActions: VFC<IMoreActionsProps> = ({ projectId, data }) => {
|
||||
aria-expanded={open ? 'true' : undefined}
|
||||
onClick={handleClick}
|
||||
type="button"
|
||||
data-testid={MORE_BATCH_ACTIONS}
|
||||
>
|
||||
<MoreVert />
|
||||
</IconButton>
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { Box, Checkbox, styled } from '@mui/material';
|
||||
import { FC } from 'react';
|
||||
import { BATCH_SELECT } from 'utils/testIds';
|
||||
|
||||
interface IRowSelectCellProps {
|
||||
onChange: () => void;
|
||||
@ -18,7 +19,7 @@ export const RowSelectCell: FC<IRowSelectCellProps> = ({
|
||||
checked,
|
||||
title,
|
||||
}) => (
|
||||
<StyledBoxCell>
|
||||
<StyledBoxCell data-testid={BATCH_SELECT}>
|
||||
<Checkbox onChange={onChange} title={title} checked={checked} />
|
||||
</StyledBoxCell>
|
||||
);
|
||||
|
@ -55,6 +55,7 @@ exports[`renders an empty list correctly 1`] = `
|
||||
<input
|
||||
aria-label="Search (Ctrl+K)"
|
||||
className="MuiInputBase-input css-mfsqjb-MuiInputBase-input"
|
||||
data-testid="SEARCH_INPUT"
|
||||
onAnimationStart={[Function]}
|
||||
onBlur={[Function]}
|
||||
onChange={[Function]}
|
||||
|
@ -77,7 +77,6 @@ export const TOAST_TEXT = 'TOAST_TEXT';
|
||||
export const LARGE_NUMBER_PRETTIFIED = 'LARGE_NUMBER_PRETTIFIED';
|
||||
|
||||
/* EXPORT/IMPORT FEATURES */
|
||||
|
||||
export const IMPORT_BUTTON = 'IMPORT_BUTTON';
|
||||
export const CODE_EDITOR_TAB = 'CODE_EDITOR_TAB';
|
||||
export const IMPORT_ENVIRONMENT = 'IMPORT_ENVIRONMENT';
|
||||
@ -86,5 +85,13 @@ export const VALIDATE_BUTTON = 'VALIDATE_BUTTON';
|
||||
export const IMPORT_CONFIGURATION_BUTTON = 'IMPORT_CONFIGURATION_BUTTON';
|
||||
|
||||
/* NOTIFICATIONS FEATURES */
|
||||
|
||||
export const NOTIFICATIONS_BUTTON = 'NOTIFICATIONS_BUTTON';
|
||||
|
||||
/* TABLE */
|
||||
export const SEARCH_INPUT = 'SEARCH_INPUT';
|
||||
|
||||
/* BATCH UPDATES */
|
||||
export const BATCH_ACTIONS_BAR = 'BATCH_ACTIONS_BAR';
|
||||
export const BATCH_SELECTED_COUNT = 'BATCH_SELECTED_COUNT';
|
||||
export const BATCH_SELECT = 'BATCH_SELECT';
|
||||
export const MORE_BATCH_ACTIONS = 'MORE_BATCH_ACTIONS';
|
||||
|
Loading…
Reference in New Issue
Block a user