Skip to content

test: deprecate react-unit-test-utils part-4 #462

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
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
33 changes: 17 additions & 16 deletions src/containers/DemoWarning/DemoWarning.test.jsx
Original file line number Diff line number Diff line change
@@ -1,33 +1,34 @@
import React from 'react';
import { shallow } from '@edx/react-unit-test-utils';

import { render } from '@testing-library/react';
import { selectors } from 'data/redux';
import { DemoWarning, mapStateToProps } from '.';

jest.unmock('@openedx/paragon');
jest.unmock('react');

jest.mock('data/redux', () => ({
selectors: {
app: { isEnabled: (args) => ({ isEnabled: args }) },
},
}));

let el;

describe('DemoWarning component', () => {
describe('snapshots', () => {
test('does not render if disabled flag is missing', () => {
el = shallow(<DemoWarning hide />);
expect(el.snapshot).toMatchSnapshot();
expect(el.isEmptyRender()).toEqual(true);
describe('behavior', () => {
it('does not render when hide prop is true', () => {
const { container } = render(<DemoWarning hide />);
expect(container.firstChild).toBeNull();
});
test('snapshot: disabled flag is present', () => {
el = shallow(<DemoWarning hide={false} />);
expect(el.snapshot).toMatchSnapshot();
expect(el.isEmptyRender()).toEqual(false);

it('renders alert with warning message when hide prop is false', () => {
const { getByRole } = render(<DemoWarning hide={false} />);
const alert = getByRole('alert');
expect(alert).toBeInTheDocument();
expect(alert).toHaveClass('alert-warning');
});
});

describe('mapStateToProps', () => {
const testState = { some: 'test-state' };
test('hide is forwarded from app.isEnabled', () => {
it('maps hide prop from app.isEnabled selector', () => {
const testState = { some: 'test-state' };
expect(mapStateToProps(testState).hide).toEqual(
selectors.app.isEnabled(testState),
);
Expand Down
25 changes: 0 additions & 25 deletions src/containers/DemoWarning/__snapshots__/DemoWarning.test.jsx.snap

This file was deleted.

59 changes: 37 additions & 22 deletions src/containers/ListView/EmptySubmission.test.jsx
Original file line number Diff line number Diff line change
@@ -1,33 +1,48 @@
import React from 'react';
import { shallow } from '@edx/react-unit-test-utils';

import { Hyperlink } from '@openedx/paragon';

import { render } from '@testing-library/react';
import { IntlProvider } from '@edx/frontend-platform/i18n';
import urls from 'data/services/lms/urls';

import EmptySubmission from './EmptySubmission';

jest.unmock('@openedx/paragon');
jest.unmock('react');
jest.unmock('@edx/frontend-platform/i18n');

jest.mock('data/services/lms/urls', () => ({
openResponse: (courseId) => `openResponseUrl(${courseId})`,
}));

jest.mock('./assets/emptyState.svg', () => './assets/emptyState.svg');

let el;
jest.mock('./assets/empty-state.svg', () => './assets/empty-state.svg');

describe('EmptySubmission component', () => {
describe('component', () => {
const props = { courseId: 'test-course-id' };
beforeEach(() => {
el = shallow(<EmptySubmission {...props} />);
});
test('snapshot', () => {
expect(el.snapshot).toMatchSnapshot();
});
test('openResponse destination', () => {
expect(
el.instance.findByType(Hyperlink)[0].props.destination,
).toEqual(urls.openResponse(props.courseId));
});
const props = { courseId: 'test-course-id' };

const renderWithIntl = (component) => render(
<IntlProvider locale="en" messages={{}}>
{component}
</IntlProvider>,
);

it('renders the empty state image with correct alt text', () => {
const { getByAltText } = renderWithIntl(<EmptySubmission {...props} />);
expect(getByAltText('empty state')).toBeInTheDocument();
});

it('renders the no results found title message', () => {
const { getByText } = renderWithIntl(<EmptySubmission {...props} />);
expect(getByText('Nothing here yet')).toBeInTheDocument();
});

it('renders hyperlink with correct destination URL', () => {
const { container } = renderWithIntl(<EmptySubmission {...props} />);
const hyperlink = container.querySelector('a');
expect(hyperlink).toHaveAttribute(
'href',
urls.openResponse(props.courseId),
);
});

it('renders the back to responses button', () => {
const { getByText } = renderWithIntl(<EmptySubmission {...props} />);
expect(getByText('Back to all open responses')).toBeInTheDocument();
});
});
161 changes: 96 additions & 65 deletions src/containers/ListView/FilterStatusComponent.test.jsx
Original file line number Diff line number Diff line change
@@ -1,54 +1,21 @@
import React from 'react';
import { shallow } from '@edx/react-unit-test-utils';
import PropTypes from 'prop-types';
import { render } from '@testing-library/react';
import { DataTableContext } from '@openedx/paragon';

import * as module from './FilterStatusComponent';

const fieldIds = [
'field-id-0',
'field-id-1',
'field-id-2',
'field-id-3',
];
jest.unmock('@openedx/paragon');
jest.unmock('react');

const fieldIds = ['field-id-0', 'field-id-1', 'field-id-2', 'field-id-3'];
const filterOrder = [1, 0, 3, 2];
const filters = filterOrder.map(v => ({ id: fieldIds[v] }));
const headers = [0, 1, 2, 3].map(v => ({
const filters = filterOrder.map((v) => ({ id: fieldIds[v] }));
const headers = [0, 1, 2, 3].map((v) => ({
id: fieldIds[v],
Header: `HeaDer-${v}`,
}));

describe('FilterStatusComponent hooks', () => {
const context = { headers, state: { filters } };
const mockTableContext = (newContext) => {
React.useContext.mockReturnValueOnce(newContext);
};
beforeEach(() => {
context.setAllFilters = jest.fn();
});
it('returns empty dict if setAllFilters or state.filters is falsey', () => {
mockTableContext({ ...context, setAllFilters: null });
expect(module.filterHooks()).toEqual({});
mockTableContext({ ...context, state: { filters: null } });
expect(module.filterHooks()).toEqual({});
});
describe('clearFilters', () => {
it('uses React.useCallback to clear filters, only once', () => {
mockTableContext(context);
const { cb, prereqs } = module.filterHooks().clearFilters.useCallback;
expect(prereqs).toEqual([context.setAllFilters]);
expect(context.setAllFilters).not.toHaveBeenCalled();
cb();
expect(context.setAllFilters).toHaveBeenCalledWith([]);
});
});
describe('filterNames', () => {
it('returns list of Header values by filter order', () => {
mockTableContext(context);
expect(module.filterHooks().filterNames).toEqual(
filterOrder.map(v => headers[v].Header),
);
});
});
});
describe('FilterStatusComponent component', () => {
const props = {
className: 'css-class-name',
Expand All @@ -58,34 +25,98 @@ describe('FilterStatusComponent component', () => {
buttonClassName: 'css-class-name-for-button',
showFilteredFields: true,
};
const hookProps = {
clearFilters: jest.fn().mockName('hookProps.clearFilters'),
filterNames: ['filter-name-0', 'filter-name-1'],
};
const { FilterStatusComponent } = module;
const mockHooks = (value) => {
jest.spyOn(module, 'filterHooks').mockReturnValueOnce(value);

const renderWithContext = (contextValue, componentProps = props) => {
const TestWrapper = ({ children }) => (
<DataTableContext.Provider value={contextValue}>
{children}
</DataTableContext.Provider>
);
TestWrapper.propTypes = {
children: PropTypes.node,
};
return render(
<TestWrapper>
<FilterStatusComponent {...componentProps} />
</TestWrapper>,
);
};
describe('snapshot', () => {
describe('with filters', () => {
test('showFilteredFields', () => {
mockHooks(hookProps);
const el = shallow(<FilterStatusComponent {...props} />);
expect(el.snapshot).toMatchSnapshot();

beforeEach(() => {
jest.clearAllMocks();
});

describe('behavior', () => {
it('does not render when there are no filters', () => {
const contextValue = {
headers,
state: { filters: null },
setAllFilters: jest.fn(),
};
const { container } = renderWithContext(contextValue);
expect(container.firstChild).toBeNull();
});

it('does not render when setAllFilters is not available', () => {
const contextValue = { headers, state: { filters }, setAllFilters: null };
const { container } = renderWithContext(contextValue);
expect(container.firstChild).toBeNull();
});

it('renders clear filters button with correct text when filters exist', () => {
const contextValue = {
headers,
state: { filters },
setAllFilters: jest.fn(),
};
const { getByText } = renderWithContext(contextValue);
expect(getByText(props.clearFiltersText)).toBeInTheDocument();
});

it('displays filtered field names when showFilteredFields is true', () => {
const contextValue = {
headers,
state: { filters },
setAllFilters: jest.fn(),
};
const { getByText } = renderWithContext(contextValue);
const expectedFilterNames = filterOrder.map((v) => headers[v].Header);
expectedFilterNames.forEach((name) => {
expect(getByText(name, { exact: false })).toBeInTheDocument();
});
test('showFilteredFields=false - hide filterTexts', () => {
mockHooks(hookProps);
const el = shallow(
<FilterStatusComponent {...props} showFilteredFields={false} />,
);
expect(el.snapshot).toMatchSnapshot();
});

it('does not display filtered field names when showFilteredFields is false', () => {
const contextValue = {
headers,
state: { filters },
setAllFilters: jest.fn(),
};
const { queryByText } = renderWithContext(contextValue, {
...props,
showFilteredFields: false,
});
expect(queryByText(/Filtered by/)).not.toBeInTheDocument();
});
test('without filters', () => {
mockHooks({});
const el = shallow(<FilterStatusComponent {...props} />);
expect(el.snapshot).toMatchSnapshot();
expect(el.isEmptyRender()).toEqual(true);

it('applies correct CSS classes to the component', () => {
const contextValue = {
headers,
state: { filters },
setAllFilters: jest.fn(),
};
const { container } = renderWithContext(contextValue);
expect(container.firstChild).toHaveClass(props.className);
});

it('calls setAllFilters with empty array when clear button is clicked', () => {
const setAllFilters = jest.fn();
const contextValue = { headers, state: { filters }, setAllFilters };
const { getByText } = renderWithContext(contextValue);
const clearButton = getByText(props.clearFiltersText);
clearButton.click();
expect(setAllFilters).toHaveBeenCalledWith([]);
});
});
});
Loading