@testing-library/dom#within JavaScript Examples
The following examples show how to use
@testing-library/dom#within.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: HeatmapMetadataTrackSettings.test.jsx From ui with MIT License | 5 votes |
checkReorderableListState = (contentList, enabledList, items) => {
items.forEach((item, index) => {
expect(item).toHaveTextContent(contentList[index]);
const expectedAriaChecked = enabledList[index] ? 'true' : 'false';
expect(within(item).getByRole('switch')).toHaveAttribute('aria-checked', expectedAriaChecked);
});
}
Example #2
Source File: HeatmapMetadataTrackSettings.test.jsx From ui with MIT License | 5 votes |
describe('HeatmapMetadataTrackSettings', () => {
it('Renders correctly', async () => {
await loadAndRenderDefault();
const items = screen.getAllByTestId('reorderableListItem');
checkReorderableListState(
['louvain clusters', 'Custom cell sets', 'Samples'],
[true, false, false],
items,
);
});
it('Can enable and reorder correctly', async () => {
await loadAndRenderDefault();
let items = screen.getAllByTestId('reorderableListItem');
// When samples is enabled
act(() => {
userEvent.click(within(items[2]).getByRole('switch'));
});
items = screen.getAllByTestId('reorderableListItem');
checkReorderableListState(
['louvain clusters', 'Samples', 'Custom cell sets'],
[true, true, false],
items,
);
// When louvain is moved down
act(() => {
const downButton = within(items[0]).getAllByRole('button')[1];
userEvent.click(downButton);
});
items = screen.getAllByTestId('reorderableListItem');
// Louvain is now second
checkReorderableListState(
['Samples', 'louvain clusters', 'Custom cell sets'],
[true, true, false],
items,
);
// When louvain is attempted to be moved down again
items = screen.getAllByTestId('reorderableListItem');
act(() => {
const downButton = within(items[1]).getAllByRole('button')[1];
userEvent.click(downButton);
});
items = screen.getAllByTestId('reorderableListItem');
// Nothing changes, because custom cell sets is disabled
checkReorderableListState(
['Samples', 'louvain clusters', 'Custom cell sets'],
[true, true, false],
items,
);
});
});
Example #3
Source File: index.test.jsx From ui with MIT License | 4 votes |
describe('Marker heatmap plot', () => {
beforeAll(async () => {
await preloadAll();
});
beforeEach(async () => {
jest.clearAllMocks();
seekFromS3
.mockReset()
// load gene list
.mockImplementationOnce(() => null)
.mockImplementationOnce((Etag) => mockWorkerResponses[Etag])
// load gene expression
.mockImplementationOnce(() => null)
.mockImplementationOnce((Etag) => mockWorkerResponses[Etag]);
enableFetchMocks();
fetchMock.resetMocks();
fetchMock.doMock();
fetchMock.mockIf(/.*/, mockAPI(defaultResponses));
storeState = makeStore();
// Set up state for backend status
await storeState.dispatch(loadBackendStatus(experimentId));
});
it('Loads controls and elements', async () => {
await renderHeatmapPage(storeState);
expect(screen.getByText(/Gene selection/i)).toBeInTheDocument();
expect(screen.getByText(/Select data/i)).toBeInTheDocument();
expect(screen.getByText(/Cluster guardlines/i)).toBeInTheDocument();
expect(screen.getByText(/Metadata tracks/i)).toBeInTheDocument();
expect(screen.getByText(/Group by/i)).toBeInTheDocument();
expect(screen.getByText(/Expression values/i)).toBeInTheDocument();
expect(screen.getByText(/Main schema/i)).toBeInTheDocument();
expect(screen.getByText(/Colours/i)).toBeInTheDocument();
expect(screen.getByText(/Legend/i)).toBeInTheDocument();
});
it('Loads the plot', async () => {
await renderHeatmapPage(storeState);
expect(screen.getByRole('graphics-document', { name: 'Marker heatmap' })).toBeInTheDocument();
});
it('Shows an error message if marker genes failed to load', async () => {
seekFromS3
.mockReset()
// load genes list
.mockImplementationOnce(() => null)
.mockImplementationOnce((Etag) => mockWorkerResponses[Etag])
// throw error on marker genes load
.mockImplementationOnce(() => null)
.mockImplementationOnce(() => { throw new Error('Not found'); });
await renderHeatmapPage(storeState);
// It shouldn't show the plot
expect(screen.queryByRole('graphics-document', { name: 'Marker heatmap' })).toBeNull();
// There is an error message
expect(screen.getByText(/Could not load marker genes/i)).toBeInTheDocument();
});
it('loads marker genes on specifying new number of genes per cluster', async () => {
await renderHeatmapPage(storeState);
// Check that initially there are 5 marker genes - the default
markerGenesData5.order.forEach((geneName) => {
expect(screen.getByText(geneName)).toBeInTheDocument();
});
await act(async () => {
userEvent.click(screen.getByText('Marker genes'));
});
expect(screen.getByText('Number of marker genes per cluster')).toBeInTheDocument();
const nGenesInput = screen.getByRole('spinbutton', { name: 'Number of genes input' });
userEvent.type(nGenesInput, '{backspace}2');
await act(async () => {
userEvent.click(screen.getByText('Run'));
});
// Go back to "Custom Genes" and check the number of genes
await act(async () => {
userEvent.click(screen.getByText('Custom genes'));
});
// The genes in Data 2 should exist
markerGenesData2.order.forEach((geneName) => {
expect(screen.getByText(geneName)).toBeInTheDocument();
});
});
it('adds genes correctly into the plot', async () => {
seekFromS3
.mockReset()
// load genes list
.mockImplementationOnce(() => null)
.mockImplementationOnce((Etag) => mockWorkerResponses[Etag])
// 1st load
.mockImplementationOnce(() => null)
.mockImplementationOnce((ETag) => mockWorkerResponses[ETag])
// 2nd load
.mockImplementationOnce(() => null)
.mockImplementationOnce((ETag) => mockWorkerResponses[ETag]);
await renderHeatmapPage(storeState);
// Add in a new gene
// This is done because we can not insert text into the genes list input
const genesToLoad = [...markerGenesData5.order, 'FAKEGENE'];
await act(async () => {
await storeState.dispatch(loadGeneExpression(experimentId, genesToLoad, plotUuid));
});
expect(screen.getByText('FAKEGENE')).toBeInTheDocument();
// The returned value is a HTML NodeList
const genesContainer = screen.getByText('FAKEGENE').closest('div[class*=selector]');
const displayedGenesList = getDisplayedGenes(genesContainer);
// Check that the genes is ordered correctly.
// This means that FAKEGENE should not be the last in the genes list
expect(_.isEqual(displayedGenesList, genesToLoad)).toEqual(false);
});
it('Shows an error message if gene expression fails to load', async () => {
seekFromS3
.mockReset()
// load genes list
.mockImplementationOnce(() => null)
.mockImplementationOnce((Etag) => mockWorkerResponses[Etag])
// throw error on gene expression load
.mockImplementationOnce(() => null)
.mockImplementationOnce(() => { throw new Error('Not found'); });
await renderHeatmapPage(storeState);
const genesToLoad = [...markerGenesData5.order, 'FAKEGENE'];
await act(async () => {
await storeState.dispatch(loadGeneExpression(experimentId, genesToLoad, plotUuid));
});
// It shouldn't show the plot
expect(screen.queryByRole('graphics-document', { name: 'Marker heatmap' })).toBeNull();
// There is an error message
expect(screen.getByText(/Could not load gene expression data/i)).toBeInTheDocument();
});
it('removing a gene keeps the sorted order without re-sorting', async () => {
seekFromS3
.mockReset()
// load genes list
.mockImplementationOnce(() => null)
.mockImplementationOnce((Etag) => mockWorkerResponses[Etag])
// 1st load
.mockImplementationOnce(() => null)
.mockImplementationOnce((ETag) => mockWorkerResponses[ETag])
// 2nd load
.mockImplementationOnce(() => null)
.mockImplementationOnce((ETag) => mockWorkerResponses[ETag]);
await renderHeatmapPage(storeState);
// Setting up so that there is an inserted gene in the list
const genesToLoad = [...markerGenesData5.order, 'FAKEGENE'];
await act(async () => {
// This is done because we can not insert text into the genes list input
await storeState.dispatch(loadGeneExpression(experimentId, genesToLoad, plotUuid));
});
expect(screen.getByText('FAKEGENE')).toBeInTheDocument();
// The returned value is a HTML NodeList
const genesContainer = screen.getByText('FAKEGENE').closest('div[class*=selector]');
const genesListBeforeRemoval = getDisplayedGenes(genesContainer);
// Removing the 5th gene from the list
// genesListBeforeRemoval is modified - splice removes the item from the list
const geneToRemove = genesListBeforeRemoval.splice(5, 1);
const geneRemoveButton = screen.getByText(geneToRemove).nextSibling;
userEvent.click(geneRemoveButton);
// Get newly displayed genes after the removal
const genesListAfterRemoval = getDisplayedGenes(genesContainer);
// The list of displayed genes should be in the same order as the displayed genes
expect(_.isEqual(genesListAfterRemoval, genesListBeforeRemoval)).toEqual(true);
});
it('loads the tabs under gene selection', async () => {
await renderHeatmapPage(storeState);
expect(screen.getByText(/Add\/Remove genes/i)).toBeInTheDocument();
expect(screen.getByText(/Search for and re-order genes/i)).toBeInTheDocument();
});
it('switches tabs and removes genes within the tree', async () => {
await renderHeatmapPage(storeState);
await act(async () => {
userEvent.click(screen.getByText('Search for and re-order genes'));
});
// note: clicking another tab doesn't remove previous tab from screen
// screen.getByText will find multiples of the same gene -> use within(geneTree)
const geneTree = screen.getByRole('tree');
// The genes in Data 5 should be in the tree
markerGenesData5.order.forEach((geneName) => {
expect(within(geneTree).getByText(geneName)).toBeInTheDocument();
});
// Remove a gene using the X button
const genesListBeforeRemoval = getTreeGenes(geneTree);
const geneToRemove = within(geneTree).getByText(genesListBeforeRemoval[1]);
const geneRemoveButton = geneToRemove.nextSibling.firstChild;
userEvent.click(geneRemoveButton);
const genesListAfterRemoval = getTreeGenes(geneTree);
// remove element from list manually to compare
genesListBeforeRemoval.splice(1, 1);
// The gene should be deleted from the list
expect(_.isEqual(genesListAfterRemoval, genesListBeforeRemoval)).toEqual(true);
});
it('searches for genes and adds a valid gene', async () => {
await renderHeatmapPage(storeState);
await act(async () => {
userEvent.click(screen.getByText('Search for and re-order genes'));
});
// check placeholder text is loaded
expect(screen.getByText('Search for genes...')).toBeInTheDocument();
const searchBox = screen.getByRole('combobox');
// remove a gene to check if genes can be added
const geneTree = screen.getByRole('tree');
const geneToRemove = within(geneTree).getByText('Tmem176a');
const geneRemoveButton = geneToRemove.nextSibling.firstChild;
userEvent.click(geneRemoveButton);
// search for genes using lowercase
userEvent.type(searchBox, 'tmem');
// antd creates multiple elements for options
// find option element by title, clicking on element with role='option' does nothing
const option = screen.getByTitle('Tmem176a');
await act(async () => {
// the element has pointer-events set to 'none', skip check
// based on https://stackoverflow.com/questions/61080116
userEvent.click(option, undefined, { skipPointerEventsCheck: true });
});
// check the search text is cleared after selecting a valid option
expect(searchBox.value).toBe('');
// check the selected gene was added
expect(within(geneTree).getByText('Tmem176a')).toBeInTheDocument();
});
it('adds an already loaded gene and clears the input', async () => {
await renderHeatmapPage(storeState);
await act(async () => {
userEvent.click(screen.getByText('Search for and re-order genes'));
});
const searchBox = screen.getByRole('combobox');
userEvent.type(searchBox, 'tmem');
// this finds option for selection box in 1st tab and search box, use second element
const option = screen.getAllByTitle('Tmem176a')[1];
await act(async () => {
userEvent.click(option, undefined, { skipPointerEventsCheck: true });
});
// search box shouldn't clear when selecting an already loaded gene
expect(searchBox.value).toBe('tmem');
// clear button is automatically generated by antd and cannot be easily accessed
const clearButton = searchBox.closest('div[class*=ant-select-auto-complete]').lastChild;
userEvent.click(clearButton);
expect(searchBox.value).toBe('');
});
});