Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Expand test setup #105

Merged
merged 30 commits into from
Jul 12, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
8905ffc
POC: Screenshot-based tests of randomly generated HTML before vs afte…
papandreou Nov 2, 2019
66eb145
Simplify a bit with excludedDescendants
papandreou Nov 3, 2019
f9a9d28
Back to the official html-generators
papandreou Nov 6, 2019
24270e3
Wire css-generators in
papandreou Nov 9, 2019
7ac62ea
Check in the smiley
papandreou Nov 10, 2019
bf04bfc
Handle empty attributes
papandreou Nov 10, 2019
74a9757
Render the HTML when the before-vs-after assertion fails
papandreou Nov 11, 2019
a891ace
Render the original HTML when it fails
papandreou Nov 11, 2019
318c796
Avoid all:initial
papandreou Nov 11, 2019
b9c9c0b
Also avoid all:unset
papandreou Nov 13, 2019
e48da7f
Increase mocha timeout
papandreou Nov 13, 2019
596bcc2
Update unexpected-check to ^2.3.1
papandreou Nov 18, 2019
1407955
Update assetgraph to ^6.0.3
papandreou Nov 28, 2019
34f62a0
Use html-generators' stringify, which has had some fixes applied
papandreou Nov 28, 2019
9c4993e
Add a bit of debugging code
papandreou Nov 28, 2019
c1e9797
Add oblique with angle workaround
papandreou Dec 1, 2019
1305471
Avoid font-variant-caps for now (not supported)
papandreou Dec 1, 2019
9daaaa3
Fix lint
papandreou Dec 1, 2019
558628e
Update css-generators and html-generators to the latest master commits
papandreou Dec 10, 2019
b643f42
Merge branch 'master' into feature/htmlGeneratorTests
papandreou Jan 3, 2020
7cdc7ec
Add test/expect.js and separate the generated tests from the referenc…
papandreou Jan 3, 2020
c88681b
Merge branch 'master' into feature/htmlGeneratorTests
papandreou Jul 5, 2020
7e00f1f
prettier --write test/generatedHtml.js
papandreou Jul 5, 2020
9f9ad69
Clean up fuzz testing setup a bit
papandreou Jul 5, 2020
30dcf0d
subsetFonts: Default to global.console when no console is handed in (…
papandreou Jul 5, 2020
31fc53d
Add more reference image tests
papandreou Jul 5, 2020
a9b487f
Degrade the missing glyph message to info now that we overcome it better
papandreou Jul 5, 2020
d8c79b7
Whoops, it's maxIterations
papandreou Jul 5, 2020
2989082
Just do one iteration so it isn't too slow
papandreou Jul 5, 2020
d65da5f
Update to released versions of html-generators and css-generators
papandreou Jul 5, 2020
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
2 changes: 1 addition & 1 deletion .mocharc.yml
Original file line number Diff line number Diff line change
@@ -1 +1 @@
timeout: 30000
timeout: 300000
4 changes: 2 additions & 2 deletions lib/subsetFonts.js
Original file line number Diff line number Diff line change
Expand Up @@ -581,7 +581,7 @@ async function subsetFonts(
fontDisplay,
onlyInfo,
dynamic,
console,
console = global.console,
} = {}
) {
if (!validFontDisplayValues.includes(fontDisplay)) {
Expand Down Expand Up @@ -909,7 +909,7 @@ async function subsetFonts(
When your primary webfont doesn't contain the glyphs you use, browsers that don't support unicode-range will load your fallback fonts, which will be a potential waste of bandwidth.
These glyphs are used on your site, but they don't exist in the font you applied to them:`;

assetGraph.warn(new Error(`${message}\n${errorLog.join('\n')}`));
assetGraph.info(new Error(`${message}\n${errorLog.join('\n')}`));
}

// Insert subsets:
Expand Down
4 changes: 4 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@
},
"devDependencies": {
"coveralls": "^3.0.9",
"css-generators": "^0.2.0",
"eslint": "^7.4.0",
"eslint-config-prettier": "^6.7.0",
"eslint-config-standard": "^14.0.0",
Expand All @@ -76,7 +77,9 @@
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-promise": "^4.0.1",
"eslint-plugin-standard": "^4.0.0",
"html-generators": "^1.0.3",
"httpception": "^3.0.0",
"magicpen-prism": "^3.0.2",
"mocha": "^8.0.1",
"nyc": "^15.1.0",
"offline-github-changelog": "^1.6.1",
Expand All @@ -85,6 +88,7 @@
"puppeteer": "^3.1.0",
"sinon": "^9.0.2",
"unexpected": "^11.8.1",
"unexpected-check": "^2.3.1",
"unexpected-resemble": "^4.3.0",
"unexpected-set": "^2.0.1",
"unexpected-sinon": "^10.11.2"
Expand Down
114 changes: 114 additions & 0 deletions test/expect.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
const expect = require('unexpected')
.clone()
.use(require('unexpected-resemble'))
.use(require('unexpected-check'))
.use(require('magicpen-prism'));
const subsetFonts = require('../lib/subsetFonts');
const pathModule = require('path');
const AssetGraph = require('assetgraph');

let browser;
async function getBrowser() {
if (!browser) {
browser = await require('puppeteer').launch();

after(async function () {
await browser.close();
});
}
return browser;
}

async function screenshot(browser, assetGraph, bannedUrls) {
const page = await browser.newPage();
await page.setRequestInterception(true);
const loadedUrls = [];
page.on('request', (request) => {
const url = request.url();
loadedUrls.push(url);
if (url.startsWith('https://example.com/')) {
let agUrl = url.replace('https://example.com/', assetGraph.root);
if (/\/$/.test(agUrl)) {
agUrl += 'index.html';
}
const asset = assetGraph.findAssets({
isLoaded: true,
url: agUrl,
})[0];
if (asset) {
request.respond({
status: 200,
contentType: asset.contentType,
body: asset.rawSrc,
});
return;
}
}
request.continue();
});
await page.goto('https://example.com/');
if (bannedUrls) {
const loadedBannedUrls = loadedUrls.filter((url) =>
bannedUrls.includes(url)
);
if (loadedBannedUrls.length > 0) {
throw new Error(
`One or more of the original fonts were loaded:\n ${loadedBannedUrls.join(
'\n '
)}`
);
}
}
const screenshot = await page.screenshot();
await page.close();
return screenshot;
}

expect.addAssertion(
'<string> to render the same after subsetting <object?>',
(expect, path, ...rest) => {
const assetGraph = new AssetGraph({
root: pathModule.resolve(
__dirname,
'..',
'testdata',
'referenceImages',
path
),
});
return expect(assetGraph, 'to render the same after subsetting', ...rest);
}
);

expect.addAssertion(
'<object> to render the same after subsetting <object?>',
async (expect, assetGraph, options = {}) => {
const [htmlAsset] = await assetGraph.loadAssets('index.html');
const originalText = htmlAsset.text;
expect.subjectOutput = (output) => {
output.code(originalText, 'html');
};

await assetGraph.populate();
const browser = await getBrowser();
const fontsBefore = assetGraph
.findAssets({ type: { $in: ['Ttf', 'Woff', 'Woff2', 'Eot'] } })
.map((asset) =>
asset.url.replace(assetGraph.root, 'https://example.com/')
);
const screenshotBefore = await screenshot(browser, assetGraph);
const { fontInfo } = await subsetFonts(assetGraph, options);
if (fontInfo.length > 0) {
const screenshotAfter = await screenshot(
browser,
assetGraph,
fontsBefore
);
await expect(screenshotAfter, 'to resemble', screenshotBefore, {
mismatchPercentage: 0,
});
}
}
);

module.exports = expect;
115 changes: 115 additions & 0 deletions test/generatedHtml.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
const fs = require('fs');
const { html } = require('html-generators');
const { stylesheet } = require('css-generators');
const AssetGraph = require('assetgraph');
const pathModule = require('path');
const stringify = require('html-generators/src/stringify');
const expect = require('./expect');

function fixupUnsupportedHtmlConstructs(obj) {
if (obj.type === 'tag') {
if (obj.tag === 'object') {
delete obj.attributes.data;
}
if ('src' in obj.attributes) {
delete obj.attributes.src;
}
for (const child of obj.children) {
fixupUnsupportedHtmlConstructs(child);
}
}
}

describe('generated html', function () {
let smileySvgBase64;

before(async function () {
smileySvgBase64 = `data:image/svg+xml;base64,${fs
.readFileSync(
pathModule.resolve(__dirname, '..', 'testdata', 'smiley.svg')
)
.toString('base64')}`;
});

it('should render the same before and after subsetting', async function () {
return expect(
async (htmlObjectTree, stylesheet) => {
fixupUnsupportedHtmlConstructs(htmlObjectTree);

stylesheet = stylesheet
.replace(/url\([^)]*\)/g, `url(${smileySvgBase64})`)
.replace(/all: (?:initial|unset);/g, '') // Makes the contents of stylesheets visible
.replace(/font-variant-caps: [^;]+;/, '') // See build #260.3 failure
.replace(/oblique [0-9.]+\w+/, 'oblique'); // oblique with an angle is not yet fully standardized or implemented in font-snapper
const head = htmlObjectTree.children[0];
head.children.push({
type: 'tag',
tag: 'style',
attributes: [],
children: [
{
type: 'text',
value: `
@font-face {
font-family: 'IBM Plex Sans';
font-style: normal;
font-weight: 400;
src: url('IBMPlexSans-Regular.woff') format('woff');
}

@font-face {
font-family: 'IBM Plex Sans';
font-style: italic;
font-weight: 400;
src: url('IBMPlexSans-Italic.woff') format('woff');
}
body {
font-family: 'IBM Plex Sans', sans-serif;
font-style: normal;
font-weight: 400;
}

${stylesheet}
`,
},
],
});

const assetGraph = new AssetGraph({
root: pathModule.resolve(
__dirname,
'..',
'testdata',
'subsetFonts',
'unused-variant-on-one-page'
),
});
const text = stringify(htmlObjectTree);
assetGraph.addAsset({
url: `${assetGraph.root}index.html`,
type: 'Html',
text,
});
await assetGraph.populate();
return expect(assetGraph, 'to render the same after subsetting', {
omitFallbacks: true,
});
},
'to be valid for all',
{
maxIterations: 1,
generators: [
html({
excludedDescendants: new Set([
'svg',
'script',
'style',
'progress',
]),
}),
stylesheet,
],
}
);
});
});
Loading