Skip to content

Commit

Permalink
test: Add tests for new content tags editing
Browse files Browse the repository at this point in the history
  • Loading branch information
yusuf-musleh committed Nov 28, 2023
1 parent b9e9657 commit 63e965c
Show file tree
Hide file tree
Showing 6 changed files with 207 additions and 10 deletions.
140 changes: 136 additions & 4 deletions src/content-tags-drawer/ContentTagsCollapsible.test.jsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,25 @@
import React from 'react';
import { IntlProvider } from '@edx/frontend-platform/i18n';
import { act, render } from '@testing-library/react';
import {
act,
render,
fireEvent,
waitFor,
} from '@testing-library/react';
import PropTypes from 'prop-types';

import ContentTagsCollapsible from './ContentTagsCollapsible';
import messages from './messages';
import { useTaxonomyTagsData } from './data/apiHooks';

jest.mock('./data/apiHooks', () => ({
useContentTaxonomyTagsMutation: jest.fn(() => ({
isError: false,
mutate: jest.fn(),
})),
useTaxonomyTagsData: jest.fn(() => ({
isSuccess: false,
data: {},
})),
}));

Expand Down Expand Up @@ -65,16 +77,136 @@ describe('<ContentTagsCollapsible />', () => {
});
});

it('should render taxonomy tags data without tags number badge', async () => {
data.taxonomyAndTagsData.contentTags = [];
it('should render new tags as they are checked in the dropdown', async () => {
useTaxonomyTagsData.mockReturnValue({
isSuccess: true,
data: {
results: [{
value: 'Tag 1',
subTagsUrl: null,
}, {
value: 'Tag 2',
subTagsUrl: null,
}, {
value: 'Tag 3',
subTagsUrl: null,
}],
},
});

await act(async () => {
const { container, getByText } = render(
const { container, getByText, getAllByText } = render(
<ContentTagsCollapsibleComponent
contentId={data.contentId}
taxonomyAndTagsData={data.taxonomyAndTagsData}
editable={data.editable}
/>,
);

// Expand the Taxonomy to view applied tags and "Add tags" button
const expandToggle = container.getElementsByClassName('collapsible-trigger')[0];
await act(async () => {
fireEvent.click(expandToggle);
});

// Click on "Add tags" button to open dropdown to select new tags
const addTagsButton = getByText(messages.addTagsButtonText.defaultMessage);
await act(async () => {
fireEvent.click(addTagsButton);
});

// Wait for the dropdown selector for tags to open,
// Tag 3 should only appear there
await waitFor(() => {
expect(getByText('Tag 3')).toBeInTheDocument();
expect(getAllByText('Tag 3').length === 1);
});

const tag3 = getByText('Tag 3');
await act(async () => {
fireEvent.click(tag3);
});

// After clicking on Tag 3, it should also appear in amongst
// the tag bubbles in the tree
await waitFor(() => {
expect(getAllByText('Tag 3').length === 2);
});
});
});

it('should remove tag when they are unchecked in the dropdown', async () => {
useTaxonomyTagsData.mockReturnValue({
isSuccess: true,
data: {
results: [{
value: 'Tag 1',
subTagsUrl: null,
}, {
value: 'Tag 2',
subTagsUrl: null,
}, {
value: 'Tag 3',
subTagsUrl: null,
}],
},
});

await act(async () => {
const { container, getByText, getAllByText } = render(
<ContentTagsCollapsibleComponent
contentId={data.contentId}
taxonomyAndTagsData={data.taxonomyAndTagsData}
editable={data.editable}
/>,
);

// Expand the Taxonomy to view applied tags and "Add tags" button
const expandToggle = container.getElementsByClassName('collapsible-trigger')[0];
await act(async () => {
fireEvent.click(expandToggle);
});

// Check that Tag 2 appears in tag bubbles
await waitFor(() => {
expect(getByText('Tag 2')).toBeInTheDocument();
});

// Click on "Add tags" button to open dropdown to select new tags
const addTagsButton = getByText(messages.addTagsButtonText.defaultMessage);
await act(async () => {
fireEvent.click(addTagsButton);
});

// Wait for the dropdown selector for tags to open,
// Tag 3 should only appear there, (i.e. the dropdown is open, since Tag 3 is not applied)
await waitFor(() => {
expect(getByText('Tag 3')).toBeInTheDocument();
});

// Get the Tag 2 checkbox and click on it
const tag2 = getAllByText('Tag 2')[1];
await act(async () => {
fireEvent.click(tag2);
});

// After clicking on Tag 2, it should be removed from
// the tag bubbles in so only the one in the dropdown appears
expect(getAllByText('Tag 2').length === 1);
});
});

it('should render taxonomy tags data without tags number badge', async () => {
const updatedData = { ...data };
updatedData.taxonomyAndTagsData.contentTags = [];
await act(async () => {
const { container, getByText } = render(
<ContentTagsCollapsibleComponent
contentId={updatedData.contentId}
taxonomyAndTagsData={updatedData.taxonomyAndTagsData}
editable={updatedData.editable}
/>,
);
expect(getByText('Taxonomy 1')).toBeInTheDocument();
expect(container.getElementsByClassName('invisible').length).toBe(1);
});
Expand Down
26 changes: 24 additions & 2 deletions src/content-tags-drawer/TagBubble.test.jsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import React from 'react';
import { IntlProvider } from '@edx/frontend-platform/i18n';
import { render } from '@testing-library/react';
import { act, render, fireEvent } from '@testing-library/react';
import PropTypes from 'prop-types';

import TagBubble from './TagBubble';

const data = {
value: 'Tag 1',
lineage: [],
removeTagHandler: () => {},
removeTagHandler: jest.fn(),
};

const TagBubbleComponent = ({
Expand Down Expand Up @@ -73,4 +73,26 @@ describe('<TagBubble />', () => {
expect(container.getElementsByClassName('implicit').length).toBe(0);
expect(container.getElementsByClassName('pgn__chip__icon-after').length).toBe(1);
});

it('should call removeTagHandler when "x" clicked on explicit tag', async () => {
const tagBubbleData = {
implicit: false,
...data,
};
const { container } = render(
<TagBubbleComponent
value={tagBubbleData.value}
editable
lineage={data.lineage}
implicit={tagBubbleData.implicit}
removeTagHandler={tagBubbleData.removeTagHandler}
/>,
);

const xButton = container.getElementsByClassName('pgn__chip__icon-after')[0];
await act(async () => {
fireEvent.click(xButton);
});
expect(data.removeTagHandler).toHaveBeenCalled();
});
});
1 change: 1 addition & 0 deletions src/content-tags-drawer/__mocks__/index.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export { default as taxonomyTagsMock } from './taxonomyTagsMock';
export { default as contentTaxonomyTagsMock } from './contentTaxonomyTagsMock';
export { default as contentDataMock } from './contentDataMock';
export { default as updateContentTaxonomyTagsMock } from './updateContentTaxonomyTagsMock';
25 changes: 25 additions & 0 deletions src/content-tags-drawer/__mocks__/updateContentTaxonomyTagsMock.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
module.exports = {
'block-v1:SampleTaxonomyOrg1+STC1+2023_1+type@vertical+block@aaf8b8eb86b54281aeeab12499d2cb0b': {
taxonomies: [
{
name: 'FlatTaxonomy',
taxonomyId: 3,
editable: true,
tags: [
{
value: 'flat taxonomy tag 100',
lineage: [
'flat taxonomy tag 100',
],
},
{
value: 'flat taxonomy tag 3856',
lineage: [
'flat taxonomy tag 3856',
],
},
],
},
],
},
};
2 changes: 1 addition & 1 deletion src/content-tags-drawer/data/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,5 +52,5 @@ export async function updateContentTaxonomyTags(contentId, taxonomyId, tags) {
let url = getContentTaxonomyTagsApiUrl(contentId);
url = `${url}?taxonomy=${taxonomyId}`;
const { data } = await getAuthenticatedHttpClient().put(url, { tags });
return camelCaseObject(data);
return camelCaseObject(data[contentId]);
}
23 changes: 20 additions & 3 deletions src/content-tags-drawer/data/api.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,12 @@ import MockAdapter from 'axios-mock-adapter';
import { initializeMockApp } from '@edx/frontend-platform';
import { getAuthenticatedHttpClient } from '@edx/frontend-platform/auth';

import { taxonomyTagsMock, contentTaxonomyTagsMock, contentDataMock } from '../__mocks__';
import {
taxonomyTagsMock,
contentTaxonomyTagsMock,
contentDataMock,
updateContentTaxonomyTagsMock,
} from '../__mocks__';

import {
getTaxonomyTagsApiUrl,
Expand All @@ -11,6 +16,7 @@ import {
getTaxonomyTagsData,
getContentTaxonomyTagsData,
getContentData,
updateContentTaxonomyTags,
} from './api';

let axiosMock;
Expand All @@ -33,7 +39,7 @@ describe('content tags drawer api calls', () => {
});

it('should get taxonomy tags data', async () => {
const taxonomyId = '123';
const taxonomyId = 123;
axiosMock.onGet().reply(200, taxonomyTagsMock);
const result = await getTaxonomyTagsData(taxonomyId);

Expand All @@ -42,7 +48,7 @@ describe('content tags drawer api calls', () => {
});

it('should get taxonomy tags data with fullPathProvided', async () => {
const taxonomyId = '123';
const taxonomyId = 123;
const fullPathProvided = 'http://example.com/';
axiosMock.onGet().reply(200, taxonomyTagsMock);
const result = await getTaxonomyTagsData(taxonomyId, fullPathProvided);
Expand All @@ -68,4 +74,15 @@ describe('content tags drawer api calls', () => {
expect(axiosMock.history.get[0].url).toEqual(getContentDataApiUrl(contentId));
expect(result).toEqual(contentDataMock);
});

it('should update content taxonomy tags', async () => {
const contentId = 'block-v1:SampleTaxonomyOrg1+STC1+2023_1+type@vertical+block@aaf8b8eb86b54281aeeab12499d2cb0b';
const taxonomyId = 3;
const tags = ['flat taxonomy tag 100', 'flat taxonomy tag 3856'];
axiosMock.onPut(`${getContentTaxonomyTagsApiUrl(contentId)}?taxonomy=${taxonomyId}`).reply(200, updateContentTaxonomyTagsMock);
const result = await updateContentTaxonomyTags(contentId, taxonomyId, tags);

expect(axiosMock.history.put[0].url).toEqual(`${getContentTaxonomyTagsApiUrl(contentId)}?taxonomy=${taxonomyId}`);
expect(result).toEqual(updateContentTaxonomyTagsMock[contentId]);
});
});

0 comments on commit 63e965c

Please sign in to comment.