From 1d00bc8d81430add3af90989efe894a5309f6be5 Mon Sep 17 00:00:00 2001 From: Vit Stanislav Date: Wed, 16 Aug 2017 11:02:25 +0200 Subject: [PATCH 1/7] Migrate "Save network to cookie" - Closes #564 --- src/components/login/loginFormComponent.js | 3 ++ .../login/loginFormComponent.test.js | 28 +++++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/src/components/login/loginFormComponent.js b/src/components/login/loginFormComponent.js index c9adfdd75..e302886dc 100644 --- a/src/components/login/loginFormComponent.js +++ b/src/components/login/loginFormComponent.js @@ -42,6 +42,9 @@ class LoginFormComponent extends React.Component { componentDidUpdate() { if (this.props.account && this.props.account.address) { this.props.history.replace('/main/transactions'); + if (this.state.address) { + Cookies.set('address', this.state.address); + } } } diff --git a/src/components/login/loginFormComponent.test.js b/src/components/login/loginFormComponent.test.js index 30e6536d6..31220c472 100644 --- a/src/components/login/loginFormComponent.test.js +++ b/src/components/login/loginFormComponent.test.js @@ -5,6 +5,7 @@ import { spy } from 'sinon'; import sinonChai from 'sinon-chai'; import { mount, shallow } from 'enzyme'; import Lisk from 'lisk-js'; +import Cookies from 'js-cookie'; import LoginFormComponent from './loginFormComponent'; chai.use(sinonChai); @@ -78,6 +79,33 @@ describe('LoginFormComponent', () => { }); }); + describe('componentDidUpdate', () => { + const address = 'http:localhost:8080'; + const props = { + account: { address: 'dummy' }, + history: { + replace: spy(), + }, + }; + + it('calls this.props.history.replace(\'/main/transactions\')', () => { + const wrapper = mount(, options); + wrapper.setProps(props); + expect(props.history.replace).to.have.been.calledWith('/main/transactions'); + }); + + it('calls Cookies.set(\'address\', address) if this.state.address', () => { + const spyFn = spy(Cookies, 'set'); + const wrapper = mount(, options); + wrapper.setState({ address }); + wrapper.setProps(props); + expect(spyFn).to.have.been.calledWith('address', address); + + spyFn.restore(); + Cookies.remove('address'); + }); + }); + describe('validateUrl', () => { it('should set address and addressValidity="" for a valid address', () => { const validURL = 'http://localhost:8080'; From 368a9ac7596a195e6fbe8bef591c80fb7f3661f0 Mon Sep 17 00:00:00 2001 From: Vit Stanislav Date: Thu, 17 Aug 2017 10:39:50 +0200 Subject: [PATCH 2/7] Save also selected network to cookie --- src/components/login/loginFormComponent.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/components/login/loginFormComponent.js b/src/components/login/loginFormComponent.js index e302886dc..c8c5c4e21 100644 --- a/src/components/login/loginFormComponent.js +++ b/src/components/login/loginFormComponent.js @@ -45,6 +45,7 @@ class LoginFormComponent extends React.Component { if (this.state.address) { Cookies.set('address', this.state.address); } + Cookies.set('network', this.state.network); } } @@ -99,8 +100,9 @@ class LoginFormComponent extends React.Component { devPreFill() { const address = Cookies.get('address'); const passphrase = Cookies.get('passphrase'); + const network = parseInt(Cookies.get('network'), 10); - this.setState({ network: address ? 2 : 0 }); + this.setState({ network }); this.validateUrl(address); this.validatePassphrase(passphrase); } From b995e079d401acc2ebdce2fea4a0f1de60de7d63 Mon Sep 17 00:00:00 2001 From: Vit Stanislav Date: Thu, 17 Aug 2017 11:33:23 +0200 Subject: [PATCH 3/7] Avoid multiple setState(...) in LoginFormComponent.devPreFill --- src/components/login/loginFormComponent.js | 31 +++++++++++++------ .../login/loginFormComponent.test.js | 4 +-- 2 files changed, 23 insertions(+), 12 deletions(-) diff --git a/src/components/login/loginFormComponent.js b/src/components/login/loginFormComponent.js index c8c5c4e21..f041ac0f9 100644 --- a/src/components/login/loginFormComponent.js +++ b/src/components/login/loginFormComponent.js @@ -32,6 +32,11 @@ class LoginFormComponent extends React.Component { address: '', network: 0, }; + + this.validators = { + address: this.validateUrl, + passphrase: this.validatePassphrase, + }; } componentDidMount() { @@ -49,6 +54,7 @@ class LoginFormComponent extends React.Component { } } + // eslint-disable-next-line class-methods-use-this validateUrl(value) { const addHttp = (url) => { const reg = /^(?:f|ht)tps?:\/\//i; @@ -64,10 +70,10 @@ class LoginFormComponent extends React.Component { } const data = { address: value, addressValidity }; - this.setState(data); return data; } + // eslint-disable-next-line class-methods-use-this validatePassphrase(value) { const data = { passphrase: value }; if (!value || value === '') { @@ -75,13 +81,15 @@ class LoginFormComponent extends React.Component { } else { data.passphraseValidity = isValidPassphrase(value) ? '' : 'Invalid passphrase'; } - - this.setState(data); return data; } changeHandler(name, value) { - this.setState({ [name]: value }); + const validator = this.validators[name] || (() => ({})); + this.setState({ + [name]: value, + ...validator(value), + }); } onLoginSubmission(passphrase) { @@ -100,11 +108,13 @@ class LoginFormComponent extends React.Component { devPreFill() { const address = Cookies.get('address'); const passphrase = Cookies.get('passphrase'); - const network = parseInt(Cookies.get('network'), 10); + const network = parseInt(Cookies.get('network'), 10) || 0; - this.setState({ network }); - this.validateUrl(address); - this.validatePassphrase(passphrase); + this.setState({ + network, + ...this.validators.address(address), + ...this.validators.passphrase(passphrase), + }); } render() { @@ -122,13 +132,14 @@ class LoginFormComponent extends React.Component { this.state.network === 2 && + onChange={this.changeHandler.bind(this, 'address')} /> } + value={this.state.passphrase} + onChange={this.changeHandler.bind(this, 'passphrase')} /> { describe('changeHandler', () => { it('call setState with matching data', () => { const wrapper = shallow(, options); - const key = 'address'; - const value = 'http://llocalhost:8080'; + const key = 'network'; + const value = 0; const spyFn = spy(LoginFormComponent.prototype, 'setState'); wrapper.instance().changeHandler(key, value); expect(spyFn).to.have.been.calledWith({ [key]: value }); From 4c4d1642f150641309730646b99c564b29960291 Mon Sep 17 00:00:00 2001 From: Vit Stanislav Date: Thu, 17 Aug 2017 14:02:11 +0200 Subject: [PATCH 4/7] Fix e2e tests --- features/step_definitions/generic.step.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/features/step_definitions/generic.step.js b/features/step_definitions/generic.step.js index f7f52b858..23a0a2f22 100644 --- a/features/step_definitions/generic.step.js +++ b/features/step_definitions/generic.step.js @@ -101,7 +101,7 @@ defineSupportCode(({ Given, When, Then, setDefaultTimeout }) => { browser.ignoreSynchronization = true; browser.driver.manage().window().setSize(1000, 1000); browser.get('http://localhost:8080/'); - browser.manage().addCookie({ name: 'address', value: 'http://localhost:4000' }); + browser.manage().addCookie({ name: 'address', value: 'http://localhost:4000', network: '2' }); browser.get('http://localhost:8080/'); waitForElemAndSendKeys('.passphrase input', accounts[accountName].passphrase); waitForElemAndClickIt('.login-button', callback); From e6348a4dc7cb5900374821d86f1ec811884c2404 Mon Sep 17 00:00:00 2001 From: Vit Stanislav Date: Thu, 17 Aug 2017 14:09:52 +0200 Subject: [PATCH 5/7] Add e2e test for "should remeber selected network" --- features/login.feature | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/features/login.feature b/features/login.feature index 911744a46..b4aae1595 100644 --- a/features/login.feature +++ b/features/login.feature @@ -21,6 +21,17 @@ Feature: Login page Then I should be logged in And I should see text "Testnet" in "peer network" element + Scenario: should remember the selected network + Given I'm on login page + When I fill in "wagon stock borrow episode laundry kitten salute link globe zero feed marble" to "passphrase" field + And I select option no. 2 from "network" select + And I click "login button" + And I click "logout button" + And I fill in "wagon stock borrow episode laundry kitten salute link globe zero feed marble" to "passphrase" field + And I click "login button" + Then I should be logged in + And I should see text "Testnet" in "peer network" element + @ignore Scenario: should allow to create a new account Given I'm on login page From 0a170da566c146c75aea52a7a5c27535183231cd Mon Sep 17 00:00:00 2001 From: Vit Stanislav Date: Thu, 17 Aug 2017 14:27:46 +0200 Subject: [PATCH 6/7] Remove Xvfb from unit tests in Jenkinsfile since we are using Headless Chrome --- Jenkinsfile | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index 6672fb46d..719b93495 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -69,10 +69,6 @@ node('lisk-nano-01'){ sh ''' export ON_JENKINS=true - # Start xvfb - export DISPLAY=:99 - Xvfb :99 -ac -screen 0 1280x1024x24 & - # Run test cd $WORKSPACE npm run test From 6e156da4dbfc70b64722c59e683036f8f99802eb Mon Sep 17 00:00:00 2001 From: Vit Stanislav Date: Thu, 17 Aug 2017 14:39:02 +0200 Subject: [PATCH 7/7] Fix e2e tests --- features/step_definitions/generic.step.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/features/step_definitions/generic.step.js b/features/step_definitions/generic.step.js index 23a0a2f22..a6df04d8f 100644 --- a/features/step_definitions/generic.step.js +++ b/features/step_definitions/generic.step.js @@ -101,7 +101,8 @@ defineSupportCode(({ Given, When, Then, setDefaultTimeout }) => { browser.ignoreSynchronization = true; browser.driver.manage().window().setSize(1000, 1000); browser.get('http://localhost:8080/'); - browser.manage().addCookie({ name: 'address', value: 'http://localhost:4000', network: '2' }); + browser.manage().addCookie({ name: 'address', value: 'http://localhost:4000' }); + browser.manage().addCookie({ name: 'network', value: '2' }); browser.get('http://localhost:8080/'); waitForElemAndSendKeys('.passphrase input', accounts[accountName].passphrase); waitForElemAndClickIt('.login-button', callback);