fix: Nits on the style of library icon [FC-0114] (#2863)

This commit is contained in:
Chris Chávez
2026-02-09 11:59:24 -05:00
committed by GitHub
parent bb6b2ab33c
commit a16087a1d0
5 changed files with 89 additions and 86 deletions

View File

@@ -305,38 +305,36 @@ describe('<CourseUnit />', () => {
const user = userEvent.setup();
render(<RootWrapper />);
await waitFor(async () => {
const iframe = screen.getByTitle(xblockContainerIframeMessages.xblockIframeTitle.defaultMessage);
expect(iframe).toHaveAttribute(
'aria-label',
xblockContainerIframeMessages.xblockIframeLabel.defaultMessage
.replace('{xblockCount}', courseVerticalChildrenMock.children.length),
);
const iframe = await screen.findByTitle(xblockContainerIframeMessages.xblockIframeTitle.defaultMessage);
expect(iframe).toHaveAttribute(
'aria-label',
xblockContainerIframeMessages.xblockIframeLabel.defaultMessage
.replace('{xblockCount}', courseVerticalChildrenMock.children.length),
);
simulatePostMessageEvent(messageTypes.deleteXBlock, {
usageId: courseVerticalChildrenMock.children[0].block_id,
});
expect(screen.getByText(/Delete this component?/i)).toBeInTheDocument();
expect(screen.getByText(/Deleting this component is permanent and cannot be undone./i)).toBeInTheDocument();
const dialog = screen.getByRole('dialog');
expect(dialog).toBeInTheDocument();
// Find the Cancel and Delete buttons within the iframe by their specific classes
const cancelButton = await within(dialog).findByRole('button', { name: /Cancel/i });
const deleteButton = await within(dialog).findByRole('button', { name: /Delete/i });
expect(cancelButton).toBeInTheDocument();
simulatePostMessageEvent(messageTypes.deleteXBlock, {
usageId: courseVerticalChildrenMock.children[0].block_id,
});
expect(screen.getByRole('dialog')).toBeInTheDocument();
await user.click(deleteButton);
simulatePostMessageEvent(messageTypes.deleteXBlock, {
usageId: courseVerticalChildrenMock.children[0].block_id,
});
expect(await screen.findByText(/Delete this component?/i)).toBeInTheDocument();
expect(await screen.findByText(/Deleting this component is permanent and cannot be undone./i)).toBeInTheDocument();
const dialog = await screen.findByRole('dialog');
expect(dialog).toBeInTheDocument();
// Find the Cancel and Delete buttons within the iframe by their specific classes
const cancelButton = await within(dialog).findByRole('button', { name: /Cancel/i });
const deleteButton = await within(dialog).findByRole('button', { name: /Delete/i });
expect(cancelButton).toBeInTheDocument();
simulatePostMessageEvent(messageTypes.deleteXBlock, {
usageId: courseVerticalChildrenMock.children[0].block_id,
});
expect(await screen.findByRole('dialog')).toBeInTheDocument();
await user.click(deleteButton);
axiosMock
.onPost(getXBlockBaseApiUrl(blockId), {
publish: PUBLISH_TYPES.makePublic,
@@ -355,17 +353,17 @@ describe('<CourseUnit />', () => {
});
await executeThunk(editCourseUnitVisibilityAndData(blockId, PUBLISH_TYPES.makePublic, true), store.dispatch);
await waitFor(() => {
// check if the sidebar status is Published and Live
expect(screen.getByText(legacySidebarMessages.sidebarTitlePublishedAndLive.defaultMessage)).toBeInTheDocument();
expect(screen.getByText(
unitInfoMessages.publishLastPublished.defaultMessage
.replace('{publishedOn}', courseSectionVerticalMock.xblock_info.published_on)
.replace('{publishedBy}', userName),
)).toBeInTheDocument();
expect(screen.queryByRole('button', { name: legacySidebarMessages.actionButtonPublishTitle.defaultMessage })).not.toBeInTheDocument();
expect(screen.getByText(unitDisplayName)).toBeInTheDocument();
});
// check if the sidebar status is Published and Live
expect(await screen.findByText(
legacySidebarMessages.sidebarTitlePublishedAndLive.defaultMessage,
)).toBeInTheDocument();
expect(await screen.findByText(
unitInfoMessages.publishLastPublished.defaultMessage
.replace('{publishedOn}', courseSectionVerticalMock.xblock_info.published_on)
.replace('{publishedBy}', userName),
)).toBeInTheDocument();
expect(screen.queryByRole('button', { name: legacySidebarMessages.actionButtonPublishTitle.defaultMessage })).not.toBeInTheDocument();
expect(await screen.findByText(unitDisplayName)).toBeInTheDocument();
axiosMock
.onDelete(getXBlockBaseApiUrl(courseVerticalChildrenMock.children[0].block_id))
@@ -397,35 +395,34 @@ describe('<CourseUnit />', () => {
.reply(200, courseSectionVerticalMock);
await executeThunk(editCourseUnitVisibilityAndData(blockId, PUBLISH_TYPES.makePublic, true), store.dispatch);
await waitFor(() => {
const iframe = screen.getByTitle(xblockContainerIframeMessages.xblockIframeTitle.defaultMessage);
expect(iframe).toHaveAttribute(
'aria-label',
xblockContainerIframeMessages.xblockIframeLabel.defaultMessage
.replace('{xblockCount}', updatedCourseVerticalChildren.length),
);
// after removing the xblock, the sidebar status changes to Draft (unpublished changes)
expect(screen.getByText(
legacySidebarMessages.sidebarTitleDraftUnpublishedChanges.defaultMessage,
)).toBeInTheDocument();
expect(screen.getByText(legacySidebarMessages.releaseStatusTitle.defaultMessage)).toBeInTheDocument();
expect(screen.getByText(unitInfoMessages.visibilityVisibleToTitle.defaultMessage)).toBeInTheDocument();
expect(screen.getByText(unitInfoMessages.visibilityCheckboxTitle.defaultMessage)).toBeInTheDocument();
expect(screen.getByText(legacySidebarMessages.actionButtonPublishTitle.defaultMessage)).toBeInTheDocument();
expect(screen.getByText(
legacySidebarMessages.actionButtonDiscardChangesTitle.defaultMessage,
)).toBeInTheDocument();
expect(screen.getByText(courseSectionVerticalMock.xblock_info.release_date)).toBeInTheDocument();
expect(screen.getByText(
unitInfoMessages.publishInfoDraftSaved.defaultMessage
.replace('{editedOn}', courseSectionVerticalMock.xblock_info.edited_on)
.replace('{editedBy}', courseSectionVerticalMock.xblock_info.edited_by),
)).toBeInTheDocument();
expect(screen.getByText(
legacySidebarMessages.releaseInfoWithSection.defaultMessage
.replace('{sectionName}', courseSectionVerticalMock.xblock_info.release_date_from),
)).toBeInTheDocument();
});
expect(await screen.findByTitle(
xblockContainerIframeMessages.xblockIframeTitle.defaultMessage,
)).toHaveAttribute(
'aria-label',
xblockContainerIframeMessages.xblockIframeLabel.defaultMessage
.replace('{xblockCount}', updatedCourseVerticalChildren.length),
);
// after removing the xblock, the sidebar status changes to Draft (unpublished changes)
expect(await screen.findByText(
legacySidebarMessages.sidebarTitleDraftUnpublishedChanges.defaultMessage,
)).toBeInTheDocument();
expect(await screen.findByText(legacySidebarMessages.releaseStatusTitle.defaultMessage)).toBeInTheDocument();
expect(await screen.findByText(unitInfoMessages.visibilityVisibleToTitle.defaultMessage)).toBeInTheDocument();
expect(await screen.findByText(unitInfoMessages.visibilityCheckboxTitle.defaultMessage)).toBeInTheDocument();
expect(await screen.findByText(legacySidebarMessages.actionButtonPublishTitle.defaultMessage)).toBeInTheDocument();
expect(await screen.findByText(
legacySidebarMessages.actionButtonDiscardChangesTitle.defaultMessage,
)).toBeInTheDocument();
expect(await screen.findByText(courseSectionVerticalMock.xblock_info.release_date)).toBeInTheDocument();
expect(await screen.findByText(
unitInfoMessages.publishInfoDraftSaved.defaultMessage
.replace('{editedOn}', courseSectionVerticalMock.xblock_info.edited_on)
.replace('{editedBy}', courseSectionVerticalMock.xblock_info.edited_by),
)).toBeInTheDocument();
expect(await screen.findByText(
legacySidebarMessages.releaseInfoWithSection.defaultMessage
.replace('{sectionName}', courseSectionVerticalMock.xblock_info.release_date_from),
)).toBeInTheDocument();
});
it('checks if the xblock unlink is called when the corresponding unlink button is clicked', async () => {

View File

@@ -45,3 +45,9 @@
height: 18px;
}
}
.upstream-info-tooltip {
.tooltip-inner {
background-color: var(--pgn-color-primary-700);
}
}

View File

@@ -25,8 +25,8 @@ describe('<UpstreamInfoIcon>', () => {
downstreamCustomized: [],
upstreamName: 'Upstream',
});
expect(screen.getByTitle('This item is linked to a library item.')).toBeInTheDocument();
expect(screen.queryByTitle('The linked library object has updates available.')).not.toBeInTheDocument();
expect(screen.getByTitle('This item is linked to a library item')).toBeInTheDocument();
expect(screen.queryByTitle('The linked library object has updates available')).not.toBeInTheDocument();
});
it('should render with broken link', () => {
@@ -37,8 +37,8 @@ describe('<UpstreamInfoIcon>', () => {
downstreamCustomized: [],
upstreamName: 'Upstream',
});
expect(screen.getByTitle('This item is linked to a library item.')).toBeInTheDocument();
expect(screen.getByTitle('The referenced library or library object is not available.')).toBeInTheDocument();
expect(screen.getByTitle('This item is linked to a library item')).toBeInTheDocument();
expect(screen.getByTitle('The referenced library or library object is not available')).toBeInTheDocument();
});
it('should render with ready to sync link and opens the sync modal', async () => {
@@ -50,9 +50,9 @@ describe('<UpstreamInfoIcon>', () => {
upstreamName: 'Upstream',
});
const icon = screen.getByTitle('This item is linked to a library item.');
const icon = screen.getByTitle('This item is linked to a library item');
expect(icon).toBeInTheDocument();
expect(screen.getByTitle('The linked library object has updates available.')).toBeInTheDocument();
expect(screen.getByTitle('The linked library object has updates available')).toBeInTheDocument();
fireEvent.click(icon);
await waitFor(() => expect(mockOpenSyncModal).toHaveBeenCalled());
@@ -67,8 +67,8 @@ describe('<UpstreamInfoIcon>', () => {
upstreamName: 'Upstream',
});
expect(screen.getByTitle('This item is linked to a library item.')).toBeInTheDocument();
expect(screen.getByTitle('This library reference has course overrides applied.')).toBeInTheDocument();
expect(screen.getByTitle('This item is linked to a library item')).toBeInTheDocument();
expect(screen.getByTitle('This library reference has course overrides applied')).toBeInTheDocument();
});
it('should render with ready to sync and course overrides', () => {
@@ -80,9 +80,9 @@ describe('<UpstreamInfoIcon>', () => {
upstreamName: 'Upstream',
});
expect(screen.getByTitle('This item is linked to a library item.')).toBeInTheDocument();
expect(screen.queryByTitle('This library reference has course overrides applied.')).not.toBeInTheDocument();
expect(screen.getByTitle('The linked library object has updates available.')).toBeInTheDocument();
expect(screen.getByTitle('This item is linked to a library item')).toBeInTheDocument();
expect(screen.queryByTitle('This library reference has course overrides applied')).not.toBeInTheDocument();
expect(screen.getByTitle('The linked library object has updates available')).toBeInTheDocument();
});
it('should render null without upstream', () => {

View File

@@ -84,7 +84,7 @@ const UpstreamInfoIconContent = ({
key={`upstream-icon-${upstreamInfo.upstreamRef}`}
placement="top"
overlay={(
<Tooltip id={`upstream-icon-tooltip-${upstreamInfo.upstreamRef}`}>
<Tooltip className="upstream-info-tooltip" id={`upstream-icon-tooltip-${upstreamInfo.upstreamRef}`}>
{tooltipMessage}
</Tooltip>
)}

View File

@@ -2,27 +2,27 @@ import { defineMessages } from '@edx/frontend-platform/i18n';
const messages = defineMessages({
upstreamLinkOk: {
defaultMessage: 'This item is linked to a library item.',
defaultMessage: 'This item is linked to a library item',
id: 'upstream-icon.ok',
description: 'Hint and aria-label for the upstream icon when the link is valid.',
},
upstreamLinkError: {
defaultMessage: 'The referenced library or library object is not available.',
defaultMessage: 'The referenced library or library object is not available',
id: 'upstream-icon.error',
description: 'Hint and aria-label for the upstream icon when the link is broken.',
},
upstreamLinkReadyToSyncAriaLabel: {
defaultMessage: 'The linked library object has updates available.',
defaultMessage: 'The linked library object has updates available',
id: 'upstream-icon.ready-to-sync.aria-label',
description: 'Hint and aria-label for the upstream icon when the link is ready to sync.',
},
upstreamLinkReadyToSyncTooltip: {
defaultMessage: 'The linked <b>{upstreamName}</b> has updates available.',
defaultMessage: 'The linked <b>{upstreamName}</b> has updates available',
id: 'upstream-icon.ready-to-sync.tooltip',
description: 'Tooltip text for the upstream icon when the link is ready to sync.',
},
upstreamLinkOverridesAriaLabel: {
defaultMessage: 'This library reference has course overrides applied.',
defaultMessage: 'This library reference has course overrides applied',
id: 'upstream-icon.course-overrides.aria-label',
description: 'Hint and aria-label for the upstream icon when the link has course overrides.',
},