tests(marketplace): await data-fetching so there's no act warnings (#18053)

This commit is contained in:
Josh 2023-09-14 08:11:40 +01:00 committed by GitHub
parent 749e4c3238
commit 1d5272ff86
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 226 additions and 2915 deletions

View File

@ -8,7 +8,7 @@ import { EmptyNpmPackageGrid } from './EmptyNpmPackageGrid';
const EmptyNpmPackageSearch = ({ content }) => {
return (
<Box position="relative" data-testid="marketplace-results">
<Box position="relative">
<EmptyNpmPackageGrid />
<Box position="absolute" top={11} width="100%">
<Flex alignItems="center" justifyContent="center" direction="column">

View File

@ -50,7 +50,6 @@ const NpmPackagesFilters = ({
<ButtonToggle
variant="tertiary"
ref={buttonRef}
data-testid="filters-button"
startIcon={<Filter />}
onClick={handleToggle}
size="S"

View File

@ -49,7 +49,7 @@ const NpmPackagesGrid = ({
}
return (
<Grid gap={4} data-testid="marketplace-results">
<Grid gap={4}>
{npmPackages.map((npmPackage) => (
<GridItem col={4} s={6} xs={12} style={{ height: '100%' }} key={npmPackage.id}>
<NpmPackageCard

View File

@ -1,33 +1,22 @@
import React from 'react';
import { fixtures } from '@strapi/admin-test-utils';
import { lightTheme, ThemeProvider } from '@strapi/design-system';
import { TrackingProvider, useAppInfo, useTracking } from '@strapi/helper-plugin';
import { fireEvent, render, screen, within } from '@testing-library/react';
import { NotificationsProvider, useAppInfo, useTracking } from '@strapi/helper-plugin';
import { fireEvent, render as renderRTL, screen, waitFor, within } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { createMemoryHistory } from 'history';
import { IntlProvider } from 'react-intl';
import { QueryClient, QueryClientProvider } from 'react-query';
import { Provider } from 'react-redux';
import { Router } from 'react-router-dom';
import { createStore } from 'redux';
import { MemoryRouter } from 'react-router-dom';
import useNavigatorOnLine from '../../../hooks/useNavigatorOnLine';
import MarketPlacePage from '../index';
import { MarketPlacePage } from '../index';
import server from './server';
const toggleNotification = jest.fn();
jest.mock('../../../hooks/useNavigatorOnLine', () => jest.fn(() => true));
jest.mock('@strapi/helper-plugin', () => ({
...jest.requireActual('@strapi/helper-plugin'),
useTracking: jest.fn(() => ({ trackUsage: jest.fn() })),
useNotification: jest.fn(() => {
return toggleNotification;
}),
CheckPagePermissions: ({ children }) => children,
useAppInfo: jest.fn(() => ({
autoReload: true,
dependencies: {
@ -39,10 +28,9 @@ jest.mock('@strapi/helper-plugin', () => ({
})),
}));
const setup = (props) => ({
...render(<MarketPlacePage {...props} />, {
const render = (props) => ({
...renderRTL(<MarketPlacePage {...props} />, {
wrapper({ children }) {
const history = createMemoryHistory();
const client = new QueryClient({
defaultOptions: {
queries: {
@ -52,30 +40,23 @@ const setup = (props) => ({
});
return (
<Provider
store={createStore((state) => state, {
admin_app: { permissions: fixtures.permissions.app },
})}
>
<QueryClientProvider client={client}>
<TrackingProvider>
<IntlProvider locale="en" messages={{}} textComponent="span">
<ThemeProvider theme={lightTheme}>
<Router history={history}>{children}</Router>
</ThemeProvider>
</IntlProvider>
</TrackingProvider>
</QueryClientProvider>
</Provider>
<QueryClientProvider client={client}>
<IntlProvider locale="en" messages={{}} textComponent="span">
<ThemeProvider theme={lightTheme}>
<NotificationsProvider>
<MemoryRouter>{children}</MemoryRouter>
</NotificationsProvider>
</ThemeProvider>
</IntlProvider>
</QueryClientProvider>
);
},
}),
user: userEvent.setup(),
});
const waitForReload = async () => {
await screen.findByTestId('marketplace-results');
await waitFor(() => expect(screen.queryByText('Loading content...')).not.toBeInTheDocument());
};
describe('Marketplace page - layout', () => {
@ -91,34 +72,21 @@ describe('Marketplace page - layout', () => {
const trackUsage = jest.fn();
useTracking.mockImplementationOnce(() => ({ trackUsage }));
const { container } = setup();
const { queryByText, getByRole } = render();
await waitForReload();
// Check snapshot
expect(container.firstChild).toMatchSnapshot();
// Calls the tracking event
expect(trackUsage).toHaveBeenCalledWith('didGoToMarketplace');
expect(trackUsage).toHaveBeenCalledTimes(1);
const offlineText = screen.queryByText('You are offline');
expect(offlineText).toEqual(null);
expect(queryByText('You are offline')).toEqual(null);
// Shows the sort button
const sortButton = screen.getByRole('combobox', { name: /Sort by/i });
expect(sortButton).toBeVisible();
expect(getByRole('combobox', { name: /Sort by/i })).toBeVisible();
// Shows the filters button
const filtersButton = screen.getByText(/Filters/i).closest('button');
expect(filtersButton).toBeVisible();
});
it('renders the offline layout', async () => {
useNavigatorOnLine.mockReturnValueOnce(false);
const { getByText } = setup();
const offlineText = getByText('You are offline');
expect(offlineText).toBeVisible();
expect(getByRole('button', { name: 'Filters' })).toBeVisible();
});
it('disables the button and shows compatibility tooltip message when version provided', async () => {
const { findByTestId, findAllByTestId } = setup();
const { findByTestId, findAllByTestId } = render();
const alreadyInstalledCard = (await findAllByTestId('npm-package-card')).find((div) =>
div.innerHTML.includes('Transformer')
@ -137,7 +105,7 @@ describe('Marketplace page - layout', () => {
});
it('shows compatibility tooltip message when no version provided', async () => {
const { findByTestId, findAllByTestId, user } = setup();
const { findByTestId, findAllByTestId, user } = render();
const alreadyInstalledCard = (await findAllByTestId('npm-package-card')).find((div) =>
div.innerHTML.includes('Config Sync')
@ -147,7 +115,7 @@ describe('Marketplace page - layout', () => {
.getByText(/copy install command/i)
.closest('button');
user.hover(button);
await user.hover(button);
const tooltip = await findByTestId(`tooltip-Config Sync`);
expect(button).not.toBeDisabled();
@ -165,24 +133,16 @@ describe('Marketplace page - layout', () => {
useYarn: true,
}));
const { queryByText } = setup();
const { queryByText, getByText } = render();
await waitForReload();
// Should display notification
expect(toggleNotification).toHaveBeenCalledWith({
type: 'info',
message: {
id: 'admin.pages.MarketPlacePage.production',
defaultMessage: 'Manage plugins from the development environment',
},
});
expect(toggleNotification).toHaveBeenCalledTimes(1);
expect(getByText('Manage plugins from the development environment')).toBeVisible();
// Should not show install buttons
expect(queryByText(/copy install command/i)).toEqual(null);
});
it('shows only downloads count and not github stars if there are no or 0 stars and no downloads available for any package', async () => {
const { findByText, findAllByTestId, user } = setup();
const { findByText, findAllByTestId, user } = render();
const providersTab = (await findByText(/providers/i)).closest('button');
await user.click(providersTab);

View File

@ -1,32 +1,23 @@
import React from 'react';
import { fixtures } from '@strapi/admin-test-utils';
import { lightTheme, ThemeProvider } from '@strapi/design-system';
import { TrackingProvider } from '@strapi/helper-plugin';
import { render, screen, within } from '@testing-library/react';
import { NotificationsProvider } from '@strapi/helper-plugin';
import { render as renderRTL, screen, waitFor, within } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { createMemoryHistory } from 'history';
import { IntlProvider } from 'react-intl';
import { QueryClient, QueryClientProvider } from 'react-query';
import { Provider } from 'react-redux';
import { Router } from 'react-router-dom';
import { createStore } from 'redux';
import { MemoryRouter, Route } from 'react-router-dom';
import MarketPlacePage from '../index';
import { MarketPlacePage } from '../index';
import server from './server';
// Increase the jest timeout to accommodate long running tests
jest.setTimeout(50000);
const toggleNotification = jest.fn();
jest.mock('../../../hooks/useNavigatorOnLine', () => jest.fn(() => true));
jest.mock('../../../hooks/useDebounce', () => (value) => value);
jest.mock('@strapi/helper-plugin', () => ({
...jest.requireActual('@strapi/helper-plugin'),
useNotification: jest.fn(() => {
return toggleNotification;
}),
CheckPagePermissions: ({ children }) => children,
useAppInfo: jest.fn(() => ({
autoReload: true,
dependencies: {
@ -38,13 +29,14 @@ jest.mock('@strapi/helper-plugin', () => ({
}));
const waitForReload = async () => {
await screen.findByTestId('marketplace-results');
await waitFor(() => expect(screen.queryByText('Loading content...')).not.toBeInTheDocument());
};
const setup = (props) => ({
...render(<MarketPlacePage {...props} />, {
let testLocation = null;
const render = (props) => ({
...renderRTL(<MarketPlacePage {...props} />, {
wrapper({ children }) {
const history = createMemoryHistory();
const client = new QueryClient({
defaultOptions: {
queries: {
@ -54,25 +46,28 @@ const setup = (props) => ({
});
return (
<Provider
store={createStore((state) => state, {
admin_app: { permissions: fixtures.permissions.app },
})}
>
<QueryClientProvider client={client}>
<TrackingProvider>
<IntlProvider locale="en" messages={{}} textComponent="span">
<ThemeProvider theme={lightTheme}>
<Router history={history}>{children}</Router>
</ThemeProvider>
</IntlProvider>
</TrackingProvider>
</QueryClientProvider>
</Provider>
<QueryClientProvider client={client}>
<IntlProvider locale="en" messages={{}} textComponent="span">
<ThemeProvider theme={lightTheme}>
<NotificationsProvider>
<MemoryRouter>
{children}
<Route
path="*"
render={({ location }) => {
testLocation = location;
return null;
}}
/>
</MemoryRouter>
</NotificationsProvider>
</ThemeProvider>
</IntlProvider>
</QueryClientProvider>
);
},
}),
user: userEvent.setup(),
});
@ -86,32 +81,22 @@ describe('Marketplace page - plugins tab', () => {
afterAll(() => server.close());
it('renders the plugins tab', async () => {
const { getByRole, getByText, queryByText } = setup();
const { getByRole, getByText, queryByText } = render();
await waitForReload();
// Make sure it defaults to the plugins tab
const button = getByRole('tab', { selected: true });
const pluginsTabActive = within(button).getByText(/plugins/i);
const pluginCardText = getByText('Comments');
const providerCardText = queryByText('Cloudinary');
const submitPluginText = queryByText('Submit plugin');
expect(pluginsTabActive).not.toBe(null);
expect(pluginCardText).toBeVisible();
expect(submitPluginText).toBeVisible();
expect(providerCardText).toEqual(null);
expect(getByRole('tab', { selected: true, name: /plugins/i })).toBeInTheDocument();
expect(getByText('Comments')).toBeVisible();
expect(queryByText('Cloudinary')).toEqual(null);
expect(getByRole('link', { name: 'Submit plugin' })).toBeVisible();
});
it('should return plugin search results matching the query', async () => {
const { getByPlaceholderText, getByText, queryByText, user } = setup();
const { getByPlaceholderText, getByText, queryByText, user } = render();
await waitForReload();
const input = getByPlaceholderText('Search');
await user.type(input, 'comment');
await user.type(getByPlaceholderText('Search'), 'comment');
await waitForReload();
const match = getByText('Comments');
@ -124,21 +109,19 @@ describe('Marketplace page - plugins tab', () => {
});
it('should return empty plugin search results given a bad query', async () => {
const { getByPlaceholderText, getByText, user } = setup();
const { getByPlaceholderText, getByText, user } = render();
await waitForReload();
const input = getByPlaceholderText('Search');
const badQuery = 'asdf';
await user.type(input, badQuery);
await user.type(getByPlaceholderText('Search'), badQuery);
await waitForReload();
const noResult = getByText(`No result for "${badQuery}"`);
expect(noResult).toBeVisible();
expect(getByText(`No result for "${badQuery}"`)).toBeVisible();
});
it('shows the installed text for installed plugins', async () => {
const { getAllByTestId } = setup();
const { getAllByTestId } = render();
await waitForReload();
@ -158,88 +141,63 @@ describe('Marketplace page - plugins tab', () => {
});
it('shows plugins filters popover', async () => {
const { getByTestId, getByRole, user } = setup();
const { getByRole, user } = render();
await waitForReload();
const filtersButton = getByTestId('filters-button');
await user.click(filtersButton);
await user.click(getByRole('button', { name: 'Filters' }));
const collectionsButton = getByRole('combobox', { name: 'Collections' });
const categoriesButton = getByRole('combobox', { name: 'Categories' });
expect(collectionsButton).toBeVisible();
expect(categoriesButton).toBeVisible();
expect(getByRole('combobox', { name: 'Collections' })).toBeVisible();
expect(getByRole('combobox', { name: 'Categories' })).toBeVisible();
});
it('shows the collections filter options', async () => {
const { getByTestId, getByRole, user } = setup();
const { getByRole, user } = render();
await waitForReload();
const filtersButton = getByTestId('filters-button');
await user.click(filtersButton);
await user.click(getByRole('button', { name: 'Filters' }));
await user.click(getByRole('combobox', { name: 'Collections' }));
const collectionsButton = getByRole('combobox', { name: 'Collections' });
await user.click(collectionsButton);
const mockedServerCollections = {
'Made by official partners': 9,
'Made by Strapi': 13,
'Made by the community': 69,
Verified: 29,
};
Object.entries(mockedServerCollections).forEach(([collectionName, count]) => {
const option = getByTestId(`${collectionName}-${count}`);
expect(option).toBeVisible();
[
'Made by official partners (9)',
'Made by Strapi (13)',
'Made by the community (69)',
'Verified (29)',
].forEach((name) => {
expect(getByRole('option', { name })).toBeVisible();
});
});
it('shows the categories filter options', async () => {
const { getByTestId, getByRole, user } = setup();
const { getByRole, user } = render();
await waitForReload();
const filtersButton = getByTestId('filters-button');
await user.click(filtersButton);
await user.click(getByRole('button', { name: 'Filters' }));
await user.click(getByRole('combobox', { name: 'Categories' }));
const categoriesButton = getByRole('combobox', { name: 'Categories' });
await user.click(categoriesButton);
const mockedServerCategories = {
'Custom fields': 4,
Deployment: 2,
Monitoring: 1,
};
Object.entries(mockedServerCategories).forEach(([categoryName, count]) => {
const option = getByTestId(`${categoryName}-${count}`);
expect(option).toBeVisible();
['Custom fields (4)', 'Deployment (2)', 'Monitoring (1)'].forEach((name) => {
expect(getByRole('option', { name })).toBeVisible();
});
});
it('filters a collection option', async () => {
const { getByTestId, getAllByTestId, getByText, queryByText, getByRole, user } = setup();
const { getAllByTestId, getByText, queryByText, getByRole, user } = render();
await waitForReload();
const filtersButton = getByTestId('filters-button');
await user.click(filtersButton);
const collectionsButton = getByRole('combobox', { name: 'Collections' });
await user.click(collectionsButton);
const option = getByTestId('Made by Strapi-13');
await user.click(option);
await user.click(getByRole('button', { name: 'Filters' }));
await user.click(getByRole('combobox', { name: 'Collections' }));
await user.click(getByRole('option', { name: 'Made by Strapi (13)' }));
// Close the combobox
await user.keyboard('[Escape]');
// Close the popover
await user.keyboard('[Escape]');
await waitForReload();
const optionTag = getByRole('button', { name: 'Made by Strapi' });
expect(optionTag).toBeVisible();
expect(getByRole('button', { name: 'Made by Strapi' })).toBeVisible();
const collectionCards = getAllByTestId('npm-package-card');
expect(collectionCards.length).toEqual(2);
@ -251,18 +209,13 @@ describe('Marketplace page - plugins tab', () => {
});
it('filters a category option', async () => {
const { getByTestId, getAllByTestId, getByText, queryByText, getByRole, user } = setup();
const { getAllByTestId, getByText, queryByText, getByRole, user } = render();
await waitForReload();
const filtersButton = getByTestId('filters-button');
await user.click(filtersButton);
const categoriesButton = getByRole('combobox', { name: 'Categories' });
await user.click(categoriesButton);
const option = getByTestId('Custom fields-4');
await user.click(option);
await user.click(getByRole('button', { name: 'Filters' }));
await user.click(getByRole('combobox', { name: 'Categories' }));
await user.click(getByRole('option', { name: 'Custom fields (4)' }));
// Close the combobox
await user.keyboard('[Escape]');
// Close the popover
@ -282,44 +235,34 @@ describe('Marketplace page - plugins tab', () => {
});
it('filters a category and a collection option', async () => {
const { getByTestId, getByRole, getAllByTestId, getByText, queryByText, user } = setup();
const { getByRole, getAllByTestId, getByText, queryByText, user } = render();
await waitForReload();
// When a user clicks the filters button
await user.click(getByTestId('filters-button'));
// They should see a select button for collections with no options selected
const collectionsButton = getByRole('combobox', { name: 'Collections' });
// When they click the select button
await user.click(collectionsButton);
// They should see a Made by Strapi option
const collectionOption = getByTestId('Made by Strapi-13');
// When they click the option
await user.click(collectionOption);
await user.click(getByRole('button', { name: 'Filters' }));
await user.click(getByRole('combobox', { name: 'Collections' }));
await user.click(getByRole('option', { name: 'Made by Strapi (13)' }));
// Close the combobox
await user.keyboard('[Escape]');
// Close the popover
await user.keyboard('[Escape]');
await user.click(getByTestId('filters-button'));
await user.click(getByRole('button', { name: 'Filters' }));
// They should see the collections button indicating 1 option selected
expect(getByRole('combobox', { name: 'Collections' })).toHaveTextContent(
'1 collection selected'
);
// They should the categories button with no options selected
const categoriesButton = getByRole('combobox', { name: 'Categories' });
await user.click(categoriesButton);
const categoryOption = getByTestId('Custom fields-4');
await user.click(categoryOption);
await user.click(getByRole('combobox', { name: 'Categories' }));
await user.click(getByRole('option', { name: 'Custom fields (4)' }));
// Close the combobox
await user.keyboard('[Escape]');
// Close the popover
await user.keyboard('[Escape]');
// When the page reloads they should see a tag for the selected option
await waitForReload();
const madeByStrapiTag = getByRole('button', { name: 'Made by Strapi' });
const customFieldsTag = getByRole('button', { name: 'Custom fields' });
expect(madeByStrapiTag).toBeVisible();
expect(customFieldsTag).toBeVisible();
expect(getByRole('button', { name: 'Made by Strapi' })).toBeVisible();
expect(getByRole('button', { name: 'Custom fields' })).toBeVisible();
// They should see the correct number of results
const filterCards = getAllByTestId('npm-package-card');
expect(filterCards.length).toEqual(4);
@ -336,13 +279,13 @@ describe('Marketplace page - plugins tab', () => {
});
it('filters multiple collection options', async () => {
const { getByTestId, getByRole, getAllByTestId, getByText, queryByText, user } = setup();
const { getByRole, getAllByTestId, getByText, queryByText, user } = render();
await waitForReload();
await user.click(getByTestId('filters-button'));
await user.click(getByRole('button', { name: 'Filters' }));
await user.click(getByRole('combobox', { name: 'Collections' }));
await user.click(getByTestId('Made by Strapi-13'));
await user.click(getByRole('option', { name: 'Made by Strapi (13)' }));
// Close the combobox
await user.keyboard('[Escape]');
// Close the popover
@ -350,7 +293,7 @@ describe('Marketplace page - plugins tab', () => {
await waitForReload();
await user.click(getByTestId('filters-button'));
await user.click(getByRole('button', { name: 'Filters' }));
await user.click(getByRole('combobox', { name: `Collections` }));
await user.click(getByRole('option', { name: `Verified (29)` }));
// Close the combobox
@ -360,10 +303,8 @@ describe('Marketplace page - plugins tab', () => {
await waitForReload();
const madeByStrapiTag = getByRole('button', { name: 'Made by Strapi' });
const verifiedTag = getByRole('button', { name: 'Verified' });
expect(madeByStrapiTag).toBeVisible();
expect(verifiedTag).toBeVisible();
expect(getByRole('button', { name: 'Made by Strapi' })).toBeVisible();
expect(getByRole('button', { name: 'Verified' })).toBeVisible();
expect(getAllByTestId('npm-package-card').length).toEqual(3);
expect(getByText('Gatsby Preview')).toBeVisible();
expect(getByText('Config Sync')).toBeVisible();
@ -371,11 +312,11 @@ describe('Marketplace page - plugins tab', () => {
});
it('filters multiple category options', async () => {
const { getByTestId, getByRole, getAllByTestId, getByText, queryByText, user } = setup();
const { getByRole, getAllByTestId, getByText, queryByText, user } = render();
await waitForReload();
await user.click(getByTestId('filters-button'));
await user.click(getByRole('button', { name: 'Filters' }));
await user.click(getByRole('combobox', { name: 'Categories' }));
await user.click(getByRole('option', { name: `Custom fields (4)` }));
// Close the combobox
@ -385,7 +326,7 @@ describe('Marketplace page - plugins tab', () => {
await waitForReload();
await user.click(getByTestId('filters-button'));
await user.click(getByRole('button', { name: 'Filters' }));
await user.click(getByRole('combobox', { name: `Categories` }));
await user.click(getByRole('option', { name: `Monitoring (1)` }));
// Close the combobox
@ -395,10 +336,8 @@ describe('Marketplace page - plugins tab', () => {
await waitForReload();
const customFieldsTag = getByRole('button', { name: 'Custom fields' });
const monitoringTag = getByRole('button', { name: 'Monitoring' });
expect(customFieldsTag).toBeVisible();
expect(monitoringTag).toBeVisible();
expect(getByRole('button', { name: 'Custom fields' })).toBeVisible();
expect(getByRole('button', { name: 'Monitoring' })).toBeVisible();
expect(getAllByTestId('npm-package-card').length).toEqual(3);
expect(getByText('CKEditor 5 custom field')).toBeVisible();
expect(getByText('Sentry')).toBeVisible();
@ -406,18 +345,13 @@ describe('Marketplace page - plugins tab', () => {
});
it('removes a filter option tag', async () => {
const { getByTestId, getByRole, user } = setup();
const { getByRole, user } = render();
await waitForReload();
const filtersButton = getByTestId('filters-button');
await user.click(filtersButton);
const collectionsButton = getByRole('combobox', { name: 'Collections' });
await user.click(collectionsButton);
const option = getByTestId('Made by Strapi-13');
await user.click(option);
await user.click(getByRole('button', { name: 'Filters' }));
await user.click(getByRole('combobox', { name: 'Collections' }));
await user.click(getByRole('option', { name: 'Made by Strapi (13)' }));
// Close the combobox
await user.keyboard('[Escape]');
// Close the popover
@ -425,28 +359,22 @@ describe('Marketplace page - plugins tab', () => {
await waitForReload();
const optionTag = getByRole('button', { name: 'Made by Strapi' });
expect(optionTag).toBeVisible();
await user.click(optionTag);
expect(optionTag).not.toBeVisible();
// expect(history.location.search).toBe('?page=1');
});
it('only filters in the plugins tab', async () => {
const { getByTestId, getByRole, getAllByTestId, findAllByTestId, user } = setup();
expect(testLocation.search).toBe('?collections[0]=Made by Strapi&page=1');
await user.click(getByRole('button', { name: 'Made by Strapi' }));
await waitForReload();
const filtersButton = getByTestId('filters-button');
await user.click(filtersButton);
expect(testLocation.search).toBe('?page=1');
});
const collectionsButton = getByRole('combobox', { name: 'Collections' });
await user.click(collectionsButton);
it('only filters in the plugins tab', async () => {
const { getByRole, getAllByTestId, findAllByTestId, user } = render();
const option = getByTestId('Made by Strapi-13');
await user.click(option);
await waitForReload();
await user.click(getByRole('button', { name: 'Filters' }));
await user.click(getByRole('combobox', { name: 'Collections' }));
await user.click(getByRole('option', { name: 'Made by Strapi (13)' }));
// Close the combobox
await user.keyboard('[Escape]');
// Close the popover
@ -465,33 +393,30 @@ describe('Marketplace page - plugins tab', () => {
});
it('shows the correct options on sort select', async () => {
const { getByRole, user } = setup();
const { getByRole, user } = render();
await waitForReload();
const sortButton = getByRole('combobox', { name: /Sort by/i });
await user.click(sortButton);
await user.click(getByRole('combobox', { name: /Sort by/i }));
expect(getByRole('option', { name: 'Alphabetical order' })).toBeVisible();
expect(getByRole('option', { name: 'Newest' })).toBeVisible();
});
it('changes the url on sort option select', async () => {
const { getByRole, user } = setup();
const { getByRole, user } = render();
await waitForReload();
const sortButton = getByRole('combobox', { name: /Sort by/i });
await user.click(sortButton);
await user.click(getByRole('combobox', { name: /Sort by/i }));
await user.click(getByRole('option', { name: 'Newest' }));
// expect(history.location.search).toEqual('?sort=submissionDate:desc&page=1');
await waitForReload();
expect(testLocation.search).toEqual('?sort=submissionDate:desc&page=1');
});
it('shows github stars and weekly downloads count for each plugin', async () => {
const { getAllByTestId } = setup();
const { getAllByTestId } = render();
await waitForReload();
@ -512,15 +437,13 @@ describe('Marketplace page - plugins tab', () => {
});
it('paginates the results', async () => {
const { getByLabelText, getAllByText, getByText, user } = setup();
const { getByLabelText, getAllByText, getByText, user } = render();
await waitForReload();
// Should have pagination section with 4 pages
const pagination = getByLabelText(/pagination/i);
expect(pagination).toBeVisible();
const pageButtons = getAllByText(/go to page \d+/i).map((el) => el.closest('a'));
expect(pageButtons.length).toBe(4);
expect(getByLabelText(/pagination/i)).toBeVisible();
expect(getAllByText(/go to page \d+/i).map((el) => el.closest('a'))).toHaveLength(4);
// Can't go to previous page since there isn't one
expect(getByText(/go to previous page/i).closest('a')).toHaveAttribute('aria-disabled', 'true');
@ -528,16 +451,16 @@ describe('Marketplace page - plugins tab', () => {
// Can go to next page
await user.click(getByText(/go to next page/i).closest('a'));
await waitForReload();
// expect(history.location.search).toBe('?page=2');
expect(testLocation.search).toBe('?page=2');
// Can go to previous page
await user.click(getByText(/go to previous page/i).closest('a'));
await waitForReload();
// expect(history.location.search).toBe('?page=1');
expect(testLocation.search).toBe('?page=1');
// Can go to specific page
await user.click(getByText(/go to page 3/i).closest('a'));
await waitForReload();
// expect(history.location.search).toBe('?page=3');
expect(testLocation.search).toBe('?page=3');
});
});

View File

@ -1,32 +1,27 @@
import React from 'react';
import { fixtures } from '@strapi/admin-test-utils';
import { lightTheme, ThemeProvider } from '@strapi/design-system';
import { TrackingProvider } from '@strapi/helper-plugin';
import { render, screen, within } from '@testing-library/react';
import { NotificationsProvider } from '@strapi/helper-plugin';
import { render as renderRTL, screen, waitFor, within } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { createMemoryHistory } from 'history';
import { IntlProvider } from 'react-intl';
import { QueryClient, QueryClientProvider } from 'react-query';
import { Provider } from 'react-redux';
import { Router } from 'react-router-dom';
import { createStore } from 'redux';
import { MemoryRouter, Route } from 'react-router-dom';
import MarketPlacePage from '../index';
import { MarketPlacePage } from '../index';
import server from './server';
// Increase the jest timeout to accommodate long running tests
jest.setTimeout(50000);
const toggleNotification = jest.fn();
jest.mock('../../../hooks/useNavigatorOnLine', () => jest.fn(() => true));
/**
* MOCKS
*/
jest.mock('../../../hooks/useDebounce', () => (value) => value);
jest.mock('../../../hooks/useNavigatorOnLine', () => jest.fn(() => true));
jest.mock('@strapi/helper-plugin', () => ({
...jest.requireActual('@strapi/helper-plugin'),
useNotification: jest.fn(() => {
return toggleNotification;
}),
CheckPagePermissions: ({ children }) => children,
useAppInfo: jest.fn(() => ({
autoReload: true,
dependencies: {
@ -37,12 +32,11 @@ jest.mock('@strapi/helper-plugin', () => ({
})),
}));
const setup = (props) => ({
...render(<MarketPlacePage {...props} />, {
let testLocation = null;
const render = (props) => ({
...renderRTL(<MarketPlacePage {...props} />, {
wrapper({ children }) {
const history = createMemoryHistory({
initialEntries: ['/?npmPackageType=provider&sort=name:asc'],
});
const client = new QueryClient({
defaultOptions: {
queries: {
@ -52,21 +46,25 @@ const setup = (props) => ({
});
return (
<Provider
store={createStore((state) => state, {
admin_app: { permissions: fixtures.permissions.app },
})}
>
<QueryClientProvider client={client}>
<TrackingProvider>
<IntlProvider locale="en" messages={{}} textComponent="span">
<ThemeProvider theme={lightTheme}>
<Router history={history}>{children}</Router>
</ThemeProvider>
</IntlProvider>
</TrackingProvider>
</QueryClientProvider>
</Provider>
<QueryClientProvider client={client}>
<IntlProvider locale="en" messages={{}} textComponent="span">
<ThemeProvider theme={lightTheme}>
<NotificationsProvider>
<MemoryRouter initialEntries={['/?npmPackageType=provider&sort=name:asc']}>
{children}
<Route
path="*"
render={({ location }) => {
testLocation = location;
return null;
}}
/>
</MemoryRouter>
</NotificationsProvider>
</ThemeProvider>
</IntlProvider>
</QueryClientProvider>
);
},
}),
@ -75,7 +73,7 @@ const setup = (props) => ({
});
const waitForReload = async () => {
await screen.findByTestId('marketplace-results');
await waitFor(() => expect(screen.queryByText('Loading content...')).not.toBeInTheDocument());
};
describe('Marketplace page - providers tab', () => {
@ -88,7 +86,7 @@ describe('Marketplace page - providers tab', () => {
afterAll(() => server.close());
it('renders the providers tab', async () => {
const { getByText, getByRole, queryByText } = setup();
const { getByText, getByRole, queryByText } = render();
await waitForReload();
@ -106,7 +104,7 @@ describe('Marketplace page - providers tab', () => {
});
it('should return providers search results matching the query', async () => {
const { getByText, getByPlaceholderText, user, queryByText } = setup();
const { getByText, getByPlaceholderText, user, queryByText } = render();
await waitForReload();
@ -125,7 +123,7 @@ describe('Marketplace page - providers tab', () => {
});
it('should return empty providers search results given a bad query', async () => {
const { getByText, getByPlaceholderText, user } = setup();
const { getByText, getByPlaceholderText, user } = render();
await waitForReload();
@ -139,7 +137,7 @@ describe('Marketplace page - providers tab', () => {
});
it('shows the installed text for installed providers', async () => {
const { getByRole, user } = setup();
const { getByRole, user } = render();
await waitForReload();
@ -163,11 +161,11 @@ describe('Marketplace page - providers tab', () => {
});
it('shows providers filters popover', async () => {
const { getByRole, getByTestId, user } = setup();
const { getByRole, user } = render();
await waitForReload();
const filtersButton = getByTestId('filters-button');
const filtersButton = getByRole('button', { name: 'Filters' });
// Only show collections filters on providers
const providersTab = getByRole('tab', { name: /providers/i });
@ -178,42 +176,34 @@ describe('Marketplace page - providers tab', () => {
});
it('shows the collections filter options', async () => {
const { getByRole, getByTestId, user } = setup();
const { getByRole, user } = render();
await waitForReload();
const filtersButton = getByTestId('filters-button');
const filtersButton = getByRole('button', { name: 'Filters' });
await user.click(filtersButton);
const collectionsButton = getByRole('combobox', { name: 'Collections' });
await user.click(collectionsButton);
const mockedServerCollections = {
'Made by official partners': 0,
'Made by Strapi': 6,
'Made by the community': 2,
Verified: 6,
};
Object.entries(mockedServerCollections).forEach(([collectionName, count]) => {
const option = screen.getByTestId(`${collectionName}-${count}`);
expect(option).toBeVisible();
[
'Made by official partners (0)',
'Made by Strapi (6)',
'Made by the community (2)',
'Verified (6)',
].forEach((name) => {
expect(getByRole('option', { name })).toBeVisible();
});
});
it('filters a collection option', async () => {
const { getAllByTestId, getByRole, getByTestId, getByText, queryByText, user } = setup();
const { getAllByTestId, getByRole, getByText, queryByText, user } = render();
await waitForReload();
const filtersButton = getByTestId('filters-button');
await user.click(filtersButton);
const collectionsButton = getByRole('combobox', { name: 'Collections' });
await user.click(collectionsButton);
const option = getByTestId('Made by Strapi-6');
await user.click(option);
await user.click(getByRole('button', { name: 'Filters' }));
await user.click(getByRole('combobox', { name: 'Collections' }));
await user.click(getByRole('option', { name: 'Made by Strapi (6)' }));
// Close the combobox
await user.keyboard('[Escape]');
// Close the popover
@ -221,8 +211,7 @@ describe('Marketplace page - providers tab', () => {
await waitForReload();
const optionTag = getByRole('button', { name: 'Made by Strapi' });
expect(optionTag).toBeVisible();
expect(getByRole('button', { name: 'Made by Strapi' })).toBeVisible();
const collectionCards = getAllByTestId('npm-package-card');
expect(collectionCards.length).toEqual(2);
@ -234,13 +223,13 @@ describe('Marketplace page - providers tab', () => {
});
it('filters multiple collection options', async () => {
const { getAllByTestId, getByRole, getByTestId, getByText, queryByText, user } = setup();
const { getAllByTestId, getByRole, getByText, queryByText, user } = render();
await waitForReload();
await user.click(getByTestId('filters-button'));
await user.click(getByRole('button', { name: 'Filters' }));
await user.click(getByRole('combobox', { name: 'Collections' }));
await user.click(getByTestId('Made by Strapi-6'));
await user.click(getByRole('option', { name: 'Made by Strapi (6)' }));
// Close the combobox
await user.keyboard('[Escape]');
// Close the popover
@ -248,7 +237,7 @@ describe('Marketplace page - providers tab', () => {
await waitForReload();
await user.click(getByTestId('filters-button'));
await user.click(getByRole('button', { name: 'Filters' }));
await user.click(getByRole('combobox', { name: `Collections` }));
await user.click(getByRole('option', { name: `Verified (6)` }));
// Close the combobox
@ -268,46 +257,36 @@ describe('Marketplace page - providers tab', () => {
});
it('removes a filter option tag', async () => {
const { getByRole, getByTestId, user } = setup();
const { getByRole, user } = render();
await waitForReload();
const filtersButton = getByTestId('filters-button');
await user.click(filtersButton);
await user.click(getByRole('button', { name: 'Filters' }));
await user.click(getByRole('combobox', { name: 'Collections' }));
const collectionsButton = getByRole('combobox', { name: 'Collections' });
await user.click(collectionsButton);
await user.click(getByRole('option', { name: 'Made by Strapi (6)' }));
const option = getByTestId('Made by Strapi-6');
await user.click(option);
// Close the combobox
await user.keyboard('[Escape]');
// Close the popover
await user.keyboard('[Escape]');
await waitForReload();
const optionTag = getByRole('button', { name: 'Made by Strapi' });
expect(optionTag).toBeVisible();
await user.click(getByRole('button', { name: 'Made by Strapi' }));
await user.click(optionTag);
expect(optionTag).not.toBeVisible();
// expect(history.location.search).toBe('?npmPackageType=provider&sort=name:asc&page=1');
await waitForReload();
expect(testLocation.search).toBe('?npmPackageType=provider&sort=name:asc&page=1');
});
it('only filters in the providers tab', async () => {
const { getAllByTestId, getByRole, getByTestId, findAllByTestId, findByText, user } = setup();
const { getAllByTestId, getByRole, findAllByTestId, findByText, user } = render();
await waitForReload();
const filtersButton = getByTestId('filters-button');
await user.click(filtersButton);
const collectionsButton = getByRole('combobox', { name: 'Collections' });
await user.click(collectionsButton);
const option = getByTestId('Made by Strapi-6');
await user.click(option);
await user.click(getByRole('button', { name: 'Filters' }));
await user.click(getByRole('combobox', { name: 'Collections' }));
await user.click(getByRole('option', { name: 'Made by Strapi (6)' }));
// Close the combobox
await user.keyboard('[Escape]');
// Close the popover
@ -326,7 +305,7 @@ describe('Marketplace page - providers tab', () => {
});
it('shows the correct options on sort select', async () => {
const { getByRole, user } = setup();
const { getByRole, user } = render();
await waitForReload();
@ -341,7 +320,7 @@ describe('Marketplace page - providers tab', () => {
});
it('changes the url on sort option select', async () => {
const { getByRole, user } = setup();
const { getByRole, user } = render();
await waitForReload();
@ -351,18 +330,17 @@ describe('Marketplace page - providers tab', () => {
const newestOption = getByRole('option', { name: 'Newest' });
await user.click(newestOption);
// expect(history.location.search).toEqual(
// '?npmPackageType=provider&sort=submissionDate:desc&page=1'
// );
await waitForReload();
expect(testLocation.search).toEqual('?npmPackageType=provider&sort=submissionDate:desc&page=1');
});
it('shows github stars and weekly downloads count for each provider', async () => {
const { getByRole, user } = setup();
const { getByRole, user } = render();
await waitForReload();
const providersTab = getByRole('tab', { name: /providers/i });
await user.click(providersTab);
await user.click(getByRole('tab', { name: /providers/i }));
const cloudinaryCard = screen
.getAllByTestId('npm-package-card')
@ -380,7 +358,7 @@ describe('Marketplace page - providers tab', () => {
});
it('paginates the results', async () => {
const { getByText, getByLabelText, getAllByText, user } = setup();
const { getByText, getByLabelText, getAllByText, user } = render();
await waitForReload();
@ -396,16 +374,16 @@ describe('Marketplace page - providers tab', () => {
// Can go to next page
await user.click(getByText(/go to next page/i).closest('a'));
await waitForReload();
// expect(history.location.search).toBe('?npmPackageType=provider&sort=name:asc&page=2');
expect(testLocation.search).toBe('?npmPackageType=provider&sort=name:asc&page=2');
// Can go to previous page
await user.click(getByText(/go to previous page/i).closest('a'));
await waitForReload();
// expect(history.location.search).toBe('?npmPackageType=provider&sort=name:asc&page=1');
expect(testLocation.search).toBe('?npmPackageType=provider&sort=name:asc&page=1');
// Can go to specific page
await user.click(getByText(/go to page 3/i).closest('a'));
await waitForReload();
// expect(history.location.search).toBe('?npmPackageType=provider&sort=name:asc&page=3');
expect(testLocation.search).toBe('?npmPackageType=provider&sort=name:asc&page=3');
});
});