From b476cbb8b58ecbb40968f118501a248a2f1e7bcd Mon Sep 17 00:00:00 2001 From: Udit Vasu Date: Mon, 25 Jun 2018 16:47:45 +0530 Subject: [PATCH 1/6] Initial Setup - Add HTML Reporter from `newman` - Initial Repository Setup --- .editorconfig | 14 ++ .eslintrc | 361 +++++++++++++++++++++++++++++++ .gitignore | 38 ++++ .jsdoc-config.json | 34 +++ .npmignore | 38 ++++ CHANGELOG.yaml | 1 + LICENSE.md | 203 +++++++++++++++++ README.md | 1 + index.js | 14 ++ lib/index.js | 186 ++++++++++++++++ lib/template-default.hbs | 160 ++++++++++++++ lib/util.js | 56 +++++ npm/test-lint.js | 57 +++++ npm/test-system.js | 74 +++++++ npm/test.js | 15 ++ package.json | 60 +++++ test/.eslintrc | 30 +++ test/system/editorconfig.test.js | 40 ++++ test/system/jsdoc-config.test.js | 98 +++++++++ test/system/repository.test.js | 217 +++++++++++++++++++ 20 files changed, 1697 insertions(+) create mode 100644 .editorconfig create mode 100644 .eslintrc create mode 100644 .gitignore create mode 100644 .jsdoc-config.json create mode 100644 .npmignore create mode 100644 CHANGELOG.yaml create mode 100644 LICENSE.md create mode 100644 README.md create mode 100644 index.js create mode 100644 lib/index.js create mode 100644 lib/template-default.hbs create mode 100644 lib/util.js create mode 100755 npm/test-lint.js create mode 100755 npm/test-system.js create mode 100755 npm/test.js create mode 100644 package.json create mode 100644 test/.eslintrc create mode 100644 test/system/editorconfig.test.js create mode 100644 test/system/jsdoc-config.test.js create mode 100644 test/system/repository.test.js diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..303be14 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,14 @@ +# editorconfig.org +root = true + +[*] +indent_style = space +indent_size = 4 +end_of_line = lf +charset = utf-8 +max_length = 120 +trim_trailing_whitespace = true +insert_final_newline = true + +[*.{json, yml, html, hbs}] +indent_size = 2 diff --git a/.eslintrc b/.eslintrc new file mode 100644 index 0000000..8e4d1dd --- /dev/null +++ b/.eslintrc @@ -0,0 +1,361 @@ +{ + "plugins": [ + "jsdoc", + "security", + "lodash", + "mocha" + ], + "env": { + "node": true, + "es6": true + }, + "rules": { + // Possible Errors + "for-direction": "error", + "getter-return": "error", + "no-await-in-loop": "error", + "no-compare-neg-zero": "error", + "no-cond-assign": "error", + "no-console": ["error", { "allow": ["info", "warn", "error"] }], + "no-constant-condition": "error", + "no-control-regex": "error", + "no-debugger": "error", + "no-dupe-args": "error", + "no-dupe-keys": "error", + "no-duplicate-case": "error", + "no-empty": "error", + "no-empty-character-class": "error", + "no-ex-assign": "error", + "no-extra-boolean-cast": "error", + "no-extra-parens": "off", + "no-extra-semi": "error", + "no-func-assign": "error", + "no-inner-declarations": "off", + "no-invalid-regexp": "error", + "no-irregular-whitespace": "error", + "no-obj-calls": "error", + "no-prototype-builtins": "error", + "no-regex-spaces": "error", + "no-sparse-arrays": "error", + "no-template-curly-in-string": "error", + "no-unexpected-multiline": "error", + "no-unreachable": "error", + "no-unsafe-finally": "error", + "no-unsafe-negation": "error", + "use-isnan": "error", + "valid-jsdoc": "off", + "valid-typeof": "error", + + // Best Practices + "accessor-pairs": "error", + "array-callback-return": "error", + "block-scoped-var": "error", + "class-methods-use-this": "error", + "complexity": "off", + "consistent-return": "warn", + "curly": "error", + "default-case": "error", + "dot-location": ["error", "property"], + "dot-notation": "error", + "eqeqeq": "error", + "guard-for-in": "warn", + "no-alert": "error", + "no-caller": "error", + "no-case-declarations": "error", + "no-div-regex": "error", + "no-else-return": "error", + "no-empty-function": "error", + "no-empty-pattern": "error", + "no-eq-null": "error", + "no-eval": "error", + "no-extend-native": "error", + "no-extra-bind": "error", + "no-extra-label": "error", + "no-fallthrough": "error", + "no-floating-decimal": "error", + "no-global-assign": "error", + "no-implicit-coercion": "error", + "no-implicit-globals": "error", + "no-implied-eval": "error", + "no-invalid-this": "error", + "no-iterator": "error", + "no-labels": "error", + "no-lone-blocks": "error", + "no-loop-func": "error", + "no-magic-numbers": "off", + "no-multi-spaces": "error", + "no-multi-str": "error", + "no-new": "error", + "no-new-func": "error", + "no-new-wrappers": "error", + "no-octal": "error", + "no-octal-escape": "error", + "no-param-reassign": "off", + "no-proto": "error", + "no-redeclare": "error", + "no-restricted-properties": "error", + "no-return-assign": "error", + "no-return-await": "error", + "no-script-url": "error", + "no-self-assign": "error", + "no-self-compare": "error", + "no-sequences": "error", + "no-throw-literal": "error", + "no-unmodified-loop-condition": "error", + "no-unused-expressions": "off", + "no-unused-labels": "error", + "no-useless-call": "error", + "no-useless-concat": "error", + "no-useless-escape": "error", + "no-useless-return": "error", + "no-void": "error", + "no-warning-comments": "off", + "no-with": "error", + "prefer-promise-reject-errors": "error", + "radix": "off", + "require-await": "error", + "vars-on-top": "off", + "wrap-iife": "error", + "yoda": "error", + + // Strict Mode + "strict": "off", + + // Variables + "init-declarations": "off", + "no-catch-shadow": "error", + "no-delete-var": "error", + "no-label-var": "error", + "no-restricted-globals": "error", + "no-shadow": "off", + "no-shadow-restricted-names": "error", + "no-undef": "off", + "no-undef-init": "error", + "no-undefined": "off", + "no-unused-vars": "error", + "no-use-before-define": "error", + + // Node.js and CommonJS + "callback-return": "error", + "global-require": "off", + "handle-callback-err": "error", + "no-buffer-constructor": "error", + "no-mixed-requires": "off", + "no-new-require": "off", + "no-path-concat": "error", + "no-process-env": "error", + "no-process-exit": "off", + "no-restricted-modules": "error", + "no-sync": "off", + + // Stylistic Issues + "array-bracket-newline": "off", + "array-bracket-spacing": "error", + "array-element-newline": "off", + "block-spacing": "error", + "brace-style": [2, "stroustrup", { "allowSingleLine": true }], + "camelcase": "off", + "capitalized-comments": "off", + "comma-dangle": ["error", "never"], + "comma-spacing": [2, { "before": false, "after": true }], + "comma-style": ["error", "last"], + "computed-property-spacing": "error", + "consistent-this": "off", + "eol-last": "error", + "func-call-spacing": "error", + "func-name-matching": "error", + "func-names": "off", + "func-style": "off", + "id-blacklist": "error", + "id-length": "off", + "id-match": "error", + "indent": ["error", 4, { + "VariableDeclarator": { "var": 1, "let": 1, "const": 1 }, + "SwitchCase": 1 + }], + "jsx-quotes": ["error", "prefer-single"], + "key-spacing": "error", + "keyword-spacing": "error", + "line-comment-position": "off", + "linebreak-style": ["error", "unix"], + "lines-around-comment": ["error", { + "beforeBlockComment": true, + "afterBlockComment": false, + "beforeLineComment": false, + "afterLineComment": false, + "allowBlockStart": true, + "allowBlockEnd": false, + "allowObjectStart": true, + "allowObjectEnd": false, + "allowArrayStart": true, + "allowArrayEnd": false + }], + "max-depth": "error", + "max-len": ["error", { + "code": 120 + }], + "max-lines": "off", + "max-nested-callbacks": "error", + "max-params": "off", + "max-statements": "off", + "max-statements-per-line": "off", + "multiline-ternary": "off", + "new-cap": "off", + "new-parens": "error", + "newline-per-chained-call": "off", + "no-array-constructor": "error", + "no-bitwise": "off", + "no-continue": "off", + "no-inline-comments": "off", + "no-lonely-if": "error", + "no-mixed-operators": "off", + "no-mixed-spaces-and-tabs": "error", + "no-multi-assign": "off", + "no-multiple-empty-lines": "error", + "no-negated-condition": "off", + "no-nested-ternary": "off", + "no-new-object": "error", + "no-plusplus": "off", + "no-restricted-syntax": "error", + "no-tabs": "error", + "no-ternary": "off", + "no-trailing-spaces": "error", + "no-underscore-dangle": "off", + "no-unneeded-ternary": "error", + "no-whitespace-before-property": "error", + "nonblock-statement-body-position": "error", + "object-curly-newline": "off", + "object-curly-spacing": ["error", "always"], + "object-property-newline": "off", + "one-var": ["error", "always"], + "one-var-declaration-per-line": "error", + "operator-assignment": "error", + "operator-linebreak": ["error", "after"], + "padded-blocks": "off", + "padding-line-between-statements": "off", + "quote-props": "off", + "quotes": ["error", "single"], + "require-jsdoc": "warn", + "semi": "error", + "semi-spacing": "error", + "sort-keys": "off", + "sort-vars": "off", + "space-before-blocks": "error", + "space-before-function-paren": "error", + "space-in-parens": "error", + "space-infix-ops": "error", + "space-unary-ops": "error", + "spaced-comment": ["error", "always", { + "block": { + "exceptions": ["!"] + } + }], + "switch-colon-spacing": "error", + "template-tag-spacing": "error", + "unicode-bom": "error", + "wrap-regex": "error", + + // ECMAScript 6 + "arrow-body-style": ["error", "always"], + "arrow-parens": ["error", "always"], + "arrow-spacing": "error", + "constructor-super": "error", + "generator-star-spacing": "error", + "no-class-assign": "error", + "no-confusing-arrow": "error", + "no-const-assign": "error", + "no-dupe-class-members": "error", + "no-duplicate-imports": "error", + "no-new-symbol": "error", + "no-restricted-imports": "error", + "no-this-before-super": "error", + "no-useless-computed-key": "error", + "no-useless-constructor": "off", + "no-var": "off", + "object-shorthand": "off", + "prefer-arrow-callback": "off", + "prefer-const": "off", + "prefer-destructuring": "off", + "prefer-numeric-literals": "off", + "prefer-rest-params": "off", + "prefer-spread": "error", + "prefer-template": "off", + "require-yield": "error", + "rest-spread-spacing": "error", + "sort-imports": "off", + "symbol-description": "off", + "template-curly-spacing": "error", + "yield-star-spacing": "error", + + // Lodash + "lodash/callback-binding": "error", + "lodash/collection-method-value": "warn", + "lodash/collection-return": "error", + "lodash/no-double-unwrap": "error", + "lodash/no-extra-args": "error", + "lodash/no-unbound-this": "error", + "lodash/unwrap": "error", + + "lodash/chain-style": ["error", "as-needed"], + "lodash/chaining": ["error", "always", 3], + "lodash/consistent-compose": ["error", "flow"], + "lodash/identity-shorthand": ["error", "always"], + "lodash/import-scope": "off", + "lodash/matches-prop-shorthand": ["error", "always"], + "lodash/matches-shorthand": ["error", "always", 3], + "lodash/no-commit": "error", + "lodash/path-style": ["error", "string"], + "lodash/prefer-compact": "error", + "lodash/prefer-filter": ["off", 3], + "lodash/prefer-flat-map": "error", + "lodash/prefer-invoke-map": "error", + "lodash/prefer-map": "error", + "lodash/prefer-reject": ["error", 3], + "lodash/prefer-thru": "error", + "lodash/prefer-wrapper-method": "error", + "lodash/preferred-alias": "error", + "lodash/prop-shorthand": ["error", "always"], + + "lodash/prefer-constant": "off", + "lodash/prefer-get": ["warn", 4], + "lodash/prefer-includes": ["error", { "includeNative": true }], + "lodash/prefer-is-nil": "error", + "lodash/prefer-lodash-chain": "error", + "lodash/prefer-lodash-method": "off", + "lodash/prefer-lodash-typecheck": "off", + "lodash/prefer-matches": ["off", 3], + "lodash/prefer-noop": "off", + "lodash/prefer-over-quantifier": "warn", + "lodash/prefer-some": "off", + "lodash/prefer-startswith": "off", + "lodash/prefer-times": "off", + + // JsDoc + "jsdoc/check-param-names": "error", + "jsdoc/check-tag-names": "off", + "jsdoc/check-types": "off", + "jsdoc/newline-after-description": "error", + "jsdoc/require-description-complete-sentence": "off", + "jsdoc/require-example": "off", + "jsdoc/require-hyphen-before-param-description": "off", + "jsdoc/require-param": "warn", + "jsdoc/require-param-description": "error", + "jsdoc/require-param-type": "error", + "jsdoc/require-returns-description": "off", + "jsdoc/require-returns-type": "error", + + // Security + "security/detect-unsafe-regex": "off", + "security/detect-buffer-noassert": "error", + "security/detect-child-process": "error", + "security/detect-disable-mustache-escape": "error", + "security/detect-eval-with-expression": "error", + "security/detect-no-csrf-before-method-override": "off", + "security/detect-non-literal-fs-filename": "off", + "security/detect-non-literal-regexp": "warn", + "security/detect-non-literal-require": "off", + "security/detect-object-injection": "off", + "security/detect-possible-timing-attacks": "error", + "security/detect-pseudoRandomBytes": "error" + } +} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5854b37 --- /dev/null +++ b/.gitignore @@ -0,0 +1,38 @@ +# PLATFORM +# ======== +# All exclusions that are specific to the NPM, GIT, IDE and Operating Systems. + +# - Do not allow installed node modules to be committed. Doing `npm install -d` will bring them in root or other places. +node_modules + +# - Do not commit any log file from anywhere +*.log +*.log.* + +# - Prevent addition of OS specific file explorer files +Thumbs.db +.DS_Store + +# Prevent IDE stuff +.idea +.vscode + +# PROJECT +# ======= +# Configuration pertaining to project specific repository structure. + +# - Prevent Sublime text IDE files from being commited to repository +*.sublime-* + +# - Allow sublime text project file to be commited in the development directory. +!/develop/*.sublime-project + +# - Prevent diff backups from SourceTree from showing as commit. +*.BACKUP.* +*.BASE.* +*.LOCAL.* +*.REMOTE.* +*.orig + +# Prevent unit test coverage reports from being added +.coverage diff --git a/.jsdoc-config.json b/.jsdoc-config.json new file mode 100644 index 0000000..90e6d5d --- /dev/null +++ b/.jsdoc-config.json @@ -0,0 +1,34 @@ +{ + "tags": { + "allowUnknownTags": true, + "dictionaries": ["jsdoc", "closure"] + }, + "source": { + "include": [ ], + "includePattern": ".+\\.js(doc)?$", + "excludePattern": "(^|\\/|\\\\)_" + }, + + "plugins": [ + "plugins/markdown" + ], + + "templates": { + "cleverLinks": false, + "monospaceLinks": false, + "highlightTutorialCode" : true + }, + + "opts": { + "template": "./node_modules/postman-jsdoc-theme", + "encoding": "utf8", + "destination": "./out/docs", + "recurse": true, + "readme": "README.md" + }, + + "markdown": { + "parser": "gfm", + "hardwrap": false + } +} diff --git a/.npmignore b/.npmignore new file mode 100644 index 0000000..5854b37 --- /dev/null +++ b/.npmignore @@ -0,0 +1,38 @@ +# PLATFORM +# ======== +# All exclusions that are specific to the NPM, GIT, IDE and Operating Systems. + +# - Do not allow installed node modules to be committed. Doing `npm install -d` will bring them in root or other places. +node_modules + +# - Do not commit any log file from anywhere +*.log +*.log.* + +# - Prevent addition of OS specific file explorer files +Thumbs.db +.DS_Store + +# Prevent IDE stuff +.idea +.vscode + +# PROJECT +# ======= +# Configuration pertaining to project specific repository structure. + +# - Prevent Sublime text IDE files from being commited to repository +*.sublime-* + +# - Allow sublime text project file to be commited in the development directory. +!/develop/*.sublime-project + +# - Prevent diff backups from SourceTree from showing as commit. +*.BACKUP.* +*.BASE.* +*.LOCAL.* +*.REMOTE.* +*.orig + +# Prevent unit test coverage reports from being added +.coverage diff --git a/CHANGELOG.yaml b/CHANGELOG.yaml new file mode 100644 index 0000000..f7d7c67 --- /dev/null +++ b/CHANGELOG.yaml @@ -0,0 +1 @@ +# Newman HTML Reporter Changelog diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 0000000..632c64b --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,203 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2016 Postdot Technologies, Inc + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + diff --git a/README.md b/README.md new file mode 100644 index 0000000..6e4ed37 --- /dev/null +++ b/README.md @@ -0,0 +1 @@ +# newman-reporter-html \ No newline at end of file diff --git a/index.js b/index.js new file mode 100644 index 0000000..2c10fca --- /dev/null +++ b/index.js @@ -0,0 +1,14 @@ +/**! + * @license Copyright 2018 Postdot Technologies, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and limitations under the License. + */ +module.exports = require('./lib'); diff --git a/lib/index.js b/lib/index.js new file mode 100644 index 0000000..75e8038 --- /dev/null +++ b/lib/index.js @@ -0,0 +1,186 @@ +var fs = require('fs'), + path = require('path'), + + _ = require('lodash'), + handlebars = require('handlebars'), + + util = require('./util'), + + /** + * An object of the default file read preferences. + * + * @type {Object} + */ + FILE_READ_OPTIONS = { encoding: 'utf8' }, + + /** + * The default Handlebars template to use when no user specified template is provided. + * + * @type {String} + */ + DEFAULT_TEMPLATE = 'template-default.hbs', + + /** + * A reference object for run stats properties to use for various assertion states. + * + * @type {Object} + */ + ASSERTION_STATE = { false: 'passed', true: 'failed' }, + + /** + * The list of execution data fields that are aggregated over multiple requests for the collection run + * + * @type {String[]} + */ + AGGREGATED_FIELDS = ['item', 'request', 'response'], + + IS_NODE_V4 = _(process && process.version).split('.').get(0) === 'v4', + + PostmanHTMLReporter; + +/** + * A function that creates raw markup to be written to Newman HTML reports. + * + * @param {Object} newman - The collection run object, with a event handler setter, used to enable event wise reporting. + * @param {Object} options - The set of HTML reporter run options. + * @param {String=} options.template - Optional path to the custom user defined HTML report template (Handlebars). + * @param {String=} options.export - Optional custom path to create the HTML report at. + * @returns {*} + */ +PostmanHTMLReporter = function (newman, options) { + handlebars.registerHelper('add', function (addend, augend) { + return addend + augend; + }); + handlebars.registerHelper('gt', function (value, threshold, options) { + return value > threshold ? options.fn(this) : options.inverse(this); + }); + + // @todo throw error here or simply don't catch them and it will show up as warning on newman + var htmlTemplate = options.template || path.join(__dirname, DEFAULT_TEMPLATE), + compiler = handlebars.compile(fs.readFileSync(htmlTemplate, FILE_READ_OPTIONS)); + + newman.on('beforeDone', function () { + var items = {}, + executionMeans = {}, + netTestCounts = {}, + aggregations = [], + traversedRequests = {}, + aggregatedExecutions = {}, + executions = _.get(this, 'summary.run.executions'), + assertions = _.transform(executions, function (result, currentExecution) { + var stream, + reducedExecution, + executionId = currentExecution.id; + + if (!_.has(traversedRequests, executionId)) { + // mark the current request instance as traversed + _.set(traversedRequests, executionId, 1); + + // set the base assertion and cumulative test details for the current request instance + _.set(result, executionId, {}); + _.set(netTestCounts, executionId, { passed: 0, failed: 0 }); + + // set base values for overall response size and time values + _.set(executionMeans, executionId, { time: { sum: 0, count: 0 }, size: { sum: 0, count: 0 } }); + + reducedExecution = _.pick(currentExecution, AGGREGATED_FIELDS); + + if (reducedExecution.response && _.isFunction(reducedExecution.response.toJSON)) { + reducedExecution.response = reducedExecution.response.toJSON(); + stream = reducedExecution.response.stream; + + // Use deprecated Buffer constructor for Node v4, contemporary one for other versions + // @todo remove when dropping support for node < v6, to save some memory. + // eslint-disable-next-line no-buffer-constructor + reducedExecution.response.body = (IS_NODE_V4 ? new Buffer(stream && stream.data) : + Buffer.from(stream)).toString(); + } + + // set sample request and response details for the current request + items[reducedExecution.item.id] = reducedExecution; + } + + executionMeans[executionId].time.sum += _.get(currentExecution, 'response.responseTime', 0); + executionMeans[executionId].size.sum += _.get(currentExecution, 'response.responseSize', 0); + + ++executionMeans[executionId].time.count; + ++executionMeans[executionId].size.count; + + _.forEach(currentExecution.assertions, function (assertion) { + var aggregationResult, + assertionName = assertion.assertion, + isError = _.get(assertion, 'error') !== undefined, + updateKey = _.get(ASSERTION_STATE, isError); + + result[executionId][assertionName] = result[executionId][assertionName] || { + name: assertionName, + passed: 0, + failed: 0 + }; + aggregationResult = result[executionId][assertionName]; + + ++aggregationResult[updateKey]; + ++netTestCounts[executionId][updateKey]; + }); + }, {}), + + aggregator = function (execution) { + // fetch aggregated run times and response sizes for items, (0 for failed requests) + var aggregationMean = executionMeans[execution.item.id], + meanTime = _.get(aggregationMean, 'time', 0), + meanSize = _.get(aggregationMean, 'size', 0), + parent = execution.item.parent(), + previous = _.last(aggregations), + current = _.merge(items[execution.item.id], { + assertions: _.values(assertions[execution.item.id]), + mean: { + time: util.prettyms(meanTime.sum / meanTime.count), + size: util.filesize(meanSize.sum / meanSize.count) + }, + cumulativeTests: netTestCounts[execution.item.id] + }); + + if (aggregatedExecutions[execution.id]) { return; } + + aggregatedExecutions[execution.id] = true; + + if (previous && parent.id === previous.parent.id) { + previous.executions.push(current); + } + else { + aggregations.push({ + parent: { + id: parent.id, + name: util.getFullName(parent) + }, + executions: [current] + }); + } + }; + + _.forEach(this.summary.run.executions, aggregator); + + this.exports.push({ + name: 'html-reporter', + default: 'newman-run-report.html', + path: options.export, + content: compiler({ + timestamp: Date(), + version: util.version, + aggregations: aggregations, + summary: { + stats: this.summary.run.stats, + collection: this.summary.collection, + globals: _.isObject(this.summary.globals) ? this.summary.globals : undefined, + environment: _.isObject(this.summary.environment) ? this.summary.environment : undefined, + failures: this.summary.run.failures, + responseTotal: util.filesize(this.summary.run.transfers.responseTotal), + responseAverage: util.prettyms(this.summary.run.timings.responseAverage), + duration: util.prettyms(this.summary.run.timings.completed - this.summary.run.timings.started) + } + }) + }); + }); +}; + +module.exports = PostmanHTMLReporter; diff --git a/lib/template-default.hbs b/lib/template-default.hbs new file mode 100644 index 0000000..3491eaf --- /dev/null +++ b/lib/template-default.hbs @@ -0,0 +1,160 @@ + + + + + Postman Report + + + + + + +
+

Newman Report

+
+ {{#with summary}} +
Collection
{{collection.name}}
+ {{#if collection.description}}
Description
{{collection.description}} 
{{/if}} + {{/with}} +
Time
{{timestamp}}
+
Exported with
Newman v{{version}}
+
 
+
 
Total
Failed
+ + {{#with summary}} + {{#with stats}} +
Iterations
{{iterations.total}}
{{iterations.failed}}
+
Requests
{{requests.total}}
{{requests.failed}}
+
Prerequest Scripts
{{prerequestScripts.total}}
{{prerequestScripts.failed}}
+
Test Scripts
{{testScripts.total}}
{{testScripts.failed}}
+
Assertions
{{assertions.total}}
{{assertions.failed}}
+ {{/with}} + +
 
+
Total run duration
{{duration}}
+
Total data received
{{responseTotal}} (approx)
+
Average response time
{{responseAverage}}
+ +
 
+
Total Failures
{{failures.length}}
+ {{/with}} +
+ +

Requests

+ + {{#each aggregations}} + {{#if parent.name}} +
+ +
+
+ {{> aggregations}} +
+
+ {{else}} + {{> aggregations}} + {{/if}} + {{/each}} + + {{#if summary.failures.length}} +

Failures

+ + {{#each summary.failures}} +
+
+ + +
+
+
 
+ {{#if error.test}} +
Description
{{error.message}}

+ {{/if}} + +
Location
{{at}}

+
Request
+ {{#gt cursor.cycles 1}} +
Iteration
{{add cursor.iteration 1}}

+ {{/gt}} +
+
+
+
+ {{/each}} + {{/if}} +
+ + + +{{#*inline "aggregations"}} + {{#each executions}} +
+
+ + +
+
+ {{#with request}} + {{#if description.content}} +
Description
{{description.content}}
+
 
+ {{/if}} + +
Method
{{method}}
+
URL
+ {{/with}} + +
 
+
Mean time per request
{{mean.time}}

+
Mean size per request
{{mean.size}}

+ +
 
+
Total passed tests
{{cumulativeTests.passed}}
+
Total failed tests
{{cumulativeTests.failed}}

+ +
 
+
Status code
{{response.code}}

+ + {{#if assertions.length}} +
 
+
Tests
+ +
+ + + {{#each assertions}}{{/each}} +
NamePass countFail count
{{this.name}}{{this.passed}}{{this.failed}}
+
+ {{/if}} +
+
+
+
+ {{/each}} +{{/inline}} diff --git a/lib/util.js b/lib/util.js new file mode 100644 index 0000000..980ecb6 --- /dev/null +++ b/lib/util.js @@ -0,0 +1,56 @@ +var _ = require('lodash'), + prettyms = require('pretty-ms'), + filesize = require('filesize'), + + util, + + SEP = ' / ', + + /** + * The auxiliary character used to prettify file sizes from raw byte counts. + * + * @type {Object} + */ + FILESIZE_OPTIONS = { spacer: '' }; + +util = { + /** + * A utility helper method that prettifies and returns raw millisecond counts. + * + * @param {Number} ms - The raw millisecond count, usually from response times. + * @returns {String} - The prettified time, scaled to units of time, depending on the input value. + */ + prettyms: function (ms) { + return (ms < 1998) ? `${parseInt(ms, 10)}ms` : prettyms(ms || 0); + }, + + /** + * A utility helper method to prettify byte counts into human readable strings. + * + * @param {Number} bytes - The raw byte count, usually from computed response sizes. + * @returns {String} - The prettified size, suffixed with scaled units, depending on the actual value provided. + */ + filesize: function (bytes) { + return filesize(bytes || 0, FILESIZE_OPTIONS); + }, + + /** + * Resolves the fully qualified name for the provided item + * + * @param {PostmanItem|PostmanItemGroup} item The item for which to resolve the full name + * @param {?String} [separator=SEP] The separator symbol to join path name entries with + * @returns {String} The full name of the provided item, including prepended parent item names + * @private + */ + getFullName: function (item, separator) { + if (_.isEmpty(item) || !_.isFunction(item.parent) || !_.isFunction(item.forEachParent)) { return; } + + var chain = []; + item.forEachParent(function (parent) { chain.unshift(parent.name || parent.id); }); + + item.parent() && chain.push(item.name || item.id); // Add the current item only if it is not the collection + return chain.join(_.isString(separator) ? separator : SEP); + } +}; + +module.exports = util; diff --git a/npm/test-lint.js b/npm/test-lint.js new file mode 100755 index 0000000..9b318e1 --- /dev/null +++ b/npm/test-lint.js @@ -0,0 +1,57 @@ +#!/usr/bin/env node +require('shelljs/global'); +require('colors'); + +var async = require('async'), + ESLintCLIEngine = require('eslint').CLIEngine, + + /** + * The list of source code files / directories to be linted. + * + * @type {Array} + */ + LINT_SOURCE_DIRS = [ + './lib', + './test', + './npm/*.js', + './index.js' + ]; + +module.exports = function (exit) { + // banner line + console.info('\nLinting files using eslint...'.yellow.bold); + + async.waterfall([ + + /** + * Instantiates an ESLint CLI engine and runs it in the scope defined within LINT_SOURCE_DIRS. + * + * @param {Function} next - The callback function whose invocation marks the end of the lint test run. + * @returns {*} + */ + function (next) { + next(null, (new ESLintCLIEngine()).executeOnFiles(LINT_SOURCE_DIRS)); + }, + + /** + * Processes a test report from the Lint test runner, and displays meaningful results. + * + * @param {Object} report - The overall test report for the current lint test. + * @param {Object} report.results - The set of test results for the current lint run. + * @param {Function} next - The callback whose invocation marks the completion of the post run tasks. + * @returns {*} + */ + function (report, next) { + var errorReport = ESLintCLIEngine.getErrorResults(report.results); + // log the result to CLI + console.info(ESLintCLIEngine.getFormatter()(report.results)); + // log the success of the parser if it has no errors + (errorReport && !errorReport.length) && console.info('eslint ok!'.green); + // ensure that the exit code is non zero in case there was an error + next(Number(errorReport && errorReport.length) || 0); + } + ], exit); +}; + +// ensure we run this script exports if this is a direct stdin.tty run +!module.parent && module.exports(exit); diff --git a/npm/test-system.js b/npm/test-system.js new file mode 100755 index 0000000..f9ba4ac --- /dev/null +++ b/npm/test-system.js @@ -0,0 +1,74 @@ +#!/usr/bin/env node +require('shelljs/global'); +require('colors'); + +var async = require('async'), + packity = require('packity'), + expect = require('chai').expect, + Mocha = require('mocha'), + recursive = require('recursive-readdir'), + + /** + * The source directory for system test specs. + * + * @type {String} + */ + SPEC_SOURCE_DIR = './test/system'; + +module.exports = function (exit) { + // banner line + console.info('\nRunning system tests...\n'.yellow.bold); + + async.series([ + + /** + * Enforces sanity checks on installed packages via packity. + * + * @param {Function} next - The callback function invoked when the package sanity check has concluded. + * @returns {*} + */ + function (next) { + console.info('checking installed packages...\n'); + packity({ path: '.' }, packity.cliReporter({}, next)); + }, + + /** + * Runs system tests on SPEC_SOURCE_DIR using Mocha. + * + * @param {Function} next - The callback invoked to mark the completion of the test run. + * @returns {*} + */ + function (next) { + console.info('\nrunning system specs using mocha...'); + + var mocha = new Mocha(); + + recursive(SPEC_SOURCE_DIR, function (err, files) { + if (err) { + console.error(err); + return exit(1); + } + + files.filter(function (file) { + return (file.substr(-8) === '.test.js'); + }).forEach(function (file) { + mocha.addFile(file); + }); + + // start the mocha run + global.expect = expect; // for easy reference + + mocha.run(function (err) { + // clear references and overrides + delete global.expect; + next(err); + }); + mocha = null; // cleanup + }); + } + + ], exit); +}; + +// ensure we run this script exports if this is a direct stdin.tty run +!module.parent && module.exports(exit); diff --git a/npm/test.js b/npm/test.js new file mode 100755 index 0000000..423f4d7 --- /dev/null +++ b/npm/test.js @@ -0,0 +1,15 @@ +#!/usr/bin/env node +require('shelljs/global'); +require('colors'); + +var prettyms = require('pretty-ms'), + startedAt = Date.now(); + +require('async').series([ + require('./test-lint'), + require('./test-system') +], function (code) { + console.info(`\nnewman-reporter-html: duration ${prettyms(Date.now() - startedAt)}\n + newman-reporter-html: ${code ? 'not ok' : 'ok'}!`[code ? 'red' : 'green']); + exit(code && (typeof code === 'number' ? code : 1) || 0); +}); diff --git a/package.json b/package.json new file mode 100644 index 0000000..93129fd --- /dev/null +++ b/package.json @@ -0,0 +1,60 @@ +{ + "name": "newman-reporter-html", + "version": "0.1.0", + "description": "Newman HTML Reporter", + "homepage": "https://github.com/postmanlabs/newman-reporter-html", + "bugs": "https://github.com/postmanlabs/newman-reporter-html/issues", + "repository": { + "type": "git", + "url": "git://github.com/postmanlabs/newman-reporter-html.git" + }, + "keywords": [ + "newman", + "reporter", + "html" + ], + "main": "index.js", + "preferGlobal": true, + "scripts": { + "test": "node npm/test.js", + "test-system": "node npm/test-system.js", + "test-lint": "node npm/test-lint.js" + }, + "author": "Postman Labs (=)", + "license": "Apache-2.0", + "dependencies": { + "filesize": "3.6.1", + "handlebars": "4.0.11", + "lodash": "4.17.10", + "pretty-ms": "3.2.0" + }, + "devDependencies": { + "async": "2.6.1", + "chai": "4.1.2", + "colors": "1.3.0", + "editorconfig": "0.15.0", + "eslint": "4.19.1", + "eslint-plugin-jsdoc": "3.7.1", + "eslint-plugin-lodash": "2.7.0", + "eslint-plugin-mocha": "4.12.1", + "eslint-plugin-security": "1.4.0", + "jsdoc": "3.5.5", + "jsdoc-to-markdown": "4.0.1", + "mocha": "5.2.0", + "packity": "0.3.2", + "parse-gitignore": "0.5.1", + "postman-jsdoc-theme": "0.0.3", + "recursive-readdir": "2.2.2", + "shelljs": "0.8.2" + }, + "engines": { + "node": ">=4" + }, + "greenkeeper": { + "ignore": [ + "cli-progress", + "cli-table3", + "csv-parse" + ] + } +} diff --git a/test/.eslintrc b/test/.eslintrc new file mode 100644 index 0000000..9d477e3 --- /dev/null +++ b/test/.eslintrc @@ -0,0 +1,30 @@ +{ + "plugins": [ + "mocha" + ], + "env": { + "mocha": true, + "node": true, + "es6": true + }, + "rules": { + // Mocha + "mocha/handle-done-callback": "error", + "mocha/max-top-level-suites": "error", + "mocha/no-exclusive-tests": "error", + "mocha/no-global-tests": "error", + "mocha/no-hooks-for-single-case": "off", + "mocha/no-hooks": "off", + "mocha/no-identical-title": "error", + "mocha/no-mocha-arrows": "error", + "mocha/no-nested-tests": "error", + "mocha/no-pending-tests": "error", + "mocha/no-return-and-callback": "error", + "mocha/no-sibling-hooks": "error", + "mocha/no-skipped-tests": "warn", + "mocha/no-synchronous-tests": "off", + "mocha/no-top-level-hooks": "warn", + "mocha/valid-test-description": "off", + "mocha/valid-suite-description": "off" + } +} diff --git a/test/system/editorconfig.test.js b/test/system/editorconfig.test.js new file mode 100644 index 0000000..6b8fcce --- /dev/null +++ b/test/system/editorconfig.test.js @@ -0,0 +1,40 @@ +/** + * @fileOverview Ensures that editorconfig settings are appropriate + */ + +var editorconfig = require('editorconfig'), + + /** + * The width (in spaces) of tabs used for indentation throughout the project + * @type {Number} + */ + TAB_WIDTH = 4; + +/* global describe, it, expect */ +describe('.editorconfig', function () { + var config = editorconfig.parseSync('.editorconfig'); // eslint-disable-line no-sync + + it('should have a tab_width of 4', function () { + expect(config.tab_width).to.equal(TAB_WIDTH); + }); + + it('should have a charset of utf-8', function () { + expect(config.charset).to.equal('utf-8'); + }); + + it('should have an indent_size of 4', function () { + expect(config.indent_size).to.equal(TAB_WIDTH); + }); + + it('should have an indent_style of 4', function () { + expect(config.indent_style).to.equal('space'); + }); + + it('should have a truthy insert_final_newline value', function () { + expect(config.insert_final_newline).to.equal(true); + }); + + it('should have a truthy trim_trailing_whitespace', function () { + expect(config.trim_trailing_whitespace).to.equal(true); + }); +}); diff --git a/test/system/jsdoc-config.test.js b/test/system/jsdoc-config.test.js new file mode 100644 index 0000000..6a4d73f --- /dev/null +++ b/test/system/jsdoc-config.test.js @@ -0,0 +1,98 @@ +/** + * @fileOverview This test specs runs tests on the ,jsdoc-config.json file of repository. It has a set of strict tests + * on the content of the file as well. Any change to .jsdoc-config.json must be accompanied by valid test case in this + * spec-sheet. + */ +/* global describe, it, expect */ +describe('JSDoc configuration', function () { + var fs = require('fs'), + _ = require('lodash'), + + json, + content, + jsdocConfigPath = './.jsdoc-config.json'; + + it('should exist', function (done) { + fs.stat(jsdocConfigPath, done); + }); + + it('should have readable content', function () { + expect(content = fs.readFileSync(jsdocConfigPath).toString()).to.be.ok; + }); + + it('should have valid JSON', function () { + expect(json = JSON.parse(content)).to.be.ok; + }); + + describe('tags', function () { + it('should allow unkown tags', function () { + expect(json.tags.allowUnknownTags).to.be.ok; + }); + + it('should have jsdoc and closure dictionaries', function () { + expect(json.tags.dictionaries).to.eql(['jsdoc', 'closure']); + }); + }); + + describe('source', function () { + it('should have an include pattern', function () { + expect(json.source.includePattern).to.equal('.+\\.js(doc)?$'); + }); + + it('should have an exclude pattern', function () { + expect(json.source.excludePattern).to.equal('(^|\\/|\\\\)_'); + }); + }); + + describe('plugins', function () { + it('should have the markdown plugin', function () { + expect(_.includes(json.plugins, 'plugins/markdown')).to.be.ok; + }); + }); + + describe('templates', function () { + it('should not have clever links', function () { + expect(json.templates.cleverLinks).to.not.be.ok; + }); + + it('should not have monospace links', function () { + expect(json.templates.monospaceLinks).to.not.be.ok; + }); + + it('should highlight tutorial code', function () { + expect(json.templates.highlightTutorialCode).to.be.ok; + }); + }); + + describe('opts', function () { + it('should use the Postman JSDoc theme', function () { + expect(json.opts.template).to.equal('./node_modules/postman-jsdoc-theme'); + }); + + it('should use UTF-8 encoding', function () { + expect(json.opts.encoding).to.equal('utf8'); + }); + + it('should create documentation in out/docs', function () { + expect(json.opts.destination).to.equal('./out/docs'); + }); + + it('should recurse', function () { + expect(json.opts.recurse).to.be.ok; + }); + + it('should have a valid readme', function () { + expect(json.opts.readme).to.equal('README.md'); + }); + }); + + describe('markdown', function () { + it('should have a gfm parser', function () { + expect(json.markdown.parser).to.equal('gfm'); + }); + + it('should have jsdoc and closure dictionaries', function () { + expect(json.markdown.hardwrap).to.not.be.ok; + }); + }); +}); diff --git a/test/system/repository.test.js b/test/system/repository.test.js new file mode 100644 index 0000000..d06033a --- /dev/null +++ b/test/system/repository.test.js @@ -0,0 +1,217 @@ +/** + * @fileOverview This test specs runs tests on the package.json file of repository. It has a set of strict tests on the + * content of the file as well. Any change to package.json must be accompanied by valid test case in this spec-sheet. + */ +var fs = require('fs'), + path = require('path'), + _ = require('lodash'), + // yml = require('js-yaml'), + parseIgnore = require('parse-gitignore'); + +/* global describe, it, expect */ +describe('project repository', function () { + describe('package.json', function () { + var content, + json; + + try { + content = fs.readFileSync('./package.json').toString(); + json = JSON.parse(content); + } + catch (e) { + console.error(e); + content = ''; + json = {}; + } + + it('should have readable JSON content', function () { + expect(content).to.be.ok; + expect(json).to.not.eql({}); + }); + + describe('package.json JSON data', function () { + it('should have valid name, description and author', function () { + expect(json).to.have.property('name', 'newman-reporter-html'); + expect(json).to.have.property('description', 'Newman HTML Reporter'); + expect(json).to.have.property('author', 'Postman Labs (=)'); + expect(json).to.have.property('license', 'Apache-2.0'); + expect(json).to.have.property('homepage', 'https://github.com/postmanlabs/newman-reporter-html'); + expect(json).to.have.property('bugs', 'https://github.com/postmanlabs/newman-reporter-html/issues'); + + expect(json).to.have.property('repository'); + expect(json.repository).to.eql({ + type: 'git', + url: 'git://github.com/postmanlabs/newman-reporter-html.git' + }); + + expect(json).to.have.property('keywords'); + expect(json.keywords).to.eql(['newman', 'reporter', 'html']); + + expect(json).to.have.property('engines'); + expect(json.engines).to.eql({ node: '>=4' }); + }); + + it('should ignore applicable dependencies for GreenKeeper pull requests', function () { + expect(json.greenkeeper).to.eql({ ignore: ['cli-progress', 'cli-table3', 'csv-parse'] }); + }); + + it('should have a valid version string in form of ..', function () { + // eslint-disable-next-line max-len + expect(json.version).to.match(/^((\d+)\.(\d+)\.(\d+))(?:-([\dA-Za-z-]+(?:\.[\dA-Za-z-]+)*))?(?:\+([\dA-Za-z-]+(?:\.[\dA-Za-z-]+)*))?$/); + }); + }); + + describe('script definitions', function () { + it('should exist', function () { + expect(json.scripts).to.be.ok; + json.scripts && Object.keys(json.scripts).forEach(function (scriptName) { + var name = json.scripts[scriptName]; + name = name.replace(/^(node\s|\.\/)/, ''); + fs.stat(name, function (err) { + var fileDetails = path.parse(name); + expect(err).to.equal(null); + expect(fileDetails.ext).to.match(/^\.(sh|js)$/); + }); + }); + }); + + it('should have the hashbang defined', function () { + expect(json.scripts).to.be.ok; + json.scripts && Object.keys(json.scripts).forEach(function (scriptName) { + var fileDetails, + name = json.scripts[scriptName].replace(/^(node\s|\.\/)/, ''); + + fileDetails = path.parse(name); + expect(fileDetails.ext).to.match(/^\.(sh|js)$/); + + fs.readFile(name, function (error, content) { + expect(error).to.equal(null); + if (fileDetails.ext === '.sh') { + expect(/^#!\/bin\/bash[\r\n][\W\w]*$/g.test(content), + `invalid or missing hashbang in ${name}`).to.be.ok; + } + else { + expect(/^#!\/usr\/bin\/env\snode[\r\n][\W\w]*$/g.test(content), + `invalid or missing hashbang in ${name}`).to.be.ok; + } + }); + }); + }); + }); + + describe('dependencies', function () { + it('should exist', function () { + expect(json.dependencies).to.be.an('object'); + }); + + it('should point to a valid and precise (no * or ^) semver', function () { + json.dependencies && Object.keys(json.dependencies).forEach(function (item) { + expect(json.dependencies[item]).to.match(new RegExp('^((\\d+)\\.(\\d+)\\.(\\d+))(?:-' + + '([\\dA-Za-z\\-]+(?:\\.[\\dA-Za-z\\-]+)*))?(?:\\+([\\dA-Za-z\\-]+(?:\\.[\\dA-Za-z\\-]+)*))?$')); + }); + }); + }); + + describe('devDependencies', function () { + it('should exist', function () { + expect(json.devDependencies).to.be.an('object'); + }); + + it('should point to a valid and precise (no * or ^) semver', function () { + json.devDependencies && Object.keys(json.devDependencies).forEach(function (item) { + expect(json.devDependencies[item]).to.match(new RegExp('^((\\d+)\\.(\\d+)\\.(\\d+))(?:-' + + '([\\dA-Za-z\\-]+(?:\\.[\\dA-Za-z\\-]+)*))?(?:\\+([\\dA-Za-z\\-]+(?:\\.[\\dA-Za-z\\-]+)*))?$')); + }); + }); + + it('should not overlap devDependencies', function () { + var clean = []; + + json.devDependencies && Object.keys(json.devDependencies).forEach(function (item) { + !json.dependencies[item] && clean.push(item); + }); + + expect(Object.keys(json.devDependencies)).to.eql(clean); + }); + }); + + describe('main entry script', function () { + it('should point to a valid file', function (done) { + expect(json.main).to.equal('index.js'); + fs.stat(json.main, done); + }); + }); + }); + + describe('README.md', function () { + it('should exist', function (done) { + fs.stat('./README.md', done); + }); + + it('should have readable content', function () { + expect(fs.readFileSync('./README.md').toString()).to.be.ok; + }); + }); + + describe('LICENSE.md', function () { + it('should exist', function (done) { + fs.stat('./LICENSE.md', done); + }); + + it('should have readable content', function () { + expect(fs.readFileSync('./LICENSE.md').toString()).to.be.ok; + }); + }); + + describe('.ignore files', function () { + var gitignorePath = '.gitignore', + npmignorePath = '.npmignore', + npmignore = parseIgnore(npmignorePath), + gitignore = parseIgnore(gitignorePath); + + describe(gitignorePath, function () { + it('should exist', function (done) { + fs.stat(gitignorePath, done); + }); + + it('should have valid content', function () { + expect(gitignore).to.not.be.empty; + }); + }); + + describe(npmignorePath, function () { + it('should exist', function (done) { + fs.stat(npmignorePath, done); + }); + + it('should have valid content', function () { + expect(npmignore).to.not.be.empty; + }); + }); + + it('should have .gitignore coverage to be a subset of .npmignore coverage', function () { + expect(_.intersection(gitignore, npmignore)).to.eql(gitignore); + }); + }); + + describe('.eslintrc', function () { + it('should exist', function (done) { + fs.stat('./.eslintrc', done); + }); + + it('should have readable content', function () { + expect(fs.readFileSync('./.eslintrc').toString()).to.be.ok; + }); + }); + + describe('CHANGELOG.yaml', function () { + it('should exist', function (done) { + fs.stat('./CHANGELOG.yaml', done); + }); + + it('should have readable content', function () { + // expect(yml.safeLoad(fs.readFileSync('./CHANGELOG.yaml')), 'not a valid yaml').to.be.ok; + }); + }); + +}); From b299e41416889af0b0a1ef9cd0d9825bd10db0b8 Mon Sep 17 00:00:00 2001 From: Udit Vasu Date: Mon, 25 Jun 2018 16:54:45 +0530 Subject: [PATCH 2/6] Add travis and appveyor config --- .appveyor.yml | 39 +++++++++++++++++++++++++++++++++++++++ .travis.yml | 8 ++++++++ 2 files changed, 47 insertions(+) create mode 100644 .appveyor.yml create mode 100644 .travis.yml diff --git a/.appveyor.yml b/.appveyor.yml new file mode 100644 index 0000000..3108dc9 --- /dev/null +++ b/.appveyor.yml @@ -0,0 +1,39 @@ +#---------------------------------# +# environment configuration # +#---------------------------------# + +# scripts that are called at very beginning, before repo cloning +init: + - git config --global core.autocrlf input + +# environment variables +environment: + matrix: + - nodejs_version: "4" + - nodejs_version: "6" + - nodejs_version: "8" + +# scripts that run after cloning repository +install: + - ps: Install-Product node $env:nodejs_version + - npm cache clean --force + - appveyor-retry npm install + +build: off # Disable MSBuilds, not related to the regular build process + +# to run your custom scripts instead of automatic tests +test_script: + - node --version && npm --version + - cmd: "npm test" + +# to disable deployment +deploy: off + +#---------------------------------# +# notifications # +#---------------------------------# + +notifications: + - provider: Slack + incoming_webhook: + secure: PRDZ1nhG/cQrwMgCLXsWvTDJtYxv78GJrSlVYpMzpUploVWDzBlpMqmFr9WxZQkY/lxsqCSpGX4zgTYzlte1WMWnghqTIFE8u7svlXHa/tk= diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..de80c4a --- /dev/null +++ b/.travis.yml @@ -0,0 +1,8 @@ +language: node_js +node_js: +- '4' +- '6' +- '8' +notifications: + slack: + secure: Fdl/sQMTl86jYN1r1CRRRQRgyFoslvrhkkfnM2JSdx4gODPgyg4nCPSKtU5j9wpSbbkq9A+YBeFv+Suh+xYNviegqa0AZbztydfFzVDS7xw43B/uR9Y4LwaP5Kis1WGuIOHawwFISNO3hTUei6aybKiKKlxvfqrARJaO01+Xxrg= From b9ef1967e91394bfe8877c6961b3169a1696c888 Mon Sep 17 00:00:00 2001 From: Udit Vasu Date: Mon, 25 Jun 2018 22:12:08 +0530 Subject: [PATCH 3/6] Update Node version to 6, 8, 10 --- .appveyor.yml | 2 +- .travis.yml | 2 +- package.json | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.appveyor.yml b/.appveyor.yml index 3108dc9..b1efa5d 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -9,9 +9,9 @@ init: # environment variables environment: matrix: - - nodejs_version: "4" - nodejs_version: "6" - nodejs_version: "8" + - nodejs_version: "10" # scripts that run after cloning repository install: diff --git a/.travis.yml b/.travis.yml index de80c4a..6166d75 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,8 +1,8 @@ language: node_js node_js: -- '4' - '6' - '8' +- '10' notifications: slack: secure: Fdl/sQMTl86jYN1r1CRRRQRgyFoslvrhkkfnM2JSdx4gODPgyg4nCPSKtU5j9wpSbbkq9A+YBeFv+Suh+xYNviegqa0AZbztydfFzVDS7xw43B/uR9Y4LwaP5Kis1WGuIOHawwFISNO3hTUei6aybKiKKlxvfqrARJaO01+Xxrg= diff --git a/package.json b/package.json index 93129fd..02026e8 100644 --- a/package.json +++ b/package.json @@ -33,10 +33,10 @@ "chai": "4.1.2", "colors": "1.3.0", "editorconfig": "0.15.0", - "eslint": "4.19.1", + "eslint": "5.0.0", "eslint-plugin-jsdoc": "3.7.1", "eslint-plugin-lodash": "2.7.0", - "eslint-plugin-mocha": "4.12.1", + "eslint-plugin-mocha": "5.0.0", "eslint-plugin-security": "1.4.0", "jsdoc": "3.5.5", "jsdoc-to-markdown": "4.0.1", @@ -48,7 +48,7 @@ "shelljs": "0.8.2" }, "engines": { - "node": ">=4" + "node": ">=6" }, "greenkeeper": { "ignore": [ From 4ba17796e6dad419ab51353531a53bc940cd401b Mon Sep 17 00:00:00 2001 From: Udit Vasu Date: Mon, 25 Jun 2018 22:12:42 +0530 Subject: [PATCH 4/6] Update eslint rules --- .eslintrc | 746 +++++++++++++++++++++++++++++------------------------- 1 file changed, 398 insertions(+), 348 deletions(-) diff --git a/.eslintrc b/.eslintrc index 8e4d1dd..f0ea042 100644 --- a/.eslintrc +++ b/.eslintrc @@ -1,361 +1,411 @@ { - "plugins": [ - "jsdoc", - "security", - "lodash", - "mocha" - ], - "env": { - "node": true, - "es6": true - }, - "rules": { - // Possible Errors - "for-direction": "error", - "getter-return": "error", - "no-await-in-loop": "error", - "no-compare-neg-zero": "error", - "no-cond-assign": "error", - "no-console": ["error", { "allow": ["info", "warn", "error"] }], - "no-constant-condition": "error", - "no-control-regex": "error", - "no-debugger": "error", - "no-dupe-args": "error", - "no-dupe-keys": "error", - "no-duplicate-case": "error", - "no-empty": "error", - "no-empty-character-class": "error", - "no-ex-assign": "error", - "no-extra-boolean-cast": "error", - "no-extra-parens": "off", - "no-extra-semi": "error", - "no-func-assign": "error", - "no-inner-declarations": "off", - "no-invalid-regexp": "error", - "no-irregular-whitespace": "error", - "no-obj-calls": "error", - "no-prototype-builtins": "error", - "no-regex-spaces": "error", - "no-sparse-arrays": "error", - "no-template-curly-in-string": "error", - "no-unexpected-multiline": "error", - "no-unreachable": "error", - "no-unsafe-finally": "error", - "no-unsafe-negation": "error", - "use-isnan": "error", - "valid-jsdoc": "off", - "valid-typeof": "error", + "plugins": [ + "jsdoc", + "lodash", + "security" + ], + "env": { + "browser": false, + "node": true, + "es6": true + }, + "globals": {}, + "settings": { + "lodash": { + "pragma": "_" + } + }, + "rules": { + // Possible Errors + "for-direction": "error", + "getter-return": "error", + "no-await-in-loop": "error", + "no-compare-neg-zero": "error", + "no-cond-assign": "error", + "no-console": ["error", { + "allow": ["info", "warn", "error"] + }], + "no-constant-condition": "error", + "no-control-regex": "error", + "no-debugger": "error", + "no-dupe-args": "error", + "no-dupe-keys": "error", + "no-duplicate-case": "error", + "no-empty": "error", + "no-empty-character-class": "error", + "no-ex-assign": "error", + "no-extra-boolean-cast": "error", + "no-extra-parens": "off", + "no-extra-semi": "error", + "no-func-assign": "error", + "no-inner-declarations": "error", + "no-invalid-regexp": "error", + "no-irregular-whitespace": "error", + "no-obj-calls": "error", + "no-prototype-builtins": "error", + "no-regex-spaces": "error", + "no-sparse-arrays": "error", + "no-template-curly-in-string": "error", + "no-unexpected-multiline": "error", + "no-unreachable": "error", + "no-unsafe-finally": "error", + "no-unsafe-negation": "error", + "use-isnan": "error", + "valid-jsdoc": "off", + "valid-typeof": "error", - // Best Practices - "accessor-pairs": "error", - "array-callback-return": "error", - "block-scoped-var": "error", - "class-methods-use-this": "error", - "complexity": "off", - "consistent-return": "warn", - "curly": "error", - "default-case": "error", - "dot-location": ["error", "property"], - "dot-notation": "error", - "eqeqeq": "error", - "guard-for-in": "warn", - "no-alert": "error", - "no-caller": "error", - "no-case-declarations": "error", - "no-div-regex": "error", - "no-else-return": "error", - "no-empty-function": "error", - "no-empty-pattern": "error", - "no-eq-null": "error", - "no-eval": "error", - "no-extend-native": "error", - "no-extra-bind": "error", - "no-extra-label": "error", - "no-fallthrough": "error", - "no-floating-decimal": "error", - "no-global-assign": "error", - "no-implicit-coercion": "error", - "no-implicit-globals": "error", - "no-implied-eval": "error", - "no-invalid-this": "error", - "no-iterator": "error", - "no-labels": "error", - "no-lone-blocks": "error", - "no-loop-func": "error", - "no-magic-numbers": "off", - "no-multi-spaces": "error", - "no-multi-str": "error", - "no-new": "error", - "no-new-func": "error", - "no-new-wrappers": "error", - "no-octal": "error", - "no-octal-escape": "error", - "no-param-reassign": "off", - "no-proto": "error", - "no-redeclare": "error", - "no-restricted-properties": "error", - "no-return-assign": "error", - "no-return-await": "error", - "no-script-url": "error", - "no-self-assign": "error", - "no-self-compare": "error", - "no-sequences": "error", - "no-throw-literal": "error", - "no-unmodified-loop-condition": "error", - "no-unused-expressions": "off", - "no-unused-labels": "error", - "no-useless-call": "error", - "no-useless-concat": "error", - "no-useless-escape": "error", - "no-useless-return": "error", - "no-void": "error", - "no-warning-comments": "off", - "no-with": "error", - "prefer-promise-reject-errors": "error", - "radix": "off", - "require-await": "error", - "vars-on-top": "off", - "wrap-iife": "error", - "yoda": "error", + // Best Practices + "accessor-pairs": "error", + "array-callback-return": "off", + "block-scoped-var": "error", + "class-methods-use-this": "error", + "complexity": "off", + "consistent-return": "warn", + "curly": "error", + "default-case": "error", + "dot-location": ["error", "property"], + "dot-notation": "error", + "eqeqeq": "error", + "guard-for-in": "warn", + "max-classes-per-file": ["error", 1], + "max-lines-per-function": "off", + "no-alert": "error", + "no-caller": "error", + "no-case-declarations": "error", + "no-div-regex": "error", + "no-else-return": "error", + "no-empty-function": "error", + "no-empty-pattern": "error", + "no-eq-null": "error", + "no-eval": "error", + "no-extend-native": "error", + "no-extra-bind": "error", + "no-extra-label": "error", + "no-fallthrough": "error", + "no-floating-decimal": "error", + "no-global-assign": "error", + "no-implicit-coercion": "error", + "no-implicit-globals": "error", + "no-implied-eval": "error", + "no-invalid-this": "error", + "no-iterator": "error", + "no-labels": "error", + "no-lone-blocks": "error", + "no-loop-func": "error", + "no-magic-numbers": "off", + "no-multi-spaces": "error", + "no-multi-str": "error", + "no-new": "error", + "no-new-func": "error", + "no-new-wrappers": "error", + "no-octal": "error", + "no-octal-escape": "error", + "no-param-reassign": "off", + "no-proto": "error", + "no-redeclare": "error", + "no-restricted-properties": "error", + "no-return-assign": "error", + "no-return-await": "error", + "no-script-url": "error", + "no-self-assign": "error", + "no-self-compare": "error", + "no-sequences": "error", + "no-throw-literal": "error", + "no-unmodified-loop-condition": "error", + "no-unused-expressions": "off", + "no-unused-labels": "error", + "no-useless-call": "error", + "no-useless-concat": "error", + "no-useless-escape": "error", + "no-useless-return": "error", + "no-void": "error", + "no-warning-comments": "off", + "no-with": "error", + "prefer-object-spread": "error", + "prefer-promise-reject-errors": "error", + "radix": "error", + "require-await": "error", + "vars-on-top": "off", + "wrap-iife": "error", + "yoda": "error", - // Strict Mode - "strict": "off", + // Strict Mode + "strict": "off", - // Variables - "init-declarations": "off", - "no-catch-shadow": "error", - "no-delete-var": "error", - "no-label-var": "error", - "no-restricted-globals": "error", - "no-shadow": "off", - "no-shadow-restricted-names": "error", - "no-undef": "off", - "no-undef-init": "error", - "no-undefined": "off", - "no-unused-vars": "error", - "no-use-before-define": "error", + // Variables + "init-declarations": "off", + "no-catch-shadow": "error", + "no-delete-var": "error", + "no-label-var": "error", + "no-restricted-globals": "error", + "no-shadow": "off", + "no-shadow-restricted-names": "error", + "no-undef": "error", + "no-undef-init": "error", + "no-undefined": "off", + "no-unused-vars": "error", + "no-use-before-define": "error", - // Node.js and CommonJS - "callback-return": "error", - "global-require": "off", - "handle-callback-err": "error", - "no-buffer-constructor": "error", - "no-mixed-requires": "off", - "no-new-require": "off", - "no-path-concat": "error", - "no-process-env": "error", - "no-process-exit": "off", - "no-restricted-modules": "error", - "no-sync": "off", + // Node.js and CommonJS + "callback-return": "error", + "global-require": "off", + "handle-callback-err": "error", + "no-buffer-constructor": "error", + "no-mixed-requires": "off", + "no-new-require": "off", + "no-path-concat": "error", + "no-process-env": "error", + "no-process-exit": "off", + "no-restricted-modules": "error", + "no-sync": "off", - // Stylistic Issues - "array-bracket-newline": "off", - "array-bracket-spacing": "error", - "array-element-newline": "off", - "block-spacing": "error", - "brace-style": [2, "stroustrup", { "allowSingleLine": true }], - "camelcase": "off", - "capitalized-comments": "off", - "comma-dangle": ["error", "never"], - "comma-spacing": [2, { "before": false, "after": true }], - "comma-style": ["error", "last"], - "computed-property-spacing": "error", - "consistent-this": "off", - "eol-last": "error", - "func-call-spacing": "error", - "func-name-matching": "error", - "func-names": "off", - "func-style": "off", - "id-blacklist": "error", - "id-length": "off", - "id-match": "error", - "indent": ["error", 4, { - "VariableDeclarator": { "var": 1, "let": 1, "const": 1 }, - "SwitchCase": 1 - }], - "jsx-quotes": ["error", "prefer-single"], - "key-spacing": "error", - "keyword-spacing": "error", - "line-comment-position": "off", - "linebreak-style": ["error", "unix"], - "lines-around-comment": ["error", { - "beforeBlockComment": true, - "afterBlockComment": false, - "beforeLineComment": false, - "afterLineComment": false, - "allowBlockStart": true, - "allowBlockEnd": false, - "allowObjectStart": true, - "allowObjectEnd": false, - "allowArrayStart": true, - "allowArrayEnd": false - }], - "max-depth": "error", - "max-len": ["error", { - "code": 120 - }], - "max-lines": "off", - "max-nested-callbacks": "error", - "max-params": "off", - "max-statements": "off", - "max-statements-per-line": "off", - "multiline-ternary": "off", - "new-cap": "off", - "new-parens": "error", - "newline-per-chained-call": "off", - "no-array-constructor": "error", - "no-bitwise": "off", - "no-continue": "off", - "no-inline-comments": "off", - "no-lonely-if": "error", - "no-mixed-operators": "off", - "no-mixed-spaces-and-tabs": "error", - "no-multi-assign": "off", - "no-multiple-empty-lines": "error", - "no-negated-condition": "off", - "no-nested-ternary": "off", - "no-new-object": "error", - "no-plusplus": "off", - "no-restricted-syntax": "error", - "no-tabs": "error", - "no-ternary": "off", - "no-trailing-spaces": "error", - "no-underscore-dangle": "off", - "no-unneeded-ternary": "error", - "no-whitespace-before-property": "error", - "nonblock-statement-body-position": "error", - "object-curly-newline": "off", - "object-curly-spacing": ["error", "always"], - "object-property-newline": "off", - "one-var": ["error", "always"], - "one-var-declaration-per-line": "error", - "operator-assignment": "error", - "operator-linebreak": ["error", "after"], - "padded-blocks": "off", - "padding-line-between-statements": "off", - "quote-props": "off", - "quotes": ["error", "single"], - "require-jsdoc": "warn", - "semi": "error", - "semi-spacing": "error", - "sort-keys": "off", - "sort-vars": "off", - "space-before-blocks": "error", - "space-before-function-paren": "error", - "space-in-parens": "error", - "space-infix-ops": "error", - "space-unary-ops": "error", - "spaced-comment": ["error", "always", { - "block": { - "exceptions": ["!"] - } - }], - "switch-colon-spacing": "error", - "template-tag-spacing": "error", - "unicode-bom": "error", - "wrap-regex": "error", + // Stylistic Issues + "array-bracket-newline": "off", + "array-bracket-spacing": "error", + "array-element-newline": "off", + "block-spacing": "error", + "brace-style": ["error", "stroustrup", { + "allowSingleLine": true + }], + "camelcase": "off", + "capitalized-comments": "off", + "comma-dangle": ["error", "never"], + "comma-spacing": ["error", { + "before": false, + "after": true + }], + "comma-style": ["error", "last"], + "computed-property-spacing": "error", + "consistent-this": "off", + "eol-last": "error", + "func-call-spacing": "error", + "func-name-matching": "error", + "func-names": "off", + "func-style": "off", + "function-paren-newline": ["error", "never"], + "id-blacklist": "error", + "id-length": "off", + "id-match": "error", + "implicit-arrow-linebreak": ["error", "beside"], + "indent": ["error", 4, { + "VariableDeclarator": { + "var": 1, + "let": 1, + "const": 1 + }, + "SwitchCase": 1 + }], + "jsx-quotes": ["error", "prefer-single"], + "key-spacing": "error", + "keyword-spacing": "error", + "line-comment-position": "off", + "linebreak-style": ["error", "unix"], + "lines-around-comment": ["error", { + "beforeBlockComment": true, + "afterBlockComment": false, + "beforeLineComment": false, + "afterLineComment": false, + "allowBlockStart": true, + "allowBlockEnd": false, + "allowObjectStart": true, + "allowObjectEnd": false, + "allowArrayStart": true, + "allowArrayEnd": false + }], + "lines-between-class-members": ["error", "always", { + "exceptAfterSingleLine": true + }], + "max-depth": "error", + "max-len": ["error", { + "code": 120 + }], + "max-lines": "off", + "max-nested-callbacks": "error", + "max-params": "off", + "max-statements": "off", + "max-statements-per-line": ["error", { + "max": 2 + }], + "multiline-comment-style": "off", + "multiline-ternary": "off", + "new-cap": "off", + "new-parens": "error", + "newline-per-chained-call": ["error", { + "ignoreChainWithDepth": 4 + }], + "no-array-constructor": "error", + "no-bitwise": "off", + "no-continue": "off", + "no-inline-comments": "off", + "no-lonely-if": "error", + "no-mixed-operators": "off", + "no-mixed-spaces-and-tabs": "error", + "no-multi-assign": "off", + "no-multiple-empty-lines": "error", + "no-negated-condition": "error", + "no-nested-ternary": "error", + "no-new-object": "error", + "no-plusplus": "off", + "no-restricted-syntax": "error", + "no-tabs": "error", + "no-ternary": "off", + "no-trailing-spaces": "error", + "no-underscore-dangle": "off", + "no-unneeded-ternary": "error", + "no-whitespace-before-property": "error", + "nonblock-statement-body-position": "error", + "object-curly-newline": "off", + "object-curly-spacing": ["error", "always"], + "object-property-newline": "off", + "one-var": ["error", "always"], + "one-var-declaration-per-line": "error", + "operator-assignment": "error", + "operator-linebreak": ["error", "after"], + "padded-blocks": ["error", "never"], + "padding-line-between-statements": ["error", + { + "blankLine": "always", + "prev": "*", + "next": "return" + }, + { + "blankLine": "always", + "prev": ["const", "let", "var"], + "next": "*" + }, + { + "blankLine": "any", + "prev": ["const", "let", "var"], + "next": ["const", "let", "var"] + } + ], + "quote-props": ["error", "as-needed"], + "quotes": ["error", "single"], + "require-jsdoc": "warn", + "semi": "error", + "semi-spacing": "error", + "semi-style": ["error", "last"], + "sort-keys": "off", + "sort-vars": "off", + "space-before-blocks": "error", + "space-before-function-paren": "error", + "space-in-parens": "error", + "space-infix-ops": "error", + "space-unary-ops": "error", + "spaced-comment": ["error", "always", { + "block": { + "exceptions": ["!"] + } + }], + "switch-colon-spacing": "error", + "template-tag-spacing": "error", + "unicode-bom": "error", + "wrap-regex": "error", - // ECMAScript 6 - "arrow-body-style": ["error", "always"], - "arrow-parens": ["error", "always"], - "arrow-spacing": "error", - "constructor-super": "error", - "generator-star-spacing": "error", - "no-class-assign": "error", - "no-confusing-arrow": "error", - "no-const-assign": "error", - "no-dupe-class-members": "error", - "no-duplicate-imports": "error", - "no-new-symbol": "error", - "no-restricted-imports": "error", - "no-this-before-super": "error", - "no-useless-computed-key": "error", - "no-useless-constructor": "off", - "no-var": "off", - "object-shorthand": "off", - "prefer-arrow-callback": "off", - "prefer-const": "off", - "prefer-destructuring": "off", - "prefer-numeric-literals": "off", - "prefer-rest-params": "off", - "prefer-spread": "error", - "prefer-template": "off", - "require-yield": "error", - "rest-spread-spacing": "error", - "sort-imports": "off", - "symbol-description": "off", - "template-curly-spacing": "error", - "yield-star-spacing": "error", + // ECMAScript 6 + "arrow-body-style": ["error", "always"], + "arrow-parens": ["error", "always"], + "arrow-spacing": "error", + "constructor-super": "error", + "generator-star-spacing": "error", + "no-class-assign": "error", + "no-confusing-arrow": "error", + "no-const-assign": "error", + "no-dupe-class-members": "error", + "no-duplicate-imports": "error", + "no-new-symbol": "error", + "no-restricted-imports": "error", + "no-this-before-super": "error", + "no-useless-computed-key": "error", + "no-useless-constructor": "error", + "no-useless-rename": "error", + "no-var": "off", + "object-shorthand": ["error", "consistent-as-needed"], + "prefer-arrow-callback": "off", + "prefer-const": "off", + "prefer-destructuring": "off", + "prefer-numeric-literals": "off", + "prefer-rest-params": "off", + "prefer-spread": "error", + "prefer-template": "off", + "require-yield": "error", + "rest-spread-spacing": "error", + "sort-imports": "off", + "symbol-description": "off", + "template-curly-spacing": "error", + "yield-star-spacing": "error", - // Lodash - "lodash/callback-binding": "error", - "lodash/collection-method-value": "warn", - "lodash/collection-return": "error", - "lodash/no-double-unwrap": "error", - "lodash/no-extra-args": "error", - "lodash/no-unbound-this": "error", - "lodash/unwrap": "error", + // Lodash + "lodash/callback-binding": "error", + "lodash/collection-method-value": "warn", + "lodash/collection-return": "error", + "lodash/no-double-unwrap": "error", + "lodash/no-extra-args": "error", + "lodash/no-unbound-this": "error", + "lodash/unwrap": "error", - "lodash/chain-style": ["error", "as-needed"], - "lodash/chaining": ["error", "always", 3], - "lodash/consistent-compose": ["error", "flow"], - "lodash/identity-shorthand": ["error", "always"], - "lodash/import-scope": "off", - "lodash/matches-prop-shorthand": ["error", "always"], - "lodash/matches-shorthand": ["error", "always", 3], - "lodash/no-commit": "error", - "lodash/path-style": ["error", "string"], - "lodash/prefer-compact": "error", - "lodash/prefer-filter": ["off", 3], - "lodash/prefer-flat-map": "error", - "lodash/prefer-invoke-map": "error", - "lodash/prefer-map": "error", - "lodash/prefer-reject": ["error", 3], - "lodash/prefer-thru": "error", - "lodash/prefer-wrapper-method": "error", - "lodash/preferred-alias": "error", - "lodash/prop-shorthand": ["error", "always"], + "lodash/chain-style": ["error", "as-needed"], + "lodash/chaining": ["error", "always", 3], + "lodash/consistent-compose": ["error", "flow"], + "lodash/identity-shorthand": ["error", "always"], + "lodash/import-scope": "off", + "lodash/matches-prop-shorthand": ["error", "always"], + "lodash/matches-shorthand": ["error", "always", 3], + "lodash/no-commit": "error", + "lodash/path-style": ["error", "as-needed"], + "lodash/prefer-compact": "error", + "lodash/prefer-filter": ["off", 3], + "lodash/prefer-flat-map": "error", + "lodash/prefer-invoke-map": "error", + "lodash/prefer-map": "error", + "lodash/prefer-reject": ["error", 3], + "lodash/prefer-thru": "error", + "lodash/prefer-wrapper-method": "error", + "lodash/preferred-alias": "error", + "lodash/prop-shorthand": ["error", "always"], - "lodash/prefer-constant": "off", - "lodash/prefer-get": ["warn", 4], - "lodash/prefer-includes": ["error", { "includeNative": true }], - "lodash/prefer-is-nil": "error", - "lodash/prefer-lodash-chain": "error", - "lodash/prefer-lodash-method": "off", - "lodash/prefer-lodash-typecheck": "off", - "lodash/prefer-matches": ["off", 3], - "lodash/prefer-noop": "off", - "lodash/prefer-over-quantifier": "warn", - "lodash/prefer-some": "off", - "lodash/prefer-startswith": "off", - "lodash/prefer-times": "off", + "lodash/prefer-constant": "off", + "lodash/prefer-get": ["warn", 4], + "lodash/prefer-includes": ["error", { + "includeNative": true + }], + "lodash/prefer-is-nil": "error", + "lodash/prefer-lodash-chain": "error", + "lodash/prefer-lodash-method": "off", + "lodash/prefer-lodash-typecheck": "off", + "lodash/prefer-matches": ["off", 3], + "lodash/prefer-noop": "off", + "lodash/prefer-over-quantifier": "warn", + "lodash/prefer-some": "off", + "lodash/prefer-startswith": "off", + "lodash/prefer-times": "off", - // JsDoc - "jsdoc/check-param-names": "error", - "jsdoc/check-tag-names": "off", - "jsdoc/check-types": "off", - "jsdoc/newline-after-description": "error", - "jsdoc/require-description-complete-sentence": "off", - "jsdoc/require-example": "off", - "jsdoc/require-hyphen-before-param-description": "off", - "jsdoc/require-param": "warn", - "jsdoc/require-param-description": "error", - "jsdoc/require-param-type": "error", - "jsdoc/require-returns-description": "off", - "jsdoc/require-returns-type": "error", + // JsDoc + "jsdoc/check-param-names": "error", + "jsdoc/check-tag-names": "off", + "jsdoc/check-types": "off", + "jsdoc/newline-after-description": "error", + "jsdoc/require-description-complete-sentence": "off", + "jsdoc/require-example": "off", + "jsdoc/require-hyphen-before-param-description": "off", + "jsdoc/require-param": "error", + "jsdoc/require-param-description": "error", + "jsdoc/require-param-type": "error", + "jsdoc/require-returns-description": "off", + "jsdoc/require-returns-type": "error", - // Security - "security/detect-unsafe-regex": "off", - "security/detect-buffer-noassert": "error", - "security/detect-child-process": "error", - "security/detect-disable-mustache-escape": "error", - "security/detect-eval-with-expression": "error", - "security/detect-no-csrf-before-method-override": "off", - "security/detect-non-literal-fs-filename": "off", - "security/detect-non-literal-regexp": "warn", - "security/detect-non-literal-require": "off", - "security/detect-object-injection": "off", - "security/detect-possible-timing-attacks": "error", - "security/detect-pseudoRandomBytes": "error" - } + // Security + "security/detect-unsafe-regex": "off", + "security/detect-buffer-noassert": "error", + "security/detect-child-process": "error", + "security/detect-disable-mustache-escape": "error", + "security/detect-eval-with-expression": "error", + "security/detect-no-csrf-before-method-override": "error", + "security/detect-non-literal-fs-filename": "off", + "security/detect-non-literal-regexp": "off", + "security/detect-non-literal-require": "error", + "security/detect-object-injection": "off", + "security/detect-possible-timing-attacks": "error", + "security/detect-pseudoRandomBytes": "error" + } } From b98d0dfae410646aaac46350aecad2a8a1dd9c96 Mon Sep 17 00:00:00 2001 From: Udit Vasu Date: Mon, 25 Jun 2018 22:12:57 +0530 Subject: [PATCH 5/6] Fix eslint warnings --- lib/util.js | 8 +++++--- npm/test-lint.js | 2 ++ npm/test-system.js | 2 ++ npm/test.js | 1 + test/system/repository.test.js | 3 ++- 5 files changed, 12 insertions(+), 4 deletions(-) diff --git a/lib/util.js b/lib/util.js index 980ecb6..a909e95 100644 --- a/lib/util.js +++ b/lib/util.js @@ -20,7 +20,7 @@ util = { * @param {Number} ms - The raw millisecond count, usually from response times. * @returns {String} - The prettified time, scaled to units of time, depending on the input value. */ - prettyms: function (ms) { + prettyms (ms) { return (ms < 1998) ? `${parseInt(ms, 10)}ms` : prettyms(ms || 0); }, @@ -30,7 +30,7 @@ util = { * @param {Number} bytes - The raw byte count, usually from computed response sizes. * @returns {String} - The prettified size, suffixed with scaled units, depending on the actual value provided. */ - filesize: function (bytes) { + filesize (bytes) { return filesize(bytes || 0, FILESIZE_OPTIONS); }, @@ -42,13 +42,15 @@ util = { * @returns {String} The full name of the provided item, including prepended parent item names * @private */ - getFullName: function (item, separator) { + getFullName (item, separator) { if (_.isEmpty(item) || !_.isFunction(item.parent) || !_.isFunction(item.forEachParent)) { return; } var chain = []; + item.forEachParent(function (parent) { chain.unshift(parent.name || parent.id); }); item.parent() && chain.push(item.name || item.id); // Add the current item only if it is not the collection + return chain.join(_.isString(separator) ? separator : SEP); } }; diff --git a/npm/test-lint.js b/npm/test-lint.js index 9b318e1..16e7838 100755 --- a/npm/test-lint.js +++ b/npm/test-lint.js @@ -1,4 +1,5 @@ #!/usr/bin/env node +/* global exit */ require('shelljs/global'); require('colors'); @@ -44,6 +45,7 @@ module.exports = function (exit) { function (report, next) { var errorReport = ESLintCLIEngine.getErrorResults(report.results); // log the result to CLI + console.info(ESLintCLIEngine.getFormatter()(report.results)); // log the success of the parser if it has no errors (errorReport && !errorReport.length) && console.info('eslint ok!'.green); diff --git a/npm/test-system.js b/npm/test-system.js index f9ba4ac..2cf7ba2 100755 --- a/npm/test-system.js +++ b/npm/test-system.js @@ -1,4 +1,5 @@ #!/usr/bin/env node +/* global exit */ require('shelljs/global'); require('colors'); @@ -46,6 +47,7 @@ module.exports = function (exit) { recursive(SPEC_SOURCE_DIR, function (err, files) { if (err) { console.error(err); + return exit(1); } diff --git a/npm/test.js b/npm/test.js index 423f4d7..69f41b0 100755 --- a/npm/test.js +++ b/npm/test.js @@ -1,4 +1,5 @@ #!/usr/bin/env node +/* global exit */ require('shelljs/global'); require('colors'); diff --git a/test/system/repository.test.js b/test/system/repository.test.js index d06033a..c648901 100644 --- a/test/system/repository.test.js +++ b/test/system/repository.test.js @@ -66,9 +66,11 @@ describe('project repository', function () { expect(json.scripts).to.be.ok; json.scripts && Object.keys(json.scripts).forEach(function (scriptName) { var name = json.scripts[scriptName]; + name = name.replace(/^(node\s|\.\/)/, ''); fs.stat(name, function (err) { var fileDetails = path.parse(name); + expect(err).to.equal(null); expect(fileDetails.ext).to.match(/^\.(sh|js)$/); }); @@ -213,5 +215,4 @@ describe('project repository', function () { // expect(yml.safeLoad(fs.readFileSync('./CHANGELOG.yaml')), 'not a valid yaml').to.be.ok; }); }); - }); From 2ffb08672597934eab8f87c662ddced0644e2806 Mon Sep 17 00:00:00 2001 From: Udit Vasu Date: Mon, 25 Jun 2018 22:16:01 +0530 Subject: [PATCH 6/6] Minor: Update repository test --- test/system/repository.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/system/repository.test.js b/test/system/repository.test.js index c648901..88a2de6 100644 --- a/test/system/repository.test.js +++ b/test/system/repository.test.js @@ -48,7 +48,7 @@ describe('project repository', function () { expect(json.keywords).to.eql(['newman', 'reporter', 'html']); expect(json).to.have.property('engines'); - expect(json.engines).to.eql({ node: '>=4' }); + expect(json.engines).to.eql({ node: '>=6' }); }); it('should ignore applicable dependencies for GreenKeeper pull requests', function () {