mirror of
https://github.com/elyby/accounts-frontend.git
synced 2024-11-26 16:52:06 +05:30
Cover register and activation with e2e tests
This commit is contained in:
parent
f6f0aedc65
commit
c8b0168c69
@ -288,11 +288,9 @@ export default class AuthFlow implements AuthContext {
|
||||
* Tries to restore last oauth request, if it was stored in localStorage
|
||||
* in last 2 hours
|
||||
*
|
||||
* @api private
|
||||
*
|
||||
* @returns {bool} - whether oauth state is being restored
|
||||
*/
|
||||
restoreOAuthState() {
|
||||
private restoreOAuthState() {
|
||||
if (/^\/(register|oauth2)/.test(this.getRequest().path)) {
|
||||
// allow register or the new oauth requests
|
||||
return;
|
||||
|
@ -7,9 +7,10 @@ let sitekey;
|
||||
|
||||
export type CaptchaID = string;
|
||||
|
||||
export default {
|
||||
class Captcha {
|
||||
/**
|
||||
* @param {DOMNode|string} el - dom node or id of element where to render captcha
|
||||
* @param {object} options
|
||||
* @param {string} options.skin - skin color (dark|light)
|
||||
* @param {Function} options.onSetCode - the callback, that will be called with
|
||||
* captcha verification code, after user successfully solves captcha
|
||||
@ -26,6 +27,9 @@ export default {
|
||||
onSetCode: (code: string) => void;
|
||||
},
|
||||
): Promise<CaptchaID> {
|
||||
// for testing purposes only
|
||||
(window as any).e2eCaptchaSetCode = callback;
|
||||
|
||||
return this.loadApi().then(() =>
|
||||
(window as any).grecaptcha.render(el, {
|
||||
sitekey,
|
||||
@ -33,14 +37,16 @@ export default {
|
||||
callback,
|
||||
}),
|
||||
);
|
||||
},
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} captchaId - captcha id, returned from render promise
|
||||
*/
|
||||
reset(captchaId: CaptchaID) {
|
||||
delete (window as any).e2eCaptchaSetCode;
|
||||
|
||||
this.loadApi().then(() => (window as any).grecaptcha.reset(captchaId));
|
||||
},
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {stirng} newLang
|
||||
@ -49,7 +55,7 @@ export default {
|
||||
*/
|
||||
setLang(newLang: string) {
|
||||
lang = newLang;
|
||||
},
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} apiKey
|
||||
@ -58,14 +64,12 @@ export default {
|
||||
*/
|
||||
setApiKey(apiKey: string) {
|
||||
sitekey = apiKey;
|
||||
},
|
||||
}
|
||||
|
||||
/**
|
||||
* @api private
|
||||
*
|
||||
* @returns {Promise}
|
||||
*/
|
||||
loadApi(): Promise<void> {
|
||||
private loadApi(): Promise<void> {
|
||||
if (!readyPromise) {
|
||||
readyPromise = Promise.all([
|
||||
new Promise(resolve => {
|
||||
@ -80,5 +84,7 @@ export default {
|
||||
}
|
||||
|
||||
return readyPromise;
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export default new Captcha();
|
||||
|
@ -0,0 +1,145 @@
|
||||
it('should register', () => {
|
||||
const username = `test${Date.now()}`;
|
||||
const email = `${Date.now()}@gmail.com`;
|
||||
const password = String(Date.now());
|
||||
const captchaCode = 'captchaCode';
|
||||
const activationKey = 'activationKey';
|
||||
|
||||
cy.server();
|
||||
cy.route({
|
||||
method: 'POST',
|
||||
url: '/api/signup',
|
||||
response: {
|
||||
success: true,
|
||||
},
|
||||
}).as('signup');
|
||||
cy.login({
|
||||
accounts: ['default'],
|
||||
updateState: false,
|
||||
rawApiResp: true,
|
||||
}).then(({ accounts: [account] }) => {
|
||||
cy.route({
|
||||
method: 'POST',
|
||||
url: '/api/signup/confirm',
|
||||
response: account,
|
||||
}).as('activate');
|
||||
});
|
||||
cy.visit('/');
|
||||
|
||||
cy.getByTestId('toolbar')
|
||||
.contains('Join')
|
||||
.click();
|
||||
|
||||
cy.location('pathname').should('eq', '/register');
|
||||
|
||||
cy.get('[name=username]').type(username);
|
||||
cy.get('[name=email]').type(email);
|
||||
cy.get('[name=password]').type(password);
|
||||
cy.get('[name=rePassword]').type(password);
|
||||
cy.get('[name=rulesAgreement]').should('not.be.checked');
|
||||
cy.get('[name=rulesAgreement]')
|
||||
.parent()
|
||||
.click();
|
||||
cy.get('[name=rulesAgreement]').should('be.checked');
|
||||
cy.window().should('have.property', 'e2eCaptchaSetCode');
|
||||
cy.window().then(win => {
|
||||
// fake captcha response
|
||||
// @ts-ignore
|
||||
win.e2eCaptchaSetCode(captchaCode);
|
||||
});
|
||||
cy.get('[type=submit]').click();
|
||||
|
||||
cy.wait('@signup')
|
||||
.its('requestBody')
|
||||
.should(
|
||||
'eq',
|
||||
new URLSearchParams({
|
||||
email,
|
||||
username,
|
||||
password,
|
||||
rePassword: password,
|
||||
rulesAgreement: '1',
|
||||
lang: 'en',
|
||||
captcha: captchaCode,
|
||||
}).toString(),
|
||||
);
|
||||
|
||||
cy.location('pathname').should('eq', '/activation');
|
||||
|
||||
cy.get('[name=key]').type(`${activationKey}{enter}`);
|
||||
|
||||
cy.wait('@activate')
|
||||
.its('requestBody')
|
||||
.should('eq', `key=${activationKey}`);
|
||||
|
||||
cy.location('pathname').should('eq', '/');
|
||||
});
|
||||
|
||||
it('should allow activation', () => {
|
||||
const activationKey = 'activationKey';
|
||||
|
||||
cy.server();
|
||||
cy.login({
|
||||
accounts: ['default'],
|
||||
updateState: false,
|
||||
rawApiResp: true,
|
||||
}).then(({ accounts: [account] }) => {
|
||||
cy.route({
|
||||
method: 'POST',
|
||||
url: '/api/signup/confirm',
|
||||
response: account,
|
||||
}).as('activate');
|
||||
});
|
||||
cy.visit('/register');
|
||||
|
||||
cy.getByTestId('auth-secondary-controls')
|
||||
.contains('Already have')
|
||||
.click();
|
||||
|
||||
cy.location('pathname').should('eq', '/activation');
|
||||
|
||||
cy.get('[name=key]').type(`${activationKey}{enter}`);
|
||||
|
||||
cy.wait('@activate')
|
||||
.its('requestBody')
|
||||
.should('eq', `key=${activationKey}`);
|
||||
|
||||
cy.location('pathname').should('eq', '/');
|
||||
});
|
||||
|
||||
it('should allow resend code', () => {
|
||||
const email = `${Date.now()}@gmail.com`;
|
||||
const captchaCode = 'captchaCode';
|
||||
|
||||
cy.server();
|
||||
cy.route({
|
||||
method: 'POST',
|
||||
url: '/api/signup/repeat-message',
|
||||
response: { success: true },
|
||||
}).as('resend');
|
||||
cy.visit('/register');
|
||||
|
||||
cy.getByTestId('auth-secondary-controls')
|
||||
.contains('not received')
|
||||
.click();
|
||||
|
||||
cy.location('pathname').should('eq', '/resend-activation');
|
||||
|
||||
cy.get('[name=email]').type(email);
|
||||
cy.window().should('have.property', 'e2eCaptchaSetCode');
|
||||
cy.window().then(win => {
|
||||
// fake captcha response
|
||||
// @ts-ignore
|
||||
win.e2eCaptchaSetCode(captchaCode);
|
||||
});
|
||||
cy.get('[type=submit]').click();
|
||||
|
||||
cy.wait('@resend')
|
||||
.its('requestBody')
|
||||
.should(
|
||||
'eq',
|
||||
new URLSearchParams({ email, captcha: captchaCode }).toString(),
|
||||
);
|
||||
|
||||
cy.location('pathname').should('eq', '/activation');
|
||||
});
|
@ -31,47 +31,56 @@ const accountsMap = {
|
||||
default2: account1,
|
||||
};
|
||||
|
||||
Cypress.Commands.add('login', async ({ accounts }) => {
|
||||
const accountsData = await Promise.all(
|
||||
accounts.map(async account => {
|
||||
let credentials;
|
||||
Cypress.Commands.add(
|
||||
'login',
|
||||
async ({ accounts, updateState = true, rawApiResp = false }) => {
|
||||
const accountsData = await Promise.all(
|
||||
accounts.map(async account => {
|
||||
let credentials;
|
||||
|
||||
if (account) {
|
||||
credentials = accountsMap[account];
|
||||
if (account) {
|
||||
credentials = accountsMap[account];
|
||||
|
||||
if (!credentials) {
|
||||
throw new Error(`Unknown account name: ${account}`);
|
||||
if (!credentials) {
|
||||
throw new Error(`Unknown account name: ${account}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const resp = await fetch('/api/authentication/login', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
|
||||
},
|
||||
body: `${new URLSearchParams({
|
||||
login: credentials.login,
|
||||
password: credentials.password,
|
||||
rememberMe: '1',
|
||||
})}`,
|
||||
}).then(rawResp => rawResp.json());
|
||||
const resp = await fetch('/api/authentication/login', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
|
||||
},
|
||||
body: `${new URLSearchParams({
|
||||
login: credentials.login,
|
||||
password: credentials.password,
|
||||
rememberMe: '1',
|
||||
})}`,
|
||||
}).then(rawResp => rawResp.json());
|
||||
|
||||
return {
|
||||
id: credentials.id,
|
||||
username: credentials.username,
|
||||
email: credentials.email,
|
||||
token: resp.access_token,
|
||||
refreshToken: resp.refresh_token,
|
||||
};
|
||||
}),
|
||||
);
|
||||
if (rawApiResp) {
|
||||
return resp;
|
||||
}
|
||||
|
||||
const state = createState(accountsData);
|
||||
return {
|
||||
id: credentials.id,
|
||||
username: credentials.username,
|
||||
email: credentials.email,
|
||||
token: resp.access_token,
|
||||
refreshToken: resp.refresh_token,
|
||||
};
|
||||
}),
|
||||
);
|
||||
|
||||
localStorage.setItem('redux-storage', JSON.stringify(state));
|
||||
if (updateState) {
|
||||
const state = createState(accountsData);
|
||||
|
||||
return { accounts: accountsData };
|
||||
});
|
||||
localStorage.setItem('redux-storage', JSON.stringify(state));
|
||||
}
|
||||
|
||||
return { accounts: accountsData };
|
||||
},
|
||||
);
|
||||
|
||||
Cypress.Commands.add('getByTestId', (id, options) =>
|
||||
cy.get(`[data-testid=${id}]`, options),
|
||||
|
13
tests-e2e/cypress/support/index.d.ts
vendored
13
tests-e2e/cypress/support/index.d.ts
vendored
@ -15,10 +15,21 @@ declare namespace Cypress {
|
||||
/**
|
||||
* Custom command to log in the user
|
||||
*
|
||||
* @example cy.login(account)
|
||||
* @example cy.login({ accounts: ['default'] })
|
||||
*/
|
||||
login(options: {
|
||||
accounts: AccountAlias[];
|
||||
/**
|
||||
* defaults to `true`. if `false` — than only api response will
|
||||
* be returned without mutating app state
|
||||
* (useful for custom scenarios such as mocking of other api responses
|
||||
* or checking whether account is registered)
|
||||
*/
|
||||
updateState?: boolean;
|
||||
/**
|
||||
* Whether return raw api response without any conversion. Defaults to: `false`
|
||||
*/
|
||||
rawApiResp?: boolean;
|
||||
}): Promise<{ accounts: Account[] }>;
|
||||
|
||||
getByTestId<S = any>(
|
||||
|
Loading…
Reference in New Issue
Block a user