Skip to content

Commit

Permalink
SBVT-699: Update Cypress to use CDN for scripts (#19)
Browse files Browse the repository at this point in the history
* SBVT-699: Gets the CDNs as soon as the plugin file is loaded

* SBVT-699: Remove the folder with all the hard coded minified files

* SBVT-699: Renaming function

* SBVT-699: removing junk

* SBVT-699: removing async for the return function

Co-authored-by: trevor.nelms <[email protected]>
  • Loading branch information
tnelms1 and trevor.nelms authored Dec 13, 2022
1 parent 6d8c332 commit dd72148
Show file tree
Hide file tree
Showing 6 changed files with 105 additions and 83 deletions.
7 changes: 3 additions & 4 deletions commands.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ let toolkitScripts;
let deviceInfoResponse;

Cypress.Commands.add('sbvtCapture', { prevSubject: 'optional' }, (element, name, options) => {
if (!toolkitScripts) cy.task('loadScripts').then((scripts) => toolkitScripts = scripts) //load the scripts from the toolkit
if (!toolkitScripts) cy.task('getToolkit').then((scripts) => toolkitScripts = scripts);
imageName = (name) ? name : (function(){throw new Error("sbvtCapture name cannot be null, please try sbvtCapture('Example name')")})(); //check for file name and then assign to global let
imageType = (options && options.capture) ? options.capture : imageType; //pass through options.capture if provided

Expand All @@ -29,10 +29,9 @@ Cypress.Commands.add('sbvtCapture', { prevSubject: 'optional' }, (element, name,

cy.task('logger', {type: 'trace', message: `Beginning sbvtCapture('${name}')`});
if (element) cy.task('logger', {type: 'trace', message: 'This is chained and there is an "element" value'});

cy.window()
.then((win) => {
userAgentData = win.eval(toolkitScripts.userAgentScript)
userAgentData = win.eval(toolkitScripts.userAgent)
return cy.task('postTestRunId', userAgentData).then((taskData) => {
vtConfFile = taskData; //grab visualTest.config.js data
cy.request({
Expand Down Expand Up @@ -177,7 +176,7 @@ let picFileFormat = () => {
let domCapture = () => {
cy.window()
.then((win) => {
dom = win.eval(toolkitScripts.captureDomScript)
dom = win.eval(toolkitScripts.domCapture)
});
};
let getImageById = () => {
Expand Down
167 changes: 102 additions & 65 deletions plugin.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
const axios = require('axios').default;
const { v4: uuidv4 } = require('uuid');
const fs = require("fs");
const toolkitScripts = require('./sbvt-browser-toolkit/index');
const package_json = require('./package.json');
const cwd = process.cwd();
const path = require("path");
Expand All @@ -14,78 +13,116 @@ logger.level = 'warn' ;// warn will be the default level for debug logs
//set debug flag on visualTest.config.js file by including: PINO_LOG_LEVEL: 'trace'
//options are [trace, debug, info, warn, error, fatal] in that order

let config = {};

//TODO work on this file if cypress is not a devDependency, and a regular it throws errors...


let usersCypress;
try {
const packageFile = fs.readFileSync(path.resolve(path.dirname(require.resolve('cypress', {paths: [cwd]})), 'package.json'))
usersCypress = JSON.parse(packageFile.toString());
if (!usersCypress.version) {
usersCypress.version = "10.0.0.failure" // #TODO improve this if cypress folder isnt found (when the folder isnt a devDependency)
usersCypress.version = "10.0.0.failure"
logger.warn('failed to find cypress assuming it is v10+')
}
} catch (err) {
logger.warn("catch")
usersCypress.version = "10.0.0" // #TODO improve this if cypress folder isnt found
usersCypress.version = "10.0.0"
console.log(err)
logger.warn(err.message)
}

let configFile = (() => {
try {
let config = {}
const fileName = 'visualTest.config.js';
const fullPath = `${process.cwd()}/${fileName}`;
if (fs.existsSync(fullPath)) {
logger.trace(fileName + ' has been found');
config = {...require(fullPath)}; //write the VT config file into config object

function getCdnUrl() {
return config.apiHost === 'https://api.dev.visualtest.io' ? "https://cdn.dev.visualtest.io/browser-toolkit"
: config.apiHost === 'https://api.int.visualtest.io' ? "https://cdn.int.visualtest.io/browser-toolkit"
: "https://cdn.visualtest.io/browser-toolkit";
}
config.cdnUrl = getCdnUrl();
return config;
} else {
config.fail = true;
logger.fatal('The path ' + fullPath + ' was not found');
return config;
}
} catch (e) {
console.log(e)
}})();

let getDomCapture = (async () => {
try {
const domCapture = await axios.get(`${configFile.cdnUrl}/dom-capture.min.js`)
return domCapture.data
} catch (error) {
configFile.fail = true;
logger.fatal(`Error with grabbing getDomCapture: %o`, error.message);
}
})();

let getUserAgent = (async () => {
try {
const domCapture = await axios.get(`${configFile.cdnUrl}/user-agent.min.js`)
return domCapture.data
} catch (error) {
configFile.fail = true;
logger.fatal(`Error with grabbing getUserAgent: %o`, error.message);
}
})();

let domToolKit = null
Promise.all([getDomCapture, getUserAgent]).then((values) => {
const data = {}
data.domCapture = values[0]
data.userAgent = values[1]
domToolKit = data
});

function makeGlobalRunHooks() {
return {
'task': {
async postTestRunId (userAgent) { //cy.task('postTestRunId') to run this code
if (!config.testRunId && !config.fail) {//all this only needs to run once
const fileName = 'visualTest.config.js';
if (!configFile.testRunId && !configFile.fail) {//all this only needs to run once
const sessionId = uuidv4();
const fullPath = `${process.cwd()}/${fileName}`;
if (fs.existsSync(fullPath)) {
logger.trace(fileName + ' has been found');
config = {...require(fullPath)}; //write the VT config file into config object
} else {
config.fail = true;
logger.fatal('The path ' + fullPath + ' was not found');
return config;
}

if (config.PINO_LOG_LEVEL) {
logger.level = config.PINO_LOG_LEVEL //overwrite if the user includes a pino flag in VTconf
} else if (config.log) {
logger.level = config.log
if (configFile.PINO_LOG_LEVEL) {
logger.level = configFile.PINO_LOG_LEVEL //overwrite if the user includes a pino flag in VTconf
} else if (configFile.log) {
logger.level = configFile.log
}

if (!config.projectToken) { //check to make sure user added a projectToken
config.fail = true;
if (!configFile.projectToken) { //check to make sure user added a projectToken
configFile.fail = true;
logger.fatal(`Please add **module.exports = { projectToken: 'PROJECT_TOKEN' }** to your visualTest.config.js file`);
return config;
return configFile;
}

if (config.projectToken.includes("_")) { //check to make sure the user changed it from the default
config.fail = true;
if (configFile.projectToken.includes("_")) { //check to make sure the user changed it from the default
configFile.fail = true;
logger.fatal(`Please insert your actual projectToken`);
return config;
return configFile;
}

if (!config.projectToken.split('/')[1]) { //check to make sure user added the auth part(~second-half) of projectToken
config.fail = true;
if (!configFile.projectToken.split('/')[1]) { //check to make sure user added the auth part(~second-half) of projectToken
configFile.fail = true;
logger.fatal(`Please add your full projectToken for example -> ** projectToken: 'xxxxxxxx/xxxxxxxxxxxx' **`);
return config;
return configFile;
}

logger.trace('config.projectToken: ' + config.projectToken);
config.projectId = config.projectToken.split('/')[0]; //take the first ~half to get the projectId
logger.trace('config.projectId: ' + config.projectId);
logger.trace('config.projectToken: ' + configFile.projectToken);
configFile.projectId = configFile.projectToken.split('/')[0]; //take the first ~half to get the projectId
logger.trace('config.projectId: ' + configFile.projectId);

axios.defaults.headers.common['Authorization'] = `Bearer ${config.projectToken}`;
axios.defaults.headers.common['Authorization'] = `Bearer ${configFile.projectToken}`;
logger.trace(`axios.defaults.headers.common['Authorization']: ` + axios.defaults.headers.common['Authorization']);

config.sessionId = sessionId;
logger.trace('config.sessionId: ' + config.sessionId);
configFile.sessionId = sessionId;
logger.trace('config.sessionId: ' + configFile.sessionId);

if (!config.testRunName) { //if testRunName not defined---testRunName will be the sessionId
if (!configFile.testRunName) { //if testRunName not defined---use device / browser
let osPrettyName;
if (userAgent.osName === 'macos') {
osPrettyName = 'macOS';
Expand All @@ -97,40 +134,40 @@ function makeGlobalRunHooks() {
const browserPrettyName = str.charAt(0).toUpperCase() + str.slice(1);

const browserMajorVersion = userAgent.browserVersion.split('.');
config.testRunName = `${osPrettyName} ${userAgent.osVersion} / ${browserPrettyName} ${browserMajorVersion[0]}`;
configFile.testRunName = `${osPrettyName} ${userAgent.osVersion} / ${browserPrettyName} ${browserMajorVersion[0]}`;
}
logger.trace('config.testRunName: ' + config.testRunName);
logger.trace('config.testRunName: ' + configFile.testRunName);

if (config.apiHost) {
if (configFile.apiHost) {
logger.debug('Found config.apiHost')
config.url = config.apiHost
logger.warn('overwritten URL is: ' + config.url);
} else{
config.url = 'https://api.visualtest.io';
logger.trace('URL is: ' + config.url);
configFile.url = configFile.apiHost
logger.warn('overwritten URL is: ' + configFile.url);
} else {
configFile.url = 'https://api.visualtest.io';
logger.trace('URL is: ' + configFile.url);
}
config.websiteUrl = config.url.replace('api', 'app');
logger.trace('config.websiteUrl: ' + config.websiteUrl);
configFile.websiteUrl = configFile.url.replace('api', 'app');
logger.trace('config.websiteUrl: ' + configFile.websiteUrl);

config.cypressVersion = usersCypress.version
configFile.cypressVersion = usersCypress.version
try {
const postResponse = await axios.post(`${config.url}/api/v1/projects/${config.projectId}/testruns`, {
testRunName: config.testRunName,
const postResponse = await axios.post(`${configFile.url}/api/v1/projects/${configFile.projectId}/testruns`, {
testRunName: configFile.testRunName,
sdk: 'cypress',
sdkVersion: `${package_json.version}/c${usersCypress.version}`
})
config.testRunId = postResponse.data.testRunId;
logger.debug('config.testRunId: ' + config.testRunId);
configFile.testRunId = postResponse.data.testRunId;
logger.debug('config.testRunId: ' + configFile.testRunId);
} catch (error) {
config.fail = true;
configFile.fail = true;
logger.fatal(`Error with creating testRun: %o`, error.message);
logger.trace(`Full error with creating testRun: %o`, error);
return config;
return configFile;
}
config.fail = false; //no errors in generating testRunId
configFile.fail = false; //no errors in generating testRunId
logger.trace('—————————————————Successfully created a testRunId—————————————————');
}
return config;
return configFile;
},
async logger ({type, message}) { //this task is for printing logs to node console from the custom command
type === 'fatal' ? logger.fatal(message) :
Expand All @@ -142,19 +179,19 @@ function makeGlobalRunHooks() {
logger.warn('error with the logger task')
return null
},
async loadScripts () {
return toolkitScripts
getToolkit () {
return domToolKit;
}
},
'after:run':
async () => {
if (config.fail === false) {
if (configFile.fail === false) {
try {
const imageResponse = await axios.get(`${config.url}/api/v1/projects/${config.projectId}/testruns/${config.testRunId}/images`);
const imageResponse = await axios.get(`${configFile.url}/api/v1/projects/${configFile.projectId}/testruns/${configFile.testRunId}/images`);
const imageCount = imageResponse.data.page.totalItems;

process.stdout.write(`View your ${imageCount} ${(imageCount === 1 ? 'capture' : 'captures')} here: `);
console.log(chalk.blue(`${config.websiteUrl}/projects/${config.projectId}/testruns/${config.testRunId}/comparisons`));
console.log(chalk.blue(`${configFile.websiteUrl}/projects/${configFile.projectId}/testruns/${configFile.testRunId}/comparisons`));

function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
Expand All @@ -164,7 +201,7 @@ function makeGlobalRunHooks() {
let comparisonTotal = 0;
for (let i = 0; comparisonTotal !== imageCount && i < 15; i++) {
if (i > 0) await sleep(250); //don't wait the first iteration
comparisonResponse = await axios.get(`${config.url}/api/v1/projects/${config.projectId}/testruns/${config.testRunId}?expand=comparison-totals`);
comparisonResponse = await axios.get(`${configFile.url}/api/v1/projects/${configFile.projectId}/testruns/${configFile.testRunId}?expand=comparison-totals`);
comparisonTotal = comparisonResponse.data.comparisons.total;
}
let comparisonResult = comparisonResponse.data.comparisons;
Expand All @@ -177,7 +214,7 @@ function makeGlobalRunHooks() {
} catch (error) {
console.error(error);
}
} else if (config.fail === true) {
} else if (configFile.fail === true) {
logger.fatal('There were issues with VisualTest. Check above logs.');
} else {
console.log('There were no VisualTest captures taken.');
Expand Down
1 change: 0 additions & 1 deletion sbvt-browser-toolkit/dist/dom-capture.min.js

This file was deleted.

1 change: 0 additions & 1 deletion sbvt-browser-toolkit/dist/freeze-page.min.js

This file was deleted.

Loading

0 comments on commit dd72148

Please sign in to comment.