chore(admin): convert context to use assertion technique (#18598)

This commit is contained in:
Josh 2023-10-27 11:03:39 +01:00 committed by GitHub
parent 6ee826075d
commit c7c44a121f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
40 changed files with 212 additions and 2551 deletions

View File

@ -24,7 +24,7 @@ import { Route, Switch } from 'react-router-dom';
import { PrivateRoute } from './components/PrivateRoute';
import { ADMIN_PERMISSIONS_CE, ACTION_SET_ADMIN_PERMISSIONS } from './constants';
import { useConfiguration } from './hooks/useConfiguration';
import { useConfiguration } from './contexts/configuration';
import { useEnterprise } from './hooks/useEnterprise';
// @ts-expect-error not converted yet
import AuthPage from './pages/AuthPage';

View File

@ -15,7 +15,7 @@ import valid from 'semver/functions/valid';
import packageJSON from '../../../package.json';
import { UserEntity } from '../../../shared/entities';
import { useConfiguration } from '../hooks/useConfiguration';
import { useConfiguration } from '../contexts/configuration';
import { APIResponse, APIResponseUsersLegacy } from '../types/adminAPI';
import { getFullName } from '../utils/getFullName';
import { hashAdminUserEmail } from '../utils/hashAdminUserEmail';

View File

@ -1,6 +1,6 @@
import * as React from 'react';
import { ConfigurationContext, ConfigurationContextValue } from '../contexts/configuration';
import { ConfigurationContextProvider, ConfigurationContextValue } from '../contexts/configuration';
interface ConfigurationProviderProps {
children: React.ReactNode;
@ -37,30 +37,18 @@ const ConfigurationProvider = ({
[defaultAuthLogo, defaultMenuLogo]
);
const configurationValue = React.useMemo(() => {
return {
logos: {
return (
<ConfigurationContextProvider
updateProjectSettings={updateProjectSettings}
showReleaseNotification={showReleaseNotification}
showTutorials={showTutorials}
logos={{
menu: { custom: menuLogo, default: defaultMenuLogo },
auth: { custom: authLogo, default: defaultAuthLogo },
},
updateProjectSettings,
showReleaseNotification,
showTutorials,
};
}, [
menuLogo,
defaultMenuLogo,
authLogo,
defaultAuthLogo,
updateProjectSettings,
showReleaseNotification,
showTutorials,
]);
return (
<ConfigurationContext.Provider value={configurationValue}>
}}
>
{children}
</ConfigurationContext.Provider>
</ConfigurationContextProvider>
);
};

View File

@ -8,6 +8,7 @@
import * as React from 'react';
import { createContext } from '@radix-ui/react-context';
import defaultsDeep from 'lodash/defaultsDeep';
import { IntlProvider } from 'react-intl';
@ -20,14 +21,10 @@ interface LocalesContextValue {
localeNames: Record<string, string>;
}
const LocalesContext = React.createContext<LocalesContextValue>({
changeLocale: () => {
throw new Error('LocalesContext: changeLocale() is not implemented');
},
localeNames: {},
});
const [LocalesContextProvider, useLocalesContext] =
createContext<LocalesContextValue>('LocalesContext');
const useLocales = () => React.useContext(LocalesContext);
const useLocales = () => useLocalesContext('useLocales');
/* -------------------------------------------------------------------------------------------------
* LanguageProvider
@ -76,14 +73,11 @@ const LanguageProvider = ({ children, localeNames, messages }: LanguageProviderP
const appMessages = defaultsDeep(messages[locale], messages.en);
const contextValue = React.useMemo(
() => ({ changeLocale, localeNames }),
[changeLocale, localeNames]
);
return (
<IntlProvider locale={locale} defaultLocale="en" messages={appMessages} textComponent="span">
<LocalesContext.Provider value={contextValue}>{children}</LocalesContext.Provider>
<LocalesContextProvider changeLocale={changeLocale} localeNames={localeNames}>
{children}
</LocalesContextProvider>
</IntlProvider>
);
};

View File

@ -23,7 +23,7 @@ import { useIntl } from 'react-intl';
import { NavLink as RouterNavLink, useHistory, useLocation } from 'react-router-dom';
import styled from 'styled-components';
import { useConfiguration } from '../hooks/useConfiguration';
import { useConfiguration } from '../contexts/configuration';
import { Menu } from '../hooks/useMenu';
const LinkUserWrapper = styled(Box)`

View File

@ -14,7 +14,7 @@ import {
import { QueryClient, QueryClientProvider } from 'react-query';
import { Provider } from 'react-redux';
import { AdminContext, AdminContextValue } from '../contexts/admin';
import { AdminContextProvider, AdminContextValue } from '../contexts/admin';
import { ConfigurationProvider, ConfigurationProviderProps } from './ConfigurationProvider';
import { GuidedTourProvider } from './GuidedTour/Provider';
@ -84,7 +84,7 @@ const Providers = ({
<Theme>
<QueryClientProvider client={queryClient}>
<Provider store={store}>
<AdminContext.Provider value={{ getAdminInjectedComponents }}>
<AdminContextProvider getAdminInjectedComponents={getAdminInjectedComponents}>
<ConfigurationProvider
authLogo={authLogo}
menuLogo={menuLogo}
@ -113,7 +113,7 @@ const Providers = ({
</LibraryProvider>
</StrapiAppProvider>
</ConfigurationProvider>
</AdminContext.Provider>
</AdminContextProvider>
</Provider>
</QueryClientProvider>
</Theme>

View File

@ -4,7 +4,7 @@ import { DesignSystemProvider } from '@strapi/design-system';
import { useIntl } from 'react-intl';
import { createGlobalStyle } from 'styled-components';
import { useThemeToggle } from '../hooks/useThemeToggle';
import { useThemeToggle } from '../contexts/themeToggle';
interface ThemeProps {
children: React.ReactNode;

View File

@ -2,7 +2,7 @@ import * as React from 'react';
import { DefaultTheme } from 'styled-components';
import { ThemeToggleContext, ThemeName, NonSystemThemeName } from '../contexts/themeToggle';
import { ThemeToggleContextProvider, ThemeName, NonSystemThemeName } from '../contexts/themeToggle';
const THEME_KEY = 'STRAPI_THEME';
@ -48,16 +48,16 @@ const ThemeToggleProvider = ({ children, themes }: ThemeToggleProviderProps) =>
};
}, []);
const themeValues = React.useMemo(() => {
return {
currentTheme,
onChangeTheme: handleChangeTheme,
themes,
systemTheme,
};
}, [currentTheme, handleChangeTheme, themes, systemTheme]);
return <ThemeToggleContext.Provider value={themeValues}>{children}</ThemeToggleContext.Provider>;
return (
<ThemeToggleContextProvider
currentTheme={currentTheme}
onChangeTheme={handleChangeTheme}
themes={themes}
systemTheme={systemTheme}
>
{children}
</ThemeToggleContextProvider>
);
};
export { ThemeToggleProvider };

View File

@ -1,6 +1,6 @@
import styled from 'styled-components';
import { useConfiguration } from '../hooks/useConfiguration';
import { useConfiguration } from '../contexts/configuration';
const Img = styled.img`
height: ${72 / 16}rem;

View File

@ -1,9 +0,0 @@
/* eslint-disable check-file/filename-naming-convention */
export function useLocalesProvider() {
return {
changeLocale() {},
localeNames: { en: 'English' },
messages: ['test'],
};
}

View File

@ -1,6 +1,6 @@
import { render } from '@tests/utils';
import { useConfiguration } from '../../hooks/useConfiguration';
import { useConfiguration } from '../../contexts/configuration';
import { ConfigurationProvider } from '../ConfigurationProvider';
describe('ConfigurationProvider', () => {

View File

@ -23,6 +23,8 @@ const localStorageMock = {
const originalLocalStorage = window.localStorage;
describe('NPS survey', () => {
const NPS_KEY = 'STRAPI_NPS_SURVEY_SETTINGS';
beforeAll(() => {
// @ts-expect-error we're mocking.
window.localStorage = localStorageMock;
@ -39,11 +41,17 @@ describe('NPS survey', () => {
beforeEach(() => {
jest.useFakeTimers();
localStorageMock.getItem.mockImplementation((key) => {
if (key === NPS_KEY) {
return { enabled: true };
}
return originalLocalStorage.getItem(key);
});
});
it('renders survey if enabled', () => {
localStorageMock.getItem.mockReturnValueOnce({ enabled: true });
const { getByLabelText, getByText } = render(<NpsSurvey />);
act(() => jest.runAllTimers());
@ -55,7 +63,13 @@ describe('NPS survey', () => {
});
it("renders survey if settings don't exist", () => {
localStorageMock.getItem.mockReturnValueOnce(null);
localStorageMock.getItem.mockImplementation((key) => {
if (key === NPS_KEY) {
return null;
}
return originalLocalStorage.getItem(key);
});
const { getByLabelText, getByText } = render(<NpsSurvey />);
@ -68,15 +82,20 @@ describe('NPS survey', () => {
});
it('does not render survey if disabled', () => {
localStorageMock.getItem.mockReturnValueOnce({ enabled: false });
localStorageMock.getItem.mockImplementation((key) => {
if (key === NPS_KEY) {
return { enabled: false };
}
return originalLocalStorage.getItem(key);
});
const { queryByText } = render(<NpsSurvey />);
act(() => jest.runAllTimers());
expect(queryByText(/not at all likely/i)).not.toBeInTheDocument();
});
it('saves user response', async () => {
localStorageMock.getItem.mockReturnValueOnce({ enabled: true });
const { getByRole, queryByText, getByText } = render(<NpsSurvey />);
act(() => jest.runAllTimers());
@ -105,8 +124,6 @@ describe('NPS survey', () => {
const originalError = console.error;
console.error = jest.fn();
localStorageMock.getItem.mockReturnValueOnce({ enabled: true });
server.use(
rest.post('https://analytics.strapi.io/submit-nps', (req, res, ctx) => {
return res.once(ctx.status(500));
@ -137,8 +154,6 @@ describe('NPS survey', () => {
});
it('saves first user dismissal', async () => {
localStorageMock.getItem.mockReturnValueOnce({ enabled: true });
const { queryByText, user, getByRole } = render(<NpsSurvey />);
act(() => {
@ -164,9 +179,13 @@ describe('NPS survey', () => {
it('saves subsequent user dismissal', async () => {
const firstDismissalDate = '2000-07-20T09:28:51.963Z';
localStorageMock.getItem.mockReturnValueOnce({
enabled: true,
firstDismissalDate,
localStorageMock.getItem.mockImplementation((key) => {
if (key === NPS_KEY) {
return { enabled: true, firstDismissalDate };
}
return originalLocalStorage.getItem(key);
});
const { user, queryByText, getByText } = render(<NpsSurvey />);
@ -197,7 +216,13 @@ describe('NPS survey', () => {
const withinDelay = new Date('2020-01-31');
const beyondDelay = new Date('2020-03-31');
localStorageMock.getItem.mockReturnValue({ enabled: true, lastResponseDate: initialDate });
localStorageMock.getItem.mockImplementation((key) => {
if (key === NPS_KEY) {
return { enabled: true, lastResponseDate: initialDate };
}
return originalLocalStorage.getItem(key);
});
jest.setSystemTime(initialDate);
@ -226,11 +251,17 @@ describe('NPS survey', () => {
const withinDelay = new Date('2020-01-04');
const beyondDelay = new Date('2020-01-08');
localStorageMock.getItem.mockReturnValue({
enabled: true,
firstDismissalDate: initialDate,
lastDismissalDate: null,
lastResponseDate: null,
localStorageMock.getItem.mockImplementation((key) => {
if (key === NPS_KEY) {
return {
enabled: true,
firstDismissalDate: initialDate,
lastDismissalDate: null,
lastResponseDate: null,
};
}
return originalLocalStorage.getItem(key);
});
jest.setSystemTime(initialDate);
@ -260,11 +291,17 @@ describe('NPS survey', () => {
const withinDelay = new Date('2020-03-30');
const beyondDelay = new Date('2020-04-01');
localStorageMock.getItem.mockReturnValue({
enabled: true,
firstDismissalDate: initialDate,
lastDismissalDate: initialDate,
lastResponseDate: null,
localStorageMock.getItem.mockImplementation((key) => {
if (key === NPS_KEY) {
return {
enabled: true,
firstDismissalDate: initialDate,
lastDismissalDate: initialDate,
lastResponseDate: null,
};
}
return originalLocalStorage.getItem(key);
});
jest.setSystemTime(initialDate);

View File

@ -1,17 +1,15 @@
import * as React from 'react';
import { createContext } from '@radix-ui/react-context';
import type { StrapiApp } from '../StrapiApp';
interface AdminContextValue {
getAdminInjectedComponents: StrapiApp['getAdminInjectedComponents'];
}
const AdminContext = React.createContext<AdminContextValue>({
getAdminInjectedComponents() {
throw new Error('AdminContext: getAdminInjectedComponents() not implemented');
},
});
const [AdminContextProvider, useAdminContext] = createContext<AdminContextValue>('AdminContext');
const useAdmin = () => React.useContext(AdminContext);
const useAdmin = () => useAdminContext('useAdmin');
export { AdminContext, useAdmin };
export { AdminContextProvider, useAdmin };
export type { AdminContextValue };

View File

@ -2,6 +2,7 @@
import * as React from 'react';
import { createContext } from '@radix-ui/react-context';
import { Entity } from '@strapi/types';
interface PseudoEvent {
@ -29,36 +30,19 @@ interface ApiTokenPermissionsContextProviderProps extends ApiTokenPermissionsCon
children: React.ReactNode[];
}
const ApiTokenPermissionsContext = React.createContext<ApiTokenPermissionsContextValue>({
selectedAction: null,
routes: [],
selectedActions: [],
data: {
allActionsIds: [],
permissions: [],
},
onChange: () => {},
onChangeSelectAll: () => {},
setSelectedAction: () => {},
});
const [ApiTokenPermissionsContextProvider, useApiTokenPermissionsContext] =
createContext<ApiTokenPermissionsContextValue>('ApiTokenPermissionsContext');
const ApiTokenPermissionsContextProvider = ({
const ApiTokenPermissionsProvider = ({
children,
...rest
}: ApiTokenPermissionsContextProviderProps) => {
return (
<ApiTokenPermissionsContext.Provider value={rest}>
{children}
</ApiTokenPermissionsContext.Provider>
<ApiTokenPermissionsContextProvider {...rest}>{children}</ApiTokenPermissionsContextProvider>
);
};
const useApiTokenPermissionsContext = () => React.useContext(ApiTokenPermissionsContext);
export {
ApiTokenPermissionsContext,
ApiTokenPermissionsContextProvider,
useApiTokenPermissionsContext,
};
const useApiTokenPermissions = () => useApiTokenPermissionsContext('useApiTokenPermissions');
export { ApiTokenPermissionsProvider, useApiTokenPermissions };
export type { ApiTokenPermissionsContextValue, ApiTokenPermissionsContextProviderProps };

View File

@ -1,4 +1,4 @@
import { createContext } from 'react';
import { createContext } from '@radix-ui/react-context';
export interface ConfigurationContextValue {
logos: {
@ -10,16 +10,9 @@ export interface ConfigurationContextValue {
updateProjectSettings: (settings: { authLogo?: string; menuLogo?: string }) => void;
}
const ConfigurationContext = createContext<ConfigurationContextValue>({
logos: {
auth: { default: '' },
menu: { default: '' },
},
showTutorials: false,
showReleaseNotification: false,
updateProjectSettings: () => {
throw new Error('updateProjectSettings was not implemented');
},
});
const [ConfigurationContextProvider, useConfigurationContext] =
createContext<ConfigurationContextValue>('ConfigurationContext');
export { ConfigurationContext };
const useConfiguration = () => useConfigurationContext('useConfiguration');
export { ConfigurationContextProvider, useConfiguration };

View File

@ -1,9 +1,8 @@
import { createContext } from 'react';
import { createContext } from '@radix-ui/react-context';
import { DefaultTheme } from 'styled-components';
export type ThemeName = 'light' | 'dark' | 'system';
export type NonSystemThemeName = Exclude<ThemeName, 'system'>;
type ThemeName = 'light' | 'dark' | 'system';
type NonSystemThemeName = Exclude<ThemeName, 'system'>;
interface ThemeToggleContextContextValue {
currentTheme?: ThemeName;
@ -15,4 +14,10 @@ interface ThemeToggleContextContextValue {
systemTheme?: NonSystemThemeName;
}
export const ThemeToggleContext = createContext<ThemeToggleContextContextValue>({});
const [ThemeToggleContextProvider, useThemeToggleContext] =
createContext<ThemeToggleContextContextValue>('ThemeToggleContext');
const useThemeToggle = () => useThemeToggleContext('useThemeToggle');
export { ThemeToggleContextProvider, useThemeToggle };
export type { ThemeName, NonSystemThemeName, ThemeToggleContextContextValue };

View File

@ -1,9 +0,0 @@
const useConfiguration = () => {
return {
logos: {
auth: { custom: 'customAuthLogo.png', default: 'defaultAuthLogo.png' },
},
};
};
export { useConfiguration };

View File

@ -1,5 +0,0 @@
import { useContext } from 'react';
import { ConfigurationContext } from '../contexts/configuration';
export const useConfiguration = () => useContext(ConfigurationContext);

View File

@ -1,9 +0,0 @@
import { useContext } from 'react';
import { ThemeToggleContext } from '../contexts/themeToggle';
export const useThemeToggle = () => {
const context = useContext(ThemeToggleContext);
return context;
};

View File

@ -15,8 +15,8 @@ import { GuidedTourModal } from '../components/GuidedTour/Modal';
import { LeftMenu } from '../components/LeftMenu';
import { Onboarding } from '../components/Onboarding';
import { ACTION_SET_APP_RUNTIME_STATUS } from '../constants';
import { useConfiguration } from '../contexts/configuration';
import { useTypedDispatch, useTypedSelector } from '../core/store/hooks';
import { useConfiguration } from '../hooks/useConfiguration';
import { useMenu } from '../hooks/useMenu';
import { AppLayout } from '../layouts/AppLayout';
import { createRoute } from '../utils/createRoute';

View File

@ -1,865 +0,0 @@
import React from 'react';
import { lightTheme, ThemeProvider } from '@strapi/design-system';
import { render } from '@testing-library/react';
import { createMemoryHistory } from 'history';
import { IntlProvider } from 'react-intl';
import { Router } from 'react-router-dom';
import * as yup from 'yup';
import BaseLogin from '../BaseLogin';
jest.mock('../../../../../hooks/useConfiguration', () => ({
useConfiguration: () => ({
logos: {
auth: { custom: 'customAuthLogo.png', default: 'defaultAuthLogo.png' },
},
}),
}));
describe('ADMIN | PAGES | AUTH | BaseLogin', () => {
it('should render and match the snapshot', () => {
const history = createMemoryHistory();
const { container } = render(
<IntlProvider locale="en" messages={{}} defaultLocale="en" textComponent="span">
<ThemeProvider theme={lightTheme}>
<Router history={history}>
<BaseLogin onSubmit={() => {}} schema={yup.object()} />
</Router>
</ThemeProvider>
</IntlProvider>
);
expect(container.firstChild).toMatchInlineSnapshot(`
.c27 {
border: 0;
-webkit-clip: rect(0 0 0 0);
clip: rect(0 0 0 0);
height: 1px;
margin: -1px;
overflow: hidden;
padding: 0;
position: absolute;
width: 1px;
}
.c8 {
font-weight: 600;
font-size: 2rem;
line-height: 1.25;
color: #32324d;
}
.c10 {
font-size: 1rem;
line-height: 1.5;
color: #666687;
}
.c13 {
font-size: 0.75rem;
line-height: 1.33;
font-weight: 600;
color: #32324d;
}
.c15 {
font-size: 0.875rem;
line-height: 1.43;
color: #d02b20;
}
.c28 {
font-size: 0.875rem;
line-height: 1.43;
color: #32324d;
}
.c36 {
font-size: 0.75rem;
line-height: 1.33;
font-weight: 600;
color: #ffffff;
}
.c40 {
font-size: 0.875rem;
line-height: 1.43;
color: #4945ff;
}
.c1 {
background: #ffffff;
padding-top: 48px;
padding-right: 56px;
padding-bottom: 48px;
padding-left: 56px;
border-radius: 4px;
box-shadow: 0px 1px 4px rgba(33,33,52,0.1);
}
.c6 {
padding-top: 24px;
padding-bottom: 4px;
}
.c9 {
padding-bottom: 32px;
}
.c22 {
padding-right: 12px;
padding-left: 8px;
}
.c23 {
background: transparent;
border-style: none;
}
.c31 {
padding-left: 8px;
}
.c32 {
background: #4945ff;
padding: 8px;
padding-right: 16px;
padding-left: 16px;
border-radius: 4px;
border-color: #4945ff;
border: 1px solid #4945ff;
width: 100%;
cursor: pointer;
}
.c38 {
padding-top: 16px;
}
.c3 {
-webkit-align-items: center;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-flex-direction: row;
-ms-flex-direction: row;
flex-direction: row;
}
.c11 {
-webkit-align-items: stretch;
-webkit-box-align: stretch;
-ms-flex-align: stretch;
align-items: stretch;
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-flex-direction: column;
-ms-flex-direction: column;
flex-direction: column;
gap: 24px;
}
.c12 {
-webkit-align-items: stretch;
-webkit-box-align: stretch;
-ms-flex-align: stretch;
align-items: stretch;
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-flex-direction: column;
-ms-flex-direction: column;
flex-direction: column;
gap: 4px;
}
.c17 {
-webkit-align-items: center;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-flex-direction: row;
-ms-flex-direction: row;
flex-direction: row;
-webkit-box-pack: justify;
-webkit-justify-content: space-between;
-ms-flex-pack: justify;
justify-content: space-between;
}
.c24 {
-webkit-align-items: center;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-flex-direction: row;
-ms-flex-direction: row;
flex-direction: row;
-webkit-box-pack: unset;
-webkit-justify-content: unset;
-ms-flex-pack: unset;
justify-content: unset;
}
.c33 {
-webkit-align-items: center;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
display: -webkit-inline-box;
display: -webkit-inline-flex;
display: -ms-inline-flexbox;
display: inline-flex;
-webkit-flex-direction: row;
-ms-flex-direction: row;
flex-direction: row;
gap: 8px;
-webkit-box-pack: center;
-webkit-justify-content: center;
-ms-flex-pack: center;
justify-content: center;
}
.c37 {
-webkit-align-items: center;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-flex-direction: row;
-ms-flex-direction: row;
flex-direction: row;
-webkit-box-pack: center;
-webkit-justify-content: center;
-ms-flex-pack: center;
justify-content: center;
}
.c34 {
position: relative;
outline: none;
}
.c34 > svg {
height: 12px;
width: 12px;
}
.c34 > svg > g,
.c34 > svg path {
fill: #ffffff;
}
.c34[aria-disabled='true'] {
pointer-events: none;
}
.c34:after {
-webkit-transition-property: all;
transition-property: all;
-webkit-transition-duration: 0.2s;
transition-duration: 0.2s;
border-radius: 8px;
content: '';
position: absolute;
top: -4px;
bottom: -4px;
left: -4px;
right: -4px;
border: 2px solid transparent;
}
.c34:focus-visible {
outline: none;
}
.c34:focus-visible:after {
border-radius: 8px;
content: '';
position: absolute;
top: -5px;
bottom: -5px;
left: -5px;
right: -5px;
border: 2px solid #4945ff;
}
.c30 {
height: 18px;
min-width: 18px;
margin: 0;
border-radius: 4px;
border: 1px solid #c0c0cf;
-webkit-appearance: none;
background-color: #ffffff;
cursor: pointer;
}
.c30:checked {
background-color: #4945ff;
border: 1px solid #4945ff;
}
.c30:checked:after {
content: '';
display: block;
position: relative;
background: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTAiIGhlaWdodD0iOCIgdmlld0JveD0iMCAwIDEwIDgiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CiAgPHBhdGgKICAgIGQ9Ik04LjU1MzIzIDAuMzk2OTczQzguNjMxMzUgMC4zMTYzNTUgOC43NjA1MSAwLjMxNTgxMSA4LjgzOTMxIDAuMzk1NzY4TDkuODYyNTYgMS40MzQwN0M5LjkzODkzIDEuNTExNTcgOS45MzkzNSAxLjYzNTkgOS44NjM0OSAxLjcxMzlMNC4wNjQwMSA3LjY3NzI0QzMuOTg1OSA3Ljc1NzU1IDMuODU3MDcgNy43NTgwNSAzLjc3ODM0IDcuNjc4MzRMMC4xMzg2NiAzLjk5MzMzQzAuMDYxNzc5OCAzLjkxNTQ5IDAuMDYxNzEwMiAzLjc5MDMyIDAuMTM4NTA0IDMuNzEyNEwxLjE2MjEzIDIuNjczNzJDMS4yNDAzOCAyLjU5NDMyIDEuMzY4NDMgMi41OTQyMiAxLjQ0NjggMi42NzM0OEwzLjkyMTc0IDUuMTc2NDdMOC41NTMyMyAwLjM5Njk3M1oiCiAgICBmaWxsPSJ3aGl0ZSIKICAvPgo8L3N2Zz4=) no-repeat no-repeat center center;
width: 10px;
height: 10px;
left: 50%;
top: 50%;
-webkit-transform: translateX(-50%) translateY(-50%);
-ms-transform: translateX(-50%) translateY(-50%);
transform: translateX(-50%) translateY(-50%);
}
.c30:checked:disabled:after {
background: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTAiIGhlaWdodD0iOCIgdmlld0JveD0iMCAwIDEwIDgiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CiAgPHBhdGgKICAgIGQ9Ik04LjU1MzIzIDAuMzk2OTczQzguNjMxMzUgMC4zMTYzNTUgOC43NjA1MSAwLjMxNTgxMSA4LjgzOTMxIDAuMzk1NzY4TDkuODYyNTYgMS40MzQwN0M5LjkzODkzIDEuNTExNTcgOS45MzkzNSAxLjYzNTkgOS44NjM0OSAxLjcxMzlMNC4wNjQwMSA3LjY3NzI0QzMuOTg1OSA3Ljc1NzU1IDMuODU3MDcgNy43NTgwNSAzLjc3ODM0IDcuNjc4MzRMMC4xMzg2NiAzLjk5MzMzQzAuMDYxNzc5OCAzLjkxNTQ5IDAuMDYxNzEwMiAzLjc5MDMyIDAuMTM4NTA0IDMuNzEyNEwxLjE2MjEzIDIuNjczNzJDMS4yNDAzOCAyLjU5NDMyIDEuMzY4NDMgMi41OTQyMiAxLjQ0NjggMi42NzM0OEwzLjkyMTc0IDUuMTc2NDdMOC41NTMyMyAwLjM5Njk3M1oiCiAgICBmaWxsPSIjOEU4RUE5IgogIC8+Cjwvc3ZnPg==) no-repeat no-repeat center center;
}
.c30:disabled {
background-color: #dcdce4;
border: 1px solid #c0c0cf;
}
.c30:indeterminate {
background-color: #4945ff;
border: 1px solid #4945ff;
}
.c30:indeterminate:after {
content: '';
display: block;
position: relative;
color: white;
height: 2px;
width: 10px;
background-color: #ffffff;
left: 50%;
top: 50%;
-webkit-transform: translateX(-50%) translateY(-50%);
-ms-transform: translateX(-50%) translateY(-50%);
transform: translateX(-50%) translateY(-50%);
}
.c30:indeterminate:disabled {
background-color: #dcdce4;
border: 1px solid #c0c0cf;
}
.c30:indeterminate:disabled:after {
background-color: #8e8ea9;
}
.c35 {
height: 2rem;
}
.c35 svg {
height: 0.75rem;
width: auto;
}
.c35[aria-disabled='true'] {
border: 1px solid #dcdce4;
background: #eaeaef;
}
.c35[aria-disabled='true'] .c7 {
color: #666687;
}
.c35[aria-disabled='true'] svg > g,
.c35[aria-disabled='true'] svg path {
fill: #666687;
}
.c35[aria-disabled='true']:active {
border: 1px solid #dcdce4;
background: #eaeaef;
}
.c35[aria-disabled='true']:active .c7 {
color: #666687;
}
.c35[aria-disabled='true']:active svg > g,
.c35[aria-disabled='true']:active svg path {
fill: #666687;
}
.c35:hover {
border: 1px solid #7b79ff;
background: #7b79ff;
}
.c35:active {
border: 1px solid #4945ff;
background: #4945ff;
}
.c35 svg > g,
.c35 svg path {
fill: #ffffff;
}
.c14 {
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-align-items: center;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
}
.c16 {
line-height: 0;
}
.c29 {
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-align-items: flex-start;
-webkit-box-align: flex-start;
-ms-flex-align: flex-start;
align-items: flex-start;
}
.c29 * {
cursor: pointer;
}
.c19 {
border: none;
border-radius: 4px;
padding-bottom: 0.65625rem;
padding-left: 16px;
padding-right: 16px;
padding-top: 0.65625rem;
color: #32324d;
font-weight: 400;
font-size: 0.875rem;
display: block;
width: 100%;
background: inherit;
}
.c19::-webkit-input-placeholder {
color: #8e8ea9;
opacity: 1;
}
.c19::-moz-placeholder {
color: #8e8ea9;
opacity: 1;
}
.c19:-ms-input-placeholder {
color: #8e8ea9;
opacity: 1;
}
.c19::placeholder {
color: #8e8ea9;
opacity: 1;
}
.c19[aria-disabled='true'] {
color: inherit;
}
.c19:focus {
outline: none;
box-shadow: none;
}
.c20 {
border: none;
border-radius: 4px;
padding-bottom: 0.65625rem;
padding-left: 16px;
padding-right: 0;
padding-top: 0.65625rem;
color: #32324d;
font-weight: 400;
font-size: 0.875rem;
display: block;
width: 100%;
background: inherit;
}
.c20::-webkit-input-placeholder {
color: #8e8ea9;
opacity: 1;
}
.c20::-moz-placeholder {
color: #8e8ea9;
opacity: 1;
}
.c20:-ms-input-placeholder {
color: #8e8ea9;
opacity: 1;
}
.c20::placeholder {
color: #8e8ea9;
opacity: 1;
}
.c20[aria-disabled='true'] {
color: inherit;
}
.c20:focus {
outline: none;
box-shadow: none;
}
.c18 {
border: 1px solid #dcdce4;
border-radius: 4px;
background: #ffffff;
outline: none;
box-shadow: 0;
-webkit-transition-property: border-color,box-shadow,fill;
transition-property: border-color,box-shadow,fill;
-webkit-transition-duration: 0.2s;
transition-duration: 0.2s;
}
.c18:focus-within {
border: 1px solid #4945ff;
box-shadow: #4945ff 0px 0px 0px 2px;
}
.c25 {
font-size: 1.6rem;
padding: 0;
}
.c0:focus-visible {
outline: none;
}
.c39 {
display: -webkit-inline-box;
display: -webkit-inline-flex;
display: -ms-inline-flexbox;
display: inline-flex;
-webkit-align-items: center;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
-webkit-text-decoration: none;
text-decoration: none;
gap: 8px;
position: relative;
outline: none;
}
.c39 svg {
font-size: 0.625rem;
}
.c39 svg path {
fill: #4945ff;
}
.c39:hover {
color: #7b79ff;
}
.c39:active {
color: #271fe0;
}
.c39:after {
-webkit-transition-property: all;
transition-property: all;
-webkit-transition-duration: 0.2s;
transition-duration: 0.2s;
border-radius: 8px;
content: '';
position: absolute;
top: -4px;
bottom: -4px;
left: -4px;
right: -4px;
border: 2px solid transparent;
}
.c39:focus-visible {
outline: none;
}
.c39:focus-visible:after {
border-radius: 8px;
content: '';
position: absolute;
top: -5px;
bottom: -5px;
left: -5px;
right: -5px;
border: 2px solid #4945ff;
}
.c5 {
height: 4.5rem;
}
.c2 {
margin: 0 auto;
width: 552px;
}
.c4 {
-webkit-flex-direction: column;
-ms-flex-direction: column;
flex-direction: column;
}
.c26 svg {
height: 1rem;
width: 1rem;
}
.c26 svg path {
fill: #666687;
}
.c21::-ms-reveal {
display: none;
}
<main
aria-labelledby="main-content-title"
class="c0"
id="main-content"
tabindex="-1"
>
<div
class="c1 c2"
>
<form
action="#"
novalidate=""
>
<div
class="c3 c4"
>
<img
alt=""
aria-hidden="true"
class="c5"
src="customAuthLogo.png"
/>
<div
class="c6"
>
<h1
class="c7 c8"
>
Welcome!
</h1>
</div>
<div
class="c9"
>
<span
class="c7 c10"
>
Log in to your Strapi account
</span>
</div>
</div>
<div
class="c11"
>
<div>
<div
class=""
>
<div
class="c12"
>
<label
class="c7 c13 c14"
for=":r0:"
>
Email
<span
class="c7 c15 c16"
>
*
</span>
</label>
<div
class="c17 c18"
>
<input
aria-disabled="false"
aria-invalid="false"
aria-required="true"
class="c19"
id=":r0:"
name="email"
placeholder="kai@doe.com"
value=""
/>
</div>
</div>
</div>
</div>
<div>
<div
class=""
>
<div
class="c12"
>
<label
class="c7 c13 c14"
for=":r2:"
>
Password
<span
class="c7 c15 c16"
>
*
</span>
</label>
<div
class="c17 c18"
>
<input
aria-disabled="false"
aria-invalid="false"
aria-required="true"
class="c20 c21"
id=":r2:"
name="password"
type="password"
value=""
/>
<div
class="c22"
>
<button
class="c23 c24 c25 c26"
type="button"
>
<span
class="c27"
>
Hide password
</span>
<svg
aria-hidden="true"
fill="none"
focusable="false"
height="1rem"
viewBox="0 0 24 24"
width="1rem"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M4.048 6.875 2.103 4.93a1 1 0 1 1 1.414-1.415l16.966 16.966a1 1 0 1 1-1.414 1.415l-2.686-2.686a12.247 12.247 0 0 1-4.383.788c-3.573 0-6.559-1.425-8.962-3.783a15.842 15.842 0 0 1-2.116-2.568 11.096 11.096 0 0 1-.711-1.211 1.145 1.145 0 0 1 0-.875c.124-.258.36-.68.711-1.211.58-.876 1.283-1.75 2.116-2.569.326-.32.663-.622 1.01-.906Zm10.539 10.539-1.551-1.551a4.005 4.005 0 0 1-4.9-4.9L6.584 9.411a6 6 0 0 0 8.002 8.002ZM7.617 4.787A12.248 12.248 0 0 1 12 3.998c3.572 0 6.559 1.426 8.961 3.783a15.845 15.845 0 0 1 2.117 2.569c.351.532.587.954.711 1.211.116.242.115.636 0 .875-.124.257-.36.68-.711 1.211-.58.876-1.283 1.75-2.117 2.568-.325.32-.662.623-1.01.907l-2.536-2.537a6 6 0 0 0-8.002-8.002L7.617 4.787Zm3.347 3.347A4.005 4.005 0 0 1 16 11.998c0 .359-.047.706-.136 1.037l-4.9-4.901Z"
fill="#212134"
/>
</svg>
</button>
</div>
</div>
</div>
</div>
</div>
<div
class=""
>
<div
class="c12"
>
<label
class="c7 c28 c29"
>
<div
class=""
>
<input
aria-label="rememberMe"
class="c30"
id=":r4:"
name="rememberMe"
type="checkbox"
/>
</div>
<div
class="c31"
>
Remember me
</div>
</label>
</div>
</div>
<button
aria-disabled="false"
class="c32 c33 c34 c35"
type="submit"
>
<span
class="c7 c36"
>
Login
</span>
</button>
</div>
</form>
</div>
<div
class="c37"
>
<div
class="c38"
>
<a
class="c39"
href="/auth/forgot-password"
>
<span
class="c7 c40"
>
Forgot your password?
</span>
</a>
</div>
</div>
</main>
`);
});
});

View File

@ -1,464 +0,0 @@
import React from 'react';
import { lightTheme, ThemeProvider } from '@strapi/design-system';
import { render } from '@testing-library/react';
import { createMemoryHistory } from 'history';
import { IntlProvider } from 'react-intl';
import { Router } from 'react-router-dom';
import Oops from '..';
describe('ADMIN | PAGES | AUTH | Oops', () => {
it('should render and match the snapshot', () => {
const history = createMemoryHistory();
const { container } = render(
<IntlProvider locale="en" messages={{}} textComponent="span">
<ThemeProvider theme={lightTheme}>
<Router history={history}>
<Oops />
</Router>
</ThemeProvider>
</IntlProvider>
);
expect(container.firstChild).toMatchInlineSnapshot(`
.c8 {
font-size: 0.875rem;
line-height: 1.43;
display: block;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
color: #32324d;
}
.c20 {
font-weight: 600;
font-size: 2rem;
line-height: 1.25;
color: #32324d;
}
.c21 {
font-size: 0.875rem;
line-height: 1.43;
color: #32324d;
}
.c25 {
font-size: 0.875rem;
line-height: 1.43;
color: #4945ff;
}
.c1 {
padding-top: 24px;
padding-right: 40px;
}
.c3 {
background: #ffffff;
padding-right: 12px;
padding-left: 12px;
border-radius: 4px;
position: relative;
overflow: hidden;
width: 100%;
cursor: default;
}
.c6 {
-webkit-flex: 1;
-ms-flex: 1;
flex: 1;
}
.c12 {
padding-top: 8px;
padding-bottom: 64px;
}
.c14 {
background: #ffffff;
padding-top: 48px;
padding-right: 56px;
padding-bottom: 48px;
padding-left: 56px;
border-radius: 4px;
box-shadow: 0px 1px 4px rgba(33,33,52,0.1);
}
.c19 {
padding-top: 24px;
padding-bottom: 32px;
}
.c22 {
padding-top: 16px;
}
.c0 {
-webkit-align-items: center;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-flex-direction: row;
-ms-flex-direction: row;
flex-direction: row;
-webkit-box-pack: end;
-webkit-justify-content: flex-end;
-ms-flex-pack: end;
justify-content: flex-end;
}
.c2 {
-webkit-align-items: stretch;
-webkit-box-align: stretch;
-ms-flex-align: stretch;
align-items: stretch;
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-flex-direction: column;
-ms-flex-direction: column;
flex-direction: column;
gap: 4px;
}
.c4 {
-webkit-align-items: center;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-flex-direction: row;
-ms-flex-direction: row;
flex-direction: row;
gap: 16px;
-webkit-box-pack: justify;
-webkit-justify-content: space-between;
-ms-flex-pack: justify;
justify-content: space-between;
}
.c7 {
-webkit-align-items: center;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-flex-direction: row;
-ms-flex-direction: row;
flex-direction: row;
gap: 12px;
}
.c16 {
-webkit-align-items: center;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-flex-direction: row;
-ms-flex-direction: row;
flex-direction: row;
}
.c23 {
-webkit-align-items: center;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-flex-direction: row;
-ms-flex-direction: row;
flex-direction: row;
-webkit-box-pack: center;
-webkit-justify-content: center;
-ms-flex-pack: center;
justify-content: center;
}
.c5 {
border: 1px solid #dcdce4;
min-height: 2.5rem;
outline: none;
box-shadow: 0;
-webkit-transition-property: border-color,box-shadow,fill;
transition-property: border-color,box-shadow,fill;
-webkit-transition-duration: 0.2s;
transition-duration: 0.2s;
}
.c5[aria-disabled='true'] {
color: #666687;
}
.c5:focus-visible {
outline: none;
}
.c5:focus-within {
border: 1px solid #4945ff;
box-shadow: #4945ff 0px 0px 0px 2px;
}
.c11 > svg {
width: 0.375rem;
}
.c11 > svg > path {
fill: #666687;
}
.c9 {
-webkit-flex: 1;
-ms-flex: 1;
flex: 1;
}
.c10 {
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
gap: 4px;
-webkit-flex-wrap: wrap;
-ms-flex-wrap: wrap;
flex-wrap: wrap;
}
.c13:focus-visible {
outline: none;
}
.c24 {
display: -webkit-inline-box;
display: -webkit-inline-flex;
display: -ms-inline-flexbox;
display: inline-flex;
-webkit-align-items: center;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
-webkit-text-decoration: none;
text-decoration: none;
gap: 8px;
position: relative;
outline: none;
}
.c24 svg {
font-size: 0.625rem;
}
.c24 svg path {
fill: #4945ff;
}
.c24:hover {
color: #7b79ff;
}
.c24:active {
color: #271fe0;
}
.c24:after {
-webkit-transition-property: all;
transition-property: all;
-webkit-transition-duration: 0.2s;
transition-duration: 0.2s;
border-radius: 8px;
content: '';
position: absolute;
top: -4px;
bottom: -4px;
left: -4px;
right: -4px;
border: 2px solid transparent;
}
.c24:focus-visible {
outline: none;
}
.c24:focus-visible:after {
border-radius: 8px;
content: '';
position: absolute;
top: -5px;
bottom: -5px;
left: -5px;
right: -5px;
border: 2px solid #4945ff;
}
.c18 {
height: 4.5rem;
}
.c15 {
margin: 0 auto;
width: 552px;
}
.c17 {
-webkit-flex-direction: column;
-ms-flex-direction: column;
flex-direction: column;
}
<div>
<header
class="c0"
>
<div
class="c1"
>
<div
class=""
>
<div
class="c2"
>
<div
aria-autocomplete="none"
aria-controls="radix-:r3:"
aria-describedby=":r0:-hint :r0:-error"
aria-expanded="false"
aria-label="Select interface language"
class="c3 c4 c5"
data-state="closed"
dir="ltr"
id=":r0:"
overflow="hidden"
role="combobox"
tabindex="0"
>
<span
class="c6 c7"
>
<span
class="c8 c9"
>
<span
class="c10"
/>
</span>
</span>
<span
class="c7"
>
<span
aria-hidden="true"
class="c11"
>
<svg
fill="none"
height="1rem"
viewBox="0 0 14 8"
width="1rem"
xmlns="http://www.w3.org/2000/svg"
>
<path
clip-rule="evenodd"
d="M14 .889a.86.86 0 0 1-.26.625L7.615 7.736A.834.834 0 0 1 7 8a.834.834 0 0 1-.615-.264L.26 1.514A.861.861 0 0 1 0 .889c0-.24.087-.45.26-.625A.834.834 0 0 1 .875 0h12.25c.237 0 .442.088.615.264a.86.86 0 0 1 .26.625Z"
fill="#32324D"
fill-rule="evenodd"
/>
</svg>
</span>
</span>
</div>
</div>
</div>
</div>
</header>
<div
class="c12"
>
<main
aria-labelledby="main-content-title"
class="c13"
id="main-content"
tabindex="-1"
>
<div
class="c14 c15"
>
<div
class="c16 c17"
>
<img
alt=""
aria-hidden="true"
class="c18"
src=""
/>
<div
class="c19"
>
<h1
class="c20"
>
Oops...
</h1>
</div>
<span
class="c21"
>
Your account has been suspended.
</span>
<div
class="c22"
>
<span
class="c21"
>
If this is a mistake, please contact your administrator.
</span>
</div>
</div>
</div>
<div
class="c23"
>
<div
class="c22"
>
<a
class="c24"
href="/auth/login"
>
<span
class="c25"
>
Sign in
</span>
</a>
</div>
</div>
</main>
</div>
</div>
`);
});
});

View File

@ -8,14 +8,6 @@ import Register from '../index';
const PASSWORD_VALID = '!Eight_8_characters!';
jest.mock('../../../../../hooks/useConfiguration', () => ({
useConfiguration: () => ({
logos: {
auth: { custom: 'customAuthLogo.png', default: 'defaultAuthLogo.png' },
},
}),
}));
describe('AUTH | Register', () => {
beforeEach(() => {
jest.clearAllMocks();

View File

@ -1,923 +0,0 @@
import React from 'react';
import { lightTheme, ThemeProvider } from '@strapi/design-system';
import { render } from '@testing-library/react';
import { createMemoryHistory } from 'history';
import { IntlProvider } from 'react-intl';
import { Router } from 'react-router-dom';
import * as yup from 'yup';
import ResetPassword from '..';
jest.mock('@strapi/helper-plugin', () => ({
...jest.requireActual('@strapi/helper-plugin'),
useNotification: () => jest.fn({}),
}));
describe('ADMIN | PAGES | AUTH | ResetPassword', () => {
it('should render and match the snapshot', () => {
const history = createMemoryHistory();
const { container } = render(
<IntlProvider locale="en" messages={{}} textComponent="span">
<ThemeProvider theme={lightTheme}>
<Router history={history}>
<ResetPassword onSubmit={() => {}} schema={yup.object()} />
</Router>
</ThemeProvider>
</IntlProvider>
);
expect(container.firstChild).toMatchInlineSnapshot(`
.c36 {
border: 0;
-webkit-clip: rect(0 0 0 0);
clip: rect(0 0 0 0);
height: 1px;
margin: -1px;
overflow: hidden;
padding: 0;
position: absolute;
width: 1px;
}
.c9 {
font-size: 0.875rem;
line-height: 1.43;
display: block;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
color: #32324d;
}
.c21 {
font-weight: 600;
font-size: 2rem;
line-height: 1.25;
color: #32324d;
}
.c23 {
font-size: 0.75rem;
line-height: 1.33;
font-weight: 600;
color: #32324d;
}
.c25 {
font-size: 0.875rem;
line-height: 1.43;
color: #d02b20;
}
.c37 {
font-size: 0.75rem;
line-height: 1.33;
color: #666687;
}
.c42 {
font-size: 0.75rem;
line-height: 1.33;
font-weight: 600;
color: #ffffff;
}
.c46 {
font-size: 0.875rem;
line-height: 1.43;
color: #4945ff;
}
.c1 {
padding-top: 24px;
padding-right: 40px;
}
.c3 {
background: #ffffff;
padding-right: 12px;
padding-left: 12px;
border-radius: 4px;
position: relative;
overflow: hidden;
width: 100%;
cursor: default;
}
.c6 {
-webkit-flex: 1;
-ms-flex: 1;
flex: 1;
}
.c13 {
padding-top: 8px;
padding-bottom: 64px;
}
.c15 {
background: #ffffff;
padding-top: 48px;
padding-right: 56px;
padding-bottom: 48px;
padding-left: 56px;
border-radius: 4px;
box-shadow: 0px 1px 4px rgba(33,33,52,0.1);
}
.c20 {
padding-top: 24px;
padding-bottom: 32px;
}
.c31 {
padding-right: 12px;
padding-left: 8px;
}
.c32 {
background: transparent;
border-style: none;
}
.c38 {
background: #4945ff;
padding: 8px;
padding-right: 16px;
padding-left: 16px;
border-radius: 4px;
border-color: #4945ff;
border: 1px solid #4945ff;
cursor: pointer;
}
.c44 {
padding-top: 16px;
}
.c0 {
-webkit-align-items: center;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-flex-direction: row;
-ms-flex-direction: row;
flex-direction: row;
-webkit-box-pack: end;
-webkit-justify-content: flex-end;
-ms-flex-pack: end;
justify-content: flex-end;
}
.c2 {
-webkit-align-items: stretch;
-webkit-box-align: stretch;
-ms-flex-align: stretch;
align-items: stretch;
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-flex-direction: column;
-ms-flex-direction: column;
flex-direction: column;
gap: 4px;
}
.c4 {
-webkit-align-items: center;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-flex-direction: row;
-ms-flex-direction: row;
flex-direction: row;
gap: 16px;
-webkit-box-pack: justify;
-webkit-justify-content: space-between;
-ms-flex-pack: justify;
justify-content: space-between;
}
.c7 {
-webkit-align-items: center;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-flex-direction: row;
-ms-flex-direction: row;
flex-direction: row;
gap: 12px;
}
.c17 {
-webkit-align-items: center;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-flex-direction: row;
-ms-flex-direction: row;
flex-direction: row;
}
.c22 {
-webkit-align-items: stretch;
-webkit-box-align: stretch;
-ms-flex-align: stretch;
align-items: stretch;
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-flex-direction: column;
-ms-flex-direction: column;
flex-direction: column;
gap: 24px;
}
.c27 {
-webkit-align-items: center;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-flex-direction: row;
-ms-flex-direction: row;
flex-direction: row;
-webkit-box-pack: justify;
-webkit-justify-content: space-between;
-ms-flex-pack: justify;
justify-content: space-between;
}
.c33 {
-webkit-align-items: center;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-flex-direction: row;
-ms-flex-direction: row;
flex-direction: row;
-webkit-box-pack: unset;
-webkit-justify-content: unset;
-ms-flex-pack: unset;
justify-content: unset;
}
.c39 {
-webkit-align-items: center;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-flex-direction: row;
-ms-flex-direction: row;
flex-direction: row;
gap: 8px;
}
.c43 {
-webkit-align-items: center;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-flex-direction: row;
-ms-flex-direction: row;
flex-direction: row;
-webkit-box-pack: center;
-webkit-justify-content: center;
-ms-flex-pack: center;
justify-content: center;
}
.c40 {
position: relative;
outline: none;
}
.c40 > svg {
height: 12px;
width: 12px;
}
.c40 > svg > g,
.c40 > svg path {
fill: #ffffff;
}
.c40[aria-disabled='true'] {
pointer-events: none;
}
.c40:after {
-webkit-transition-property: all;
transition-property: all;
-webkit-transition-duration: 0.2s;
transition-duration: 0.2s;
border-radius: 8px;
content: '';
position: absolute;
top: -4px;
bottom: -4px;
left: -4px;
right: -4px;
border: 2px solid transparent;
}
.c40:focus-visible {
outline: none;
}
.c40:focus-visible:after {
border-radius: 8px;
content: '';
position: absolute;
top: -5px;
bottom: -5px;
left: -5px;
right: -5px;
border: 2px solid #4945ff;
}
.c41 {
height: 2rem;
}
.c41 svg {
height: 0.75rem;
width: auto;
}
.c41[aria-disabled='true'] {
border: 1px solid #dcdce4;
background: #eaeaef;
}
.c41[aria-disabled='true'] .c8 {
color: #666687;
}
.c41[aria-disabled='true'] svg > g,
.c41[aria-disabled='true'] svg path {
fill: #666687;
}
.c41[aria-disabled='true']:active {
border: 1px solid #dcdce4;
background: #eaeaef;
}
.c41[aria-disabled='true']:active .c8 {
color: #666687;
}
.c41[aria-disabled='true']:active svg > g,
.c41[aria-disabled='true']:active svg path {
fill: #666687;
}
.c41:hover {
border: 1px solid #7b79ff;
background: #7b79ff;
}
.c41:active {
border: 1px solid #4945ff;
background: #4945ff;
}
.c41 svg > g,
.c41 svg path {
fill: #ffffff;
}
.c24 {
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-align-items: center;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
}
.c26 {
line-height: 0;
}
.c5 {
border: 1px solid #dcdce4;
min-height: 2.5rem;
outline: none;
box-shadow: 0;
-webkit-transition-property: border-color,box-shadow,fill;
transition-property: border-color,box-shadow,fill;
-webkit-transition-duration: 0.2s;
transition-duration: 0.2s;
}
.c5[aria-disabled='true'] {
color: #666687;
}
.c5:focus-visible {
outline: none;
}
.c5:focus-within {
border: 1px solid #4945ff;
box-shadow: #4945ff 0px 0px 0px 2px;
}
.c12 > svg {
width: 0.375rem;
}
.c12 > svg > path {
fill: #666687;
}
.c10 {
-webkit-flex: 1;
-ms-flex: 1;
flex: 1;
}
.c11 {
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
gap: 4px;
-webkit-flex-wrap: wrap;
-ms-flex-wrap: wrap;
flex-wrap: wrap;
}
.c29 {
border: none;
border-radius: 4px;
padding-bottom: 0.65625rem;
padding-left: 16px;
padding-right: 0;
padding-top: 0.65625rem;
color: #32324d;
font-weight: 400;
font-size: 0.875rem;
display: block;
width: 100%;
background: inherit;
}
.c29::-webkit-input-placeholder {
color: #8e8ea9;
opacity: 1;
}
.c29::-moz-placeholder {
color: #8e8ea9;
opacity: 1;
}
.c29:-ms-input-placeholder {
color: #8e8ea9;
opacity: 1;
}
.c29::placeholder {
color: #8e8ea9;
opacity: 1;
}
.c29[aria-disabled='true'] {
color: inherit;
}
.c29:focus {
outline: none;
box-shadow: none;
}
.c28 {
border: 1px solid #dcdce4;
border-radius: 4px;
background: #ffffff;
outline: none;
box-shadow: 0;
-webkit-transition-property: border-color,box-shadow,fill;
transition-property: border-color,box-shadow,fill;
-webkit-transition-duration: 0.2s;
transition-duration: 0.2s;
}
.c28:focus-within {
border: 1px solid #4945ff;
box-shadow: #4945ff 0px 0px 0px 2px;
}
.c34 {
font-size: 1.6rem;
padding: 0;
}
.c14:focus-visible {
outline: none;
}
.c45 {
display: -webkit-inline-box;
display: -webkit-inline-flex;
display: -ms-inline-flexbox;
display: inline-flex;
-webkit-align-items: center;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
-webkit-text-decoration: none;
text-decoration: none;
gap: 8px;
position: relative;
outline: none;
}
.c45 svg {
font-size: 0.625rem;
}
.c45 svg path {
fill: #4945ff;
}
.c45:hover {
color: #7b79ff;
}
.c45:active {
color: #271fe0;
}
.c45:after {
-webkit-transition-property: all;
transition-property: all;
-webkit-transition-duration: 0.2s;
transition-duration: 0.2s;
border-radius: 8px;
content: '';
position: absolute;
top: -4px;
bottom: -4px;
left: -4px;
right: -4px;
border: 2px solid transparent;
}
.c45:focus-visible {
outline: none;
}
.c45:focus-visible:after {
border-radius: 8px;
content: '';
position: absolute;
top: -5px;
bottom: -5px;
left: -5px;
right: -5px;
border: 2px solid #4945ff;
}
.c19 {
height: 4.5rem;
}
.c16 {
margin: 0 auto;
width: 552px;
}
.c18 {
-webkit-flex-direction: column;
-ms-flex-direction: column;
flex-direction: column;
}
.c35 svg {
height: 1rem;
width: 1rem;
}
.c35 svg path {
fill: #666687;
}
.c30::-ms-reveal {
display: none;
}
<div>
<header
class="c0"
>
<div
class="c1"
>
<div
class=""
>
<div
class="c2"
>
<div
aria-autocomplete="none"
aria-controls="radix-:r3:"
aria-describedby=":r0:-hint :r0:-error"
aria-expanded="false"
aria-label="Select interface language"
class="c3 c4 c5"
data-state="closed"
dir="ltr"
id=":r0:"
overflow="hidden"
role="combobox"
tabindex="0"
>
<span
class="c6 c7"
>
<span
class="c8 c9 c10"
>
<span
class="c11"
/>
</span>
</span>
<span
class="c7"
>
<span
aria-hidden="true"
class="c12"
>
<svg
fill="none"
height="1rem"
viewBox="0 0 14 8"
width="1rem"
xmlns="http://www.w3.org/2000/svg"
>
<path
clip-rule="evenodd"
d="M14 .889a.86.86 0 0 1-.26.625L7.615 7.736A.834.834 0 0 1 7 8a.834.834 0 0 1-.615-.264L.26 1.514A.861.861 0 0 1 0 .889c0-.24.087-.45.26-.625A.834.834 0 0 1 .875 0h12.25c.237 0 .442.088.615.264a.86.86 0 0 1 .26.625Z"
fill="#32324D"
fill-rule="evenodd"
/>
</svg>
</span>
</span>
</div>
</div>
</div>
</div>
</header>
<div
class="c13"
>
<main
aria-labelledby="main-content-title"
class="c14"
id="main-content"
tabindex="-1"
>
<div
class="c15 c16"
>
<form
action="#"
novalidate=""
>
<div
class="c17 c18"
>
<img
alt=""
aria-hidden="true"
class="c19"
src=""
/>
<div
class="c20"
>
<h1
class="c8 c21"
>
Reset password
</h1>
</div>
</div>
<div
class="c22"
>
<div>
<div
class=""
>
<div
class="c2"
>
<label
class="c8 c23 c24"
for=":r4:"
>
Password
<span
class="c8 c25 c26"
>
*
</span>
</label>
<div
class="c27 c28"
>
<input
aria-describedby=":r4:-hint"
aria-disabled="false"
aria-invalid="false"
aria-required="true"
class="c29 c30"
id=":r4:"
name="password"
type="password"
value=""
/>
<div
class="c31"
>
<button
class="c32 c33 c34 c35"
type="button"
>
<span
class="c36"
>
Hide password
</span>
<svg
aria-hidden="true"
fill="none"
focusable="false"
height="1rem"
viewBox="0 0 24 24"
width="1rem"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M4.048 6.875 2.103 4.93a1 1 0 1 1 1.414-1.415l16.966 16.966a1 1 0 1 1-1.414 1.415l-2.686-2.686a12.247 12.247 0 0 1-4.383.788c-3.573 0-6.559-1.425-8.962-3.783a15.842 15.842 0 0 1-2.116-2.568 11.096 11.096 0 0 1-.711-1.211 1.145 1.145 0 0 1 0-.875c.124-.258.36-.68.711-1.211.58-.876 1.283-1.75 2.116-2.569.326-.32.663-.622 1.01-.906Zm10.539 10.539-1.551-1.551a4.005 4.005 0 0 1-4.9-4.9L6.584 9.411a6 6 0 0 0 8.002 8.002ZM7.617 4.787A12.248 12.248 0 0 1 12 3.998c3.572 0 6.559 1.426 8.961 3.783a15.845 15.845 0 0 1 2.117 2.569c.351.532.587.954.711 1.211.116.242.115.636 0 .875-.124.257-.36.68-.711 1.211-.58.876-1.283 1.75-2.117 2.568-.325.32-.662.623-1.01.907l-2.536-2.537a6 6 0 0 0-8.002-8.002L7.617 4.787Zm3.347 3.347A4.005 4.005 0 0 1 16 11.998c0 .359-.047.706-.136 1.037l-4.9-4.901Z"
fill="#212134"
/>
</svg>
</button>
</div>
</div>
<p
class="c8 c37"
id=":r4:-hint"
>
Password must contain at least 8 characters, 1 uppercase, 1 lowercase and 1 number
</p>
</div>
</div>
</div>
<div>
<div
class=""
>
<div
class="c2"
>
<label
class="c8 c23 c24"
for=":r6:"
>
Confirm Password
<span
class="c8 c25 c26"
>
*
</span>
</label>
<div
class="c27 c28"
>
<input
aria-disabled="false"
aria-invalid="false"
aria-required="true"
class="c29 c30"
id=":r6:"
name="confirmPassword"
type="password"
value=""
/>
<div
class="c31"
>
<button
class="c32 c33 c34 c35"
type="button"
>
<span
class="c36"
>
Hide password
</span>
<svg
aria-hidden="true"
fill="none"
focusable="false"
height="1rem"
viewBox="0 0 24 24"
width="1rem"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M4.048 6.875 2.103 4.93a1 1 0 1 1 1.414-1.415l16.966 16.966a1 1 0 1 1-1.414 1.415l-2.686-2.686a12.247 12.247 0 0 1-4.383.788c-3.573 0-6.559-1.425-8.962-3.783a15.842 15.842 0 0 1-2.116-2.568 11.096 11.096 0 0 1-.711-1.211 1.145 1.145 0 0 1 0-.875c.124-.258.36-.68.711-1.211.58-.876 1.283-1.75 2.116-2.569.326-.32.663-.622 1.01-.906Zm10.539 10.539-1.551-1.551a4.005 4.005 0 0 1-4.9-4.9L6.584 9.411a6 6 0 0 0 8.002 8.002ZM7.617 4.787A12.248 12.248 0 0 1 12 3.998c3.572 0 6.559 1.426 8.961 3.783a15.845 15.845 0 0 1 2.117 2.569c.351.532.587.954.711 1.211.116.242.115.636 0 .875-.124.257-.36.68-.711 1.211-.58.876-1.283 1.75-2.117 2.568-.325.32-.662.623-1.01.907l-2.536-2.537a6 6 0 0 0-8.002-8.002L7.617 4.787Zm3.347 3.347A4.005 4.005 0 0 1 16 11.998c0 .359-.047.706-.136 1.037l-4.9-4.901Z"
fill="#212134"
/>
</svg>
</button>
</div>
</div>
</div>
</div>
</div>
<button
aria-disabled="false"
class="c38 c39 c40 c41"
type="submit"
>
<span
class="c8 c42"
>
Change password
</span>
</button>
</div>
</form>
</div>
<div
class="c43"
>
<div
class="c44"
>
<a
class="c45"
href="/auth/login"
>
<span
class="c8 c46"
>
Ready to sign in?
</span>
</a>
</div>
</div>
</main>
</div>
</div>
`);
});
});

View File

@ -27,7 +27,7 @@ import { useIntl } from 'react-intl';
import { useMutation, useQuery, useQueryClient } from 'react-query';
import { useLocales } from '../../components/LanguageProvider';
import { useThemeToggle } from '../../hooks/useThemeToggle';
import { useThemeToggle } from '../../contexts/themeToggle';
import { getFullName } from '../../utils/getFullName';
import Password from './components/Password';

View File

@ -3,13 +3,13 @@ import React from 'react';
import { Flex, GridItem, Typography } from '@strapi/design-system';
import { useIntl } from 'react-intl';
import { useApiTokenPermissionsContext } from '../../../../../../../contexts/apiTokenPermissions';
import { useApiTokenPermissions } from '../../../../../../../contexts/apiTokenPermissions';
import BoundRoute from '../BoundRoute';
const ActionBoundRoutes = () => {
const {
value: { selectedAction, routes },
} = useApiTokenPermissionsContext();
} = useApiTokenPermissions();
const { formatMessage } = useIntl();
const actionSection = selectedAction?.split('.')[0];

View File

@ -17,7 +17,7 @@ import PropTypes from 'prop-types';
import { useIntl } from 'react-intl';
import styled from 'styled-components';
import { useApiTokenPermissionsContext } from '../../../../../../../contexts/apiTokenPermissions';
import { useApiTokenPermissions } from '../../../../../../../contexts/apiTokenPermissions';
import CheckboxWrapper from './CheckBoxWrapper';
@ -37,7 +37,7 @@ const CollapsableContentType = ({
}) => {
const {
value: { onChangeSelectAll, onChange, selectedActions, setSelectedAction, selectedAction },
} = useApiTokenPermissionsContext();
} = useApiTokenPermissions();
const [expanded, setExpanded] = useState(false);
const { formatMessage } = useIntl();

View File

@ -3,14 +3,14 @@ import React, { memo } from 'react';
import { Flex, Grid, GridItem, Typography } from '@strapi/design-system';
import { useIntl } from 'react-intl';
import { useApiTokenPermissionsContext } from '../../../../../../../contexts/apiTokenPermissions';
import { useApiTokenPermissions } from '../../../../../../../contexts/apiTokenPermissions';
import ActionBoundRoutes from '../ActionBoundRoutes';
import ContentTypesSection from '../ContenTypesSection';
const Permissions = ({ ...props }) => {
const {
value: { data },
} = useApiTokenPermissionsContext();
} = useApiTokenPermissions();
const { formatMessage } = useIntl();
return (

View File

@ -18,7 +18,7 @@ import { useQuery } from 'react-query';
import { useSelector } from 'react-redux';
import { useHistory, useRouteMatch } from 'react-router-dom';
import { ApiTokenPermissionsContextProvider } from '../../../../../contexts/apiTokenPermissions';
import { ApiTokenPermissionsProvider } from '../../../../../contexts/apiTokenPermissions';
import { selectAdminPermissions } from '../../../../../selectors';
import { formatAPIErrors } from '../../../../../utils/formatAPIErrors';
import { API_TOKEN_TYPE } from '../../../components/Tokens/constants';
@ -270,7 +270,7 @@ const ApiTokenCreateView = () => {
}
return (
<ApiTokenPermissionsContextProvider value={providerValue}>
<ApiTokenPermissionsProvider value={providerValue}>
<Main>
<SettingsPageTitle name="API Tokens" />
<Formik
@ -335,7 +335,7 @@ const ApiTokenCreateView = () => {
}}
</Formik>
</Main>
</ApiTokenPermissionsContextProvider>
</ApiTokenPermissionsProvider>
);
};

View File

@ -5,7 +5,7 @@ import { useTracking } from '@strapi/helper-plugin';
import PropTypes from 'prop-types';
import { useIntl } from 'react-intl';
import { useConfiguration } from '../../../../../../hooks/useConfiguration';
import { useConfiguration } from '../../../../../../contexts/configuration';
import { DIMENSION, SIZE } from '../../utils/constants';
import LogoInput from '../LogoInput';

View File

@ -25,7 +25,7 @@ const PROJECT_SETTINGS_DATA_FIXTURES = {
},
};
jest.mock('../../../../../../../hooks/useConfiguration', () => ({
jest.mock('../../../../../../../contexts/configuration', () => ({
useConfiguration: jest.fn(() => ({
logos: {
menu: { custom: 'customMenuLogo.png', default: 'defaultMenuLogo.png' },

View File

@ -29,7 +29,7 @@ import { useIntl } from 'react-intl';
import { useMutation, useQuery } from 'react-query';
import { useSelector } from 'react-redux';
import { useConfiguration } from '../../../../hooks/useConfiguration';
import { useConfiguration } from '../../../../contexts/configuration';
import { useEnterprise } from '../../../../hooks/useEnterprise';
import { selectAdminPermissions } from '../../../../selectors';

View File

@ -6,8 +6,6 @@ import { render, waitFor } from '@tests/utils';
import ApplicationInfosPage from '../index';
const updateProjectSettingsSpy = jest.fn();
jest.mock('@strapi/helper-plugin', () => ({
...jest.requireActual('@strapi/helper-plugin'),
// eslint-disable-next-line
@ -16,16 +14,6 @@ jest.mock('@strapi/helper-plugin', () => ({
useRBAC: jest.fn(() => ({ allowedActions: { canRead: true, canUpdate: true } })),
}));
jest.mock('../../../../../hooks/useConfiguration', () => ({
useConfiguration: jest.fn(() => ({
logos: {
menu: { custom: 'customMenuLogo.png', default: 'defaultMenuLogo.png' },
auth: { custom: 'customAuthLogo.png', default: 'defaultAuthLogo.png' },
},
updateProjectSettings: updateProjectSettingsSpy,
})),
}));
describe('Application page', () => {
afterEach(() => {
jest.clearAllMocks();
@ -92,12 +80,12 @@ describe('Application page', () => {
it('should update project settings on save', async () => {
useRBAC.mockReturnValue({ allowedActions: { canRead: true, canUpdate: true } });
const { getByRole, queryByText } = render(<ApplicationInfosPage />);
const { getByRole, queryByText, getByText } = render(<ApplicationInfosPage />);
await waitForElementToBeRemoved(() => queryByText('Loading'));
fireEvent.click(getByRole('button', { name: 'Save' }));
await waitFor(() => expect(updateProjectSettingsSpy).toHaveBeenCalledTimes(1));
await waitFor(() => expect(getByText('Saved')).toBeInTheDocument());
});
});

View File

@ -7,8 +7,8 @@ import isEmpty from 'lodash/isEmpty';
import PropTypes from 'prop-types';
import { useIntl } from 'react-intl';
import { PermissionsDataManagerProvider } from '../../hooks/usePermissionsDataManager';
import ContentTypes from '../ContentTypes';
import PermissionsDataManagerProvider from '../PermissionsDataManagerProvider';
import PluginsAndSettings from '../PluginsAndSettings';
import init from './init';
@ -102,16 +102,13 @@ const Permissions = forwardRef(({ layout, isFormDisabled, permissions }, ref) =>
return (
<PermissionsDataManagerProvider
value={{
availableConditions: layout.conditions,
modifiedData,
onChangeConditions: handleChangeConditions,
onChangeSimpleCheckbox: handleChangeSimpleCheckbox,
onChangeParentCheckbox: handleChangeParentCheckbox,
onChangeCollectionTypeLeftActionRowCheckbox:
handleChangeCollectionTypeLeftActionRowCheckbox,
onChangeCollectionTypeGlobalActionCheckbox: handleChangeCollectionTypeGlobalActionCheckbox,
}}
availableConditions={layout.conditions}
modifiedData={modifiedData}
onChangeConditions={handleChangeConditions}
onChangeSimpleCheckbox={handleChangeSimpleCheckbox}
onChangeParentCheckbox={handleChangeParentCheckbox}
onChangeCollectionTypeLeftActionRowCheckbox={handleChangeCollectionTypeLeftActionRowCheckbox}
onChangeCollectionTypeGlobalActionCheckbox={handleChangeCollectionTypeGlobalActionCheckbox}
>
<TabGroup
id="tabs"

View File

@ -1,28 +0,0 @@
import React from 'react';
import PropTypes from 'prop-types';
import { PermissionsDataManagerContext } from '../../hooks/usePermissionsDataManager';
const PermissionsDataManagerProvider = ({ children, value }) => {
return (
<PermissionsDataManagerContext.Provider value={value}>
{children}
</PermissionsDataManagerContext.Provider>
);
};
PermissionsDataManagerProvider.propTypes = {
children: PropTypes.node.isRequired,
value: PropTypes.exact({
availableConditions: PropTypes.array.isRequired,
modifiedData: PropTypes.object.isRequired,
onChangeCollectionTypeLeftActionRowCheckbox: PropTypes.func.isRequired,
onChangeConditions: PropTypes.func.isRequired,
onChangeSimpleCheckbox: PropTypes.func.isRequired,
onChangeParentCheckbox: PropTypes.func.isRequired,
onChangeCollectionTypeGlobalActionCheckbox: PropTypes.func.isRequired,
}).isRequired,
};
export default PermissionsDataManagerProvider;

View File

@ -1,4 +1,4 @@
import * as React from 'react';
import { createContext } from '@radix-ui/react-context';
// Note: I had to guess most of these types based on the name and usage, but I actually don't
// know if they are correct, because the usage is very generic. Feel free to correct them if
@ -22,7 +22,10 @@ export interface PermissionsDataManagerContextValue {
) => void;
}
export const PermissionsDataManagerContext =
React.createContext<PermissionsDataManagerContextValue | null>(null);
const [PermissionsDataManagerProvider, usePermissionsDataManagerContext] =
createContext<PermissionsDataManagerContextValue>('PermissionsDataManager');
export const usePermissionsDataManager = () => React.useContext(PermissionsDataManagerContext);
export const usePermissionsDataManager = () =>
usePermissionsDataManagerContext('usePermissionsDataManager');
export { PermissionsDataManagerProvider };

View File

@ -1,9 +1,4 @@
import { lightTheme, ThemeProvider } from '@strapi/design-system';
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { createMemoryHistory } from 'history';
import { IntlProvider } from 'react-intl';
import { Router } from 'react-router-dom';
import { render, screen } from '@tests/utils';
import { UseCasePage } from '../UseCasePage';
@ -18,22 +13,9 @@ jest.mock('@strapi/helper-plugin', () => ({
},
}));
const history = createMemoryHistory();
const App = (
<IntlProvider messages={{}} textComponent="span" locale="en">
<ThemeProvider theme={lightTheme}>
<Router history={history}>
<UseCasePage />
</Router>
</ThemeProvider>
</IntlProvider>
);
describe('Admin | UseCasePage', () => {
it('should not show Other input if select value is not Other', async () => {
const { queryByTestId } = render(App);
const user = userEvent.setup();
const { queryByTestId, user } = render(<UseCasePage />);
const selectInput = screen.getByRole('combobox', { name: 'What type of work do you do?' });
@ -45,8 +27,7 @@ describe('Admin | UseCasePage', () => {
});
it('should show Other input if select value is Other', async () => {
const { getByTestId } = render(App);
const user = userEvent.setup();
const { getByTestId, user } = render(<UseCasePage />);
const selectInput = screen.getByRole('combobox', { name: 'What type of work do you do?' });

View File

@ -3,7 +3,7 @@ import * as React from 'react';
import { configureStore } from '@reduxjs/toolkit';
import { fixtures } from '@strapi/admin-test-utils';
import { DesignSystemProvider } from '@strapi/design-system';
import { DesignSystemProvider, darkTheme, lightTheme } from '@strapi/design-system';
import { NotificationsProvider, RBACContext } from '@strapi/helper-plugin';
import {
renderHook as renderHookRTL,
@ -17,15 +17,16 @@ import {
import userEvent from '@testing-library/user-event';
import { DndProvider } from 'react-dnd';
import { HTML5Backend } from 'react-dnd-html5-backend';
import { IntlProvider } from 'react-intl';
import { QueryClient, QueryClientProvider, setLogger } from 'react-query';
import { Provider } from 'react-redux';
import { MemoryRouter, MemoryRouterProps } from 'react-router-dom';
import { LanguageProvider } from '../src/components/LanguageProvider';
import { ThemeToggleProvider } from '../src/components/ThemeToggleProvider';
// @ts-expect-error no types yet.
import ModelsContext from '../src/content-manager/contexts/ModelsContext';
import { AdminContext } from '../src/contexts/admin';
import { ConfigurationContext } from '../src/contexts/configuration';
import { AdminContextProvider } from '../src/contexts/admin';
import { ConfigurationContextProvider } from '../src/contexts/configuration';
import { server } from './server';
import { initialState } from './store';
@ -59,49 +60,59 @@ const Providers = ({ children, initialEntries }: ProvidersProps) => {
return (
<Provider store={store}>
<MemoryRouter initialEntries={initialEntries}>
<IntlProvider locale="en" textComponent="span">
<ThemeToggleProvider
themes={{
light: lightTheme,
dark: darkTheme,
}}
>
<DesignSystemProvider locale="en">
<QueryClientProvider client={queryClient}>
<DndProvider backend={HTML5Backend}>
<NotificationsProvider>
<RBACContext.Provider
value={{
refetchPermissions: jest.fn(),
allPermissions: [
...fixtures.permissions.allPermissions,
{
id: 314,
action: 'admin::users.read',
subject: null,
properties: {},
conditions: [],
},
],
}}
>
<ModelsContext.Provider value={{ refetchData: jest.fn() }}>
<AdminContext.Provider value={{ getAdminInjectedComponents: jest.fn() }}>
<ConfigurationContext.Provider
value={{
showReleaseNotification: false,
showTutorials: false,
updateProjectSettings: jest.fn(),
logos: {
<LanguageProvider
localeNames={{
en: 'english',
}}
messages={{}}
>
<NotificationsProvider>
<RBACContext.Provider
value={{
refetchPermissions: jest.fn(),
allPermissions: [
...fixtures.permissions.allPermissions,
{
id: 314,
action: 'admin::users.read',
subject: null,
properties: {},
conditions: [],
},
],
}}
>
<ModelsContext.Provider value={{ refetchData: jest.fn() }}>
<AdminContextProvider getAdminInjectedComponents={jest.fn()}>
<ConfigurationContextProvider
showReleaseNotification={false}
showTutorials={false}
updateProjectSettings={jest.fn()}
logos={{
auth: { default: '' },
menu: { default: '' },
},
}}
>
{children}
</ConfigurationContext.Provider>
</AdminContext.Provider>
</ModelsContext.Provider>
</RBACContext.Provider>
</NotificationsProvider>
}}
>
{children}
</ConfigurationContextProvider>
</AdminContextProvider>
</ModelsContext.Provider>
</RBACContext.Provider>
</NotificationsProvider>
</LanguageProvider>
</DndProvider>
</QueryClientProvider>
</DesignSystemProvider>
</IntlProvider>
</ThemeToggleProvider>
</MemoryRouter>
</Provider>
);

View File

@ -43,6 +43,7 @@
"dependencies": {
"@casl/ability": "6.5.0",
"@pmmmwh/react-refresh-webpack-plugin": "0.5.10",
"@radix-ui/react-context": "1.0.1",
"@radix-ui/react-toolbar": "1.0.4",
"@reduxjs/toolkit": "1.9.7",
"@strapi/data-transfer": "4.15.0",

View File

@ -7440,6 +7440,7 @@ __metadata:
dependencies:
"@casl/ability": "npm:6.5.0"
"@pmmmwh/react-refresh-webpack-plugin": "npm:0.5.10"
"@radix-ui/react-context": "npm:1.0.1"
"@radix-ui/react-toolbar": "npm:1.0.4"
"@reduxjs/toolkit": "npm:1.9.7"
"@strapi/admin-test-utils": "npm:4.15.0"