mirror of https://github.com/portainer/portainer
refactor(tests): wrap tests explicitly with provider [EE-6686] (#11276)
parent
e265b8b67c
commit
dd2be9fb1e
|
@ -45,6 +45,12 @@ rules:
|
||||||
pathGroupsExcludedImportTypes: ['internal'],
|
pathGroupsExcludedImportTypes: ['internal'],
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
no-restricted-imports:
|
||||||
|
- error
|
||||||
|
- patterns:
|
||||||
|
- group:
|
||||||
|
- '@/react/test-utils/*'
|
||||||
|
message: 'These utils are just for test files'
|
||||||
|
|
||||||
settings:
|
settings:
|
||||||
'import/resolver':
|
'import/resolver':
|
||||||
|
@ -113,6 +119,12 @@ overrides:
|
||||||
'no-await-in-loop': 'off'
|
'no-await-in-loop': 'off'
|
||||||
'react/jsx-no-useless-fragment': ['error', { allowExpressions: true }]
|
'react/jsx-no-useless-fragment': ['error', { allowExpressions: true }]
|
||||||
'regex/invalid': ['error', [{ 'regex': '<Icon icon="(.*)"', 'message': 'Please directly import the `lucide-react` icon instead of using the string' }]]
|
'regex/invalid': ['error', [{ 'regex': '<Icon icon="(.*)"', 'message': 'Please directly import the `lucide-react` icon instead of using the string' }]]
|
||||||
|
'@typescript-eslint/no-restricted-imports':
|
||||||
|
- error
|
||||||
|
- patterns:
|
||||||
|
- group:
|
||||||
|
- '@/react/test-utils/*'
|
||||||
|
message: 'These utils are just for test files'
|
||||||
overrides: # allow props spreading for hoc files
|
overrides: # allow props spreading for hoc files
|
||||||
- files:
|
- files:
|
||||||
- app/**/with*.ts{,x}
|
- app/**/with*.ts{,x}
|
||||||
|
@ -126,7 +138,11 @@ overrides:
|
||||||
'vitest/env': true
|
'vitest/env': true
|
||||||
rules:
|
rules:
|
||||||
'react/jsx-no-constructed-context-values': off
|
'react/jsx-no-constructed-context-values': off
|
||||||
|
'@typescript-eslint/no-restricted-imports': off
|
||||||
|
no-restricted-imports: off
|
||||||
- files:
|
- files:
|
||||||
- app/**/*.stories.*
|
- app/**/*.stories.*
|
||||||
rules:
|
rules:
|
||||||
'no-alert': off
|
'no-alert': off
|
||||||
|
'@typescript-eslint/no-restricted-imports': off
|
||||||
|
no-restricted-imports: off
|
||||||
|
|
|
@ -1,37 +0,0 @@
|
||||||
import 'vitest-dom/extend-expect';
|
|
||||||
import { render, RenderOptions } from '@testing-library/react';
|
|
||||||
import { UIRouter, pushStateLocationPlugin } from '@uirouter/react';
|
|
||||||
import { PropsWithChildren, ReactElement } from 'react';
|
|
||||||
import { QueryClient, QueryClientProvider } from 'react-query';
|
|
||||||
|
|
||||||
function Provider({ children }: PropsWithChildren<unknown>) {
|
|
||||||
return <UIRouter plugins={[pushStateLocationPlugin]}>{children}</UIRouter>;
|
|
||||||
}
|
|
||||||
|
|
||||||
function customRender(ui: ReactElement, options?: RenderOptions) {
|
|
||||||
return render(ui, { wrapper: Provider, ...options });
|
|
||||||
}
|
|
||||||
|
|
||||||
// re-export everything
|
|
||||||
export * from '@testing-library/react';
|
|
||||||
|
|
||||||
// override render method
|
|
||||||
export { customRender as render };
|
|
||||||
|
|
||||||
export function renderWithQueryClient(ui: React.ReactElement) {
|
|
||||||
const testQueryClient = new QueryClient({
|
|
||||||
defaultOptions: { queries: { retry: false } },
|
|
||||||
});
|
|
||||||
const { rerender, ...result } = customRender(
|
|
||||||
<QueryClientProvider client={testQueryClient}>{ui}</QueryClientProvider>
|
|
||||||
);
|
|
||||||
return {
|
|
||||||
...result,
|
|
||||||
rerender: (rerenderUi: React.ReactElement) =>
|
|
||||||
rerender(
|
|
||||||
<QueryClientProvider client={testQueryClient}>
|
|
||||||
{rerenderUi}
|
|
||||||
</QueryClientProvider>
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -1,13 +1,15 @@
|
||||||
import { http, HttpResponse } from 'msw';
|
import { http, HttpResponse } from 'msw';
|
||||||
|
import { render, within } from '@testing-library/react';
|
||||||
|
|
||||||
import { renderWithQueryClient, within } from '@/react-tools/test-utils';
|
|
||||||
import { UserContext } from '@/react/hooks/useUser';
|
|
||||||
import { UserViewModel } from '@/portainer/models/user';
|
import { UserViewModel } from '@/portainer/models/user';
|
||||||
import { server } from '@/setup-tests/server';
|
import { server } from '@/setup-tests/server';
|
||||||
import {
|
import {
|
||||||
createMockResourceGroups,
|
createMockResourceGroups,
|
||||||
createMockSubscriptions,
|
createMockSubscriptions,
|
||||||
} from '@/react-tools/test-mocks';
|
} from '@/react-tools/test-mocks';
|
||||||
|
import { withUserProvider } from '@/react/test-utils/withUserProvider';
|
||||||
|
import { withTestRouter } from '@/react/test-utils/withRouter';
|
||||||
|
import { withTestQueryProvider } from '@/react/test-utils/withTestQuery';
|
||||||
|
|
||||||
import { DashboardView } from './DashboardView';
|
import { DashboardView } from './DashboardView';
|
||||||
|
|
||||||
|
@ -105,7 +107,6 @@ async function renderComponent(
|
||||||
resourceGroupsStatus = 200
|
resourceGroupsStatus = 200
|
||||||
) {
|
) {
|
||||||
const user = new UserViewModel({ Username: 'user' });
|
const user = new UserViewModel({ Username: 'user' });
|
||||||
const state = { user };
|
|
||||||
|
|
||||||
server.use(
|
server.use(
|
||||||
http.get('/api/endpoints/1', () => HttpResponse.json({})),
|
http.get('/api/endpoints/1', () => HttpResponse.json({})),
|
||||||
|
@ -135,12 +136,13 @@ async function renderComponent(
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
const renderResult = renderWithQueryClient(
|
|
||||||
<UserContext.Provider value={state}>
|
const Wrapped = withTestQueryProvider(
|
||||||
<DashboardView />
|
withUserProvider(withTestRouter(DashboardView), user)
|
||||||
</UserContext.Provider>
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const renderResult = render(<Wrapped />);
|
||||||
|
|
||||||
await expect(renderResult.findByText(/Home/)).resolves.toBeVisible();
|
await expect(renderResult.findByText(/Home/)).resolves.toBeVisible();
|
||||||
|
|
||||||
return renderResult;
|
return renderResult;
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
import userEvent from '@testing-library/user-event';
|
import userEvent from '@testing-library/user-event';
|
||||||
import { HttpResponse } from 'msw';
|
import { HttpResponse, http } from 'msw';
|
||||||
|
import { render } from '@testing-library/react';
|
||||||
|
|
||||||
import { UserContext } from '@/react/hooks/useUser';
|
|
||||||
import { UserViewModel } from '@/portainer/models/user';
|
import { UserViewModel } from '@/portainer/models/user';
|
||||||
import { renderWithQueryClient } from '@/react-tools/test-utils';
|
import { withUserProvider } from '@/react/test-utils/withUserProvider';
|
||||||
import { http, server } from '@/setup-tests/server';
|
import { withTestRouter } from '@/react/test-utils/withRouter';
|
||||||
|
import { withTestQueryProvider } from '@/react/test-utils/withTestQuery';
|
||||||
|
import { server } from '@/setup-tests/server';
|
||||||
|
|
||||||
import { CreateContainerInstanceForm } from './CreateContainerInstanceForm';
|
import { CreateContainerInstanceForm } from './CreateContainerInstanceForm';
|
||||||
|
|
||||||
|
@ -19,12 +21,10 @@ test('submit button should be disabled when name or image is missing', async ()
|
||||||
server.use(http.get('/api/endpoints/5', () => HttpResponse.json({})));
|
server.use(http.get('/api/endpoints/5', () => HttpResponse.json({})));
|
||||||
|
|
||||||
const user = new UserViewModel({ Username: 'user' });
|
const user = new UserViewModel({ Username: 'user' });
|
||||||
|
const Wrapped = withTestQueryProvider(
|
||||||
const { findByText, getByText, getByLabelText } = renderWithQueryClient(
|
withUserProvider(withTestRouter(CreateContainerInstanceForm), user)
|
||||||
<UserContext.Provider value={{ user }}>
|
|
||||||
<CreateContainerInstanceForm />
|
|
||||||
</UserContext.Provider>
|
|
||||||
);
|
);
|
||||||
|
const { findByText, getByText, getByLabelText } = render(<Wrapped />);
|
||||||
|
|
||||||
await expect(findByText(/Azure settings/)).resolves.toBeVisible();
|
await expect(findByText(/Azure settings/)).resolves.toBeVisible();
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { render } from '@/react-tools/test-utils';
|
import { render } from '@testing-library/react';
|
||||||
|
|
||||||
import { Badge } from './Badge';
|
import { Badge } from './Badge';
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import { Rocket } from 'lucide-react';
|
import { Rocket } from 'lucide-react';
|
||||||
|
import { render, fireEvent } from '@testing-library/react';
|
||||||
import { render, fireEvent } from '@/react-tools/test-utils';
|
|
||||||
|
|
||||||
import { BoxSelector } from './BoxSelector';
|
import { BoxSelector } from './BoxSelector';
|
||||||
import { BoxSelectorOption, Value } from './types';
|
import { BoxSelectorOption, Value } from './types';
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import { User } from 'lucide-react';
|
import { User } from 'lucide-react';
|
||||||
|
import { render } from '@testing-library/react';
|
||||||
import { render } from '@/react-tools/test-utils';
|
|
||||||
|
|
||||||
import { DashboardItem } from './DashboardItem';
|
import { DashboardItem } from './DashboardItem';
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { render } from '@/react-tools/test-utils';
|
import { render } from '@testing-library/react';
|
||||||
|
|
||||||
import { DetailsTable } from './index';
|
import { DetailsTable } from './index';
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
|
import { render } from '@testing-library/react';
|
||||||
|
|
||||||
import { createMockEnvironment } from '@/react-tools/test-mocks';
|
import { createMockEnvironment } from '@/react-tools/test-mocks';
|
||||||
import { renderWithQueryClient } from '@/react-tools/test-utils';
|
|
||||||
|
import { withTestQueryProvider } from '../test-utils/withTestQuery';
|
||||||
|
|
||||||
import { EdgeIndicator } from './EdgeIndicator';
|
import { EdgeIndicator } from './EdgeIndicator';
|
||||||
|
|
||||||
|
@ -31,8 +34,10 @@ async function renderComponent(
|
||||||
environment.EdgeCheckinInterval = checkInInterval;
|
environment.EdgeCheckinInterval = checkInInterval;
|
||||||
environment.QueryDate = queryDate;
|
environment.QueryDate = queryDate;
|
||||||
|
|
||||||
const queries = renderWithQueryClient(
|
const Wrapped = withTestQueryProvider(EdgeIndicator);
|
||||||
<EdgeIndicator environment={environment} showLastCheckInDate />
|
|
||||||
|
const queries = render(
|
||||||
|
<Wrapped environment={environment} showLastCheckInDate />
|
||||||
);
|
);
|
||||||
|
|
||||||
await expect(queries.findByRole('status')).resolves.toBeVisible();
|
await expect(queries.findByRole('status')).resolves.toBeVisible();
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
import { FormikErrors } from 'formik';
|
import { FormikErrors } from 'formik';
|
||||||
import { ComponentProps } from 'react';
|
import { ComponentProps } from 'react';
|
||||||
import { HttpResponse } from 'msw';
|
import { HttpResponse } from 'msw';
|
||||||
|
import { render, fireEvent } from '@testing-library/react';
|
||||||
|
|
||||||
import { renderWithQueryClient, fireEvent } from '@/react-tools/test-utils';
|
|
||||||
import { http, server } from '@/setup-tests/server';
|
import { http, server } from '@/setup-tests/server';
|
||||||
|
import { withTestQueryProvider } from '@/react/test-utils/withTestQuery';
|
||||||
|
|
||||||
import { ImageConfigFieldset } from './ImageConfigFieldset';
|
import { ImageConfigFieldset } from './ImageConfigFieldset';
|
||||||
import { Values } from './types';
|
import { Values } from './types';
|
||||||
|
@ -16,20 +17,20 @@ vi.mock('@uirouter/react', async (importOriginal: () => Promise<object>) => ({
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('should render SimpleForm when useRegistry is true', () => {
|
it('should render SimpleForm when useRegistry is true', () => {
|
||||||
const { getByText } = render({ values: { useRegistry: true } });
|
const { getByText } = renderComponent({ values: { useRegistry: true } });
|
||||||
|
|
||||||
expect(getByText('Advanced mode')).toBeInTheDocument();
|
expect(getByText('Advanced mode')).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should render AdvancedForm when useRegistry is false', () => {
|
it('should render AdvancedForm when useRegistry is false', () => {
|
||||||
const { getByText } = render({ values: { useRegistry: false } });
|
const { getByText } = renderComponent({ values: { useRegistry: false } });
|
||||||
|
|
||||||
expect(getByText('Simple mode')).toBeInTheDocument();
|
expect(getByText('Simple mode')).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should call setFieldValue with useRegistry set to false when "Advanced mode" button is clicked', () => {
|
it('should call setFieldValue with useRegistry set to false when "Advanced mode" button is clicked', () => {
|
||||||
const setFieldValue = vi.fn();
|
const setFieldValue = vi.fn();
|
||||||
const { getByText } = render({
|
const { getByText } = renderComponent({
|
||||||
values: { useRegistry: true },
|
values: { useRegistry: true },
|
||||||
setFieldValue,
|
setFieldValue,
|
||||||
});
|
});
|
||||||
|
@ -41,7 +42,7 @@ it('should call setFieldValue with useRegistry set to false when "Advanced mode"
|
||||||
|
|
||||||
it('should call setFieldValue with useRegistry set to true when "Simple mode" button is clicked', () => {
|
it('should call setFieldValue with useRegistry set to true when "Simple mode" button is clicked', () => {
|
||||||
const setFieldValue = vi.fn();
|
const setFieldValue = vi.fn();
|
||||||
const { getByText } = render({
|
const { getByText } = renderComponent({
|
||||||
values: { useRegistry: false },
|
values: { useRegistry: false },
|
||||||
setFieldValue,
|
setFieldValue,
|
||||||
});
|
});
|
||||||
|
@ -51,7 +52,7 @@ it('should call setFieldValue with useRegistry set to true when "Simple mode" bu
|
||||||
expect(setFieldValue).toHaveBeenCalledWith('useRegistry', true);
|
expect(setFieldValue).toHaveBeenCalledWith('useRegistry', true);
|
||||||
});
|
});
|
||||||
|
|
||||||
function render({
|
function renderComponent({
|
||||||
values = {
|
values = {
|
||||||
useRegistry: true,
|
useRegistry: true,
|
||||||
registryId: 123,
|
registryId: 123,
|
||||||
|
@ -73,8 +74,10 @@ function render({
|
||||||
http.get('/api/endpoints/:id', () => HttpResponse.json({}))
|
http.get('/api/endpoints/:id', () => HttpResponse.json({}))
|
||||||
);
|
);
|
||||||
|
|
||||||
return renderWithQueryClient(
|
const Wrapped = withTestQueryProvider(ImageConfigFieldset);
|
||||||
<ImageConfigFieldset
|
|
||||||
|
return render(
|
||||||
|
<Wrapped
|
||||||
values={{
|
values={{
|
||||||
useRegistry: true,
|
useRegistry: true,
|
||||||
registryId: 123,
|
registryId: 123,
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
import { render } from '@testing-library/react';
|
|
||||||
import userEvent from '@testing-library/user-event';
|
import userEvent from '@testing-library/user-event';
|
||||||
|
import { render } from '@testing-library/react';
|
||||||
|
|
||||||
|
import { withTestRouter } from '@/react/test-utils/withRouter';
|
||||||
|
|
||||||
import { NavTabs, Option } from './NavTabs';
|
import { NavTabs, Option } from './NavTabs';
|
||||||
|
|
||||||
|
@ -32,6 +34,7 @@ test('should show selected id content', async () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should call onSelect when clicked with id', async () => {
|
test('should call onSelect when clicked with id', async () => {
|
||||||
|
const user = userEvent.setup();
|
||||||
const options = [
|
const options = [
|
||||||
{ children: 'Content 1', id: 'option1', label: 'Option 1' },
|
{ children: 'Content 1', id: 'option1', label: 'Option 1' },
|
||||||
{ children: 'Content 2', id: 'option2', label: 'Option 2' },
|
{ children: 'Content 2', id: 'option2', label: 'Option 2' },
|
||||||
|
@ -42,7 +45,7 @@ test('should call onSelect when clicked with id', async () => {
|
||||||
const { findByText } = renderComponent(options, options[1].id, onSelect);
|
const { findByText } = renderComponent(options, options[1].id, onSelect);
|
||||||
|
|
||||||
const heading = await findByText(options[0].label);
|
const heading = await findByText(options[0].label);
|
||||||
await userEvent.click(heading);
|
await user.click(heading);
|
||||||
|
|
||||||
expect(onSelect).toHaveBeenCalledWith(options[0].id);
|
expect(onSelect).toHaveBeenCalledWith(options[0].id);
|
||||||
});
|
});
|
||||||
|
@ -52,7 +55,9 @@ function renderComponent(
|
||||||
selectedId?: string | number,
|
selectedId?: string | number,
|
||||||
onSelect?: (id: string | number) => void
|
onSelect?: (id: string | number) => void
|
||||||
) {
|
) {
|
||||||
|
const Wrapped = withTestRouter(NavTabs);
|
||||||
|
|
||||||
return render(
|
return render(
|
||||||
<NavTabs options={options} selectedId={selectedId} onSelect={onSelect} />
|
<Wrapped options={options} selectedId={selectedId} onSelect={onSelect} />
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { render } from '@/react-tools/test-utils';
|
import { render } from '@testing-library/react';
|
||||||
|
|
||||||
import { Breadcrumbs } from './Breadcrumbs';
|
import { Breadcrumbs } from './Breadcrumbs';
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
import { QueryClient, QueryClientProvider } from 'react-query';
|
import { render } from '@testing-library/react';
|
||||||
|
|
||||||
import { UserContext } from '@/react/hooks/useUser';
|
|
||||||
import { UserViewModel } from '@/portainer/models/user';
|
import { UserViewModel } from '@/portainer/models/user';
|
||||||
import { render } from '@/react-tools/test-utils';
|
import { withUserProvider } from '@/react/test-utils/withUserProvider';
|
||||||
|
import { withTestRouter } from '@/react/test-utils/withRouter';
|
||||||
|
import { withTestQueryProvider } from '@/react/test-utils/withTestQuery';
|
||||||
|
|
||||||
import { HeaderContainer } from './HeaderContainer';
|
import { HeaderContainer } from './HeaderContainer';
|
||||||
import { HeaderTitle } from './HeaderTitle';
|
import { HeaderTitle } from './HeaderTitle';
|
||||||
|
@ -14,7 +15,8 @@ test('should not render without a wrapping HeaderContainer', async () => {
|
||||||
|
|
||||||
const title = 'title';
|
const title = 'title';
|
||||||
function renderComponent() {
|
function renderComponent() {
|
||||||
return render(<HeaderTitle title={title} />);
|
const Wrapped = withTestQueryProvider(HeaderTitle);
|
||||||
|
return render(<Wrapped title={title} />);
|
||||||
}
|
}
|
||||||
|
|
||||||
expect(renderComponent).toThrowErrorMatchingSnapshot();
|
expect(renderComponent).toThrowErrorMatchingSnapshot();
|
||||||
|
@ -25,19 +27,22 @@ test('should not render without a wrapping HeaderContainer', async () => {
|
||||||
test('should display a HeaderTitle', async () => {
|
test('should display a HeaderTitle', async () => {
|
||||||
const username = 'username';
|
const username = 'username';
|
||||||
const user = new UserViewModel({ Username: username });
|
const user = new UserViewModel({ Username: username });
|
||||||
const queryClient = new QueryClient();
|
|
||||||
|
|
||||||
const title = 'title';
|
const title = 'title';
|
||||||
const { queryByText } = render(
|
|
||||||
<QueryClientProvider client={queryClient}>
|
const Wrapped = withTestQueryProvider(
|
||||||
<UserContext.Provider value={{ user }}>
|
withUserProvider(
|
||||||
|
withTestRouter(() => (
|
||||||
<HeaderContainer>
|
<HeaderContainer>
|
||||||
<HeaderTitle title={title} />
|
<HeaderTitle title={title} />
|
||||||
</HeaderContainer>
|
</HeaderContainer>
|
||||||
</UserContext.Provider>
|
)),
|
||||||
</QueryClientProvider>
|
user
|
||||||
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const { queryByText } = render(<Wrapped />);
|
||||||
|
|
||||||
const heading = queryByText(title);
|
const heading = queryByText(title);
|
||||||
expect(heading).toBeVisible();
|
expect(heading).toBeVisible();
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
import { UserContext } from '@/react/hooks/useUser';
|
import { render } from '@testing-library/react';
|
||||||
|
|
||||||
import { UserViewModel } from '@/portainer/models/user';
|
import { UserViewModel } from '@/portainer/models/user';
|
||||||
import { renderWithQueryClient } from '@/react-tools/test-utils';
|
import { withTestRouter } from '@/react/test-utils/withRouter';
|
||||||
|
import { withUserProvider } from '@/react/test-utils/withUserProvider';
|
||||||
|
import { withTestQueryProvider } from '@/react/test-utils/withTestQuery';
|
||||||
|
|
||||||
import { PageHeader } from './PageHeader';
|
import { PageHeader } from './PageHeader';
|
||||||
|
|
||||||
|
@ -8,13 +11,13 @@ test('should display a PageHeader', async () => {
|
||||||
const username = 'username';
|
const username = 'username';
|
||||||
const user = new UserViewModel({ Username: username });
|
const user = new UserViewModel({ Username: username });
|
||||||
|
|
||||||
const title = 'title';
|
const Wrapped = withTestQueryProvider(
|
||||||
const { queryByText } = renderWithQueryClient(
|
withUserProvider(withTestRouter(PageHeader), user)
|
||||||
<UserContext.Provider value={{ user }}>
|
|
||||||
<PageHeader title={title} />
|
|
||||||
</UserContext.Provider>
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const title = 'title';
|
||||||
|
const { queryByText } = render(<Wrapped title={title} />);
|
||||||
|
|
||||||
const heading = queryByText(title);
|
const heading = queryByText(title);
|
||||||
expect(heading).toBeVisible();
|
expect(heading).toBeVisible();
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
import { http, HttpResponse } from 'msw';
|
import { http, HttpResponse } from 'msw';
|
||||||
import { Mock } from 'vitest';
|
import { Mock } from 'vitest';
|
||||||
|
import { render } from '@testing-library/react';
|
||||||
|
|
||||||
import { Tag, TagId } from '@/portainer/tags/types';
|
import { Tag, TagId } from '@/portainer/tags/types';
|
||||||
import { renderWithQueryClient } from '@/react-tools/test-utils';
|
|
||||||
import { server } from '@/setup-tests/server';
|
import { server } from '@/setup-tests/server';
|
||||||
|
import { withTestRouter } from '@/react/test-utils/withRouter';
|
||||||
|
import { withTestQueryProvider } from '@/react/test-utils/withTestQuery';
|
||||||
|
|
||||||
import { TagSelector } from './TagSelector';
|
import { TagSelector } from './TagSelector';
|
||||||
|
|
||||||
|
@ -54,8 +56,10 @@ async function renderComponent(
|
||||||
) {
|
) {
|
||||||
server.use(http.get('/api/tags', () => HttpResponse.json(tags)));
|
server.use(http.get('/api/tags', () => HttpResponse.json(tags)));
|
||||||
|
|
||||||
const queries = renderWithQueryClient(
|
const Wrapped = withTestQueryProvider(withTestRouter(TagSelector));
|
||||||
<TagSelector value={value} allowCreate={allowCreate} onChange={onChange} />
|
|
||||||
|
const queries = render(
|
||||||
|
<Wrapped value={value} allowCreate={allowCreate} onChange={onChange} />
|
||||||
);
|
);
|
||||||
|
|
||||||
const tagElement = await queries.findAllByText('tags', { exact: false });
|
const tagElement = await queries.findAllByText('tags', { exact: false });
|
||||||
|
|
|
@ -1,11 +1,34 @@
|
||||||
import { render } from '@/react-tools/test-utils';
|
import { UIView } from '@uirouter/react';
|
||||||
|
import { render } from '@testing-library/react';
|
||||||
|
|
||||||
|
import { withTestRouter } from '@/react/test-utils/withRouter';
|
||||||
|
|
||||||
import { AddButton } from './AddButton';
|
import { AddButton } from './AddButton';
|
||||||
|
|
||||||
function renderDefault({
|
function renderDefault({
|
||||||
label = 'default label',
|
label = 'default label',
|
||||||
}: Partial<{ label: string }> = {}) {
|
}: Partial<{ label: string }> = {}) {
|
||||||
return render(<AddButton to="">{label}</AddButton>);
|
const Wrapped = withTestRouter(AddButton, {
|
||||||
|
stateConfig: [
|
||||||
|
{
|
||||||
|
name: 'root',
|
||||||
|
url: '/',
|
||||||
|
|
||||||
|
component: () => (
|
||||||
|
<>
|
||||||
|
<div>Root</div>
|
||||||
|
<UIView />
|
||||||
|
</>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'root.new',
|
||||||
|
url: 'new',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
route: 'root',
|
||||||
|
});
|
||||||
|
return render(<Wrapped to="">{label}</Wrapped>);
|
||||||
}
|
}
|
||||||
|
|
||||||
test('should display a AddButton component', async () => {
|
test('should display a AddButton component', async () => {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { fireEvent, render } from '@testing-library/react';
|
|
||||||
import { PropsWithChildren } from 'react';
|
import { PropsWithChildren } from 'react';
|
||||||
|
import { fireEvent, render } from '@testing-library/react';
|
||||||
|
|
||||||
import { Button, Props } from './Button';
|
import { Button, Props } from './Button';
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { render } from '@testing-library/react';
|
|
||||||
import { PropsWithChildren } from 'react';
|
import { PropsWithChildren } from 'react';
|
||||||
|
import { render } from '@testing-library/react';
|
||||||
|
|
||||||
import { ButtonGroup, Props } from './ButtonGroup';
|
import { ButtonGroup, Props } from './ButtonGroup';
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { render } from '@/react-tools/test-utils';
|
import { render } from '@testing-library/react';
|
||||||
|
|
||||||
import { LoadingButton } from './LoadingButton';
|
import { LoadingButton } from './LoadingButton';
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { fireEvent, render } from '@/react-tools/test-utils';
|
import { fireEvent, render } from '@testing-library/react';
|
||||||
|
|
||||||
import { FileUploadField } from './FileUploadField';
|
import { FileUploadField } from './FileUploadField';
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { render } from '@/react-tools/test-utils';
|
import { render } from '@testing-library/react';
|
||||||
|
|
||||||
import { FileUploadForm } from './FileUploadForm';
|
import { FileUploadForm } from './FileUploadForm';
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { render } from '@/react-tools/test-utils';
|
import { render } from '@testing-library/react';
|
||||||
|
|
||||||
import { Slider, Props } from './Slider';
|
import { Slider, Props } from './Slider';
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { render } from '@testing-library/react';
|
|
||||||
import { PropsWithChildren } from 'react';
|
import { PropsWithChildren } from 'react';
|
||||||
|
import { render } from '@testing-library/react';
|
||||||
|
|
||||||
import { Switch, Props } from './Switch';
|
import { Switch, Props } from './Switch';
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { render, fireEvent } from '@/react-tools/test-utils';
|
import { render, fireEvent } from '@testing-library/react';
|
||||||
|
|
||||||
import { SwitchField, Props } from './SwitchField';
|
import { SwitchField, Props } from './SwitchField';
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,39 @@
|
||||||
|
import { UISref, UIView } from '@uirouter/react';
|
||||||
|
import { render, screen } from '@testing-library/react';
|
||||||
|
|
||||||
|
import { withTestRouter } from '@/react/test-utils/withRouter';
|
||||||
|
|
||||||
|
function RelativePathLink() {
|
||||||
|
return (
|
||||||
|
<UISref to=".custom">
|
||||||
|
<span>Link</span>
|
||||||
|
</UISref>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
test.todo('should render a link with relative path', () => {
|
||||||
|
const WrappedComponent = withTestRouter(RelativePathLink, {
|
||||||
|
stateConfig: [
|
||||||
|
{
|
||||||
|
name: 'parent',
|
||||||
|
url: '/',
|
||||||
|
|
||||||
|
component: () => (
|
||||||
|
<>
|
||||||
|
<div>parent</div>
|
||||||
|
<UIView />
|
||||||
|
</>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'parent.custom',
|
||||||
|
url: 'custom',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
route: 'parent',
|
||||||
|
});
|
||||||
|
|
||||||
|
render(<WrappedComponent />);
|
||||||
|
|
||||||
|
expect(screen.getByText('Link')).toBeInTheDocument();
|
||||||
|
});
|
|
@ -1,9 +1,11 @@
|
||||||
import { HttpResponse } from 'msw';
|
import { render } from '@testing-library/react';
|
||||||
|
import { http, HttpResponse } from 'msw';
|
||||||
|
|
||||||
import { renderWithQueryClient } from '@/react-tools/test-utils';
|
|
||||||
import { UserContext } from '@/react/hooks/useUser';
|
|
||||||
import { UserViewModel } from '@/portainer/models/user';
|
import { UserViewModel } from '@/portainer/models/user';
|
||||||
import { http, server } from '@/setup-tests/server';
|
import { withUserProvider } from '@/react/test-utils/withUserProvider';
|
||||||
|
import { withTestRouter } from '@/react/test-utils/withRouter';
|
||||||
|
import { withTestQueryProvider } from '@/react/test-utils/withTestQuery';
|
||||||
|
import { server } from '@/setup-tests/server';
|
||||||
|
|
||||||
import { NetworkContainer } from '../types';
|
import { NetworkContainer } from '../types';
|
||||||
|
|
||||||
|
@ -32,15 +34,18 @@ test('Network container values should be visible and the link should be valid',
|
||||||
server.use(http.get('/api/endpoints/1', () => HttpResponse.json({})));
|
server.use(http.get('/api/endpoints/1', () => HttpResponse.json({})));
|
||||||
|
|
||||||
const user = new UserViewModel({ Username: 'test', Role: 1 });
|
const user = new UserViewModel({ Username: 'test', Role: 1 });
|
||||||
const { findByText } = renderWithQueryClient(
|
|
||||||
<UserContext.Provider value={{ user }}>
|
const Wrapped = withTestQueryProvider(
|
||||||
<NetworkContainersTable
|
withUserProvider(withTestRouter(NetworkContainersTable), user)
|
||||||
|
);
|
||||||
|
|
||||||
|
const { findByText } = render(
|
||||||
|
<Wrapped
|
||||||
networkContainers={networkContainers}
|
networkContainers={networkContainers}
|
||||||
nodeName=""
|
nodeName=""
|
||||||
environmentId={1}
|
environmentId={1}
|
||||||
networkId="pc8xc9s6ot043vl1q5iz4zhfs"
|
networkId="pc8xc9s6ot043vl1q5iz4zhfs"
|
||||||
/>
|
/>
|
||||||
</UserContext.Provider>
|
|
||||||
);
|
);
|
||||||
|
|
||||||
await expect(findByText('Containers in network')).resolves.toBeVisible();
|
await expect(findByText('Containers in network')).resolves.toBeVisible();
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
import { HttpResponse, http } from 'msw';
|
import { HttpResponse, http } from 'msw';
|
||||||
|
import { render } from '@testing-library/react';
|
||||||
|
|
||||||
import { renderWithQueryClient } from '@/react-tools/test-utils';
|
|
||||||
import { UserContext } from '@/react/hooks/useUser';
|
|
||||||
import { UserViewModel } from '@/portainer/models/user';
|
import { UserViewModel } from '@/portainer/models/user';
|
||||||
import { server } from '@/setup-tests/server';
|
import { server } from '@/setup-tests/server';
|
||||||
|
import { withUserProvider } from '@/react/test-utils/withUserProvider';
|
||||||
|
import { withTestQueryProvider } from '@/react/test-utils/withTestQuery';
|
||||||
|
|
||||||
import { DockerNetwork } from '../types';
|
import { DockerNetwork } from '../types';
|
||||||
|
|
||||||
|
@ -26,7 +27,9 @@ test('Network details values should be visible', async () => {
|
||||||
await expect(findByText(network.Driver)).resolves.toBeVisible();
|
await expect(findByText(network.Driver)).resolves.toBeVisible();
|
||||||
await expect(findByText(network.Scope)).resolves.toBeVisible();
|
await expect(findByText(network.Scope)).resolves.toBeVisible();
|
||||||
await expect(
|
await expect(
|
||||||
findByText(network.IPAM?.Config[0].Gateway || 'not found', { exact: false })
|
findByText(network.IPAM?.Config[0].Gateway || 'not found', {
|
||||||
|
exact: false,
|
||||||
|
})
|
||||||
).resolves.toBeVisible();
|
).resolves.toBeVisible();
|
||||||
await expect(
|
await expect(
|
||||||
findByText(network.IPAM?.Config[0].Subnet || 'not found', { exact: false })
|
findByText(network.IPAM?.Config[0].Subnet || 'not found', { exact: false })
|
||||||
|
@ -55,13 +58,12 @@ async function renderComponent(isAdmin: boolean, network: DockerNetwork) {
|
||||||
|
|
||||||
const user = new UserViewModel({ Username: 'test', Role: isAdmin ? 1 : 2 });
|
const user = new UserViewModel({ Username: 'test', Role: isAdmin ? 1 : 2 });
|
||||||
|
|
||||||
const queries = renderWithQueryClient(
|
const Wrapped = withTestQueryProvider(
|
||||||
<UserContext.Provider value={{ user }}>
|
withUserProvider(NetworkDetailsTable, user)
|
||||||
<NetworkDetailsTable
|
);
|
||||||
network={network}
|
|
||||||
onRemoveNetworkClicked={() => {}}
|
const queries = render(
|
||||||
/>
|
<Wrapped network={network} onRemoveNetworkClicked={() => {}} />
|
||||||
</UserContext.Provider>
|
|
||||||
);
|
);
|
||||||
|
|
||||||
await expect(queries.findByText('Network details')).resolves.toBeVisible();
|
await expect(queries.findByText('Network details')).resolves.toBeVisible();
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { render } from '@/react-tools/test-utils';
|
import { render } from '@testing-library/react';
|
||||||
|
|
||||||
import { NetworkOptions } from '../types';
|
import { NetworkOptions } from '../types';
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import { render, screen } from '@/react-tools/test-utils';
|
import { render, screen } from '@testing-library/react';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
EnvVarType,
|
EnvVarType,
|
||||||
TemplateViewModel,
|
TemplateViewModel,
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import { vi } from 'vitest';
|
import { vi } from 'vitest';
|
||||||
import userEvent from '@testing-library/user-event';
|
import userEvent from '@testing-library/user-event';
|
||||||
|
import { render, screen } from '@testing-library/react';
|
||||||
import { render, screen } from '@/react-tools/test-utils';
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
EnvVarsFieldset,
|
EnvVarsFieldset,
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import { vi } from 'vitest';
|
import { vi } from 'vitest';
|
||||||
|
import { render, screen } from '@testing-library/react';
|
||||||
import { render, screen } from '@/react-tools/test-utils';
|
|
||||||
|
|
||||||
import { TemplateNote } from './TemplateNote';
|
import { TemplateNote } from './TemplateNote';
|
||||||
|
|
||||||
|
|
|
@ -1,17 +1,18 @@
|
||||||
import { vi } from 'vitest';
|
import { vi } from 'vitest';
|
||||||
import { HttpResponse, http } from 'msw';
|
import { HttpResponse, http } from 'msw';
|
||||||
|
import { render, screen } from '@testing-library/react';
|
||||||
|
|
||||||
import { renderWithQueryClient, screen } from '@/react-tools/test-utils';
|
|
||||||
import { AppTemplate } from '@/react/portainer/templates/app-templates/types';
|
import { AppTemplate } from '@/react/portainer/templates/app-templates/types';
|
||||||
import { CustomTemplate } from '@/react/portainer/templates/custom-templates/types';
|
import { CustomTemplate } from '@/react/portainer/templates/custom-templates/types';
|
||||||
import { server } from '@/setup-tests/server';
|
import { server } from '@/setup-tests/server';
|
||||||
import selectEvent from '@/react/test-utils/react-select';
|
import selectEvent from '@/react/test-utils/react-select';
|
||||||
|
import { withTestQueryProvider } from '@/react/test-utils/withTestQuery';
|
||||||
|
|
||||||
import { SelectedTemplateValue } from './types';
|
import { SelectedTemplateValue } from './types';
|
||||||
import { TemplateSelector } from './TemplateSelector';
|
import { TemplateSelector } from './TemplateSelector';
|
||||||
|
|
||||||
test('renders TemplateSelector component', async () => {
|
test('renders TemplateSelector component', async () => {
|
||||||
render();
|
renderComponent();
|
||||||
|
|
||||||
const templateSelectorElement = screen.getByLabelText('Template');
|
const templateSelectorElement = screen.getByLabelText('Template');
|
||||||
expect(templateSelectorElement).toBeInTheDocument();
|
expect(templateSelectorElement).toBeInTheDocument();
|
||||||
|
@ -30,7 +31,7 @@ test.skip('selects an edge app template', async () => {
|
||||||
categories: ['edge'],
|
categories: ['edge'],
|
||||||
};
|
};
|
||||||
|
|
||||||
const { select } = render({
|
const { select } = renderComponent({
|
||||||
onChange,
|
onChange,
|
||||||
appTemplates: [
|
appTemplates: [
|
||||||
{
|
{
|
||||||
|
@ -59,7 +60,7 @@ test.skip('selects an edge custom template', async () => {
|
||||||
Id: 2,
|
Id: 2,
|
||||||
};
|
};
|
||||||
|
|
||||||
const { select } = render({
|
const { select } = renderComponent({
|
||||||
onChange,
|
onChange,
|
||||||
customTemplates: [
|
customTemplates: [
|
||||||
{
|
{
|
||||||
|
@ -75,7 +76,7 @@ test.skip('selects an edge custom template', async () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
test('renders with error', async () => {
|
test('renders with error', async () => {
|
||||||
render({
|
renderComponent({
|
||||||
error: 'Invalid template',
|
error: 'Invalid template',
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -87,7 +88,7 @@ test('renders with error', async () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
test.skip('renders TemplateSelector component with no custom templates available', async () => {
|
test.skip('renders TemplateSelector component with no custom templates available', async () => {
|
||||||
render({
|
renderComponent({
|
||||||
customTemplates: [],
|
customTemplates: [],
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -102,7 +103,7 @@ test.skip('renders TemplateSelector component with no custom templates available
|
||||||
expect(noCustomTemplatesElement).toBeInTheDocument();
|
expect(noCustomTemplatesElement).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
function render({
|
function renderComponent({
|
||||||
onChange = vi.fn(),
|
onChange = vi.fn(),
|
||||||
appTemplates = [],
|
appTemplates = [],
|
||||||
customTemplates = [],
|
customTemplates = [],
|
||||||
|
@ -123,8 +124,10 @@ function render({
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
renderWithQueryClient(
|
const Wrapped = withTestQueryProvider(TemplateSelector);
|
||||||
<TemplateSelector
|
|
||||||
|
render(
|
||||||
|
<Wrapped
|
||||||
value={{ template: undefined, type: undefined }}
|
value={{ template: undefined, type: undefined }}
|
||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
error={error}
|
error={error}
|
||||||
|
|
|
@ -1,20 +1,17 @@
|
||||||
import { http, HttpResponse } from 'msw';
|
import { http, HttpResponse } from 'msw';
|
||||||
|
import { render } from '@testing-library/react';
|
||||||
|
|
||||||
import { server } from '@/setup-tests/server';
|
import { server } from '@/setup-tests/server';
|
||||||
import { renderWithQueryClient } from '@/react-tools/test-utils';
|
|
||||||
import { isoDate } from '@/portainer/filters/filters';
|
import { isoDate } from '@/portainer/filters/filters';
|
||||||
|
import { withTestRouter } from '@/react/test-utils/withRouter';
|
||||||
|
import { withTestQueryProvider } from '@/react/test-utils/withTestQuery';
|
||||||
|
|
||||||
import { BackupFailedPanel } from './BackupFailedPanel';
|
import { BackupFailedPanel } from './BackupFailedPanel';
|
||||||
|
|
||||||
test('when backup failed, should show message', async () => {
|
test('when backup failed, should show message', async () => {
|
||||||
const timestamp = 1500;
|
const timestamp = 1500;
|
||||||
server.use(
|
|
||||||
http.get('/api/backup/s3/status', () =>
|
|
||||||
HttpResponse.json({ Failed: true, TimestampUTC: timestamp })
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
const { findByText } = renderWithQueryClient(<BackupFailedPanel />);
|
const { findByText } = renderComponent({ failed: true, timestamp });
|
||||||
|
|
||||||
await expect(
|
await expect(
|
||||||
findByText(
|
findByText(
|
||||||
|
@ -27,14 +24,27 @@ test('when backup failed, should show message', async () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
test("when user is using less nodes then allowed he shouldn't see message", async () => {
|
test("when user is using less nodes then allowed he shouldn't see message", async () => {
|
||||||
server.use(
|
const { findByText } = renderComponent({ failed: false });
|
||||||
http.get('/api/backup/s3/status', () =>
|
|
||||||
HttpResponse.json({ Failed: false })
|
|
||||||
)
|
|
||||||
);
|
|
||||||
const { findByText } = renderWithQueryClient(<BackupFailedPanel />);
|
|
||||||
|
|
||||||
await expect(
|
await expect(
|
||||||
findByText('The latest automated backup has failed at', { exact: false })
|
findByText('The latest automated backup has failed at', { exact: false })
|
||||||
).rejects.toBeTruthy();
|
).rejects.toBeTruthy();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function renderComponent({
|
||||||
|
failed,
|
||||||
|
timestamp,
|
||||||
|
}: {
|
||||||
|
failed: boolean;
|
||||||
|
timestamp?: number;
|
||||||
|
}) {
|
||||||
|
server.use(
|
||||||
|
http.get('/api/backup/s3/status', () =>
|
||||||
|
HttpResponse.json({ Failed: failed, TimestampUTC: timestamp })
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
const Wrapped = withTestQueryProvider(withTestRouter(BackupFailedPanel));
|
||||||
|
|
||||||
|
return render(<Wrapped />);
|
||||||
|
}
|
||||||
|
|
|
@ -1,16 +1,18 @@
|
||||||
import { http, HttpResponse } from 'msw';
|
import { http, HttpResponse } from 'msw';
|
||||||
|
import { render } from '@testing-library/react';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
EnvironmentGroup,
|
EnvironmentGroup,
|
||||||
EnvironmentGroupId,
|
EnvironmentGroupId,
|
||||||
} from '@/react/portainer/environments/environment-groups/types';
|
} from '@/react/portainer/environments/environment-groups/types';
|
||||||
import { Environment } from '@/react/portainer/environments/types';
|
import { Environment } from '@/react/portainer/environments/types';
|
||||||
import { UserContext } from '@/react/hooks/useUser';
|
|
||||||
import { UserViewModel } from '@/portainer/models/user';
|
import { UserViewModel } from '@/portainer/models/user';
|
||||||
import { Tag } from '@/portainer/tags/types';
|
import { Tag } from '@/portainer/tags/types';
|
||||||
import { createMockEnvironment } from '@/react-tools/test-mocks';
|
import { createMockEnvironment } from '@/react-tools/test-mocks';
|
||||||
import { renderWithQueryClient } from '@/react-tools/test-utils';
|
|
||||||
import { server } from '@/setup-tests/server';
|
import { server } from '@/setup-tests/server';
|
||||||
|
import { withTestRouter } from '@/react/test-utils/withRouter';
|
||||||
|
import { withUserProvider } from '@/react/test-utils/withUserProvider';
|
||||||
|
import { withTestQueryProvider } from '@/react/test-utils/withTestQuery';
|
||||||
|
|
||||||
import { EnvironmentItem } from './EnvironmentItem';
|
import { EnvironmentItem } from './EnvironmentItem';
|
||||||
|
|
||||||
|
@ -43,15 +45,17 @@ function renderComponent(
|
||||||
|
|
||||||
server.use(http.get('/api/tags', () => HttpResponse.json(tags)));
|
server.use(http.get('/api/tags', () => HttpResponse.json(tags)));
|
||||||
|
|
||||||
return renderWithQueryClient(
|
const Wrapped = withTestQueryProvider(
|
||||||
<UserContext.Provider value={{ user }}>
|
withTestRouter(withUserProvider(EnvironmentItem, user))
|
||||||
<EnvironmentItem
|
);
|
||||||
|
|
||||||
|
return render(
|
||||||
|
<Wrapped
|
||||||
isActive={false}
|
isActive={false}
|
||||||
onClickBrowse={() => {}}
|
onClickBrowse={() => {}}
|
||||||
onClickDisconnect={() => {}}
|
onClickDisconnect={() => {}}
|
||||||
environment={env}
|
environment={env}
|
||||||
groupName={group.Name}
|
groupName={group.Name}
|
||||||
/>
|
/>
|
||||||
</UserContext.Provider>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
import { http, HttpResponse } from 'msw';
|
import { http, HttpResponse } from 'msw';
|
||||||
|
import { render } from '@testing-library/react';
|
||||||
|
|
||||||
import { Environment } from '@/react/portainer/environments/types';
|
import { Environment } from '@/react/portainer/environments/types';
|
||||||
import { UserContext } from '@/react/hooks/useUser';
|
|
||||||
import { UserViewModel } from '@/portainer/models/user';
|
import { UserViewModel } from '@/portainer/models/user';
|
||||||
import { renderWithQueryClient } from '@/react-tools/test-utils';
|
|
||||||
import { server } from '@/setup-tests/server';
|
import { server } from '@/setup-tests/server';
|
||||||
|
import { withUserProvider } from '@/react/test-utils/withUserProvider';
|
||||||
|
import { withTestRouter } from '@/react/test-utils/withRouter';
|
||||||
|
import { withTestQueryProvider } from '@/react/test-utils/withTestQuery';
|
||||||
|
|
||||||
import { EnvironmentList } from './EnvironmentList';
|
import { EnvironmentList } from './EnvironmentList';
|
||||||
|
|
||||||
|
@ -49,10 +51,12 @@ async function renderComponent(
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
const queries = renderWithQueryClient(
|
const Wrapped = withTestQueryProvider(
|
||||||
<UserContext.Provider value={{ user }}>
|
withUserProvider(withTestRouter(EnvironmentList), user)
|
||||||
<EnvironmentList onClickBrowse={vi.fn()} onRefresh={vi.fn()} />
|
);
|
||||||
</UserContext.Provider>
|
|
||||||
|
const queries = render(
|
||||||
|
<Wrapped onClickBrowse={vi.fn()} onRefresh={vi.fn()} />
|
||||||
);
|
);
|
||||||
|
|
||||||
await expect(queries.findByText('Environments')).resolves.toBeVisible();
|
await expect(queries.findByText('Environments')).resolves.toBeVisible();
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
import { http, HttpResponse } from 'msw';
|
import { http, HttpResponse } from 'msw';
|
||||||
|
import { render } from '@testing-library/react';
|
||||||
|
|
||||||
import { server } from '@/setup-tests/server';
|
import { server } from '@/setup-tests/server';
|
||||||
import { renderWithQueryClient } from '@/react-tools/test-utils';
|
import { withTestQueryProvider } from '@/react/test-utils/withTestQuery';
|
||||||
|
|
||||||
import { LicenseType } from '../licenses/types';
|
import { LicenseType } from '../licenses/types';
|
||||||
|
|
||||||
|
@ -17,7 +18,7 @@ test('when user is using more nodes then allowed he should see message', async (
|
||||||
http.get('/api/system/nodes', () => HttpResponse.json({ nodes: used }))
|
http.get('/api/system/nodes', () => HttpResponse.json({ nodes: used }))
|
||||||
);
|
);
|
||||||
|
|
||||||
const { findByText } = renderWithQueryClient(<LicenseNodePanel />);
|
const { findByText } = renderComponent();
|
||||||
|
|
||||||
await expect(
|
await expect(
|
||||||
findByText(
|
findByText(
|
||||||
|
@ -36,7 +37,7 @@ test("when user is using less nodes then allowed he shouldn't see message", asyn
|
||||||
http.get('/api/system/nodes', () => HttpResponse.json({ nodes: used }))
|
http.get('/api/system/nodes', () => HttpResponse.json({ nodes: used }))
|
||||||
);
|
);
|
||||||
|
|
||||||
const { findByText } = renderWithQueryClient(<LicenseNodePanel />);
|
const { findByText } = renderComponent();
|
||||||
|
|
||||||
await expect(
|
await expect(
|
||||||
findByText(
|
findByText(
|
||||||
|
@ -44,3 +45,9 @@ test("when user is using less nodes then allowed he shouldn't see message", asyn
|
||||||
)
|
)
|
||||||
).rejects.toBeTruthy();
|
).rejects.toBeTruthy();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function renderComponent() {
|
||||||
|
const Wrapped = withTestQueryProvider(LicenseNodePanel);
|
||||||
|
|
||||||
|
return render(<Wrapped />);
|
||||||
|
}
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
import { Meta, Story } from '@storybook/react';
|
import { Meta, Story } from '@storybook/react';
|
||||||
import { useMemo, useState } from 'react';
|
import { useState } from 'react';
|
||||||
import { QueryClient, QueryClientProvider } from 'react-query';
|
|
||||||
|
|
||||||
import { UserContext } from '@/react/hooks/useUser';
|
|
||||||
import { UserViewModel } from '@/portainer/models/user';
|
import { UserViewModel } from '@/portainer/models/user';
|
||||||
|
import { Role, User } from '@/portainer/users/types';
|
||||||
|
import { isPureAdmin } from '@/portainer/users/user.helpers';
|
||||||
|
import { withUserProvider } from '@/react/test-utils/withUserProvider';
|
||||||
|
|
||||||
import { parseAccessControlFormData } from '../utils';
|
import { parseAccessControlFormData } from '../utils';
|
||||||
|
|
||||||
|
@ -16,41 +17,25 @@ const meta: Meta = {
|
||||||
|
|
||||||
export default meta;
|
export default meta;
|
||||||
|
|
||||||
enum Role {
|
|
||||||
Admin = 1,
|
|
||||||
User,
|
|
||||||
}
|
|
||||||
|
|
||||||
const testQueryClient = new QueryClient({
|
|
||||||
defaultOptions: { queries: { retry: false } },
|
|
||||||
});
|
|
||||||
|
|
||||||
interface Args {
|
interface Args {
|
||||||
userRole: Role;
|
userRole: Role;
|
||||||
}
|
}
|
||||||
|
|
||||||
function Template({ userRole }: Args) {
|
function Template({ userRole }: Args) {
|
||||||
const isAdmin = userRole === Role.Admin;
|
const defaults = parseAccessControlFormData(
|
||||||
const defaults = parseAccessControlFormData(isAdmin, 0);
|
isPureAdmin({ Role: userRole } as User),
|
||||||
|
0
|
||||||
|
);
|
||||||
|
|
||||||
const [value, setValue] = useState(defaults);
|
const [value, setValue] = useState(defaults);
|
||||||
|
|
||||||
const userProviderState = useMemo(
|
const Wrapped = withUserProvider(
|
||||||
() => ({ user: new UserViewModel({ Role: userRole }) }),
|
AccessControlForm,
|
||||||
[userRole]
|
new UserViewModel({ Role: userRole })
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<QueryClientProvider client={testQueryClient}>
|
<Wrapped values={value} onChange={setValue} errors={{}} environmentId={1} />
|
||||||
<UserContext.Provider value={userProviderState}>
|
|
||||||
<AccessControlForm
|
|
||||||
values={value}
|
|
||||||
onChange={setValue}
|
|
||||||
errors={{}}
|
|
||||||
environmentId={1}
|
|
||||||
/>
|
|
||||||
</UserContext.Provider>
|
|
||||||
</QueryClientProvider>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -61,5 +46,5 @@ AdminAccessControl.args = {
|
||||||
|
|
||||||
export const NonAdminAccessControl: Story<Args> = Template.bind({});
|
export const NonAdminAccessControl: Story<Args> = Template.bind({});
|
||||||
NonAdminAccessControl.args = {
|
NonAdminAccessControl.args = {
|
||||||
userRole: Role.User,
|
userRole: Role.Standard,
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,12 +1,14 @@
|
||||||
import { http, HttpResponse } from 'msw';
|
import { http, HttpResponse } from 'msw';
|
||||||
|
import { render, within } from '@testing-library/react';
|
||||||
|
|
||||||
import { server } from '@/setup-tests/server';
|
import { server } from '@/setup-tests/server';
|
||||||
import { UserContext } from '@/react/hooks/useUser';
|
|
||||||
import { UserViewModel } from '@/portainer/models/user';
|
import { UserViewModel } from '@/portainer/models/user';
|
||||||
import { renderWithQueryClient, within } from '@/react-tools/test-utils';
|
|
||||||
import { Team, TeamId } from '@/react/portainer/users/teams/types';
|
import { Team, TeamId } from '@/react/portainer/users/teams/types';
|
||||||
import { createMockTeams } from '@/react-tools/test-mocks';
|
import { createMockTeams } from '@/react-tools/test-mocks';
|
||||||
import { UserId } from '@/portainer/users/types';
|
import { UserId } from '@/portainer/users/types';
|
||||||
|
import { withUserProvider } from '@/react/test-utils/withUserProvider';
|
||||||
|
import { withTestQueryProvider } from '@/react/test-utils/withTestQuery';
|
||||||
|
import { withTestRouter } from '@/react/test-utils/withRouter';
|
||||||
|
|
||||||
import { ResourceControlOwnership, AccessControlFormData } from '../types';
|
import { ResourceControlOwnership, AccessControlFormData } from '../types';
|
||||||
import { ResourceControlViewModel } from '../models/ResourceControlViewModel';
|
import { ResourceControlViewModel } from '../models/ResourceControlViewModel';
|
||||||
|
@ -304,7 +306,6 @@ async function renderComponent(
|
||||||
{ isAdmin = false, hideTitle = false, teams, users }: AdditionalProps = {}
|
{ isAdmin = false, hideTitle = false, teams, users }: AdditionalProps = {}
|
||||||
) {
|
) {
|
||||||
const user = new UserViewModel({ Username: 'user', Role: isAdmin ? 1 : 2 });
|
const user = new UserViewModel({ Username: 'user', Role: isAdmin ? 1 : 2 });
|
||||||
const state = { user };
|
|
||||||
|
|
||||||
if (teams) {
|
if (teams) {
|
||||||
server.use(http.get('/api/teams', () => HttpResponse.json(teams)));
|
server.use(http.get('/api/teams', () => HttpResponse.json(teams)));
|
||||||
|
@ -314,16 +315,18 @@ async function renderComponent(
|
||||||
server.use(http.get('/api/users', () => HttpResponse.json(users)));
|
server.use(http.get('/api/users', () => HttpResponse.json(users)));
|
||||||
}
|
}
|
||||||
|
|
||||||
const renderResult = renderWithQueryClient(
|
const Wrapped = withTestRouter(
|
||||||
<UserContext.Provider value={state}>
|
withTestQueryProvider(withUserProvider(AccessControlForm, user))
|
||||||
<AccessControlForm
|
);
|
||||||
|
|
||||||
|
const renderResult = render(
|
||||||
|
<Wrapped
|
||||||
environmentId={1}
|
environmentId={1}
|
||||||
errors={{}}
|
errors={{}}
|
||||||
values={values}
|
values={values}
|
||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
hideTitle={hideTitle}
|
hideTitle={hideTitle}
|
||||||
/>
|
/>
|
||||||
</UserContext.Provider>
|
|
||||||
);
|
);
|
||||||
|
|
||||||
await expect(
|
await expect(
|
||||||
|
|
|
@ -1,11 +1,13 @@
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
import { http, HttpResponse } from 'msw';
|
import { http, HttpResponse } from 'msw';
|
||||||
|
import { render } from '@testing-library/react';
|
||||||
|
|
||||||
import { createMockTeams, createMockUsers } from '@/react-tools/test-mocks';
|
import { createMockTeams, createMockUsers } from '@/react-tools/test-mocks';
|
||||||
import { renderWithQueryClient } from '@/react-tools/test-utils';
|
|
||||||
import { server } from '@/setup-tests/server';
|
import { server } from '@/setup-tests/server';
|
||||||
import { Role } from '@/portainer/users/types';
|
import { Role } from '@/portainer/users/types';
|
||||||
import { withUserProvider } from '@/react/test-utils/withUserProvider';
|
import { withUserProvider } from '@/react/test-utils/withUserProvider';
|
||||||
|
import { withTestRouter } from '@/react/test-utils/withRouter';
|
||||||
|
import { withTestQueryProvider } from '@/react/test-utils/withTestQuery';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
ResourceControlOwnership,
|
ResourceControlOwnership,
|
||||||
|
@ -145,9 +147,11 @@ async function renderComponent(
|
||||||
resourceType: ResourceControlType = ResourceControlType.Container,
|
resourceType: ResourceControlType = ResourceControlType.Container,
|
||||||
resourceControl?: ResourceControlViewModel
|
resourceControl?: ResourceControlViewModel
|
||||||
) {
|
) {
|
||||||
const WithUser = withUserProvider(AccessControlPanelDetails);
|
const Wrapped = withTestQueryProvider(
|
||||||
const queries = renderWithQueryClient(
|
withTestRouter(withUserProvider(AccessControlPanelDetails))
|
||||||
<WithUser resourceControl={resourceControl} resourceType={resourceType} />
|
);
|
||||||
|
const queries = render(
|
||||||
|
<Wrapped resourceControl={resourceControl} resourceType={resourceType} />
|
||||||
);
|
);
|
||||||
await expect(queries.findByText('Ownership')).resolves.toBeVisible();
|
await expect(queries.findByText('Ownership')).resolves.toBeVisible();
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
import userEvent from '@testing-library/user-event';
|
import userEvent from '@testing-library/user-event';
|
||||||
|
import { render, waitFor } from '@testing-library/react';
|
||||||
|
|
||||||
import { renderWithQueryClient, waitFor } from '@/react-tools/test-utils';
|
|
||||||
import { UserViewModel } from '@/portainer/models/user';
|
import { UserViewModel } from '@/portainer/models/user';
|
||||||
import { UserContext } from '@/react/hooks/useUser';
|
import { withTestRouter } from '@/react/test-utils/withRouter';
|
||||||
|
import { withUserProvider } from '@/react/test-utils/withUserProvider';
|
||||||
|
import { withTestQueryProvider } from '@/react/test-utils/withTestQuery';
|
||||||
|
|
||||||
import { CreateUserAccessToken } from './CreateUserAccessToken';
|
import { CreateUserAccessToken } from './CreateUserAccessToken';
|
||||||
|
|
||||||
|
@ -33,9 +35,9 @@ test('the button is disabled when all fields are blank and enabled when all fiel
|
||||||
function renderComponent() {
|
function renderComponent() {
|
||||||
const user = new UserViewModel({ Username: 'user' });
|
const user = new UserViewModel({ Username: 'user' });
|
||||||
|
|
||||||
return renderWithQueryClient(
|
const Wrapped = withTestQueryProvider(
|
||||||
<UserContext.Provider value={{ user }}>
|
withUserProvider(withTestRouter(CreateUserAccessToken), user)
|
||||||
<CreateUserAccessToken />
|
|
||||||
</UserContext.Provider>
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
return render(<Wrapped />);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import { vi } from 'vitest';
|
import { vi } from 'vitest';
|
||||||
import userEvent from '@testing-library/user-event';
|
import userEvent from '@testing-library/user-event';
|
||||||
|
import { render, screen } from '@testing-library/react';
|
||||||
import { render, screen } from '@/react-tools/test-utils';
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
CustomTemplatesVariablesField,
|
CustomTemplatesVariablesField,
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import { vi } from 'vitest';
|
import { vi } from 'vitest';
|
||||||
import userEvent from '@testing-library/user-event';
|
import userEvent from '@testing-library/user-event';
|
||||||
|
import { render, screen } from '@testing-library/react';
|
||||||
import { render, screen } from '@/react-tools/test-utils';
|
|
||||||
|
|
||||||
import { VariableFieldItem } from './VariableFieldItem';
|
import { VariableFieldItem } from './VariableFieldItem';
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import userEvent from '@testing-library/user-event';
|
import userEvent from '@testing-library/user-event';
|
||||||
import { PropsWithChildren } from 'react';
|
import { PropsWithChildren } from 'react';
|
||||||
|
import { render } from '@testing-library/react';
|
||||||
import { render } from '@/react-tools/test-utils';
|
|
||||||
|
|
||||||
import { AppTemplatesListItem } from './AppTemplatesListItem';
|
import { AppTemplatesListItem } from './AppTemplatesListItem';
|
||||||
import { TemplateViewModel } from './view-model';
|
import { TemplateViewModel } from './view-model';
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
import { UserContext } from '@/react/hooks/useUser';
|
import { render } from '@testing-library/react';
|
||||||
|
|
||||||
import { UserViewModel } from '@/portainer/models/user';
|
import { UserViewModel } from '@/portainer/models/user';
|
||||||
import { renderWithQueryClient } from '@/react-tools/test-utils';
|
import { withTestQueryProvider } from '@/react/test-utils/withTestQuery';
|
||||||
|
import { withUserProvider } from '@/react/test-utils/withUserProvider';
|
||||||
|
|
||||||
import { TeamAssociationSelector } from './TeamAssociationSelector';
|
import { TeamAssociationSelector } from './TeamAssociationSelector';
|
||||||
|
|
||||||
|
@ -13,9 +15,9 @@ test('renders correctly', () => {
|
||||||
function renderComponent() {
|
function renderComponent() {
|
||||||
const user = new UserViewModel({ Username: 'user' });
|
const user = new UserViewModel({ Username: 'user' });
|
||||||
|
|
||||||
return renderWithQueryClient(
|
const Wrapped = withTestQueryProvider(
|
||||||
<UserContext.Provider value={{ user }}>
|
withUserProvider(TeamAssociationSelector, user)
|
||||||
<TeamAssociationSelector users={[]} memberships={[]} teamId={3} />
|
|
||||||
</UserContext.Provider>
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
return render(<Wrapped users={[]} memberships={[]} teamId={3} />);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
import { UserContext } from '@/react/hooks/useUser';
|
import { render } from '@testing-library/react';
|
||||||
|
|
||||||
import { UserViewModel } from '@/portainer/models/user';
|
import { UserViewModel } from '@/portainer/models/user';
|
||||||
import { renderWithQueryClient } from '@/react-tools/test-utils';
|
import { withUserProvider } from '@/react/test-utils/withUserProvider';
|
||||||
|
import { withTestQueryProvider } from '@/react/test-utils/withTestQuery';
|
||||||
|
|
||||||
import { TeamMembersList } from './TeamMembersList';
|
import { TeamMembersList } from './TeamMembersList';
|
||||||
|
|
||||||
|
@ -13,11 +15,11 @@ test('renders correctly', () => {
|
||||||
function renderComponent() {
|
function renderComponent() {
|
||||||
const user = new UserViewModel({ Username: 'user' });
|
const user = new UserViewModel({ Username: 'user' });
|
||||||
|
|
||||||
return renderWithQueryClient(
|
const Wrapped = withTestQueryProvider(
|
||||||
<UserContext.Provider value={{ user }}>
|
withUserProvider(TeamMembersList, user)
|
||||||
<TeamMembersList users={[]} roles={{}} teamId={3} />
|
|
||||||
</UserContext.Provider>
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
return render(<Wrapped users={[]} roles={{}} teamId={3} />);
|
||||||
}
|
}
|
||||||
|
|
||||||
test.todo('when users list is empty, add all users button is disabled');
|
test.todo('when users list is empty, add all users button is disabled');
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
import { UserContext } from '@/react/hooks/useUser';
|
import { render } from '@testing-library/react';
|
||||||
|
|
||||||
import { UserViewModel } from '@/portainer/models/user';
|
import { UserViewModel } from '@/portainer/models/user';
|
||||||
import { renderWithQueryClient } from '@/react-tools/test-utils';
|
import { withTestQueryProvider } from '@/react/test-utils/withTestQuery';
|
||||||
|
import { withUserProvider } from '@/react/test-utils/withUserProvider';
|
||||||
|
|
||||||
import { UsersList } from './UsersList';
|
import { UsersList } from './UsersList';
|
||||||
|
|
||||||
|
@ -12,11 +14,10 @@ test('renders correctly', () => {
|
||||||
|
|
||||||
function renderComponent() {
|
function renderComponent() {
|
||||||
const user = new UserViewModel({ Username: 'user' });
|
const user = new UserViewModel({ Username: 'user' });
|
||||||
return renderWithQueryClient(
|
|
||||||
<UserContext.Provider value={{ user }}>
|
const Wrapped = withTestQueryProvider(withUserProvider(UsersList, user));
|
||||||
<UsersList users={[]} teamId={3} />
|
|
||||||
</UserContext.Provider>
|
return render(<Wrapped users={[]} teamId={3} />);
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
test.todo('when users list is empty, add all users button is disabled');
|
test.todo('when users list is empty, add all users button is disabled');
|
||||||
|
|
|
@ -1,12 +1,15 @@
|
||||||
import userEvent from '@testing-library/user-event';
|
import userEvent from '@testing-library/user-event';
|
||||||
|
import { render, waitFor } from '@testing-library/react';
|
||||||
|
|
||||||
import { renderWithQueryClient, waitFor } from '@/react-tools/test-utils';
|
import { withTestQueryProvider } from '@/react/test-utils/withTestQuery';
|
||||||
|
|
||||||
import { CreateTeamForm } from './CreateTeamForm';
|
import { CreateTeamForm } from './CreateTeamForm';
|
||||||
|
|
||||||
test('filling the name should make the submit button clickable and emptying it should make it disabled', async () => {
|
test('filling the name should make the submit button clickable and emptying it should make it disabled', async () => {
|
||||||
const { findByLabelText, findByText } = renderWithQueryClient(
|
const Wrapped = withTestQueryProvider(CreateTeamForm);
|
||||||
<CreateTeamForm users={[]} teams={[]} />
|
|
||||||
|
const { findByLabelText, findByText } = render(
|
||||||
|
<Wrapped users={[]} teams={[]} />
|
||||||
);
|
);
|
||||||
|
|
||||||
const button = await findByText('Create team');
|
const button = await findByText('Create team');
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
import { UserContext } from '@/react/hooks/useUser';
|
import { render, within } from '@testing-library/react';
|
||||||
|
|
||||||
import { UserViewModel } from '@/portainer/models/user';
|
import { UserViewModel } from '@/portainer/models/user';
|
||||||
import { render, within } from '@/react-tools/test-utils';
|
import { withUserProvider } from '@/react/test-utils/withUserProvider';
|
||||||
|
import { withTestRouter } from '@/react/test-utils/withRouter';
|
||||||
|
|
||||||
import { TestSidebarProvider } from '../useSidebarState';
|
import { TestSidebarProvider } from '../useSidebarState';
|
||||||
|
|
||||||
|
@ -30,11 +32,11 @@ test('dashboard items should render correctly', () => {
|
||||||
function renderComponent() {
|
function renderComponent() {
|
||||||
const user = new UserViewModel({ Username: 'user' });
|
const user = new UserViewModel({ Username: 'user' });
|
||||||
|
|
||||||
|
const Wrapped = withUserProvider(withTestRouter(AzureSidebar), user);
|
||||||
|
|
||||||
return render(
|
return render(
|
||||||
<UserContext.Provider value={{ user }}>
|
|
||||||
<TestSidebarProvider>
|
<TestSidebarProvider>
|
||||||
<AzureSidebar environmentId={1} />
|
<Wrapped environmentId={1} />
|
||||||
</TestSidebarProvider>
|
</TestSidebarProvider>
|
||||||
</UserContext.Provider>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,49 @@
|
||||||
|
import { ComponentType } from 'react';
|
||||||
|
import {
|
||||||
|
ReactStateDeclaration,
|
||||||
|
UIRouter,
|
||||||
|
UIRouterReact,
|
||||||
|
UIView,
|
||||||
|
hashLocationPlugin,
|
||||||
|
servicesPlugin,
|
||||||
|
} from '@uirouter/react';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A helper function to wrap a component with a UIRouter Provider.
|
||||||
|
*
|
||||||
|
* should only be used in tests
|
||||||
|
*/
|
||||||
|
export function withTestRouter<T>(
|
||||||
|
WrappedComponent: ComponentType<T>,
|
||||||
|
{
|
||||||
|
route = '/',
|
||||||
|
stateConfig = [],
|
||||||
|
}: { route?: string; stateConfig?: Array<ReactStateDeclaration> } = {}
|
||||||
|
): ComponentType<T> {
|
||||||
|
const router = new UIRouterReact();
|
||||||
|
|
||||||
|
// router.trace.enable(Category.TRANSITION);
|
||||||
|
router.plugin(servicesPlugin);
|
||||||
|
router.plugin(hashLocationPlugin);
|
||||||
|
|
||||||
|
// Set up your custom state configuration
|
||||||
|
stateConfig.forEach((state) => router.stateRegistry.register(state));
|
||||||
|
router.urlService.rules.initial({ state: route });
|
||||||
|
|
||||||
|
// Try to create a nice displayName for React Dev Tools.
|
||||||
|
const displayName =
|
||||||
|
WrappedComponent.displayName || WrappedComponent.name || 'Component';
|
||||||
|
|
||||||
|
function WrapperComponent(props: T & JSX.IntrinsicAttributes) {
|
||||||
|
return (
|
||||||
|
<UIRouter router={router}>
|
||||||
|
<UIView />
|
||||||
|
<WrappedComponent {...props} />
|
||||||
|
</UIRouter>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
WrapperComponent.displayName = `withTestRouter(${displayName})`;
|
||||||
|
|
||||||
|
return WrapperComponent;
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
import { ComponentType } from 'react';
|
||||||
|
import { QueryClient } from 'react-query';
|
||||||
|
|
||||||
|
import { withReactQuery } from '@/react-tools/withReactQuery';
|
||||||
|
|
||||||
|
export function withTestQueryProvider<T>(
|
||||||
|
WrappedComponent: ComponentType<T & JSX.IntrinsicAttributes>
|
||||||
|
) {
|
||||||
|
const testQueryClient = new QueryClient({
|
||||||
|
defaultOptions: { queries: { retry: false } },
|
||||||
|
});
|
||||||
|
|
||||||
|
return withReactQuery(WrappedComponent, testQueryClient);
|
||||||
|
}
|
|
@ -11,6 +11,7 @@ import { StatusResponse } from '@/react/portainer/system/useSystemStatus';
|
||||||
import { createMockTeams } from '@/react-tools/test-mocks';
|
import { createMockTeams } from '@/react-tools/test-mocks';
|
||||||
import { PublicSettingsResponse } from '@/react/portainer/settings/types';
|
import { PublicSettingsResponse } from '@/react/portainer/settings/types';
|
||||||
import { UserId } from '@/portainer/users/types';
|
import { UserId } from '@/portainer/users/types';
|
||||||
|
import { VersionResponse } from '@/react/portainer/system/useSystemVersion';
|
||||||
|
|
||||||
import { azureHandlers } from './setup-handlers/azure';
|
import { azureHandlers } from './setup-handlers/azure';
|
||||||
import { dockerHandlers } from './setup-handlers/docker';
|
import { dockerHandlers } from './setup-handlers/docker';
|
||||||
|
@ -85,6 +86,9 @@ export const handlers = [
|
||||||
http.get<never, never, Partial<StatusResponse>>('/api/status', () =>
|
http.get<never, never, Partial<StatusResponse>>('/api/status', () =>
|
||||||
HttpResponse.json({})
|
HttpResponse.json({})
|
||||||
),
|
),
|
||||||
|
http.get<never, never, Partial<VersionResponse>>('/api/system/version', () =>
|
||||||
|
HttpResponse.json({ ServerVersion: 'v2.10.0' })
|
||||||
|
),
|
||||||
http.get('/api/teams/:id/memberships', () => HttpResponse.json([])),
|
http.get('/api/teams/:id/memberships', () => HttpResponse.json([])),
|
||||||
http.get('/api/endpoints/agent_versions', () => HttpResponse.json([])),
|
http.get('/api/endpoints/agent_versions', () => HttpResponse.json([])),
|
||||||
];
|
];
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
import 'vitest-dom/extend-expect';
|
|
@ -7,7 +7,7 @@ export default defineConfig({
|
||||||
test: {
|
test: {
|
||||||
globals: true,
|
globals: true,
|
||||||
environment: 'jsdom',
|
environment: 'jsdom',
|
||||||
setupFiles: ['./app/setup-tests/setup-msw.ts', './app/setup-tests/stub-modules.ts'],
|
setupFiles: ['./app/setup-tests/setup-msw.ts', './app/setup-tests/stub-modules.ts', './app/setup-tests/setup.ts'],
|
||||||
coverage: {
|
coverage: {
|
||||||
reporter: ['text', 'html'],
|
reporter: ['text', 'html'],
|
||||||
exclude: ['node_modules/', 'app/setup-tests/global-setup.js'],
|
exclude: ['node_modules/', 'app/setup-tests/global-setup.js'],
|
||||||
|
|
Loading…
Reference in New Issue