mirror of
https://github.com/Unleash/unleash.git
synced 2025-01-20 00:08:02 +01:00
fix: announce navigation to screen readers (#911)
* refactor: unify page titles * refactor: update page title on navigation * refactor: add AnnouncerContext to test contexts * fix: announce navigation to screen readers
This commit is contained in:
parent
06232a5522
commit
f7266cde10
@ -8,7 +8,7 @@
|
|||||||
<meta name="cdnPrefix" content="::cdnPrefix::" />
|
<meta name="cdnPrefix" content="::cdnPrefix::" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
<meta name="description" content="unleash" />
|
<meta name="description" content="unleash" />
|
||||||
<title>Unleash - Enterprise ready feature toggles</title>
|
<title>Unleash</title>
|
||||||
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||||||
<link
|
<link
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import { render } from 'utils/testRenderer';
|
import { render } from 'utils/testRenderer';
|
||||||
import { AnnouncerProvider } from 'component/common/Announcer/AnnouncerProvider/AnnouncerProvider';
|
|
||||||
import { AnnouncerContext } from 'component/common/Announcer/AnnouncerContext/AnnouncerContext';
|
import { AnnouncerContext } from 'component/common/Announcer/AnnouncerContext/AnnouncerContext';
|
||||||
import { useContext, useEffect } from 'react';
|
import { useContext, useEffect } from 'react';
|
||||||
import { screen } from '@testing-library/react';
|
import { screen } from '@testing-library/react';
|
||||||
|
import { ANNOUNCER_ELEMENT_TEST_ID } from 'utils/testIds';
|
||||||
|
|
||||||
test('AnnouncerContext', async () => {
|
test('AnnouncerContext', async () => {
|
||||||
const TestComponent = () => {
|
const TestComponent = () => {
|
||||||
@ -16,12 +16,9 @@ test('AnnouncerContext', async () => {
|
|||||||
return null;
|
return null;
|
||||||
};
|
};
|
||||||
|
|
||||||
render(
|
render(<TestComponent />);
|
||||||
<AnnouncerProvider>
|
|
||||||
<TestComponent />
|
|
||||||
</AnnouncerProvider>
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(screen.getByRole('status')).not.toHaveTextContent('Foo');
|
const el = screen.getByTestId(ANNOUNCER_ELEMENT_TEST_ID);
|
||||||
expect(screen.getByRole('status')).toHaveTextContent('Bar');
|
expect(el).not.toHaveTextContent('Foo');
|
||||||
|
expect(el).toHaveTextContent('Bar');
|
||||||
});
|
});
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import React, { ReactElement } from 'react';
|
import React, { ReactElement } from 'react';
|
||||||
import { useStyles } from 'component/common/Announcer/AnnouncerElement/AnnouncerElement.styles';
|
import { useStyles } from 'component/common/Announcer/AnnouncerElement/AnnouncerElement.styles';
|
||||||
|
import { ANNOUNCER_ELEMENT_TEST_ID } from 'utils/testIds';
|
||||||
|
|
||||||
interface IAnnouncerElementProps {
|
interface IAnnouncerElementProps {
|
||||||
announcement?: string;
|
announcement?: string;
|
||||||
@ -16,6 +17,7 @@ export const AnnouncerElement = ({
|
|||||||
aria-live="polite"
|
aria-live="polite"
|
||||||
aria-atomic
|
aria-atomic
|
||||||
className={styles.container}
|
className={styles.container}
|
||||||
|
data-testid={ANNOUNCER_ELEMENT_TEST_ID}
|
||||||
>
|
>
|
||||||
{announcement}
|
{announcement}
|
||||||
</div>
|
</div>
|
||||||
|
@ -6,6 +6,7 @@ import { Typography } from '@material-ui/core';
|
|||||||
import ConditionallyRender from '../ConditionallyRender/ConditionallyRender';
|
import ConditionallyRender from '../ConditionallyRender/ConditionallyRender';
|
||||||
|
|
||||||
import { useStyles } from './styles';
|
import { useStyles } from './styles';
|
||||||
|
import { usePageTitle } from 'hooks/usePageTitle';
|
||||||
|
|
||||||
const HeaderTitle = ({
|
const HeaderTitle = ({
|
||||||
title,
|
title,
|
||||||
@ -18,6 +19,8 @@ const HeaderTitle = ({
|
|||||||
const styles = useStyles();
|
const styles = useStyles();
|
||||||
const headerClasses = classnames({ skeleton: loading });
|
const headerClasses = classnames({ skeleton: loading });
|
||||||
|
|
||||||
|
usePageTitle(title);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.headerTitleContainer}>
|
<div className={styles.headerTitleContainer}>
|
||||||
<div className={headerClasses} data-loading>
|
<div className={headerClasses} data-loading>
|
||||||
|
@ -96,12 +96,12 @@ const FeatureToggleList = ({
|
|||||||
};
|
};
|
||||||
|
|
||||||
const searchResultsHeader = filter.query
|
const searchResultsHeader = filter.query
|
||||||
? `(${features.length} matches)`
|
? ` (${features.length} matches)`
|
||||||
: '';
|
: '';
|
||||||
|
|
||||||
const headerTitle = archive
|
const headerTitle = archive
|
||||||
? `Archived Features ${searchResultsHeader}`
|
? `Archived feature toggles${searchResultsHeader}`
|
||||||
: `Features ${searchResultsHeader}`;
|
: `Feature toggles${searchResultsHeader}`;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.featureContainer}>
|
<div className={styles.featureContainer}>
|
||||||
|
@ -6,6 +6,7 @@ import renderer from 'react-test-renderer';
|
|||||||
import theme from 'themes/mainTheme';
|
import theme from 'themes/mainTheme';
|
||||||
import { CREATE_FEATURE } from 'component/providers/AccessProvider/permissions';
|
import { CREATE_FEATURE } from 'component/providers/AccessProvider/permissions';
|
||||||
import AccessProvider from 'component/providers/AccessProvider/AccessProvider';
|
import AccessProvider from 'component/providers/AccessProvider/AccessProvider';
|
||||||
|
import { AnnouncerProvider } from 'component/common/Announcer/AnnouncerProvider/AnnouncerProvider';
|
||||||
|
|
||||||
jest.mock('./FeatureToggleListItem/FeatureToggleListItem', () => ({
|
jest.mock('./FeatureToggleListItem/FeatureToggleListItem', () => ({
|
||||||
__esModule: true,
|
__esModule: true,
|
||||||
@ -24,18 +25,22 @@ test('renders correctly with one feature', () => {
|
|||||||
const tree = renderer.create(
|
const tree = renderer.create(
|
||||||
<MemoryRouter>
|
<MemoryRouter>
|
||||||
<ThemeProvider theme={theme}>
|
<ThemeProvider theme={theme}>
|
||||||
<AccessProvider permissions={[{ permission: CREATE_FEATURE }]}>
|
<AnnouncerProvider>
|
||||||
<FeatureToggleList
|
<AccessProvider
|
||||||
updateSetting={jest.fn()}
|
permissions={[{ permission: CREATE_FEATURE }]}
|
||||||
filter={{}}
|
>
|
||||||
setFilter={jest.fn()}
|
<FeatureToggleList
|
||||||
sort={{}}
|
updateSetting={jest.fn()}
|
||||||
setSort={jest.fn()}
|
filter={{}}
|
||||||
features={features}
|
setFilter={jest.fn()}
|
||||||
fetcher={jest.fn()}
|
sort={{}}
|
||||||
flags={{}}
|
setSort={jest.fn()}
|
||||||
/>
|
features={features}
|
||||||
</AccessProvider>
|
fetcher={jest.fn()}
|
||||||
|
flags={{}}
|
||||||
|
/>
|
||||||
|
</AccessProvider>
|
||||||
|
</AnnouncerProvider>
|
||||||
</ThemeProvider>
|
</ThemeProvider>
|
||||||
</MemoryRouter>
|
</MemoryRouter>
|
||||||
);
|
);
|
||||||
@ -52,17 +57,21 @@ test('renders correctly with one feature without permissions', () => {
|
|||||||
const tree = renderer.create(
|
const tree = renderer.create(
|
||||||
<MemoryRouter>
|
<MemoryRouter>
|
||||||
<ThemeProvider theme={theme}>
|
<ThemeProvider theme={theme}>
|
||||||
<AccessProvider permissions={[{ permission: CREATE_FEATURE }]}>
|
<AnnouncerProvider>
|
||||||
<FeatureToggleList
|
<AccessProvider
|
||||||
filter={{}}
|
permissions={[{ permission: CREATE_FEATURE }]}
|
||||||
setFilter={jest.fn()}
|
>
|
||||||
sort={{}}
|
<FeatureToggleList
|
||||||
setSort={jest.fn()}
|
filter={{}}
|
||||||
features={features}
|
setFilter={jest.fn()}
|
||||||
fetcher={jest.fn()}
|
sort={{}}
|
||||||
flags={{}}
|
setSort={jest.fn()}
|
||||||
/>
|
features={features}
|
||||||
</AccessProvider>
|
fetcher={jest.fn()}
|
||||||
|
flags={{}}
|
||||||
|
/>
|
||||||
|
</AccessProvider>
|
||||||
|
</AnnouncerProvider>
|
||||||
</ThemeProvider>
|
</ThemeProvider>
|
||||||
</MemoryRouter>
|
</MemoryRouter>
|
||||||
);
|
);
|
||||||
|
@ -1,348 +1,368 @@
|
|||||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||||
|
|
||||||
exports[`renders correctly with one feature 1`] = `
|
exports[`renders correctly with one feature 1`] = `
|
||||||
<div>
|
Array [
|
||||||
<div
|
<div>
|
||||||
className="makeStyles-searchBarContainer-3"
|
|
||||||
>
|
|
||||||
<form
|
|
||||||
className="makeStyles-container-6"
|
|
||||||
role="search"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
className="makeStyles-search-7 makeStyles-searchBar-4"
|
|
||||||
>
|
|
||||||
<svg
|
|
||||||
aria-hidden={true}
|
|
||||||
className="MuiSvgIcon-root makeStyles-searchIcon-8"
|
|
||||||
focusable="false"
|
|
||||||
viewBox="0 0 24 24"
|
|
||||||
>
|
|
||||||
<path
|
|
||||||
d="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
<div
|
|
||||||
className="MuiInputBase-root makeStyles-inputRoot-9"
|
|
||||||
onClick={[Function]}
|
|
||||||
onKeyPress={[Function]}
|
|
||||||
>
|
|
||||||
<input
|
|
||||||
aria-label="search"
|
|
||||||
className="MuiInputBase-input MuiInputBase-inputTypeSearch"
|
|
||||||
onAnimationStart={[Function]}
|
|
||||||
onBlur={[Function]}
|
|
||||||
onChange={[Function]}
|
|
||||||
onFocus={[Function]}
|
|
||||||
placeholder="Search..."
|
|
||||||
type="search"
|
|
||||||
value=""
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
<a
|
|
||||||
href="/archive"
|
|
||||||
onClick={[Function]}
|
|
||||||
>
|
|
||||||
Archive
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className="MuiPaper-root MuiPaper-elevation1 MuiPaper-rounded"
|
|
||||||
style={
|
|
||||||
Object {
|
|
||||||
"borderRadius": "10px",
|
|
||||||
"boxShadow": "none",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<div
|
<div
|
||||||
className="makeStyles-headerContainer-10"
|
className="makeStyles-searchBarContainer-3"
|
||||||
>
|
>
|
||||||
<div
|
<form
|
||||||
className="makeStyles-headerTitleContainer-14"
|
className="makeStyles-container-6"
|
||||||
|
role="search"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
className=""
|
className="makeStyles-search-7 makeStyles-searchBar-4"
|
||||||
data-loading={true}
|
|
||||||
>
|
>
|
||||||
<h1
|
<svg
|
||||||
className="MuiTypography-root makeStyles-headerTitle-15 MuiTypography-h1"
|
aria-hidden={true}
|
||||||
|
className="MuiSvgIcon-root makeStyles-searchIcon-8"
|
||||||
|
focusable="false"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
>
|
>
|
||||||
Features
|
<path
|
||||||
</h1>
|
d="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
<div
|
||||||
|
className="MuiInputBase-root makeStyles-inputRoot-9"
|
||||||
|
onClick={[Function]}
|
||||||
|
onKeyPress={[Function]}
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
aria-label="search"
|
||||||
|
className="MuiInputBase-input MuiInputBase-inputTypeSearch"
|
||||||
|
onAnimationStart={[Function]}
|
||||||
|
onBlur={[Function]}
|
||||||
|
onChange={[Function]}
|
||||||
|
onFocus={[Function]}
|
||||||
|
placeholder="Search..."
|
||||||
|
type="search"
|
||||||
|
value=""
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</form>
|
||||||
|
<a
|
||||||
|
href="/archive"
|
||||||
|
onClick={[Function]}
|
||||||
|
>
|
||||||
|
Archive
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
className="MuiPaper-root MuiPaper-elevation1 MuiPaper-rounded"
|
||||||
|
style={
|
||||||
|
Object {
|
||||||
|
"borderRadius": "10px",
|
||||||
|
"boxShadow": "none",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
className="makeStyles-headerContainer-10"
|
||||||
|
>
|
||||||
<div
|
<div
|
||||||
className="makeStyles-headerActions-16"
|
className="makeStyles-headerTitleContainer-14"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
className="makeStyles-actionsContainer-1"
|
className=""
|
||||||
|
data-loading={true}
|
||||||
|
>
|
||||||
|
<h1
|
||||||
|
className="MuiTypography-root makeStyles-headerTitle-15 MuiTypography-h1"
|
||||||
|
>
|
||||||
|
Feature toggles
|
||||||
|
</h1>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
className="makeStyles-headerActions-16"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
className="makeStyles-actions-17"
|
className="makeStyles-actionsContainer-1"
|
||||||
>
|
>
|
||||||
<p
|
<div
|
||||||
className="MuiTypography-root MuiTypography-body2"
|
className="makeStyles-actions-17"
|
||||||
data-loading={true}
|
|
||||||
>
|
>
|
||||||
Sorted by:
|
<p
|
||||||
</p>
|
className="MuiTypography-root MuiTypography-body2"
|
||||||
<button
|
data-loading={true}
|
||||||
aria-controls="sorting"
|
>
|
||||||
aria-haspopup="true"
|
Sorted by:
|
||||||
className="MuiButtonBase-root MuiButton-root MuiButton-text"
|
</p>
|
||||||
data-loading={true}
|
<button
|
||||||
disabled={false}
|
aria-controls="sorting"
|
||||||
id="sorting"
|
aria-haspopup="true"
|
||||||
onBlur={[Function]}
|
className="MuiButtonBase-root MuiButton-root MuiButton-text"
|
||||||
onClick={[Function]}
|
data-loading={true}
|
||||||
onDragLeave={[Function]}
|
disabled={false}
|
||||||
onFocus={[Function]}
|
id="sorting"
|
||||||
onKeyDown={[Function]}
|
onBlur={[Function]}
|
||||||
onKeyUp={[Function]}
|
onClick={[Function]}
|
||||||
onMouseDown={[Function]}
|
onDragLeave={[Function]}
|
||||||
onMouseLeave={[Function]}
|
onFocus={[Function]}
|
||||||
onMouseUp={[Function]}
|
onKeyDown={[Function]}
|
||||||
onTouchEnd={[Function]}
|
onKeyUp={[Function]}
|
||||||
onTouchMove={[Function]}
|
onMouseDown={[Function]}
|
||||||
onTouchStart={[Function]}
|
onMouseLeave={[Function]}
|
||||||
style={
|
onMouseUp={[Function]}
|
||||||
Object {
|
onTouchEnd={[Function]}
|
||||||
"fontWeight": "normal",
|
onTouchMove={[Function]}
|
||||||
"textTransform": "lowercase",
|
onTouchStart={[Function]}
|
||||||
}
|
style={
|
||||||
}
|
Object {
|
||||||
tabIndex={0}
|
"fontWeight": "normal",
|
||||||
title="Sort by"
|
"textTransform": "lowercase",
|
||||||
type="button"
|
}
|
||||||
>
|
}
|
||||||
<span
|
tabIndex={0}
|
||||||
className="MuiButton-label"
|
title="Sort by"
|
||||||
|
type="button"
|
||||||
>
|
>
|
||||||
By Name
|
|
||||||
<span
|
<span
|
||||||
className="MuiButton-endIcon MuiButton-iconSizeMedium"
|
className="MuiButton-label"
|
||||||
>
|
>
|
||||||
|
By Name
|
||||||
<span
|
<span
|
||||||
aria-hidden={true}
|
className="MuiButton-endIcon MuiButton-iconSizeMedium"
|
||||||
className="material-icons MuiIcon-root"
|
|
||||||
>
|
>
|
||||||
<svg
|
<span
|
||||||
className="MuiSvgIcon-root"
|
aria-hidden={true}
|
||||||
focusable="false"
|
className="material-icons MuiIcon-root"
|
||||||
role="img"
|
|
||||||
viewBox="0 0 24 24"
|
|
||||||
>
|
>
|
||||||
<path
|
<svg
|
||||||
d="M7 10l5 5 5-5z"
|
className="MuiSvgIcon-root"
|
||||||
/>
|
focusable="false"
|
||||||
<title>
|
role="img"
|
||||||
Toggle
|
viewBox="0 0 24 24"
|
||||||
</title>
|
>
|
||||||
</svg>
|
<path
|
||||||
|
d="M7 10l5 5 5-5z"
|
||||||
|
/>
|
||||||
|
<title>
|
||||||
|
Toggle
|
||||||
|
</title>
|
||||||
|
</svg>
|
||||||
|
</span>
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</button>
|
||||||
</button>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div
|
||||||
<div
|
className="makeStyles-bodyContainer-11"
|
||||||
className="makeStyles-bodyContainer-11"
|
|
||||||
>
|
|
||||||
<ul
|
|
||||||
className="MuiList-root MuiList-padding"
|
|
||||||
>
|
>
|
||||||
<ListItem
|
<ul
|
||||||
feature={
|
className="MuiList-root MuiList-padding"
|
||||||
Object {
|
>
|
||||||
"name": "Another",
|
<ListItem
|
||||||
"reviveName": "Another",
|
feature={
|
||||||
|
Object {
|
||||||
|
"name": "Another",
|
||||||
|
"reviveName": "Another",
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
flags={Object {}}
|
||||||
flags={Object {}}
|
hasAccess={[Function]}
|
||||||
hasAccess={[Function]}
|
/>
|
||||||
/>
|
</ul>
|
||||||
</ul>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>,
|
||||||
</div>
|
<div
|
||||||
|
aria-atomic={true}
|
||||||
|
aria-live="polite"
|
||||||
|
className="makeStyles-container-18"
|
||||||
|
data-testid="ANNOUNCER_ELEMENT_TEST_ID"
|
||||||
|
role="status"
|
||||||
|
/>,
|
||||||
|
]
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`renders correctly with one feature without permissions 1`] = `
|
exports[`renders correctly with one feature without permissions 1`] = `
|
||||||
<div>
|
Array [
|
||||||
<div
|
<div>
|
||||||
className="makeStyles-searchBarContainer-3"
|
|
||||||
>
|
|
||||||
<form
|
|
||||||
className="makeStyles-container-6"
|
|
||||||
role="search"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
className="makeStyles-search-7 makeStyles-searchBar-4"
|
|
||||||
>
|
|
||||||
<svg
|
|
||||||
aria-hidden={true}
|
|
||||||
className="MuiSvgIcon-root makeStyles-searchIcon-8"
|
|
||||||
focusable="false"
|
|
||||||
viewBox="0 0 24 24"
|
|
||||||
>
|
|
||||||
<path
|
|
||||||
d="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
<div
|
|
||||||
className="MuiInputBase-root makeStyles-inputRoot-9"
|
|
||||||
onClick={[Function]}
|
|
||||||
onKeyPress={[Function]}
|
|
||||||
>
|
|
||||||
<input
|
|
||||||
aria-label="search"
|
|
||||||
className="MuiInputBase-input MuiInputBase-inputTypeSearch"
|
|
||||||
onAnimationStart={[Function]}
|
|
||||||
onBlur={[Function]}
|
|
||||||
onChange={[Function]}
|
|
||||||
onFocus={[Function]}
|
|
||||||
placeholder="Search..."
|
|
||||||
type="search"
|
|
||||||
value=""
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
<a
|
|
||||||
href="/archive"
|
|
||||||
onClick={[Function]}
|
|
||||||
>
|
|
||||||
Archive
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className="MuiPaper-root MuiPaper-elevation1 MuiPaper-rounded"
|
|
||||||
style={
|
|
||||||
Object {
|
|
||||||
"borderRadius": "10px",
|
|
||||||
"boxShadow": "none",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<div
|
<div
|
||||||
className="makeStyles-headerContainer-10"
|
className="makeStyles-searchBarContainer-3"
|
||||||
>
|
>
|
||||||
<div
|
<form
|
||||||
className="makeStyles-headerTitleContainer-14"
|
className="makeStyles-container-6"
|
||||||
|
role="search"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
className=""
|
className="makeStyles-search-7 makeStyles-searchBar-4"
|
||||||
data-loading={true}
|
|
||||||
>
|
>
|
||||||
<h1
|
<svg
|
||||||
className="MuiTypography-root makeStyles-headerTitle-15 MuiTypography-h1"
|
aria-hidden={true}
|
||||||
|
className="MuiSvgIcon-root makeStyles-searchIcon-8"
|
||||||
|
focusable="false"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
>
|
>
|
||||||
Features
|
<path
|
||||||
</h1>
|
d="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
<div
|
||||||
|
className="MuiInputBase-root makeStyles-inputRoot-9"
|
||||||
|
onClick={[Function]}
|
||||||
|
onKeyPress={[Function]}
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
aria-label="search"
|
||||||
|
className="MuiInputBase-input MuiInputBase-inputTypeSearch"
|
||||||
|
onAnimationStart={[Function]}
|
||||||
|
onBlur={[Function]}
|
||||||
|
onChange={[Function]}
|
||||||
|
onFocus={[Function]}
|
||||||
|
placeholder="Search..."
|
||||||
|
type="search"
|
||||||
|
value=""
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</form>
|
||||||
|
<a
|
||||||
|
href="/archive"
|
||||||
|
onClick={[Function]}
|
||||||
|
>
|
||||||
|
Archive
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
className="MuiPaper-root MuiPaper-elevation1 MuiPaper-rounded"
|
||||||
|
style={
|
||||||
|
Object {
|
||||||
|
"borderRadius": "10px",
|
||||||
|
"boxShadow": "none",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
className="makeStyles-headerContainer-10"
|
||||||
|
>
|
||||||
<div
|
<div
|
||||||
className="makeStyles-headerActions-16"
|
className="makeStyles-headerTitleContainer-14"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
className="makeStyles-actionsContainer-1"
|
className=""
|
||||||
|
data-loading={true}
|
||||||
|
>
|
||||||
|
<h1
|
||||||
|
className="MuiTypography-root makeStyles-headerTitle-15 MuiTypography-h1"
|
||||||
|
>
|
||||||
|
Feature toggles
|
||||||
|
</h1>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
className="makeStyles-headerActions-16"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
className="makeStyles-actions-17"
|
className="makeStyles-actionsContainer-1"
|
||||||
>
|
>
|
||||||
<p
|
<div
|
||||||
className="MuiTypography-root MuiTypography-body2"
|
className="makeStyles-actions-17"
|
||||||
data-loading={true}
|
|
||||||
>
|
>
|
||||||
Sorted by:
|
<p
|
||||||
</p>
|
className="MuiTypography-root MuiTypography-body2"
|
||||||
<button
|
data-loading={true}
|
||||||
aria-controls="sorting"
|
>
|
||||||
aria-haspopup="true"
|
Sorted by:
|
||||||
className="MuiButtonBase-root MuiButton-root MuiButton-text"
|
</p>
|
||||||
data-loading={true}
|
<button
|
||||||
disabled={false}
|
aria-controls="sorting"
|
||||||
id="sorting"
|
aria-haspopup="true"
|
||||||
onBlur={[Function]}
|
className="MuiButtonBase-root MuiButton-root MuiButton-text"
|
||||||
onClick={[Function]}
|
data-loading={true}
|
||||||
onDragLeave={[Function]}
|
disabled={false}
|
||||||
onFocus={[Function]}
|
id="sorting"
|
||||||
onKeyDown={[Function]}
|
onBlur={[Function]}
|
||||||
onKeyUp={[Function]}
|
onClick={[Function]}
|
||||||
onMouseDown={[Function]}
|
onDragLeave={[Function]}
|
||||||
onMouseLeave={[Function]}
|
onFocus={[Function]}
|
||||||
onMouseUp={[Function]}
|
onKeyDown={[Function]}
|
||||||
onTouchEnd={[Function]}
|
onKeyUp={[Function]}
|
||||||
onTouchMove={[Function]}
|
onMouseDown={[Function]}
|
||||||
onTouchStart={[Function]}
|
onMouseLeave={[Function]}
|
||||||
style={
|
onMouseUp={[Function]}
|
||||||
Object {
|
onTouchEnd={[Function]}
|
||||||
"fontWeight": "normal",
|
onTouchMove={[Function]}
|
||||||
"textTransform": "lowercase",
|
onTouchStart={[Function]}
|
||||||
}
|
style={
|
||||||
}
|
Object {
|
||||||
tabIndex={0}
|
"fontWeight": "normal",
|
||||||
title="Sort by"
|
"textTransform": "lowercase",
|
||||||
type="button"
|
}
|
||||||
>
|
}
|
||||||
<span
|
tabIndex={0}
|
||||||
className="MuiButton-label"
|
title="Sort by"
|
||||||
|
type="button"
|
||||||
>
|
>
|
||||||
By Name
|
|
||||||
<span
|
<span
|
||||||
className="MuiButton-endIcon MuiButton-iconSizeMedium"
|
className="MuiButton-label"
|
||||||
>
|
>
|
||||||
|
By Name
|
||||||
<span
|
<span
|
||||||
aria-hidden={true}
|
className="MuiButton-endIcon MuiButton-iconSizeMedium"
|
||||||
className="material-icons MuiIcon-root"
|
|
||||||
>
|
>
|
||||||
<svg
|
<span
|
||||||
className="MuiSvgIcon-root"
|
aria-hidden={true}
|
||||||
focusable="false"
|
className="material-icons MuiIcon-root"
|
||||||
role="img"
|
|
||||||
viewBox="0 0 24 24"
|
|
||||||
>
|
>
|
||||||
<path
|
<svg
|
||||||
d="M7 10l5 5 5-5z"
|
className="MuiSvgIcon-root"
|
||||||
/>
|
focusable="false"
|
||||||
<title>
|
role="img"
|
||||||
Toggle
|
viewBox="0 0 24 24"
|
||||||
</title>
|
>
|
||||||
</svg>
|
<path
|
||||||
|
d="M7 10l5 5 5-5z"
|
||||||
|
/>
|
||||||
|
<title>
|
||||||
|
Toggle
|
||||||
|
</title>
|
||||||
|
</svg>
|
||||||
|
</span>
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
</span>
|
<span
|
||||||
<span
|
className="MuiTouchRipple-root"
|
||||||
className="MuiTouchRipple-root"
|
/>
|
||||||
/>
|
</button>
|
||||||
</button>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div
|
||||||
<div
|
className="makeStyles-bodyContainer-11"
|
||||||
className="makeStyles-bodyContainer-11"
|
|
||||||
>
|
|
||||||
<ul
|
|
||||||
className="MuiList-root MuiList-padding"
|
|
||||||
>
|
>
|
||||||
<ListItem
|
<ul
|
||||||
feature={
|
className="MuiList-root MuiList-padding"
|
||||||
Object {
|
>
|
||||||
"name": "Another",
|
<ListItem
|
||||||
"reviveName": "Another",
|
feature={
|
||||||
|
Object {
|
||||||
|
"name": "Another",
|
||||||
|
"reviveName": "Another",
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
flags={Object {}}
|
||||||
flags={Object {}}
|
hasAccess={[Function]}
|
||||||
hasAccess={[Function]}
|
/>
|
||||||
/>
|
</ul>
|
||||||
</ul>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>,
|
||||||
</div>
|
<div
|
||||||
|
aria-atomic={true}
|
||||||
|
aria-live="polite"
|
||||||
|
className="makeStyles-container-18"
|
||||||
|
data-testid="ANNOUNCER_ELEMENT_TEST_ID"
|
||||||
|
role="status"
|
||||||
|
>
|
||||||
|
Navigated to Feature toggles
|
||||||
|
</div>,
|
||||||
|
]
|
||||||
`;
|
`;
|
||||||
|
@ -16,12 +16,14 @@ import { FeatureMetricsChips } from './FeatureMetricsChips/FeatureMetricsChips';
|
|||||||
import { useFeature } from 'hooks/api/getters/useFeature/useFeature';
|
import { useFeature } from 'hooks/api/getters/useFeature/useFeature';
|
||||||
import ConditionallyRender from 'component/common/ConditionallyRender';
|
import ConditionallyRender from 'component/common/ConditionallyRender';
|
||||||
import { useStyles } from './FeatureMetrics.styles';
|
import { useStyles } from './FeatureMetrics.styles';
|
||||||
|
import { usePageTitle } from 'hooks/usePageTitle';
|
||||||
|
|
||||||
export const FeatureMetrics = () => {
|
export const FeatureMetrics = () => {
|
||||||
const { projectId, featureId } = useParams<IFeatureViewParams>();
|
const { projectId, featureId } = useParams<IFeatureViewParams>();
|
||||||
const environments = useFeatureMetricsEnvironments(projectId, featureId);
|
const environments = useFeatureMetricsEnvironments(projectId, featureId);
|
||||||
const applications = useFeatureMetricsApplications(featureId);
|
const applications = useFeatureMetricsApplications(featureId);
|
||||||
const styles = useStyles();
|
const styles = useStyles();
|
||||||
|
usePageTitle('Metrics');
|
||||||
|
|
||||||
const [hoursBack = FEATURE_METRIC_HOURS_BACK_MAX, setHoursBack] =
|
const [hoursBack = FEATURE_METRIC_HOURS_BACK_MAX, setHoursBack] =
|
||||||
useQueryStringNumberState('hoursBack');
|
useQueryStringNumberState('hoursBack');
|
||||||
|
@ -10,15 +10,16 @@ import {
|
|||||||
formatFeaturePath,
|
formatFeaturePath,
|
||||||
} from 'component/feature/FeatureStrategy/FeatureStrategyEdit/FeatureStrategyEdit';
|
} from 'component/feature/FeatureStrategy/FeatureStrategyEdit/FeatureStrategyEdit';
|
||||||
import { useRequiredPathParam } from 'hooks/useRequiredPathParam';
|
import { useRequiredPathParam } from 'hooks/useRequiredPathParam';
|
||||||
|
import { usePageTitle } from 'hooks/usePageTitle';
|
||||||
|
|
||||||
const FeatureOverview = () => {
|
const FeatureOverview = () => {
|
||||||
const styles = useStyles();
|
const styles = useStyles();
|
||||||
const { push } = useHistory();
|
const { push } = useHistory();
|
||||||
|
|
||||||
const projectId = useRequiredPathParam('projectId');
|
const projectId = useRequiredPathParam('projectId');
|
||||||
const featureId = useRequiredPathParam('featureId');
|
const featureId = useRequiredPathParam('featureId');
|
||||||
const featurePath = formatFeaturePath(projectId, featureId);
|
const featurePath = formatFeaturePath(projectId, featureId);
|
||||||
const onSidebarClose = () => push(featurePath);
|
const onSidebarClose = () => push(featurePath);
|
||||||
|
usePageTitle(featureId);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.container}>
|
<div className={styles.container}>
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
import { useStyles } from './FeatureVariants.styles';
|
import { useStyles } from './FeatureVariants.styles';
|
||||||
import FeatureOverviewVariants from './FeatureVariantsList/FeatureVariantsList';
|
import FeatureOverviewVariants from './FeatureVariantsList/FeatureVariantsList';
|
||||||
|
import { usePageTitle } from 'hooks/usePageTitle';
|
||||||
|
|
||||||
const FeatureVariants = () => {
|
const FeatureVariants = () => {
|
||||||
const styles = useStyles();
|
const styles = useStyles();
|
||||||
|
usePageTitle('Variants');
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.container}>
|
<div className={styles.container}>
|
||||||
|
@ -8,5 +8,5 @@ export const EventHistory = () => {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return <EventLog history={events} title="Recent changes" />;
|
return <EventLog history={events} title="Event log" />;
|
||||||
};
|
};
|
||||||
|
@ -10,7 +10,7 @@ export const FeatureEventHistory = ({ toggleName }) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<EventLog history={events} hideName title="Change log" displayInline />
|
<EventLog history={events} hideName title="Event log" displayInline />
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -23,6 +23,13 @@ exports[`renders correctly with empty version 1`] = `
|
|||||||
</small>
|
</small>
|
||||||
<br />
|
<br />
|
||||||
</section>
|
</section>
|
||||||
|
<div
|
||||||
|
aria-atomic="true"
|
||||||
|
aria-live="polite"
|
||||||
|
class="makeStyles-container-2"
|
||||||
|
data-testid="ANNOUNCER_ELEMENT_TEST_ID"
|
||||||
|
role="status"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
`;
|
`;
|
||||||
@ -34,7 +41,7 @@ exports[`renders correctly with ui-config 1`] = `
|
|||||||
title="API details"
|
title="API details"
|
||||||
>
|
>
|
||||||
<h2
|
<h2
|
||||||
class="makeStyles-title-2"
|
class="makeStyles-title-3"
|
||||||
>
|
>
|
||||||
Unleash 1.1.0
|
Unleash 1.1.0
|
||||||
|
|
||||||
@ -50,6 +57,13 @@ exports[`renders correctly with ui-config 1`] = `
|
|||||||
</small>
|
</small>
|
||||||
<br />
|
<br />
|
||||||
</section>
|
</section>
|
||||||
|
<div
|
||||||
|
aria-atomic="true"
|
||||||
|
aria-live="polite"
|
||||||
|
class="makeStyles-container-4"
|
||||||
|
data-testid="ANNOUNCER_ELEMENT_TEST_ID"
|
||||||
|
role="status"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
`;
|
`;
|
||||||
@ -61,7 +75,7 @@ exports[`renders correctly with versionInfo 1`] = `
|
|||||||
title="API details"
|
title="API details"
|
||||||
>
|
>
|
||||||
<h2
|
<h2
|
||||||
class="makeStyles-title-4"
|
class="makeStyles-title-7"
|
||||||
>
|
>
|
||||||
Unleash 1.2.3
|
Unleash 1.2.3
|
||||||
|
|
||||||
@ -77,6 +91,13 @@ exports[`renders correctly with versionInfo 1`] = `
|
|||||||
1
|
1
|
||||||
</small>
|
</small>
|
||||||
</section>
|
</section>
|
||||||
|
<div
|
||||||
|
aria-atomic="true"
|
||||||
|
aria-live="polite"
|
||||||
|
class="makeStyles-container-8"
|
||||||
|
data-testid="ANNOUNCER_ELEMENT_TEST_ID"
|
||||||
|
role="status"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
`;
|
`;
|
||||||
@ -88,7 +109,7 @@ exports[`renders correctly without uiConfig 1`] = `
|
|||||||
title="API details"
|
title="API details"
|
||||||
>
|
>
|
||||||
<h2
|
<h2
|
||||||
class="makeStyles-title-3"
|
class="makeStyles-title-5"
|
||||||
>
|
>
|
||||||
Unleash 1.1.0
|
Unleash 1.1.0
|
||||||
|
|
||||||
@ -97,6 +118,13 @@ exports[`renders correctly without uiConfig 1`] = `
|
|||||||
<small />
|
<small />
|
||||||
<br />
|
<br />
|
||||||
</section>
|
</section>
|
||||||
|
<div
|
||||||
|
aria-atomic="true"
|
||||||
|
aria-live="polite"
|
||||||
|
class="makeStyles-container-6"
|
||||||
|
data-testid="ANNOUNCER_ELEMENT_TEST_ID"
|
||||||
|
role="status"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
`;
|
`;
|
||||||
|
@ -46,7 +46,7 @@ Array [
|
|||||||
"menu": Object {},
|
"menu": Object {},
|
||||||
"parent": "/projects",
|
"parent": "/projects",
|
||||||
"path": "/projects/:projectId/features/:featureId/edit",
|
"path": "/projects/:projectId/features/:featureId/edit",
|
||||||
"title": "Edit Feature",
|
"title": "Edit feature",
|
||||||
"type": "protected",
|
"type": "protected",
|
||||||
},
|
},
|
||||||
Object {
|
Object {
|
||||||
@ -122,7 +122,7 @@ Array [
|
|||||||
"mobile": true,
|
"mobile": true,
|
||||||
},
|
},
|
||||||
"path": "/features",
|
"path": "/features",
|
||||||
"title": "Feature Toggles",
|
"title": "Feature toggles",
|
||||||
"type": "protected",
|
"type": "protected",
|
||||||
},
|
},
|
||||||
Object {
|
Object {
|
||||||
@ -169,7 +169,7 @@ Array [
|
|||||||
"mobile": true,
|
"mobile": true,
|
||||||
},
|
},
|
||||||
"path": "/context",
|
"path": "/context",
|
||||||
"title": "Context Fields",
|
"title": "Context fields",
|
||||||
"type": "protected",
|
"type": "protected",
|
||||||
},
|
},
|
||||||
Object {
|
Object {
|
||||||
@ -331,14 +331,14 @@ Array [
|
|||||||
"adminSettings": true,
|
"adminSettings": true,
|
||||||
},
|
},
|
||||||
"path": "/history",
|
"path": "/history",
|
||||||
"title": "Event History",
|
"title": "Event log",
|
||||||
"type": "protected",
|
"type": "protected",
|
||||||
},
|
},
|
||||||
Object {
|
Object {
|
||||||
"component": [Function],
|
"component": [Function],
|
||||||
"menu": Object {},
|
"menu": Object {},
|
||||||
"path": "/archive",
|
"path": "/archive",
|
||||||
"title": "Archived Toggles",
|
"title": "Archived toggles",
|
||||||
"type": "protected",
|
"type": "protected",
|
||||||
},
|
},
|
||||||
Object {
|
Object {
|
||||||
@ -402,7 +402,7 @@ Array [
|
|||||||
},
|
},
|
||||||
"parent": "/admin",
|
"parent": "/admin",
|
||||||
"path": "/admin/roles",
|
"path": "/admin/roles",
|
||||||
"title": "Project Roles",
|
"title": "Project roles",
|
||||||
"type": "protected",
|
"type": "protected",
|
||||||
},
|
},
|
||||||
Object {
|
Object {
|
||||||
@ -412,7 +412,7 @@ Array [
|
|||||||
},
|
},
|
||||||
"parent": "/admin",
|
"parent": "/admin",
|
||||||
"path": "/admin/auth",
|
"path": "/admin/auth",
|
||||||
"title": "Single Sign-On",
|
"title": "Single sign-on",
|
||||||
"type": "protected",
|
"type": "protected",
|
||||||
},
|
},
|
||||||
Object {
|
Object {
|
||||||
|
@ -98,7 +98,7 @@ export const routes: IRoute[] = [
|
|||||||
{
|
{
|
||||||
path: '/projects/:projectId/features/:featureId/edit',
|
path: '/projects/:projectId/features/:featureId/edit',
|
||||||
parent: '/projects',
|
parent: '/projects',
|
||||||
title: 'Edit Feature',
|
title: 'Edit feature',
|
||||||
component: EditFeature,
|
component: EditFeature,
|
||||||
type: 'protected',
|
type: 'protected',
|
||||||
menu: {},
|
menu: {},
|
||||||
@ -172,7 +172,7 @@ export const routes: IRoute[] = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/features',
|
path: '/features',
|
||||||
title: 'Feature Toggles',
|
title: 'Feature toggles',
|
||||||
component: FeatureToggleListContainer,
|
component: FeatureToggleListContainer,
|
||||||
type: 'protected',
|
type: 'protected',
|
||||||
menu: { mobile: true },
|
menu: { mobile: true },
|
||||||
@ -216,7 +216,7 @@ export const routes: IRoute[] = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/context',
|
path: '/context',
|
||||||
title: 'Context Fields',
|
title: 'Context fields',
|
||||||
component: ContextList,
|
component: ContextList,
|
||||||
type: 'protected',
|
type: 'protected',
|
||||||
flag: C,
|
flag: C,
|
||||||
@ -372,7 +372,7 @@ export const routes: IRoute[] = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/history',
|
path: '/history',
|
||||||
title: 'Event History',
|
title: 'Event log',
|
||||||
component: EventHistoryPage,
|
component: EventHistoryPage,
|
||||||
type: 'protected',
|
type: 'protected',
|
||||||
menu: { adminSettings: true },
|
menu: { adminSettings: true },
|
||||||
@ -381,7 +381,7 @@ export const routes: IRoute[] = [
|
|||||||
// Archive
|
// Archive
|
||||||
{
|
{
|
||||||
path: '/archive',
|
path: '/archive',
|
||||||
title: 'Archived Toggles',
|
title: 'Archived toggles',
|
||||||
component: ArchiveListContainer,
|
component: ArchiveListContainer,
|
||||||
type: 'protected',
|
type: 'protected',
|
||||||
menu: {},
|
menu: {},
|
||||||
@ -447,7 +447,7 @@ export const routes: IRoute[] = [
|
|||||||
{
|
{
|
||||||
path: '/admin/roles',
|
path: '/admin/roles',
|
||||||
parent: '/admin',
|
parent: '/admin',
|
||||||
title: 'Project Roles',
|
title: 'Project roles',
|
||||||
component: ProjectRoles,
|
component: ProjectRoles,
|
||||||
type: 'protected',
|
type: 'protected',
|
||||||
flag: RE,
|
flag: RE,
|
||||||
@ -456,7 +456,7 @@ export const routes: IRoute[] = [
|
|||||||
{
|
{
|
||||||
path: '/admin/auth',
|
path: '/admin/auth',
|
||||||
parent: '/admin',
|
parent: '/admin',
|
||||||
title: 'Single Sign-On',
|
title: 'Single sign-on',
|
||||||
component: AuthSettings,
|
component: AuthSettings,
|
||||||
type: 'protected',
|
type: 'protected',
|
||||||
menu: { adminSettings: true },
|
menu: { adminSettings: true },
|
||||||
|
@ -49,7 +49,7 @@ export const ProjectFeatureToggles = ({
|
|||||||
headerContent={
|
headerContent={
|
||||||
<HeaderTitle
|
<HeaderTitle
|
||||||
className={styles.title}
|
className={styles.title}
|
||||||
title={`Feature toggles (${filteredFeatures.length})`}
|
title={`Project features (${filteredFeatures.length})`}
|
||||||
actions={
|
actions={
|
||||||
<div className={styles.actionsContainer}>
|
<div className={styles.actionsContainer}>
|
||||||
<SearchField
|
<SearchField
|
||||||
|
@ -3,12 +3,15 @@ import ApiError from 'component/common/ApiError/ApiError';
|
|||||||
import ConditionallyRender from 'component/common/ConditionallyRender';
|
import ConditionallyRender from 'component/common/ConditionallyRender';
|
||||||
import ReportToggleList from 'component/Reporting/ReportToggleList/ReportToggleList';
|
import ReportToggleList from 'component/Reporting/ReportToggleList/ReportToggleList';
|
||||||
import { ReportCard } from 'component/Reporting/ReportCard/ReportCard';
|
import { ReportCard } from 'component/Reporting/ReportCard/ReportCard';
|
||||||
|
import { usePageTitle } from 'hooks/usePageTitle';
|
||||||
|
|
||||||
interface IProjectHealthProps {
|
interface IProjectHealthProps {
|
||||||
projectId: string;
|
projectId: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ProjectHealth = ({ projectId }: IProjectHealthProps) => {
|
const ProjectHealth = ({ projectId }: IProjectHealthProps) => {
|
||||||
|
usePageTitle('Project health');
|
||||||
|
|
||||||
const { healthReport, refetchHealthReport, error } =
|
const { healthReport, refetchHealthReport, error } =
|
||||||
useHealthReport(projectId);
|
useHealthReport(projectId);
|
||||||
|
|
||||||
|
@ -6,6 +6,7 @@ import theme from 'themes/mainTheme';
|
|||||||
import AccessProvider from 'component/providers/AccessProvider/AccessProvider';
|
import AccessProvider from 'component/providers/AccessProvider/AccessProvider';
|
||||||
import { ADMIN } from 'component/providers/AccessProvider/permissions';
|
import { ADMIN } from 'component/providers/AccessProvider/permissions';
|
||||||
import UIProvider from 'component/providers/UIProvider/UIProvider';
|
import UIProvider from 'component/providers/UIProvider/UIProvider';
|
||||||
|
import { AnnouncerProvider } from 'component/common/Announcer/AnnouncerProvider/AnnouncerProvider';
|
||||||
|
|
||||||
test('renders correctly with one strategy', () => {
|
test('renders correctly with one strategy', () => {
|
||||||
const strategy = {
|
const strategy = {
|
||||||
@ -15,17 +16,19 @@ test('renders correctly with one strategy', () => {
|
|||||||
const tree = renderer.create(
|
const tree = renderer.create(
|
||||||
<MemoryRouter>
|
<MemoryRouter>
|
||||||
<ThemeProvider theme={theme}>
|
<ThemeProvider theme={theme}>
|
||||||
<UIProvider>
|
<AnnouncerProvider>
|
||||||
<AccessProvider permissions={[{ permission: ADMIN }]}>
|
<UIProvider>
|
||||||
<StrategiesList
|
<AccessProvider permissions={[{ permission: ADMIN }]}>
|
||||||
strategies={[strategy]}
|
<StrategiesList
|
||||||
fetchStrategies={jest.fn()}
|
strategies={[strategy]}
|
||||||
removeStrategy={jest.fn()}
|
fetchStrategies={jest.fn()}
|
||||||
deprecateStrategy={jest.fn()}
|
removeStrategy={jest.fn()}
|
||||||
reactivateStrategy={jest.fn()}
|
deprecateStrategy={jest.fn()}
|
||||||
/>
|
reactivateStrategy={jest.fn()}
|
||||||
</AccessProvider>
|
/>
|
||||||
</UIProvider>
|
</AccessProvider>
|
||||||
|
</UIProvider>
|
||||||
|
</AnnouncerProvider>
|
||||||
</ThemeProvider>
|
</ThemeProvider>
|
||||||
</MemoryRouter>
|
</MemoryRouter>
|
||||||
);
|
);
|
||||||
@ -41,17 +44,19 @@ test('renders correctly with one strategy without permissions', () => {
|
|||||||
const tree = renderer.create(
|
const tree = renderer.create(
|
||||||
<MemoryRouter>
|
<MemoryRouter>
|
||||||
<ThemeProvider theme={theme}>
|
<ThemeProvider theme={theme}>
|
||||||
<UIProvider>
|
<AnnouncerProvider>
|
||||||
<AccessProvider permissions={[{ permission: ADMIN }]}>
|
<UIProvider>
|
||||||
<StrategiesList
|
<AccessProvider permissions={[{ permission: ADMIN }]}>
|
||||||
strategies={[strategy]}
|
<StrategiesList
|
||||||
fetchStrategies={jest.fn()}
|
strategies={[strategy]}
|
||||||
removeStrategy={jest.fn()}
|
fetchStrategies={jest.fn()}
|
||||||
deprecateStrategy={jest.fn()}
|
removeStrategy={jest.fn()}
|
||||||
reactivateStrategy={jest.fn()}
|
deprecateStrategy={jest.fn()}
|
||||||
/>
|
reactivateStrategy={jest.fn()}
|
||||||
</AccessProvider>
|
/>
|
||||||
</UIProvider>
|
</AccessProvider>
|
||||||
|
</UIProvider>
|
||||||
|
</AnnouncerProvider>
|
||||||
</ThemeProvider>
|
</ThemeProvider>
|
||||||
</MemoryRouter>
|
</MemoryRouter>
|
||||||
);
|
);
|
||||||
|
@ -1,139 +1,42 @@
|
|||||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||||
|
|
||||||
exports[`renders correctly with one strategy 1`] = `
|
exports[`renders correctly with one strategy 1`] = `
|
||||||
<div
|
Array [
|
||||||
className="MuiPaper-root MuiPaper-elevation1 MuiPaper-rounded"
|
|
||||||
style={
|
|
||||||
Object {
|
|
||||||
"borderRadius": "10px",
|
|
||||||
"boxShadow": "none",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<div
|
<div
|
||||||
className="makeStyles-headerContainer-2"
|
className="MuiPaper-root MuiPaper-elevation1 MuiPaper-rounded"
|
||||||
|
style={
|
||||||
|
Object {
|
||||||
|
"borderRadius": "10px",
|
||||||
|
"boxShadow": "none",
|
||||||
|
}
|
||||||
|
}
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
className="makeStyles-headerTitleContainer-6"
|
className="makeStyles-headerContainer-2"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
className=""
|
className="makeStyles-headerTitleContainer-6"
|
||||||
data-loading={true}
|
|
||||||
>
|
|
||||||
<h1
|
|
||||||
className="MuiTypography-root makeStyles-headerTitle-7 MuiTypography-h1"
|
|
||||||
>
|
|
||||||
Strategies
|
|
||||||
</h1>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className="makeStyles-headerActions-8"
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
id="useId-0"
|
|
||||||
>
|
|
||||||
<button
|
|
||||||
aria-describedby="useId-0"
|
|
||||||
className="MuiButtonBase-root MuiButton-root MuiButton-contained MuiButton-containedPrimary"
|
|
||||||
data-testid="ADD_NEW_STRATEGY_ID"
|
|
||||||
disabled={false}
|
|
||||||
onBlur={[Function]}
|
|
||||||
onClick={[Function]}
|
|
||||||
onDragLeave={[Function]}
|
|
||||||
onFocus={[Function]}
|
|
||||||
onKeyDown={[Function]}
|
|
||||||
onKeyUp={[Function]}
|
|
||||||
onMouseDown={[Function]}
|
|
||||||
onMouseLeave={[Function]}
|
|
||||||
onMouseUp={[Function]}
|
|
||||||
onTouchEnd={[Function]}
|
|
||||||
onTouchMove={[Function]}
|
|
||||||
onTouchStart={[Function]}
|
|
||||||
tabIndex={0}
|
|
||||||
type="button"
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
className="MuiButton-label"
|
|
||||||
>
|
|
||||||
New strategy
|
|
||||||
<span
|
|
||||||
className="MuiButton-endIcon MuiButton-iconSizeMedium"
|
|
||||||
/>
|
|
||||||
</span>
|
|
||||||
<span
|
|
||||||
className="MuiTouchRipple-root"
|
|
||||||
/>
|
|
||||||
</button>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className="makeStyles-bodyContainer-3"
|
|
||||||
>
|
|
||||||
<ul
|
|
||||||
className="MuiList-root MuiList-padding"
|
|
||||||
>
|
|
||||||
<li
|
|
||||||
className="MuiListItem-root makeStyles-listItem-1 MuiListItem-gutters"
|
|
||||||
disabled={false}
|
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
className="MuiListItemAvatar-root"
|
className=""
|
||||||
|
data-loading={true}
|
||||||
>
|
>
|
||||||
<svg
|
<h1
|
||||||
aria-hidden={true}
|
className="MuiTypography-root makeStyles-headerTitle-7 MuiTypography-h1"
|
||||||
className="MuiSvgIcon-root"
|
|
||||||
focusable="false"
|
|
||||||
style={
|
|
||||||
Object {
|
|
||||||
"color": "#0000008a",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
viewBox="0 0 24 24"
|
|
||||||
>
|
>
|
||||||
<path
|
Strategies
|
||||||
d="M20.5 11H19V7c0-1.1-.9-2-2-2h-4V3.5C13 2.12 11.88 1 10.5 1S8 2.12 8 3.5V5H4c-1.1 0-1.99.9-1.99 2v3.8H3.5c1.49 0 2.7 1.21 2.7 2.7s-1.21 2.7-2.7 2.7H2V20c0 1.1.9 2 2 2h3.8v-1.5c0-1.49 1.21-2.7 2.7-2.7 1.49 0 2.7 1.21 2.7 2.7V22H17c1.1 0 2-.9 2-2v-4h1.5c1.38 0 2.5-1.12 2.5-2.5S21.88 11 20.5 11z"
|
</h1>
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
className="MuiListItemText-root MuiListItemText-multiline"
|
className="makeStyles-headerActions-8"
|
||||||
>
|
>
|
||||||
<span
|
<span
|
||||||
className="MuiTypography-root MuiListItemText-primary MuiTypography-body1 MuiTypography-displayBlock"
|
id="useId-0"
|
||||||
>
|
|
||||||
<a
|
|
||||||
href="/strategies/flexibleRollout"
|
|
||||||
onClick={[Function]}
|
|
||||||
>
|
|
||||||
<strong>
|
|
||||||
Gradual rollout
|
|
||||||
</strong>
|
|
||||||
</a>
|
|
||||||
</span>
|
|
||||||
<p
|
|
||||||
className="MuiTypography-root MuiListItemText-secondary MuiTypography-body2 MuiTypography-colorTextSecondary MuiTypography-displayBlock"
|
|
||||||
>
|
|
||||||
Roll out to a percentage of your userbase, and ensure that the experience is the same for the user on each visit.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<span
|
|
||||||
aria-describedby={null}
|
|
||||||
className=""
|
|
||||||
id="useId-1"
|
|
||||||
onBlur={[Function]}
|
|
||||||
onFocus={[Function]}
|
|
||||||
onMouseLeave={[Function]}
|
|
||||||
onMouseOver={[Function]}
|
|
||||||
onTouchEnd={[Function]}
|
|
||||||
onTouchStart={[Function]}
|
|
||||||
title="Deprecate strategy"
|
|
||||||
>
|
>
|
||||||
<button
|
<button
|
||||||
aria-labelledby="useId-1"
|
aria-describedby="useId-0"
|
||||||
className="MuiButtonBase-root MuiIconButton-root"
|
className="MuiButtonBase-root MuiButton-root MuiButton-contained MuiButton-containedPrimary"
|
||||||
|
data-testid="ADD_NEW_STRATEGY_ID"
|
||||||
disabled={false}
|
disabled={false}
|
||||||
onBlur={[Function]}
|
onBlur={[Function]}
|
||||||
onClick={[Function]}
|
onClick={[Function]}
|
||||||
@ -151,18 +54,12 @@ exports[`renders correctly with one strategy 1`] = `
|
|||||||
type="button"
|
type="button"
|
||||||
>
|
>
|
||||||
<span
|
<span
|
||||||
className="MuiIconButton-label"
|
className="MuiButton-label"
|
||||||
>
|
>
|
||||||
<svg
|
New strategy
|
||||||
aria-hidden={true}
|
<span
|
||||||
className="MuiSvgIcon-root"
|
className="MuiButton-endIcon MuiButton-iconSizeMedium"
|
||||||
focusable="false"
|
/>
|
||||||
viewBox="0 0 24 24"
|
|
||||||
>
|
|
||||||
<path
|
|
||||||
d="M12 4.5C7 4.5 2.73 7.61 1 12c1.73 4.39 6 7.5 11 7.5s9.27-3.11 11-7.5c-1.73-4.39-6-7.5-11-7.5zM12 17c-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5 5-2.24 5-5 5zm0-8c-1.66 0-3 1.34-3 3s1.34 3 3 3 3-1.34 3-3-1.34-3-3-3z"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
</span>
|
</span>
|
||||||
<span
|
<span
|
||||||
className="MuiTouchRipple-root"
|
className="MuiTouchRipple-root"
|
||||||
@ -170,240 +67,257 @@ exports[`renders correctly with one strategy 1`] = `
|
|||||||
</button>
|
</button>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div
|
</div>
|
||||||
aria-describedby={null}
|
</div>
|
||||||
className=""
|
<div
|
||||||
onBlur={[Function]}
|
className="makeStyles-bodyContainer-3"
|
||||||
onFocus={[Function]}
|
>
|
||||||
onMouseLeave={[Function]}
|
<ul
|
||||||
onMouseOver={[Function]}
|
className="MuiList-root MuiList-padding"
|
||||||
onTouchEnd={[Function]}
|
>
|
||||||
onTouchStart={[Function]}
|
<li
|
||||||
title="You cannot delete a built-in strategy"
|
className="MuiListItem-root makeStyles-listItem-1 MuiListItem-gutters"
|
||||||
|
disabled={false}
|
||||||
>
|
>
|
||||||
<button
|
<div
|
||||||
className="MuiButtonBase-root MuiIconButton-root Mui-disabled Mui-disabled"
|
className="MuiListItemAvatar-root"
|
||||||
disabled={true}
|
>
|
||||||
onBlur={[Function]}
|
<svg
|
||||||
onDragLeave={[Function]}
|
aria-hidden={true}
|
||||||
onFocus={[Function]}
|
className="MuiSvgIcon-root"
|
||||||
onKeyDown={[Function]}
|
focusable="false"
|
||||||
onKeyUp={[Function]}
|
style={
|
||||||
onMouseDown={[Function]}
|
Object {
|
||||||
onMouseLeave={[Function]}
|
"color": "#0000008a",
|
||||||
onMouseUp={[Function]}
|
}
|
||||||
onTouchEnd={[Function]}
|
}
|
||||||
onTouchMove={[Function]}
|
viewBox="0 0 24 24"
|
||||||
onTouchStart={[Function]}
|
>
|
||||||
tabIndex={-1}
|
<path
|
||||||
type="button"
|
d="M20.5 11H19V7c0-1.1-.9-2-2-2h-4V3.5C13 2.12 11.88 1 10.5 1S8 2.12 8 3.5V5H4c-1.1 0-1.99.9-1.99 2v3.8H3.5c1.49 0 2.7 1.21 2.7 2.7s-1.21 2.7-2.7 2.7H2V20c0 1.1.9 2 2 2h3.8v-1.5c0-1.49 1.21-2.7 2.7-2.7 1.49 0 2.7 1.21 2.7 2.7V22H17c1.1 0 2-.9 2-2v-4h1.5c1.38 0 2.5-1.12 2.5-2.5S21.88 11 20.5 11z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
className="MuiListItemText-root MuiListItemText-multiline"
|
||||||
>
|
>
|
||||||
<span
|
<span
|
||||||
className="MuiIconButton-label"
|
className="MuiTypography-root MuiListItemText-primary MuiTypography-body1 MuiTypography-displayBlock"
|
||||||
>
|
>
|
||||||
<svg
|
<a
|
||||||
className="MuiSvgIcon-root"
|
href="/strategies/flexibleRollout"
|
||||||
focusable="false"
|
onClick={[Function]}
|
||||||
role="img"
|
|
||||||
viewBox="0 0 24 24"
|
|
||||||
>
|
>
|
||||||
<path
|
<strong>
|
||||||
d="M3 17.25V21h3.75L17.81 9.94l-3.75-3.75L3 17.25zM20.71 7.04c.39-.39.39-1.02 0-1.41l-2.34-2.34a.9959.9959 0 00-1.41 0l-1.83 1.83 3.75 3.75 1.83-1.83z"
|
Gradual rollout
|
||||||
/>
|
</strong>
|
||||||
<title>
|
</a>
|
||||||
Edit strategy
|
|
||||||
</title>
|
|
||||||
</svg>
|
|
||||||
</span>
|
</span>
|
||||||
</button>
|
<p
|
||||||
</div>
|
className="MuiTypography-root MuiListItemText-secondary MuiTypography-body2 MuiTypography-colorTextSecondary MuiTypography-displayBlock"
|
||||||
<div
|
>
|
||||||
aria-describedby={null}
|
Roll out to a percentage of your userbase, and ensure that the experience is the same for the user on each visit.
|
||||||
className=""
|
</p>
|
||||||
onBlur={[Function]}
|
</div>
|
||||||
onFocus={[Function]}
|
<div>
|
||||||
onMouseLeave={[Function]}
|
|
||||||
onMouseOver={[Function]}
|
|
||||||
onTouchEnd={[Function]}
|
|
||||||
onTouchStart={[Function]}
|
|
||||||
title="You cannot delete a built-in strategy"
|
|
||||||
>
|
|
||||||
<button
|
|
||||||
className="MuiButtonBase-root MuiIconButton-root Mui-disabled Mui-disabled"
|
|
||||||
disabled={true}
|
|
||||||
onBlur={[Function]}
|
|
||||||
onDragLeave={[Function]}
|
|
||||||
onFocus={[Function]}
|
|
||||||
onKeyDown={[Function]}
|
|
||||||
onKeyUp={[Function]}
|
|
||||||
onMouseDown={[Function]}
|
|
||||||
onMouseLeave={[Function]}
|
|
||||||
onMouseUp={[Function]}
|
|
||||||
onTouchEnd={[Function]}
|
|
||||||
onTouchMove={[Function]}
|
|
||||||
onTouchStart={[Function]}
|
|
||||||
tabIndex={-1}
|
|
||||||
type="button"
|
|
||||||
>
|
|
||||||
<span
|
<span
|
||||||
className="MuiIconButton-label"
|
aria-describedby={null}
|
||||||
|
className=""
|
||||||
|
id="useId-1"
|
||||||
|
onBlur={[Function]}
|
||||||
|
onFocus={[Function]}
|
||||||
|
onMouseLeave={[Function]}
|
||||||
|
onMouseOver={[Function]}
|
||||||
|
onTouchEnd={[Function]}
|
||||||
|
onTouchStart={[Function]}
|
||||||
|
title="Deprecate strategy"
|
||||||
>
|
>
|
||||||
<svg
|
<button
|
||||||
className="MuiSvgIcon-root"
|
aria-labelledby="useId-1"
|
||||||
focusable="false"
|
className="MuiButtonBase-root MuiIconButton-root"
|
||||||
role="img"
|
disabled={false}
|
||||||
viewBox="0 0 24 24"
|
onBlur={[Function]}
|
||||||
|
onClick={[Function]}
|
||||||
|
onDragLeave={[Function]}
|
||||||
|
onFocus={[Function]}
|
||||||
|
onKeyDown={[Function]}
|
||||||
|
onKeyUp={[Function]}
|
||||||
|
onMouseDown={[Function]}
|
||||||
|
onMouseLeave={[Function]}
|
||||||
|
onMouseUp={[Function]}
|
||||||
|
onTouchEnd={[Function]}
|
||||||
|
onTouchMove={[Function]}
|
||||||
|
onTouchStart={[Function]}
|
||||||
|
tabIndex={0}
|
||||||
|
type="button"
|
||||||
>
|
>
|
||||||
<path
|
<span
|
||||||
d="M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zM19 4h-3.5l-1-1h-5l-1 1H5v2h14V4z"
|
className="MuiIconButton-label"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
aria-hidden={true}
|
||||||
|
className="MuiSvgIcon-root"
|
||||||
|
focusable="false"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M12 4.5C7 4.5 2.73 7.61 1 12c1.73 4.39 6 7.5 11 7.5s9.27-3.11 11-7.5c-1.73-4.39-6-7.5-11-7.5zM12 17c-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5 5-2.24 5-5 5zm0-8c-1.66 0-3 1.34-3 3s1.34 3 3 3 3-1.34 3-3-1.34-3-3-3z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</span>
|
||||||
|
<span
|
||||||
|
className="MuiTouchRipple-root"
|
||||||
/>
|
/>
|
||||||
<title>
|
</button>
|
||||||
Delete strategy
|
|
||||||
</title>
|
|
||||||
</svg>
|
|
||||||
</span>
|
</span>
|
||||||
</button>
|
</div>
|
||||||
</div>
|
<div
|
||||||
</li>
|
aria-describedby={null}
|
||||||
</ul>
|
className=""
|
||||||
</div>
|
onBlur={[Function]}
|
||||||
</div>
|
onFocus={[Function]}
|
||||||
|
onMouseLeave={[Function]}
|
||||||
|
onMouseOver={[Function]}
|
||||||
|
onTouchEnd={[Function]}
|
||||||
|
onTouchStart={[Function]}
|
||||||
|
title="You cannot delete a built-in strategy"
|
||||||
|
>
|
||||||
|
<button
|
||||||
|
className="MuiButtonBase-root MuiIconButton-root Mui-disabled Mui-disabled"
|
||||||
|
disabled={true}
|
||||||
|
onBlur={[Function]}
|
||||||
|
onDragLeave={[Function]}
|
||||||
|
onFocus={[Function]}
|
||||||
|
onKeyDown={[Function]}
|
||||||
|
onKeyUp={[Function]}
|
||||||
|
onMouseDown={[Function]}
|
||||||
|
onMouseLeave={[Function]}
|
||||||
|
onMouseUp={[Function]}
|
||||||
|
onTouchEnd={[Function]}
|
||||||
|
onTouchMove={[Function]}
|
||||||
|
onTouchStart={[Function]}
|
||||||
|
tabIndex={-1}
|
||||||
|
type="button"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
className="MuiIconButton-label"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
className="MuiSvgIcon-root"
|
||||||
|
focusable="false"
|
||||||
|
role="img"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M3 17.25V21h3.75L17.81 9.94l-3.75-3.75L3 17.25zM20.71 7.04c.39-.39.39-1.02 0-1.41l-2.34-2.34a.9959.9959 0 00-1.41 0l-1.83 1.83 3.75 3.75 1.83-1.83z"
|
||||||
|
/>
|
||||||
|
<title>
|
||||||
|
Edit strategy
|
||||||
|
</title>
|
||||||
|
</svg>
|
||||||
|
</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
aria-describedby={null}
|
||||||
|
className=""
|
||||||
|
onBlur={[Function]}
|
||||||
|
onFocus={[Function]}
|
||||||
|
onMouseLeave={[Function]}
|
||||||
|
onMouseOver={[Function]}
|
||||||
|
onTouchEnd={[Function]}
|
||||||
|
onTouchStart={[Function]}
|
||||||
|
title="You cannot delete a built-in strategy"
|
||||||
|
>
|
||||||
|
<button
|
||||||
|
className="MuiButtonBase-root MuiIconButton-root Mui-disabled Mui-disabled"
|
||||||
|
disabled={true}
|
||||||
|
onBlur={[Function]}
|
||||||
|
onDragLeave={[Function]}
|
||||||
|
onFocus={[Function]}
|
||||||
|
onKeyDown={[Function]}
|
||||||
|
onKeyUp={[Function]}
|
||||||
|
onMouseDown={[Function]}
|
||||||
|
onMouseLeave={[Function]}
|
||||||
|
onMouseUp={[Function]}
|
||||||
|
onTouchEnd={[Function]}
|
||||||
|
onTouchMove={[Function]}
|
||||||
|
onTouchStart={[Function]}
|
||||||
|
tabIndex={-1}
|
||||||
|
type="button"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
className="MuiIconButton-label"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
className="MuiSvgIcon-root"
|
||||||
|
focusable="false"
|
||||||
|
role="img"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zM19 4h-3.5l-1-1h-5l-1 1H5v2h14V4z"
|
||||||
|
/>
|
||||||
|
<title>
|
||||||
|
Delete strategy
|
||||||
|
</title>
|
||||||
|
</svg>
|
||||||
|
</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>,
|
||||||
|
<div
|
||||||
|
aria-atomic={true}
|
||||||
|
aria-live="polite"
|
||||||
|
className="makeStyles-container-11"
|
||||||
|
data-testid="ANNOUNCER_ELEMENT_TEST_ID"
|
||||||
|
role="status"
|
||||||
|
>
|
||||||
|
Navigated to Strategies
|
||||||
|
</div>,
|
||||||
|
]
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`renders correctly with one strategy without permissions 1`] = `
|
exports[`renders correctly with one strategy without permissions 1`] = `
|
||||||
<div
|
Array [
|
||||||
className="MuiPaper-root MuiPaper-elevation1 MuiPaper-rounded"
|
|
||||||
style={
|
|
||||||
Object {
|
|
||||||
"borderRadius": "10px",
|
|
||||||
"boxShadow": "none",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<div
|
<div
|
||||||
className="makeStyles-headerContainer-2"
|
className="MuiPaper-root MuiPaper-elevation1 MuiPaper-rounded"
|
||||||
|
style={
|
||||||
|
Object {
|
||||||
|
"borderRadius": "10px",
|
||||||
|
"boxShadow": "none",
|
||||||
|
}
|
||||||
|
}
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
className="makeStyles-headerTitleContainer-6"
|
className="makeStyles-headerContainer-2"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
className=""
|
className="makeStyles-headerTitleContainer-6"
|
||||||
data-loading={true}
|
|
||||||
>
|
|
||||||
<h1
|
|
||||||
className="MuiTypography-root makeStyles-headerTitle-7 MuiTypography-h1"
|
|
||||||
>
|
|
||||||
Strategies
|
|
||||||
</h1>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className="makeStyles-headerActions-8"
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
id="useId-2"
|
|
||||||
>
|
|
||||||
<button
|
|
||||||
aria-describedby="useId-2"
|
|
||||||
className="MuiButtonBase-root MuiButton-root MuiButton-contained MuiButton-containedPrimary"
|
|
||||||
data-testid="ADD_NEW_STRATEGY_ID"
|
|
||||||
disabled={false}
|
|
||||||
onBlur={[Function]}
|
|
||||||
onClick={[Function]}
|
|
||||||
onDragLeave={[Function]}
|
|
||||||
onFocus={[Function]}
|
|
||||||
onKeyDown={[Function]}
|
|
||||||
onKeyUp={[Function]}
|
|
||||||
onMouseDown={[Function]}
|
|
||||||
onMouseLeave={[Function]}
|
|
||||||
onMouseUp={[Function]}
|
|
||||||
onTouchEnd={[Function]}
|
|
||||||
onTouchMove={[Function]}
|
|
||||||
onTouchStart={[Function]}
|
|
||||||
tabIndex={0}
|
|
||||||
type="button"
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
className="MuiButton-label"
|
|
||||||
>
|
|
||||||
New strategy
|
|
||||||
<span
|
|
||||||
className="MuiButton-endIcon MuiButton-iconSizeMedium"
|
|
||||||
/>
|
|
||||||
</span>
|
|
||||||
<span
|
|
||||||
className="MuiTouchRipple-root"
|
|
||||||
/>
|
|
||||||
</button>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className="makeStyles-bodyContainer-3"
|
|
||||||
>
|
|
||||||
<ul
|
|
||||||
className="MuiList-root MuiList-padding"
|
|
||||||
>
|
|
||||||
<li
|
|
||||||
className="MuiListItem-root makeStyles-listItem-1 MuiListItem-gutters"
|
|
||||||
disabled={false}
|
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
className="MuiListItemAvatar-root"
|
className=""
|
||||||
|
data-loading={true}
|
||||||
>
|
>
|
||||||
<svg
|
<h1
|
||||||
aria-hidden={true}
|
className="MuiTypography-root makeStyles-headerTitle-7 MuiTypography-h1"
|
||||||
className="MuiSvgIcon-root"
|
|
||||||
focusable="false"
|
|
||||||
style={
|
|
||||||
Object {
|
|
||||||
"color": "#0000008a",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
viewBox="0 0 24 24"
|
|
||||||
>
|
>
|
||||||
<path
|
Strategies
|
||||||
d="M20.5 11H19V7c0-1.1-.9-2-2-2h-4V3.5C13 2.12 11.88 1 10.5 1S8 2.12 8 3.5V5H4c-1.1 0-1.99.9-1.99 2v3.8H3.5c1.49 0 2.7 1.21 2.7 2.7s-1.21 2.7-2.7 2.7H2V20c0 1.1.9 2 2 2h3.8v-1.5c0-1.49 1.21-2.7 2.7-2.7 1.49 0 2.7 1.21 2.7 2.7V22H17c1.1 0 2-.9 2-2v-4h1.5c1.38 0 2.5-1.12 2.5-2.5S21.88 11 20.5 11z"
|
</h1>
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
className="MuiListItemText-root MuiListItemText-multiline"
|
className="makeStyles-headerActions-8"
|
||||||
>
|
>
|
||||||
<span
|
<span
|
||||||
className="MuiTypography-root MuiListItemText-primary MuiTypography-body1 MuiTypography-displayBlock"
|
id="useId-2"
|
||||||
>
|
|
||||||
<a
|
|
||||||
href="/strategies/flexibleRollout"
|
|
||||||
onClick={[Function]}
|
|
||||||
>
|
|
||||||
<strong>
|
|
||||||
Gradual rollout
|
|
||||||
</strong>
|
|
||||||
</a>
|
|
||||||
</span>
|
|
||||||
<p
|
|
||||||
className="MuiTypography-root MuiListItemText-secondary MuiTypography-body2 MuiTypography-colorTextSecondary MuiTypography-displayBlock"
|
|
||||||
>
|
|
||||||
Roll out to a percentage of your userbase, and ensure that the experience is the same for the user on each visit.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<span
|
|
||||||
aria-describedby={null}
|
|
||||||
className=""
|
|
||||||
id="useId-3"
|
|
||||||
onBlur={[Function]}
|
|
||||||
onFocus={[Function]}
|
|
||||||
onMouseLeave={[Function]}
|
|
||||||
onMouseOver={[Function]}
|
|
||||||
onTouchEnd={[Function]}
|
|
||||||
onTouchStart={[Function]}
|
|
||||||
title="Deprecate strategy"
|
|
||||||
>
|
>
|
||||||
<button
|
<button
|
||||||
aria-labelledby="useId-3"
|
aria-describedby="useId-2"
|
||||||
className="MuiButtonBase-root MuiIconButton-root"
|
className="MuiButtonBase-root MuiButton-root MuiButton-contained MuiButton-containedPrimary"
|
||||||
|
data-testid="ADD_NEW_STRATEGY_ID"
|
||||||
disabled={false}
|
disabled={false}
|
||||||
onBlur={[Function]}
|
onBlur={[Function]}
|
||||||
onClick={[Function]}
|
onClick={[Function]}
|
||||||
@ -421,18 +335,12 @@ exports[`renders correctly with one strategy without permissions 1`] = `
|
|||||||
type="button"
|
type="button"
|
||||||
>
|
>
|
||||||
<span
|
<span
|
||||||
className="MuiIconButton-label"
|
className="MuiButton-label"
|
||||||
>
|
>
|
||||||
<svg
|
New strategy
|
||||||
aria-hidden={true}
|
<span
|
||||||
className="MuiSvgIcon-root"
|
className="MuiButton-endIcon MuiButton-iconSizeMedium"
|
||||||
focusable="false"
|
/>
|
||||||
viewBox="0 0 24 24"
|
|
||||||
>
|
|
||||||
<path
|
|
||||||
d="M12 4.5C7 4.5 2.73 7.61 1 12c1.73 4.39 6 7.5 11 7.5s9.27-3.11 11-7.5c-1.73-4.39-6-7.5-11-7.5zM12 17c-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5 5-2.24 5-5 5zm0-8c-1.66 0-3 1.34-3 3s1.34 3 3 3 3-1.34 3-3-1.34-3-3-3z"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
</span>
|
</span>
|
||||||
<span
|
<span
|
||||||
className="MuiTouchRipple-root"
|
className="MuiTouchRipple-root"
|
||||||
@ -440,102 +348,216 @@ exports[`renders correctly with one strategy without permissions 1`] = `
|
|||||||
</button>
|
</button>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div
|
</div>
|
||||||
aria-describedby={null}
|
</div>
|
||||||
className=""
|
<div
|
||||||
onBlur={[Function]}
|
className="makeStyles-bodyContainer-3"
|
||||||
onFocus={[Function]}
|
>
|
||||||
onMouseLeave={[Function]}
|
<ul
|
||||||
onMouseOver={[Function]}
|
className="MuiList-root MuiList-padding"
|
||||||
onTouchEnd={[Function]}
|
>
|
||||||
onTouchStart={[Function]}
|
<li
|
||||||
title="You cannot delete a built-in strategy"
|
className="MuiListItem-root makeStyles-listItem-1 MuiListItem-gutters"
|
||||||
|
disabled={false}
|
||||||
>
|
>
|
||||||
<button
|
<div
|
||||||
className="MuiButtonBase-root MuiIconButton-root Mui-disabled Mui-disabled"
|
className="MuiListItemAvatar-root"
|
||||||
disabled={true}
|
>
|
||||||
onBlur={[Function]}
|
<svg
|
||||||
onDragLeave={[Function]}
|
aria-hidden={true}
|
||||||
onFocus={[Function]}
|
className="MuiSvgIcon-root"
|
||||||
onKeyDown={[Function]}
|
focusable="false"
|
||||||
onKeyUp={[Function]}
|
style={
|
||||||
onMouseDown={[Function]}
|
Object {
|
||||||
onMouseLeave={[Function]}
|
"color": "#0000008a",
|
||||||
onMouseUp={[Function]}
|
}
|
||||||
onTouchEnd={[Function]}
|
}
|
||||||
onTouchMove={[Function]}
|
viewBox="0 0 24 24"
|
||||||
onTouchStart={[Function]}
|
>
|
||||||
tabIndex={-1}
|
<path
|
||||||
type="button"
|
d="M20.5 11H19V7c0-1.1-.9-2-2-2h-4V3.5C13 2.12 11.88 1 10.5 1S8 2.12 8 3.5V5H4c-1.1 0-1.99.9-1.99 2v3.8H3.5c1.49 0 2.7 1.21 2.7 2.7s-1.21 2.7-2.7 2.7H2V20c0 1.1.9 2 2 2h3.8v-1.5c0-1.49 1.21-2.7 2.7-2.7 1.49 0 2.7 1.21 2.7 2.7V22H17c1.1 0 2-.9 2-2v-4h1.5c1.38 0 2.5-1.12 2.5-2.5S21.88 11 20.5 11z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
className="MuiListItemText-root MuiListItemText-multiline"
|
||||||
>
|
>
|
||||||
<span
|
<span
|
||||||
className="MuiIconButton-label"
|
className="MuiTypography-root MuiListItemText-primary MuiTypography-body1 MuiTypography-displayBlock"
|
||||||
>
|
>
|
||||||
<svg
|
<a
|
||||||
className="MuiSvgIcon-root"
|
href="/strategies/flexibleRollout"
|
||||||
focusable="false"
|
onClick={[Function]}
|
||||||
role="img"
|
|
||||||
viewBox="0 0 24 24"
|
|
||||||
>
|
>
|
||||||
<path
|
<strong>
|
||||||
d="M3 17.25V21h3.75L17.81 9.94l-3.75-3.75L3 17.25zM20.71 7.04c.39-.39.39-1.02 0-1.41l-2.34-2.34a.9959.9959 0 00-1.41 0l-1.83 1.83 3.75 3.75 1.83-1.83z"
|
Gradual rollout
|
||||||
/>
|
</strong>
|
||||||
<title>
|
</a>
|
||||||
Edit strategy
|
|
||||||
</title>
|
|
||||||
</svg>
|
|
||||||
</span>
|
</span>
|
||||||
</button>
|
<p
|
||||||
</div>
|
className="MuiTypography-root MuiListItemText-secondary MuiTypography-body2 MuiTypography-colorTextSecondary MuiTypography-displayBlock"
|
||||||
<div
|
>
|
||||||
aria-describedby={null}
|
Roll out to a percentage of your userbase, and ensure that the experience is the same for the user on each visit.
|
||||||
className=""
|
</p>
|
||||||
onBlur={[Function]}
|
</div>
|
||||||
onFocus={[Function]}
|
<div>
|
||||||
onMouseLeave={[Function]}
|
|
||||||
onMouseOver={[Function]}
|
|
||||||
onTouchEnd={[Function]}
|
|
||||||
onTouchStart={[Function]}
|
|
||||||
title="You cannot delete a built-in strategy"
|
|
||||||
>
|
|
||||||
<button
|
|
||||||
className="MuiButtonBase-root MuiIconButton-root Mui-disabled Mui-disabled"
|
|
||||||
disabled={true}
|
|
||||||
onBlur={[Function]}
|
|
||||||
onDragLeave={[Function]}
|
|
||||||
onFocus={[Function]}
|
|
||||||
onKeyDown={[Function]}
|
|
||||||
onKeyUp={[Function]}
|
|
||||||
onMouseDown={[Function]}
|
|
||||||
onMouseLeave={[Function]}
|
|
||||||
onMouseUp={[Function]}
|
|
||||||
onTouchEnd={[Function]}
|
|
||||||
onTouchMove={[Function]}
|
|
||||||
onTouchStart={[Function]}
|
|
||||||
tabIndex={-1}
|
|
||||||
type="button"
|
|
||||||
>
|
|
||||||
<span
|
<span
|
||||||
className="MuiIconButton-label"
|
aria-describedby={null}
|
||||||
|
className=""
|
||||||
|
id="useId-3"
|
||||||
|
onBlur={[Function]}
|
||||||
|
onFocus={[Function]}
|
||||||
|
onMouseLeave={[Function]}
|
||||||
|
onMouseOver={[Function]}
|
||||||
|
onTouchEnd={[Function]}
|
||||||
|
onTouchStart={[Function]}
|
||||||
|
title="Deprecate strategy"
|
||||||
>
|
>
|
||||||
<svg
|
<button
|
||||||
className="MuiSvgIcon-root"
|
aria-labelledby="useId-3"
|
||||||
focusable="false"
|
className="MuiButtonBase-root MuiIconButton-root"
|
||||||
role="img"
|
disabled={false}
|
||||||
viewBox="0 0 24 24"
|
onBlur={[Function]}
|
||||||
|
onClick={[Function]}
|
||||||
|
onDragLeave={[Function]}
|
||||||
|
onFocus={[Function]}
|
||||||
|
onKeyDown={[Function]}
|
||||||
|
onKeyUp={[Function]}
|
||||||
|
onMouseDown={[Function]}
|
||||||
|
onMouseLeave={[Function]}
|
||||||
|
onMouseUp={[Function]}
|
||||||
|
onTouchEnd={[Function]}
|
||||||
|
onTouchMove={[Function]}
|
||||||
|
onTouchStart={[Function]}
|
||||||
|
tabIndex={0}
|
||||||
|
type="button"
|
||||||
>
|
>
|
||||||
<path
|
<span
|
||||||
d="M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zM19 4h-3.5l-1-1h-5l-1 1H5v2h14V4z"
|
className="MuiIconButton-label"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
aria-hidden={true}
|
||||||
|
className="MuiSvgIcon-root"
|
||||||
|
focusable="false"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M12 4.5C7 4.5 2.73 7.61 1 12c1.73 4.39 6 7.5 11 7.5s9.27-3.11 11-7.5c-1.73-4.39-6-7.5-11-7.5zM12 17c-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5 5-2.24 5-5 5zm0-8c-1.66 0-3 1.34-3 3s1.34 3 3 3 3-1.34 3-3-1.34-3-3-3z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</span>
|
||||||
|
<span
|
||||||
|
className="MuiTouchRipple-root"
|
||||||
/>
|
/>
|
||||||
<title>
|
</button>
|
||||||
Delete strategy
|
|
||||||
</title>
|
|
||||||
</svg>
|
|
||||||
</span>
|
</span>
|
||||||
</button>
|
</div>
|
||||||
</div>
|
<div
|
||||||
</li>
|
aria-describedby={null}
|
||||||
</ul>
|
className=""
|
||||||
</div>
|
onBlur={[Function]}
|
||||||
</div>
|
onFocus={[Function]}
|
||||||
|
onMouseLeave={[Function]}
|
||||||
|
onMouseOver={[Function]}
|
||||||
|
onTouchEnd={[Function]}
|
||||||
|
onTouchStart={[Function]}
|
||||||
|
title="You cannot delete a built-in strategy"
|
||||||
|
>
|
||||||
|
<button
|
||||||
|
className="MuiButtonBase-root MuiIconButton-root Mui-disabled Mui-disabled"
|
||||||
|
disabled={true}
|
||||||
|
onBlur={[Function]}
|
||||||
|
onDragLeave={[Function]}
|
||||||
|
onFocus={[Function]}
|
||||||
|
onKeyDown={[Function]}
|
||||||
|
onKeyUp={[Function]}
|
||||||
|
onMouseDown={[Function]}
|
||||||
|
onMouseLeave={[Function]}
|
||||||
|
onMouseUp={[Function]}
|
||||||
|
onTouchEnd={[Function]}
|
||||||
|
onTouchMove={[Function]}
|
||||||
|
onTouchStart={[Function]}
|
||||||
|
tabIndex={-1}
|
||||||
|
type="button"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
className="MuiIconButton-label"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
className="MuiSvgIcon-root"
|
||||||
|
focusable="false"
|
||||||
|
role="img"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M3 17.25V21h3.75L17.81 9.94l-3.75-3.75L3 17.25zM20.71 7.04c.39-.39.39-1.02 0-1.41l-2.34-2.34a.9959.9959 0 00-1.41 0l-1.83 1.83 3.75 3.75 1.83-1.83z"
|
||||||
|
/>
|
||||||
|
<title>
|
||||||
|
Edit strategy
|
||||||
|
</title>
|
||||||
|
</svg>
|
||||||
|
</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
aria-describedby={null}
|
||||||
|
className=""
|
||||||
|
onBlur={[Function]}
|
||||||
|
onFocus={[Function]}
|
||||||
|
onMouseLeave={[Function]}
|
||||||
|
onMouseOver={[Function]}
|
||||||
|
onTouchEnd={[Function]}
|
||||||
|
onTouchStart={[Function]}
|
||||||
|
title="You cannot delete a built-in strategy"
|
||||||
|
>
|
||||||
|
<button
|
||||||
|
className="MuiButtonBase-root MuiIconButton-root Mui-disabled Mui-disabled"
|
||||||
|
disabled={true}
|
||||||
|
onBlur={[Function]}
|
||||||
|
onDragLeave={[Function]}
|
||||||
|
onFocus={[Function]}
|
||||||
|
onKeyDown={[Function]}
|
||||||
|
onKeyUp={[Function]}
|
||||||
|
onMouseDown={[Function]}
|
||||||
|
onMouseLeave={[Function]}
|
||||||
|
onMouseUp={[Function]}
|
||||||
|
onTouchEnd={[Function]}
|
||||||
|
onTouchMove={[Function]}
|
||||||
|
onTouchStart={[Function]}
|
||||||
|
tabIndex={-1}
|
||||||
|
type="button"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
className="MuiIconButton-label"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
className="MuiSvgIcon-root"
|
||||||
|
focusable="false"
|
||||||
|
role="img"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zM19 4h-3.5l-1-1h-5l-1 1H5v2h14V4z"
|
||||||
|
/>
|
||||||
|
<title>
|
||||||
|
Delete strategy
|
||||||
|
</title>
|
||||||
|
</svg>
|
||||||
|
</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>,
|
||||||
|
<div
|
||||||
|
aria-atomic={true}
|
||||||
|
aria-live="polite"
|
||||||
|
className="makeStyles-container-11"
|
||||||
|
data-testid="ANNOUNCER_ELEMENT_TEST_ID"
|
||||||
|
role="status"
|
||||||
|
>
|
||||||
|
Navigated to Strategies
|
||||||
|
</div>,
|
||||||
|
]
|
||||||
`;
|
`;
|
||||||
|
21
frontend/src/hooks/usePageTitle.ts
Normal file
21
frontend/src/hooks/usePageTitle.ts
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
import { useEffect, useContext } from 'react';
|
||||||
|
import { AnnouncerContext } from 'component/common/Announcer/AnnouncerContext/AnnouncerContext';
|
||||||
|
|
||||||
|
export const usePageTitle = (title: string) => {
|
||||||
|
const { setAnnouncement } = useContext(AnnouncerContext);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
document.title = title;
|
||||||
|
return () => {
|
||||||
|
document.title = DEFAULT_PAGE_TITLE;
|
||||||
|
};
|
||||||
|
}, [title]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (title !== DEFAULT_PAGE_TITLE) {
|
||||||
|
setAnnouncement(`Navigated to ${title}`);
|
||||||
|
}
|
||||||
|
}, [setAnnouncement, title]);
|
||||||
|
};
|
||||||
|
|
||||||
|
const DEFAULT_PAGE_TITLE = 'Unleash';
|
@ -49,3 +49,4 @@ export const INPUT_ERROR_TEXT = 'INPUT_ERROR_TEXT';
|
|||||||
export const HEADER_USER_AVATAR = 'HEADER_USER_AVATAR';
|
export const HEADER_USER_AVATAR = 'HEADER_USER_AVATAR';
|
||||||
export const SIDEBAR_MODAL_ID = 'SIDEBAR_MODAL_ID';
|
export const SIDEBAR_MODAL_ID = 'SIDEBAR_MODAL_ID';
|
||||||
export const AUTH_PAGE_ID = 'AUTH_PAGE_ID';
|
export const AUTH_PAGE_ID = 'AUTH_PAGE_ID';
|
||||||
|
export const ANNOUNCER_ELEMENT_TEST_ID = 'ANNOUNCER_ELEMENT_TEST_ID';
|
||||||
|
@ -3,6 +3,7 @@ import { BrowserRouter as Router } from 'react-router-dom';
|
|||||||
import { render as rtlRender, RenderOptions } from '@testing-library/react';
|
import { render as rtlRender, RenderOptions } from '@testing-library/react';
|
||||||
import { SWRConfig } from 'swr';
|
import { SWRConfig } from 'swr';
|
||||||
import { MainThemeProvider } from 'themes/MainThemeProvider';
|
import { MainThemeProvider } from 'themes/MainThemeProvider';
|
||||||
|
import { AnnouncerProvider } from 'component/common/Announcer/AnnouncerProvider/AnnouncerProvider';
|
||||||
|
|
||||||
export const render = (
|
export const render = (
|
||||||
ui: JSX.Element,
|
ui: JSX.Element,
|
||||||
@ -23,7 +24,9 @@ const Wrapper: FC = ({ children }) => {
|
|||||||
return (
|
return (
|
||||||
<SWRConfig value={{ provider: () => new Map() }}>
|
<SWRConfig value={{ provider: () => new Map() }}>
|
||||||
<MainThemeProvider>
|
<MainThemeProvider>
|
||||||
<Router>{children}</Router>
|
<AnnouncerProvider>
|
||||||
|
<Router>{children}</Router>
|
||||||
|
</AnnouncerProvider>
|
||||||
</MainThemeProvider>
|
</MainThemeProvider>
|
||||||
</SWRConfig>
|
</SWRConfig>
|
||||||
);
|
);
|
||||||
|
Loading…
Reference in New Issue
Block a user