mirror of
https://github.com/danog/inline-critical.git
synced 2024-12-11 17:09:39 +01:00
430 lines
16 KiB
JavaScript
430 lines
16 KiB
JavaScript
'use strict';
|
|
var expect = require('chai').expect;
|
|
var reaver = require('reaver');
|
|
var fs = require('fs');
|
|
var path = require('path');
|
|
var exec = require('child_process').exec;
|
|
var execFile = require('child_process').execFile;
|
|
var readJson = require('read-package-json');
|
|
var mockery = require('mockery');
|
|
var concat = require('concat-stream');
|
|
var inlineCritical = require('..');
|
|
var skipWin = process.platform === 'win32' ? it.skip : it;
|
|
|
|
function strip(string) {
|
|
return string.replace(/[\r\n]+/mg, ' ').replace(/\s+/gm, '');
|
|
}
|
|
|
|
function read(file) {
|
|
return fs.readFileSync(file, 'utf8');
|
|
}
|
|
|
|
describe('Module: inline-critical', function () {
|
|
it('should inline css', function (done) {
|
|
var html = read('test/fixtures/index.html');
|
|
var css = read('test/fixtures/critical.css');
|
|
|
|
var expected = read('test/expected/index-inlined-async-final.html');
|
|
var out = inlineCritical(html, css, {minify: false});
|
|
|
|
expect(strip(out.toString('utf-8'))).to.be.equal(strip(expected));
|
|
|
|
done();
|
|
});
|
|
|
|
it('should inline absolute css', function (done) {
|
|
var html = read('test/fixtures/index-absolute.html');
|
|
var css = read('test/fixtures/critical.css');
|
|
|
|
var expected = read('test/expected/index-inlined-absolute.html');
|
|
var out = inlineCritical(html, css, {minify: false});
|
|
|
|
expect(strip(out.toString('utf-8'))).to.be.equal(strip(expected));
|
|
|
|
done();
|
|
});
|
|
|
|
it('should inline and minify css', function (done) {
|
|
var html = read('test/fixtures/index.html');
|
|
var css = read('test/fixtures/critical.css');
|
|
|
|
var expected = read('test/expected/index-inlined-async-minified-final.html');
|
|
var out = inlineCritical(html, css, {minify: true});
|
|
|
|
expect(strip(out.toString('utf-8'))).to.be.equal(strip(expected));
|
|
|
|
done();
|
|
});
|
|
|
|
it('should inline and extract css', function (done) {
|
|
var html = read('test/fixtures/cartoon.html');
|
|
var css = read('test/fixtures/critical.css');
|
|
var expected = read('test/expected/cartoon-expected.css');
|
|
var expectedHtml = read('test/expected/cartoon-expected.html');
|
|
|
|
var out = inlineCritical(html, css, {minify: false, extract: true, basePath: 'test/fixtures'});
|
|
|
|
expect(read(reaver.rev('test/fixtures/css/cartoon.css', expected))).to.be.equal(expected);
|
|
expect(strip(out.toString('utf-8'))).to.be.equal(strip(expectedHtml));
|
|
|
|
done();
|
|
});
|
|
|
|
it('should inline and extract css correctly with absolute paths', function (done) {
|
|
var html = read('test/fixtures/cartoon-absolute.html');
|
|
var css = read('test/fixtures/critical.css');
|
|
var expected = read('test/expected/cartoon-expected.css');
|
|
var expectedHtml = read('test/expected/cartoon-absolute-expected.html');
|
|
|
|
var out = inlineCritical(html, css, {minify: false, extract: true, basePath: 'test/fixtures'});
|
|
|
|
expect(read(reaver.rev('test/fixtures/css/cartoon.css', expected))).to.be.equal(expected);
|
|
expect(strip(out.toString('utf-8'))).to.be.equal(strip(expectedHtml));
|
|
|
|
done();
|
|
});
|
|
|
|
it('should not strip of svg closing tags', function (done) {
|
|
var html = read('test/fixtures/entities.html');
|
|
var out = inlineCritical(html, '', {minify: false});
|
|
|
|
expect(strip(out.toString('utf-8'))).to.be.equal(strip(html));
|
|
done();
|
|
});
|
|
|
|
it('should not keep external urls', function (done) {
|
|
function strip2(string) {
|
|
return string.replace(/\s+/gm, '');
|
|
}
|
|
|
|
var html = read('test/fixtures/external.html');
|
|
var expected = read('test/expected/external-expected.html');
|
|
var css = read('test/fixtures/critical.css');
|
|
var out = inlineCritical(html, css, {minify: false});
|
|
|
|
expect(strip2(out.toString('utf-8'))).to.be.equal(strip2(expected));
|
|
done();
|
|
});
|
|
|
|
it('should not keep external urls on extract', function (done) {
|
|
function strip2(string) {
|
|
return string.replace(/\s+/gm, '');
|
|
}
|
|
|
|
var html = read('test/fixtures/external.html');
|
|
var expected = read('test/expected/external-extract-expected.html');
|
|
var css = read('test/fixtures/critical.css');
|
|
var out = inlineCritical(html, css, {minify: false, extract: true, basePath: 'test/fixtures'});
|
|
|
|
expect(strip2(out.toString('utf-8'))).to.be.equal(strip2(expected));
|
|
done();
|
|
});
|
|
|
|
it('should keep self closing svg elements', function (done) {
|
|
var html = read('test/fixtures/entities2.html');
|
|
var out = inlineCritical(html, '', {minify: false});
|
|
expect(strip(out.toString('utf-8'))).to.be.equal(strip(html));
|
|
done();
|
|
});
|
|
|
|
it('should respect ignore option with string', function (done) {
|
|
function strip2(string) {
|
|
return string.replace(/\s+/gm, '');
|
|
}
|
|
|
|
var html = read('test/fixtures/external.html');
|
|
var expected = read('test/expected/external-ignore-expected.html');
|
|
var css = read('test/fixtures/critical.css');
|
|
var out = inlineCritical(html, css, {minify: false, ignore: ['bower_components/bootstrap/dist/css/bootstrap.css']});
|
|
|
|
expect(strip2(out.toString('utf-8'))).to.be.equal(strip2(expected));
|
|
done();
|
|
});
|
|
it('should respect ignore option with RegExp', function (done) {
|
|
function strip2(string) {
|
|
return string.replace(/\s+/gm, '');
|
|
}
|
|
|
|
var html = read('test/fixtures/external.html');
|
|
var expected = read('test/expected/external-ignore-expected.html');
|
|
var css = read('test/fixtures/critical.css');
|
|
var out = inlineCritical(html, css, {minify: false, ignore: [/bootstrap/]});
|
|
|
|
expect(strip2(out.toString('utf-8'))).to.be.equal(strip2(expected));
|
|
done();
|
|
});
|
|
|
|
it('should respect selector option', function (done) {
|
|
var html = read('test/fixtures/index.html');
|
|
var css = read('test/fixtures/critical.css');
|
|
|
|
var expected = read('test/expected/index-before.html');
|
|
var out = inlineCritical(html, css, {minify: true, selector: 'title'});
|
|
|
|
expect(strip(out.toString('utf-8'))).to.be.equal(strip(expected));
|
|
done();
|
|
});
|
|
|
|
it('should ignore stylesheets wrapped in noscript', function (done) {
|
|
var html = read('test/fixtures/index-noscript.html');
|
|
var css = read('test/fixtures/critical.css');
|
|
|
|
var expected = read('test/expected/index-noscript-inlined-minified-final.html');
|
|
var out = inlineCritical(html, css, {minify: true});
|
|
|
|
expect(strip(out.toString('utf-8'))).to.be.equal(strip(expected));
|
|
done();
|
|
});
|
|
|
|
it('should skip loadcss if it\'s already present and used for all existing link tags', function (done) {
|
|
var html = read('test/fixtures/loadcss.html');
|
|
var css = read('test/fixtures/critical.css');
|
|
|
|
var expected = read('test/expected/index-loadcss.html');
|
|
var out = inlineCritical(html, css, {minify: true});
|
|
|
|
expect(strip(out.toString('utf-8'))).to.be.equal(strip(expected));
|
|
done();
|
|
});
|
|
});
|
|
|
|
describe('CLI', function () {
|
|
beforeEach(function (done) {
|
|
readJson(path.join(__dirname, '../', 'package.json'), function (err, data) {
|
|
expect(err).to.not.exist;
|
|
this.pkg = data;
|
|
this.bin = path.join(__dirname, '../', data.bin['inline-critical']);
|
|
done();
|
|
}.bind(this));
|
|
});
|
|
|
|
|
|
function handleError(err) {
|
|
expect(err).to.equal(null);
|
|
process.exit(1);
|
|
}
|
|
|
|
describe('acceptance', function () {
|
|
// empty stdout on appveyor? runs correct on manual test with Windows 7
|
|
skipWin('should return the version', function (done) {
|
|
execFile('node', [this.bin, '--version'], function (error, stdout) {
|
|
expect(stdout.replace(/\r\n|\n/g, '')).to.equal(this.pkg.version);
|
|
done();
|
|
}.bind(this));
|
|
});
|
|
|
|
it('should work well with the critical CSS & html file passed as input', function (done) {
|
|
var expected = read('test/expected/index-inlined-async-final.html');
|
|
var cp = execFile('node', [
|
|
this.bin,
|
|
'test/fixtures/index.html',
|
|
'test/fixtures/critical.css',
|
|
'--no-minify'
|
|
]);
|
|
|
|
var cnt = 0;
|
|
cp.stdout.pipe(concat(function(data){
|
|
cnt++;
|
|
expect(strip(data.toString('utf-8'))).to.be.equal(strip(expected));
|
|
}));
|
|
|
|
cp.stdout.on('error', handleError);
|
|
cp.on('close', function(){
|
|
expect(cnt).to.equal(1);
|
|
done();
|
|
});
|
|
});
|
|
|
|
it('should work well with the critical CSS passed as input & html file passed as option', function (done) {
|
|
var expected = read('test/expected/index-inlined-async-final.html');
|
|
var cp = execFile('node', [
|
|
this.bin,
|
|
'--html',
|
|
'test/fixtures/index.html',
|
|
'test/fixtures/critical.css',
|
|
'--no-minify'
|
|
]);
|
|
|
|
var cnt = 0;
|
|
cp.stdout.pipe(concat(function(data){
|
|
cnt++;
|
|
expect(strip(data.toString('utf-8'))).to.be.equal(strip(expected));
|
|
}));
|
|
|
|
cp.stdout.on('error', handleError);
|
|
cp.on('close', function(){
|
|
expect(cnt).to.equal(1);
|
|
done();
|
|
});
|
|
|
|
});
|
|
|
|
it('should work well with the critical CSS passed as option & html file passed as input', function (done) {
|
|
var expected = read('test/expected/index-inlined-async-final.html');
|
|
var cp = execFile('node', [
|
|
this.bin,
|
|
'--css',
|
|
'test/fixtures/critical.css',
|
|
'test/fixtures/index.html',
|
|
'--no-minify'
|
|
]);
|
|
|
|
var cnt = 0;
|
|
cp.stdout.pipe(concat(function(data){
|
|
cnt++;
|
|
expect(strip(data.toString('utf-8'))).to.be.equal(strip(expected));
|
|
}));
|
|
|
|
cp.stdout.on('error', handleError);
|
|
cp.on('close', function(){
|
|
expect(cnt).to.equal(1);
|
|
done();
|
|
});
|
|
});
|
|
|
|
// pipes don't work on windows
|
|
skipWin('should work well with the critical CSS file piped to inline-critical and html file as input', function (done) {
|
|
var cp = exec('cat test/fixtures/critical.css | node ' + this.bin + ' test/fixtures/index.html --no-minify');
|
|
var expected = read('test/expected/index-inlined-async-final.html');
|
|
|
|
var cnt = 0;
|
|
cp.stdout.pipe(concat(function(data){
|
|
cnt++;
|
|
expect(strip(data.toString('utf-8'))).to.be.equal(strip(expected));
|
|
}));
|
|
|
|
cp.stdout.on('error', handleError);
|
|
cp.on('close', function(){
|
|
expect(cnt).to.equal(1);
|
|
done();
|
|
});
|
|
});
|
|
|
|
skipWin('should work well with the html file piped to inline-critical and critical CSS file as input', function (done) {
|
|
var cp = exec('cat test/fixtures/index.html | node ' + this.bin + ' test/fixtures/critical.css --no-minify');
|
|
var expected = read('test/expected/index-inlined-async-final.html');
|
|
|
|
var cnt = 0;
|
|
cp.stdout.pipe(concat(function(data){
|
|
cnt++;
|
|
expect(strip(data.toString('utf-8'))).to.be.equal(strip(expected));
|
|
}));
|
|
|
|
cp.stdout.on('error', handleError);
|
|
cp.on('close', function(){
|
|
expect(cnt).to.equal(1);
|
|
done();
|
|
});
|
|
});
|
|
|
|
it('should exit with code 1 and show help', function (done) {
|
|
execFile('node', [this.bin, 'fixtures/not-exists.html'], function (err, stdout, stderr) {
|
|
expect(err).to.exist;
|
|
expect(err.code).equal(1);
|
|
expect(stderr).to.have.string('Usage:');
|
|
done();
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('mocked', function () {
|
|
beforeEach(function () {
|
|
this.origArgv = process.argv;
|
|
this.origExit = process.exit;
|
|
this.stdout = process.stdout.write;
|
|
this.stderr = process.stderr.write;
|
|
|
|
mockery.enable({
|
|
warnOnUnregistered: false,
|
|
useCleanCache: true
|
|
});
|
|
|
|
mockery.registerMock('./', function (html, styles, options) {
|
|
this.mockOpts = options;
|
|
this.mockOpts.html = html;
|
|
this.mockOpts.css = styles;
|
|
return '';
|
|
}.bind(this));
|
|
});
|
|
|
|
afterEach(function () {
|
|
mockery.deregisterAll();
|
|
mockery.disable();
|
|
process.argv = this.origArgv;
|
|
process.exit = this.origExit;
|
|
});
|
|
|
|
it('should pass the correct opts when using short opts', function (done) {
|
|
process.argv = [
|
|
'node',
|
|
this.bin,
|
|
'-c', 'test/fixtures/critical.css',
|
|
'-h', 'test/fixtures/index.html',
|
|
'-i', 'ignore-me',
|
|
'-i', '/regexp/',
|
|
'-b', 'basePath',
|
|
'-s', 'selector',
|
|
'-m',
|
|
'-e'
|
|
];
|
|
|
|
process.stdout.write = function () {
|
|
};
|
|
process.stderr.write = function () {
|
|
};
|
|
require('../cli');
|
|
|
|
// timeout to wait for get-stdin timeout
|
|
setTimeout(function () {
|
|
process.stdout.write = this.stdout;
|
|
process.stderr.write = this.stderr;
|
|
expect(this.mockOpts.css).to.equal(read('test/fixtures/critical.css'));
|
|
expect(this.mockOpts.html).to.equal(read('test/fixtures/index.html'));
|
|
expect(this.mockOpts.selector).to.equal('selector');
|
|
expect(this.mockOpts.ignore).to.be.instanceof(Array);
|
|
expect(this.mockOpts.ignore[0]).to.be.a('string');
|
|
expect(this.mockOpts.ignore[1]).to.instanceof(RegExp);
|
|
expect(this.mockOpts.minify).to.be.ok;
|
|
expect(this.mockOpts.extract).to.be.ok;
|
|
done();
|
|
}.bind(this), 200);
|
|
});
|
|
|
|
it('should pass the correct opts when using long opts', function (done) {
|
|
process.argv = [
|
|
'node',
|
|
this.bin,
|
|
'--css', 'test/fixtures/critical.css',
|
|
'--html', 'test/fixtures/index.html',
|
|
'--ignore', 'ignore-me',
|
|
'--ignore', '/regexp/',
|
|
'--base', 'basePath',
|
|
'--selector', 'selector',
|
|
'--minify',
|
|
'--extract'
|
|
];
|
|
|
|
process.stdout.write = function () {
|
|
};
|
|
process.stderr.write = function () {
|
|
};
|
|
require('../cli');
|
|
|
|
// timeout to wait for get-stdin timeout
|
|
setTimeout(function () {
|
|
process.stdout.write = this.stdout;
|
|
process.stderr.write = this.stderr;
|
|
expect(this.mockOpts.css).to.equal(read('test/fixtures/critical.css'));
|
|
expect(this.mockOpts.html).to.equal(read('test/fixtures/index.html'));
|
|
expect(this.mockOpts.selector).to.equal('selector');
|
|
expect(this.mockOpts.ignore).to.be.instanceof(Array);
|
|
expect(this.mockOpts.ignore[0]).to.be.a('string');
|
|
expect(this.mockOpts.ignore[1]).to.instanceof(RegExp);
|
|
expect(this.mockOpts.minify).to.be.ok;
|
|
expect(this.mockOpts.extract).to.be.ok;
|
|
done();
|
|
}.bind(this), 200);
|
|
});
|
|
});
|
|
});
|