From 5e949a3daea6817cf6fbc6eac8a8a640d8a32ea6 Mon Sep 17 00:00:00 2001 From: Adam Gruber Date: Fri, 24 Mar 2017 15:09:01 -0400 Subject: [PATCH 1/4] add/fix jsdoc comments --- .eslintrc | 3 +- bin/src/cli-main.js | 7 +++++ lib/src/main.js | 72 ++++++++++++++++++++++++--------------------- package.json | 2 +- 4 files changed, 49 insertions(+), 35 deletions(-) diff --git a/.eslintrc b/.eslintrc index 160a64e4..161537e8 100644 --- a/.eslintrc +++ b/.eslintrc @@ -62,6 +62,7 @@ "semi": [1, "always"], "global-require": 0, "import/no-unresolved": 0, - "import/no-extraneous-dependencies": 0 + "import/no-extraneous-dependencies": 0, + "valid-jsdoc": ["error", { "requireReturn": false }] } } diff --git a/bin/src/cli-main.js b/bin/src/cli-main.js index ba982fdc..09e66f53 100644 --- a/bin/src/cli-main.js +++ b/bin/src/cli-main.js @@ -18,6 +18,9 @@ const ERRORS = { /** * Validate the data file * + * @param {string} dataInFile Filename of test data + * + * @return {Object} JSON test data if valid, otherwise error object { err: message } */ function validateInFile(dataInFile) { let dataIn; @@ -52,6 +55,9 @@ function validateInFile(dataInFile) { /** * Get options to send to report generator * + * @param {Object} args Arguments passed in + * + * @return {Object} Options to pass to report generator */ function getOptions(args) { const { reportFilename, reportDir, reportTitle, reportPageTitle, @@ -71,6 +77,7 @@ function getOptions(args) { /** * Main CLI Program * + * @param {Object} processArgs CLI arguments */ function mareport(processArgs) { const args = processArgs || { _: [] }; diff --git a/lib/src/main.js b/lib/src/main.js index 372e420d..73a2d484 100644 --- a/lib/src/main.js +++ b/lib/src/main.js @@ -10,19 +10,14 @@ const distDir = path.join(__dirname, '..', 'dist'); const inlineAssetsDir = path.join(distDir, 'assets', 'inline'); const externalAssetsDir = path.join(distDir, 'assets', 'external'); -/** - * Private functions - * - */ - /** * Saves a file * - * @param {String} filename - * @param {String} data - * @returns {Promise} + * @param {string} filename Name of file to save + * @param {string} data Data to be saved + * + * @return {Promise} Resolves if file has been successfully saved */ - function saveFile(filename, data) { return new Promise((resolve, reject) => { fs.outputFile(filename, data, err => err === null ? resolve(true) : reject(err)); @@ -32,10 +27,10 @@ function saveFile(filename, data) { /** * Synchronously loads a file with utf8 encoding * - * @param {String} filename - * @returns {String} + * @param {string} filename Name of file to load + * + * @return {string} File data as string */ - function loadFile(filename) { return fs.readFileSync(filename, 'utf8'); } @@ -44,10 +39,10 @@ function loadFile(filename) { * Get report options by extending base options * with user provided options * - * @param {Object} opts - * @returns {Object} + * @param {Object} opts Report options + * + * @return {Object} User options merged with default options */ - function getOptions(opts) { const userOptions = opts || {}; const baseOptions = { @@ -72,10 +67,8 @@ function getOptions(opts) { /** * Get the report assets for inline use * - * @param {Object} opts - * @returns {Object} + * @return {Object} Object with styles and scripts as strings */ - function getAssets() { return { styles: loadFile(path.join(inlineAssetsDir, 'app.css')), @@ -94,10 +87,9 @@ function getAssets() { * - Asset version is not found -> copy assets * - Asset version differs from current version -> copy assets * - * @param {Object} opts - * @returns {Object} + * @param {Object} opts Report options + * */ - function copyAssets(opts) { const assetsDir = path.join(opts.reportDir, 'assets'); const assetsExist = fs.existsSync(assetsDir); @@ -119,13 +111,13 @@ function copyAssets(opts) { /** * Renders the main report React component * - * @param {JSON} data - * @param {Object} options - * @param {String} styles - * @param {String} scripts - * @returns {String} html + * @param {Object} data JSON test data + * @param {Object} options Report options + * @param {string} styles Inline stylesheet + * @param {string} scripts Inline script + * + * @return {string} Rendered HTML string */ - function renderHtml(data, options, styles, scripts) { return render(React.createElement(MainHTML, { data, options, styles, scripts })); } @@ -134,11 +126,11 @@ function renderHtml(data, options, styles, scripts) { /** * Prepare options, assets, and html for saving * - * @param {String} data - * @param {Object} opts - * @returns {Object} + * @param {string} reportData JSON test data + * @param {Object} opts Report options + * + * @return {Object} Prepared data for saving */ - function prepare(reportData, opts) { // Stringify the data if needed let data = reportData; @@ -168,20 +160,34 @@ function prepare(reportData, opts) { } /** - * Exposed functions + * Create the report * + * @param {string} data JSON test data + * @param {Object} opts Report options + * + * @return {Promise} Resolves if report was created successfully */ - function create(data, opts) { const { html, reportFilename, options } = prepare(data, opts); return saveFile(reportFilename, html) .then(() => { if (options.autoOpen) opener(reportFilename); }); } +/** + * Create the report synchronously + * + * @param {string} data JSON test data + * @param {Object} opts Report options + * + */ function createSync(data, opts) { const { html, reportFilename, options } = prepare(data, opts); fs.outputFileSync(reportFilename, html); if (options.autoOpen) opener(reportFilename); } +/** + * Expose create/createSync functions + * + */ module.exports = { create, createSync }; diff --git a/package.json b/package.json index be2a51cc..f8809c9c 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "version": "1.1.1", "description": "Generates gorgeous HTML reports from mochawesome reporter.", "scripts": { - "lint": "eslint bin lib src/js src/components/**/*.js src/components/**/*.jsx test/**/*.js test/**/*.jsx", + "lint": "eslint bin/src lib/src src/js src/components/**/*.js src/components/**/*.jsx test/**/*.js test/**/*.jsx", "test": "cross-env UV_THREADPOOL_SIZE=100 BABEL_DISABLE_CACHE=1 NODE_ENV=test nyc $(npm bin)/mocha --require test/helper.js \"test/spec/**/*.test.+(js|jsx)\"", "test:single": "cross-env UV_THREADPOOL_SIZE=100 BABEL_DISABLE_CACHE=1 NODE_ENV=test nyc $(npm bin)/mocha --require test/helper.js ", "compile:main": "$(npm bin)/babel ./lib/src -d lib/", From 23533d0f609dfc453e581c79c3846aea4776505a Mon Sep 17 00:00:00 2001 From: Adam Gruber Date: Fri, 24 Mar 2017 15:53:05 -0400 Subject: [PATCH 2/4] wrap file opening in a promise to ensure files are opened before report creation finishes --- lib/src/main.js | 15 ++++++++++++++- test/spec/lib/main.test.js | 11 ++++++++++- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/lib/src/main.js b/lib/src/main.js index 73a2d484..a346e8b5 100644 --- a/lib/src/main.js +++ b/lib/src/main.js @@ -24,6 +24,19 @@ function saveFile(filename, data) { }); } +/** + * Opens a file + * + * @param {string} filename Name of file to open + * + * @return {Promise} Resolves if file has been successfully opened + */ +function openFile(filename) { + return new Promise((resolve, reject) => { + opener(filename, null, err => err === null ? resolve(true) : reject(err)); + }); +} + /** * Synchronously loads a file with utf8 encoding * @@ -170,7 +183,7 @@ function prepare(reportData, opts) { function create(data, opts) { const { html, reportFilename, options } = prepare(data, opts); return saveFile(reportFilename, html) - .then(() => { if (options.autoOpen) opener(reportFilename); }); + .then(() => options.autoOpen && openFile(reportFilename)); } /** diff --git a/test/spec/lib/main.test.js b/test/spec/lib/main.test.js index c1bc89d6..343f15aa 100644 --- a/test/spec/lib/main.test.js +++ b/test/spec/lib/main.test.js @@ -50,6 +50,7 @@ afterEach(() => { copySyncStub.reset(); readFileSyncStub.reset(); existsSyncStub.reset(); + openerStub.reset(); }); describe('lib/main', () => { @@ -60,6 +61,7 @@ describe('lib/main', () => { it('runs create with autoOpen', () => { opts.autoOpen = true; + openerStub.yields(null); outputFileStub.yields(null); return mareport.create(testData, opts).then(() => { expect(openerStub.called).to.equal(true); @@ -71,6 +73,13 @@ describe('lib/main', () => { return expect(mareport.create(testData, opts)).to.be.rejectedWith('save error'); }); + it('runs create with autoOpen and throws', () => { + opts.autoOpen = true; + openerStub.yields('open error'); + outputFileStub.yields(null); + return expect(mareport.create(testData, opts)).to.be.rejectedWith('open error'); + }); + it('runs createSync', () => { mareport.createSync(testData, opts); expect(outputFileSyncStub.calledWith('mochawesome-report/test.html')).to.equal(true); @@ -86,7 +95,7 @@ describe('lib/main', () => { expect(outputFileSyncStub.calledWith('mochawesome-report/mochawesome.html')).to.equal(true); }); - it('runs create with autoOpen', () => { + it('runs createSync with autoOpen', () => { opts.autoOpen = true; outputFileStub.yields(null); mareport.createSync(testData, opts); From b24c48df4374a6b22cb0a1a5a23f1839639963a6 Mon Sep 17 00:00:00 2001 From: Adam Gruber Date: Fri, 24 Mar 2017 15:53:30 -0400 Subject: [PATCH 3/4] add autoOpen as a cli option --- bin/src/cli-main.js | 3 ++- bin/src/cli.js | 6 ++++++ test/spec/cli/cli-main.test.js | 1 + 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/bin/src/cli-main.js b/bin/src/cli-main.js index 09e66f53..8538ea03 100644 --- a/bin/src/cli-main.js +++ b/bin/src/cli-main.js @@ -61,7 +61,7 @@ function validateInFile(dataInFile) { */ function getOptions(args) { const { reportFilename, reportDir, reportTitle, reportPageTitle, - inlineAssets, enableCharts, enableCode, dev } = args; + inlineAssets, enableCharts, enableCode, autoOpen, dev } = args; const filename = `${reportFilename.replace(fileExtRegex, '')}.html`; return { reportHtmlFile: path.join(reportDir, filename), @@ -70,6 +70,7 @@ function getOptions(args) { inlineAssets, enableCharts, enableCode, + autoOpen, dev }; } diff --git a/bin/src/cli.js b/bin/src/cli.js index 9a63f326..b49750a8 100755 --- a/bin/src/cli.js +++ b/bin/src/cli.js @@ -15,6 +15,7 @@ const mareport = require('./cli-main'); * @property {boolean} inlineAssets Should assets be inlined into HTML file (default: false) * @property {boolean} charts Should charts be enabled (default: true) * @property {boolean} code Should test code output be enabled (default: true) + * @property {boolean} autoOpen Open the report after creation (default: false) * @property {boolean} dev Enable dev mode in the report, * asssets loaded via webpack (default: false) */ @@ -70,6 +71,11 @@ yargs describe: 'Display test code', boolean: true }, + autoOpen: { + default: false, + describe: 'Automatically open the report HTML', + boolean: true + }, dev: { default: false, describe: 'Enable dev mode', diff --git a/test/spec/cli/cli-main.test.js b/test/spec/cli/cli-main.test.js index 6c745c6c..4338fb93 100644 --- a/test/spec/cli/cli-main.test.js +++ b/test/spec/cli/cli-main.test.js @@ -20,6 +20,7 @@ const sharedOpts = { inlineAssets: false, enableCharts: true, enableCode: true, + autoOpen: false, dev: true }; From 110995e578084d26a8cca699494d03a98cf9218c Mon Sep 17 00:00:00 2001 From: Adam Gruber Date: Fri, 24 Mar 2017 16:22:34 -0400 Subject: [PATCH 4/4] fix broken test --- test/spec/lib/main.test.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/test/spec/lib/main.test.js b/test/spec/lib/main.test.js index 343f15aa..6a234b94 100644 --- a/test/spec/lib/main.test.js +++ b/test/spec/lib/main.test.js @@ -44,13 +44,15 @@ beforeEach(() => { opts = Object.assign({}, baseOpts); }); -afterEach(() => { +beforeEach(() => { outputFileStub.reset(); + outputFileStub.resetBehavior(); outputFileSyncStub.reset(); copySyncStub.reset(); readFileSyncStub.reset(); existsSyncStub.reset(); openerStub.reset(); + openerStub.resetBehavior(); }); describe('lib/main', () => { @@ -97,7 +99,6 @@ describe('lib/main', () => { it('runs createSync with autoOpen', () => { opts.autoOpen = true; - outputFileStub.yields(null); mareport.createSync(testData, opts); expect(openerStub.called).to.equal(true); });