Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion jest.config.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,15 @@
const { createConfig } = require('@openedx/frontend-build');

const { TestEnvironment } = require('jest-environment-jsdom');
module.exports = createConfig('jest', {
setupFiles: ['<rootDir>/src/setupTest.js'],
testEnvironment: 'jsdom',



setupFilesAfterEnv: ['@testing-library/jest-dom'],



collectCoverage: true,
collectCoverageFrom: ['src/**/*.{js,jsx}'],
coveragePathIgnorePatterns: [
Expand Down
10,839 changes: 5,927 additions & 4,912 deletions package-lock.json

Large diffs are not rendered by default.

32 changes: 15 additions & 17 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
"lint:fix": "fedx-scripts eslint --fix --ext .js --ext .jsx .",
"start": "fedx-scripts webpack-dev-server --progress",
"debug-test": "node --inspect-brk node_modules/.bin/jest --coverage --runInBand",
"test": "TZ=UTC fedx-scripts jest --coverage --maxWorkers=2",
"test": "fedx-scripts jest --coverage --maxWorkers=2",
"test:watch": "npm run test -- --watch",
"snapshot": "fedx-scripts jest --updateSnapshot"
},
Expand All @@ -31,15 +31,15 @@
},
"dependencies": {
"@edx/brand": "npm:@openedx/brand-openedx@^1.2.2",
"@edx/frontend-enterprise-utils": "9.1.0",
"@edx/frontend-platform": "^8.3.2",
"@edx/frontend-enterprise-utils": "^10.0.0",
"@edx/frontend-platform": "^8.5.0",
"@edx/openedx-atlas": "^0.6.0",
"@fortawesome/fontawesome-svg-core": "1.2.32",
"@fortawesome/free-brands-svg-icons": "5.15.1",
"@fortawesome/free-regular-svg-icons": "5.15.1",
"@fortawesome/free-solid-svg-icons": "5.15.1",
"@fortawesome/react-fontawesome": "^0.1.14",
"@openedx/paragon": "^23.4.2",
"@openedx/paragon": "^22.17.0",
"axios": "^1.7.7",
"babel-polyfill": "6.26.0",
"classnames": "2.2.6",
Expand All @@ -48,36 +48,34 @@
"lodash.snakecase": "4.1.1",
"moment": "2.29.4",
"prop-types": "15.7.2",
"react": "17.0.2",
"react-dom": "17.0.2",
"react-helmet": "^6.1.0",
"react-redux": "^7.2.9",
"react": "18.3.1",
"react-dom": "18.3.1",
"react-helmet-async": "^2.0.4",
"react-redux": "^8.1.3",
"react-responsive": "^8.2.0",
"react-router": "6.15.0",
"react-router-dom": "6.15.0",
"react-table": "^7.6.3",
"react-transition-group": "4.4.1",
"redux": "4.0.5",
"redux": "^4.2.1",
"use-context-selector": "1.4.1",
"uuid": "9.0.0"
},
"devDependencies": {
"@edx/browserslist-config": "^1.1.0",
"@edx/reactifex": "^1.0.3",
"@openedx/frontend-build": "^14.3.3",
"@testing-library/dom": "^9.3.4",
"@testing-library/jest-dom": "^5.17.0",
"@testing-library/react": "12.1.4",
"@testing-library/react-hooks": "^8.0.1",
"@emotion/jest": "^11.13.0",
"@openedx/frontend-build": "^14.6.0",
"@testing-library/jest-dom": "^6.6.4",
"@testing-library/react": "^14.3.1",
"@testing-library/user-event": "^14.5.2",
"@types/react-table": "^7.7.2",
"@wojtekmaj/enzyme-adapter-react-17": "^0.8.0",
"axios-mock-adapter": "^1.19.0",
"enzyme": "3.11.0",
"glob": "7.1.6",
"jest": "^29.7.0",
"jest-emotion": "^11.0.0",
"jest-environment-jsdom": "^29.7.0",
"react-test-renderer": "^17.0.2",
"react-test-renderer": "^18.3.1",
"reactifex": "1.1.1"
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { renderHook } from '@testing-library/react-hooks';
import { waitFor } from '@testing-library/react';
import { renderHook, waitFor } from '@testing-library/react';

import LmsApiService from '../../../../../data/services/EnterpriseApiService';
import useCustomerUsersTableData from '../useCustomerUsersTableData';
Expand All @@ -14,9 +13,12 @@ describe('useCustomerUsersTableData', () => {
};
const { result } = renderHook(() => useCustomerUsersTableData(args));
const { enterpriseUsersTableData } = result.current;
expect(enterpriseUsersTableData).toEqual({ itemCount: 0, pageCount: 0, results: [] });
expect(enterpriseUsersTableData).toEqual({
itemCount: 0,
pageCount: 0,
results: [],
});

// shouldn't fetch because its only 2 characters
const searchArgs1 = {
filters: [{ id: 'details', value: 'vi' }],
sortBy: [{}],
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
/* eslint-disable react/prop-types */
import PropTypes from 'prop-types';
import { renderWithRouter } from '@edx/frontend-enterprise-utils';
import {
fireEvent, screen, waitFor, act,
} from '@testing-library/react';
import { fireEvent, screen, waitFor } from '@testing-library/react';
import ProvisioningFormCustomCatalogDropdown from '../ProvisioningFormCustomCatalogDropdown';
import { initialStateValue, ProvisioningContext } from '../../../../testData/Provisioning';
import PROVISIONING_PAGE_TEXT from '../../../data/constants';
Expand All @@ -22,126 +20,167 @@ jest.mock('../../../../../data/services/EnterpriseApiService', () => ({
fetchEnterpriseCustomerCatalogs: jest.fn(() => Promise.resolve(mockData)),
}));

// Patch frontend-platform to serve a custom version of PREDEFINED_CATALOG_QUERIES.
jest.mock('@edx/frontend-platform', () => ({
...jest.requireActual('@edx/frontend-platform'),
getConfig: jest.fn(() => ({
PREDEFINED_CATALOG_QUERIES: MOCK_PREDEFINED_CATALOG_QUERIES,
})),
}));

const ProvisioningFormCustomCatalogDropdownWrapper = ({
value = {
const ProvisioningFormCustomCatalogDropdownWrapper = ({ value }) => (
<ProvisioningContext value={value}>
<ProvisioningFormCustomCatalogDropdown />
</ProvisioningContext>
);

ProvisioningFormCustomCatalogDropdownWrapper.propTypes = {
value: PropTypes.shape({
existingEnterpriseCatalogs: PropTypes.shape({
data: PropTypes.arrayOf(
PropTypes.shape({
title: PropTypes.string,
enterpriseCatalogQuery: PropTypes.string,
uuid: PropTypes.string,
}),
),
isLoading: PropTypes.bool,
}),
isEditMode: PropTypes.bool,
formData: PropTypes.shape({
policies: PropTypes.arrayOf(
PropTypes.shape({
oldCustomCatalog: PropTypes.bool,
oldCatalogTitle: PropTypes.string,
customCatalog: PropTypes.bool,
catalogTitle: PropTypes.string,
catalogUuid: PropTypes.string,
}),
),
}),
}),
};

ProvisioningFormCustomCatalogDropdownWrapper.defaultProps = {
value: {
...initialStateValue,
existingEnterpriseCatalogs: {
data: sampleCatalogs,
isLoading: false,
},
},
}) => (
<ProvisioningContext value={value}>
<ProvisioningFormCustomCatalogDropdown />
</ProvisioningContext>
);
};

describe('ProvisioningFormCustomCatalogDropdown', () => {
beforeEach(() => {
jest.clearAllMocks();
});
it('renders the custom catalog dropdown', () => {
renderWithRouter(
<ProvisioningFormCustomCatalogDropdownWrapper />,
);

it('renders the custom catalog dropdown', () => {
renderWithRouter(<ProvisioningFormCustomCatalogDropdownWrapper />);
expect(screen.getByText(CUSTOM_CATALOG.OPTIONS.enterpriseCatalog.title)).toBeTruthy();
expect(screen.getByText(CUSTOM_CATALOG.OPTIONS.enterpriseCatalog.subtitle)).toBeTruthy();
});

it('renders the custom catalog dropdown options', () => {
renderWithRouter(
<ProvisioningFormCustomCatalogDropdownWrapper />,
);
renderWithRouter(<ProvisioningFormCustomCatalogDropdownWrapper />);

const autoSuggestInput = screen.getByTestId('custom-catalog-dropdown-autosuggest');
const autoSuggestButton = screen.getAllByRole('button')[0];
// open dropdown
fireEvent.click(autoSuggestButton);
// Check values are populating

const { queryIdToQueryType } = getPredefinedCatalogQueryMappings();
sampleCatalogs.forEach(({ title, enterpriseCatalogQuery }) => {
if (!(enterpriseCatalogQuery in queryIdToQueryType)) {
expect(screen.getByText(title, { exact: false })).toBeTruthy();
}
});

const autoSuggestDropdownButtons = screen.getAllByRole('button');
const filteredDropdowns = autoSuggestDropdownButtons.filter((element) => element.textContent.includes('73cb6181'));
// close dropdown

fireEvent.click(autoSuggestButton);

for (let i = 0; i < filteredDropdowns.length; i++) {
fireEvent.click(autoSuggestButton);
fireEvent.click(filteredDropdowns[i]);
waitFor(() => expect(autoSuggestInput.getAttribute('value')).toContain(filteredDropdowns[i].textContent));
waitFor(() => {
expect(autoSuggestInput).toHaveValue(expect.stringContaining(filteredDropdowns[i].textContent));
});
}
});

it('renders correct dropdown when catalogs list is still loading', () => {
LmsApiService.fetchEnterpriseCustomerCatalogs.mockResolvedValueOnce({ data: { results: [] } });
renderWithRouter(
<ProvisioningFormCustomCatalogDropdownWrapper
value={initialStateValue}
/>,
);

renderWithRouter(<ProvisioningFormCustomCatalogDropdownWrapper value={initialStateValue} />);
const autoSuggestButton = screen.getAllByRole('button')[0];
fireEvent.click(autoSuggestButton);
expect(screen.getByText('Loading...')).toBeTruthy();
});

it('renders correct dropdown when the selected customer has no custom catalogs', () => {
LmsApiService.fetchEnterpriseCustomerCatalogs.mockResolvedValueOnce({ data: { results: [] } });
renderWithRouter(
<ProvisioningFormCustomCatalogDropdownWrapper
value={{
...initialStateValue,
existingEnterpriseCatalogs: {
data: [], // This customer has no custom/unique/curated catalogs!
data: [],
isLoading: false,
},
}}
/>,
);

const autoSuggestButton = screen.getAllByRole('button')[0];
fireEvent.click(autoSuggestButton);
expect(screen.getByText('No catalogs found for customer.')).toBeTruthy();
});

it('renders default catalog query title when isEditMode is true', async () => {
LmsApiService.fetchEnterpriseCustomerCatalogs.mockResolvedValue({ data: { results: sampleCatalogs } });
const customSampleCatalogs = [
...sampleCatalogs,
{
title: 'Snoopy gang',
enterpriseCatalogQuery: 'custom-query',
uuid: '4ev3r',
},
];

LmsApiService.fetchEnterpriseCustomerCatalogs.mockResolvedValue({
data: { results: customSampleCatalogs },
});

renderWithRouter(
<ProvisioningFormCustomCatalogDropdownWrapper
value={{
...initialStateValue,
isEditMode: true,
existingEnterpriseCatalogs: {
data: sampleCatalogs,
data: customSampleCatalogs,
isLoading: false,
},
formData: {
policies: [{
oldCustomCatalog: true,
oldCatalogTitle: 'Snoopy gang',
customCatalog: true,
catalogTitle: 'Snoopy gang',
catalogUuid: '4ev3r',
}],
policies: [
{
oldCustomCatalog: true,
oldCatalogTitle: 'Snoopy gang',
customCatalog: true,
catalogTitle: 'Snoopy gang',
catalogUuid: '4ev3r',
},
],
},
}}
/>,
);
act(async () => {
expect(await screen.findByRole('list', {
name: 'Enterprise Catalog',
}).value).toBe('Snoopy gang --- 4ev3r');
});

const input = await screen.findByTestId('custom-catalog-dropdown-autosuggest');
const toggleButton = screen.getAllByRole('button')[0];
fireEvent.click(toggleButton);
const option = await screen.findByText(/Snoopy gang --- 4ev3r/i);
fireEvent.click(option);
expect(input).toHaveValue('Snoopy gang --- 4ev3r');
});

it('renders empty string title when isEditMode is false', async () => {
renderWithRouter(
<ProvisioningFormCustomCatalogDropdownWrapper
Expand All @@ -153,19 +192,18 @@ describe('ProvisioningFormCustomCatalogDropdown', () => {
isLoading: false,
},
formData: {
policies: [{
customCatalog: true,
catalogTitle: 'Snoopy gang',
catalogUuid: '4ev3r',
}],
policies: [
{
customCatalog: true,
catalogTitle: 'Snoopy gang',
catalogUuid: '4ev3r',
},
],
},
}}
/>,
);
act(async () => {
expect(await screen.findByRole('list', {
name: 'Enterprise Catalog',
}).value).toBe('');
});
const input = await screen.findByTestId('custom-catalog-dropdown-autosuggest');
expect(input).toHaveValue('');
});
});
Loading