From bd82c1d33dff8073a58f8e8f0fc6d28cf7ad5901 Mon Sep 17 00:00:00 2001 From: Navin Karkera Date: Mon, 3 Nov 2025 20:31:30 +0530 Subject: [PATCH] fix: publish status of container on adding new children (#2587) Updates publish status of container when adding new child components to a unit or other containers. --- .../ConfirmationView.tsx | 1 + .../LegacyLibMigrationPage.test.tsx | 62 +++++++++++++------ src/legacy-libraries-migration/messages.ts | 14 +++-- src/library-authoring/data/apiHooks.test.tsx | 9 +-- src/library-authoring/data/apiHooks.ts | 2 + 5 files changed, 58 insertions(+), 30 deletions(-) diff --git a/src/legacy-libraries-migration/ConfirmationView.tsx b/src/legacy-libraries-migration/ConfirmationView.tsx index 6cb8e025e..99acf23c3 100644 --- a/src/legacy-libraries-migration/ConfirmationView.tsx +++ b/src/legacy-libraries-migration/ConfirmationView.tsx @@ -81,6 +81,7 @@ export const ConfirmationView = ({ {legacyLibraries.map((legacyLib) => ( diff --git a/src/legacy-libraries-migration/LegacyLibMigrationPage.test.tsx b/src/legacy-libraries-migration/LegacyLibMigrationPage.test.tsx index 79110706a..dea7ab7ef 100644 --- a/src/legacy-libraries-migration/LegacyLibMigrationPage.test.tsx +++ b/src/legacy-libraries-migration/LegacyLibMigrationPage.test.tsx @@ -6,6 +6,7 @@ import { render, screen, waitFor, + within, } from '@src/testUtils'; import studioHomeMock from '@src/studio-home/__mocks__/studioHomeMock'; import { mockGetContentLibraryV2List } from '@src/library-authoring/data/api.mocks'; @@ -184,7 +185,7 @@ describe('', () => { nextButton.click(); // Should show alert of SelectDestinationView - expect(await screen.findByText(/any legacy libraries that are used/i)).toBeInTheDocument(); + expect(await screen.findByText(/you selected will be migrated to this new library/i)).toBeInTheDocument(); const backButton = screen.getByRole('button', { name: /back/i }); backButton.click(); @@ -210,7 +211,7 @@ describe('', () => { nextButton.click(); // Should show alert of SelectDestinationView - expect(await screen.findByText(/any legacy libraries that are used/i)).toBeInTheDocument(); + expect(await screen.findByText(/you selected will be migrated to this new library/i)).toBeInTheDocument(); // The next button is disabled expect(nextButton).toBeDisabled(); @@ -224,24 +225,31 @@ describe('', () => { }); it('should back to select library destination', async () => { + const user = userEvent.setup(); renderPage(); expect(await screen.findByText('Migrate Legacy Libraries')).toBeInTheDocument(); expect(await screen.findByText('MBA')).toBeInTheDocument(); const legacyLibrary = screen.getByRole('checkbox', { name: 'MBA' }); - legacyLibrary.click(); + await user.click(legacyLibrary); - const nextButton = screen.getByRole('button', { name: /next/i }); - nextButton.click(); + const nextButton = await screen.findByRole('button', { name: /next/i }); + await user.click(nextButton); // Should show alert of SelectDestinationView - expect(await screen.findByText(/any legacy libraries that are used/i)).toBeInTheDocument(); + expect(await screen.findByText(/you selected will be migrated to this new library/i)).toBeInTheDocument(); expect(await screen.findByText('Test Library 1')).toBeInTheDocument(); const radioButton = screen.getByRole('radio', { name: /test library 1/i }); - radioButton.click(); + await user.click(radioButton); - nextButton.click(); - expect(await screen.findByText(/these 1 legacy library will be migrated to/i)).toBeInTheDocument(); + await user.click(nextButton); + const alert = await screen.findByRole('alert'); + expect(await within(alert).findByText( + /All content from the 1 legacy library you selected will be migrated to/i, + )).toBeInTheDocument(); + expect(await within(alert).findByText( + /test library 1/i, + )).toBeInTheDocument(); const backButton = screen.getByRole('button', { name: /back/i }); backButton.click(); @@ -269,7 +277,7 @@ describe('', () => { nextButton.click(); // Should show alert of SelectDestinationView - expect(await screen.findByText(/any legacy libraries that are used/i)).toBeInTheDocument(); + expect(await screen.findByText(/you selected will be migrated to this new library/i)).toBeInTheDocument(); const createButton = await screen.findByRole('button', { name: /create new library/i }); expect(createButton).toBeInTheDocument(); @@ -336,18 +344,24 @@ describe('', () => { legacyLibrary3.click(); const nextButton = screen.getByRole('button', { name: /next/i }); - nextButton.click(); + await user.click(nextButton); // Should show alert of SelectDestinationView - expect(await screen.findByText(/any legacy libraries that are used/i)).toBeInTheDocument(); + expect(await screen.findByText(/you selected will be migrated to this new library/i)).toBeInTheDocument(); expect(await screen.findByText('Test Library 1')).toBeInTheDocument(); const radioButton = screen.getByRole('radio', { name: /test library 1/i }); - radioButton.click(); + await user.click(radioButton); - nextButton.click(); + await user.click(nextButton); // Should show alert of ConfirmationView - expect(await screen.findByText(/these 3 legacy libraries will be migrated to/i)).toBeInTheDocument(); + const alert = await screen.findByRole('alert'); + expect(await within(alert).findByText( + /All content from the 3 legacy libraries you selected will be migrated to/i, + )).toBeInTheDocument(); + expect(await within(alert).findByText( + /test library 1/i, + )).toBeInTheDocument(); expect(screen.getByText('MBA')).toBeInTheDocument(); expect(screen.getByText('Legacy library 1')).toBeInTheDocument(); expect(screen.getByText('MBA 1')).toBeInTheDocument(); @@ -390,18 +404,26 @@ describe('', () => { legacyLibrary3.click(); const nextButton = screen.getByRole('button', { name: /next/i }); - nextButton.click(); + await user.click(nextButton); // Should show alert of SelectDestinationView - expect(await screen.findByText(/any legacy libraries that are used/i)).toBeInTheDocument(); + expect(await screen.findByText(/you selected will be migrated to this new library/i)).toBeInTheDocument(); expect(await screen.findByText('Test Library 1')).toBeInTheDocument(); const radioButton = screen.getByRole('radio', { name: /test library 1/i }); - radioButton.click(); + await user.click(radioButton); - nextButton.click(); + await user.click(nextButton); // Should show alert of ConfirmationView - expect(await screen.findByText(/these 3 legacy libraries will be migrated to/i)).toBeInTheDocument(); + const alert = await screen.findByRole('alert'); + expect(await within(alert).findByText( + /All content from the 3 legacy libraries you selected will be migrated to /i, + { exact: false }, + )).toBeInTheDocument(); + expect(await within(alert).findByText( + /test library 1/i, + { exact: false }, + )).toBeInTheDocument(); expect(screen.getByText('MBA')).toBeInTheDocument(); expect(screen.getByText('Legacy library 1')).toBeInTheDocument(); expect(screen.getByText('MBA 1')).toBeInTheDocument(); diff --git a/src/legacy-libraries-migration/messages.ts b/src/legacy-libraries-migration/messages.ts index e7322d9a7..eaf1a2168 100644 --- a/src/legacy-libraries-migration/messages.ts +++ b/src/legacy-libraries-migration/messages.ts @@ -65,16 +65,18 @@ const messages = defineMessages({ id: 'legacy-libraries-migration.select-destination.alert.text', defaultMessage: 'All content from the' + ' {count, plural, one {{count} legacy library} other {{count} legacy libraries}} you selected will' - + ' be migrated to this new library, organized into collections. Any legacy libraries that are used in' - + ' problem banks will maintain their link with migrated content the first time they are migrated.', + + ' be migrated to this new library, organized into collections. Legacy library content used in courses will' + + ' continue to work as-is. To receive any future changes to migrated content, you must update these' + + ' references within your course.', description: 'Alert text in the select destination step of the legacy libraries migration page.', }, confirmationViewAlert: { id: 'legacy-libraries-migration.select-destination.alert.text', - defaultMessage: 'These {count, plural, one {{count} legacy library} other {{count} legacy libraries}}' - + ' will be migrated to {libraryName} and organized as collections. Legacy library content used' - + ' in courses will continue to work as-is. To receive any future changes to migrated content,' - + ' you must update these references within your course.', + defaultMessage: 'All content from the' + + ' {count, plural, one {{count} legacy library} other {{count} legacy libraries}} you selected will' + + ' be migrated to {libraryName}, organized into collections. Legacy library content used in courses will' + + ' continue to work as-is. To receive any future changes to migrated content, you must update these' + + ' references within your course.', description: 'Alert text in the confirmation step of the legacy libraries migration page.', }, previouslyMigratedAlert: { diff --git a/src/library-authoring/data/apiHooks.test.tsx b/src/library-authoring/data/apiHooks.test.tsx index df5d5166a..ba6a3ccf4 100644 --- a/src/library-authoring/data/apiHooks.test.tsx +++ b/src/library-authoring/data/apiHooks.test.tsx @@ -329,10 +329,11 @@ describe('library api hooks', () => { // Keys should be invalidated: // 1. library // 2. containerChildren - // 3. containerHierarchy - // 4 & 5. subsections - // 6 all hierarchies - expect(spy).toHaveBeenCalledTimes(6); + // 3. container + // 4. containerHierarchy + // 5 & 6. subsections + // 7 all hierarchies + expect(spy).toHaveBeenCalledTimes(7); }); describe('publishContainer', () => { diff --git a/src/library-authoring/data/apiHooks.ts b/src/library-authoring/data/apiHooks.ts index dca9de9d6..5646d2f6b 100644 --- a/src/library-authoring/data/apiHooks.ts +++ b/src/library-authoring/data/apiHooks.ts @@ -817,6 +817,8 @@ export const useAddItemsToContainer = (containerId?: string) => { // It would be complex to bring the entire hierarchy and only update the items within that hierarchy. queryClient.invalidateQueries({ queryKey: libraryAuthoringQueryKeys.containerHierarchy(undefined) }); queryClient.invalidateQueries({ queryKey: xblockQueryKeys.componentHierarchy(undefined) }); + // Invalidate the container to update its publish status + queryClient.invalidateQueries({ queryKey: libraryAuthoringQueryKeys.container(containerId) }); const containerType = getBlockType(containerId); if (containerType === 'section') {