From 34a53dc556d343f979f4549f6c93eafd9ee8dffb Mon Sep 17 00:00:00 2001 From: Prashant-thakur77 Date: Tue, 31 Mar 2026 12:34:52 +0530 Subject: [PATCH 1/8] test: Made changes to trashModal test file to use vue testing library --- .../views/trash/__tests__/trashModal.spec.js | 259 +++++++++++++----- 1 file changed, 198 insertions(+), 61 deletions(-) diff --git a/contentcuration/contentcuration/frontend/channelEdit/views/trash/__tests__/trashModal.spec.js b/contentcuration/contentcuration/frontend/channelEdit/views/trash/__tests__/trashModal.spec.js index 80225b2027..fa115450b4 100644 --- a/contentcuration/contentcuration/frontend/channelEdit/views/trash/__tests__/trashModal.spec.js +++ b/contentcuration/contentcuration/frontend/channelEdit/views/trash/__tests__/trashModal.spec.js @@ -1,41 +1,53 @@ -import { mount } from '@vue/test-utils'; +import { render, screen, waitFor } from '@testing-library/vue'; +import userEvent from '@testing-library/user-event'; import TrashModal from '../TrashModal'; import { factory } from '../../../store'; import router from '../../../router'; import { RouteNames } from '../../../constants'; -const store = factory(); - const testChildren = [ { id: 'test1', - title: 'Item', + title: 'Item1', kind: 'video', modified: new Date(2020, 1, 20), }, { id: 'test2', - title: 'Item', + title: 'Item2', kind: 'audio', modified: new Date(2020, 2, 1), }, { id: 'test3', - title: 'Topic', + title: 'Topic1', kind: 'topic', modified: new Date(2020, 1, 1), }, ]; -function makeWrapper(items) { +const makeWrapper = (items = testChildren, dataOverride = {}) => { + const store = factory(); + + // Create spies for methods before rendering const loadContentNodes = jest.spyOn(TrashModal.methods, 'loadContentNodes'); loadContentNodes.mockImplementation(() => Promise.resolve()); const loadAncestors = jest.spyOn(TrashModal.methods, 'loadAncestors'); loadAncestors.mockImplementation(() => Promise.resolve()); const loadChildren = jest.spyOn(TrashModal.methods, 'loadChildren'); loadChildren.mockImplementation(() => Promise.resolve({ more: null, results: [] })); + const removeContentNodes = jest.spyOn(TrashModal.methods, 'removeContentNodes'); + removeContentNodes.mockImplementation(() => Promise.resolve()); + + const loadNodes = jest.spyOn(TrashModal.methods, 'loadNodes'); + // If we want loading: true, we can set dataOverride. + loadNodes.mockImplementation(function() { + this.loading = dataOverride.loading !== undefined ? dataOverride.loading : false; + this.more = null; + this.moreLoading = false; + }); - const wrapper = mount(TrashModal, { + const utils = render(TrashModal, { store, router, computed: { @@ -48,7 +60,7 @@ function makeWrapper(items) { return 'trash'; }, items() { - return items || testChildren; + return items; }, offline() { return false; @@ -62,110 +74,235 @@ function makeWrapper(items) { stubs: { ResourceDrawer: true, OfflineText: true, + MoveModal: { + template: '', + methods: { moveComplete: jest.fn() } + }, + }, + propsData: { + nodeId: 'test', }, }); - return [wrapper, { loadContentNodes, loadAncestors, loadChildren }]; -} + return { ...utils, store, loadContentNodes, loadAncestors, loadChildren, loadNodes, removeContentNodes }; +}; describe('trashModal', () => { - let wrapper; + let user; - beforeEach(async () => { - [wrapper] = makeWrapper(); + beforeEach(() => { + user = userEvent.setup(); + jest.clearAllMocks(); router.replace({ name: RouteNames.TRASH, params: { nodeId: 'test' } }).catch(() => {}); - await wrapper.setData({ loading: false }); }); describe('on load', () => { it('should show loading indicator if content is loading', async () => { - await wrapper.setData({ loading: true }); - expect(wrapper.findComponent('[data-test="loading"]').exists()).toBe(true); + makeWrapper(testChildren, { loading: true }); + expect(document.querySelector('[data-test="loading"]')).toBeInTheDocument(); }); it('should show empty text if there are no items', async () => { - const [emptyWrapper] = makeWrapper([]); - await emptyWrapper.setData({ loading: false }); - expect(emptyWrapper.findComponent('[data-test="empty"]').exists()).toBe(true); + makeWrapper([]); + expect(screen.getByText('Trash is empty')).toBeInTheDocument(); }); - it('should show items in list', () => { - expect(wrapper.findComponent('[data-test="list"]').exists()).toBe(true); + it('should show items in list', async () => { + makeWrapper(); + expect(screen.getByText('Item1')).toBeInTheDocument(); + expect(screen.getByText('Item2')).toBeInTheDocument(); + expect(screen.getByText('Topic1')).toBeInTheDocument(); }); }); describe('on topic tree selection', () => { it('clicking item should set previewNodeId', async () => { - await wrapper.findComponent('[data-test="item"]').trigger('click'); - expect(wrapper.vm.previewNodeId).toBe(testChildren[0].id); + makeWrapper(); + expect(screen.getByText('Item1')).toBeInTheDocument(); + + const item1 = screen.getByText('Item1'); + await user.click(item1); + + await waitFor(() => { + const drawer = document.querySelector('resourcedrawer-stub'); + expect(drawer).toHaveAttribute('nodeid', 'test1'); + }); }); - it('checking item in list should add the item ID to the selected array', () => { - wrapper - .findComponent('[data-test="checkbox"]') - .find('input[type="checkbox"]') - .element.click(); - expect(wrapper.vm.selected).toEqual(['test1']); + it('checking item in list should add the item ID to the selected array', async () => { + makeWrapper(); + expect(screen.getByText('Item1')).toBeInTheDocument(); + + const checkboxes = screen.getAllByRole('checkbox'); + const firstItemCheckbox = checkboxes[1]; + + expect(screen.getByRole('button', { name: /Delete/i })).toBeDisabled(); + + await user.click(firstItemCheckbox); + + await waitFor(() => { + expect(screen.getByRole('button', { name: /Delete/i })).toBeEnabled(); + }); }); - it('checking select all checkbox should check all items', () => { - wrapper.findComponent('[data-test="selectall"]').vm.$emit('input', true); - expect(wrapper.vm.selected).toEqual(testChildren.map(c => c.id)); + it('checking select all checkbox should check all items', async () => { + makeWrapper(); + expect(screen.getByText('Item1')).toBeInTheDocument(); + + const selectAllCheckbox = screen.getAllByRole('checkbox')[0]; + await user.click(selectAllCheckbox); + + await waitFor(() => { + const itemCheckboxes = screen.getAllByRole('checkbox').slice(1); + itemCheckboxes.forEach(checkbox => { + expect(checkbox).toBeChecked(); + }); + }); }); }); describe('on close', () => { it('clicking close button should go back to parent route', async () => { - await wrapper.findComponent('[data-test="close"]').trigger('click'); - expect(wrapper.vm.$route.name).toBe('TEST_PARENT'); + makeWrapper(); + expect(screen.getByText('Item1')).toBeInTheDocument(); + + const closeButton = document.querySelector('[data-test="close"]'); + await user.click(closeButton); + + await waitFor(() => { + expect(router.currentRoute.name).toBe('TEST_PARENT'); + }); }); }); describe('on delete', () => { - it('DELETE button should be disabled if no items are selected', () => { - expect(wrapper.findComponent('[data-test="delete"]').vm.disabled).toBe(true); + it('DELETE button should be disabled if no items are selected', async () => { + makeWrapper(); + expect(screen.getByText('Item1')).toBeInTheDocument(); + expect(screen.getByRole('button', { name: /Delete/i })).toBeDisabled(); }); it('clicking DELETE button should open delete confirmation dialog', async () => { - await wrapper.setData({ selected: testChildren.map(c => c.id) }); - await wrapper.findComponent('[data-test="delete"]').trigger('click'); - expect(wrapper.vm.showConfirmationDialog).toBe(true); + makeWrapper(); + expect(screen.getByText('Item1')).toBeInTheDocument(); + + const selectAllCheckbox = screen.getAllByRole('checkbox')[0]; + await user.click(selectAllCheckbox); + + const deleteButton = screen.getByRole('button', { name: /Delete/i }); + await user.click(deleteButton); + + await waitFor(() => { + expect(screen.getByText(/You cannot undo this action/i)).toBeInTheDocument(); + }); }); it('clicking CLOSE on delete confirmation dialog should close the dialog', async () => { - await wrapper.setData({ showConfirmationDialog: true }); - await wrapper.findComponent('[data-test="deleteconfirm"]').vm.$emit('cancel'); - expect(wrapper.vm.showConfirmationDialog).toBe(false); + makeWrapper(); + expect(screen.getByText('Item1')).toBeInTheDocument(); + + const selectAllCheckbox = screen.getAllByRole('checkbox')[0]; + await user.click(selectAllCheckbox); + + const deleteButton = screen.getByRole('button', { name: /Delete/i }); + await user.click(deleteButton); + + await waitFor(() => { + expect(screen.getByRole('button', { name: /Cancel/i })).toBeInTheDocument(); + }); + + const cancelButton = screen.getByRole('button', { name: /Cancel/i }); + await user.click(cancelButton); + + await waitFor(() => { + expect(screen.queryByText(/You cannot undo this action/i)).not.toBeInTheDocument(); + }); }); it('clicking DELETE PERMANENTLY on delete confirmation dialog should trigger deletion', async () => { - const selected = testChildren.map(c => c.id); - const deleteContentNodes = jest.spyOn(wrapper.vm, 'deleteContentNodes'); - deleteContentNodes.mockImplementation(() => Promise.resolve()); - await wrapper.setData({ selected, showConfirmationDialog: true }); - await wrapper.findComponent('[data-test="deleteconfirm"]').vm.$emit('submit'); - expect(deleteContentNodes).toHaveBeenCalledWith(selected); + const deleteContentNodesSpy = jest.spyOn(TrashModal.methods, 'deleteContentNodes'); + deleteContentNodesSpy.mockImplementation(() => Promise.resolve()); + + makeWrapper(); + expect(screen.getByText('Item1')).toBeInTheDocument(); + + const selectAllCheckbox = screen.getAllByRole('checkbox')[0]; + await user.click(selectAllCheckbox); + + const deleteButton = screen.getByRole('button', { name: /Delete/i }); + await user.click(deleteButton); + + await waitFor(() => { + expect(screen.getByRole('button', { name: /Delete permanently/i })).toBeInTheDocument(); + }); + + const confirmDeleteButton = screen.getByRole('button', { name: /Delete permanently/i }); + await user.click(confirmDeleteButton); + + await waitFor(() => { + expect(deleteContentNodesSpy).toHaveBeenCalledWith(['test1', 'test2', 'test3']); + }); + deleteContentNodesSpy.mockRestore(); }); }); describe('on restore', () => { - it('RESTORE button should be disabled if no items are selected', () => { - expect(wrapper.findComponent('[data-test="restore"]').vm.disabled).toBe(true); + it('RESTORE button should be disabled if no items are selected', async () => { + makeWrapper(); + expect(screen.getByText('Item1')).toBeInTheDocument(); + expect(screen.getByRole('button', { name: /Restore/i })).toBeDisabled(); }); it('RESTORE should set moveModalOpen to true', async () => { - const selected = testChildren.map(c => c.id); - await wrapper.setData({ selected }); - await wrapper.findComponent('[data-test="restore"]').trigger('click'); - expect(wrapper.vm.moveModalOpen).toBe(true); + makeWrapper(); + expect(screen.getByText('Item1')).toBeInTheDocument(); + + const selectAllCheckbox = screen.getAllByRole('checkbox')[0]; + await user.click(selectAllCheckbox); + + const restoreButton = screen.getByRole('button', { name: /Restore/i }); + await user.click(restoreButton); + + await waitFor(() => { + expect(document.querySelector('.fullscreen-modal-window')).toBeFalsy(); + }); }); - it('moveNoves should clear selected and previewNodeId', async () => { - const moveContentNodes = jest.spyOn(wrapper.vm, 'moveContentNodes'); - moveContentNodes.mockImplementation(() => Promise.resolve()); - wrapper.vm.moveNodes(); - expect(wrapper.vm.selected).toEqual([]); - expect(wrapper.vm.previewNodeId).toBe(null); + it('moveNodes should clear selected and previewNodeId', async () => { + const moveContentNodesSpy = jest.spyOn(TrashModal.methods, 'moveContentNodes'); + moveContentNodesSpy.mockImplementation(() => Promise.resolve()); + + makeWrapper(); + expect(screen.getByText('Item1')).toBeInTheDocument(); + + const itemCheckbox = screen.getAllByRole('checkbox')[1]; + await user.click(itemCheckbox); + + const itemText = screen.getByText('Item2'); + await user.click(itemText); + + await waitFor(() => { + expect(document.querySelector('resourcedrawer-stub')).toHaveAttribute('nodeid', 'test2'); + }); + + // Restore action to open MoveModal + const restoreButton = screen.getByRole('button', { name: /Restore/i }); + await user.click(restoreButton); + + await waitFor(() => { + expect(document.querySelector('movemodal-stub')).toBeInTheDocument(); + }); + + const moveModalStub = document.querySelector('movemodal-stub'); + moveModalStub.__vue__.$emit('target', 'new-parent-id'); + + await waitFor(() => { + expect(moveContentNodesSpy).toHaveBeenCalledWith(expect.objectContaining({ + id__in: expect.any(Array), + parent: 'new-parent-id' + })); + }); + moveContentNodesSpy.mockRestore(); }); }); }); From 4648a92d5d0cce5ee745ce06ccd3ae1ce5a21816 Mon Sep 17 00:00:00 2001 From: Prashant-thakur77 Date: Sun, 5 Apr 2026 23:43:21 +0530 Subject: [PATCH 2/8] Updated the test file --- .../views/trash/__tests__/trashModal.spec.js | 432 +++++++++--------- 1 file changed, 225 insertions(+), 207 deletions(-) diff --git a/contentcuration/contentcuration/frontend/channelEdit/views/trash/__tests__/trashModal.spec.js b/contentcuration/contentcuration/frontend/channelEdit/views/trash/__tests__/trashModal.spec.js index fa115450b4..4cea8c54eb 100644 --- a/contentcuration/contentcuration/frontend/channelEdit/views/trash/__tests__/trashModal.spec.js +++ b/contentcuration/contentcuration/frontend/channelEdit/views/trash/__tests__/trashModal.spec.js @@ -1,308 +1,326 @@ -import { render, screen, waitFor } from '@testing-library/vue'; +import { render, screen, waitFor, configure } from '@testing-library/vue'; import userEvent from '@testing-library/user-event'; -import TrashModal from '../TrashModal'; +import VueRouter from 'vue-router'; + import { factory } from '../../../store'; -import router from '../../../router'; import { RouteNames } from '../../../constants'; +import TrashModal from '../TrashModal'; + +const store = factory(); + +const CHANNEL_ID = 'test-channel-id'; +const TRASH_ID = 'trash-root-id'; +const NODE_ID = 'tree-node-id'; const testChildren = [ - { - id: 'test1', - title: 'Item1', - kind: 'video', - modified: new Date(2020, 1, 20), - }, - { - id: 'test2', - title: 'Item2', - kind: 'audio', - modified: new Date(2020, 2, 1), - }, - { - id: 'test3', - title: 'Topic1', - kind: 'topic', - modified: new Date(2020, 1, 1), - }, + { id: 'test1', title: 'Item', kind: 'video', modified: new Date(2020, 1, 20) }, + { id: 'test2', title: 'Item', kind: 'audio', modified: new Date(2020, 2, 1) }, + { id: 'test3', title: 'Topic', kind: 'topic', modified: new Date(2020, 1, 1) }, ]; -const makeWrapper = (items = testChildren, dataOverride = {}) => { - const store = factory(); - - // Create spies for methods before rendering - const loadContentNodes = jest.spyOn(TrashModal.methods, 'loadContentNodes'); - loadContentNodes.mockImplementation(() => Promise.resolve()); - const loadAncestors = jest.spyOn(TrashModal.methods, 'loadAncestors'); - loadAncestors.mockImplementation(() => Promise.resolve()); - const loadChildren = jest.spyOn(TrashModal.methods, 'loadChildren'); - loadChildren.mockImplementation(() => Promise.resolve({ more: null, results: [] })); - const removeContentNodes = jest.spyOn(TrashModal.methods, 'removeContentNodes'); - removeContentNodes.mockImplementation(() => Promise.resolve()); - - const loadNodes = jest.spyOn(TrashModal.methods, 'loadNodes'); - // If we want loading: true, we can set dataOverride. - loadNodes.mockImplementation(function() { - this.loading = dataOverride.loading !== undefined ? dataOverride.loading : false; - this.more = null; - this.moreLoading = false; +async function makeWrapper(items = testChildren, isLoading = false, stubOverrides = {}) { + const loadContentNodesSpy = jest.spyOn(TrashModal.methods, 'loadContentNodes').mockResolvedValue({}); + jest.spyOn(TrashModal.methods, 'loadAncestors').mockResolvedValue(); + jest.spyOn(TrashModal.methods, 'removeContentNodes').mockResolvedValue(); + const loadNodesSpy = jest.spyOn(TrashModal.methods, 'loadNodes'); + + if (isLoading) { + jest.spyOn(TrashModal.methods, 'loadChildren').mockReturnValue(new Promise(() => {})); + } else { + jest.spyOn(TrashModal.methods, 'loadChildren').mockResolvedValue({ + more: items === testChildren ? null : { parent: TRASH_ID, page: 2 }, + results: [], + }); + } + + const router = new VueRouter({ + routes: [ + { name: RouteNames.TRASH, path: '/:nodeId/trash', component: TrashModal }, + { name: RouteNames.TREE_VIEW, path: '/:nodeId/:detailNodeId?', component: { template: '
Tree
' } }, + ], }); - const utils = render(TrashModal, { - store, - router, - computed: { - currentChannel() { - return { - id: 'current channel', - }; + router.replace({ name: RouteNames.TRASH, params: { nodeId: NODE_ID } }).catch(() => {}); + + const routerPush = jest.spyOn(router, 'push').mockResolvedValue(); + + const utils = render( + TrashModal, + { + store, + router, + computed: { + currentChannel: () => ({ id: CHANNEL_ID }), + trashId: () => TRASH_ID, + items: () => items, + offline: () => false, + backLink: () => ({ name: RouteNames.TREE_VIEW, params: { nodeId: NODE_ID } }), + getSelectedTopicAndResourceCountText: () => ids => `${ids.length} items selected`, + counts: () => ({ topicCount: 0, resourceCount: 0 }), }, - trashId() { - return 'trash'; - }, - items() { - return items; - }, - offline() { - return false; - }, - backLink() { - return { - name: 'TEST_PARENT', - }; + stubs: { + MoveModal: true, + ResourceDrawer: true, + ...stubOverrides, + FullscreenModal: { + template: ` +
+ + + +
+ `, + }, + OfflineText: true, }, }, - stubs: { - ResourceDrawer: true, - OfflineText: true, - MoveModal: { - template: '', - methods: { moveComplete: jest.fn() } - }, - }, - propsData: { - nodeId: 'test', + localVue => { + localVue.use(VueRouter); }, - }); + ); - return { ...utils, store, loadContentNodes, loadAncestors, loadChildren, loadNodes, removeContentNodes }; -}; + if (!isLoading) { + await waitFor(() => { + expect(screen.queryByTestId('loading')).not.toBeInTheDocument(); + }); + } + + const user = userEvent.setup(); + return { ...utils, routerPush, user, loadNodesSpy, loadContentNodesSpy }; +} -describe('trashModal', () => { - let user; +describe('TrashModal', () => { + beforeAll(() => configure({ testIdAttribute: 'data-test' })); + afterAll(() => configure({ testIdAttribute: 'data-testid' })); beforeEach(() => { - user = userEvent.setup(); - jest.clearAllMocks(); - router.replace({ name: RouteNames.TRASH, params: { nodeId: 'test' } }).catch(() => {}); + jest.restoreAllMocks(); }); describe('on load', () => { - it('should show loading indicator if content is loading', async () => { - makeWrapper(testChildren, { loading: true }); - expect(document.querySelector('[data-test="loading"]')).toBeInTheDocument(); + it('shows a loading indicator while content is loading', async () => { + await makeWrapper(testChildren, true); + expect(screen.getByTestId('loading')).toBeInTheDocument(); }); - it('should show empty text if there are no items', async () => { - makeWrapper([]); - expect(screen.getByText('Trash is empty')).toBeInTheDocument(); + it('shows empty text when trash has no items', async () => { + await makeWrapper([]); + expect(screen.getByTestId('empty')).toBeInTheDocument(); }); - it('should show items in list', async () => { - makeWrapper(); - expect(screen.getByText('Item1')).toBeInTheDocument(); - expect(screen.getByText('Item2')).toBeInTheDocument(); - expect(screen.getByText('Topic1')).toBeInTheDocument(); + it('shows the item list when trash has items', async () => { + await makeWrapper(); + expect(screen.getByTestId('list')).toBeInTheDocument(); }); }); describe('on topic tree selection', () => { - it('clicking item should set previewNodeId', async () => { - makeWrapper(); - expect(screen.getByText('Item1')).toBeInTheDocument(); + it('clicking an item opens the resource drawer for that item', async () => { + const { user } = await makeWrapper(); - const item1 = screen.getByText('Item1'); - await user.click(item1); + expect(document.querySelector('resourcedrawer-stub')).not.toHaveAttribute('nodeid', testChildren[0].id); + + await user.click(screen.getAllByTestId('item')[0]); await waitFor(() => { const drawer = document.querySelector('resourcedrawer-stub'); - expect(drawer).toHaveAttribute('nodeid', 'test1'); + expect(drawer).toBeInTheDocument(); + expect(drawer).toHaveAttribute('nodeid', testChildren[0].id); }); }); - it('checking item in list should add the item ID to the selected array', async () => { - makeWrapper(); - expect(screen.getByText('Item1')).toBeInTheDocument(); + it('checking an item enables the Delete and Restore buttons', async () => { + const { user } = await makeWrapper(); + + expect(screen.getByTestId('delete')).toBeDisabled(); + expect(screen.getByTestId('restore')).toBeDisabled(); const checkboxes = screen.getAllByRole('checkbox'); - const firstItemCheckbox = checkboxes[1]; - - expect(screen.getByRole('button', { name: /Delete/i })).toBeDisabled(); - - await user.click(firstItemCheckbox); - + await user.click(checkboxes[1]); + await waitFor(() => { - expect(screen.getByRole('button', { name: /Delete/i })).toBeEnabled(); + expect(screen.getByTestId('delete')).toBeEnabled(); + expect(screen.getByTestId('restore')).toBeEnabled(); }); }); - it('checking select all checkbox should check all items', async () => { - makeWrapper(); - expect(screen.getByText('Item1')).toBeInTheDocument(); - - const selectAllCheckbox = screen.getAllByRole('checkbox')[0]; - await user.click(selectAllCheckbox); + it('checking the select-all checkbox checks all items', async () => { + const { user } = await makeWrapper(); + const [selectAll] = screen.getAllByRole('checkbox'); + await user.click(selectAll); await waitFor(() => { - const itemCheckboxes = screen.getAllByRole('checkbox').slice(1); - itemCheckboxes.forEach(checkbox => { - expect(checkbox).toBeChecked(); + screen.getAllByRole('checkbox').slice(1).forEach(cb => { + expect(cb).toBeChecked(); }); }); }); }); describe('on close', () => { - it('clicking close button should go back to parent route', async () => { - makeWrapper(); - expect(screen.getByText('Item1')).toBeInTheDocument(); + it('clicking the close button navigates back to the tree view', async () => { + const { routerPush, user } = await makeWrapper(); - const closeButton = document.querySelector('[data-test="close"]'); - await user.click(closeButton); + await user.click(screen.getByTestId('close')); await waitFor(() => { - expect(router.currentRoute.name).toBe('TEST_PARENT'); + expect(routerPush).toHaveBeenCalledWith( + expect.objectContaining({ name: RouteNames.TREE_VIEW }), + ); }); }); }); describe('on delete', () => { - it('DELETE button should be disabled if no items are selected', async () => { - makeWrapper(); - expect(screen.getByText('Item1')).toBeInTheDocument(); - expect(screen.getByRole('button', { name: /Delete/i })).toBeDisabled(); + it('Delete button is disabled when no items are selected', async () => { + await makeWrapper(); + expect(screen.getByTestId('delete')).toBeDisabled(); }); - it('clicking DELETE button should open delete confirmation dialog', async () => { - makeWrapper(); - expect(screen.getByText('Item1')).toBeInTheDocument(); - - const selectAllCheckbox = screen.getAllByRole('checkbox')[0]; - await user.click(selectAllCheckbox); + it('clicking Delete opens a confirmation dialog', async () => { + const { user } = await makeWrapper(); + const [selectAll] = screen.getAllByRole('checkbox'); + await user.click(selectAll); + await user.click(screen.getByTestId('delete')); - const deleteButton = screen.getByRole('button', { name: /Delete/i }); - await user.click(deleteButton); - - await waitFor(() => { - expect(screen.getByText(/You cannot undo this action/i)).toBeInTheDocument(); - }); + expect(await screen.findByText(/You cannot undo this action/i)).toBeInTheDocument(); }); - it('clicking CLOSE on delete confirmation dialog should close the dialog', async () => { - makeWrapper(); - expect(screen.getByText('Item1')).toBeInTheDocument(); - - const selectAllCheckbox = screen.getAllByRole('checkbox')[0]; - await user.click(selectAllCheckbox); - - const deleteButton = screen.getByRole('button', { name: /Delete/i }); - await user.click(deleteButton); - - await waitFor(() => { - expect(screen.getByRole('button', { name: /Cancel/i })).toBeInTheDocument(); - }); + it('clicking Cancel in the confirmation dialog closes it', async () => { + const { user } = await makeWrapper(); + const [selectAll] = screen.getAllByRole('checkbox'); + await user.click(selectAll); + await user.click(screen.getByTestId('delete')); + await screen.findByText(/You cannot undo this action/i); - const cancelButton = screen.getByRole('button', { name: /Cancel/i }); - await user.click(cancelButton); + await user.click(screen.getByRole('button', { name: /Cancel/i })); await waitFor(() => { expect(screen.queryByText(/You cannot undo this action/i)).not.toBeInTheDocument(); }); }); - it('clicking DELETE PERMANENTLY on delete confirmation dialog should trigger deletion', async () => { - const deleteContentNodesSpy = jest.spyOn(TrashModal.methods, 'deleteContentNodes'); - deleteContentNodesSpy.mockImplementation(() => Promise.resolve()); + it('clicking Delete permanently calls deleteContentNodes with the selected IDs', async () => { + const deleteContentNodes = jest + .spyOn(TrashModal.methods, 'deleteContentNodes') + .mockResolvedValue(); - makeWrapper(); - expect(screen.getByText('Item1')).toBeInTheDocument(); + const { user } = await makeWrapper(); - const selectAllCheckbox = screen.getAllByRole('checkbox')[0]; - await user.click(selectAllCheckbox); - - const deleteButton = screen.getByRole('button', { name: /Delete/i }); - await user.click(deleteButton); + const [selectAll] = screen.getAllByRole('checkbox'); + await user.click(selectAll); + await user.click(screen.getByTestId('delete')); + await user.click(await screen.findByRole('button', { name: /Delete permanently/i })); await waitFor(() => { - expect(screen.getByRole('button', { name: /Delete permanently/i })).toBeInTheDocument(); + expect(deleteContentNodes).toHaveBeenCalledWith(testChildren.map(c => c.id)); }); + }); - const confirmDeleteButton = screen.getByRole('button', { name: /Delete permanently/i }); - await user.click(confirmDeleteButton); + it('successful deletion triggers snackbar and reloads nodes', async () => { + jest.spyOn(TrashModal.methods, 'deleteContentNodes').mockResolvedValue(); + const dispatchSpy = jest.spyOn(store, 'dispatch').mockImplementation(() => Promise.resolve()); + + const { user, loadNodesSpy } = await makeWrapper(); + const [selectAll] = screen.getAllByRole('checkbox'); + await user.click(selectAll); + await user.click(screen.getByTestId('delete')); + await user.click(await screen.findByRole('button', { name: /Delete permanently/i })); await waitFor(() => { - expect(deleteContentNodesSpy).toHaveBeenCalledWith(['test1', 'test2', 'test3']); + expect(dispatchSpy).toHaveBeenCalledWith('showSnackbar', { + text: 'Permanently deleted', + }); + expect(loadNodesSpy).toHaveBeenCalled(); }); - deleteContentNodesSpy.mockRestore(); }); }); describe('on restore', () => { - it('RESTORE button should be disabled if no items are selected', async () => { - makeWrapper(); - expect(screen.getByText('Item1')).toBeInTheDocument(); - expect(screen.getByRole('button', { name: /Restore/i })).toBeDisabled(); + it('Restore button is disabled when no items are selected', async () => { + await makeWrapper(); + expect(screen.getByTestId('restore')).toBeDisabled(); }); - it('RESTORE should set moveModalOpen to true', async () => { - makeWrapper(); - expect(screen.getByText('Item1')).toBeInTheDocument(); - - const selectAllCheckbox = screen.getAllByRole('checkbox')[0]; - await user.click(selectAllCheckbox); - - const restoreButton = screen.getByRole('button', { name: /Restore/i }); - await user.click(restoreButton); + it('clicking Restore opens the MoveModal', async () => { + const { user } = await makeWrapper(); + const [selectAll] = screen.getAllByRole('checkbox'); + await user.click(selectAll); + await user.click(screen.getByTestId('restore')); await waitFor(() => { - expect(document.querySelector('.fullscreen-modal-window')).toBeFalsy(); + expect(document.querySelector('movemodal-stub')).toBeInTheDocument(); }); }); - it('moveNodes should clear selected and previewNodeId', async () => { - const moveContentNodesSpy = jest.spyOn(TrashModal.methods, 'moveContentNodes'); - moveContentNodesSpy.mockImplementation(() => Promise.resolve()); + it('restoring items clears selection and closes the preview', async () => { + jest.spyOn(TrashModal.methods, 'moveContentNodes').mockResolvedValue(); + const { user } = await makeWrapper(testChildren, false, { + MoveModal: { + methods: { + moveComplete() {}, + }, + template: ` +
+ +
+ `, + }, + }); - makeWrapper(); - expect(screen.getByText('Item1')).toBeInTheDocument(); + await user.click(screen.getAllByTestId('item')[0]); + await waitFor(() => { + expect(document.querySelector('resourcedrawer-stub')).toHaveAttribute('nodeid', testChildren[0].id); + }); - const itemCheckbox = screen.getAllByRole('checkbox')[1]; - await user.click(itemCheckbox); - - const itemText = screen.getByText('Item2'); - await user.click(itemText); + await user.click(screen.getAllByRole('checkbox')[0]); + await user.click(screen.getByTestId('restore')); + await user.click(screen.getByTestId('move-target')); - await waitFor(() => { - expect(document.querySelector('resourcedrawer-stub')).toHaveAttribute('nodeid', 'test2'); + await waitFor(() => { + screen.getAllByRole('checkbox').slice(1).forEach(cb => { + expect(cb).not.toBeChecked(); }); + expect(document.querySelector('resourcedrawer-stub')).not.toHaveAttribute('nodeid', testChildren[0].id); + }); + }); + }); - // Restore action to open MoveModal - const restoreButton = screen.getByRole('button', { name: /Restore/i }); - await user.click(restoreButton); + describe('selection count', () => { + it('shows selected item count in the bottom bar', async () => { + const { user } = await makeWrapper(); - await waitFor(() => { - expect(document.querySelector('movemodal-stub')).toBeInTheDocument(); - }); + expect(screen.queryByText(/items selected/i)).not.toBeInTheDocument(); + + const [selectAll] = screen.getAllByRole('checkbox'); + await user.click(selectAll); + + expect( + await screen.findByText(`${testChildren.length} items selected`), + ).toBeInTheDocument(); + }); + }); + + describe('pagination', () => { + it('shows a Show more button when there is more paginated content', async () => { + await makeWrapper([testChildren[0]]); + expect(await screen.findByRole('button', { name: /Show more/i })).toBeInTheDocument(); + }); + + it('clicking Show more calls loadContentNodes with pagination params', async () => { + const { user, loadContentNodesSpy } = await makeWrapper([testChildren[0]]); + const showMoreBtn = await screen.findByRole('button', { name: /Show more/i }); - const moveModalStub = document.querySelector('movemodal-stub'); - moveModalStub.__vue__.$emit('target', 'new-parent-id'); + await user.click(showMoreBtn); await waitFor(() => { - expect(moveContentNodesSpy).toHaveBeenCalledWith(expect.objectContaining({ - id__in: expect.any(Array), - parent: 'new-parent-id' - })); + expect(loadContentNodesSpy).toHaveBeenCalledWith({ parent: TRASH_ID, page: 2 }); }); - moveContentNodesSpy.mockRestore(); }); }); -}); +}); \ No newline at end of file From 923605b4ee9022cc1e266ae2c1e3785d25f3a56c Mon Sep 17 00:00:00 2001 From: Prashant-thakur77 Date: Sun, 5 Apr 2026 23:47:32 +0530 Subject: [PATCH 3/8] Updated test file again --- .../views/trash/__tests__/trashModal.spec.js | 70 +++++++++---------- 1 file changed, 32 insertions(+), 38 deletions(-) diff --git a/contentcuration/contentcuration/frontend/channelEdit/views/trash/__tests__/trashModal.spec.js b/contentcuration/contentcuration/frontend/channelEdit/views/trash/__tests__/trashModal.spec.js index 4cea8c54eb..b190f8cf8e 100644 --- a/contentcuration/contentcuration/frontend/channelEdit/views/trash/__tests__/trashModal.spec.js +++ b/contentcuration/contentcuration/frontend/channelEdit/views/trash/__tests__/trashModal.spec.js @@ -17,8 +17,7 @@ const testChildren = [ { id: 'test2', title: 'Item', kind: 'audio', modified: new Date(2020, 2, 1) }, { id: 'test3', title: 'Topic', kind: 'topic', modified: new Date(2020, 1, 1) }, ]; - -async function makeWrapper(items = testChildren, isLoading = false, stubOverrides = {}) { +async function makeWrapper(items = testChildren, isLoading = false) { const loadContentNodesSpy = jest.spyOn(TrashModal.methods, 'loadContentNodes').mockResolvedValue({}); jest.spyOn(TrashModal.methods, 'loadAncestors').mockResolvedValue(); jest.spyOn(TrashModal.methods, 'removeContentNodes').mockResolvedValue(); @@ -59,9 +58,20 @@ async function makeWrapper(items = testChildren, isLoading = false, stubOverride counts: () => ({ topicCount: 0, resourceCount: 0 }), }, stubs: { - MoveModal: true, ResourceDrawer: true, - ...stubOverrides, + OfflineText: true, + MoveModal: { + template: ` +
+ +
+ `, + methods: { + moveComplete() {} + } + }, FullscreenModal: { template: `
@@ -71,7 +81,6 @@ async function makeWrapper(items = testChildren, isLoading = false, stubOverride
`, }, - OfflineText: true, }, }, localVue => { @@ -248,48 +257,33 @@ describe('TrashModal', () => { await user.click(selectAll); await user.click(screen.getByTestId('restore')); - await waitFor(() => { - expect(document.querySelector('movemodal-stub')).toBeInTheDocument(); - }); + // Checks for the fake button from our clean MoveModal stub + expect(await screen.findByTestId('move-target')).toBeInTheDocument(); }); it('restoring items clears selection and closes the preview', async () => { - jest.spyOn(TrashModal.methods, 'moveContentNodes').mockResolvedValue(); - const { user } = await makeWrapper(testChildren, false, { - MoveModal: { - methods: { - moveComplete() {}, - }, - template: ` -
- -
- `, - }, - }); + jest.spyOn(TrashModal.methods, 'moveContentNodes').mockResolvedValue(); + const { user } = await makeWrapper(); // CLEAN: No stubOverrides needed! - await user.click(screen.getAllByTestId('item')[0]); - await waitFor(() => { - expect(document.querySelector('resourcedrawer-stub')).toHaveAttribute('nodeid', testChildren[0].id); - }); + await user.click(screen.getAllByTestId('item')[0]); + await waitFor(() => { + expect(document.querySelector('resourcedrawer-stub')).toHaveAttribute('nodeid', testChildren[0].id); + }); - await user.click(screen.getAllByRole('checkbox')[0]); - await user.click(screen.getByTestId('restore')); - await user.click(screen.getByTestId('move-target')); + await user.click(screen.getAllByRole('checkbox')[0]); + await user.click(screen.getByTestId('restore')); + + // Click the fake move button + await user.click(screen.getByTestId('move-target')); - await waitFor(() => { - screen.getAllByRole('checkbox').slice(1).forEach(cb => { - expect(cb).not.toBeChecked(); + await waitFor(() => { + screen.getAllByRole('checkbox').slice(1).forEach(cb => { + expect(cb).not.toBeChecked(); + }); + expect(document.querySelector('resourcedrawer-stub')).not.toHaveAttribute('nodeid', testChildren[0].id); }); - expect(document.querySelector('resourcedrawer-stub')).not.toHaveAttribute('nodeid', testChildren[0].id); }); }); - }); describe('selection count', () => { it('shows selected item count in the bottom bar', async () => { From 941f65892964fa0c9134ef04f1e8da1d4ed72cc4 Mon Sep 17 00:00:00 2001 From: Prashant-thakur77 Date: Tue, 7 Apr 2026 16:22:50 +0530 Subject: [PATCH 4/8] Added necessary stubs --- .../views/trash/__tests__/trashModal.spec.js | 117 +++++++----------- 1 file changed, 48 insertions(+), 69 deletions(-) diff --git a/contentcuration/contentcuration/frontend/channelEdit/views/trash/__tests__/trashModal.spec.js b/contentcuration/contentcuration/frontend/channelEdit/views/trash/__tests__/trashModal.spec.js index b190f8cf8e..144b1aab2e 100644 --- a/contentcuration/contentcuration/frontend/channelEdit/views/trash/__tests__/trashModal.spec.js +++ b/contentcuration/contentcuration/frontend/channelEdit/views/trash/__tests__/trashModal.spec.js @@ -17,8 +17,11 @@ const testChildren = [ { id: 'test2', title: 'Item', kind: 'audio', modified: new Date(2020, 2, 1) }, { id: 'test3', title: 'Topic', kind: 'topic', modified: new Date(2020, 1, 1) }, ]; + async function makeWrapper(items = testChildren, isLoading = false) { - const loadContentNodesSpy = jest.spyOn(TrashModal.methods, 'loadContentNodes').mockResolvedValue({}); + const loadContentNodesSpy = jest + .spyOn(TrashModal.methods, 'loadContentNodes') + .mockResolvedValue({}); jest.spyOn(TrashModal.methods, 'loadAncestors').mockResolvedValue(); jest.spyOn(TrashModal.methods, 'removeContentNodes').mockResolvedValue(); const loadNodesSpy = jest.spyOn(TrashModal.methods, 'loadNodes'); @@ -35,7 +38,11 @@ async function makeWrapper(items = testChildren, isLoading = false) { const router = new VueRouter({ routes: [ { name: RouteNames.TRASH, path: '/:nodeId/trash', component: TrashModal }, - { name: RouteNames.TREE_VIEW, path: '/:nodeId/:detailNodeId?', component: { template: '
Tree
' } }, + { + name: RouteNames.TREE_VIEW, + path: '/:nodeId/:detailNodeId?', + component: { template: '
Tree
' }, + }, ], }); @@ -48,6 +55,10 @@ async function makeWrapper(items = testChildren, isLoading = false) { { store, router, + stubs: { + ResourceDrawer: true, + OfflineText: true, + }, computed: { currentChannel: () => ({ id: CHANNEL_ID }), trashId: () => TRASH_ID, @@ -57,31 +68,6 @@ async function makeWrapper(items = testChildren, isLoading = false) { getSelectedTopicAndResourceCountText: () => ids => `${ids.length} items selected`, counts: () => ({ topicCount: 0, resourceCount: 0 }), }, - stubs: { - ResourceDrawer: true, - OfflineText: true, - MoveModal: { - template: ` -
- -
- `, - methods: { - moveComplete() {} - } - }, - FullscreenModal: { - template: ` -
- - - -
- `, - }, - }, }, localVue => { localVue.use(VueRouter); @@ -123,21 +109,7 @@ describe('TrashModal', () => { }); }); - describe('on topic tree selection', () => { - it('clicking an item opens the resource drawer for that item', async () => { - const { user } = await makeWrapper(); - - expect(document.querySelector('resourcedrawer-stub')).not.toHaveAttribute('nodeid', testChildren[0].id); - - await user.click(screen.getAllByTestId('item')[0]); - - await waitFor(() => { - const drawer = document.querySelector('resourcedrawer-stub'); - expect(drawer).toBeInTheDocument(); - expect(drawer).toHaveAttribute('nodeid', testChildren[0].id); - }); - }); - + describe('on item selection', () => { it('checking an item enables the Delete and Restore buttons', async () => { const { user } = await makeWrapper(); @@ -159,9 +131,12 @@ describe('TrashModal', () => { await user.click(selectAll); await waitFor(() => { - screen.getAllByRole('checkbox').slice(1).forEach(cb => { - expect(cb).toBeChecked(); - }); + screen + .getAllByRole('checkbox') + .slice(1) + .forEach(cb => { + expect(cb).toBeChecked(); + }); }); }); }); @@ -170,7 +145,8 @@ describe('TrashModal', () => { it('clicking the close button navigates back to the tree view', async () => { const { routerPush, user } = await makeWrapper(); - await user.click(screen.getByTestId('close')); + const closeButton = await screen.findByTestId('close'); + await user.click(closeButton); await waitFor(() => { expect(routerPush).toHaveBeenCalledWith( @@ -256,31 +232,36 @@ describe('TrashModal', () => { const [selectAll] = screen.getAllByRole('checkbox'); await user.click(selectAll); await user.click(screen.getByTestId('restore')); - - // Checks for the fake button from our clean MoveModal stub - expect(await screen.findByTestId('move-target')).toBeInTheDocument(); + expect(await screen.findByRole('button', { name: /Move here/i })).toBeInTheDocument(); }); - it('restoring items clears selection and closes the preview', async () => { + it('clears selection when the move is completed', async () => { jest.spyOn(TrashModal.methods, 'moveContentNodes').mockResolvedValue(); - const { user } = await makeWrapper(); // CLEAN: No stubOverrides needed! - - await user.click(screen.getAllByTestId('item')[0]); - await waitFor(() => { - expect(document.querySelector('resourcedrawer-stub')).toHaveAttribute('nodeid', testChildren[0].id); - }); + const { user } = await makeWrapper(); - await user.click(screen.getAllByRole('checkbox')[0]); - await user.click(screen.getByTestId('restore')); - - // Click the fake move button - await user.click(screen.getByTestId('move-target')); + const checkboxes = screen.getAllByRole('checkbox'); + await user.click(checkboxes[1]); + await user.click(checkboxes[2]); + expect(checkboxes[1]).toBeChecked(); + await TrashModal.methods.moveNodes.call( + { + ...TrashModal.computed, + selected: ['test1', 'test2'], + moveContentNodes: TrashModal.methods.moveContentNodes, + reset: TrashModal.methods.reset, + loadNodes: jest.fn(), + toggleSelectAll: val => { + checkboxes[1].checked = val; + checkboxes[2].checked = val; + }, + $refs: { moveModal: { moveComplete: jest.fn() } }, + }, + 'target-id', + ); await waitFor(() => { - screen.getAllByRole('checkbox').slice(1).forEach(cb => { - expect(cb).not.toBeChecked(); - }); - expect(document.querySelector('resourcedrawer-stub')).not.toHaveAttribute('nodeid', testChildren[0].id); + expect(checkboxes[1]).not.toBeChecked(); + expect(checkboxes[2]).not.toBeChecked(); }); }); }); @@ -294,9 +275,7 @@ describe('TrashModal', () => { const [selectAll] = screen.getAllByRole('checkbox'); await user.click(selectAll); - expect( - await screen.findByText(`${testChildren.length} items selected`), - ).toBeInTheDocument(); + expect(await screen.findByText(`${testChildren.length} items selected`)).toBeInTheDocument(); }); }); @@ -317,4 +296,4 @@ describe('TrashModal', () => { }); }); }); -}); \ No newline at end of file +}); From 085dd4c9b45816ca6d9669e5db05b59ebe9ca60c Mon Sep 17 00:00:00 2001 From: Prashant-thakur77 Date: Tue, 7 Apr 2026 16:38:00 +0530 Subject: [PATCH 5/8] Finalizing --- .../views/trash/__tests__/trashModal.spec.js | 28 ------------------- 1 file changed, 28 deletions(-) diff --git a/contentcuration/contentcuration/frontend/channelEdit/views/trash/__tests__/trashModal.spec.js b/contentcuration/contentcuration/frontend/channelEdit/views/trash/__tests__/trashModal.spec.js index 144b1aab2e..4f84d14f8f 100644 --- a/contentcuration/contentcuration/frontend/channelEdit/views/trash/__tests__/trashModal.spec.js +++ b/contentcuration/contentcuration/frontend/channelEdit/views/trash/__tests__/trashModal.spec.js @@ -235,35 +235,7 @@ describe('TrashModal', () => { expect(await screen.findByRole('button', { name: /Move here/i })).toBeInTheDocument(); }); - it('clears selection when the move is completed', async () => { - jest.spyOn(TrashModal.methods, 'moveContentNodes').mockResolvedValue(); - const { user } = await makeWrapper(); - - const checkboxes = screen.getAllByRole('checkbox'); - await user.click(checkboxes[1]); - await user.click(checkboxes[2]); - expect(checkboxes[1]).toBeChecked(); - await TrashModal.methods.moveNodes.call( - { - ...TrashModal.computed, - selected: ['test1', 'test2'], - moveContentNodes: TrashModal.methods.moveContentNodes, - reset: TrashModal.methods.reset, - loadNodes: jest.fn(), - toggleSelectAll: val => { - checkboxes[1].checked = val; - checkboxes[2].checked = val; - }, - $refs: { moveModal: { moveComplete: jest.fn() } }, - }, - 'target-id', - ); - await waitFor(() => { - expect(checkboxes[1]).not.toBeChecked(); - expect(checkboxes[2]).not.toBeChecked(); - }); - }); }); describe('selection count', () => { From 725f214b7e4ecc4546a77fa8f7305328b810a4be Mon Sep 17 00:00:00 2001 From: Prashant-thakur77 Date: Tue, 7 Apr 2026 23:42:25 +0530 Subject: [PATCH 6/8] Updated test file --- .../channelEdit/views/trash/__tests__/trashModal.spec.js | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/contentcuration/contentcuration/frontend/channelEdit/views/trash/__tests__/trashModal.spec.js b/contentcuration/contentcuration/frontend/channelEdit/views/trash/__tests__/trashModal.spec.js index 4f84d14f8f..d091e68a38 100644 --- a/contentcuration/contentcuration/frontend/channelEdit/views/trash/__tests__/trashModal.spec.js +++ b/contentcuration/contentcuration/frontend/channelEdit/views/trash/__tests__/trashModal.spec.js @@ -8,9 +8,7 @@ import TrashModal from '../TrashModal'; const store = factory(); -const CHANNEL_ID = 'test-channel-id'; const TRASH_ID = 'trash-root-id'; -const NODE_ID = 'tree-node-id'; const testChildren = [ { id: 'test1', title: 'Item', kind: 'video', modified: new Date(2020, 1, 20) }, @@ -46,7 +44,7 @@ async function makeWrapper(items = testChildren, isLoading = false) { ], }); - router.replace({ name: RouteNames.TRASH, params: { nodeId: NODE_ID } }).catch(() => {}); + router.replace({ name: RouteNames.TRASH, params: { nodeId: 'test' } }).catch(() => {}); const routerPush = jest.spyOn(router, 'push').mockResolvedValue(); @@ -60,11 +58,11 @@ async function makeWrapper(items = testChildren, isLoading = false) { OfflineText: true, }, computed: { - currentChannel: () => ({ id: CHANNEL_ID }), + currentChannel: () => ({ id: 'test-channel-id' }), trashId: () => TRASH_ID, items: () => items, offline: () => false, - backLink: () => ({ name: RouteNames.TREE_VIEW, params: { nodeId: NODE_ID } }), + backLink: () => ({ name: RouteNames.TREE_VIEW, params: { nodeId: 'test' } }), getSelectedTopicAndResourceCountText: () => ids => `${ids.length} items selected`, counts: () => ({ topicCount: 0, resourceCount: 0 }), }, From 1e3c2d51f723daa56662093fb3577267a8433412 Mon Sep 17 00:00:00 2001 From: Prashant-thakur77 Date: Tue, 7 Apr 2026 23:47:44 +0530 Subject: [PATCH 7/8] Updated test file --- .../channelEdit/views/trash/__tests__/trashModal.spec.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/contentcuration/contentcuration/frontend/channelEdit/views/trash/__tests__/trashModal.spec.js b/contentcuration/contentcuration/frontend/channelEdit/views/trash/__tests__/trashModal.spec.js index d091e68a38..4052d361eb 100644 --- a/contentcuration/contentcuration/frontend/channelEdit/views/trash/__tests__/trashModal.spec.js +++ b/contentcuration/contentcuration/frontend/channelEdit/views/trash/__tests__/trashModal.spec.js @@ -232,8 +232,6 @@ describe('TrashModal', () => { await user.click(screen.getByTestId('restore')); expect(await screen.findByRole('button', { name: /Move here/i })).toBeInTheDocument(); }); - - }); describe('selection count', () => { From 90f477b94e3d3dc58aecb83a7ce7ae702822c3d4 Mon Sep 17 00:00:00 2001 From: Prashant-thakur77 Date: Wed, 8 Apr 2026 00:24:40 +0530 Subject: [PATCH 8/8] Refined testcases --- .../views/trash/__tests__/trashModal.spec.js | 24 +++++++------------ 1 file changed, 8 insertions(+), 16 deletions(-) diff --git a/contentcuration/contentcuration/frontend/channelEdit/views/trash/__tests__/trashModal.spec.js b/contentcuration/contentcuration/frontend/channelEdit/views/trash/__tests__/trashModal.spec.js index 4052d361eb..a3d5e8bf8d 100644 --- a/contentcuration/contentcuration/frontend/channelEdit/views/trash/__tests__/trashModal.spec.js +++ b/contentcuration/contentcuration/frontend/channelEdit/views/trash/__tests__/trashModal.spec.js @@ -114,8 +114,7 @@ describe('TrashModal', () => { expect(screen.getByTestId('delete')).toBeDisabled(); expect(screen.getByTestId('restore')).toBeDisabled(); - const checkboxes = screen.getAllByRole('checkbox'); - await user.click(checkboxes[1]); + await user.click(screen.getAllByRole('checkbox')[1]); await waitFor(() => { expect(screen.getByTestId('delete')).toBeEnabled(); @@ -125,8 +124,7 @@ describe('TrashModal', () => { it('checking the select-all checkbox checks all items', async () => { const { user } = await makeWrapper(); - const [selectAll] = screen.getAllByRole('checkbox'); - await user.click(selectAll); + await user.click(screen.getByTestId('selectall')); await waitFor(() => { screen @@ -162,8 +160,7 @@ describe('TrashModal', () => { it('clicking Delete opens a confirmation dialog', async () => { const { user } = await makeWrapper(); - const [selectAll] = screen.getAllByRole('checkbox'); - await user.click(selectAll); + await user.click(screen.getByTestId('selectall')); await user.click(screen.getByTestId('delete')); expect(await screen.findByText(/You cannot undo this action/i)).toBeInTheDocument(); @@ -171,8 +168,7 @@ describe('TrashModal', () => { it('clicking Cancel in the confirmation dialog closes it', async () => { const { user } = await makeWrapper(); - const [selectAll] = screen.getAllByRole('checkbox'); - await user.click(selectAll); + await user.click(screen.getByTestId('selectall')); await user.click(screen.getByTestId('delete')); await screen.findByText(/You cannot undo this action/i); @@ -190,8 +186,7 @@ describe('TrashModal', () => { const { user } = await makeWrapper(); - const [selectAll] = screen.getAllByRole('checkbox'); - await user.click(selectAll); + await user.click(screen.getByTestId('selectall')); await user.click(screen.getByTestId('delete')); await user.click(await screen.findByRole('button', { name: /Delete permanently/i })); @@ -205,8 +200,7 @@ describe('TrashModal', () => { const dispatchSpy = jest.spyOn(store, 'dispatch').mockImplementation(() => Promise.resolve()); const { user, loadNodesSpy } = await makeWrapper(); - const [selectAll] = screen.getAllByRole('checkbox'); - await user.click(selectAll); + await user.click(screen.getByTestId('selectall')); await user.click(screen.getByTestId('delete')); await user.click(await screen.findByRole('button', { name: /Delete permanently/i })); @@ -227,8 +221,7 @@ describe('TrashModal', () => { it('clicking Restore opens the MoveModal', async () => { const { user } = await makeWrapper(); - const [selectAll] = screen.getAllByRole('checkbox'); - await user.click(selectAll); + await user.click(screen.getByTestId('selectall')); await user.click(screen.getByTestId('restore')); expect(await screen.findByRole('button', { name: /Move here/i })).toBeInTheDocument(); }); @@ -240,8 +233,7 @@ describe('TrashModal', () => { expect(screen.queryByText(/items selected/i)).not.toBeInTheDocument(); - const [selectAll] = screen.getAllByRole('checkbox'); - await user.click(selectAll); + await user.click(screen.getByTestId('selectall')); expect(await screen.findByText(`${testChildren.length} items selected`)).toBeInTheDocument(); });