Fix CSS tests (#839)

* Fix CSS tests

* Revamp

* -

* fix failing test

* add test for minifyCss with fixtures & snapshot

* remove unintended addition

* simplify the test.css
This commit is contained in:
Yangshun Tay 2018-07-10 10:42:32 -07:00 committed by GitHub
parent 8cd4b4fca6
commit 4267337fb0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 178 additions and 88 deletions

View file

@ -3,6 +3,10 @@
"test": { "test": {
"presets": [ "presets": [
"env" "env"
],
"plugins": [
"transform-class-properties",
"transform-object-rest-spread"
] ]
} }
} }

View file

@ -5,7 +5,6 @@
* LICENSE file in the root directory of this source tree. * LICENSE file in the root directory of this source tree.
*/ */
const cssnano = require('cssnano');
const filepath = require('filepath'); const filepath = require('filepath');
const fm = require('front-matter'); const fm = require('front-matter');
const fs = require('fs-extra'); const fs = require('fs-extra');
@ -15,6 +14,7 @@ const shell = require('shelljs');
const CWD = process.cwd(); const CWD = process.cwd();
const utils = require('../server/utils');
const siteConfig = require(CWD + '/website/siteConfig.js'); const siteConfig = require(CWD + '/website/siteConfig.js');
const buildDir = CWD + '/website/build'; const buildDir = CWD + '/website/build';
const docsDir = CWD + '/docs'; const docsDir = CWD + '/docs';
@ -34,82 +34,85 @@ function clearBuildFolder() {
return rimraf(buildDir); return rimraf(buildDir);
} }
beforeEach(() => { describe('Build files', () => {
shell.cd(CWD); beforeEach(() => {
}); shell.cd(CWD);
beforeAll(() => {
generateSite();
return Promise.all([
glob(docsDir + '/**/*.md'),
glob(buildDir + '/' + siteConfig.projectName + '/docs/**/*.html'),
glob(docsDir + '/assets/*'),
glob(buildDir + '/' + siteConfig.projectName + '/img/*'),
]).then(function(results) {
[
inputMarkdownFiles,
outputHTMLFiles,
inputAssetsFiles,
outputAssetsFiles,
] = results;
}); });
});
afterAll(() => { beforeAll(() => {
clearBuildFolder(); generateSite();
}); return Promise.all([
glob(docsDir + '/**/*.md'),
test('Build folder exists', function() { glob(buildDir + '/' + siteConfig.projectName + '/docs/**/*.html'),
return fs.stat(buildDir).then(function(status) { glob(docsDir + '/assets/*'),
expect(status.isDirectory()).toBeTruthy(); glob(buildDir + '/' + siteConfig.projectName + '/img/*'),
]).then(function(results) {
[
inputMarkdownFiles,
outputHTMLFiles,
inputAssetsFiles,
outputAssetsFiles,
] = results;
});
}); });
});
test('Generated HTML for each Markdown resource', function() { afterAll(() => {
let metadata = []; clearBuildFolder();
outputHTMLFiles.forEach(function(file) {
const path = filepath.create(file);
metadata.push(path.basename());
}); });
inputMarkdownFiles.forEach(function(file) {
const data = fs.readFileSync(file, 'utf8');
const frontmatter = fm(data);
expect(metadata).toContain(frontmatter.attributes.id + '.html');
});
});
test('Generated table of contents', function() { test('Build folder exists', function() {
outputHTMLFiles.forEach(function(file) { return fs.stat(buildDir).then(function(status) {
const fileContents = fs.readFileSync(file, 'utf8'); expect(status.isDirectory()).toBeTruthy();
expect(fileContents).not.toContain('<AUTOGENERATED_TABLE_OF_CONTENTS>'); });
}); });
});
test('Concatenated CSS files', function() { test('Generated HTML for each Markdown resource', function() {
return Promise.all([ let metadata = [];
glob(staticCSSDir + '/*.css'), outputHTMLFiles.forEach(function(file) {
fs.readFile( const path = filepath.create(file);
buildDir + '/' + siteConfig.projectName + '/css/main.css', metadata.push(path.basename());
'utf8' });
), inputMarkdownFiles.forEach(function(file) {
]).then(function(results) { const data = fs.readFileSync(file, 'utf8');
const [inputFiles, outputFile] = results; const frontmatter = fm(data);
inputFiles.forEach(async function(file) { expect(metadata).toContain(frontmatter.attributes.id + '.html');
const contents = fs.readFileSync(file, 'utf8'); });
const {css} = await cssnano.process(contents, {}, {preset: 'default'}); });
expect(outputFile).toContain(css);
test('Generated table of contents', function() {
outputHTMLFiles.forEach(function(file) {
const fileContents = fs.readFileSync(file, 'utf8');
expect(fileContents).not.toContain('<AUTOGENERATED_TABLE_OF_CONTENTS>');
});
});
test('Concatenated CSS files', async function() {
const inputFiles = await glob(staticCSSDir + '/*.css');
const combinedCSSFile =
buildDir + '/' + siteConfig.projectName + '/css/main.css';
const fileContents = await Promise.all(
[combinedCSSFile, ...inputFiles].map(file => fs.readFile(file, 'utf8'))
);
const [outputFileContent, ...inputFileContents] = fileContents;
const minifiedCssFiles = await Promise.all(
inputFileContents.map(utils.minifyCss)
);
minifiedCssFiles.forEach(fileContent => {
expect(outputFileContent).toContain(fileContent);
});
});
test('Copied assets from /docs/assets', function() {
let metadata = [];
outputAssetsFiles.forEach(function(file) {
const path = filepath.create(file);
metadata.push(path.basename());
});
inputAssetsFiles.forEach(function(file) {
const path = filepath.create(file);
expect(metadata).toContain(path.basename());
}); });
}); });
}); });
test('Copied assets from /docs/assets', function() {
let metadata = [];
outputAssetsFiles.forEach(function(file) {
const path = filepath.create(file);
metadata.push(path.basename());
});
inputAssetsFiles.forEach(function(file) {
const path = filepath.create(file);
expect(metadata).toContain(path.basename());
});
});

View file

@ -0,0 +1,21 @@
/**
* Copyright (c) 2017-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
.hljs {
margin-left: -15px;
margin-right: -15px;
border: 1px solid #eee;
border-radius: 6px;
padding: 15px;
font-size: 15px;
max-width: 50rem;
}
.hljs.javascript {
background-color: rgba(247, 223, 30, 0.03);
}
.hljs .comment {
opacity: 0.7;
}

View file

@ -0,0 +1,26 @@
---
title: This is not a css
---
This is a markdown, not a css
.homeWrapperInner .homeCodeSnippet > div:nth-child(1) {
display: none;
}
@media (max-width: 480px) {
.projectTitle {
font-size: 30px;
}
.homeCodeSnippet .hljs {
font-size: 13px;
padding: 0;
}
.homeWrapperInner .homeCodeSnippet > div:nth-child(1) {
display: block;
}
.homeWrapperInner .homeCodeSnippet > div:nth-child(2) {
display: none;
}
}

View file

@ -0,0 +1,5 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`server utils minify css 1`] = `".hljs{margin-left:-15px;margin-right:-15px;border:1px solid #eee;border-radius:6px;padding:15px;font-size:15px;max-width:50rem}.hljs.javascript{background-color:rgba(247,223,30,.03)}.hljs .comment{opacity:.7}"`;
exports[`server utils minify css 2`] = `[Error: Unexpected "space" found.]`;

View file

@ -0,0 +1,24 @@
/**
* Copyright (c) 2017-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
const path = require('path');
const fs = require('fs');
const utils = require('../utils');
describe('server utils', () => {
test('minify css', () => {
const testCss = fs.readFileSync(
path.join(__dirname, '__fixtures__', 'test.css'),
'utf8'
);
const notCss = fs.readFileSync(
path.join(__dirname, '__fixtures__', 'test.md'),
'utf8'
);
utils.minifyCss(testCss).then(css => expect(css).toMatchSnapshot());
utils.minifyCss(notCss).catch(e => expect(e).toMatchSnapshot());
});
});

View file

@ -11,12 +11,12 @@ async function execute() {
const metadataUtils = require('./metadataUtils'); const metadataUtils = require('./metadataUtils');
const CWD = process.cwd(); const CWD = process.cwd();
const cssnano = require('cssnano');
const fs = require('fs-extra'); const fs = require('fs-extra');
const readMetadata = require('./readMetadata.js'); const readMetadata = require('./readMetadata.js');
const path = require('path'); const path = require('path');
const getTOC = require('../core/getTOC.js'); const getTOC = require('../core/getTOC');
const utils = require('../core/utils.js'); const utils = require('../core/utils.js');
const serverUtils = require('./utils');
const React = require('react'); const React = require('react');
const mkdirp = require('mkdirp'); const mkdirp = require('mkdirp');
const glob = require('glob'); const glob = require('glob');
@ -445,13 +445,7 @@ async function execute() {
// Use cssnano to minify the final combined CSS. // Use cssnano to minify the final combined CSS.
const mainCss = join(buildDir, 'css', 'main.css'); const mainCss = join(buildDir, 'css', 'main.css');
const cssContent = fs.readFileSync(mainCss, 'utf8'); const cssContent = fs.readFileSync(mainCss, 'utf8');
const {css} = await cssnano.process( const css = await serverUtils.minifyCss(cssContent);
cssContent,
/* postcssOpts */ {},
/* cssnanoOpts */ {
preset: 'default',
}
);
fs.writeFileSync(mainCss, css); fs.writeFileSync(mainCss, css);
// compile/copy pages from user // compile/copy pages from user

View file

@ -4,9 +4,10 @@
* This source code is licensed under the MIT license found in the * This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree. * LICENSE file in the root directory of this source tree.
*/ */
const cssnano = require('cssnano');
const path = require('path'); const path = require('path');
const escapeStringRegexp = require('escape-string-regexp'); const escapeStringRegexp = require('escape-string-regexp');
const env = require('./env.js');
// Return the subdirectory path from a reference directory // Return the subdirectory path from a reference directory
// Example: // Example:
@ -29,6 +30,7 @@ function getLanguage(file, refDir) {
const match = regexSubFolder.exec(file); const match = regexSubFolder.exec(file);
// Avoid misinterpreting subdirectory as language // Avoid misinterpreting subdirectory as language
const env = require('./env.js');
if (match && env.translation.enabled) { if (match && env.translation.enabled) {
const enabledLanguages = env.translation const enabledLanguages = env.translation
.enabledLanguages() .enabledLanguages()
@ -40,7 +42,17 @@ function getLanguage(file, refDir) {
return null; return null;
} }
function minifyCss(cssContent) {
return cssnano
.process(cssContent, {
preset: 'default',
zindex: false,
})
.then(result => result.css);
}
module.exports = { module.exports = {
getSubDir, getSubDir,
getLanguage, getLanguage,
minifyCss,
}; };

View file

@ -3,7 +3,12 @@
"description": "Easy to Maintain Open Source Documentation Websites", "description": "Easy to Maintain Open Source Documentation Websites",
"version": "1.3.2", "version": "1.3.2",
"license": "MIT", "license": "MIT",
"keywords": ["documentation", "websites", "open source", "docusaurus"], "keywords": [
"documentation",
"websites",
"open source",
"docusaurus"
],
"repository": { "repository": {
"type": "git", "type": "git",
"url": "https://github.com/facebook/Docusaurus.git" "url": "https://github.com/facebook/Docusaurus.git"
@ -11,14 +16,10 @@
"scripts": { "scripts": {
"ci-check": "yarn lint && yarn prettier:diff", "ci-check": "yarn lint && yarn prettier:diff",
"format:source": "prettier --config .prettierrc --write \"lib/**/*.js\"", "format:source": "prettier --config .prettierrc --write \"lib/**/*.js\"",
"format:examples": "format:examples": "prettier --config .prettierrc --write \"examples/**/*.js\"",
"prettier --config .prettierrc --write \"examples/**/*.js\"", "lint": "eslint --cache \"lib/**/*.js\" \"examples/**/*.js\" \"website/**/*.js\"",
"lint": "nit:source": "prettier --config .prettierrc --list-different \"lib/**/*.js\"",
"eslint --cache \"lib/**/*.js\" \"examples/**/*.js\" \"website/**/*.js\"", "nit:examples": "prettier --config .prettierrc --list-different \"examples/**/*.js\"",
"nit:source":
"prettier --config .prettierrc --list-different \"lib/**/*.js\"",
"nit:examples":
"prettier --config .prettierrc --list-different \"examples/**/*.js\"",
"precommit": "lint-staged", "precommit": "lint-staged",
"prettier": "yarn format:source && yarn format:examples", "prettier": "yarn format:source && yarn format:examples",
"prettier:diff": "yarn nit:source && yarn nit:examples", "prettier:diff": "yarn nit:source && yarn nit:examples",