Allow closing upload modal in B&I
refs MAT-168 flag=rce_buttons_and_icons Test Plan - Open a buttons and icons tray - Navigate to the image section - Click "Upload Image" > Verify an image upload modal appears > Verify pressing "escape" key closes the modal > Verify pressing the "x" in the top right corner closes the modal > Verify pressing the "Close" button in the modal footer closes the modal > Verify the modal can be re-opened after being closed Change-Id: I139885b1d693a910b22a4a2e64a9cf5170031596 Reviewed-on: https://gerrit.instructure.com/c/canvas-lms/+/283227 Tested-by: Service Cloud Jenkins <svc.cloudjenkins@instructure.com> Reviewed-by: Joe Hernandez <joe.hernandez@instructure.com> QA-Review: Joe Hernandez <joe.hernandez@instructure.com> Product-Review: Weston Dransfield <wdransfield@instructure.com>
This commit is contained in:
parent
ba9bfc7b42
commit
162b421ea6
|
@ -19,17 +19,20 @@
|
|||
import React from 'react'
|
||||
|
||||
import formatMessage from '../../../../../../format-message'
|
||||
import {actions} from '../../../reducers/imageSection'
|
||||
|
||||
import {UploadFile} from '../../../../shared/Upload/UploadFile'
|
||||
|
||||
const Upload = ({editor}) => {
|
||||
const Upload = ({editor, dispatch}) => {
|
||||
return (
|
||||
<UploadFile
|
||||
accept={undefined}
|
||||
editor={editor}
|
||||
label={formatMessage('Upload Image')}
|
||||
panels={['COMPUTER']}
|
||||
onDismiss={() => {}}
|
||||
onDismiss={() => {
|
||||
dispatch(actions.CLEAR_MODE)
|
||||
}}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -131,17 +131,15 @@ describe('ImageSection', () => {
|
|||
})
|
||||
|
||||
describe('when the "upload image" mode is selected', () => {
|
||||
let getByText
|
||||
let rendered
|
||||
|
||||
beforeEach(() => {
|
||||
fetchMock.mock('/api/session', '{}')
|
||||
|
||||
const rendered = subject({editor: new FakeEditor()})
|
||||
rendered = subject({editor: new FakeEditor()})
|
||||
|
||||
getByText = rendered.getByText
|
||||
|
||||
fireEvent.click(getByText('Add Image'))
|
||||
fireEvent.click(getByText('Upload Image'))
|
||||
fireEvent.click(rendered.getByText('Add Image'))
|
||||
fireEvent.click(rendered.getByText('Upload Image'))
|
||||
})
|
||||
|
||||
afterEach(() => {
|
||||
|
@ -149,7 +147,18 @@ describe('ImageSection', () => {
|
|||
})
|
||||
|
||||
it('renders the image upload modal', async () => {
|
||||
await waitFor(() => expect(getByText('Upload Image')).toBeInTheDocument())
|
||||
await waitFor(() => expect(rendered.getByText('Upload Image')).toBeInTheDocument())
|
||||
})
|
||||
|
||||
describe('and the the "close" button is clicked', () => {
|
||||
beforeEach(async () => {
|
||||
const button = await rendered.findAllByText(/Close/i)
|
||||
fireEvent.click(button[0])
|
||||
})
|
||||
|
||||
it('closes the modal', () => {
|
||||
expect(rendered.queryByText('Upload Image')).toBe(null)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
*/
|
||||
|
||||
import React from 'react'
|
||||
import {render, waitFor} from '@testing-library/react'
|
||||
import {render, waitFor, fireEvent} from '@testing-library/react'
|
||||
import Upload from '../Upload'
|
||||
import FakeEditor from '../../../../../shared/__tests__/FakeEditor'
|
||||
import fetchMock from 'fetch-mock'
|
||||
|
@ -31,20 +31,35 @@ jest.mock('../../../../../../../bridge', () => {
|
|||
})
|
||||
|
||||
let props
|
||||
const subject = overrides => render(<Upload {...props} />)
|
||||
const subject = () => render(<Upload {...props} />)
|
||||
|
||||
describe('Upload()', () => {
|
||||
beforeEach(() => {
|
||||
props = {editor: new FakeEditor()}
|
||||
props = {editor: new FakeEditor(), dispatch: jest.fn()}
|
||||
fetchMock.mock('/api/session', '{}')
|
||||
})
|
||||
|
||||
afterEach(() => {
|
||||
fetchMock.restore()
|
||||
jest.clearAllMocks()
|
||||
})
|
||||
|
||||
it('renders an upload modal', async () => {
|
||||
const {getAllByText} = subject(props)
|
||||
await waitFor(() => expect(getAllByText('Upload Image').length).toBe(2))
|
||||
})
|
||||
|
||||
describe('when the "Close" button is pressed', () => {
|
||||
let rendered
|
||||
|
||||
beforeEach(async () => {
|
||||
rendered = subject()
|
||||
const button = await rendered.findAllByText(/Close/i)
|
||||
fireEvent.click(button[0])
|
||||
})
|
||||
|
||||
it('closes the modal', async () => {
|
||||
expect(props.dispatch).toHaveBeenCalled()
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
|
@ -75,7 +75,7 @@ describe('<CreateButtonForm />', () => {
|
|||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<metadata>
|
||||
{"name":"","alt":"","shape":"square","size":"small","color":null,"outlineColor":null,"outlineSize":"none","text":"","textSize":"small","textColor":null,"textBackgroundColor":null,"textPosition":"middle","encodedImage":"","encodedImageType":"course","encodedImageName":""}
|
||||
{"name":"","alt":"","shape":"square","size":"small","color":null,"outlineColor":null,"outlineSize":"none","text":"","textSize":"small","textColor":null,"textBackgroundColor":null,"textPosition":"middle","encodedImage":"","encodedImageType":"","encodedImageName":""}
|
||||
</metadata>
|
||||
<svg
|
||||
fill="none"
|
||||
|
|
|
@ -16,64 +16,68 @@
|
|||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import imageSection, {defaultState} from '../imageSection'
|
||||
import imageSection, {initialState} from '../imageSection'
|
||||
|
||||
describe('imageSection()', () => {
|
||||
const subject = (action, stateOverrides) =>
|
||||
imageSection({...defaultState, ...stateOverrides}, action)
|
||||
imageSection({...initialState, ...stateOverrides}, action)
|
||||
|
||||
it('handles "ClearMode" actions', () => {
|
||||
expect(subject({type: 'ClearMode'})).toMatchObject(initialState)
|
||||
})
|
||||
|
||||
it('handles "Course" actions', () => {
|
||||
expect(subject({type: 'Course'})).toMatchObject({
|
||||
...defaultState,
|
||||
...initialState,
|
||||
mode: 'Course'
|
||||
})
|
||||
})
|
||||
|
||||
it('handles "Upload" actions', () => {
|
||||
expect(subject({type: 'Upload'})).toMatchObject({
|
||||
...defaultState,
|
||||
...initialState,
|
||||
mode: 'Upload'
|
||||
})
|
||||
})
|
||||
|
||||
it('handles "SingleColor" actions', () => {
|
||||
expect(subject({type: 'SingleColor'})).toMatchObject({
|
||||
...defaultState,
|
||||
...initialState,
|
||||
mode: 'SingleColor'
|
||||
})
|
||||
})
|
||||
|
||||
it('handles "MultiColor" actions', () => {
|
||||
expect(subject({type: 'MultiColor'})).toMatchObject({
|
||||
...defaultState,
|
||||
...initialState,
|
||||
mode: 'MultiColor'
|
||||
})
|
||||
})
|
||||
|
||||
it('handles "StartLoading" actions', () => {
|
||||
expect(subject({type: 'StartLoading'})).toMatchObject({
|
||||
...defaultState,
|
||||
...initialState,
|
||||
loading: true
|
||||
})
|
||||
})
|
||||
|
||||
it('handles "StopLoading" actions', () => {
|
||||
expect(subject({type: 'StopLoading'})).toMatchObject({
|
||||
...defaultState,
|
||||
...initialState,
|
||||
loading: false
|
||||
})
|
||||
})
|
||||
|
||||
it('handles "SetImage" actions', () => {
|
||||
expect(subject({type: 'SetImage', payload: 'img'})).toMatchObject({
|
||||
...defaultState,
|
||||
...initialState,
|
||||
image: 'img'
|
||||
})
|
||||
})
|
||||
|
||||
it('handles "SetImageName" actions', () => {
|
||||
expect(subject({type: 'SetImageName', payload: 'name'})).toMatchObject({
|
||||
...defaultState,
|
||||
...initialState,
|
||||
imageName: 'name'
|
||||
})
|
||||
})
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
import formatMessage from '../../../../format-message'
|
||||
|
||||
export const initialState = {
|
||||
mode: 'course', // TODO: Update to 'upload' once we support it
|
||||
mode: '',
|
||||
image: '',
|
||||
imageName: '',
|
||||
loading: false,
|
||||
|
@ -30,7 +30,8 @@ export const actions = {
|
|||
SET_IMAGE: {type: 'SetImage'},
|
||||
SET_IMAGE_NAME: {type: 'SetImageName'},
|
||||
START_LOADING: {type: 'StartLoading'},
|
||||
STOP_LOADING: {type: 'StopLoading'}
|
||||
STOP_LOADING: {type: 'StopLoading'},
|
||||
CLEAR_MODE: {type: 'ClearMode'}
|
||||
}
|
||||
|
||||
export const modes = {
|
||||
|
@ -50,6 +51,8 @@ const imageSection = (state, action) => {
|
|||
return {...state, image: action.payload}
|
||||
case actions.SET_IMAGE_NAME.type:
|
||||
return {...state, imageName: action.payload}
|
||||
case actions.CLEAR_MODE.type:
|
||||
return {...state, mode: ''}
|
||||
case modes.uploadImages.type:
|
||||
return {...state, mode: modes.uploadImages.type}
|
||||
case modes.singleColorImages.type:
|
||||
|
|
Loading…
Reference in New Issue