diff options
| author | Andrej Mihajlov <and@codeispoetry.ru> | 2017-07-19 22:15:36 +0100 |
|---|---|---|
| committer | Andrej Mihajlov <and@codeispoetry.ru> | 2017-07-21 10:03:57 +0100 |
| commit | 85ab19b58c934c06a63c67fe177204a7813dbaf4 (patch) | |
| tree | 9b188159db99a1511a9f95e710305d8b7a6d258f | |
| parent | 9f107f383afd25def91d4886d22dc8ae0e4ca604 (diff) | |
| download | mullvadvpn-85ab19b58c934c06a63c67fe177204a7813dbaf4.tar.xz mullvadvpn-85ab19b58c934c06a63c67fe177204a7813dbaf4.zip | |
Add tests for settings
| -rw-r--r-- | app/components/Settings.js | 32 | ||||
| -rw-r--r-- | test/components/Settings.spec.js | 166 |
2 files changed, 183 insertions, 15 deletions
diff --git a/app/components/Settings.js b/app/components/Settings.js index ade9dba8f5..df6947a258 100644 --- a/app/components/Settings.js +++ b/app/components/Settings.js @@ -58,9 +58,9 @@ export default class Settings extends Component { { /* show account options when logged in */ } <If condition={ isLoggedIn }> <Then> - <div> + <div className="settings__account"> - <div className="settings__cell settings__cell--active" onClick={ this.props.onViewAccount }> + <div className="settings__view-account settings__cell settings__cell--active" onClick={ this.props.onViewAccount }> <div className="settings__cell-label">Account</div> <div className="settings__cell-value"> <If condition={ isOutOfTime }> @@ -79,7 +79,7 @@ export default class Settings extends Component { <div className="settings__cell"> <div className="settings__cell-label">Auto-connect</div> <div className="settings__cell-value"> - <Switch onChange={ this.onAutoSecure } isOn={ this.props.settings.autoSecure } /> + <Switch className="settings__autosecure" onChange={ this.onAutoSecure } isOn={ this.props.settings.autoSecure } /> </div> </div> <div className="settings__cell-footer"> @@ -89,22 +89,24 @@ export default class Settings extends Component { </Then> </If> - <div className="settings__cell settings__cell--active" onClick={ this.onExternalLink.bind(this, 'faq') }> - <div className="settings__cell-label">FAQs</div> - <img className="settings__cell-icon" src="./assets/images/icon-extLink.svg" /> - </div> - <div className="settings__cell settings__cell--active" onClick={ this.onExternalLink.bind(this, 'guides') }> - <div className="settings__cell-label">Guides</div> - <img className="settings__cell-icon" src="./assets/images/icon-extLink.svg" /> - </div> - <div className="settings__cell settings__cell--active" onClick={ this.onExternalLink.bind(this, 'supportEmail') }> - <div className="settings__cell-label">Contact support</div> - <img className="settings__cell-icon" src="./assets/images/icon-email.svg" /> + <div className="settings__external"> + <div className="settings__cell settings__cell--active" onClick={ this.onExternalLink.bind(this, 'faq') }> + <div className="settings__cell-label">FAQs</div> + <img className="settings__cell-icon" src="./assets/images/icon-extLink.svg" /> + </div> + <div className="settings__cell settings__cell--active" onClick={ this.onExternalLink.bind(this, 'guides') }> + <div className="settings__cell-label">Guides</div> + <img className="settings__cell-icon" src="./assets/images/icon-extLink.svg" /> + </div> + <div className="settings__cell settings__cell--active" onClick={ this.onExternalLink.bind(this, 'supportEmail') }> + <div className="settings__cell-label">Contact support</div> + <img className="settings__cell-icon" src="./assets/images/icon-email.svg" /> + </div> </div> </div> <div className="settings__footer"> - <button className="button button--negative" onClick={ this.props.onQuit }>Quit app</button> + <button className="settings__quit button button--negative" onClick={ this.props.onQuit }>Quit app</button> </div> </div> diff --git a/test/components/Settings.spec.js b/test/components/Settings.spec.js new file mode 100644 index 0000000000..705da60098 --- /dev/null +++ b/test/components/Settings.spec.js @@ -0,0 +1,166 @@ +// @flow + +import { expect } from 'chai'; +import React from 'react'; +import ReactTestUtils, { Simulate } from 'react-dom/test-utils'; +import Settings from '../../app/components/Settings'; +import { defaultServer } from '../../app/config'; + +import type { AccountReduxState } from '../../app/redux/account/reducers'; +import type { SettingsReduxState } from '../../app/redux/settings/reducers'; +import type { SettingsProps } from '../../app/components/Settings'; + +describe('components/Settings', () => { + const loggedOutAccountState: AccountReduxState = { + accountNumber: null, + paidUntil: null, + status: 'none', + error: null + }; + + const loggedInAccountState: AccountReduxState = { + accountNumber: '1234', + paidUntil: (new Date('2038-01-01')).toISOString(), + status: 'ok', + error: null + }; + + const unpaidAccountState: AccountReduxState = { + accountNumber: '1234', + paidUntil: (new Date('2001-01-01')).toISOString(), + status: 'ok', + error: null + }; + + const settingsState: SettingsReduxState = { + autoSecure: true, + preferredServer: defaultServer + }; + + const makeProps = (anAccountState: AccountReduxState, aSettingsState: SettingsReduxState, mergeProps: $Shape<SettingsProps> = {}): SettingsProps => { + const defaultProps: SettingsProps = { + account: anAccountState, + settings: aSettingsState, + onQuit: () => {}, + onClose: () => {}, + onViewAccount: () => {}, + onExternalLink: (_type) => {}, + onUpdateSettings: (_update) => {} + }; + return Object.assign({}, defaultProps, mergeProps); + }; + + const render = (props: SettingsProps): Settings => { + return ReactTestUtils.renderIntoDocument( + <Settings { ...props } /> + ); + }; + + it('should show quit button when logged out', () => { + const props = makeProps(loggedOutAccountState, settingsState); + ReactTestUtils.findRenderedDOMComponentWithClass(render(props), 'settings__quit'); + }); + + it('should show quit button when logged in', () => { + const props = makeProps(loggedInAccountState, settingsState); + ReactTestUtils.findRenderedDOMComponentWithClass(render(props), 'settings__quit'); + }); + + it('should show external links when logged out', () => { + const props = makeProps(loggedOutAccountState, settingsState); + ReactTestUtils.findRenderedDOMComponentWithClass(render(props), 'settings__external'); + }); + + it('should show external links when logged in', () => { + const props = makeProps(loggedInAccountState, settingsState); + ReactTestUtils.findRenderedDOMComponentWithClass(render(props), 'settings__external'); + }); + + it('should show account section when logged in', () => { + const props = makeProps(loggedInAccountState, settingsState); + ReactTestUtils.findRenderedDOMComponentWithClass(render(props), 'settings__account'); + }); + + it('should hide account section when logged out', () => { + const props = makeProps(loggedOutAccountState, settingsState); + const elements = ReactTestUtils.scryRenderedDOMComponentsWithClass(render(props), 'settings__account'); + expect(elements).to.be.empty; + }); + + it('should hide account link when not logged in', () => { + const props = makeProps(loggedOutAccountState, settingsState); + const elements = ReactTestUtils.scryRenderedDOMComponentsWithClass(render(props), 'settings__view-account'); + expect(elements).to.be.empty; + }); + + it('should show out-of-time message for unpaid account', () => { + const props = makeProps(unpaidAccountState, settingsState); + const domNode = ReactTestUtils.findRenderedDOMComponentWithClass(render(props), 'settings__account-paid-until-label'); + expect(domNode.textContent).to.contain('OUT OF TIME'); + }); + + it('should hide out-of-time message for paid account', () => { + const props = makeProps(loggedInAccountState, settingsState); + const domNode = ReactTestUtils.findRenderedDOMComponentWithClass(render(props), 'settings__account-paid-until-label'); + expect(domNode.textContent).to.not.contain('OUT OF TIME'); + }); + + it('should call close callback', (done) => { + const props = makeProps(loggedOutAccountState, settingsState, { + onClose: () => done() + }); + const domNode = ReactTestUtils.findRenderedDOMComponentWithClass(render(props), 'settings__close'); + Simulate.click(domNode); + }); + + it('should call quit callback', (done) => { + const props = makeProps(loggedOutAccountState, settingsState, { + onQuit: () => done() + }); + const domNode = ReactTestUtils.findRenderedDOMComponentWithClass(render(props), 'settings__quit'); + Simulate.click(domNode); + }); + + it('should call account callback', (done) => { + const props = makeProps(loggedInAccountState, settingsState, { + onViewAccount: () => done() + }); + const domNode = ReactTestUtils.findRenderedDOMComponentWithClass(render(props), 'settings__view-account'); + Simulate.click(domNode); + }); + + it('should call update callback', (done) => { + const props = makeProps(loggedInAccountState, settingsState, { + onUpdateSettings: (update) => { + try { + expect(update).to.include({ autoSecure: false }); + done(); + } catch(e) { + done(e); + } + } + }); + const domNode = ReactTestUtils.findRenderedDOMComponentWithClass(render(props), 'settings__autosecure'); + + // TODO(Andrej): Add click handler to Switch to avoid calling that horrible chain of events. + Simulate.mouseDown(domNode); + Simulate.mouseUp(domNode); + Simulate.change(domNode, { target: { checked: false } }); + }); + + it('should call external links callback', () => { + let collectedExternalLinkTypes: Array<string> = []; + const props = makeProps(loggedOutAccountState, settingsState, { + onExternalLink: (type) => { + collectedExternalLinkTypes.push(type); + } + }); + const container = ReactTestUtils.findRenderedDOMComponentWithClass(render(props), 'settings__external'); + Array.from(container.childNodes) + .filter((elm: HTMLElement) => elm.classList.contains('settings__cell')) + .forEach((elm) => Simulate.click(elm)); + + expect(collectedExternalLinkTypes).to.include.ordered.members(['faq', 'guides', 'supportEmail']); + }); + +}); |
