index.spec.js
const chai = require('chai');
const cleanCSS = require('.');
const concat = require('gulp-concat');
const File = require('vinyl');
const gulp = require('gulp');
const gulpSass = require('gulp-sass');
const rename = require('gulp-rename');
const sourcemaps = require('gulp-sourcemaps');
const expect = chai.expect;
chai.should();
chai.use(require('chai-string'));
describe('gulp-clean-css: init', () => {
it('should return the gulp-clean-css object: required export', () => {
expect(cleanCSS).to.exist;
});
});
describe('gulp-clean-css: base functionality', () => {
it('should play nicely with other plugins: gulp-sass: before', done => {
let i = 0;
gulp.src(['test/fixtures/**/*.scss', '!test/fixtures/empty/**', '!test/fixtures/sourcemaps-load/**'])
.pipe(gulpSass())
.pipe(cleanCSS())
.pipe(rename({
suffix: '.generated',
}))
.pipe(gulp.dest('test/fixtures/'))
.on('data', file => {
i += 1;
})
.once('end', () => {
i.should.equal(3);
done();
});
});
it('should allow the file through', done => {
let i = 0;
gulp.src('test/fixtures/test.css')
.pipe(cleanCSS())
.on('data', file => {
i += 1;
})
.once('end', () => {
i.should.equal(1);
done();
});
});
it('should allow the file through: no options specified', done => {
let i = 0;
gulp.src('test/fixtures/test.css')
.pipe(cleanCSS(details => {
console.log('hi');
}))
.on('data', file => {
i += 1;
})
.once('end', () => {
i.should.equal(1);
done();
});
});
it('should allow empty files through', done => {
let i = 0;
gulp.src('test/fixtures/empty.css')
.pipe(cleanCSS())
.on('data', file => {
i += 1;
})
.once('end', () => {
i.should.equal(1);
done();
});
});
it('should allow the file through:empty file, pipe dest', done => {
let i = 0;
gulp.src('test/fixtures/empty/**/*.scss')
.pipe(gulpSass())
.pipe(cleanCSS())
.pipe(rename({
suffix: '.generated',
}))
.pipe(gulp.dest(file => `${file.base}/empty-parsed`))
.on('data', file => {
i += 1;
})
.once('end', () => {
i.should.equal(3);
done();
});
});
it('should produce the expected file', done => {
let mockFile = new File({
cwd: '/',
base: '/test/',
path: '/test/expected.test.css',
contents: new Buffer.from('p{text-align:center;color:green}')
});
gulp.src('test/fixtures/test.css')
.pipe(cleanCSS())
.on('data', file => {
file.contents.should.exist && expect(file.contents.toString()).to.equal(mockFile.contents.toString());
done();
});
});
it('should invoke optional callback with details specified in options: debug', done => {
gulp.src('test/fixtures/test.css')
.pipe(cleanCSS({debug: true}, (details) => {
details.stats.should.exist &&
details.stats.originalSize.should.exist &&
details.stats.minifiedSize.should.exist;
}))
.on('data', file => {
done();
});
});
it('should invoke optional callback with out options object supplied: return object hash', done => {
let called = false;
gulp.src('test/fixtures/test.css')
.pipe(cleanCSS({}, details => {
called = true;
details.stats.should.exist &&
expect(details).to.have.ownProperty('stats') &&
expect(details).to.have.ownProperty('errors') &&
expect(details).to.have.ownProperty('warnings') &&
expect(details).to.not.have.ownProperty('sourceMap');
}))
.on('data', (file) => {
//
})
.once('end', () => {
expect(called).to.be.true;
done();
})
});
it('should invoke optional callback without options object supplied: return object hash with sourceMap: true; return correct hash', done => {
gulp.src('test/fixtures/test.css')
.pipe(cleanCSS({sourceMap: true}, details => {
details.stats.should.exist &&
expect(details).have.ownProperty('sourceMap');
}))
.on('data', file => {
done();
});
});
it('should invoke optional callback with file details returned', done => {
let expected = 'test.css';
gulp.src('test/fixtures/test.css')
.pipe(cleanCSS(details => {
details.name.should.containIgnoreCase(expected)
}))
.on('data', file => {
done();
});
});
it('should write sourcemaps', done => {
let i = 0;
gulp.src(['test/fixtures/sourcemaps/**/*.css', '!test/fixtures/sourcemaps/**/*.generated.css'])
.pipe(sourcemaps.init())
.pipe(concat('sourcemapped.css'))
.pipe(cleanCSS())
.pipe(rename({
suffix: '.generated',
}))
.on('data', file => {
i += 1;
})
.pipe(sourcemaps.write())
.pipe(gulp.dest(file => file.base))
.once('end', () => {
i.should.equal(1);
done();
});
});
it('should write sourcemaps, worrectly map output', done => {
let i = 0;
gulp.src('test/fixtures/sourcemaps-load/scss/test-sass.scss')
.pipe(sourcemaps.init())
.pipe(gulpSass())
.pipe(sourcemaps.init({loadMaps: true}))
.pipe(cleanCSS({sourceMapInlineSources: true}))
.on('data', file => {
i += 1;
})
.pipe(rename({
suffix: '.min'
}))
.pipe(sourcemaps.write())
.pipe(gulp.dest('test/fixtures/sourcemaps-load/min'))
.once('end', () => {
i.should.equal(1); // todo inspect mapping here
done();
});
});
it('should invoke a plugin error: streaming not supported', done => {
gulp.src('test/fixtures/test.css', {buffer: false})
.pipe(cleanCSS()
.on('error', err => {
expect(err.message).to.equal('Streaming not supported!');
done();
}));
});
it('should handle malformed CSS', done => {
let i = 0;
gulp.src('test/fixtures/malformed.css')
.pipe(cleanCSS())
.on('error', e => {
expect(e).to.exist;
done();
})
});
it('should not process empty directories or files', done => {
gulp.src('./test/fixtures/very-empty/**')
.pipe(cleanCSS({}, detail => {
expect(detail.errors).to.be.empty;
}))
.on('data', file => {
//
})
.on('end', () => {
done();
});
})
it('should write sourcemaps, correct source path', done => {
let maps = {};
gulp.src(['test/fixtures/sourcemaps-import/styles/main.css'], {base: 'test/fixtures/sourcemaps-import/styles'})
.pipe(sourcemaps.init())
.pipe(cleanCSS())
.pipe(sourcemaps.mapSources(function (sourcePath, file) {
maps[sourcePath] = true;
return sourcePath;
}))
.pipe(sourcemaps.write('./', {sourceRoot: '/'}))
.pipe(gulp.dest('test/fixtures/sourcemaps-import'))
.once('end', () => {
maps['main.css'].should.be.true;
maps['partial.css'].should.be.true;
done();
});
});
});
describe('gulp-clean-css: rebase', () => {
it('should not rebase files by default - do not resolve relative files', done => {
gulp.src(['test/fixtures/rebasing/subdir/insub.css'])
.pipe(cleanCSS({rebase: false}))
.on('data', file => {
let expected = `
p.insub_same{background:url(insub.png)}
p.insub_child{background:url(child/child.png)}
p.insub_parent{background:url(../parent.png)}
p.insub_other{background:url(../othersub/inother.png)}
p.insub_absolute{background:url(/inroot.png)}`;
let actual = file.contents.toString();
expect(actual).to.equalIgnoreSpaces(expected)
})
.once('end', done);
});
it('should by rebase files with target specified', done => {
gulp.src(['test/fixtures/rebasing/subdir/insub.css'])
.pipe(cleanCSS({rebaseTo: 'test'}))
.on('data', file => {
let expected = `
p.insub_same{background:url(fixtures/rebasing/subdir/insub.png)}
p.insub_child{background:url(fixtures/rebasing/subdir/child/child.png)}
p.insub_parent{background:url(fixtures/rebasing/parent.png)}
p.insub_other{background:url(fixtures/rebasing/othersub/inother.png)}
p.insub_absolute{background:url(/inroot.png)}`;
let actual = file.contents.toString();
expect(actual).to.equalIgnoreSpaces(expected);
})
.once('end', done);
});
it('should rebase to current relative file location - relative imports are resolved like in the browser', done => {
gulp.src(['test/fixtures/rebasing/subdir/import.css'])
.pipe(cleanCSS())
.on('data', file => {
let expected = `
p.imported_nested{background:url(../otherdir/nestedsub/nested.png)}
p.imported_same{background:url(../otherdir/imported.png)}
p.imported_parent{background:url(../parent.png)}
p.imported_other{background:url(../othersub/inother.png)}
p.imported_absolute{background:url(/inroot.png)}
p.insub_same{background:url(insub.png)}
p.insub_child{background:url(child/child.png)}
p.insub_parent{background:url(../parent.png)}
p.insub_other{background:url(../othersub/inother.png)}
p.insub_absolute{background:url(/inroot.png)}
p.import{background:url(import.png)}`;
let actual = file.contents.toString();
expect(actual).to.equalIgnoreSpaces(expected)
})
.once('end', done);
});
});