Add SR messages to bulk module publishing

closes LS-3955
flag=module_publish_menu

test plan:
  - with the SR on
  - with a couple modules with items
  - publish/unpublish all with items
  - click "Continue" in the modal
  > expect the Continue button to change to Stop Publishing
  > expect teh SR to tell you what happens if you click it
  > expect a SR message once progress is > 0

  - repeat, but refresh the page before publish completes
  > expect progress SR messages as the publish continues
    to completion

Change-Id: I422e32af802dd45563bc850433a38952bfb79d7f
Reviewed-on: https://gerrit.instructure.com/c/canvas-lms/+/316655
Tested-by: Service Cloud Jenkins <svc.cloudjenkins@instructure.com>
Reviewed-by: Robin Kuss <rkuss@instructure.com>
QA-Review: Robin Kuss <rkuss@instructure.com>
Product-Review: Ed Schiebel <eschiebel@instructure.com>
This commit is contained in:
Ed Schiebel 2023-04-21 10:44:49 -04:00
parent dd35ce331b
commit 684f6bf34f
4 changed files with 60 additions and 13 deletions

View File

@ -72,6 +72,7 @@ const ContextModulesPublishMenu: React.FC<Props> = ({courseId, runningProgressId
setModelsReady(true)
})
}, [])
// if the module page is loaded while a publish is in progress,
// initialize the UI accordingly
useEffect(() => {
@ -141,6 +142,16 @@ const ContextModulesPublishMenu: React.FC<Props> = ({courseId, runningProgressId
refreshPublishStates()
} else {
setCurrentProgress(progress)
if (progress.workflow_state === 'running' && progress.completion > 0) {
showFlashAlert({
message: I18n.t('Publishing progress is %{progress} percent complete', {
progress: Math.round(progress.completion),
}),
type: 'info',
err: undefined,
srOnly: true,
})
}
}
}

View File

@ -22,6 +22,7 @@ import {Button, CloseButton} from '@instructure/ui-buttons'
import {Heading} from '@instructure/ui-heading'
import {Modal} from '@instructure/ui-modal'
import {ProgressBar} from '@instructure/ui-progress'
import {AccessibleContent} from '@instructure/ui-a11y-content'
import {Text} from '@instructure/ui-text'
import {View} from '@instructure/ui-view'
@ -74,7 +75,7 @@ const ContextModulesPublishModal: React.FC<Props> = ({
<ProgressBar
screenReaderLabel={I18n.t('Publishing Progress')}
formatScreenReaderValue={({valueNow, valueMax}) => {
return Math.round((valueNow / valueMax) * 100) + ' percent'
return I18n.t('%val percent', {val: Math.round((valueNow / valueMax) * 100)})
}}
renderValue={({valueNow, valueMax}) => {
return <Text size="small">{Math.round((valueNow / valueMax) * 100)}%</Text>
@ -123,7 +124,15 @@ const ContextModulesPublishModal: React.FC<Props> = ({
color="primary"
disabled={isCanceling}
>
{isPublishing ? I18n.t('Stop') : I18n.t('Continue')}
{isPublishing ? (
<AccessibleContent
alt={I18n.t('Stop publishing button. Click to discontinue processing.')}
>
{I18n.t('Stop Publishing')}
</AccessibleContent>
) : (
I18n.t('Continue')
)}
</Button>
</Modal.Footer>
</Modal>

View File

@ -39,15 +39,7 @@ const defaultProps = {
describe('ContextModulesPublishMenu', () => {
beforeEach(() => {
doFetchApi.mockResolvedValue({
json: {
progress: {
progress: {
id: 1234,
},
},
},
})
doFetchApi.mockResolvedValue({response: {ok: true}, json: [], link: null})
})
afterEach(() => {
@ -70,6 +62,13 @@ describe('ContextModulesPublishMenu', () => {
})
it('renders a spinner when publish is in-flight', () => {
doFetchApi.mockResolvedValueOnce({
json: {
id: 1234,
completion: 100,
workflow_state: 'completed',
},
})
const {getByText} = render(
<ContextModulesPublishMenu {...defaultProps} runningProgressId={17} />
)
@ -77,12 +76,36 @@ describe('ContextModulesPublishMenu', () => {
})
it('updates all the modules when ready', async () => {
doFetchApi.mockResolvedValueOnce({
json: {
id: 1234,
completion: 100,
workflow_state: 'completed',
},
})
const spy = jest.spyOn(publishAllModulesHelperModule, 'updateModulePendingPublishedStates')
render(<ContextModulesPublishMenu {...defaultProps} runningProgressId={17} />)
expect(spy).not.toHaveBeenCalled()
window.dispatchEvent(new Event('module-publish-models-ready'))
await waitFor(() => expect(spy).toHaveBeenCalled())
})
it('renders a screenreader message with progress updates', async () => {
doFetchApi.mockResolvedValueOnce({
json: {
id: 1234,
completion: 17,
workflow_state: 'running',
},
})
const {getByText} = render(
<ContextModulesPublishMenu {...defaultProps} runningProgressId={17} />
)
await waitFor(() =>
expect(getByText('Publishing progress is 17 percent complete')).toBeInTheDocument()
)
})
})
describe('menu actions', () => {

View File

@ -83,7 +83,9 @@ describe('ContextModulesPublishModal', () => {
const publishButton = getByTestId('publish-button')
expect(publishButton.textContent).toBe('Continue')
rerender(<ContextModulesPublishModal {...defaultProps} isPublishing={true} />)
expect(publishButton.textContent).toBe('Stop')
expect(publishButton.textContent).toBe(
'Stop publishing button. Click to discontinue processing.Stop Publishing'
)
})
it('disables the stop button if canceling', () => {
@ -91,7 +93,9 @@ describe('ContextModulesPublishModal', () => {
<ContextModulesPublishModal {...defaultProps} isPublishing={true} isCanceling={true} />
)
const publishButton = getByTestId('publish-button')
expect(publishButton.textContent).toBe('Stop')
expect(publishButton.textContent).toBe(
'Stop publishing button. Click to discontinue processing.Stop Publishing'
)
expect(publishButton).toBeDisabled()
})
})