Initial version of smartbooking generated by generator-jhipster@9.0.0-beta.0
This commit is contained in:
56
src/test/javascript/cypress/e2e/account/login-page.cy.ts
Normal file
56
src/test/javascript/cypress/e2e/account/login-page.cy.ts
Normal file
@@ -0,0 +1,56 @@
|
||||
import {
|
||||
errorLoginSelector,
|
||||
passwordLoginSelector,
|
||||
submitLoginSelector,
|
||||
titleLoginSelector,
|
||||
usernameLoginSelector,
|
||||
} from '../../support/commands';
|
||||
|
||||
describe('login page', () => {
|
||||
const username = Cypress.env('E2E_USERNAME') ?? 'user';
|
||||
const password = Cypress.env('E2E_PASSWORD') ?? 'user';
|
||||
|
||||
beforeEach(() => {
|
||||
cy.visit('');
|
||||
cy.clickOnLoginItem();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
cy.intercept('POST', '/api/authentication').as('authenticate');
|
||||
});
|
||||
|
||||
it('greets with signin', () => {
|
||||
cy.get(titleLoginSelector).should('be.visible');
|
||||
});
|
||||
|
||||
it('requires username', () => {
|
||||
cy.get(passwordLoginSelector).should('be.visible').type('a-password');
|
||||
cy.get(submitLoginSelector).click();
|
||||
cy.wait('@authenticate').then(({ response }) => expect(response?.statusCode).to.equal(401));
|
||||
// login page should stay open when login fails
|
||||
cy.get(titleLoginSelector).should('be.visible');
|
||||
});
|
||||
|
||||
it('requires password', () => {
|
||||
cy.get(usernameLoginSelector).should('be.visible').type('a-login');
|
||||
cy.get(submitLoginSelector).click();
|
||||
cy.wait('@authenticate').then(({ response }) => expect(response?.statusCode).to.equal(401));
|
||||
cy.get(errorLoginSelector).should('be.visible');
|
||||
});
|
||||
|
||||
it('errors when password is incorrect', () => {
|
||||
cy.get(usernameLoginSelector).should('be.visible').type(username);
|
||||
cy.get(passwordLoginSelector).should('be.visible').type('bad-password');
|
||||
cy.get(submitLoginSelector).click();
|
||||
cy.wait('@authenticate').then(({ response }) => expect(response?.statusCode).to.equal(401));
|
||||
cy.get(errorLoginSelector).should('be.visible');
|
||||
});
|
||||
|
||||
it('go to home page when successfully logs in', () => {
|
||||
cy.get(usernameLoginSelector).should('be.visible').type(username);
|
||||
cy.get(passwordLoginSelector).should('be.visible').type(password);
|
||||
cy.get(submitLoginSelector).click();
|
||||
cy.wait('@authenticate').then(({ response }) => expect(response?.statusCode).to.equal(200));
|
||||
cy.hash().should('eq', '');
|
||||
});
|
||||
});
|
||||
21
src/test/javascript/cypress/e2e/account/logout.cy.ts
Normal file
21
src/test/javascript/cypress/e2e/account/logout.cy.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
import { accountMenuSelector, loginItemSelector, navbarSelector } from '../../support/commands';
|
||||
|
||||
describe('logout', () => {
|
||||
const username = Cypress.env('E2E_USERNAME') ?? 'user';
|
||||
const password = Cypress.env('E2E_PASSWORD') ?? 'user';
|
||||
|
||||
beforeEach(() => {
|
||||
cy.intercept('POST', '/api/logout').as('logout');
|
||||
});
|
||||
|
||||
it('go to home page when successfully logs out', () => {
|
||||
cy.login(username, password);
|
||||
cy.visit('');
|
||||
|
||||
cy.clickOnLogoutItem();
|
||||
|
||||
cy.wait('@logout');
|
||||
cy.get(navbarSelector).get(accountMenuSelector).click();
|
||||
cy.get(navbarSelector).get(accountMenuSelector).get(loginItemSelector).should('be.visible');
|
||||
});
|
||||
});
|
||||
66
src/test/javascript/cypress/e2e/account/password-page.cy.ts
Normal file
66
src/test/javascript/cypress/e2e/account/password-page.cy.ts
Normal file
@@ -0,0 +1,66 @@
|
||||
import {
|
||||
classInvalid,
|
||||
classValid,
|
||||
confirmPasswordSelector,
|
||||
currentPasswordSelector,
|
||||
newPasswordSelector,
|
||||
submitPasswordSelector,
|
||||
} from '../../support/commands';
|
||||
|
||||
describe('/account/password', () => {
|
||||
const username = Cypress.env('E2E_USERNAME') ?? 'user';
|
||||
const password = Cypress.env('E2E_PASSWORD') ?? 'user';
|
||||
|
||||
beforeEach(() => {
|
||||
cy.login(username, password);
|
||||
cy.visit('/account/password');
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
cy.intercept('POST', '/api/account/change-password').as('passwordSave');
|
||||
});
|
||||
|
||||
it('should be accessible through menu', () => {
|
||||
cy.visit('');
|
||||
cy.clickOnPasswordItem();
|
||||
cy.url().should('match', /\/account\/password$/);
|
||||
});
|
||||
|
||||
it('requires current password', () => {
|
||||
cy.get(currentPasswordSelector).should('have.class', classInvalid);
|
||||
cy.get(currentPasswordSelector).type('wrong-current-password');
|
||||
cy.get(currentPasswordSelector).blur();
|
||||
cy.get(currentPasswordSelector).should('have.class', classValid);
|
||||
});
|
||||
|
||||
it('requires new password', () => {
|
||||
cy.get(newPasswordSelector).should('have.class', classInvalid);
|
||||
cy.get(newPasswordSelector).type('jhipster');
|
||||
cy.get(newPasswordSelector).blur();
|
||||
cy.get(newPasswordSelector).should('have.class', classValid);
|
||||
});
|
||||
|
||||
it('requires confirm new password', () => {
|
||||
cy.get(newPasswordSelector).type('jhipster');
|
||||
cy.get(confirmPasswordSelector).should('have.class', classInvalid);
|
||||
cy.get(confirmPasswordSelector).type('jhipster');
|
||||
cy.get(confirmPasswordSelector).blur();
|
||||
cy.get(confirmPasswordSelector).should('have.class', classValid);
|
||||
});
|
||||
|
||||
it('should fail to update password when using incorrect current password', () => {
|
||||
cy.get(currentPasswordSelector).type('wrong-current-password');
|
||||
cy.get(newPasswordSelector).type('jhipster');
|
||||
cy.get(confirmPasswordSelector).type('jhipster');
|
||||
cy.get(submitPasswordSelector).click();
|
||||
cy.wait('@passwordSave').then(({ response }) => expect(response?.statusCode).to.equal(400));
|
||||
});
|
||||
|
||||
it('should be able to update password', () => {
|
||||
cy.get(currentPasswordSelector).type(password);
|
||||
cy.get(newPasswordSelector).type(password);
|
||||
cy.get(confirmPasswordSelector).type(password);
|
||||
cy.get(submitPasswordSelector).click();
|
||||
cy.wait('@passwordSave').then(({ response }) => expect(response?.statusCode).to.equal(200));
|
||||
});
|
||||
});
|
||||
90
src/test/javascript/cypress/e2e/account/register-page.cy.ts
Normal file
90
src/test/javascript/cypress/e2e/account/register-page.cy.ts
Normal file
@@ -0,0 +1,90 @@
|
||||
import {
|
||||
classInvalid,
|
||||
classValid,
|
||||
emailRegisterSelector,
|
||||
firstPasswordRegisterSelector,
|
||||
secondPasswordRegisterSelector,
|
||||
submitRegisterSelector,
|
||||
usernameRegisterSelector,
|
||||
} from '../../support/commands';
|
||||
|
||||
describe('/register', () => {
|
||||
beforeEach(() => {
|
||||
cy.visit('/register');
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
cy.intercept('POST', '/api/register').as('registerSave');
|
||||
});
|
||||
|
||||
it('should be accessible through menu', () => {
|
||||
cy.visit('');
|
||||
cy.clickOnRegisterItem();
|
||||
cy.url().should('match', /\/register$/);
|
||||
});
|
||||
|
||||
it('should load the register page', () => {
|
||||
cy.get(submitRegisterSelector).should('be.visible');
|
||||
});
|
||||
|
||||
it('requires username', () => {
|
||||
cy.get(usernameRegisterSelector).should('have.class', classInvalid);
|
||||
cy.get(usernameRegisterSelector).type('test');
|
||||
cy.get(usernameRegisterSelector).blur();
|
||||
cy.get(usernameRegisterSelector).should('have.class', classValid);
|
||||
});
|
||||
|
||||
it('should not accept invalid email', () => {
|
||||
cy.get(emailRegisterSelector).should('have.class', classInvalid);
|
||||
cy.get(emailRegisterSelector).type('testtest.fr');
|
||||
cy.get(emailRegisterSelector).blur();
|
||||
cy.get(emailRegisterSelector).should('have.class', classInvalid);
|
||||
});
|
||||
|
||||
it('requires email in correct format', () => {
|
||||
cy.get(emailRegisterSelector).should('have.class', classInvalid);
|
||||
cy.get(emailRegisterSelector).type('test@test.fr');
|
||||
cy.get(emailRegisterSelector).blur();
|
||||
cy.get(emailRegisterSelector).should('have.class', classValid);
|
||||
});
|
||||
|
||||
it('requires first password', () => {
|
||||
cy.get(firstPasswordRegisterSelector).should('have.class', classInvalid);
|
||||
cy.get(firstPasswordRegisterSelector).type('test@test.fr');
|
||||
cy.get(firstPasswordRegisterSelector).blur();
|
||||
cy.get(firstPasswordRegisterSelector).should('have.class', classValid);
|
||||
});
|
||||
|
||||
it('requires password and confirm password to be same', () => {
|
||||
cy.get(firstPasswordRegisterSelector).should('have.class', classInvalid);
|
||||
cy.get(firstPasswordRegisterSelector).type('test');
|
||||
cy.get(firstPasswordRegisterSelector).blur();
|
||||
cy.get(firstPasswordRegisterSelector).should('have.class', classValid);
|
||||
cy.get(secondPasswordRegisterSelector).should('have.class', classInvalid);
|
||||
cy.get(secondPasswordRegisterSelector).type('test');
|
||||
cy.get(secondPasswordRegisterSelector).blur();
|
||||
cy.get(secondPasswordRegisterSelector).should('have.class', classValid);
|
||||
});
|
||||
|
||||
it('requires password and confirm password have not the same value', () => {
|
||||
cy.get(firstPasswordRegisterSelector).should('have.class', classInvalid);
|
||||
cy.get(firstPasswordRegisterSelector).type('test');
|
||||
cy.get(firstPasswordRegisterSelector).blur();
|
||||
cy.get(firstPasswordRegisterSelector).should('have.class', classValid);
|
||||
cy.get(secondPasswordRegisterSelector).should('have.class', classInvalid);
|
||||
cy.get(secondPasswordRegisterSelector).type('otherPassword');
|
||||
cy.get(secondPasswordRegisterSelector).blur();
|
||||
cy.get(secondPasswordRegisterSelector).should('have.class', classInvalid);
|
||||
});
|
||||
|
||||
it('register a valid user', () => {
|
||||
const randomEmail = 'Marina96@yahoo.com';
|
||||
const randomUsername = 'Isobel35';
|
||||
cy.get(usernameRegisterSelector).type(randomUsername);
|
||||
cy.get(emailRegisterSelector).type(randomEmail);
|
||||
cy.get(firstPasswordRegisterSelector).type('jondoe');
|
||||
cy.get(secondPasswordRegisterSelector).type('jondoe');
|
||||
cy.get(submitRegisterSelector).click();
|
||||
cy.wait('@registerSave').then(({ response }) => expect(response?.statusCode).to.equal(201));
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,35 @@
|
||||
import {
|
||||
classInvalid,
|
||||
classValid,
|
||||
emailResetPasswordSelector,
|
||||
forgetYourPasswordSelector,
|
||||
submitInitResetPasswordSelector,
|
||||
usernameLoginSelector,
|
||||
} from '../../support/commands';
|
||||
|
||||
describe('forgot your password', () => {
|
||||
const username = Cypress.env('E2E_USERNAME') ?? 'user';
|
||||
|
||||
beforeEach(() => {
|
||||
cy.visit('');
|
||||
cy.clickOnLoginItem();
|
||||
cy.get(usernameLoginSelector).should('be.visible').type(username);
|
||||
cy.get(forgetYourPasswordSelector).click();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
cy.intercept('POST', '/api/account/reset-password/init').as('initResetPassword');
|
||||
});
|
||||
|
||||
it('requires email', () => {
|
||||
cy.get(emailResetPasswordSelector).should('have.class', classInvalid);
|
||||
cy.get(emailResetPasswordSelector).type('user@gmail.com');
|
||||
cy.get(emailResetPasswordSelector).should('have.class', classValid);
|
||||
});
|
||||
|
||||
it('should be able to init reset password', () => {
|
||||
cy.get(emailResetPasswordSelector).type('user@gmail.com');
|
||||
cy.get(submitInitResetPasswordSelector).click({ force: true });
|
||||
cy.wait('@initResetPassword').then(({ response }) => expect(response?.statusCode).to.equal(200));
|
||||
});
|
||||
});
|
||||
102
src/test/javascript/cypress/e2e/account/settings-page.cy.ts
Normal file
102
src/test/javascript/cypress/e2e/account/settings-page.cy.ts
Normal file
@@ -0,0 +1,102 @@
|
||||
import type { Account } from '../../support/account';
|
||||
import { emailSettingsSelector, firstNameSettingsSelector, lastNameSettingsSelector, submitSettingsSelector } from '../../support/commands';
|
||||
|
||||
describe('/account/settings', () => {
|
||||
const adminUsername = Cypress.env('E2E_USERNAME') ?? 'admin';
|
||||
const adminPassword = Cypress.env('E2E_PASSWORD') ?? 'admin';
|
||||
const username = Cypress.env('E2E_USERNAME') ?? 'user';
|
||||
const password = Cypress.env('E2E_PASSWORD') ?? 'user';
|
||||
|
||||
const testUserEmail = 'user@localhost.fr';
|
||||
let originalUserAccount: Account;
|
||||
let testUserAccount: Account;
|
||||
|
||||
before(() => {
|
||||
cy.login(username, password);
|
||||
|
||||
cy.getAccount().then(account => {
|
||||
originalUserAccount = account;
|
||||
testUserAccount = { ...account, email: testUserEmail };
|
||||
|
||||
// need to modify email because default email does not match regex in some frameworks
|
||||
cy.saveAccount(testUserAccount).its('status').should('eq', 200);
|
||||
});
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
cy.login(username, password);
|
||||
cy.visit('/account/settings');
|
||||
cy.get(emailSettingsSelector).should('have.value', testUserEmail);
|
||||
|
||||
cy.intercept('POST', '/api/account').as('settingsSave');
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
cy.login(username, password);
|
||||
cy.saveAccount(testUserAccount).its('status').should('eq', 200);
|
||||
});
|
||||
|
||||
after(() => {
|
||||
cy.login(username, password);
|
||||
cy.saveAccount(originalUserAccount).its('status').should('eq', 200);
|
||||
});
|
||||
|
||||
it('should be accessible through menu', () => {
|
||||
cy.visit('');
|
||||
cy.clickOnSettingsItem();
|
||||
cy.url().should('match', /\/account\/settings$/);
|
||||
});
|
||||
|
||||
it("should be able to change 'user' firstname settings", () => {
|
||||
cy.get(firstNameSettingsSelector).clear();
|
||||
cy.get(firstNameSettingsSelector).type('jhipster');
|
||||
cy.get(submitSettingsSelector).click();
|
||||
cy.wait('@settingsSave').then(({ response }) => expect(response?.statusCode).to.equal(200));
|
||||
});
|
||||
|
||||
it("should be able to change 'user' lastname settings", () => {
|
||||
cy.get(lastNameSettingsSelector).clear();
|
||||
cy.get(firstNameSettingsSelector).type('jhipster');
|
||||
cy.get(lastNameSettingsSelector).type('retspihj');
|
||||
cy.get(submitSettingsSelector).click();
|
||||
cy.wait('@settingsSave').then(({ response }) => expect(response?.statusCode).to.equal(200));
|
||||
});
|
||||
|
||||
it("should be able to change 'user' email settings", () => {
|
||||
cy.get(emailSettingsSelector).clear();
|
||||
cy.get(firstNameSettingsSelector).type('jhipster');
|
||||
cy.get(emailSettingsSelector).type('user@localhost.fr');
|
||||
cy.get(submitSettingsSelector).click();
|
||||
cy.wait('@settingsSave').then(({ response }) => expect(response?.statusCode).to.equal(200));
|
||||
});
|
||||
|
||||
describe('if there is another user with an email', () => {
|
||||
let originalAdminAccount: Account;
|
||||
const testAdminEmail = 'admin@localhost.fr';
|
||||
|
||||
before(() => {
|
||||
cy.login(adminUsername, adminPassword);
|
||||
cy.getAccount().then(account => {
|
||||
originalAdminAccount = account;
|
||||
|
||||
// need to modify email because default email does not match regex in some frameworks
|
||||
cy.saveAccount({ ...account, email: testAdminEmail })
|
||||
.its('status')
|
||||
.should('eq', 200);
|
||||
});
|
||||
});
|
||||
|
||||
after(() => {
|
||||
cy.login(adminUsername, adminPassword);
|
||||
cy.saveAccount(originalAdminAccount).its('status').should('eq', 200);
|
||||
});
|
||||
|
||||
it("should not be able to change 'user' email to same value", () => {
|
||||
cy.get(emailSettingsSelector).clear();
|
||||
cy.get(firstNameSettingsSelector).type('jhipster');
|
||||
cy.get(emailSettingsSelector).type(testAdminEmail);
|
||||
cy.get(submitSettingsSelector).click();
|
||||
cy.wait('@settingsSave').then(({ response }) => expect(response?.statusCode).to.equal(400));
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,76 @@
|
||||
import {
|
||||
configurationPageHeadingSelector,
|
||||
healthPageHeadingSelector,
|
||||
logsPageHeadingSelector,
|
||||
metricsPageHeadingSelector,
|
||||
swaggerFrameSelector,
|
||||
swaggerPageSelector,
|
||||
userManagementPageHeadingSelector,
|
||||
} from '../../support/commands';
|
||||
|
||||
describe('/admin', () => {
|
||||
const username = Cypress.env('E2E_USERNAME') ?? 'admin';
|
||||
const password = Cypress.env('E2E_PASSWORD') ?? 'admin';
|
||||
|
||||
beforeEach(() => {
|
||||
cy.login(username, password);
|
||||
cy.visit('');
|
||||
});
|
||||
|
||||
describe('/user-management', () => {
|
||||
it('should load the page', () => {
|
||||
cy.clickOnAdminMenuItem('user-management');
|
||||
cy.get(userManagementPageHeadingSelector).should('be.visible');
|
||||
});
|
||||
});
|
||||
|
||||
describe('/metrics', () => {
|
||||
it('should load the page', () => {
|
||||
cy.clickOnAdminMenuItem('metrics');
|
||||
cy.get(metricsPageHeadingSelector).should('be.visible');
|
||||
});
|
||||
});
|
||||
|
||||
describe('/health', () => {
|
||||
it('should load the page', () => {
|
||||
cy.clickOnAdminMenuItem('health');
|
||||
cy.get(healthPageHeadingSelector).should('be.visible');
|
||||
});
|
||||
});
|
||||
|
||||
describe('/logs', () => {
|
||||
it('should load the page', () => {
|
||||
cy.clickOnAdminMenuItem('logs');
|
||||
cy.get(logsPageHeadingSelector).should('be.visible');
|
||||
});
|
||||
});
|
||||
|
||||
describe('/configuration', () => {
|
||||
it('should load the page', () => {
|
||||
cy.clickOnAdminMenuItem('configuration');
|
||||
cy.get(configurationPageHeadingSelector).should('be.visible');
|
||||
});
|
||||
});
|
||||
|
||||
describe('/docs', () => {
|
||||
it('should load the page', () => {
|
||||
cy.getManagementInfo().then(info => {
|
||||
if (info.activeProfiles.includes('api-docs')) {
|
||||
cy.clickOnAdminMenuItem('docs');
|
||||
cy.get(swaggerFrameSelector)
|
||||
.should('be.visible')
|
||||
.then(() => {
|
||||
// Wait iframe to load
|
||||
cy.wait(500); // eslint-disable-line cypress/no-unnecessary-waiting
|
||||
const getSwaggerIframe = () => {
|
||||
return cy.get(swaggerFrameSelector).its('0.contentDocument.body').should('not.be.empty').then(cy.wrap);
|
||||
};
|
||||
getSwaggerIframe().find(swaggerPageSelector, { timeout: 15000 }).should('be.visible');
|
||||
getSwaggerIframe().find('[id="select"] > option').its('length').should('be.gt', 0);
|
||||
getSwaggerIframe().find(swaggerPageSelector).then(cy.wrap).find('.information-container').its('length').should('be.gt', 0);
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
28
src/test/javascript/cypress/e2e/lighthouse.audits.ts
Normal file
28
src/test/javascript/cypress/e2e/lighthouse.audits.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
describe('Lighthouse Audits', () => {
|
||||
beforeEach(() => {
|
||||
cy.visit('/');
|
||||
});
|
||||
|
||||
it('homepage', () => {
|
||||
const customThresholds = {
|
||||
performance: 80,
|
||||
accessibility: 90,
|
||||
seo: 90,
|
||||
'best-practices': 90,
|
||||
// If you have enabled PWA you should set this threshold to 100
|
||||
pwa: 0,
|
||||
};
|
||||
|
||||
const desktopConfig = {
|
||||
extends: 'lighthouse:default',
|
||||
formFactor: 'desktop',
|
||||
// Change the CPU slowdown multiplier to emulate different kind of devices
|
||||
// See https://github.com/GoogleChrome/lighthouse/blob/master/docs/throttling.md#cpu-throttling for details
|
||||
throttling: {
|
||||
cpuSlowdownMultiplier: 1,
|
||||
},
|
||||
screenEmulation: { disabled: true },
|
||||
};
|
||||
cy.lighthouse(customThresholds, desktopConfig);
|
||||
});
|
||||
});
|
||||
BIN
src/test/javascript/cypress/fixtures/integration-test.png
Normal file
BIN
src/test/javascript/cypress/fixtures/integration-test.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.1 KiB |
49
src/test/javascript/cypress/plugins/index.ts
Normal file
49
src/test/javascript/cypress/plugins/index.ts
Normal file
@@ -0,0 +1,49 @@
|
||||
// ***********************************************************
|
||||
// This example plugins/index.js can be used to load plugins
|
||||
//
|
||||
// You can change the location of this file or turn off loading
|
||||
// the plugins file with the 'pluginsFile' configuration option.
|
||||
//
|
||||
// You can read more here:
|
||||
// https://on.cypress.io/plugins-guide
|
||||
// ***********************************************************
|
||||
|
||||
// This function is called when a project is opened or re-opened (e.g. due to
|
||||
// the project's config changing)
|
||||
import { existsSync, mkdirSync, writeFileSync } from 'fs';
|
||||
|
||||
import { lighthouse, pa11y, prepareAudit } from 'cypress-audit';
|
||||
|
||||
export default (on: Cypress.PluginEvents, config: Cypress.PluginConfigOptions) => {
|
||||
on('before:browser:launch', (browser, launchOptions) => {
|
||||
prepareAudit(launchOptions);
|
||||
if (browser.name === 'chrome' && browser.isHeadless) {
|
||||
launchOptions.args.push('--disable-gpu');
|
||||
return launchOptions;
|
||||
}
|
||||
});
|
||||
|
||||
// Allows logging with cy.task('log', 'message') or cy.task('table', object)
|
||||
on('task', {
|
||||
log(message) {
|
||||
console.log(message);
|
||||
return null;
|
||||
},
|
||||
table(message) {
|
||||
console.table(message);
|
||||
return null;
|
||||
},
|
||||
});
|
||||
|
||||
on('task', {
|
||||
lighthouse: lighthouse(async lighthouseReport => {
|
||||
const { default: ReportGenerator } = await import('lighthouse/report/generator/report-generator');
|
||||
if (!existsSync('build/cypress/')) {
|
||||
mkdirSync('build/cypress/', { recursive: true });
|
||||
}
|
||||
writeFileSync('build/cypress/lhreport.html', ReportGenerator.generateReport(lighthouseReport.lhr, 'html'));
|
||||
}),
|
||||
pa11y: pa11y(),
|
||||
});
|
||||
return config;
|
||||
};
|
||||
28
src/test/javascript/cypress/support/account.ts
Normal file
28
src/test/javascript/cypress/support/account.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
/* eslint-disable @typescript-eslint/no-namespace */
|
||||
export type Account = Record<string, string | boolean | number>;
|
||||
|
||||
Cypress.Commands.add('getAccount', () => {
|
||||
return cy
|
||||
.authenticatedRequest({
|
||||
method: 'GET',
|
||||
url: '/api/account',
|
||||
})
|
||||
.then(response => response.body as Account);
|
||||
});
|
||||
|
||||
Cypress.Commands.add('saveAccount', (account: Account) => {
|
||||
return cy.authenticatedRequest({
|
||||
method: 'POST',
|
||||
url: '/api/account',
|
||||
body: account,
|
||||
});
|
||||
});
|
||||
|
||||
declare global {
|
||||
namespace Cypress {
|
||||
interface Chainable {
|
||||
getAccount(): Cypress.Chainable<Account>;
|
||||
saveAccount(account: Account): Cypress.Chainable<Cypress.Response<Account>>;
|
||||
}
|
||||
}
|
||||
}
|
||||
123
src/test/javascript/cypress/support/commands.ts
Normal file
123
src/test/javascript/cypress/support/commands.ts
Normal file
@@ -0,0 +1,123 @@
|
||||
/* eslint-disable @typescript-eslint/no-namespace */
|
||||
|
||||
// ***********************************************
|
||||
// This commands.ts shows you how to
|
||||
// create various custom commands and overwrite
|
||||
// existing commands.
|
||||
//
|
||||
// For more comprehensive examples of custom
|
||||
// commands please read more here:
|
||||
// https://on.cypress.io/custom-commands
|
||||
// ***********************************************
|
||||
|
||||
// ***********************************************
|
||||
// Begin Specific Selector Attributes for Cypress
|
||||
// ***********************************************
|
||||
|
||||
// Navbar
|
||||
export const navbarSelector = '[data-cy="navbar"]';
|
||||
export const adminMenuSelector = '[data-cy="adminMenu"]';
|
||||
export const accountMenuSelector = '[data-cy="accountMenu"]';
|
||||
export const registerItemSelector = '[data-cy="register"]';
|
||||
export const settingsItemSelector = '[data-cy="settings"]';
|
||||
export const passwordItemSelector = '[data-cy="passwordItem"]';
|
||||
export const loginItemSelector = '[data-cy="login"]';
|
||||
export const logoutItemSelector = '[data-cy="logout"]';
|
||||
export const entityItemSelector = '[data-cy="entity"]';
|
||||
|
||||
// Login
|
||||
export const titleLoginSelector = '[data-cy="loginTitle"]';
|
||||
export const errorLoginSelector = '[data-cy="loginError"]';
|
||||
export const usernameLoginSelector = '[data-cy="username"]';
|
||||
export const passwordLoginSelector = '[data-cy="password"]';
|
||||
export const forgetYourPasswordSelector = '[data-cy="forgetYourPasswordSelector"]';
|
||||
export const submitLoginSelector = '[data-cy="submit"]';
|
||||
|
||||
// Register
|
||||
export const usernameRegisterSelector = '[data-cy="username"]';
|
||||
export const emailRegisterSelector = '[data-cy="email"]';
|
||||
export const firstPasswordRegisterSelector = '[data-cy="firstPassword"]';
|
||||
export const secondPasswordRegisterSelector = '[data-cy="secondPassword"]';
|
||||
export const submitRegisterSelector = '[data-cy="submit"]';
|
||||
|
||||
// Settings
|
||||
export const firstNameSettingsSelector = '[data-cy="firstname"]';
|
||||
export const lastNameSettingsSelector = '[data-cy="lastname"]';
|
||||
export const emailSettingsSelector = '[data-cy="email"]';
|
||||
export const submitSettingsSelector = '[data-cy="submit"]';
|
||||
|
||||
// Password
|
||||
export const currentPasswordSelector = '[data-cy="currentPassword"]';
|
||||
export const newPasswordSelector = '[data-cy="newPassword"]';
|
||||
export const confirmPasswordSelector = '[data-cy="confirmPassword"]';
|
||||
export const submitPasswordSelector = '[data-cy="submit"]';
|
||||
|
||||
// Reset Password
|
||||
export const emailResetPasswordSelector = '[data-cy="emailResetPassword"]';
|
||||
export const submitInitResetPasswordSelector = '[data-cy="submit"]';
|
||||
|
||||
// Administration
|
||||
export const userManagementPageHeadingSelector = '[data-cy="userManagementPageHeading"]';
|
||||
export const swaggerFrameSelector = 'iframe[data-cy="swagger-frame"]';
|
||||
export const swaggerPageSelector = '[id="swagger-ui"]';
|
||||
export const metricsPageHeadingSelector = '[data-cy="metricsPageHeading"]';
|
||||
export const healthPageHeadingSelector = '[data-cy="healthPageHeading"]';
|
||||
export const logsPageHeadingSelector = '[data-cy="logsPageHeading"]';
|
||||
export const configurationPageHeadingSelector = '[data-cy="configurationPageHeading"]';
|
||||
|
||||
// ***********************************************
|
||||
// End Specific Selector Attributes for Cypress
|
||||
// ***********************************************
|
||||
|
||||
export const classInvalid = 'is-invalid';
|
||||
|
||||
export const classValid = 'is-valid';
|
||||
|
||||
Cypress.Commands.add('authenticatedRequest', data => {
|
||||
return cy.getCookie('XSRF-TOKEN').then(csrfCookie => {
|
||||
return cy.request({
|
||||
...data,
|
||||
headers: {
|
||||
...data.headers,
|
||||
'X-XSRF-TOKEN': csrfCookie?.value,
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Cypress.Commands.add('login', (username: string, password: string) => {
|
||||
cy.session(
|
||||
[username, password],
|
||||
() => {
|
||||
cy.request({
|
||||
method: 'GET',
|
||||
url: '/api/account',
|
||||
failOnStatusCode: false,
|
||||
});
|
||||
cy.authenticatedRequest({
|
||||
method: 'POST',
|
||||
body: { username, password },
|
||||
url: Cypress.env('authenticationUrl'),
|
||||
form: true,
|
||||
});
|
||||
},
|
||||
{
|
||||
validate() {
|
||||
cy.authenticatedRequest({ url: '/api/account' }).its('status').should('eq', 200);
|
||||
},
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
declare global {
|
||||
namespace Cypress {
|
||||
interface Chainable {
|
||||
authenticatedRequest(data): Cypress.Chainable;
|
||||
login(username: string, password: string): Cypress.Chainable;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
import 'cypress-audit/commands';
|
||||
// Convert this to a module instead of a script (allows import/export)
|
||||
export {};
|
||||
77
src/test/javascript/cypress/support/entity.ts
Normal file
77
src/test/javascript/cypress/support/entity.ts
Normal file
@@ -0,0 +1,77 @@
|
||||
/* eslint-disable @typescript-eslint/no-namespace */
|
||||
|
||||
// ***********************************************
|
||||
// Begin Specific Selector Attributes for Cypress
|
||||
// ***********************************************
|
||||
|
||||
// Entity
|
||||
export const entityTableSelector = '[data-cy="entityTable"]';
|
||||
export const entityCreateButtonSelector = '[data-cy="entityCreateButton"]';
|
||||
export const entityCreateSaveButtonSelector = '[data-cy="entityCreateSaveButton"]';
|
||||
export const entityCreateCancelButtonSelector = '[data-cy="entityCreateCancelButton"]';
|
||||
export const entityDetailsButtonSelector = '[data-cy="entityDetailsButton"]'; // can return multiple elements
|
||||
export const entityDetailsBackButtonSelector = '[data-cy="entityDetailsBackButton"]';
|
||||
export const entityEditButtonSelector = '[data-cy="entityEditButton"]';
|
||||
export const entityDeleteButtonSelector = '[data-cy="entityDeleteButton"]';
|
||||
export const entityConfirmDeleteButtonSelector = '[data-cy="entityConfirmDeleteButton"]';
|
||||
|
||||
// ***********************************************
|
||||
// End Specific Selector Attributes for Cypress
|
||||
// ***********************************************
|
||||
|
||||
Cypress.Commands.add('getEntityHeading', (entityName: string) => cy.get(`[data-cy="${entityName}Heading"]`));
|
||||
|
||||
Cypress.Commands.add('getEntityCreateUpdateHeading', (entityName: string) => cy.get(`[data-cy="${entityName}CreateUpdateHeading"]`));
|
||||
|
||||
Cypress.Commands.add('getEntityDetailsHeading', (entityInstanceName: string) => cy.get(`[data-cy="${entityInstanceName}DetailsHeading"]`));
|
||||
|
||||
Cypress.Commands.add('getEntityDeleteDialogHeading', (entityInstanceName: string) =>
|
||||
cy.get(`[data-cy="${entityInstanceName}DeleteDialogHeading"]`),
|
||||
);
|
||||
|
||||
Cypress.Commands.add('setFieldImageAsBytesOfEntity', (fieldName: string, fileName: string, mimeType: string) => {
|
||||
// fileName is the image which you have already put in cypress fixture folder
|
||||
// should be like: 'integration-test.png', 'image/png'
|
||||
cy.fixture(fileName)
|
||||
.as('image')
|
||||
.get(`[data-cy="${fieldName}"]`)
|
||||
.then(function (el) {
|
||||
const blob = Cypress.Blob.base64StringToBlob(this.image, mimeType);
|
||||
const file = new File([blob], fileName, { type: mimeType });
|
||||
const list = new DataTransfer();
|
||||
list.items.add(file);
|
||||
(el[0] as HTMLInputElement).files = list.files;
|
||||
el[0].dispatchEvent(new Event('change', { bubbles: true }));
|
||||
});
|
||||
});
|
||||
|
||||
Cypress.Commands.add('setFieldSelectToLastOfEntity', (fieldName: string) => {
|
||||
return cy.get(`[data-cy="${fieldName}"]`).then(select => {
|
||||
const selectSize = (select[0] as HTMLSelectElement)?.options?.length || Number(select.attr('size')) || 0;
|
||||
if (selectSize > 0) {
|
||||
return cy.get(`[data-cy="${fieldName}"] option`).then((options: JQuery<HTMLElement>) => {
|
||||
const elements = [...options].map((o: HTMLElement) => (o as HTMLOptionElement).label);
|
||||
const lastElement = elements.length - 1;
|
||||
cy.get(`[data-cy="${fieldName}"]`).select(lastElement);
|
||||
cy.get(`[data-cy="${fieldName}"]`).type('{downarrow}');
|
||||
});
|
||||
}
|
||||
return cy.get(`[data-cy="${fieldName}"]`).type('{downarrow}');
|
||||
});
|
||||
});
|
||||
|
||||
declare global {
|
||||
namespace Cypress {
|
||||
interface Chainable {
|
||||
getEntityHeading(entityName: string): Cypress.Chainable;
|
||||
getEntityCreateUpdateHeading(entityName: string): Cypress.Chainable;
|
||||
getEntityDetailsHeading(entityInstanceName: string): Cypress.Chainable;
|
||||
getEntityDeleteDialogHeading(entityInstanceName: string): Cypress.Chainable;
|
||||
setFieldImageAsBytesOfEntity(fieldName: string, fileName: string, mimeType: string): Cypress.Chainable;
|
||||
setFieldSelectToLastOfEntity(fieldName: string): Cypress.Chainable;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Convert this to a module instead of a script (allows import/export)
|
||||
export {};
|
||||
20
src/test/javascript/cypress/support/index.ts
Normal file
20
src/test/javascript/cypress/support/index.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
// ***********************************************************
|
||||
// This support/index.js is processed and
|
||||
// loaded automatically before your test files.
|
||||
//
|
||||
// This is a great place to put global configuration and
|
||||
// behavior that modifies Cypress.
|
||||
//
|
||||
// You can change the location of this file or turn off
|
||||
// automatically serving support files with the
|
||||
// 'supportFile' configuration option.
|
||||
//
|
||||
// You can read more here:
|
||||
// https://on.cypress.io/configuration
|
||||
// ***********************************************************
|
||||
|
||||
import './account';
|
||||
import './commands';
|
||||
import './navbar';
|
||||
import './entity';
|
||||
import './management';
|
||||
22
src/test/javascript/cypress/support/management.ts
Normal file
22
src/test/javascript/cypress/support/management.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
/* eslint-disable @typescript-eslint/no-namespace */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-return */
|
||||
|
||||
Cypress.Commands.add('getManagementInfo', () => {
|
||||
return cy
|
||||
.request({
|
||||
method: 'GET',
|
||||
url: '/management/info',
|
||||
})
|
||||
.then(response => response.body);
|
||||
});
|
||||
|
||||
declare global {
|
||||
namespace Cypress {
|
||||
interface Chainable {
|
||||
getManagementInfo(): Cypress.Chainable;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Convert this to a module instead of a script (allows import/export)
|
||||
export {};
|
||||
65
src/test/javascript/cypress/support/navbar.ts
Normal file
65
src/test/javascript/cypress/support/navbar.ts
Normal file
@@ -0,0 +1,65 @@
|
||||
/* eslint-disable @typescript-eslint/no-namespace */
|
||||
|
||||
import {
|
||||
accountMenuSelector,
|
||||
adminMenuSelector,
|
||||
entityItemSelector,
|
||||
loginItemSelector,
|
||||
logoutItemSelector,
|
||||
navbarSelector,
|
||||
passwordItemSelector,
|
||||
registerItemSelector,
|
||||
settingsItemSelector,
|
||||
} from './commands';
|
||||
|
||||
Cypress.Commands.add('clickOnLoginItem', () => {
|
||||
cy.get(navbarSelector).get(accountMenuSelector).click();
|
||||
return cy.get(navbarSelector).get(accountMenuSelector).get(loginItemSelector).click();
|
||||
});
|
||||
|
||||
Cypress.Commands.add('clickOnLogoutItem', () => {
|
||||
cy.get(navbarSelector).get(accountMenuSelector).click();
|
||||
return cy.get(navbarSelector).get(accountMenuSelector).get(logoutItemSelector).click();
|
||||
});
|
||||
|
||||
Cypress.Commands.add('clickOnRegisterItem', () => {
|
||||
cy.get(navbarSelector).get(accountMenuSelector).click();
|
||||
return cy.get(navbarSelector).get(accountMenuSelector).get(registerItemSelector).click();
|
||||
});
|
||||
|
||||
Cypress.Commands.add('clickOnSettingsItem', () => {
|
||||
cy.get(navbarSelector).get(accountMenuSelector).click();
|
||||
return cy.get(navbarSelector).get(accountMenuSelector).get(settingsItemSelector).click();
|
||||
});
|
||||
|
||||
Cypress.Commands.add('clickOnPasswordItem', () => {
|
||||
cy.get(navbarSelector).get(accountMenuSelector).click();
|
||||
return cy.get(navbarSelector).get(accountMenuSelector).get(passwordItemSelector).click();
|
||||
});
|
||||
|
||||
Cypress.Commands.add('clickOnAdminMenuItem', (item: string) => {
|
||||
cy.get(navbarSelector).get(adminMenuSelector).click();
|
||||
return cy.get(navbarSelector).get(adminMenuSelector).get(`.dropdown-item[href="/admin/${item}"]`).click();
|
||||
});
|
||||
|
||||
Cypress.Commands.add('clickOnEntityMenuItem', (entityName: string) => {
|
||||
cy.get(navbarSelector).get(entityItemSelector).click();
|
||||
return cy.get(navbarSelector).get(entityItemSelector).get(`.dropdown-item[href="/${entityName}"]`).click();
|
||||
});
|
||||
|
||||
declare global {
|
||||
namespace Cypress {
|
||||
interface Chainable {
|
||||
clickOnLoginItem(): Cypress.Chainable;
|
||||
clickOnLogoutItem(): Cypress.Chainable;
|
||||
clickOnRegisterItem(): Cypress.Chainable;
|
||||
clickOnSettingsItem(): Cypress.Chainable;
|
||||
clickOnPasswordItem(): Cypress.Chainable;
|
||||
clickOnAdminMenuItem(item: string): Cypress.Chainable;
|
||||
clickOnEntityMenuItem(entityName: string): Cypress.Chainable;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Convert this to a module instead of a script (allows import/export)
|
||||
export {};
|
||||
11
src/test/javascript/cypress/tsconfig.json
Normal file
11
src/test/javascript/cypress/tsconfig.json
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"extends": "@vue/tsconfig/tsconfig.dom.json",
|
||||
"compilerOptions": {
|
||||
"baseUrl": "./",
|
||||
"sourceMap": false,
|
||||
"outDir": "../../../../build/cypress/tsc",
|
||||
"target": "es2018",
|
||||
"types": ["cypress", "node"]
|
||||
},
|
||||
"include": ["./../../../../cypress*.config.ts", "./**/*.ts"]
|
||||
}
|
||||
Reference in New Issue
Block a user