diff --git a/src/components/accounts/actions.js b/src/components/accounts/actions.js index 9753cb4..37d5cc7 100644 --- a/src/components/accounts/actions.js +++ b/src/components/accounts/actions.js @@ -29,7 +29,7 @@ type State = { }, }; -export { updateToken, activate }; +export { updateToken, activate, remove }; /** * @param {Account|object} account diff --git a/src/components/auth/actions.js b/src/components/auth/actions.js index 3baa0ab..6e1947d 100644 --- a/src/components/auth/actions.js +++ b/src/components/auth/actions.js @@ -14,15 +14,15 @@ import signup from 'services/api/signup'; import dispatchBsod from 'components/ui/bsod/dispatchBsod'; import { create as createPopup } from 'components/ui/popup/actions'; import ContactForm from 'components/contact/ContactForm'; +import { getCredentials } from './reducer'; export { updateUser } from 'components/user/actions'; export { authenticate, logoutAll as logout, - revoke as removeAccount, + remove as removeAccount, activate as activateAccount } from 'components/accounts/actions'; -import { getCredentials } from './reducer'; /** * Reoutes user to the previous page if it is possible diff --git a/tests-e2e/cypress/integration/invalid-refreshToken.test.js b/tests-e2e/cypress/integration/invalid-refreshToken.test.js index d83c111..72e305e 100644 --- a/tests-e2e/cypress/integration/invalid-refreshToken.test.js +++ b/tests-e2e/cypress/integration/invalid-refreshToken.test.js @@ -1,15 +1,39 @@ +// account1 - authenticated +// account2 - invalid refreshToken import { account1, account2 } from '../fixtures/accounts.json'; -const multiAccount - = '{"accounts":{"available":[{"id":7,"username":"SleepWalker","email":"danilenkos@auroraglobal.com","token":"eyJhbGciOiJIUzI1NiJ9.eyJlbHktc2NvcGVzIjoiYWNjb3VudHNfd2ViX3VzZXIiLCJpYXQiOjE1MTgzNzM4MDksImV4cCI6MTUxODM3NzQwOSwic3ViIjoiZWx5fDciLCJqdGkiOjM1NDh9.Fv4AbJ0iDbrH3bhbgF0ViJLfYYiwH78deR4fMlMhKrQ","refreshToken":"3gh6ZZ3R9jGeFdp0TmlY7sd0zBxH6Zfq48M86eUAv952RcAKx32RAnjlKkgd6i-MV-RKbjtADIdoRwMUWOYQjEYtwwXPjcQJ"},{"id":102,"username":"test","email":"admin@udf.su","token":"eyJhbGciOiJIUzI1NiJ9.eyJlbHktc2NvcGVzIjoiYWNjb3VudHNfd2ViX3VzZXIiLCJpYXQiOjE1MTgzNzM4NjUsImV4cCI6MTUxODM3NzQ2NSwic3ViIjoiZWx5fDEwMiIsImp0aSI6MzU0OX0.eJEgvXT3leGqBe3tYNGZb0E4WEvWfrLPjcD7eNjyQYO","refreshToken":"Al75SIx-LFOCP7kaqZBVqMVmSljJw9_bdFQGyuM64c6ShP7YsXbkCD8vPOundAwUDfRZqsIbOHUROmAHPB0VBfjLfw96yqxx"}],"active":102},"user":{"id":102,"uuid":"e49cafdc-6e0c-442d-b608-dacdb864ee34","username":"test","token":"","email":"admin@udf.su","maskedEmail":"","avatar":"","lang":"en","isActive":true,"isOtpEnabled":true,"shouldAcceptRules":false,"passwordChangedAt":1478961317,"hasMojangUsernameCollision":true,"isGuest":false,"registeredAt":1478961317,"elyProfileLink":"http://ely.by/u102","originalResponse":{}}}'; -const singleAccount - = '{"accounts":{"available":[{"id":102,"username":"test","email":"admin@udf.su","token":"eyJhbGciOiJIUzI1NiJ9.eyJlbHktc2NvcGVzIjoiYWNjb3VudHNfd2ViX3VzZXIiLCJpYXQiOjE1MTgzNzM4NjUsImV4cCI6MTUxODM3NzQ2NSwic3ViIjoiZWx5fDEwMiIsImp0aSI6MzU0OX0.eJEgvXT3leGqBe3tYNGZb0E4WEvWfrLPjcD7eNjyQYO","refreshToken":"Al75SIx-LFOCP7kaqZBVqMVmSljJw9_bdFQGyuM64c6ShP7YsXbkCD8vPOundAwUDfRZqsIbOHUROmAHPB0VBfjLfw96yqxx"}],"active":102},"user":{"id":102,"uuid":"e49cafdc-6e0c-442d-b608-dacdb864ee34","username":"test","token":"","email":"admin@udf.su","maskedEmail":"","avatar":"","lang":"en","isActive":true,"isOtpEnabled":true,"shouldAcceptRules":false,"passwordChangedAt":1478961317,"hasMojangUsernameCollision":true,"isGuest":false,"registeredAt":1478961317,"elyProfileLink":"http://ely.by/u102","originalResponse":{}}}'; +const multiAccount = createState(); +const multiAccountWithBadTokens = createState(); +const singleAccount = createState(); +singleAccount.accounts.available = singleAccount.accounts.available.filter( + (account) => account.id === singleAccount.accounts.active +); describe('when user\'s token and refreshToken are invalid', () => { + before(() => + // ensure we always have one account with correct token + cy.visit('/').then(() => + fetch('/api/authentication/login', { + method: 'POST', + headers: { + 'Content-Type': + 'application/x-www-form-urlencoded; charset=UTF-8' + }, + body: `login=${account1.login}&password=${account1.password}` + }) + .then((resp) => resp.json()) + .then((resp) => { + const account = multiAccount.accounts.available.find( + (account) => account.username === account1.username + ); + + account.token = resp.access_token; + }) + ) + ); + beforeEach(() => - cy - .visit('/') - .then(() => localStorage.setItem('redux-storage', multiAccount)) + localStorage.setItem('redux-storage', JSON.stringify(multiAccount)) ); it('should ask for password', () => { @@ -63,9 +87,16 @@ describe('when user\'s token and refreshToken are invalid', () => { it('it should redirect to login, when one account and clicking back', () => { cy .url() - .should(() => localStorage.setItem('redux-storage', singleAccount)); + .should(() => + localStorage.setItem( + 'redux-storage', + JSON.stringify(singleAccount) + ) + ); cy.visit('/'); + cy.url().should('include', '/password'); + cy.get('[data-e2e-go-back]').click(); cy.url().should('include', '/login'); @@ -85,7 +116,13 @@ describe('when user\'s token and refreshToken are invalid', () => { .contains('Log out') .click(); - cy.contains(account2.email).should('not.exist'); + cy + .get('@fetch', { timeout: 15000 }) + .should('be.calledWith', '/api/authentication/logout'); + cy + .get('[data-e2e-toolbar]') + .contains(account2.email) + .should('not.exist'); cy .get('[data-e2e-toolbar]') .contains(account2.username) @@ -132,6 +169,14 @@ describe('when user\'s token and refreshToken are invalid', () => { }); it('should ask for password if selected account with bad token', () => { + cy + .url() + .should(() => + localStorage.setItem( + 'redux-storage', + JSON.stringify(multiAccountWithBadTokens) + ) + ); cy.visit('/'); cy.get('[data-e2e-go-back]').click(); @@ -145,6 +190,9 @@ describe('when user\'s token and refreshToken are invalid', () => { cy.url().should('include', '/password'); + // TODO: remove wait and fix logic so that + // it won't show 'Please enter E‑mail or username' error + cy.wait(1000); cy.get('[name="password"]').type(`${account1.password}{enter}`); cy.location('pathname', { timeout: 15000 }).should('eq', '/'); @@ -199,3 +247,49 @@ describe('when user\'s token and refreshToken are invalid', () => { cy.url().should('contain', '//ely.by'); }); }); + +function createState() { + return { + accounts: { + available: [ + { + id: 7, + username: 'SleepWalker', + email: 'danilenkos@auroraglobal.com', + token: + 'eyJhbGciOiJIUzI1NiJ9.eyJlbHktc2NvcGVzIjoiYWNjb3VudHNfd2ViX3VzZXIiLCJpYXQiOjE1MTgzNzM4MDksImV4cCI6MTUxODM3NzQwOSwic3ViIjoiZWx5fDciLCJqdGkiOjM1NDh9.Fv4AbJ0iDbrH3bhbgF0ViJLfYYiwH78deR4fMlMhKrQ', + refreshToken: + '3gh6ZZ3R9jGeFdp0TmlY7sd0zBxH6Zfq48M86eUAv952RcAKx32RAnjlKkgd6i-MV-RKbjtADIdoRwMUWOYQjEYtwwXPjcQJ' + }, + { + id: 102, + username: 'test', + email: 'admin@udf.su', + token: + 'eyJhbGciOiJIUzI1NiJ9.eyJlbHktc2NvcGVzIjoiYWNjb3VudHNfd2ViX3VzZXIiLCJpYXQiOjE1MTgzNzM4NjUsImV4cCI6MTUxODM3NzQ2NSwic3ViIjoiZWx5fDEwMiIsImp0aSI6MzU0OX0.eJEgvXT3leGqBe3tYNGZb0E4WEvWfrLPjcD7eNjyQYO', + refreshToken: + 'Al75SIx-LFOCP7kaqZBVqMVmSljJw9_bdFQGyuM64c6ShP7YsXbkCD8vPOundAwUDfRZqsIbOHUROmAHPB0VBfjLfw96yqxx' + } + ], + active: 102 + }, + user: { + id: 102, + uuid: 'e49cafdc-6e0c-442d-b608-dacdb864ee34', + username: 'test', + token: '', + email: 'admin@udf.su', + maskedEmail: '', + avatar: '', + lang: 'en', + isActive: true, + isOtpEnabled: true, + shouldAcceptRules: false, + passwordChangedAt: 1478961317, + hasMojangUsernameCollision: true, + isGuest: false, + registeredAt: 1478961317, + elyProfileLink: 'http://ely.by/u102' + } + }; +} diff --git a/tests-e2e/yarn.lock b/tests-e2e/yarn.lock index b2cd564..c046cf9 100644 --- a/tests-e2e/yarn.lock +++ b/tests-e2e/yarn.lock @@ -41,8 +41,8 @@ resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.0.8.tgz#d27600e9ba2f371e08695d90a0fe0408d89c7be7" "@types/jquery@*": - version "3.3.0" - resolved "https://registry.yarnpkg.com/@types/jquery/-/jquery-3.3.0.tgz#6316ac20a1a13c5d521a2dc661befc7184f73f5b" + version "3.3.1" + resolved "https://registry.yarnpkg.com/@types/jquery/-/jquery-3.3.1.tgz#55758d44d422756d6329cbf54e6d41931d7ba28f" "@types/jquery@3.2.16": version "3.2.16" @@ -68,8 +68,8 @@ "@types/sinon" "*" "@types/sinon@*": - version "4.1.3" - resolved "https://registry.yarnpkg.com/@types/sinon/-/sinon-4.1.3.tgz#2ee25e0e302f31e78a945650a60029e08878eaf8" + version "4.3.0" + resolved "https://registry.yarnpkg.com/@types/sinon/-/sinon-4.3.0.tgz#7f53915994a00ccea24f4e0c24709822ed11a3b1" "@types/sinon@4.0.0": version "4.0.0" @@ -95,8 +95,8 @@ ansi-styles@^2.2.1: resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" ansi-styles@^3.1.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.0.tgz#c159b8d5be0f9e5a6f346dab94f16ce022161b88" + version "3.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" dependencies: color-convert "^1.9.0" @@ -195,8 +195,8 @@ check-more-types@2.24.0: resolved "https://registry.yarnpkg.com/check-more-types/-/check-more-types-2.24.0.tgz#1420ffb10fd444dcfc79b43891bbfffd32a84600" ci-info@^1.0.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-1.1.2.tgz#03561259db48d0474c8bdc90f5b47b068b6bbfb4" + version "1.1.3" + resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-1.1.3.tgz#710193264bb05c77b8c90d02f5aaf22216a667b2" cli-cursor@^1.0.2: version "1.0.2" @@ -276,8 +276,8 @@ cryptiles@2.x.x: boom "2.x.x" cypress@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/cypress/-/cypress-2.0.1.tgz#cbb62e7c2ff7e646aab5ab0570db07ceaecf3d4e" + version "2.1.0" + resolved "https://registry.yarnpkg.com/cypress/-/cypress-2.1.0.tgz#a8bd7d9b89c38a1e380db83b57d9bba0dbb95ba4" dependencies: "@cypress/listr-verbose-renderer" "0.4.1" "@cypress/xvfb" "1.1.3" @@ -772,8 +772,8 @@ performance-now@^0.2.0: resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-0.2.0.tgz#33ef30c5c77d4ea21c5a53869d91b56d8f2555e5" prettier@^1.10.2: - version "1.10.2" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.10.2.tgz#1af8356d1842276a99a5b5529c82dd9e9ad3cc93" + version "1.11.1" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.11.1.tgz#61e43fc4cd44e68f2b0dfc2c38cd4bb0fccdcc75" process-nextick-args@~2.0.0: version "2.0.0" @@ -804,8 +804,8 @@ ramda@0.24.1: resolved "https://registry.yarnpkg.com/ramda/-/ramda-0.24.1.tgz#c3b7755197f35b8dc3502228262c4c91ddb6b857" readable-stream@^2.2.2: - version "2.3.4" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.4.tgz#c946c3f47fa7d8eabc0b6150f4a12f69a4574071" + version "2.3.5" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.5.tgz#b4f85003a938cbb6ecbce2a124fb1012bd1a838d" dependencies: core-util-is "~1.0.0" inherits "~2.0.3" @@ -866,8 +866,8 @@ restore-cursor@^1.0.1: onetime "^1.0.0" rxjs@^5.0.0-beta.11: - version "5.5.6" - resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-5.5.6.tgz#e31fb96d6fd2ff1fd84bcea8ae9c02d007179c02" + version "5.5.7" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-5.5.7.tgz#afb3d1642b069b2fbf203903d6501d1acb4cda27" dependencies: symbol-observable "1.0.1" @@ -886,8 +886,8 @@ sntp@1.x.x: hoek "2.x.x" sshpk@^1.7.0: - version "1.13.1" - resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.13.1.tgz#512df6da6287144316dc4c18fe1cf1d940739be3" + version "1.14.1" + resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.14.1.tgz#130f5975eddad963f1d56f92b9ac6c51fa9f83eb" dependencies: asn1 "~0.2.3" assert-plus "^1.0.0" @@ -958,8 +958,8 @@ tmp@0.0.31: os-tmpdir "~1.0.1" tough-cookie@~2.3.0: - version "2.3.3" - resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.3.3.tgz#0b618a5565b6dea90bf3425d04d55edc475a7561" + version "2.3.4" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.3.4.tgz#ec60cee38ac675063ffc97a5c18970578ee83655" dependencies: punycode "^1.4.1"