Upgrade to Inst-UI 3.2
fixes GRADE-180 Test plan: Smoke test all Canvas pages that use InstUI. Change-Id: I9ca3dc199924ec3a26c21bcc47dacb51ed12df6a Reviewed-on: https://gerrit.instructure.com/122611 Tested-by: Jenkins Reviewed-by: Derek Bender <djbender@instructure.com> Reviewed-by: Jeremy Neander <jneander@instructure.com> QA-Review: KC Naegle <knaegle@instructure.com> Product-Review: Neil Gupta <ngupta@instructure.com>
This commit is contained in:
parent
e29b71e5cf
commit
b9737cc05c
|
@ -146,12 +146,13 @@ export default class ActAsModal extends React.Component {
|
|||
return (
|
||||
<span>
|
||||
<Modal
|
||||
onRequestClose={this.handleModalRequestClose}
|
||||
onDismiss={this.handleModalRequestClose}
|
||||
transition="fade"
|
||||
size="fullscreen"
|
||||
label={I18n.t('Act as User')}
|
||||
closeButtonLabel={I18n.t('Close')}
|
||||
isOpen
|
||||
applicationElement={() => document.getElementById('application')}
|
||||
open
|
||||
>
|
||||
<ModalHeader>
|
||||
<Typography size="large">
|
||||
|
|
|
@ -98,17 +98,11 @@ import APIError from './api_error'
|
|||
}
|
||||
componentDidMount () {
|
||||
this.manageFocus();
|
||||
document.getElementById('application').setAttribute('aria-hidden', 'true')
|
||||
}
|
||||
componentWillReceiveProps (nextProps) {
|
||||
if (nextProps.usersEnrolled) {
|
||||
this.close();
|
||||
}
|
||||
if (nextProps.isOpen) {
|
||||
document.getElementById('application').setAttribute('aria-hidden', 'true')
|
||||
} else {
|
||||
document.getElementById('application').removeAttribute('aria-hidden')
|
||||
}
|
||||
}
|
||||
componentDidUpdate () {
|
||||
this.manageFocus();
|
||||
|
@ -295,13 +289,14 @@ import APIError from './api_error'
|
|||
<Modal
|
||||
closeButtonLabel={cancelLabel}
|
||||
id="add_people_modal"
|
||||
isOpen={this.props.isOpen}
|
||||
open={this.props.isOpen}
|
||||
label={I18n.t('Modal Dialog: Add People')}
|
||||
onRequestClose={this.close}
|
||||
applicationElement={() => document.getElementById('application')}
|
||||
onDismiss={this.close}
|
||||
ref={(node) => { this.node = node; }}
|
||||
shouldCloseOnOverlayClick={false}
|
||||
size="medium"
|
||||
tabindex="-1"
|
||||
tabIndex="-1"
|
||||
>
|
||||
<ModalHeader>
|
||||
<Heading tabIndex="-1">{I18n.t('Add People')}</Heading>
|
||||
|
|
|
@ -39,8 +39,8 @@ import ScreenReaderContent from 'instructure-ui/lib/components/ScreenReaderConte
|
|||
renderNotice () {
|
||||
return (
|
||||
this.props.nameList.length > 0
|
||||
? <Alert variant="success" dismissable={false}>{I18n.t('The following users are ready to be added to the course.')}</Alert>
|
||||
: <Alert variant="info" dismissable={false}>{I18n.t('No users were selected to add to the course')}</Alert>
|
||||
? <Alert variant="success">{I18n.t('The following users are ready to be added to the course.')}</Alert>
|
||||
: <Alert variant="info">{I18n.t('No users were selected to add to the course')}</Alert>
|
||||
);
|
||||
}
|
||||
renderUserTable () {
|
||||
|
|
|
@ -93,7 +93,7 @@ import Alert from 'instructure-ui/lib/components/Alert'
|
|||
}
|
||||
return (
|
||||
<div className="peopleValidationissues__duplicates">
|
||||
<Alert variant="warning" dismissable={false}>
|
||||
<Alert variant="warning">
|
||||
{I18n.t('There were several possible matches with the import. Please resolve them below.')}
|
||||
</Alert>
|
||||
{duplicateAddresses.map((address) => {
|
||||
|
@ -124,7 +124,7 @@ import Alert from 'instructure-ui/lib/components/Alert'
|
|||
|
||||
return (
|
||||
<div className="peoplevalidationissues__missing">
|
||||
<Alert variant="warning" dismissable={false}>{alertText}</Alert>
|
||||
<Alert variant="warning">{alertText}</Alert>
|
||||
<MissingPeopleSection
|
||||
inviteUsersURL={this.props.inviteUsersURL}
|
||||
missing={this.props.missing}
|
||||
|
|
|
@ -86,9 +86,10 @@ export default class BlueprintModal extends Component {
|
|||
|
||||
return (
|
||||
<Modal
|
||||
isOpen={this.props.isOpen}
|
||||
onRequestClose={this.props.onCancel}
|
||||
open={this.props.isOpen}
|
||||
onDismiss={this.props.onCancel}
|
||||
onClose={this.handleModalClose}
|
||||
applicationElement={() => document.getElementById('application')}
|
||||
transition="fade"
|
||||
size="fullscreen"
|
||||
label={this.props.title}
|
||||
|
@ -114,6 +115,6 @@ export default class BlueprintModal extends Component {
|
|||
)}
|
||||
</ModalFooter>
|
||||
</Modal>
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -49,11 +49,10 @@ export default class BlueprintCourseSidebar extends Component {
|
|||
this.state = {
|
||||
isOpen: false,
|
||||
}
|
||||
this.trayRef = null
|
||||
}
|
||||
|
||||
handleOpen = () => {
|
||||
this.props.onOpen(this.trayRef)
|
||||
this.props.onOpen()
|
||||
this.closeBtn.focus()
|
||||
}
|
||||
|
||||
|
@ -74,7 +73,7 @@ export default class BlueprintCourseSidebar extends Component {
|
|||
return (
|
||||
<div className="bcs__wrapper">
|
||||
<div className="bcs__trigger">
|
||||
<Button ref={(c) => { this.openBtn = c }} variant="icon-inverse" onClick={this.open}>
|
||||
<Button buttonRef={(c) => { this.openBtn = c }} variant="icon-inverse" onClick={this.open}>
|
||||
<Typography color="primary-inverse" size="large">
|
||||
<IconBlueprintSolid title={I18n.t('Open sidebar')} />
|
||||
</Typography>
|
||||
|
@ -82,18 +81,18 @@ export default class BlueprintCourseSidebar extends Component {
|
|||
</div>
|
||||
<Tray
|
||||
label={I18n.t('Blueprint Settings')}
|
||||
dismissable={false}
|
||||
trapFocus
|
||||
isOpen={this.state.isOpen}
|
||||
shouldContainFocus
|
||||
open={this.state.isOpen}
|
||||
placement="end"
|
||||
onEntering={this.handleOpen}
|
||||
onEntered={this.handleOpen}
|
||||
onExiting={this.handleClose}
|
||||
contentRef={(el) => { this.trayRef = el }}
|
||||
applicationElement={() => document.getElementById('application')}
|
||||
contentRef={this.props.contentRef}
|
||||
>
|
||||
<div className="bcs__content" ref={this.props.contentRef}>
|
||||
<div className="bcs__content">
|
||||
<header className="bcs__header">
|
||||
<div className="bcs__close-wrapper">
|
||||
<Button variant="icon-inverse" onClick={this.close} ref={(c) => { this.closeBtn = c }}>
|
||||
<Button variant="icon-inverse" onClick={this.close} buttonRef={(c) => { this.closeBtn = c }}>
|
||||
<Typography color="primary-inverse" size="small">
|
||||
<IconXSolid title={I18n.t('Close sidebar')} />
|
||||
</Typography>
|
||||
|
@ -110,6 +109,6 @@ export default class BlueprintCourseSidebar extends Component {
|
|||
</Tray>
|
||||
{this.props.detachedChildren}
|
||||
</div>
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -91,24 +91,7 @@ export default class CourseSidebar extends Component {
|
|||
}
|
||||
}
|
||||
|
||||
componentWillUpdate (nextProps, nextState) {
|
||||
if (this.state.isModalOpen !== nextState.isModalOpen) {
|
||||
if (nextState.isModalOpen) {
|
||||
document.getElementById('application').setAttribute('aria-hidden', 'true')
|
||||
if (this.sidebarRef) {
|
||||
this.sidebarRef.setAttribute('aria-hidden', 'true')
|
||||
}
|
||||
} else {
|
||||
document.getElementById('application').removeAttribute('aria-hidden')
|
||||
if (this.sidebarRef) {
|
||||
this.sidebarRef.removeAttribute('aria-hidden')
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onOpenSidebar = (trayRef) => {
|
||||
this.sidebarRef = trayRef
|
||||
onOpenSidebar = () => {
|
||||
if (!this.props.hasLoadedAssociations) {
|
||||
this.props.loadAssociations()
|
||||
}
|
||||
|
@ -117,11 +100,6 @@ export default class CourseSidebar extends Component {
|
|||
}
|
||||
}
|
||||
|
||||
onCloseSidebar = () => {
|
||||
this.sidebarRef = null
|
||||
}
|
||||
|
||||
sidebarRef = null
|
||||
modals = {
|
||||
associations: () => ({
|
||||
props: {
|
||||
|
@ -348,7 +326,6 @@ export default class CourseSidebar extends Component {
|
|||
return (
|
||||
<BlueprintSidebar
|
||||
onOpen={this.onOpenSidebar}
|
||||
onClose={this.onCloseSidebar}
|
||||
contentRef={this.props.contentRef}
|
||||
detachedChildren={this.renderModal()}
|
||||
>
|
||||
|
|
|
@ -121,7 +121,7 @@ import Actions from 'jsx/calendar/scheduler/actions'
|
|||
</div>
|
||||
</Modal>
|
||||
</div>
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -87,13 +87,11 @@ export default class BreakdownDetails extends React.Component {
|
|||
|
||||
return (
|
||||
<Tray
|
||||
isOpen={this.props.showDetails}
|
||||
open={this.props.showDetails}
|
||||
placement="end"
|
||||
dismissable={false}
|
||||
trapFocus
|
||||
getDefaultFocusElement={() => this.closeButton}
|
||||
onReady={() => document.getElementById('application').setAttribute('aria-hidden', true)}
|
||||
onClose={() => document.getElementById('application').setAttribute('aria-hidden', false)}
|
||||
shouldContainFocus
|
||||
defaultFocusElement={() => this.closeButton}
|
||||
applicationElement={() => document.getElementById('application')}
|
||||
>
|
||||
<div className="crs-breakdown-details">
|
||||
<div className="crs-breakdown-details__content">
|
||||
|
@ -128,6 +126,6 @@ export default class BreakdownDetails extends React.Component {
|
|||
</div>
|
||||
</div>
|
||||
</Tray>
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -206,11 +206,11 @@ export default class StudentContextTray extends React.Component {
|
|||
|
||||
<Tray
|
||||
label={I18n.t('Student Details')}
|
||||
dismissable={!this.state.isLoading}
|
||||
closeButtonLabel={I18n.t('Close')}
|
||||
closeButtonLabel={!this.state.isLoading ? I18n.t('Close') : null}
|
||||
closeButtonRef={this.getCloseButtonRef}
|
||||
isOpen={this.state.isOpen}
|
||||
onRequestClose={this.handleRequestClose}
|
||||
applicationElement={() => document.getElementById('application')}
|
||||
open={this.state.isOpen}
|
||||
onDismiss={this.handleRequestClose}
|
||||
placement='end'
|
||||
zIndex='1000'
|
||||
onClose={this.props.onClose}
|
||||
|
@ -307,6 +307,6 @@ export default class StudentContextTray extends React.Component {
|
|||
</aside>
|
||||
</Tray>
|
||||
</div>
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -52,7 +52,6 @@ class CourseHomeDialog extends React.Component {
|
|||
constructor (props) {
|
||||
super(props)
|
||||
this.state = props.store.getState()
|
||||
this.appElement = document.getElementById('application')
|
||||
}
|
||||
|
||||
renderWikiLabelContent () {
|
||||
|
@ -127,66 +126,68 @@ class CourseHomeDialog extends React.Component {
|
|||
I18n.t('Before publishing your course, you must either publish a module in the Modules page, or choose a different home page.') :
|
||||
I18n.t("Select what you'd like to display on the home page.")
|
||||
|
||||
return (<Modal
|
||||
isOpen={this.props.open}
|
||||
transition="fade"
|
||||
label={I18n.t('Choose Course Home Page')}
|
||||
closeButtonLabel={I18n.t("Close")}
|
||||
onReady={this.onReady}
|
||||
onRequestClose={this.props.onRequestClose}
|
||||
onClose={this.onClose}
|
||||
>
|
||||
<ModalHeader>
|
||||
<Heading tag="h2" level="h3">{I18n.t('Choose Home Page')}</Heading>
|
||||
</ModalHeader>
|
||||
<ModalBody>
|
||||
<div className="content-box-mini" style={{marginTop: '0'}}>
|
||||
<AccessibleContent>
|
||||
<Typography weight="bold" size="small">
|
||||
{instructions}
|
||||
</Typography>
|
||||
</AccessibleContent>
|
||||
</div>
|
||||
<RadioInputGroup
|
||||
description={<ScreenReaderContent>{instructions}</ScreenReaderContent>}
|
||||
name="course[default_view]"
|
||||
onChange={this.onChange}
|
||||
defaultValue={selectedDefaultView}
|
||||
>
|
||||
{inputs.map(input =>
|
||||
<RadioInput
|
||||
key={input.value}
|
||||
checked={input.checked}
|
||||
value={input.value}
|
||||
label={input.label}
|
||||
disabled={input.disabled}
|
||||
/>)
|
||||
return (
|
||||
<Modal
|
||||
open={this.props.open}
|
||||
transition="fade"
|
||||
label={I18n.t('Choose Course Home Page')}
|
||||
closeButtonLabel={I18n.t('Close')}
|
||||
applicationElement={() => document.getElementById('application')}
|
||||
onDismiss={this.props.onRequestClose}
|
||||
onClose={this.onClose}
|
||||
>
|
||||
<ModalHeader>
|
||||
<Heading tag="h2" level="h3">{I18n.t('Choose Home Page')}</Heading>
|
||||
</ModalHeader>
|
||||
<ModalBody>
|
||||
<div className="content-box-mini" style={{marginTop: '0'}}>
|
||||
<AccessibleContent>
|
||||
<Typography weight="bold" size="small">
|
||||
{instructions}
|
||||
</Typography>
|
||||
</AccessibleContent>
|
||||
</div>
|
||||
<RadioInputGroup
|
||||
description={<ScreenReaderContent>{instructions}</ScreenReaderContent>}
|
||||
name="course[default_view]"
|
||||
onChange={this.onChange}
|
||||
defaultValue={selectedDefaultView}
|
||||
>
|
||||
{inputs.map(input =>
|
||||
<RadioInput
|
||||
key={input.value}
|
||||
checked={input.checked}
|
||||
value={input.value}
|
||||
label={input.label}
|
||||
disabled={input.disabled}
|
||||
/>)
|
||||
}
|
||||
</RadioInputGroup>
|
||||
|
||||
{
|
||||
wikiFrontPageTitle ? (
|
||||
null
|
||||
) : (
|
||||
<div className="content-box-mini">
|
||||
* <Link href={wikiUrl}>{I18n.t('Front page must be set first')}
|
||||
</Link></div>
|
||||
)
|
||||
}
|
||||
</RadioInputGroup>
|
||||
|
||||
{
|
||||
wikiFrontPageTitle ? (
|
||||
null
|
||||
) : (
|
||||
<div className="content-box-mini">
|
||||
* <Link href={wikiUrl}>{I18n.t('Front page must be set first')}
|
||||
</Link></div>
|
||||
)
|
||||
}
|
||||
</ModalBody>
|
||||
|
||||
</ModalBody>
|
||||
|
||||
<ModalFooter>
|
||||
<Button onClick={this.props.onRequestClose}>{I18n.t('Cancel')}</Button>
|
||||
<Button
|
||||
onClick={this.onSubmit}
|
||||
disabled={this.props.isPublishing && this.state.selectedDefaultView === 'modules'}
|
||||
variant="primary"
|
||||
>{
|
||||
this.props.isPublishing ? I18n.t('Choose and Publish') : I18n.t('Save')
|
||||
}</Button>
|
||||
</ModalFooter>
|
||||
</Modal>)
|
||||
<ModalFooter>
|
||||
<Button onClick={this.props.onRequestClose}>{I18n.t('Cancel')}</Button>
|
||||
<Button
|
||||
onClick={this.onSubmit}
|
||||
disabled={this.props.isPublishing && this.state.selectedDefaultView === 'modules'}
|
||||
variant="primary"
|
||||
>{
|
||||
this.props.isPublishing ? I18n.t('Choose and Publish') : I18n.t('Save')
|
||||
}</Button>
|
||||
</ModalFooter>
|
||||
</Modal>
|
||||
);
|
||||
}
|
||||
|
||||
componentDidMount () {
|
||||
|
@ -197,13 +198,7 @@ class CourseHomeDialog extends React.Component {
|
|||
this.props.store.removeChangeListener(this.onStoreChange)
|
||||
}
|
||||
|
||||
onReady = () => {
|
||||
this.appElement.setAttribute('aria-hidden', 'true')
|
||||
}
|
||||
|
||||
onClose = () => {
|
||||
this.appElement.removeAttribute('aria-hidden')
|
||||
|
||||
// this (unnecessary?) setTimeout fixes returning focus in ie11
|
||||
window.setTimeout(() => {
|
||||
const returnFocusTo = this.props.returnFocusTo
|
||||
|
|
|
@ -96,12 +96,13 @@ import Select from 'instructure-ui/lib/components/Select'
|
|||
source: this.props.source.label
|
||||
})
|
||||
return (
|
||||
<Modal ref='modal' isOpen={this.state.isOpen}
|
||||
<Modal ref='modal' open={this.state.isOpen}
|
||||
modalSize='small'
|
||||
label={dialogLabel}
|
||||
closeButtonLabel={I18n.t('Cancel')}
|
||||
onReady={this.handleReady}
|
||||
onRequestClose={this.handleRequestClose}
|
||||
applicationElement={() => document.getElementById('application')}
|
||||
onOpen={this.handleReady}
|
||||
onDismiss={this.handleRequestClose}
|
||||
onClose={this.handleClose}
|
||||
>
|
||||
<ModalHeader>
|
||||
|
@ -115,7 +116,7 @@ import Select from 'instructure-ui/lib/components/Select'
|
|||
<Button id='MoveToDialog__move' variant='primary' onClick={this.handleMove}>{I18n.t('Move')}</Button>
|
||||
</ModalFooter>
|
||||
</Modal>
|
||||
)
|
||||
);
|
||||
}
|
||||
});
|
||||
export default MoveToDialog
|
||||
|
|
|
@ -269,6 +269,6 @@ export default React.createClass({
|
|||
|
||||
</Modal>
|
||||
</div>
|
||||
)
|
||||
);
|
||||
}
|
||||
});
|
||||
|
|
|
@ -189,6 +189,6 @@ export default React.createClass({
|
|||
</div>
|
||||
</Modal>
|
||||
</li>
|
||||
)
|
||||
);
|
||||
}
|
||||
});
|
||||
|
|
|
@ -124,7 +124,7 @@ export default React.createClass({
|
|||
</div>
|
||||
</Modal>
|
||||
</li>
|
||||
)
|
||||
);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -177,7 +177,7 @@ export default React.createClass({
|
|||
</div>
|
||||
</Modal>
|
||||
</li>
|
||||
)
|
||||
);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -66,7 +66,7 @@ export default React.createClass({
|
|||
},
|
||||
|
||||
render() {
|
||||
return(
|
||||
return (
|
||||
<Modal className="ReactModal__Content--canvas ReactModal__Content--mini-modal"
|
||||
overlayClassName="ReactModal__Overlay--canvas"
|
||||
isOpen={this.state.modalIsOpen}
|
||||
|
@ -98,7 +98,7 @@ export default React.createClass({
|
|||
</div>
|
||||
</div>
|
||||
</Modal>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
});
|
||||
|
|
|
@ -116,7 +116,7 @@ class SearchFormComponent extends Component {
|
|||
}
|
||||
}
|
||||
|
||||
setSelectedFrom = (from) => {
|
||||
setSelectedFrom = (_, from) => {
|
||||
const startOfFrom = from ? moment(from).startOf('day').format() : '';
|
||||
this.setState(prevState => ({
|
||||
selected: {
|
||||
|
@ -126,7 +126,7 @@ class SearchFormComponent extends Component {
|
|||
}));
|
||||
}
|
||||
|
||||
setSelectedTo = (to) => {
|
||||
setSelectedTo = (_, to) => {
|
||||
const endOfTo = to ? moment(to).endOf('day').format() : '';
|
||||
this.setState(prevState => ({
|
||||
selected: {
|
||||
|
|
|
@ -227,7 +227,7 @@ class AssignmentColumnHeader extends ColumnHeader {
|
|||
return (
|
||||
<PopoverMenu
|
||||
contentRef={this.bindOptionsMenuContent}
|
||||
focusTriggerOnClose={false}
|
||||
shouldFocusTriggerOnClose={false}
|
||||
trigger={this.renderTrigger()}
|
||||
onToggle={this.onToggle}
|
||||
onClose={this.props.onMenuClose}
|
||||
|
|
|
@ -93,7 +93,7 @@ class AssignmentGroupColumnHeader extends ColumnHeader {
|
|||
|
||||
<PopoverMenu
|
||||
contentRef={this.bindOptionsMenuContent}
|
||||
focusTriggerOnClose={false}
|
||||
shouldFocusTriggerOnClose={false}
|
||||
trigger={renderTrigger(this.props.assignmentGroup, menuShown, this.bindOptionsMenuTrigger)}
|
||||
onToggle={this.onToggle}
|
||||
onClose={this.props.onMenuClose}
|
||||
|
|
|
@ -125,11 +125,12 @@ class GradebookSettingsModal extends React.Component {
|
|||
return (
|
||||
<Modal
|
||||
size="large"
|
||||
isOpen={isOpen}
|
||||
open={isOpen}
|
||||
label={title}
|
||||
closeButtonLabel={I18n.t('Close')}
|
||||
onAfterOpen={this.fetchLatePolicy}
|
||||
onRequestClose={this.close}
|
||||
applicationElement={() => document.getElementById('application')}
|
||||
onOpen={this.fetchLatePolicy}
|
||||
onDismiss={this.close}
|
||||
onExited={this.props.onClose}
|
||||
>
|
||||
<ModalHeader>
|
||||
|
|
|
@ -228,8 +228,7 @@ class LatePoliciesTabPanel extends React.Component {
|
|||
<Alert
|
||||
variant="warning"
|
||||
closeButtonLabel={I18n.t('Close')}
|
||||
dismissable
|
||||
onClose={this.closeAlert}
|
||||
onDismiss={this.closeAlert}
|
||||
margin="small"
|
||||
>
|
||||
{I18n.t('Changing your policy now will affect previously graded submissions.')}
|
||||
|
|
|
@ -98,6 +98,7 @@ class StatusColorListItem extends React.Component {
|
|||
show={isColorPickerShown}
|
||||
onToggle={colorPickerOnToggle}
|
||||
contentRef={colorPickerContentRef}
|
||||
applicationElement={() => document.getElementById('application')}
|
||||
>
|
||||
<PopoverTrigger>
|
||||
|
||||
|
|
|
@ -135,11 +135,12 @@ class StatusesModal extends React.Component {
|
|||
|
||||
return (
|
||||
<Modal
|
||||
isOpen={isOpen}
|
||||
open={isOpen}
|
||||
label={I18n.t('Statuses')}
|
||||
closeButtonLabel={I18n.t('Close')}
|
||||
closeButtonRef={bindCloseButton}
|
||||
onRequestClose={close}
|
||||
applicationElement={() => document.getElementById('application')}
|
||||
onDismiss={close}
|
||||
onExited={onClose}
|
||||
contentRef={bindContentRef}
|
||||
>
|
||||
|
|
|
@ -120,7 +120,7 @@ export default class StudentColumnHeader extends ColumnHeader {
|
|||
|
||||
<PopoverMenu
|
||||
contentRef={this.bindOptionsMenuContent}
|
||||
focusTriggerOnClose={false}
|
||||
shouldFocusTriggerOnClose={false}
|
||||
trigger={
|
||||
<span ref={this.bindOptionsMenuTrigger} className={classes}>
|
||||
<Typography weight="bold" fontStyle="normal" size="large" color="brand">
|
||||
|
|
|
@ -65,12 +65,12 @@ export default function SubmissionTray (props) {
|
|||
<Tray
|
||||
contentRef={props.contentRef}
|
||||
label={I18n.t('Submission tray')}
|
||||
isDismissable
|
||||
closeButtonLabel={I18n.t('Close submission tray')}
|
||||
isOpen={props.isOpen}
|
||||
trapFocus
|
||||
applicationElement={() => document.getElementById('application')}
|
||||
open={props.isOpen}
|
||||
shouldContainFocus
|
||||
placement="end"
|
||||
onRequestClose={props.onRequestClose}
|
||||
onDismiss={props.onRequestClose}
|
||||
onClose={props.onClose}
|
||||
>
|
||||
<div className="SubmissionTray__Container">
|
||||
|
|
|
@ -111,7 +111,7 @@ class TotalGradeColumnHeader extends ColumnHeader {
|
|||
<PopoverMenu
|
||||
ref={this.bindOptionsMenu}
|
||||
contentRef={this.bindOptionsMenuContent}
|
||||
focusTriggerOnClose={false}
|
||||
shouldFocusTriggerOnClose={false}
|
||||
trigger={renderTrigger(menuShown, this.bindOptionsMenuTrigger)}
|
||||
onToggle={this.onToggle}
|
||||
onClose={this.props.onMenuClose}
|
||||
|
|
|
@ -22,6 +22,10 @@ import PropTypes from 'prop-types'
|
|||
import SVGWrapper from 'jsx/shared/SVGWrapper'
|
||||
import PreventDefault from 'compiled/fn/preventDefault'
|
||||
|
||||
function readCookie(key) {
|
||||
return (document.cookie.match('(^|; )' + encodeURIComponent(key) + '=([^;]*)') || 0)[2]
|
||||
}
|
||||
|
||||
var ProfileTray = React.createClass({
|
||||
|
||||
propTypes: {
|
||||
|
@ -66,7 +70,7 @@ import PreventDefault from 'compiled/fn/preventDefault'
|
|||
>
|
||||
<input name="utf8" value="✓" type="hidden"/>
|
||||
<input name="_method" value="delete" type="hidden"/>
|
||||
<input name="authenticity_token" value={$.cookie('_csrf_token')} type="hidden"/>
|
||||
<input name="authenticity_token" value={readCookie('_csrf_token')} type="hidden"/>
|
||||
<button
|
||||
type="submit"
|
||||
className="Button Button--small">
|
||||
|
|
|
@ -35,19 +35,6 @@ import axios from 'axios'
|
|||
isOpen: false
|
||||
}
|
||||
|
||||
constructor (props) {
|
||||
super(props);
|
||||
this.appElement = document.getElementById('application');
|
||||
}
|
||||
|
||||
handleModalReady = () => {
|
||||
this.appElement.setAttribute('aria-hidden', 'true');
|
||||
}
|
||||
|
||||
handleModalClose = () => {
|
||||
this.appElement.removeAttribute('aria-hidden');
|
||||
}
|
||||
|
||||
handleOkayButtonClick = (e, onSuccessFunc = window.location.reload) => {
|
||||
const API_URL = '/api/v1/users/self/features/flags/new_user_tutorial_on_off';
|
||||
axios.put(API_URL, {
|
||||
|
@ -62,13 +49,12 @@ import axios from 'axios'
|
|||
render () {
|
||||
return (
|
||||
<Modal
|
||||
isOpen={this.props.isOpen}
|
||||
open={this.props.isOpen}
|
||||
size="small"
|
||||
onReady={this.handleModalReady}
|
||||
onClose={this.handleModalClose}
|
||||
onRequestClose={this.props.handleRequestClose}
|
||||
onDismiss={this.props.handleRequestClose}
|
||||
label={I18n.t('End Course Set-up Tutorial Dialog')}
|
||||
closeButtonLabel={I18n.t('Close')}
|
||||
applicationElement={() => document.getElementById('application')}
|
||||
>
|
||||
<ModalHeader>
|
||||
<Heading>{I18n.t('End Course Set-up Tutorial')}</Heading>
|
||||
|
|
|
@ -91,14 +91,13 @@ class TutorialTray extends React.Component {
|
|||
return (
|
||||
<Tray
|
||||
label={this.props.label}
|
||||
isDismissable={false}
|
||||
isOpen={!this.state.isCollapsed}
|
||||
open={!this.state.isCollapsed}
|
||||
placement="end"
|
||||
zIndex="100"
|
||||
onEntering={this.handleEntering}
|
||||
onExiting={this.handleExiting}
|
||||
onEntered={this.handleEntering}
|
||||
trapFocus
|
||||
shouldContainFocus
|
||||
applicationElement={() => document.getElementById('application')}
|
||||
>
|
||||
<div className="NewUserTutorialTray">
|
||||
<div className="NewUserTutorialTray__ButtonContainer">
|
||||
|
|
|
@ -37,17 +37,18 @@ export default React.createClass({
|
|||
render: function () {
|
||||
return (
|
||||
<Modal
|
||||
isOpen={this.state.isOpen}
|
||||
open={this.state.isOpen}
|
||||
shouldCloseOnOverlayClick={true}
|
||||
onRequestClose={this.close}
|
||||
onDismiss={this.close}
|
||||
transition="fade"
|
||||
size="auto"
|
||||
label={I18n.t("Modal Dialog: Add to course")}
|
||||
closeButtonLabel={I18n.t("Close")}
|
||||
applicationElement={() => document.getElementById('application')}
|
||||
ref={this._saveModal}
|
||||
onEntering={this._fixFocus}
|
||||
onClose={this.props.onClose}
|
||||
onReady={this.props.onReady}
|
||||
onOpen={this.props.onReady}
|
||||
>
|
||||
<ModalHeader>
|
||||
<Heading>{I18n.t("Add to course...")}</Heading>
|
||||
|
|
|
@ -168,12 +168,11 @@ export default class FlashAlert extends React.Component {
|
|||
<Alert
|
||||
variant={this.props.variant}
|
||||
closeButtonLabel={I18n.t('Close')}
|
||||
onClose={this.closeAlert}
|
||||
dismissable
|
||||
onDismiss={this.closeAlert}
|
||||
margin="small auto"
|
||||
timeout={timeout}
|
||||
liveRegion={this.getLiveRegion}
|
||||
transitionType="fade"
|
||||
transition="fade"
|
||||
>
|
||||
<div>
|
||||
<p style={{margin: '0 -5px'}}>
|
||||
|
@ -183,7 +182,7 @@ export default class FlashAlert extends React.Component {
|
|||
</div>
|
||||
</Alert>
|
||||
</Transition>
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -216,13 +216,12 @@ import Alert from 'instructure-ui/lib/components/Alert'
|
|||
<div className="MessageStudents__Alert">
|
||||
<Alert variant={variant}
|
||||
closeButtonLabel={I18n.t('Close')}
|
||||
dismissable
|
||||
onClose={this.handleAlertClose}
|
||||
onDismiss={this.handleAlertClose}
|
||||
>
|
||||
{message}
|
||||
</Alert>
|
||||
</div>
|
||||
)
|
||||
);
|
||||
} else { return null }
|
||||
}
|
||||
|
||||
|
@ -244,11 +243,12 @@ import Alert from 'instructure-ui/lib/components/Alert'
|
|||
return (
|
||||
<div className="MessageStudents">
|
||||
<Modal
|
||||
isOpen={this.state.open}
|
||||
open={this.state.open}
|
||||
transition="fade"
|
||||
label={this.props.title}
|
||||
onRequestClose={this.props.onRequestClose}
|
||||
onDismiss={this.props.onRequestClose}
|
||||
closeButtonLabel={I18n.t('Close')}
|
||||
applicationElement={() => document.getElementById('application')}
|
||||
size='medium'
|
||||
onExited={this.props.onExited}
|
||||
>
|
||||
|
@ -305,7 +305,7 @@ import Alert from 'instructure-ui/lib/components/Alert'
|
|||
</ModalFooter>
|
||||
</Modal>
|
||||
</div>
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -137,6 +137,6 @@ export default React.createClass({
|
|||
</ModalButtons>
|
||||
</Modal>
|
||||
</div>
|
||||
)
|
||||
);
|
||||
}
|
||||
})
|
||||
|
|
|
@ -139,6 +139,6 @@ export default React.createClass({
|
|||
>
|
||||
{this.modalContent()}
|
||||
</Modal>
|
||||
)
|
||||
);
|
||||
}
|
||||
})
|
||||
|
|
|
@ -145,6 +145,9 @@ div.form-column-right, div.overrides-column-right {
|
|||
margin: 15px 20px 0;
|
||||
}
|
||||
|
||||
#discussion-edit-view {
|
||||
@include readonly-input;
|
||||
}
|
||||
|
||||
/* support for master class locked input fields */
|
||||
#edit_assignment_form, #discussion-edit-view {
|
||||
|
@ -152,8 +155,6 @@ div.form-column-right, div.overrides-column-right {
|
|||
clear: both;
|
||||
}
|
||||
|
||||
@include readonly-input;
|
||||
|
||||
.to .ic-Form-control.readonly,
|
||||
.from .ic-Form-control.readonly { // locked availability dates
|
||||
margin-bottom: 0; // removes white space at bottom of assign box
|
||||
|
|
|
@ -42,7 +42,6 @@
|
|||
}
|
||||
|
||||
.bcs__content {
|
||||
width: 270px;
|
||||
border-bottom: 2px solid $ic-border-color;
|
||||
|
||||
.bcs__body {
|
||||
|
|
|
@ -68,7 +68,7 @@
|
|||
"ic-ajax": "~2.0.1",
|
||||
"ic-tabs": "0.1.3",
|
||||
"imports-loader": "^0.7.0",
|
||||
"instructure-ui": "2.5.0",
|
||||
"instructure-ui": "3.2.0",
|
||||
"istanbul-instrumenter-loader": "^3.0.0",
|
||||
"jquery": "https://github.com/ryankshaw/jquery.git#1.7.2-with-AMD-and-CommonJS",
|
||||
"jquery-getscrollbarwidth": "^1.0.0",
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
|
||||
import $ from 'jquery'
|
||||
import './vendor/jquery.scrollTo'
|
||||
import './jquery.instructure_jquery_patches'
|
||||
|
||||
$.fn.scrollToVisible = function(obj) {
|
||||
var options = {};
|
||||
|
|
|
@ -18,10 +18,9 @@
|
|||
|
||||
define([
|
||||
'react',
|
||||
'react-dom',
|
||||
'react-addons-test-utils',
|
||||
'enzyme',
|
||||
'jsx/add_people/components/add_people',
|
||||
], (React, ReactDOM, TestUtils, AddPeople) => {
|
||||
], (React, enzyme, AddPeople) => {
|
||||
QUnit.module('AddPeople');
|
||||
|
||||
const props = {
|
||||
|
@ -39,17 +38,23 @@ define([
|
|||
};
|
||||
|
||||
test('renders the component', () => {
|
||||
const component = TestUtils.renderIntoDocument(
|
||||
const container = document.createElement('div');
|
||||
container.id = 'application';
|
||||
document.body.appendChild(container);
|
||||
|
||||
const wrapper = enzyme.mount(
|
||||
<AddPeople
|
||||
validateUsers={() => {}}
|
||||
enrollUsers={() => {}}
|
||||
reset={() => {}}
|
||||
{...props}
|
||||
/>
|
||||
/>,
|
||||
{ attachTo: document.getElementById('fixtures') }
|
||||
);
|
||||
const addPeople = document.querySelectorAll('.addpeople');
|
||||
equal(addPeople.length, 1, 'AddPeople component rendered.');
|
||||
component.close();
|
||||
ReactDOM.unmountComponentAtNode(component.node._overlay.parentElement);
|
||||
|
||||
ok(document.getElementById('add_people_modal'));
|
||||
|
||||
wrapper.unmount();
|
||||
document.body.removeChild(container);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -20,7 +20,17 @@ import React from 'react'
|
|||
import * as enzyme from 'enzyme'
|
||||
import BlueprintModal from 'jsx/blueprint_courses/components/BlueprintModal'
|
||||
|
||||
QUnit.module('BlueprintModal component')
|
||||
QUnit.module('BlueprintModal component', {
|
||||
setup () {
|
||||
const appElement = document.createElement('div')
|
||||
appElement.id = 'application'
|
||||
document.getElementById('fixtures').appendChild(appElement)
|
||||
},
|
||||
|
||||
teardown () {
|
||||
document.getElementById('fixtures').innerHTML = ''
|
||||
}
|
||||
})
|
||||
|
||||
const defaultProps = () => ({
|
||||
isOpen: true,
|
||||
|
|
|
@ -20,41 +20,41 @@ import React from 'react'
|
|||
import * as enzyme from 'enzyme'
|
||||
import BlueprintSidebar from 'jsx/blueprint_courses/components/BlueprintSidebar'
|
||||
|
||||
QUnit.module('BlueprintSidebar component')
|
||||
QUnit.module('BlueprintSidebar', function (hooks) {
|
||||
let clock
|
||||
let wrapper
|
||||
|
||||
const defaultProps = () => ({
|
||||
hooks.beforeEach(() => {
|
||||
clock = sinon.useFakeTimers()
|
||||
const appElement = document.createElement('div')
|
||||
appElement.id = 'application'
|
||||
document.getElementById('fixtures').appendChild(appElement)
|
||||
})
|
||||
|
||||
})
|
||||
|
||||
test('renders the BlueprintSidebar component', () => {
|
||||
const tree = enzyme.shallow(<BlueprintSidebar {...defaultProps()} />)
|
||||
const node = tree.find('.bcs__wrapper')
|
||||
ok(node.exists())
|
||||
})
|
||||
|
||||
test('clicking open button sets isOpen to true', () => {
|
||||
const props = defaultProps()
|
||||
const tree = enzyme.mount(<BlueprintSidebar {...props} />)
|
||||
|
||||
const button = tree.find('.bcs__trigger button')
|
||||
button.at(0).simulate('click')
|
||||
|
||||
const instance = tree.instance()
|
||||
equal(instance.state.isOpen, true)
|
||||
tree.unmount()
|
||||
})
|
||||
|
||||
test('clicking close button sets isOpen to false', () => {
|
||||
const props = defaultProps()
|
||||
const tree = enzyme.mount(<BlueprintSidebar {...props} />)
|
||||
|
||||
const instance = tree.instance()
|
||||
instance.setState({ isOpen: true })
|
||||
|
||||
const closeBtn = instance.closeBtn
|
||||
const btnWrapper = new enzyme.ReactWrapper(closeBtn, closeBtn)
|
||||
btnWrapper.at(0).simulate('click')
|
||||
|
||||
equal(instance.state.isOpen, false)
|
||||
tree.unmount()
|
||||
hooks.afterEach(() => {
|
||||
wrapper.unmount()
|
||||
document.getElementById('fixtures').innerHTML = ''
|
||||
clock.restore()
|
||||
})
|
||||
|
||||
test('renders the BlueprintSidebar component', () => {
|
||||
wrapper = enzyme.shallow(<BlueprintSidebar />)
|
||||
ok(wrapper.find('.bcs__wrapper').exists())
|
||||
})
|
||||
|
||||
test('clicking open button sets isOpen to true', () => {
|
||||
wrapper = enzyme.mount(<BlueprintSidebar />)
|
||||
wrapper.find('.bcs__trigger button').at(0).simulate('click')
|
||||
clock.tick(500)
|
||||
strictEqual(wrapper.instance().state.isOpen, true)
|
||||
})
|
||||
|
||||
test('clicking close button sets isOpen to false', () => {
|
||||
wrapper = enzyme.mount(<BlueprintSidebar />)
|
||||
wrapper.instance().open()
|
||||
clock.tick(500)
|
||||
wrapper.instance().closeBtn.click()
|
||||
clock.tick(500)
|
||||
strictEqual(wrapper.instance().state.isOpen, false)
|
||||
})
|
||||
})
|
||||
|
|
|
@ -26,6 +26,7 @@ import MigrationStates from 'jsx/blueprint_courses/migrationStates'
|
|||
import sampleData from '../sampleData'
|
||||
import mockStore from '../mockStore'
|
||||
|
||||
let clock
|
||||
let sidebarContentRef = null
|
||||
|
||||
const initialState = {
|
||||
|
@ -53,6 +54,10 @@ function connect (props = defaultProps(), storeState = initialState) {
|
|||
|
||||
QUnit.module('Course Sidebar component', {
|
||||
setup () {
|
||||
clock = sinon.useFakeTimers()
|
||||
const appElement = document.createElement('div')
|
||||
appElement.id = 'application'
|
||||
document.getElementById('fixtures').appendChild(appElement)
|
||||
sidebarContentRef = null
|
||||
moxios.install()
|
||||
moxios.stubRequest('/api/v1/courses/4/blueprint_templates/default/migrations', {
|
||||
|
@ -62,6 +67,8 @@ QUnit.module('Course Sidebar component', {
|
|||
},
|
||||
teardown () {
|
||||
moxios.uninstall()
|
||||
document.getElementById('fixtures').innerHTML = ''
|
||||
clock.restore()
|
||||
}
|
||||
})
|
||||
|
||||
|
@ -75,6 +82,7 @@ test('renders the closed CourseSidebar component', () => {
|
|||
test('renders the open CourseSidebar component', () => {
|
||||
const tree = enzyme.mount(connect())
|
||||
tree.find('button').simulate('click')
|
||||
clock.tick(500)
|
||||
ok(sidebarContentRef, 'sidebar contents')
|
||||
|
||||
const sidebar = new enzyme.ReactWrapper(sidebarContentRef, sidebarContentRef)
|
||||
|
@ -159,6 +167,7 @@ test('renders Sync button if has associations and sync is active and no unsyced
|
|||
state.migrationStatus = MigrationStates.states.imports_queued
|
||||
const tree = enzyme.mount(connect(props, state))
|
||||
tree.find('button').simulate('click')
|
||||
clock.tick(500)
|
||||
ok(sidebarContentRef)
|
||||
const sidebar = new enzyme.ReactWrapper(sidebarContentRef, sidebarContentRef)
|
||||
|
||||
|
@ -171,6 +180,7 @@ test('renders Sync button if has associations and has unsynced changes', () => {
|
|||
const state = {...initialState}
|
||||
const tree = enzyme.mount(connect(props, state))
|
||||
tree.find('button').simulate('click')
|
||||
clock.tick(500)
|
||||
ok(sidebarContentRef)
|
||||
const sidebar = new enzyme.ReactWrapper(sidebarContentRef, sidebarContentRef)
|
||||
|
||||
|
|
|
@ -21,11 +21,24 @@ define([
|
|||
'react-dom',
|
||||
'jsx/conditional_release_stats/components/breakdown-details',
|
||||
], (React, ReactDOM, BreakdownDetails) => {
|
||||
const container = document.getElementById('fixtures')
|
||||
let clock;
|
||||
let container;
|
||||
|
||||
QUnit.module('Breakdown Details', {
|
||||
setup () {
|
||||
const applicationElement = document.createElement('div');
|
||||
applicationElement.id = 'application';
|
||||
document.getElementById('fixtures').appendChild(applicationElement);
|
||||
container = document.createElement('div');
|
||||
document.getElementById('fixtures').appendChild(container);
|
||||
|
||||
clock = sinon.useFakeTimers();
|
||||
},
|
||||
|
||||
teardown() {
|
||||
ReactDOM.unmountComponentAtNode(container);
|
||||
document.getElementById('fixtures').innerHTML = '';
|
||||
clock.restore();
|
||||
}
|
||||
})
|
||||
|
||||
|
@ -172,6 +185,7 @@ define([
|
|||
|
||||
test('renders component correctly', () => {
|
||||
const component = renderComponent(defaultProps())
|
||||
clock.tick(500);
|
||||
|
||||
const rendered = document.querySelectorAll('.crs-breakdown-details')
|
||||
equal(rendered.length, 1)
|
||||
|
@ -182,6 +196,7 @@ define([
|
|||
props.selectedPath.student = 0
|
||||
props.selectStudent = sinon.spy()
|
||||
const component = renderComponent(props)
|
||||
clock.tick(500);
|
||||
|
||||
const nextBtn = document.querySelector('.student-details__next-student')
|
||||
nextBtn.click()
|
||||
|
@ -194,6 +209,7 @@ define([
|
|||
props.selectedPath.student = 1
|
||||
props.selectStudent = sinon.spy()
|
||||
const component = renderComponent(props)
|
||||
clock.tick(500);
|
||||
|
||||
const nextBtn = document.querySelector('.student-details__next-student')
|
||||
nextBtn.click()
|
||||
|
@ -206,6 +222,7 @@ define([
|
|||
props.selectedPath.student = 1
|
||||
props.selectStudent = sinon.spy()
|
||||
const component = renderComponent(props)
|
||||
clock.tick(500);
|
||||
|
||||
const prevBtn = document.querySelector('.student-details__prev-student')
|
||||
prevBtn.click()
|
||||
|
@ -218,6 +235,7 @@ define([
|
|||
props.selectedPath.student = 0
|
||||
props.selectStudent = sinon.spy()
|
||||
const component = renderComponent(props)
|
||||
clock.tick(500);
|
||||
|
||||
const prevBtn = document.querySelector('.student-details__prev-student')
|
||||
prevBtn.click()
|
||||
|
@ -230,6 +248,7 @@ define([
|
|||
props.selectedPath.student = 0
|
||||
props.selectStudent = sinon.spy()
|
||||
const component = renderComponent(props)
|
||||
clock.tick(500);
|
||||
|
||||
const backBtn = document.querySelector('.crs-back-button')
|
||||
backBtn.click()
|
||||
|
|
|
@ -24,6 +24,7 @@ QUnit.module('StudentContextCardTrigger', {
|
|||
setup () {
|
||||
$('#fixtures').append('<button class="student_context_card_trigger">Open</button>');
|
||||
$('#fixtures').append('<div id="StudentTray__Container"></div>');
|
||||
$('#fixtures').append('<div id="application"></div>');
|
||||
window.ENV.STUDENT_CONTEXT_CARDS_ENABLED = true
|
||||
moxios.install();
|
||||
},
|
||||
|
|
|
@ -26,6 +26,9 @@ define([
|
|||
'jsx/context_cards/StudentContextTray',
|
||||
'jsx/context_cards/StudentCardStore'
|
||||
], ($, React, ReactDOM, TestUtils, Avatar, Tray, StudentContextTray, StudentCardStore) => {
|
||||
let fixtureElement
|
||||
let applicationElement
|
||||
|
||||
QUnit.module('StudentContextTray', (hooks) => {
|
||||
let store, subject
|
||||
const courseId = '1'
|
||||
|
@ -42,6 +45,11 @@ define([
|
|||
returnFocusTo={() => {}}
|
||||
/>
|
||||
)
|
||||
fixtureElement = document.createElement('div')
|
||||
document.getElementById('fixtures').appendChild(fixtureElement)
|
||||
applicationElement = document.createElement('div')
|
||||
applicationElement.id = 'application'
|
||||
document.getElementById('fixtures').appendChild(applicationElement)
|
||||
})
|
||||
hooks.afterEach(() => {
|
||||
if (subject) {
|
||||
|
@ -77,6 +85,7 @@ define([
|
|||
})
|
||||
|
||||
test('tray should set focus to the close button when mounting', () => {
|
||||
const clock = sinon.useFakeTimers()
|
||||
store.state.loading = false
|
||||
// eslint-disable-next-line react/no-render-return-value
|
||||
const component = TestUtils.renderIntoDocument(
|
||||
|
@ -86,11 +95,15 @@ define([
|
|||
studentId={studentId}
|
||||
returnFocusTo={() => {}}
|
||||
/>,
|
||||
document.getElementById('fixtures')
|
||||
fixtureElement
|
||||
)
|
||||
|
||||
component.onChange()
|
||||
ok(component.closeButtonRef.focused)
|
||||
clock.tick(1) // perform the setState timeout callback
|
||||
equal(document.activeElement, component.closeButtonRef)
|
||||
const componentNode = ReactDOM.findDOMNode(component)
|
||||
ReactDOM.unmountComponentAtNode(componentNode.parentNode)
|
||||
clock.restore()
|
||||
})
|
||||
|
||||
test('tray should set focus back to the result of the returnFocusTo prop', () => {
|
||||
|
@ -103,7 +116,7 @@ define([
|
|||
studentId={studentId}
|
||||
returnFocusTo={() => [$('#someButton')]}
|
||||
/>,
|
||||
document.getElementById('fixtures')
|
||||
fixtureElement
|
||||
)
|
||||
|
||||
const fakeEvent = {
|
||||
|
@ -111,6 +124,8 @@ define([
|
|||
}
|
||||
component.handleRequestClose(fakeEvent)
|
||||
ok(document.activeElement === document.getElementById('someButton'))
|
||||
const componentNode = ReactDOM.findDOMNode(component)
|
||||
ReactDOM.unmountComponentAtNode(componentNode.parentNode)
|
||||
})
|
||||
|
||||
QUnit.module('analytics button', () => {
|
||||
|
|
|
@ -24,11 +24,9 @@ define([
|
|||
'jsx/eportfolios/MoveToDialog',
|
||||
'helpers/assertions'
|
||||
], (React, ReactDOM, TestUtils, _, MoveToDialog, assertions) => {
|
||||
|
||||
const fixtures = document.getElementById('fixtures')
|
||||
fixtures.innerHTML = '<div id="modalRoot"></div><div id="appRoot"></div>'
|
||||
const root = document.getElementById('modalRoot')
|
||||
const appRoot= document.getElementById('appRoot')
|
||||
let root
|
||||
let appRoot
|
||||
let applicationElement
|
||||
|
||||
const mountDialog = (opts = {}) => {
|
||||
opts = _.extend({}, {
|
||||
|
@ -43,12 +41,20 @@ define([
|
|||
}
|
||||
|
||||
QUnit.module('MoveToDialog', {
|
||||
setup() {
|
||||
setup () {
|
||||
root = document.createElement('div')
|
||||
appRoot = document.createElement('div')
|
||||
applicationElement = document.createElement('div')
|
||||
applicationElement.id = 'application'
|
||||
document.getElementById('fixtures').appendChild(root)
|
||||
document.getElementById('fixtures').appendChild(appRoot)
|
||||
document.getElementById('fixtures').appendChild(applicationElement)
|
||||
},
|
||||
|
||||
teardown() {
|
||||
teardown () {
|
||||
ReactDOM.unmountComponentAtNode(root)
|
||||
appRoot.removeAttribute('aria-hidden')
|
||||
document.getElementById('fixtures').innerHTML = ''
|
||||
}
|
||||
})
|
||||
|
||||
|
@ -103,21 +109,4 @@ define([
|
|||
const button = document.getElementById('MoveToDialog__move')
|
||||
TestUtils.Simulate.click(button)
|
||||
})
|
||||
|
||||
test('handles aria-hides app element on open and close', (assert) => {
|
||||
const done = assert.async()
|
||||
notOk(appRoot.getAttribute('aria-hidden'))
|
||||
mountDialog({
|
||||
appElement: appRoot
|
||||
})
|
||||
|
||||
setTimeout(() => {
|
||||
ok(appRoot.getAttribute('aria-hidden'))
|
||||
|
||||
const button = document.getElementById('MoveToDialog__cancel')
|
||||
TestUtils.Simulate.click(button)
|
||||
notOk(appRoot.getAttribute('aria-hidden'))
|
||||
done()
|
||||
}, 1)
|
||||
})
|
||||
})
|
||||
|
|
|
@ -254,7 +254,11 @@ QUnit.module('SearchForm Autocomplete options', {
|
|||
this.assignments = Fixtures.assignmentArray();
|
||||
this.graders = Fixtures.userArray();
|
||||
this.students = Fixtures.userArray();
|
||||
this.wrapper = mount(<SearchFormComponent {...this.props} />);
|
||||
this.wrapper = mount(<SearchFormComponent {...this.props} />, {attachTo: document.getElementById('fixtures')});
|
||||
},
|
||||
|
||||
teardown () {
|
||||
this.wrapper.unmount();
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -3104,6 +3104,7 @@ QUnit.module('Menus', {
|
|||
this.gradebook.postGradesLtis = [];
|
||||
this.gradebook.postGradesStore = {};
|
||||
$fixtures.innerHTML = `
|
||||
<div id="application"></div>
|
||||
<span data-component="ViewOptionsMenu"></span>
|
||||
<span data-component="ActionMenu"></span>
|
||||
<span data-component="GradebookMenu" data-variant="DefaultGradebook"></span>
|
||||
|
@ -3137,13 +3138,16 @@ test('GradebookMenu is rendered on renderGradebookMenu', function () {
|
|||
});
|
||||
|
||||
test('StatusesModal is mounted on renderStatusesModal', function () {
|
||||
const clock = sinon.useFakeTimers();
|
||||
const statusModal = this.gradebook.renderStatusesModal();
|
||||
statusModal.open();
|
||||
clock.tick(500); // wait for Modal to transition open
|
||||
const header = document.querySelector('h3');
|
||||
equal(header.innerText, 'Statuses');
|
||||
|
||||
const statusesModalMountPoint = document.querySelector("[data-component='StatusesModal']");
|
||||
ReactDOM.unmountComponentAtNode(statusesModalMountPoint);
|
||||
clock.restore();
|
||||
});
|
||||
|
||||
QUnit.module('setupGrading', {
|
||||
|
@ -6059,13 +6063,12 @@ test('includes the column ids for related assignments when updating column heade
|
|||
QUnit.module('Gradebook#renderSubmissionTray', {
|
||||
setup () {
|
||||
this.mountPointId = 'StudentTray__Container';
|
||||
$fixtures.innerHTML = `<div id=${this.mountPointId}></div>`;
|
||||
$fixtures.innerHTML = `<div id="${this.mountPointId}"></div><div id="application"></div>`;
|
||||
this.gradebook = createGradebook();
|
||||
this.gradebook.students = {
|
||||
1101: {
|
||||
id: '1101',
|
||||
name: 'Adam Jones',
|
||||
wtf: true,
|
||||
assignment_2301: {
|
||||
assignment_id: '2301', late: false, missing: false, excused: false, seconds_late: 0
|
||||
}
|
||||
|
@ -6093,22 +6096,31 @@ QUnit.module('Gradebook#renderSubmissionTray', {
|
|||
});
|
||||
|
||||
test('shows a submission tray on the page when rendering an open tray', function () {
|
||||
const clock = sinon.useFakeTimers();
|
||||
this.gradebook.setSubmissionTrayState(true, '1101', '2301');
|
||||
this.gradebook.renderSubmissionTray(this.gradebook.student('1101'));
|
||||
ok(document.querySelector('div[aria-label="Submission tray"]'));
|
||||
clock.tick(500); // wait for Tray to transition open
|
||||
ok(document.querySelector('[aria-label="Submission tray"]'));
|
||||
clock.restore();
|
||||
});
|
||||
|
||||
test('does not show a submission tray on the page when rendering a closed tray', function () {
|
||||
const clock = sinon.useFakeTimers();
|
||||
this.gradebook.setSubmissionTrayState(false, '1101', '2301');
|
||||
this.gradebook.renderSubmissionTray(this.gradebook.student('1101'));
|
||||
notOk(document.querySelector('div[aria-label="Submission tray"]'));
|
||||
clock.tick(500); // wait for Tray transition to ensure it has not opened
|
||||
notOk(document.querySelector('[aria-label="Submission tray"]'));
|
||||
clock.restore();
|
||||
});
|
||||
|
||||
test('shows a submission tray when the related submission has not loaded for the student', function () {
|
||||
const clock = sinon.useFakeTimers();
|
||||
this.gradebook.setSubmissionTrayState(true, '1101', '2301');
|
||||
this.gradebook.student('1101').assignment_2301 = undefined;
|
||||
this.gradebook.renderSubmissionTray(this.gradebook.student('1101'));
|
||||
ok(document.querySelector('div[aria-label="Submission tray"]'));
|
||||
clock.tick(500); // wait for Tray to transition open
|
||||
ok(document.querySelector('[aria-label="Submission tray"]'));
|
||||
clock.restore();
|
||||
});
|
||||
|
||||
QUnit.module('Gradebook#updateRowAndRenderSubmissionTray', {
|
||||
|
|
|
@ -16,11 +16,16 @@
|
|||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { createGradebook } from 'spec/jsx/gradezilla/default_gradebook/GradebookSpecHelper';
|
||||
import { createGradebook, setFixtureHtml } from 'spec/jsx/gradezilla/default_gradebook/GradebookSpecHelper';
|
||||
import AssignmentRowCellPropFactory from 'jsx/gradezilla/default_gradebook/components/AssignmentRowCellPropFactory';
|
||||
|
||||
let fixture;
|
||||
|
||||
QUnit.module('AssignmentRowCellPropFactory#getProps', {
|
||||
setup () {
|
||||
fixture = document.createElement('div');
|
||||
document.body.appendChild(fixture);
|
||||
setFixtureHtml(fixture);
|
||||
this.assignment = { id: '2301' };
|
||||
this.gradebook = createGradebook({ context_id: '1201' });
|
||||
this.gradebook.gridSupport = {
|
||||
|
@ -31,6 +36,10 @@ QUnit.module('AssignmentRowCellPropFactory#getProps', {
|
|||
};
|
||||
this.factory = new AssignmentRowCellPropFactory(this.assignment, this.gradebook);
|
||||
this.student = { id: '1101', isConcluded: false };
|
||||
},
|
||||
|
||||
teardown () {
|
||||
fixture.remove();
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -22,10 +22,16 @@ import GradebookSettingsModal from 'jsx/gradezilla/default_gradebook/components/
|
|||
import GradebookSettingsModalApi from 'jsx/gradezilla/default_gradebook/apis/GradebookSettingsModalApi';
|
||||
import { destroyContainer } from 'jsx/shared/FlashAlert';
|
||||
|
||||
let clock;
|
||||
|
||||
QUnit.module('GradebookSettingsModal', {
|
||||
setup () {
|
||||
clock = sinon.useFakeTimers();
|
||||
this.qunitTimeout = QUnit.config.testTimeout;
|
||||
QUnit.config.testTimeout = 1000;
|
||||
const applicationElement = document.createElement('div');
|
||||
applicationElement.id = 'application';
|
||||
document.getElementById('fixtures').appendChild(applicationElement);
|
||||
},
|
||||
|
||||
mountComponent (customProps = {}) {
|
||||
|
@ -67,12 +73,14 @@ QUnit.module('GradebookSettingsModal', {
|
|||
QUnit.config.testTimeout = this.qunitTimeout;
|
||||
this.wrapper.unmount();
|
||||
destroyContainer();
|
||||
document.getElementById('fixtures').innerHTML = '';
|
||||
clock.restore();
|
||||
}
|
||||
});
|
||||
|
||||
test('modal is initially closed', function () {
|
||||
this.mountComponent();
|
||||
equal(this.wrapper.find('Modal').prop('isOpen'), false);
|
||||
equal(this.wrapper.find('Modal').prop('open'), false);
|
||||
});
|
||||
|
||||
test('calling open causes the modal to be rendered', function () {
|
||||
|
@ -80,7 +88,7 @@ test('calling open causes the modal to be rendered', function () {
|
|||
const fetchLatePolicy = this.stubLatePolicyFetchSuccess(component);
|
||||
component.open();
|
||||
return fetchLatePolicy.then(() => {
|
||||
equal(this.wrapper.find('Modal').prop('isOpen'), true);
|
||||
equal(this.wrapper.find('Modal').prop('open'), true);
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -89,9 +97,9 @@ test('calling close closes the modal', function () {
|
|||
const fetchLatePolicy = this.stubLatePolicyFetchSuccess(component);
|
||||
component.open();
|
||||
return fetchLatePolicy.then(() => {
|
||||
equal(this.wrapper.find('Modal').prop('isOpen'), true, 'modal is open');
|
||||
equal(this.wrapper.find('Modal').prop('open'), true, 'modal is open');
|
||||
component.close();
|
||||
equal(this.wrapper.find('Modal').prop('isOpen'), false, 'modal is closed');
|
||||
equal(this.wrapper.find('Modal').prop('open'), false, 'modal is closed');
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -99,10 +107,11 @@ test('clicking cancel closes the modal', function () {
|
|||
const component = this.mountComponent();
|
||||
const fetchLatePolicy = this.stubLatePolicyFetchSuccess(component);
|
||||
component.open();
|
||||
clock.tick(50); // wait for Modal to transition open
|
||||
return fetchLatePolicy.then(() => {
|
||||
equal(this.wrapper.find('Modal').prop('isOpen'), true);
|
||||
equal(this.wrapper.find('Modal').prop('open'), true);
|
||||
document.getElementById('gradebook-settings-cancel-button').click();
|
||||
equal(this.wrapper.find('Modal').prop('isOpen'), false);
|
||||
equal(this.wrapper.find('Modal').prop('open'), false);
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -110,6 +119,7 @@ test('the "Update" button is disabled when the modal opens', function () {
|
|||
const component = this.mountComponent();
|
||||
const fetchLatePolicy = this.stubLatePolicyFetchSuccess(component);
|
||||
component.open();
|
||||
clock.tick(50); // wait for Modal to transition open
|
||||
return fetchLatePolicy.then(() => {
|
||||
const updateButton = document.getElementById('gradebook-settings-update-button')
|
||||
ok(updateButton.getAttribute('aria-disabled'));
|
||||
|
@ -120,6 +130,7 @@ test('the "Update" button is enabled if a setting is changed', function () {
|
|||
const component = this.mountComponent();
|
||||
const fetchLatePolicy = this.stubLatePolicyFetchSuccess(component);
|
||||
component.open();
|
||||
clock.tick(50); // wait for Modal to transition open
|
||||
return fetchLatePolicy.then(() => {
|
||||
component.changeLatePolicy({ ...component.state.latePolicy, changes: { lateSubmissionDeductionEnabled: true } });
|
||||
const updateButton = document.getElementById('gradebook-settings-update-button');
|
||||
|
@ -131,6 +142,7 @@ test('the "Update" button is disabled if a setting is changed, but there are val
|
|||
const component = this.mountComponent();
|
||||
const fetchLatePolicy = this.stubLatePolicyFetchSuccess(component);
|
||||
component.open();
|
||||
clock.tick(50); // wait for Modal to transition open
|
||||
return fetchLatePolicy.then(() => {
|
||||
component.changeLatePolicy({
|
||||
...component.state.latePolicy,
|
||||
|
@ -147,6 +159,7 @@ test('clicking "Update" sends a request to update the late policy', function ()
|
|||
const component = this.mountComponent();
|
||||
const fetchLatePolicy = this.stubLatePolicyFetchSuccess(component);
|
||||
component.open();
|
||||
clock.tick(50); // wait for Modal to transition open
|
||||
return fetchLatePolicy.then(() => {
|
||||
const changes = { lateSubmissionDeductionEnabled: true };
|
||||
component.changeLatePolicy({ ...component.state.latePolicy, changes });
|
||||
|
@ -164,6 +177,7 @@ test('clicking "Update" sends a post request to create a late policy if one does
|
|||
const component = this.mountComponent();
|
||||
const fetchLatePolicy = this.stubLatePolicyFetchSuccess(component, { newRecord: true });
|
||||
component.open();
|
||||
clock.tick(50); // wait for Modal to transition open
|
||||
|
||||
return fetchLatePolicy.then(() => {
|
||||
const changes = { lateSubmissionDeductionEnabled: true };
|
||||
|
|
|
@ -21,6 +21,8 @@ import { shallow, mount, ReactWrapper } from 'enzyme';
|
|||
import StatusesModal from 'jsx/gradezilla/default_gradebook/components/StatusesModal';
|
||||
import { statusColors } from 'jsx/gradezilla/default_gradebook/constants/colors';
|
||||
|
||||
let clock;
|
||||
|
||||
function defaultProps (props = {}) {
|
||||
return {
|
||||
colors: statusColors(),
|
||||
|
@ -30,219 +32,238 @@ function defaultProps (props = {}) {
|
|||
};
|
||||
}
|
||||
|
||||
QUnit.module('StatusesModal', {
|
||||
setup () {
|
||||
this.wrapper = shallow(
|
||||
<StatusesModal {...defaultProps()} />
|
||||
);
|
||||
},
|
||||
QUnit.module('StatusesModal', function (suiteHooks) {
|
||||
suiteHooks.beforeEach(function () {
|
||||
const applicationElement = document.createElement('div');
|
||||
applicationElement.id = 'application';
|
||||
document.getElementById('fixtures').appendChild(applicationElement);
|
||||
clock = sinon.useFakeTimers();
|
||||
});
|
||||
|
||||
teardown () {
|
||||
this.wrapper.unmount();
|
||||
}
|
||||
});
|
||||
|
||||
test('modal is initially closed', function () {
|
||||
strictEqual(this.wrapper.find('Modal').prop('isOpen'), false);
|
||||
});
|
||||
|
||||
test('modal has a label of "Statuses"', function () {
|
||||
equal(this.wrapper.find('Modal').prop('label'), 'Statuses');
|
||||
});
|
||||
|
||||
test('modal has a close button label of "Close"', function () {
|
||||
equal(this.wrapper.find('Modal').prop('closeButtonLabel'), 'Close');
|
||||
});
|
||||
|
||||
test('modal has an onRequestClose function', function () {
|
||||
equal(typeof this.wrapper.find('Modal').prop('onRequestClose'), 'function');
|
||||
});
|
||||
|
||||
test('modal has an onExited function', function () {
|
||||
equal(typeof this.wrapper.find('Modal').prop('onRequestClose'), 'function');
|
||||
});
|
||||
|
||||
test('modal has a "Statuses" header', function () {
|
||||
equal(this.wrapper.find('Heading').children().text(), 'Statuses');
|
||||
});
|
||||
|
||||
test('modal has a "Done" button', function () {
|
||||
equal(this.wrapper.find('Button').children().text(), 'Done');
|
||||
});
|
||||
|
||||
test('modal opens', function () {
|
||||
this.wrapper.instance().open();
|
||||
strictEqual(this.wrapper.find('Modal').prop('isOpen'), true);
|
||||
});
|
||||
|
||||
test('modal closes', function () {
|
||||
const statusModal = this.wrapper.instance();
|
||||
statusModal.open();
|
||||
statusModal.close();
|
||||
strictEqual(this.wrapper.find('Modal').prop('isOpen'), false);
|
||||
});
|
||||
|
||||
test('on close prop is passed to Modal onExit', function () {
|
||||
const onClose = this.stub();
|
||||
const wrapper = shallow(<StatusesModal {...defaultProps({ onClose })} />);
|
||||
equal(wrapper.find('Modal').prop('onExited'), onClose);
|
||||
});
|
||||
|
||||
QUnit.module('StatusesModal#isPopoverShown', {
|
||||
setup () {
|
||||
this.wrapper = shallow(<StatusesModal {...defaultProps()} />);
|
||||
this.instance = this.wrapper.instance();
|
||||
},
|
||||
teardown () {
|
||||
this.wrapper.unmount();
|
||||
}
|
||||
});
|
||||
|
||||
test('it is true when statuses matches openPopover', function () {
|
||||
const status = 'late';
|
||||
this.instance.handleOnToggle(status)(true);
|
||||
strictEqual(this.instance.isPopoverShown(status), true);
|
||||
});
|
||||
|
||||
test('it is when statuses does not match openPopover', function () {
|
||||
this.instance.handleOnToggle('late')(true);
|
||||
strictEqual(this.instance.isPopoverShown('missing'), false);
|
||||
});
|
||||
|
||||
QUnit.module('StatusesModal#updateStatusColors');
|
||||
|
||||
test('it calls afterUpdateStatusColors', function () {
|
||||
const afterUpdateStatusColors = this.stub();
|
||||
const wrapper = shallow(<StatusesModal {...defaultProps({ afterUpdateStatusColors })} />);
|
||||
const instance = wrapper.instance();
|
||||
instance.updateStatusColors('late')('#000000');
|
||||
strictEqual(afterUpdateStatusColors.callCount, 1);
|
||||
wrapper.unmount();
|
||||
});
|
||||
|
||||
test('it calls afterUpdateStatusColors with updated colors', function () {
|
||||
const afterUpdateStatusColors = this.stub();
|
||||
const color = '#000000';
|
||||
const expectedColors = {
|
||||
late: color,
|
||||
missing: '#FFE8E5',
|
||||
resubmitted: '#E5F7E5',
|
||||
dropped: '#FEF0E5',
|
||||
excused: '#FEF7E5'
|
||||
};
|
||||
const wrapper = shallow(<StatusesModal {...defaultProps({ afterUpdateStatusColors })} />);
|
||||
const instance = wrapper.instance();
|
||||
instance.updateStatusColors('late')(color);
|
||||
|
||||
deepEqual(afterUpdateStatusColors.firstCall.args[0], expectedColors);
|
||||
wrapper.unmount();
|
||||
});
|
||||
|
||||
test('it calls afterUpdateStatusColors with updated successFn', function () {
|
||||
const successFn = this.stub();
|
||||
function afterUpdateStatusColors (_color, fn) { fn(); }
|
||||
const wrapper = shallow(<StatusesModal {...defaultProps({ afterUpdateStatusColors })} />);
|
||||
const instance = wrapper.instance();
|
||||
instance.updateStatusColors('late')('#000000', successFn);
|
||||
|
||||
strictEqual(successFn.calledOnce, true);
|
||||
wrapper.unmount();
|
||||
});
|
||||
|
||||
test('it calls afterUpdateStatusColors and sets openPopover to null', function () {
|
||||
const successFn = this.stub();
|
||||
function afterUpdateStatusColors (_color, fn) { fn(); }
|
||||
const wrapper = shallow(<StatusesModal {...defaultProps({ afterUpdateStatusColors })} />);
|
||||
const instance = wrapper.instance();
|
||||
instance.updateStatusColors('late')('#000000', successFn);
|
||||
|
||||
strictEqual(instance.isPopoverShown(null), true);
|
||||
wrapper.unmount();
|
||||
});
|
||||
|
||||
test('it calls afterUpdateStatusColors with updated failureFn', function () {
|
||||
const failureFn = this.stub();
|
||||
function afterUpdateStatusColors (_color, _fn, fn) { fn(); }
|
||||
const wrapper = shallow(<StatusesModal {...defaultProps({ afterUpdateStatusColors })} />);
|
||||
const instance = wrapper.instance();
|
||||
instance.updateStatusColors('late')('#000000', () => {}, failureFn);
|
||||
|
||||
strictEqual(failureFn.calledOnce, true);
|
||||
wrapper.unmount();
|
||||
});
|
||||
|
||||
QUnit.module('StatusesModal Behavior', {
|
||||
setup () {
|
||||
this.wrapper = shallow(<StatusesModal {...defaultProps()} />);
|
||||
this.instance = this.wrapper.instance();
|
||||
},
|
||||
teardown () {
|
||||
this.wrapper.unmount();
|
||||
}
|
||||
});
|
||||
|
||||
test('clicking Done closes the popover', function () {
|
||||
const { wrapper, instance } = this;
|
||||
instance.open();
|
||||
wrapper.find('Button').simulate('click');
|
||||
strictEqual(wrapper.find('Modal').prop('isOpen'), false);
|
||||
});
|
||||
|
||||
test('renders five StatusColorListItems', function () {
|
||||
const { wrapper, instance } = this;
|
||||
instance.open();
|
||||
strictEqual(wrapper.find('StatusColorListItem').length, 5);
|
||||
});
|
||||
|
||||
QUnit.module('StatusesModal integration behavior with StatusColorListItem', {
|
||||
setup () {
|
||||
const afterUpdateStatusColors = (color, successFn) => successFn();
|
||||
this.wrapper = mount(<StatusesModal {...defaultProps({ afterUpdateStatusColors })} />);
|
||||
this.instance = this.wrapper.instance();
|
||||
},
|
||||
teardown () {
|
||||
this.wrapper.unmount();
|
||||
}
|
||||
});
|
||||
|
||||
test('after clicking apply in the color picker, the color picker popover is closed', function () {
|
||||
const { wrapper, instance } = this;
|
||||
instance.open();
|
||||
const modalContent = new ReactWrapper(wrapper.node.modalContentRef, wrapper.node);
|
||||
modalContent.find('StatusColorListItem PopoverTrigger Button').at(0).simulate('click');
|
||||
const colorPickerContent = new ReactWrapper(wrapper.node.colorPickerContents.late, wrapper.node);
|
||||
const applyButton = colorPickerContent.find('button').findWhere(button => button.prop('children') === 'Apply');
|
||||
applyButton.simulate('click');
|
||||
strictEqual(modalContent.find('StatusColorListItem Popover').at(0).prop('show'), false);
|
||||
});
|
||||
|
||||
test('after clicking cancel in the color picker, the color picker popover is closed', function () {
|
||||
const { wrapper, instance } = this;
|
||||
instance.open();
|
||||
const modalContent = new ReactWrapper(wrapper.node.modalContentRef, wrapper.node);
|
||||
modalContent.find('StatusColorListItem PopoverTrigger Button').at(0).simulate('click');
|
||||
const colorPickerContent = new ReactWrapper(wrapper.node.colorPickerContents.late, wrapper.node);
|
||||
const applyButton = colorPickerContent.find('button').findWhere(button => button.prop('children') === 'Cancel');
|
||||
applyButton.simulate('click');
|
||||
strictEqual(modalContent.find('StatusColorListItem Popover').at(0).prop('show'), false);
|
||||
});
|
||||
|
||||
QUnit.module('StatusesModal integration behavior with StatusColorListItem');
|
||||
|
||||
|
||||
test('selecting a color and clicking Apply in the color picker passes the ' +
|
||||
'color to afterUpdateStatusColors', function () {
|
||||
const afterUpdateStatusColors = this.stub();
|
||||
const wrapper = mount(<StatusesModal {...defaultProps({ afterUpdateStatusColors })} />);
|
||||
const instance = wrapper.instance();
|
||||
instance.open();
|
||||
const modalContent = new ReactWrapper(wrapper.node.modalContentRef, wrapper.node);
|
||||
modalContent.find('StatusColorListItem PopoverTrigger Button').at(0).simulate('click');
|
||||
const colorPickerContent = new ReactWrapper(wrapper.node.colorPickerContents.late, wrapper.node);
|
||||
const whiteSwatch = colorPickerContent.find('button').findWhere(button => button.prop('title') === 'white (#FFFFFF)');
|
||||
whiteSwatch.simulate('click');
|
||||
const applyButton = colorPickerContent.find('button').findWhere(button => button.prop('children') === 'Apply');
|
||||
applyButton.simulate('click');
|
||||
strictEqual(afterUpdateStatusColors.firstCall.args[0].late, '#FFFFFF');
|
||||
wrapper.unmount();
|
||||
suiteHooks.afterEach(function () {
|
||||
document.getElementById('fixtures').innerHTML = '';
|
||||
clock.restore();
|
||||
});
|
||||
|
||||
QUnit.module('StatusesModal', {
|
||||
setup () {
|
||||
this.wrapper = shallow(
|
||||
<StatusesModal {...defaultProps()} />
|
||||
);
|
||||
},
|
||||
|
||||
teardown () {
|
||||
this.wrapper.unmount();
|
||||
document.getElementById('fixtures').innerHTML = '';
|
||||
}
|
||||
});
|
||||
|
||||
test('modal is initially closed', function () {
|
||||
strictEqual(this.wrapper.find('Modal').prop('open'), false);
|
||||
});
|
||||
|
||||
test('modal has a label of "Statuses"', function () {
|
||||
equal(this.wrapper.find('Modal').prop('label'), 'Statuses');
|
||||
});
|
||||
|
||||
test('modal has a close button label of "Close"', function () {
|
||||
equal(this.wrapper.find('Modal').prop('closeButtonLabel'), 'Close');
|
||||
});
|
||||
|
||||
test('modal has an onDismiss function', function () {
|
||||
equal(typeof this.wrapper.find('Modal').prop('onDismiss'), 'function');
|
||||
});
|
||||
|
||||
test('modal has an onExited function', function () {
|
||||
equal(typeof this.wrapper.find('Modal').prop('onExited'), 'function');
|
||||
});
|
||||
|
||||
test('modal has a "Statuses" header', function () {
|
||||
equal(this.wrapper.find('Heading').children().text(), 'Statuses');
|
||||
});
|
||||
|
||||
test('modal has a "Done" button', function () {
|
||||
equal(this.wrapper.find('Button').children().text(), 'Done');
|
||||
});
|
||||
|
||||
test('modal opens', function () {
|
||||
this.wrapper.instance().open();
|
||||
strictEqual(this.wrapper.find('Modal').prop('open'), true);
|
||||
});
|
||||
|
||||
test('modal closes', function () {
|
||||
const statusModal = this.wrapper.instance();
|
||||
statusModal.open();
|
||||
clock.tick(50); // wait for Modal to transition open
|
||||
statusModal.close();
|
||||
clock.tick(50); // wait for Modal to transition closed
|
||||
strictEqual(this.wrapper.find('Modal').prop('open'), false);
|
||||
});
|
||||
|
||||
test('on close prop is passed to Modal onExit', function () {
|
||||
const onClose = this.stub();
|
||||
const wrapper = shallow(<StatusesModal {...defaultProps({ onClose })} />);
|
||||
equal(wrapper.find('Modal').prop('onExited'), onClose);
|
||||
});
|
||||
|
||||
QUnit.module('StatusesModal#isPopoverShown', {
|
||||
setup () {
|
||||
this.wrapper = shallow(<StatusesModal {...defaultProps()} />);
|
||||
this.instance = this.wrapper.instance();
|
||||
},
|
||||
teardown () {
|
||||
this.wrapper.unmount();
|
||||
}
|
||||
});
|
||||
|
||||
test('it is true when statuses matches openPopover', function () {
|
||||
const status = 'late';
|
||||
this.instance.handleOnToggle(status)(true);
|
||||
strictEqual(this.instance.isPopoverShown(status), true);
|
||||
});
|
||||
|
||||
test('it is when statuses does not match openPopover', function () {
|
||||
this.instance.handleOnToggle('late')(true);
|
||||
strictEqual(this.instance.isPopoverShown('missing'), false);
|
||||
});
|
||||
|
||||
QUnit.module('StatusesModal#updateStatusColors');
|
||||
|
||||
test('it calls afterUpdateStatusColors', function () {
|
||||
const afterUpdateStatusColors = this.stub();
|
||||
const wrapper = shallow(<StatusesModal {...defaultProps({ afterUpdateStatusColors })} />);
|
||||
const instance = wrapper.instance();
|
||||
instance.updateStatusColors('late')('#000000');
|
||||
strictEqual(afterUpdateStatusColors.callCount, 1);
|
||||
wrapper.unmount();
|
||||
});
|
||||
|
||||
test('it calls afterUpdateStatusColors with updated colors', function () {
|
||||
const afterUpdateStatusColors = this.stub();
|
||||
const color = '#000000';
|
||||
const expectedColors = {
|
||||
late: color,
|
||||
missing: '#FFE8E5',
|
||||
resubmitted: '#E5F7E5',
|
||||
dropped: '#FEF0E5',
|
||||
excused: '#FEF7E5'
|
||||
};
|
||||
const wrapper = shallow(<StatusesModal {...defaultProps({ afterUpdateStatusColors })} />);
|
||||
const instance = wrapper.instance();
|
||||
instance.updateStatusColors('late')(color);
|
||||
|
||||
deepEqual(afterUpdateStatusColors.firstCall.args[0], expectedColors);
|
||||
wrapper.unmount();
|
||||
});
|
||||
|
||||
test('it calls afterUpdateStatusColors with updated successFn', function () {
|
||||
const successFn = this.stub();
|
||||
function afterUpdateStatusColors (_color, fn) { fn(); }
|
||||
const wrapper = shallow(<StatusesModal {...defaultProps({ afterUpdateStatusColors })} />);
|
||||
const instance = wrapper.instance();
|
||||
instance.updateStatusColors('late')('#000000', successFn);
|
||||
|
||||
strictEqual(successFn.calledOnce, true);
|
||||
wrapper.unmount();
|
||||
});
|
||||
|
||||
test('it calls afterUpdateStatusColors and sets openPopover to null', function () {
|
||||
const successFn = this.stub();
|
||||
function afterUpdateStatusColors (_color, fn) { fn(); }
|
||||
const wrapper = shallow(<StatusesModal {...defaultProps({ afterUpdateStatusColors })} />);
|
||||
const instance = wrapper.instance();
|
||||
instance.updateStatusColors('late')('#000000', successFn);
|
||||
|
||||
strictEqual(instance.isPopoverShown(null), true);
|
||||
wrapper.unmount();
|
||||
});
|
||||
|
||||
test('it calls afterUpdateStatusColors with updated failureFn', function () {
|
||||
const failureFn = this.stub();
|
||||
function afterUpdateStatusColors (_color, _fn, fn) { fn(); }
|
||||
const wrapper = shallow(<StatusesModal {...defaultProps({ afterUpdateStatusColors })} />);
|
||||
const instance = wrapper.instance();
|
||||
instance.updateStatusColors('late')('#000000', () => {}, failureFn);
|
||||
|
||||
strictEqual(failureFn.calledOnce, true);
|
||||
wrapper.unmount();
|
||||
});
|
||||
|
||||
QUnit.module('StatusesModal Behavior', {
|
||||
setup () {
|
||||
this.wrapper = shallow(<StatusesModal {...defaultProps()} />);
|
||||
this.instance = this.wrapper.instance();
|
||||
},
|
||||
teardown () {
|
||||
this.wrapper.unmount();
|
||||
}
|
||||
});
|
||||
|
||||
test('clicking Done closes the popover', function () {
|
||||
const { wrapper, instance } = this;
|
||||
instance.open();
|
||||
wrapper.find('Button').simulate('click');
|
||||
strictEqual(wrapper.find('Modal').prop('open'), false);
|
||||
});
|
||||
|
||||
test('renders five StatusColorListItems', function () {
|
||||
const { wrapper, instance } = this;
|
||||
instance.open();
|
||||
strictEqual(wrapper.find('StatusColorListItem').length, 5);
|
||||
});
|
||||
|
||||
QUnit.module('StatusesModal integration behavior with StatusColorListItem', {
|
||||
setup () {
|
||||
const afterUpdateStatusColors = (color, successFn) => successFn();
|
||||
this.wrapper = mount(<StatusesModal {...defaultProps({ afterUpdateStatusColors })} />);
|
||||
this.instance = this.wrapper.instance();
|
||||
},
|
||||
teardown () {
|
||||
this.wrapper.unmount();
|
||||
}
|
||||
});
|
||||
|
||||
test('after clicking apply in the color picker, the color picker popover is closed', function () {
|
||||
const { wrapper, instance } = this;
|
||||
instance.open();
|
||||
clock.tick(50); // wait for Modal to transition open
|
||||
const modalContent = new ReactWrapper(wrapper.node.modalContentRef, wrapper.node);
|
||||
modalContent.find('StatusColorListItem PopoverTrigger Button').at(0).simulate('click');
|
||||
const colorPickerContent = new ReactWrapper(wrapper.node.colorPickerContents.late, wrapper.node);
|
||||
const applyButton = colorPickerContent.find('button').findWhere(button => button.prop('children') === 'Apply');
|
||||
applyButton.simulate('click');
|
||||
strictEqual(modalContent.find('StatusColorListItem Popover').at(0).prop('show'), false);
|
||||
});
|
||||
|
||||
test('after clicking cancel in the color picker, the color picker popover is closed', function () {
|
||||
const { wrapper, instance } = this;
|
||||
instance.open();
|
||||
clock.tick(50); // wait for Modal to transition open
|
||||
const modalContent = new ReactWrapper(wrapper.node.modalContentRef, wrapper.node);
|
||||
modalContent.find('StatusColorListItem PopoverTrigger Button').at(0).simulate('click');
|
||||
const colorPickerContent = new ReactWrapper(wrapper.node.colorPickerContents.late, wrapper.node);
|
||||
const applyButton = colorPickerContent.find('button').findWhere(button => button.prop('children') === 'Cancel');
|
||||
applyButton.simulate('click');
|
||||
strictEqual(modalContent.find('StatusColorListItem Popover').at(0).prop('show'), false);
|
||||
});
|
||||
|
||||
QUnit.module('StatusesModal integration behavior with StatusColorListItem');
|
||||
|
||||
test('selecting a color and clicking Apply in the color picker passes the ' +
|
||||
'color to afterUpdateStatusColors', function () {
|
||||
const afterUpdateStatusColors = this.stub();
|
||||
const wrapper = mount(<StatusesModal {...defaultProps({ afterUpdateStatusColors })} />);
|
||||
const instance = wrapper.instance();
|
||||
instance.open();
|
||||
clock.tick(50); // wait for Modal to transition open
|
||||
const modalContent = new ReactWrapper(wrapper.node.modalContentRef, wrapper.node);
|
||||
modalContent.find('StatusColorListItem PopoverTrigger Button').at(0).simulate('click');
|
||||
const colorPickerContent = new ReactWrapper(wrapper.node.colorPickerContents.late, wrapper.node);
|
||||
const whiteSwatch = colorPickerContent.find('button').findWhere(button => button.prop('title') === 'white (#FFFFFF)');
|
||||
whiteSwatch.simulate('click');
|
||||
const applyButton = colorPickerContent.find('button').findWhere(button => button.prop('children') === 'Apply');
|
||||
applyButton.simulate('click');
|
||||
strictEqual(afterUpdateStatusColors.firstCall.args[0].late, '#FFFFFF');
|
||||
wrapper.unmount();
|
||||
});
|
||||
});
|
||||
|
|
|
@ -21,11 +21,21 @@ import { mount, ReactWrapper } from 'enzyme';
|
|||
import SubmissionTray from 'jsx/gradezilla/default_gradebook/components/SubmissionTray';
|
||||
|
||||
QUnit.module('SubmissionTray', function (hooks) {
|
||||
let clock;
|
||||
let content;
|
||||
let wrapper;
|
||||
|
||||
hooks.beforeEach(function () {
|
||||
const applicationElement = document.createElement('div');
|
||||
applicationElement.id = 'application';
|
||||
document.getElementById('fixtures').appendChild(applicationElement);
|
||||
clock = sinon.useFakeTimers();
|
||||
});
|
||||
|
||||
hooks.afterEach(function () {
|
||||
wrapper.unmount();
|
||||
document.getElementById('fixtures').innerHTML = '';
|
||||
clock.restore();
|
||||
});
|
||||
|
||||
function mountComponent (props) {
|
||||
|
@ -70,6 +80,7 @@ QUnit.module('SubmissionTray', function (hooks) {
|
|||
selectPreviousAssignment: () => {}
|
||||
};
|
||||
wrapper = mount(<SubmissionTray {...defaultProps} {...props} />);
|
||||
clock.tick(50); // wait for Tray to transition open
|
||||
}
|
||||
|
||||
function avatarDiv () {
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
*/
|
||||
|
||||
import ReactDOM from 'react-dom';
|
||||
import { createGradebook } from 'spec/jsx/gradezilla/default_gradebook/GradebookSpecHelper';
|
||||
import { createGradebook, setFixtureHtml } from 'spec/jsx/gradezilla/default_gradebook/GradebookSpecHelper';
|
||||
import AssignmentColumnHeaderRenderer
|
||||
from 'jsx/gradezilla/default_gradebook/slick-grid/column-headers/AssignmentColumnHeaderRenderer';
|
||||
|
||||
|
@ -35,6 +35,8 @@ QUnit.module('AssignmentColumnHeaderRenderer', function (suiteHooks) {
|
|||
|
||||
suiteHooks.beforeEach(function () {
|
||||
$container = document.createElement('div');
|
||||
document.body.appendChild($container);
|
||||
setFixtureHtml($container);
|
||||
|
||||
gradebook = createGradebook();
|
||||
|
||||
|
@ -58,6 +60,10 @@ QUnit.module('AssignmentColumnHeaderRenderer', function (suiteHooks) {
|
|||
renderer = new AssignmentColumnHeaderRenderer(gradebook);
|
||||
});
|
||||
|
||||
suiteHooks.afterEach(function() {
|
||||
$container.remove();
|
||||
});
|
||||
|
||||
QUnit.module('#render', function () {
|
||||
test('renders the AssignmentColumnHeader to the given container node', function () {
|
||||
render();
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
*/
|
||||
|
||||
import ReactDOM from 'react-dom';
|
||||
import { createGradebook } from 'spec/jsx/gradezilla/default_gradebook/GradebookSpecHelper';
|
||||
import { createGradebook, setFixtureHtml } from 'spec/jsx/gradezilla/default_gradebook/GradebookSpecHelper';
|
||||
import AssignmentGroupColumnHeaderRenderer
|
||||
from 'jsx/gradezilla/default_gradebook/slick-grid/column-headers/AssignmentGroupColumnHeaderRenderer';
|
||||
|
||||
|
@ -35,6 +35,8 @@ QUnit.module('AssignmentGroupColumnHeaderRenderer', function (suiteHooks) {
|
|||
|
||||
suiteHooks.beforeEach(function () {
|
||||
$container = document.createElement('div');
|
||||
document.body.appendChild($container);
|
||||
setFixtureHtml($container);
|
||||
|
||||
gradebook = createGradebook();
|
||||
|
||||
|
@ -62,6 +64,10 @@ QUnit.module('AssignmentGroupColumnHeaderRenderer', function (suiteHooks) {
|
|||
renderer = new AssignmentGroupColumnHeaderRenderer(gradebook);
|
||||
});
|
||||
|
||||
suiteHooks.afterEach(function() {
|
||||
$container.remove();
|
||||
});
|
||||
|
||||
QUnit.module('#render', function () {
|
||||
test('renders the AssignmentGroupColumnHeader to the given container node', function () {
|
||||
render();
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
|
||||
import I18n from 'i18n!gradebook';
|
||||
import ReactDOM from 'react-dom';
|
||||
import { createGradebook } from 'spec/jsx/gradezilla/default_gradebook/GradebookSpecHelper';
|
||||
import { createGradebook, setFixtureHtml } from 'spec/jsx/gradezilla/default_gradebook/GradebookSpecHelper';
|
||||
import CustomColumnHeaderRenderer
|
||||
from 'jsx/gradezilla/default_gradebook/slick-grid/column-headers/CustomColumnHeaderRenderer';
|
||||
|
||||
|
@ -35,6 +35,8 @@ QUnit.module('CustomColumnHeaderRenderer', function (suiteHooks) {
|
|||
|
||||
suiteHooks.beforeEach(function () {
|
||||
$container = document.createElement('div');
|
||||
document.body.appendChild($container);
|
||||
setFixtureHtml($container);
|
||||
|
||||
gradebook = createGradebook();
|
||||
gradebook.gotCustomColumns([
|
||||
|
@ -45,6 +47,10 @@ QUnit.module('CustomColumnHeaderRenderer', function (suiteHooks) {
|
|||
renderer = new CustomColumnHeaderRenderer(gradebook);
|
||||
});
|
||||
|
||||
suiteHooks.afterEach(function() {
|
||||
$container.remove();
|
||||
});
|
||||
|
||||
QUnit.module('#render', function () {
|
||||
test('renders the CustomColumnHeader to the given container node', function () {
|
||||
render();
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
*/
|
||||
|
||||
import ReactDOM from 'react-dom';
|
||||
import { createGradebook } from 'spec/jsx/gradezilla/default_gradebook/GradebookSpecHelper';
|
||||
import { createGradebook, setFixtureHtml } from 'spec/jsx/gradezilla/default_gradebook/GradebookSpecHelper';
|
||||
import StudentColumnHeaderRenderer
|
||||
from 'jsx/gradezilla/default_gradebook/slick-grid/column-headers/StudentColumnHeaderRenderer';
|
||||
|
||||
|
@ -33,6 +33,8 @@ QUnit.module('StudentColumnHeaderRenderer', function (suiteHooks) {
|
|||
|
||||
suiteHooks.beforeEach(function () {
|
||||
$container = document.createElement('div');
|
||||
document.body.appendChild($container);
|
||||
setFixtureHtml($container);
|
||||
|
||||
gradebook = createGradebook({
|
||||
login_handle_name: 'a_jones',
|
||||
|
@ -41,6 +43,10 @@ QUnit.module('StudentColumnHeaderRenderer', function (suiteHooks) {
|
|||
renderer = new StudentColumnHeaderRenderer(gradebook);
|
||||
});
|
||||
|
||||
suiteHooks.afterEach(function() {
|
||||
$container.remove();
|
||||
});
|
||||
|
||||
QUnit.module('#render', function () {
|
||||
test('renders the StudentColumnHeader to the given container node', function () {
|
||||
render();
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
*/
|
||||
|
||||
import ReactDOM from 'react-dom';
|
||||
import { createGradebook } from 'spec/jsx/gradezilla/default_gradebook/GradebookSpecHelper';
|
||||
import { createGradebook, setFixtureHtml } from 'spec/jsx/gradezilla/default_gradebook/GradebookSpecHelper';
|
||||
import TotalGradeColumnHeaderRenderer
|
||||
from 'jsx/gradezilla/default_gradebook/slick-grid/column-headers/TotalGradeColumnHeaderRenderer';
|
||||
|
||||
|
@ -36,6 +36,8 @@ QUnit.module('TotalGradeColumnHeaderRenderer', function (suiteHooks) {
|
|||
|
||||
suiteHooks.beforeEach(function () {
|
||||
$container = document.createElement('div');
|
||||
document.body.appendChild($container);
|
||||
setFixtureHtml($container);
|
||||
|
||||
gradebook = createGradebook();
|
||||
columns = {
|
||||
|
@ -55,6 +57,10 @@ QUnit.module('TotalGradeColumnHeaderRenderer', function (suiteHooks) {
|
|||
renderer = new TotalGradeColumnHeaderRenderer(gradebook);
|
||||
});
|
||||
|
||||
suiteHooks.afterEach(function() {
|
||||
$container.remove();
|
||||
});
|
||||
|
||||
QUnit.module('#render', function () {
|
||||
test('renders the TotalGradeColumnHeader to the given container node', function () {
|
||||
render();
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { createGradebook } from 'spec/jsx/gradezilla/default_gradebook/GradebookSpecHelper';
|
||||
import { createGradebook, setFixtureHtml } from 'spec/jsx/gradezilla/default_gradebook/GradebookSpecHelper';
|
||||
import AssignmentCellFormatter from 'jsx/gradezilla/default_gradebook/slick-grid/formatters/AssignmentCellFormatter';
|
||||
|
||||
QUnit.module('AssignmentCellFormatter', function (hooks) {
|
||||
|
@ -30,6 +30,7 @@ QUnit.module('AssignmentCellFormatter', function (hooks) {
|
|||
hooks.beforeEach(function () {
|
||||
$fixture = document.createElement('div');
|
||||
document.body.appendChild($fixture);
|
||||
setFixtureHtml($fixture);
|
||||
|
||||
gradebook = createGradebook();
|
||||
formatter = new AssignmentCellFormatter(gradebook);
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { createGradebook } from 'spec/jsx/gradezilla/default_gradebook/GradebookSpecHelper';
|
||||
import { createGradebook, setFixtureHtml } from 'spec/jsx/gradezilla/default_gradebook/GradebookSpecHelper';
|
||||
import AssignmentGroupCellFormatter from 'jsx/gradezilla/default_gradebook/slick-grid/formatters/AssignmentGroupCellFormatter';
|
||||
|
||||
QUnit.module('AssignmentGroupCellFormatter', function (hooks) {
|
||||
|
@ -28,6 +28,7 @@ QUnit.module('AssignmentGroupCellFormatter', function (hooks) {
|
|||
hooks.beforeEach(function () {
|
||||
$fixture = document.createElement('div');
|
||||
document.body.appendChild($fixture);
|
||||
setFixtureHtml($fixture);
|
||||
|
||||
gradebook = createGradebook();
|
||||
formatter = new AssignmentGroupCellFormatter(gradebook);
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { createGradebook } from 'spec/jsx/gradezilla/default_gradebook/GradebookSpecHelper';
|
||||
import { createGradebook, setFixtureHtml } from 'spec/jsx/gradezilla/default_gradebook/GradebookSpecHelper';
|
||||
import StudentCellFormatter from 'jsx/gradezilla/default_gradebook/slick-grid/formatters/StudentCellFormatter';
|
||||
|
||||
QUnit.module('StudentCellFormatter', function (hooks) {
|
||||
|
@ -28,6 +28,7 @@ QUnit.module('StudentCellFormatter', function (hooks) {
|
|||
hooks.beforeEach(function () {
|
||||
$fixture = document.createElement('div');
|
||||
document.body.appendChild($fixture);
|
||||
setFixtureHtml($fixture);
|
||||
|
||||
gradebook = createGradebook({});
|
||||
formatter = new StudentCellFormatter(gradebook);
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { createGradebook } from 'spec/jsx/gradezilla/default_gradebook/GradebookSpecHelper';
|
||||
import { createGradebook, setFixtureHtml } from 'spec/jsx/gradezilla/default_gradebook/GradebookSpecHelper';
|
||||
import TotalGradeCellFormatter from 'jsx/gradezilla/default_gradebook/slick-grid/formatters/TotalGradeCellFormatter';
|
||||
|
||||
QUnit.module('TotalGradeCellFormatter', function (hooks) {
|
||||
|
@ -28,6 +28,7 @@ QUnit.module('TotalGradeCellFormatter', function (hooks) {
|
|||
hooks.beforeEach(function () {
|
||||
$fixture = document.createElement('div');
|
||||
document.body.appendChild($fixture);
|
||||
setFixtureHtml($fixture);
|
||||
|
||||
gradebook = createGradebook({
|
||||
grading_standard: [['A', 0.9], ['B', 0.8], ['C', 0.7], ['D', 0.6], ['F', 0.0]],
|
||||
|
|
|
@ -202,10 +202,11 @@ define([
|
|||
});
|
||||
});
|
||||
|
||||
test('starts polling for progress and returns a rejected promise on progress failure', function () {
|
||||
test('starts polling for progress and returns a rejected promise on progress failure', function (assert) {
|
||||
const done = assert.async();
|
||||
const expectedMonitoringUrl = `${monitoringBase}/newProgressId`;
|
||||
|
||||
this.subject = new GradebookExportManager(exportingUrl, currentUserId);
|
||||
this.subject = new GradebookExportManager(exportingUrl, currentUserId, null, 1);
|
||||
|
||||
moxios.stubRequest(expectedMonitoringUrl, {
|
||||
status: 200,
|
||||
|
@ -217,13 +218,15 @@ define([
|
|||
|
||||
return this.subject.startExport().catch((reason) => {
|
||||
equal(reason, 'Error exporting gradebook: Arbitrary failure');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
test('starts polling for progress and returns a rejected promise on unknown progress status', function () {
|
||||
test('starts polling for progress and returns a rejected promise on unknown progress status', function (assert) {
|
||||
const done = assert.async();
|
||||
const expectedMonitoringUrl = `${monitoringBase}/newProgressId`;
|
||||
|
||||
this.subject = new GradebookExportManager(exportingUrl, currentUserId);
|
||||
this.subject = new GradebookExportManager(exportingUrl, currentUserId, null, 1);
|
||||
|
||||
moxios.stubRequest(expectedMonitoringUrl, {
|
||||
status: 200,
|
||||
|
@ -235,14 +238,16 @@ define([
|
|||
|
||||
return this.subject.startExport().catch((reason) => {
|
||||
equal(reason, 'Error exporting gradebook: Pattern buffer degradation');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
test('starts polling for progress and returns a fulfilled promise on progress completion', function () {
|
||||
test('starts polling for progress and returns a fulfilled promise on progress completion', function (assert) {
|
||||
const done = assert.async();
|
||||
const expectedMonitoringUrl = `${monitoringBase}/newProgressId`;
|
||||
const expectedAttachmentUrl = `${attachmentBase}/newAttachmentId`;
|
||||
|
||||
this.subject = new GradebookExportManager(exportingUrl, currentUserId);
|
||||
this.subject = new GradebookExportManager(exportingUrl, currentUserId, null, 1);
|
||||
|
||||
moxios.stubRequest(expectedMonitoringUrl, {
|
||||
status: 200,
|
||||
|
@ -267,6 +272,7 @@ define([
|
|||
updatedAt: '2009-01-20T17:00:00Z'
|
||||
};
|
||||
deepEqual(resolution, expectedResolution);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -42,24 +42,6 @@ define([
|
|||
handleRequestClose () {}
|
||||
});
|
||||
|
||||
test('sets appElment to application div', () => {
|
||||
const wrapper = shallow(<ConfirmEndTutorialDialog {...getDefaultProps()} />);
|
||||
equal(wrapper.instance().appElement, $appElement[0]);
|
||||
});
|
||||
|
||||
test('handleModalReady sets aria-hidden on appElement', () => {
|
||||
const wrapper = shallow(<ConfirmEndTutorialDialog {...getDefaultProps()} />);
|
||||
wrapper.instance().handleModalReady();
|
||||
equal($appElement.attr('aria-hidden'), 'true');
|
||||
});
|
||||
|
||||
test('handleModalClose removes aria-hidden from appElement', () => {
|
||||
const wrapper = shallow(<ConfirmEndTutorialDialog {...getDefaultProps()} />);
|
||||
$appElement.attr('aria-hidden', 'true')
|
||||
wrapper.instance().handleModalClose()
|
||||
ok(!$appElement.attr('aria-hidden'));
|
||||
});
|
||||
|
||||
test('handleOkayButtonClick calls the proper api endpoint and data', () => {
|
||||
const spy = sinon.spy(axios, 'put');
|
||||
const wrapper = shallow(<ConfirmEndTutorialDialog {...getDefaultProps()} />);
|
||||
|
|
|
@ -22,9 +22,20 @@ import {shallow, mount} from 'enzyme';
|
|||
import TutorialTray from 'jsx/new_user_tutorial/trays/TutorialTray';
|
||||
import createTutorialStore from 'jsx/new_user_tutorial/utils/createTutorialStore'
|
||||
|
||||
QUnit.module('TutorialTray Spec');
|
||||
QUnit.module('TutorialTray Spec', {
|
||||
setup () {
|
||||
const applicationElement = document.createElement('div');
|
||||
applicationElement.id = 'application';
|
||||
document.getElementById('fixtures').appendChild(applicationElement);
|
||||
store = createTutorialStore();
|
||||
},
|
||||
|
||||
const store = createTutorialStore();
|
||||
teardown () {
|
||||
document.getElementById('fixtures').innerHTML = '';
|
||||
}
|
||||
});
|
||||
|
||||
let store;
|
||||
|
||||
const getDefaultProps = overrides => (
|
||||
Object.assign({}, {
|
||||
|
@ -47,6 +58,7 @@ test('Renders', () => {
|
|||
</TutorialTray>
|
||||
);
|
||||
ok(wrapper.exists());
|
||||
wrapper.unmount()
|
||||
});
|
||||
|
||||
test('handleEntering sets focus on the toggle button', () => {
|
||||
|
@ -55,13 +67,11 @@ test('handleEntering sets focus on the toggle button', () => {
|
|||
<div>Some Content</div>
|
||||
</TutorialTray>
|
||||
);
|
||||
wrapper.setState({
|
||||
isCollapsed: false
|
||||
});
|
||||
|
||||
wrapper.instance().handleToggleClick();
|
||||
wrapper.instance().handleEntering();
|
||||
|
||||
ok(wrapper.instance().toggleButton.button.focused);
|
||||
wrapper.unmount()
|
||||
});
|
||||
|
||||
test('handleExiting calls focus on the return value of the returnFocusToFunc', () => {
|
||||
|
@ -76,6 +86,7 @@ test('handleExiting calls focus on the return value of the returnFocusToFunc', (
|
|||
wrapper.instance().handleExiting();
|
||||
|
||||
ok(spy.called);
|
||||
wrapper.unmount()
|
||||
});
|
||||
|
||||
test('handleToggleClick toggles the isCollapsed state of the store', () => {
|
||||
|
@ -88,6 +99,7 @@ test('handleToggleClick toggles the isCollapsed state of the store', () => {
|
|||
wrapper.instance().handleToggleClick();
|
||||
|
||||
ok(store.getState().isCollapsed);
|
||||
wrapper.unmount()
|
||||
});
|
||||
|
||||
test('initial state sets endUserTutorialShown to false', () => {
|
||||
|
@ -98,6 +110,7 @@ test('initial state sets endUserTutorialShown to false', () => {
|
|||
);
|
||||
|
||||
equal(wrapper.state('endUserTutorialShown'), false);
|
||||
wrapper.unmount()
|
||||
});
|
||||
|
||||
test('handleEndTutorialClick sets endUserTutorialShown to true', () => {
|
||||
|
@ -110,6 +123,7 @@ test('handleEndTutorialClick sets endUserTutorialShown to true', () => {
|
|||
wrapper.instance().handleEndTutorialClick();
|
||||
|
||||
equal(wrapper.state('endUserTutorialShown'), true);
|
||||
wrapper.unmount()
|
||||
});
|
||||
|
||||
test('closeEndTutorialDialog sets endUserTutorialShown to false', () => {
|
||||
|
@ -122,4 +136,5 @@ test('closeEndTutorialDialog sets endUserTutorialShown to false', () => {
|
|||
wrapper.instance().closeEndTutorialDialog();
|
||||
|
||||
equal(wrapper.state('endUserTutorialShown'), false);
|
||||
wrapper.unmount()
|
||||
});
|
||||
|
|
|
@ -35,18 +35,27 @@ define([
|
|||
{ default: Transition }
|
||||
) => {
|
||||
|
||||
let $domNode, subject
|
||||
let $domNode, subject, fixtures
|
||||
|
||||
const renderComponent = (props) => {
|
||||
$domNode = $domNode || document.createElement('div')
|
||||
$domNode = document.createElement('div')
|
||||
fixtures.appendChild($domNode)
|
||||
return ReactDOM.render(<MessageStudents { ...props } />, $domNode)
|
||||
}
|
||||
|
||||
QUnit.module('MessageStudents', (hooks) => {
|
||||
hooks.beforeEach(() => {
|
||||
fixtures = document.getElementById('fixtures')
|
||||
const appElement = document.createElement('div')
|
||||
appElement.id = 'application'
|
||||
fixtures.appendChild(appElement)
|
||||
|
||||
})
|
||||
hooks.afterEach(() => {
|
||||
ReactDOM.unmountComponentAtNode($domNode)
|
||||
$domNode = null
|
||||
subject= null
|
||||
fixtures.innerHTML = ''
|
||||
})
|
||||
|
||||
test('it renders', () => {
|
||||
|
|
|
@ -25,6 +25,10 @@ shared_context "blueprint lock context" do
|
|||
f('.bpc-lock-toggle__label')
|
||||
end
|
||||
|
||||
def blueprint_lock_icon_button
|
||||
blueprint_lock_icon_label.find_element(:xpath, '../../parent::button')
|
||||
end
|
||||
|
||||
def associated_index_lock_icon
|
||||
f('#content-wrapper.ic-Layout-contentWrapper')
|
||||
end
|
||||
|
@ -59,12 +63,12 @@ shared_context "blueprint lock context" do
|
|||
expect(element).not_to contain_css(@locked_button_css) # the item is now unlocked.
|
||||
end
|
||||
|
||||
def verify_show_page_locked(element)
|
||||
def verify_show_page_locked
|
||||
element = blueprint_lock_icon_label
|
||||
expect(element).to include_text("Locked") # verify item is locked
|
||||
end
|
||||
|
||||
def verify_show_page_unlocked(element)
|
||||
def verify_show_page_unlocked
|
||||
element = blueprint_lock_icon_label
|
||||
expect(element).to include_text("Blueprint") # verify the item is unlocked
|
||||
end
|
||||
|
@ -271,18 +275,15 @@ describe "master courses - locked items" do
|
|||
@tag.update(restrictions: {content: true}) # lock the item. Does not require a migration.
|
||||
get "/courses/#{@master.id}/assignments/#{@assignment.id}"
|
||||
|
||||
element = blueprint_lock_icon_label
|
||||
verify_show_page_locked(element)
|
||||
element.click
|
||||
verify_show_page_locked
|
||||
blueprint_lock_icon_button.click
|
||||
refresh_page
|
||||
|
||||
element = blueprint_lock_icon_label
|
||||
verify_show_page_unlocked(element)
|
||||
element.click
|
||||
verify_show_page_unlocked
|
||||
blueprint_lock_icon_button.click
|
||||
refresh_page
|
||||
|
||||
element = blueprint_lock_icon_label
|
||||
verify_show_page_locked(element)
|
||||
verify_show_page_locked
|
||||
end
|
||||
|
||||
it "discussions show a lock icon on the show page", priority: "2", test_id: 3127582 do
|
||||
|
@ -290,18 +291,15 @@ describe "master courses - locked items" do
|
|||
@tag.update(restrictions: {content: true}) # lock the item. Does not require a migration.
|
||||
get "/courses/#{@master.id}/discussion_topics/#{@discussion.id}"
|
||||
|
||||
element = blueprint_lock_icon_label
|
||||
verify_show_page_locked(element)
|
||||
element.click
|
||||
verify_show_page_locked
|
||||
blueprint_lock_icon_button.click
|
||||
refresh_page
|
||||
|
||||
element = blueprint_lock_icon_label
|
||||
verify_show_page_unlocked(element)
|
||||
element.click
|
||||
verify_show_page_unlocked
|
||||
blueprint_lock_icon_button.click
|
||||
refresh_page
|
||||
|
||||
element = blueprint_lock_icon_label
|
||||
verify_show_page_locked(element)
|
||||
verify_show_page_locked
|
||||
end
|
||||
|
||||
it "pages show a lock icon on the show page", priority: "2", test_id: 3127583 do
|
||||
|
@ -309,18 +307,15 @@ describe "master courses - locked items" do
|
|||
@tag.update(restrictions: {content: true}) # lock the item. Does not require a migration.
|
||||
get "/courses/#{@master.id}/pages/#{@page.id}"
|
||||
|
||||
element = blueprint_lock_icon_label
|
||||
verify_show_page_locked(element)
|
||||
element.click
|
||||
verify_show_page_locked
|
||||
blueprint_lock_icon_button.click
|
||||
refresh_page
|
||||
|
||||
element = blueprint_lock_icon_label
|
||||
verify_show_page_unlocked(element)
|
||||
element.click
|
||||
verify_show_page_unlocked
|
||||
blueprint_lock_icon_button.click
|
||||
refresh_page
|
||||
|
||||
element = blueprint_lock_icon_label
|
||||
verify_show_page_locked(element)
|
||||
verify_show_page_locked
|
||||
end
|
||||
|
||||
it "quizzes show a lock icon on the show page", priority: "2", test_id: 3127584 do
|
||||
|
@ -328,18 +323,15 @@ describe "master courses - locked items" do
|
|||
@tag.update(restrictions: {content: true}) # lock the item. Does not require a migration.
|
||||
get "/courses/#{@master.id}/quizzes/#{@quiz.id}"
|
||||
|
||||
element = blueprint_lock_icon_label
|
||||
verify_show_page_locked(element)
|
||||
element.click
|
||||
verify_show_page_locked
|
||||
blueprint_lock_icon_button.click
|
||||
refresh_page
|
||||
|
||||
element = blueprint_lock_icon_label
|
||||
verify_show_page_unlocked(element)
|
||||
element.click
|
||||
verify_show_page_unlocked
|
||||
blueprint_lock_icon_button.click
|
||||
refresh_page
|
||||
|
||||
element = blueprint_lock_icon_label
|
||||
verify_show_page_locked(element)
|
||||
verify_show_page_locked
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -29,7 +29,7 @@ shared_context "blueprint sidebar context" do
|
|||
end
|
||||
|
||||
def blueprint_open_sidebar_button
|
||||
f('.blueprint__root .bcs__wrapper .bcs__trigger')
|
||||
f('.blueprint__root .bcs__wrapper .bcs__trigger button')
|
||||
end
|
||||
|
||||
def sync_modal_send_notification_checkbox
|
||||
|
@ -136,7 +136,7 @@ describe "master courses sidebar" do
|
|||
get "/courses/#{@master.id}"
|
||||
blueprint_open_sidebar_button.click
|
||||
f('button#mcSyncHistoryBtn').click
|
||||
expect(f('div[aria-label="Sync History"]')).to be_displayed
|
||||
expect(f('span[aria-label="Sync History"]')).to be_displayed
|
||||
expect(f('#application')).to have_attribute('aria-hidden', 'true')
|
||||
end
|
||||
|
||||
|
@ -146,7 +146,7 @@ describe "master courses sidebar" do
|
|||
wait_for_ajaximations
|
||||
f('button#mcUnsyncedChangesBtn').click
|
||||
wait_for_ajaximations
|
||||
expect(f('div[aria-label="Unsynced Changes"]')).to be_displayed
|
||||
expect(f('span[aria-label="Unsynced Changes"]')).to be_displayed
|
||||
expect(f('#application')).to have_attribute('aria-hidden', 'true')
|
||||
end
|
||||
|
||||
|
@ -177,7 +177,7 @@ describe "master courses sidebar" do
|
|||
get "/courses/#{@master.id}"
|
||||
blueprint_open_sidebar_button.click
|
||||
f('button#mcSidebarAsscBtn').click
|
||||
expect(f('div[aria-label="Associations"]')).to be_displayed
|
||||
expect(f('span[aria-label="Associations"]')).to be_displayed
|
||||
end
|
||||
|
||||
it "limits notification message to 140 characters", priority: "2", test_id: 3186725 do
|
||||
|
|
Loading…
Reference in New Issue