Skip to content

Instantly share code, notes, and snippets.

@Friss
Last active April 16, 2020 05:45
Show Gist options
  • Save Friss/8121c0462544d7515c498b512dbe9303 to your computer and use it in GitHub Desktop.
Save Friss/8121c0462544d7515c498b512dbe9303 to your computer and use it in GitHub Desktop.
/* This uses a modified version of puppeteer-to-istanbul and v8-to-istanbul */
// There are a lot of diffs here but most of it is just prettier changes :(
// https://github.com/istanbuljs/puppeteer-to-istanbul/compare/master...Friss:master
// Mostly just converting it to handle the new async v8-to-istanbul code. Also fetches sourcemaps if availabile.
// https://github.com/istanbuljs/v8-to-istanbul/compare/source-maps...Friss:source-maps
// Tweaks to parse the path out to webpack files that I recreated based on the source maps.
const fetch = require('node-fetch');
const sourceMap = require('source-map');
const fs = require('fs');
const pti = require('./puppeteer-to-istanbul/index.js');
const puppeteer = require('puppeteer');
(async () => {
const browser = await puppeteer.launch({ headless: true });
const page = await browser.newPage();
// Enable both JavaScript and CSS coverage
await Promise.all([
page.coverage.startJSCoverage(),
page.coverage.startCSSCoverage(),
]);
// Navigate to page
await page.goto('https://app.hubspot.com/login');
// TODO Make sure the page actually loaded successfully.
// Disable both JavaScript and CSS coverage
const [jsCoverage, cssCoverage] = await Promise.all([
page.coverage.stopJSCoverage(),
page.coverage.stopCSSCoverage(),
]);
let totalBytes = 0;
let usedBytes = 0;
const coverage = [...jsCoverage, ...cssCoverage];
for (const entry of coverage) {
totalBytes += entry.text.length;
for (const range of entry.ranges) usedBytes += range.end - range.start - 1;
}
console.log(`Bytes used: ${(usedBytes / totalBytes) * 100}%`);
await browser.close();
// We only care about hubspot JS coverage currently so filter out any other scripts.
const hubspotUrls = jsCoverage.filter(entry => {
return (
entry.url.indexOf('hsappstatic.net') > -1 ||
entry.url.indexOf('hubspot') > -1
);
});
// Fetch the source map
const rawSourceMap = await fetch(
'https://static.hsappstatic.net/LoginUI/static-1.2758/bundles/project.js.map'
).then(res => res.text());
// Write out all the source files based on the source map.
await sourceMap.SourceMapConsumer.with(rawSourceMap, null, consumer => {
consumer.sources.forEach(src => {
const srcCode = consumer.sourceContentFor(src, true);
if (srcCode) {
const outputFilePath = `./.nyc_output/js/${src}`.replace(
'webpack:///',
'webpack:/'
);
const outputDir = outputFilePath.split('/');
outputDir.pop();
fs.mkdirSync(outputDir.join('/'), { recursive: true });
fs.writeFileSync(outputFilePath, srcCode);
}
});
});
// Convert the Chrome Coverage to istanbul coverage.
// This uses the special patched versions of the packages included in the repo.
await pti.write(hubspotUrls);
console.log('Done');
})();
/* Franken script attempt at mapping code coverage back to istanbul */
// This creates a report that looks like https://i.imgur.com/EKjSmiR.png which has all the files but the coverage is all broken.
const fetch = require('node-fetch');
const sourceMap = require('source-map');
const sourceMapLib = require('istanbul-lib-source-maps');
const libCoverage = require('istanbul-lib-coverage');
const libReport = require('istanbul-lib-report');
const reports = require('istanbul-reports');
const mkdirp = require('mkdirp');
const fs = require('fs');
(async () => {
const pti = require('puppeteer-to-istanbul');
const puppeteer = require('puppeteer');
const browser = await puppeteer.launch({ headless: true });
const page = await browser.newPage();
// Enable both JavaScript and CSS coverage
await Promise.all([
page.coverage.startJSCoverage(),
page.coverage.startCSSCoverage(),
]);
// Navigate to page
await page.goto('https://app.hubspot.com/login');
// Disable both JavaScript and CSS coverage
const [jsCoverage, cssCoverage] = await Promise.all([
page.coverage.stopJSCoverage(),
page.coverage.stopCSSCoverage(),
]);
let totalBytes = 0;
let usedBytes = 0;
const coverage = [...jsCoverage, ...cssCoverage];
for (const entry of coverage) {
totalBytes += entry.text.length;
for (const range of entry.ranges) usedBytes += range.end - range.start - 1;
}
console.log(`Bytes used: ${(usedBytes / totalBytes) * 100}%`);
await browser.close();
const hubspotUrls = jsCoverage.filter(entry => {
return (
entry.url.indexOf('hsappstatic.net') > -1 ||
entry.url.indexOf('hubspot') > -1
);
});
const rawSourceMap = await fetch(
'https://static.hsappstatic.net/LoginUI/static-1.2758/bundles/project.js.map'
).then(res => res.text());
await sourceMap.SourceMapConsumer.with(rawSourceMap, null, consumer => {
consumer.sources.forEach(src => {
const srcCode = consumer.sourceContentFor(src, true);
if (srcCode) {
const outputFilePath = `./.nyc_output/js/${src}`.replace(
'webpack:///',
'webpack:/'
);
const outputDir = outputFilePath.split('/');
outputDir.pop();
fs.mkdirSync(outputDir.join('/'), { recursive: true });
fs.writeFileSync(outputFilePath, srcCode);
} else {
console.log(src);
}
});
});
await pti.write(hubspotUrls);
const store = sourceMapLib.createSourceMapStore({});
const unmappedCoverage = fs.readFileSync('.nyc_output/out.json').toString();
const converage = JSON.parse(unmappedCoverage);
converage[
'/Users/zfriss/src/puppeteer-tests/.nyc_output/js/project.js'
].inputSourceMap = JSON.parse(rawSourceMap);
const coverageMap = libCoverage.createCoverageMap(converage);
const transformed = store.transformCoverage(coverageMap);
const output = {};
Object.keys(transformed.map.data).forEach(key => {
const value = transformed.map.data[key];
if (value.data) {
output[key] = value.data;
} else {
output[key] = value;
}
});
fs.writeFileSync('.nyc_output/out.json', JSON.stringify(output), 'utf8');
fs.writeFileSync('out_transform.json', JSON.stringify(transformed), 'utf8');
fs.writeFileSync('out_backup.json', unmappedCoverage, 'utf8');
{
"name": "puppeteer-tests",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"coverage": "nyc report --reporter=html --reporter=text",
"instrument": "nyc instrument",
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"devDependencies": {
"istanbul-api": "^2.1.5",
"istanbul-lib-coverage": "^2.0.4",
"istanbul-lib-report": "^2.0.7",
"istanbul-lib-source-maps": "^3.0.5",
"istanbul-reports": "^2.2.3",
"nyc": "^13.3.0",
"puppeteer": "^1.14.0",
"puppeteer-to-istanbul": "^1.2.2",
"node-fetch": "^2.3.0",
"source-map": "^0.7.3",
"source-map-support": "^0.5.11"
},
"dependencies": {}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment