Skip to content
This repository was archived by the owner on Feb 4, 2024. It is now read-only.
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,7 @@ yarn-error.log*

test-report.xml
github.js

# cypress
/cypress/reports
/cypress/downloads
20 changes: 20 additions & 0 deletions cypress.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
const { defineConfig } = require('cypress');

module.exports = defineConfig({
chromeWebSecurity: false,
defaultCommandTimeout: 10000,
viewportWidth: 1920,
viewportHeight: 1080,
e2e: {
// We've imported your old cypress plugins here.
// You may want to clean this up later by importing these.
setupNodeEvents(on, config) {
return require('./cypress/plugins/index.js')(on, config);
},
baseUrl: 'https://react-starter-toolkit.netlify.app',
specPattern: 'cypress/e2e/**/*.feature',
},
video: false,
numTestsKeptInMemory: 10,
screenshotsFolder: 'cypress/reports/screenshots',
});
10 changes: 10 additions & 0 deletions cypress/e2e/Features/GreenIT/Accueil.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
Feature: Green IT - Accueil
En tant que ANONYME,
Je veux mesurer les performances Green IT de la page d'accueil
Afin d'avoir une fonctionnalité respectueuse de l'environnement

@GreenIT
Scenario: Green IT react-starter-toolkit - Accueil
Given Je veux mesurer la performance Green IT de la page d'accueil
When Je mesure la performance Green IT de l'écran
Then La performance Green IT de l'écran doit être correctement mesurée
25 changes: 25 additions & 0 deletions cypress/e2e/common/GreenIT/GreenITSteps.cy.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/* eslint-disable import/no-extraneous-dependencies */
/* eslint-disable no-undef */
/// <reference types="Cypress" />
import { Given, When, Then } from 'cypress-cucumber-preprocessor/steps';

Given("Je veux mesurer la performance Green IT de la page d'accueil", () => {
const screen = 'Accueil';
const url = `${Cypress.config('baseUrl')}`;
cy.configureGreenItReportsGeneration({ screen, url });
});

When("Je mesure la performance Green IT de l'écran", () => {
cy.get('@green-it-url').then((url) => {
cy.get('@green-it-rapport').then((filename) => {
cy.executeLighthouseReportGeneration({ url, filename, token: 'Mon token' });
cy.generateEcoIndexReport({ url, filename, token: 'Mon token' });
});
});
});

Then("La performance Green IT de l'écran doit être correctement mesurée", () => {
cy.get('@green-it-rapport').then((filename) => {
cy.checkGreenItReports({ filename });
});
});
17 changes: 17 additions & 0 deletions cypress/green-it/aggregator/aggregator-args-builder.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
const fs = require('fs');
const { AGGREGATOR_OPTIONS } = require('./aggregator-config');

const { reports, verbose, srcLighthouse, srcEcoIndex, outputPath } = AGGREGATOR_OPTIONS;

const buildAggregatorArgs = () => ({
reports,
verbose,
srcLighthouse,
srcEcoIndex,
outputPath,
});

const shouldRunAggregator = () => fs.existsSync(srcLighthouse) && fs.existsSync(srcEcoIndex);

exports.buildAggregatorArgs = buildAggregatorArgs;
exports.shouldRunAggregator = shouldRunAggregator;
9 changes: 9 additions & 0 deletions cypress/green-it/aggregator/aggregator-config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
const AGGREGATOR_OPTIONS = {
reports: 'html',
verbose: true,
srcLighthouse: './cypress/reports/lighthouse',
srcEcoIndex: './cypress/reports/eco-index',
outputPath: './cypress/reports/green-it',
};

exports.AGGREGATOR_OPTIONS = AGGREGATOR_OPTIONS;
21 changes: 21 additions & 0 deletions cypress/green-it/eco-index/eco-index-args-builder.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
const buildEcoIndexArgs = (options, paths) => {
const { beforeScript, afterScript, globals, url, visits, output, waitForSelector } = options;
const { outputPathDir, outputFileName } = paths;
return {
beforeScript,
afterScript,
headless: false,
globals,
url,
visits,
output,
outputPathDir,
outputFileName,
beforeClosingPageTimeout: 2000,
remote_debugging_port: global.remote_debugging_port,
remote_debugging_address: global.remote_debugging_address,
waitForSelector,
};
};

exports.buildEcoIndexArgs = buildEcoIndexArgs;
18 changes: 18 additions & 0 deletions cypress/green-it/eco-index/eco-index-config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/* eslint-disable no-unused-vars */
export const ECOINDEX_OPTIONS = {
ecoIndex: 50,
grade: 'B',
visits: 2000,
checkThresholds: false,
beforeScript: (globals) => {
/* TODO: Injection authentification depuis globals.token ICI */
},
afterScript: (globals) => {},
globals: ({ token }) => ({ accessToken: JSON.stringify(token) }),
output: ['json'],
waitForSelector: '.af-header__content',
};

export const ECOINDEX_PATHS = {
reportsPath: './cypress/reports/eco-index',
};
56 changes: 56 additions & 0 deletions cypress/green-it/lighthouse/lighthouse-callback.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/* eslint-disable import/no-extraneous-dependencies */
const fs = require('fs');
const { minify } = require('html-minifier');

const createLighthouseReportsDirectories = (paths) => {
if (!fs.existsSync(paths.reportsPath)) {
fs.mkdirSync(paths.reportsPath, (err) => {
if (err) {
throw new Error('An error occurred while creating new directory reports');
}
});
}

if (!fs.existsSync(paths.lighthouseReportsPath)) {
fs.mkdirSync(paths.lighthouseReportsPath, (err) => {
if (err) {
throw new Error('An error occurred while creating new directory lighthouse');
}
});
}
};

const cleanLighthouseReportsFiles = (options, paths) => {
if (fs.existsSync(`${paths.lighthouseReportsPath}${options.filename}.json`)) {
fs.unlinkSync(`${paths.lighthouseReportsPath}${options.filename}.json`);
}
if (fs.existsSync(`${paths.lighthouseReportsPath}${options.filename}.html`)) {
fs.unlinkSync(`${paths.lighthouseReportsPath}${options.filename}.html`);
}
};

const writeLighthouseReportJsonFile = (options, paths, lighthouseReport) => {
const reportContent = JSON.stringify(lighthouseReport.lhr, 0, 2);
fs.writeFileSync(`${paths.lighthouseReportsPath}${options.filename}.json`, reportContent, { flag: 'a+' });
};

const writeLighthouseReportHtmlFile = (options, paths, lighthouseReport) => {
const { reportOptions } = options;
let reportContent = lighthouseReport.report;
if (reportOptions && reportOptions.minifyHtmlReports) {
reportContent = minify(reportContent, reportOptions.htmlMinifierOptions);
}
fs.writeFileSync(`${paths.lighthouseReportsPath}${options.filename}.html`, reportContent, {
flag: 'a+',
});
};

const lighthouseCallback = (options, paths) => (lighthouseReport) => {
createLighthouseReportsDirectories(paths);
cleanLighthouseReportsFiles(options, paths);
writeLighthouseReportJsonFile(options, paths, lighthouseReport);
writeLighthouseReportHtmlFile(options, paths, lighthouseReport);
return lighthouseReport;
};

exports.lighthouseCallback = lighthouseCallback;
78 changes: 78 additions & 0 deletions cypress/green-it/lighthouse/lighthouse-config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
/* eslint-disable no-undef */

export const LIGHTHOUSE_THRESHOLDS = {
performance: 80,
accessibility: 80,
'best-practices': 80,
// the custom audit ("session-init") needs to be referenced so that the lighthouse-session-gatherer is run
'session-init': 80,
};

export const LIGHTHOUSE_OPTIONS = {
formFactor: 'desktop',
screenEmulation: {
mobile: false,
disable: false,
width: Cypress.config('viewportWidth'),
height: Cypress.config('viewportHeight'),
deviceScaleRatio: 1,
},
throttling: {
rttMs: 40,
throughputKbps: 11024,
cpuSlowdownMultiplier: 1,
requestLatencyMs: 0,
downloadThroughputKbps: 0,
uploadThroughputKbps: 0,
},
output: 'html',
logLevel: 'info',
};

export const LIGHTHOUSE_CONFIG = {
extends: 'lighthouse:default',
disableStorageReset: true,
passes: [
{
passName: 'defaultPass',
gatherers: ['cypress/green-it/lighthouse/lighthouse-session-gatherer.mjs'],
recordTrace: true,
pauseAfterLoadMs: 1000,
networkQuietThresholdMs: 1000,
pauseAfterNetworkQuietMs: 1000,
},
],
audits: ['cypress/green-it/lighthouse/lighthouse-session-audit.mjs'], // our custom (dummy) audit
categories: {
'session-init': {
name: 'Browser Session Init',
title: 'Session Config',
description: 'Confirm browser session initialized',
auditRefs: [{ id: 'session-audit', weight: 1 }],
},
pauseAfterLoadMs: 1000,
},
settings: {},
};

export const LIGHTHOUSE_PATHS = {
reportsPath: './cypress/reports/',
lighthouseReportsPath: './cypress/reports/lighthouse/',
};

export const LIGHTHOUSE_REPORT_OPTIONS = {
minifyHtmlReports: true,
htmlMinifierOptions: {
includeAutoGeneratedTags: true,
removeAttributeQuotes: true,
removeComments: true,
removeRedundantAttributes: true,
removeScriptTypeAttributes: true,
removeStyleLinkTypeAttributes: true,
sortClassName: true,
useShortDoctype: true,
collapseWhitespace: true,
minifyCSS: true,
minifyJS: true,
},
};
37 changes: 37 additions & 0 deletions cypress/green-it/lighthouse/lighthouse-session-audit.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/* eslint-disable import/no-extraneous-dependencies */
import { Audit } from 'lighthouse';

const MAX_LOAD_TIME = 100;

export default class SessionAudit extends Audit {
// information about this custom audit - will be displayed in Lighthouse report
static get meta() {
return {
id: 'session-audit',
title: 'Session audit',
category: 'Session Config',
name: 'session-audit',
description: 'Configure the user session',
failureTitle: 'Session audit failed',
failureDescription: 'User session failed to initialize',
requiredArtifacts: ['SessionGatherer'],
};
}

static audit(artifacts) {
// This should "pass" if the token was set (in reality, this should always pass).
// Note: If there isn't an audit using a custom gatherer, the gatherer is not run, so
// this is a dummy audit to force our "createSession" function to be run
const loadMetrics = artifacts.TestProjectHeroImage;
const belowThreshold = loadMetrics <= MAX_LOAD_TIME;
return {
rawValue: loadMetrics,
score: Number(belowThreshold),
};
// return {
// displayValue: `This session's token: ${artifacts}`,
// score: !!artifacts ? 1 : 0,
// numericValue: !!artifacts ? 1 : 0,
// };
}
}
46 changes: 46 additions & 0 deletions cypress/green-it/lighthouse/lighthouse-session-gatherer.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/* eslint-disable import/no-extraneous-dependencies */
/* eslint-disable class-methods-use-this */
import { Gatherer } from 'lighthouse';

function createSession(authtoken) {
// add token to session storage
/* TODO: Injection authentification ICI */
}

export default class SessionGatherer extends Gatherer {
/**
* Called before navigation to target url.
* @param {!Object} options
*/
async beforePass(options) {
const { driver } = options;

// this runs after a new tab is opened, but before the tab visits the URL
driver.executionContext.evaluateOnNewDocument(createSession, {
args: [options.settings.token],
});
// return an "artifact" which can be used in the custom audit
return options.settings.token;
}

/**
* Called after target page is loaded, all gatherer `pass` methods have been
* executed, and — if generated in this pass — the trace is ended. The trace
* and record of network activity are provided in `loadData`.
* @param {!Object} options
* @param {networkRecords: !Array, trace: {traceEvents: !Array}} loadData
* @return {*|!Promise<*>}
*/
async afterPass(options) {
const { driver } = options.driver;
return driver.executionContext.evaluateAsync().then((loadMetrics) => {
if (!loadMetrics || loadMetrics.searchableTime === undefined) {
// Throw if page didn't provide the metrics we expect. This isn't
// fatal -- the Lighthouse run will continue, but any audits that
// depend on this gatherer will show this error string in the report.
throw new Error('Unable to find load metrics in page');
}
return loadMetrics;
});
}
}
Loading