-
Notifications
You must be signed in to change notification settings - Fork 34
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #61 from edx/fsheets/EDUCATOR-1828
Accessibility Policy Form
- Loading branch information
Showing
16 changed files
with
685 additions
and
73 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,13 +3,17 @@ import React from 'react'; | |
import ReactDOM from 'react-dom'; | ||
import { Provider } from 'react-redux'; | ||
|
||
import WrappedAccessibilityPolicyPage from './components/AccessibilityPolicyPage'; | ||
import AccessibilityPolicyPage from './components/AccessibilityPolicyPage'; | ||
import store from './data/store'; | ||
|
||
const AccessibilityApp = () => ( | ||
<Provider store={store}> | ||
<div> | ||
<WrappedAccessibilityPolicyPage /> | ||
<AccessibilityPolicyPage | ||
communityAccessibilityLink="https://www.edx.org/accessibility" | ||
phoneNumber="+1 617-258-6577" | ||
email="[email protected]" | ||
/> | ||
</div> | ||
</Provider> | ||
); | ||
|
20 changes: 20 additions & 0 deletions
20
src/components/AccessibilityPolicyForm/AccessibilityPolicyForm.scss
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
@import '../../SFE.scss'; | ||
|
||
.list { | ||
margin-left: $spacer * 2; | ||
} | ||
|
||
.form-section { | ||
padding: 0 $spacer $spacer; | ||
font-size: $font-size-base; | ||
|
||
// set label and validation text to be larger in Studio | ||
div, label { | ||
font-size: $font-size-base; | ||
} | ||
} | ||
|
||
.bullet-list { | ||
@extend .list; | ||
list-style-type: disc; | ||
} |
183 changes: 183 additions & 0 deletions
183
src/components/AccessibilityPolicyForm/AccessibilityPolicyForm.test.jsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,183 @@ | ||
import React from 'react'; | ||
import Enzyme from 'enzyme'; | ||
import { AccessibilityPolicyForm } from './index'; | ||
import { accessibilityActions } from '../../data/constants/actionTypes'; | ||
|
||
const mount = Enzyme.mount; | ||
|
||
const defaultProps = { | ||
accessibilityStatus: {}, | ||
accessibilityEmail: '[email protected]', | ||
clearAccessibilityStatus: () => {}, | ||
submitAccessibilityForm: () => {}, | ||
}; | ||
|
||
const formInputs = { | ||
email: '[email protected]', | ||
fullName: 'test name', | ||
message: 'feedback message', | ||
}; | ||
|
||
const validationMessages = { | ||
email: 'Valid email required.', | ||
fullName: 'Full name required.', | ||
message: 'Message required.', | ||
}; | ||
|
||
const clearStatus = (wrapper) => { | ||
wrapper.setProps({ accessibilityStatus: {} }); | ||
}; | ||
|
||
const getMockForZendeskSuccess = (wrapper) => { | ||
wrapper.setProps({ | ||
accessibilityStatus: { | ||
type: accessibilityActions.ACCESSIBILITY_FORM_SUBMIT_SUCCESS, | ||
}, | ||
}); | ||
}; | ||
|
||
const getMockForZendeskRateLimit = (wrapper) => { | ||
wrapper.setProps({ | ||
accessibilityStatus: { | ||
type: accessibilityActions.ACCESSIBILITY_FORM_SUBMIT_RATE_LIMIT_FAILURE, | ||
}, | ||
}); | ||
}; | ||
|
||
let wrapper; | ||
|
||
describe('<AccessibilityPolicyForm />', () => { | ||
describe('renders', () => { | ||
beforeEach(() => { | ||
wrapper = mount( | ||
<AccessibilityPolicyForm | ||
{...defaultProps} | ||
/>, | ||
); | ||
}); | ||
|
||
it('correct number of form fields', () => { | ||
const formSection = wrapper.find('section'); | ||
expect(formSection.find('input')).toHaveLength(2); | ||
expect(formSection.find('textarea')).toHaveLength(1); | ||
expect(formSection.find('button')).toHaveLength(1); | ||
}); | ||
|
||
it('hides StatusAlert on initial load', () => { | ||
const statusAlert = wrapper.find('StatusAlert'); | ||
expect(statusAlert.find('div').first().prop('hidden')).toEqual(true); | ||
}); | ||
|
||
it('adds validation checking on each input field', () => { | ||
const emailInput = wrapper.find('input#email'); | ||
emailInput.simulate('blur'); | ||
|
||
const emailError = wrapper.find('div#error-email'); | ||
expect(emailError.exists()).toEqual(true); | ||
expect(emailError.text()).toEqual(validationMessages.email); | ||
|
||
const fullNameInput = wrapper.find('input#fullName'); | ||
fullNameInput.simulate('blur'); | ||
|
||
const fullNameError = wrapper.find('div#error-fullName'); | ||
expect(fullNameError.exists()).toEqual(true); | ||
expect(fullNameError.text()).toEqual(validationMessages.fullName); | ||
|
||
const messageInput = wrapper.find('textarea#message'); | ||
messageInput.simulate('blur'); | ||
|
||
const messageError = wrapper.find('div#error-message'); | ||
expect(messageError.exists()).toEqual(true); | ||
expect(messageError.text()).toEqual(validationMessages.message); | ||
}); | ||
|
||
it('shows validation errors when trying to submit with empty fields', () => { | ||
const formSection = wrapper.find('section'); | ||
const submitButton = formSection.find('button'); | ||
submitButton.simulate('click'); | ||
|
||
const statusAlert = wrapper.find('StatusAlert'); | ||
expect(statusAlert.find('div').first().prop('hidden')).toEqual(false); | ||
expect(statusAlert.find('div').first().hasClass('alert-danger')).toEqual(true); | ||
expect(statusAlert.text()).toContain(`Please fill in all required fields.${validationMessages.email}${validationMessages.fullName}${validationMessages.message}`); | ||
}); | ||
|
||
it('shows correct success message', () => { | ||
wrapper.setProps({ | ||
clearAccessibilityStatus: () => clearStatus(wrapper), | ||
submitAccessibilityForm: () => getMockForZendeskSuccess(wrapper), | ||
}); | ||
wrapper.setState({ | ||
submitterEmail: '[email protected]', | ||
submitterFullName: 'test name', | ||
submitterMessage: 'feedback message', | ||
}); | ||
|
||
const formSection = wrapper.find('section'); | ||
const submitButton = formSection.find('button'); | ||
submitButton.simulate('click'); | ||
|
||
const statusAlert = wrapper.find('StatusAlert'); | ||
const statusAlertType = statusAlert.prop('alertType'); | ||
expect(statusAlertType).toEqual('success'); | ||
expect(statusAlert.find('div').first().hasClass('alert-success')).toEqual(true); | ||
expect(statusAlert.text()).toContain('Thank you for contacting edX!Thank you for your feedback regarding the accessibility of Studio. We typically respond within one business day (Monday to Friday, 13:00 to 21:00 UTC).'); | ||
}); | ||
|
||
it('shows correct rate limiting message', () => { | ||
wrapper.setProps({ | ||
clearAccessibilityStatus: () => clearStatus(wrapper), | ||
submitAccessibilityForm: () => getMockForZendeskRateLimit(wrapper), | ||
}); | ||
wrapper.setState({ | ||
submitterEmail: formInputs.email, | ||
submitterFullName: formInputs.fullName, | ||
submitterMessage: formInputs.message, | ||
}); | ||
|
||
const formSection = wrapper.find('section'); | ||
const submitButton = formSection.find('button'); | ||
submitButton.simulate('click'); | ||
|
||
const statusAlert = wrapper.find('StatusAlert'); | ||
const statusAlertType = statusAlert.prop('alertType'); | ||
expect(statusAlertType).toEqual('danger'); | ||
expect(statusAlert.find('div').first().hasClass('alert-danger')).toEqual(true); | ||
expect(statusAlert.text()).toContain(`We are currently experiencing high volume. Try again later today or send an email message to ${wrapper.props().accessibilityEmail}`); | ||
}); | ||
|
||
it('clears inputs on valid submit', () => { | ||
const formSection = wrapper.find('section'); | ||
const emailInput = wrapper.find('input#email'); | ||
const fullNameInput = wrapper.find('input#fullName'); | ||
const messageInput = wrapper.find('textarea#message'); | ||
|
||
wrapper.setState({ | ||
submitterEmail: formInputs.email, | ||
submitterFullName: formInputs.fullName, | ||
submitterMessage: formInputs.message, | ||
}); | ||
|
||
const submitButton = formSection.find('button'); | ||
submitButton.simulate('click'); | ||
|
||
expect(emailInput.instance().value).toEqual(''); | ||
expect(fullNameInput.instance().value).toEqual(''); | ||
expect(messageInput.instance().value).toEqual(''); | ||
}); | ||
|
||
it('clears accessibilityStatus as expected', () => { | ||
wrapper.setProps({ | ||
accessibilityStatus: { | ||
type: accessibilityActions.ACCESSIBILITY_FORM_SUBMIT_SUCCESS, | ||
}, | ||
clearAccessibilityStatus: () => clearStatus(wrapper), | ||
}); | ||
|
||
const formSection = wrapper.find('section'); | ||
const submitButton = formSection.find('button'); | ||
submitButton.simulate('click'); | ||
expect(wrapper.props().accessibilityStatus).toEqual({}); | ||
}); | ||
}); | ||
}); |
Oops, something went wrong.