From b3c9a50eadfe8a765f16ad127cdaeef1880a588f Mon Sep 17 00:00:00 2001 From: Matthieu Hostache Date: Tue, 17 Dec 2019 14:52:05 +0100 Subject: [PATCH] Web UI: Polling on tables --- webui/.eslintrc.js | 9 +- webui/package-lock.json | 1257 ++++++++++++++++- webui/package.json | 11 +- webui/quasar.conf.js | 1 - webui/src/_helpers/Errors.js | 3 +- webui/src/_helpers/Helps.js | 4 +- webui/src/_helpers/Mutations.js | 44 + webui/src/_mixins/Pagination.js | 74 + webui/src/boot/lodash.js | 7 - .../src/components/_commons/ChartDoughnut.vue | 5 +- .../src/components/dashboard/PanelFeature.vue | 4 +- webui/src/pages/http/Middlewares.vue | 71 +- webui/src/pages/http/Routers.vue | 71 +- webui/src/pages/http/Services.vue | 71 +- webui/src/pages/tcp/Routers.vue | 73 +- webui/src/pages/tcp/Services.vue | 73 +- webui/src/store/http/mutations.js | 74 +- webui/src/store/http/mutations.spec.js | 292 ++++ webui/src/store/tcp/mutations.js | 48 +- webui/src/store/tcp/mutations.spec.js | 197 +++ 20 files changed, 2028 insertions(+), 361 deletions(-) create mode 100644 webui/src/_helpers/Mutations.js create mode 100644 webui/src/_mixins/Pagination.js delete mode 100644 webui/src/boot/lodash.js create mode 100644 webui/src/store/http/mutations.spec.js create mode 100644 webui/src/store/tcp/mutations.spec.js diff --git a/webui/.eslintrc.js b/webui/.eslintrc.js index cea5781eb..f8fee91f8 100644 --- a/webui/.eslintrc.js +++ b/webui/.eslintrc.js @@ -7,19 +7,22 @@ module.exports = { }, env: { - browser: true + browser: true, + mocha: true }, extends: [ // https://github.com/vuejs/eslint-plugin-vue#priority-a-essential-error-prevention // consider switching to `plugin:vue/strongly-recommended` or `plugin:vue/recommended` for stricter rules. 'plugin:vue/essential', - '@vue/standard' + '@vue/standard', + 'plugin:mocha/recommended' ], // required to lint *.vue files plugins: [ - 'vue' + 'vue', + 'mocha' ], globals: { diff --git a/webui/package-lock.json b/webui/package-lock.json index 909e47be8..1956acaa2 100644 --- a/webui/package-lock.json +++ b/webui/package-lock.json @@ -2602,6 +2602,16 @@ "integrity": "sha512-8VCoJeeH8tCkzhkpfOkt+abALQkS11OIHhte5MBzYaKMTqK0A3ZAKEUVAffsOklhEv7t0yrQt696Opnu9oAx+w==", "dev": true }, + "@vue/test-utils": { + "version": "1.0.0-beta.29", + "resolved": "https://registry.npmjs.org/@vue/test-utils/-/test-utils-1.0.0-beta.29.tgz", + "integrity": "sha512-yX4sxEIHh4M9yAbLA/ikpEnGKMNBCnoX98xE1RwxfhQVcn0MaXNSj1Qmac+ZydTj6VBSEVukchBogXBTwc+9iA==", + "dev": true, + "requires": { + "dom-event-types": "^1.0.0", + "lodash": "^4.17.4" + } + }, "@webassemblyjs/ast": { "version": "1.8.5", "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.8.5.tgz", @@ -3060,6 +3070,12 @@ "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", "dev": true }, + "assertion-error": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", + "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", + "dev": true + }, "assign-symbols": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", @@ -3538,6 +3554,12 @@ "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=", "dev": true }, + "browser-stdout": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", + "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", + "dev": true + }, "browserify-aes": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", @@ -3782,6 +3804,20 @@ "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", "dev": true }, + "chai": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.2.0.tgz", + "integrity": "sha512-XQU3bhBukrOsQCuwZndwGcCVQHyZi53fQ6Ys1Fym7E4olpIqqZZhhoFJoaKVvV17lWQoXYwgWN2nF5crA8J2jw==", + "dev": true, + "requires": { + "assertion-error": "^1.1.0", + "check-error": "^1.0.2", + "deep-eql": "^3.0.1", + "get-func-name": "^2.0.0", + "pathval": "^1.1.0", + "type-detect": "^4.0.5" + } + }, "chalk": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", @@ -3832,6 +3868,12 @@ "color-name": "^1.0.0" } }, + "check-error": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", + "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=", + "dev": true + }, "check-types": { "version": "8.0.3", "resolved": "https://registry.npmjs.org/check-types/-/check-types-8.0.3.tgz", @@ -4832,6 +4874,15 @@ "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", "dev": true }, + "deep-eql": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", + "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", + "dev": true, + "requires": { + "type-detect": "^4.0.0" + } + }, "deep-equal": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.1.tgz", @@ -5002,6 +5053,12 @@ "integrity": "sha512-ZIzRpLJrOj7jjP2miAtgqIfmzbxa4ZOr5jJc601zklsfEx9oTzmmj2nVpIPRpNlRTIh8lc1kyViIY7BWSGNmKw==", "dev": true }, + "diff": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", + "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", + "dev": true + }, "diffie-hellman": { "version": "5.0.3", "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", @@ -5066,6 +5123,12 @@ "utila": "~0.4" } }, + "dom-event-types": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/dom-event-types/-/dom-event-types-1.0.0.tgz", + "integrity": "sha512-2G2Vwi2zXTHBGqXHsJ4+ak/iP0N8Ar+G8a7LiD2oup5o4sQWytwqqrZu/O6hIMV0KMID2PL69OhpshLO0n7UJQ==", + "dev": true + }, "dom-serializer": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.2.tgz", @@ -5585,6 +5648,15 @@ } } }, + "eslint-plugin-mocha": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-mocha/-/eslint-plugin-mocha-6.2.1.tgz", + "integrity": "sha512-o3Ibhpczi5MjUVpnlnrpC/+oJYGoHKB5m4bQdRnaAOeFCN3HRkqBisQ2/h0hEuCR4lPxyHP1Qzyjpna8MsOdlA==", + "dev": true, + "requires": { + "ramda": "^0.26.1" + } + }, "eslint-plugin-node": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/eslint-plugin-node/-/eslint-plugin-node-8.0.1.tgz", @@ -6185,6 +6257,23 @@ } } }, + "flat": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/flat/-/flat-4.1.0.tgz", + "integrity": "sha512-Px/TiLIznH7gEDlPXcUD4KnBusa6kR6ayRUVcnEAbreRIuhkqow/mun59BuRXwoYk7ZQOLW1ZM05ilIvK38hFw==", + "dev": true, + "requires": { + "is-buffer": "~2.0.3" + }, + "dependencies": { + "is-buffer": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.4.tgz", + "integrity": "sha512-Kq1rokWXOPXWuaMAqZiJW4XxsmD9zGx9q4aePabbn3qCRGedtH7Cm+zV8WETitMfu1wdh+Rvd6w5egwSngUX2A==", + "dev": true + } + } + }, "flat-cache": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz", @@ -6473,6 +6562,12 @@ "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==", "dev": true }, + "get-func-name": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", + "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=", + "dev": true + }, "get-own-enumerable-property-symbols": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.1.tgz", @@ -6594,6 +6689,12 @@ "integrity": "sha512-jpSvDPV4Cq/bgtpndIWbI5hmYxhQGHPC4d4cqBPb4DLniCfhJokdXhwhaDuLBGLQdvvRum/UiX6ECVIPvDXqdg==", "dev": true }, + "growl": { + "version": "1.10.5", + "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", + "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", + "dev": true + }, "gzip-size": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-5.1.1.tgz", @@ -7292,6 +7393,12 @@ "ipaddr.js": "^1.9.0" } }, + "interpret": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.2.0.tgz", + "integrity": "sha512-mT34yGKMNceBQUoVn7iCDKDntA7SC6gycMAWzGx1z/CMCTV7b2AAtXlo3nRyHZ1FelRkQbQjprHSYGwzLtkVbw==", + "dev": true + }, "invariant": { "version": "2.2.4", "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", @@ -7969,7 +8076,8 @@ "lodash": { "version": "4.17.15", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", - "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==" + "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", + "dev": true }, "lodash._reinterpolate": { "version": "3.0.0", @@ -8001,6 +8109,11 @@ "integrity": "sha1-gwWOkDtRy7dZ0JzPVG3qPqOcRxg=", "dev": true }, + "lodash.isequal": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", + "integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA=" + }, "lodash.kebabcase": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/lodash.kebabcase/-/lodash.kebabcase-4.1.1.tgz", @@ -8056,6 +8169,15 @@ "integrity": "sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=", "dev": true }, + "log-symbols": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", + "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==", + "dev": true, + "requires": { + "chalk": "^2.0.1" + } + }, "log-update": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/log-update/-/log-update-3.3.0.tgz", @@ -8580,6 +8702,1022 @@ } } }, + "mocha": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-6.2.2.tgz", + "integrity": "sha512-FgDS9Re79yU1xz5d+C4rv1G7QagNGHZ+iXF81hO8zY35YZZcLEsJVfFolfsqKFWunATEvNzMK0r/CwWd/szO9A==", + "dev": true, + "requires": { + "ansi-colors": "3.2.3", + "browser-stdout": "1.3.1", + "debug": "3.2.6", + "diff": "3.5.0", + "escape-string-regexp": "1.0.5", + "find-up": "3.0.0", + "glob": "7.1.3", + "growl": "1.10.5", + "he": "1.2.0", + "js-yaml": "3.13.1", + "log-symbols": "2.2.0", + "minimatch": "3.0.4", + "mkdirp": "0.5.1", + "ms": "2.1.1", + "node-environment-flags": "1.0.5", + "object.assign": "4.1.0", + "strip-json-comments": "2.0.1", + "supports-color": "6.0.0", + "which": "1.3.1", + "wide-align": "1.1.3", + "yargs": "13.3.0", + "yargs-parser": "13.1.1", + "yargs-unparser": "1.6.0" + }, + "dependencies": { + "ansi-colors": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.3.tgz", + "integrity": "sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw==", + "dev": true + }, + "cliui": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", + "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", + "dev": true, + "requires": { + "string-width": "^3.1.0", + "strip-ansi": "^5.2.0", + "wrap-ansi": "^5.1.0" + } + }, + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true + }, + "glob": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", + "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + }, + "require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", + "dev": true + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, + "supports-color": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.0.0.tgz", + "integrity": "sha512-on9Kwidc1IUQo+bQdhi8+Tijpo0e1SS6RoGo2guUwn5vdaxw8RXOF9Vb2ws+ihWOmh4JnCJOvaziZWP1VABaLg==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "yargs": { + "version": "13.3.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.0.tgz", + "integrity": "sha512-2eehun/8ALW8TLoIl7MVaRUrg+yCnenu8B4kBlRxj3GJGDKU1Og7sMXPNm1BYyM1DOJmTZ4YeN/Nwxv+8XJsUA==", + "dev": true, + "requires": { + "cliui": "^5.0.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^13.1.1" + } + }, + "yargs-parser": { + "version": "13.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.1.tgz", + "integrity": "sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ==", + "dev": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + } + } + }, + "mocha-webpack": { + "version": "2.0.0-beta.0", + "resolved": "https://registry.npmjs.org/mocha-webpack/-/mocha-webpack-2.0.0-beta.0.tgz", + "integrity": "sha512-2ezbW0h5cYWr874F/hzytQCqINxk+GVelMY4xWTSHwwH1LrPAOzjlUljZ+/PhpaP6QeqYbL5x5vK/bnaXqkfEw==", + "dev": true, + "requires": { + "babel-runtime": "^6.18.0", + "chalk": "^2.3.0", + "chokidar": "^2.0.2", + "glob-parent": "^3.1.0", + "globby": "^7.1.1", + "interpret": "^1.0.1", + "is-glob": "^4.0.0", + "loader-utils": "^1.1.0", + "lodash": "^4.3.0", + "memory-fs": "^0.4.1", + "nodent-runtime": "^3.0.3", + "normalize-path": "^2.0.1", + "progress": "^2.0.0", + "source-map-support": "^0.5.0", + "strip-ansi": "^4.0.0", + "toposort": "^1.0.0", + "yargs": "^11.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "anymatch": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "dev": true, + "requires": { + "micromatch": "^3.1.4", + "normalize-path": "^2.1.1" + } + }, + "binary-extensions": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", + "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==", + "dev": true + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "camelcase": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", + "dev": true + }, + "chokidar": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", + "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", + "dev": true, + "requires": { + "anymatch": "^2.0.0", + "async-each": "^1.0.1", + "braces": "^2.3.2", + "fsevents": "^1.2.7", + "glob-parent": "^3.1.0", + "inherits": "^2.0.3", + "is-binary-path": "^1.0.0", + "is-glob": "^4.0.0", + "normalize-path": "^3.0.0", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.2.1", + "upath": "^1.1.1" + }, + "dependencies": { + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true + } + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "dev": true, + "requires": { + "locate-path": "^2.0.0" + } + }, + "fsevents": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.9.tgz", + "integrity": "sha512-oeyj2H3EjjonWcFjD5NvZNE9Rqe4UW+nQBU2HNeKw0koVLEFIhtyETyAakeAM3de7Z/SW5kcA+fZUait9EApnw==", + "dev": true, + "optional": true, + "requires": { + "nan": "^2.12.1", + "node-pre-gyp": "^0.12.0" + }, + "dependencies": { + "abbrev": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "ansi-regex": { + "version": "2.1.1", + "bundled": true, + "dev": true + }, + "aproba": { + "version": "1.2.0", + "bundled": true, + "dev": true, + "optional": true + }, + "are-we-there-yet": { + "version": "1.1.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "balanced-match": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "brace-expansion": { + "version": "1.1.11", + "bundled": true, + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "chownr": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "code-point-at": { + "version": "1.1.0", + "bundled": true, + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "bundled": true, + "dev": true + }, + "console-control-strings": { + "version": "1.1.0", + "bundled": true, + "dev": true + }, + "core-util-is": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "debug": { + "version": "4.1.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ms": "^2.1.1" + } + }, + "deep-extend": { + "version": "0.6.0", + "bundled": true, + "dev": true, + "optional": true + }, + "delegates": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "detect-libc": { + "version": "1.0.3", + "bundled": true, + "dev": true, + "optional": true + }, + "fs-minipass": { + "version": "1.2.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minipass": "^2.2.1" + } + }, + "fs.realpath": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "gauge": { + "version": "2.7.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "glob": { + "version": "7.1.3", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "has-unicode": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "iconv-lite": { + "version": "0.4.24", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "ignore-walk": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minimatch": "^3.0.4" + } + }, + "inflight": { + "version": "1.0.6", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.3", + "bundled": true, + "dev": true + }, + "ini": { + "version": "1.3.5", + "bundled": true, + "dev": true, + "optional": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "isarray": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "minimatch": { + "version": "3.0.4", + "bundled": true, + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "0.0.8", + "bundled": true, + "dev": true + }, + "minipass": { + "version": "2.3.5", + "bundled": true, + "dev": true, + "requires": { + "safe-buffer": "^5.1.2", + "yallist": "^3.0.0" + } + }, + "minizlib": { + "version": "1.2.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minipass": "^2.2.1" + } + }, + "mkdirp": { + "version": "0.5.1", + "bundled": true, + "dev": true, + "requires": { + "minimist": "0.0.8" + } + }, + "ms": { + "version": "2.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "needle": { + "version": "2.3.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "debug": "^4.1.0", + "iconv-lite": "^0.4.4", + "sax": "^1.2.4" + } + }, + "node-pre-gyp": { + "version": "0.12.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "detect-libc": "^1.0.2", + "mkdirp": "^0.5.1", + "needle": "^2.2.1", + "nopt": "^4.0.1", + "npm-packlist": "^1.1.6", + "npmlog": "^4.0.2", + "rc": "^1.2.7", + "rimraf": "^2.6.1", + "semver": "^5.3.0", + "tar": "^4" + } + }, + "nopt": { + "version": "4.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "abbrev": "1", + "osenv": "^0.1.4" + } + }, + "npm-bundled": { + "version": "1.0.6", + "bundled": true, + "dev": true, + "optional": true + }, + "npm-packlist": { + "version": "1.4.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ignore-walk": "^3.0.1", + "npm-bundled": "^1.0.1" + } + }, + "npmlog": { + "version": "4.1.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "object-assign": { + "version": "4.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "once": { + "version": "1.4.0", + "bundled": true, + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "os-homedir": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "os-tmpdir": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "osenv": { + "version": "0.1.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "process-nextick-args": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "rc": { + "version": "1.2.8", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "readable-stream": { + "version": "2.3.6", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "rimraf": { + "version": "2.6.3", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "glob": "^7.1.3" + } + }, + "safe-buffer": { + "version": "5.1.2", + "bundled": true, + "dev": true + }, + "safer-buffer": { + "version": "2.1.2", + "bundled": true, + "dev": true, + "optional": true + }, + "sax": { + "version": "1.2.4", + "bundled": true, + "dev": true, + "optional": true + }, + "semver": { + "version": "5.7.0", + "bundled": true, + "dev": true, + "optional": true + }, + "set-blocking": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "signal-exit": { + "version": "3.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "string-width": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "string_decoder": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "tar": { + "version": "4.4.8", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "chownr": "^1.1.1", + "fs-minipass": "^1.2.5", + "minipass": "^2.3.4", + "minizlib": "^1.1.1", + "mkdirp": "^0.5.0", + "safe-buffer": "^5.1.2", + "yallist": "^3.0.2" + } + }, + "util-deprecate": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "wide-align": { + "version": "1.1.3", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "string-width": "^1.0.2 || 2" + } + }, + "wrappy": { + "version": "1.0.2", + "bundled": true, + "dev": true + }, + "yallist": { + "version": "3.0.3", + "bundled": true, + "dev": true + } + } + }, + "glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "dev": true, + "requires": { + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + }, + "dependencies": { + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "requires": { + "is-extglob": "^2.1.0" + } + } + } + }, + "is-binary-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", + "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", + "dev": true, + "requires": { + "binary-extensions": "^1.0.0" + } + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true + }, + "is-glob": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", + "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "dev": true, + "requires": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + } + }, + "memory-fs": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", + "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=", + "dev": true, + "requires": { + "errno": "^0.1.3", + "readable-stream": "^2.0.1" + } + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + }, + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "dev": true, + "requires": { + "remove-trailing-separator": "^1.0.1" + } + }, + "p-limit": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "dev": true, + "requires": { + "p-try": "^1.0.0" + } + }, + "p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "dev": true, + "requires": { + "p-limit": "^1.1.0" + } + }, + "p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", + "dev": true + }, + "readdirp": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", + "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.11", + "micromatch": "^3.1.10", + "readable-stream": "^2.0.2" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + }, + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "dev": true, + "requires": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + } + }, + "y18n": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", + "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", + "dev": true + }, + "yargs": { + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-11.1.1.tgz", + "integrity": "sha512-PRU7gJrJaXv3q3yQZ/+/X6KBswZiaQ+zOmdprZcouPYtQgvNU35i+68M4b1ZHLZtYFT5QObFLV+ZkmJYcwKdiw==", + "dev": true, + "requires": { + "cliui": "^4.0.0", + "decamelize": "^1.1.1", + "find-up": "^2.1.0", + "get-caller-file": "^1.0.1", + "os-locale": "^3.1.0", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^2.0.0", + "which-module": "^2.0.0", + "y18n": "^3.2.1", + "yargs-parser": "^9.0.2" + } + }, + "yargs-parser": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-9.0.2.tgz", + "integrity": "sha1-nM9qQ0YP5O1Aqbto9I1DuKaMwHc=", + "dev": true, + "requires": { + "camelcase": "^4.1.0" + } + } + } + }, "moment": { "version": "2.24.0", "resolved": "https://registry.npmjs.org/moment/-/moment-2.24.0.tgz", @@ -8685,6 +9823,24 @@ "lower-case": "^1.1.1" } }, + "node-environment-flags": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/node-environment-flags/-/node-environment-flags-1.0.5.tgz", + "integrity": "sha512-VNYPRfGfmZLx0Ye20jWzHUjyTW/c+6Wq+iLhDzUI4XmhrDd9l/FozXV3F2xOaXjvp0co0+v1YSR3CMP6g+VvLQ==", + "dev": true, + "requires": { + "object.getownpropertydescriptors": "^2.0.3", + "semver": "^5.7.0" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + } + } + }, "node-forge": { "version": "0.9.0", "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.9.0.tgz", @@ -8860,6 +10016,12 @@ } } }, + "nodent-runtime": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/nodent-runtime/-/nodent-runtime-3.2.1.tgz", + "integrity": "sha512-7Ws63oC+215smeKJQCxzrK21VFVlCFBkwl0MOObt0HOpVQXs3u483sAmtkF33nNqZ5rSOQjB76fgyPBmAUrtCA==", + "dev": true + }, "nopt": { "version": "3.0.6", "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", @@ -9421,6 +10583,12 @@ } } }, + "pathval": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.0.tgz", + "integrity": "sha1-uULm1L3mUwBe9rcTYd74cn0GReA=", + "dev": true + }, "pbkdf2": { "version": "3.0.17", "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.17.tgz", @@ -10390,6 +11558,12 @@ "integrity": "sha512-w7fLxIRCRT7U8Qu53jQnJyPkYZIaR4n5151KMfcJlO/A9397Wxb1amJvROTK6TOnp7PfoAmg/qXiNHI+08jRfA==", "dev": true }, + "ramda": { + "version": "0.26.1", + "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.26.1.tgz", + "integrity": "sha512-hLWjpy7EnsDBb0p+Z3B7rPi3GDeRG5ZtiI33kJhTt+ORCd38AbAIjB/9zRIUoeTbE/AVX5ZkU7m6bznsvrf8eQ==", + "dev": true + }, "randombytes": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", @@ -12575,6 +13749,12 @@ "prelude-ls": "~1.1.2" } }, + "type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true + }, "type-fest": { "version": "0.8.1", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", @@ -15305,6 +16485,81 @@ "camelcase": "^5.0.0", "decamelize": "^1.2.0" } + }, + "yargs-unparser": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-1.6.0.tgz", + "integrity": "sha512-W9tKgmSn0DpSatfri0nx52Joq5hVXgeLiqR/5G0sZNDoLZFOr/xjBUDcShCOGNsBnEMNo1KAMBkTej1Hm62HTw==", + "dev": true, + "requires": { + "flat": "^4.1.0", + "lodash": "^4.17.15", + "yargs": "^13.3.0" + }, + "dependencies": { + "cliui": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", + "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", + "dev": true, + "requires": { + "string-width": "^3.1.0", + "strip-ansi": "^5.2.0", + "wrap-ansi": "^5.1.0" + } + }, + "get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true + }, + "require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", + "dev": true + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, + "yargs": { + "version": "13.3.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.0.tgz", + "integrity": "sha512-2eehun/8ALW8TLoIl7MVaRUrg+yCnenu8B4kBlRxj3GJGDKU1Og7sMXPNm1BYyM1DOJmTZ4YeN/Nwxv+8XJsUA==", + "dev": true, + "requires": { + "cliui": "^5.0.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^13.1.1" + } + }, + "yargs-parser": { + "version": "13.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.1.tgz", + "integrity": "sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ==", + "dev": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + } + } } } } diff --git a/webui/package.json b/webui/package.json index 9280222b6..423cc8e66 100644 --- a/webui/package.json +++ b/webui/package.json @@ -8,7 +8,7 @@ "scripts": { "transfer": "node dev/scripts/transfer.js", "lint": "eslint --ext .js,.vue src", - "test": "echo \"No test specified\" && exit 0", + "test-unit": "mocha-webpack --mode=production './src/**/*.spec.js'", "dev": "export APP_ENV='development' && quasar dev -m pwa", "build-quasar": "quasar build -m pwa", "build-staging": "export NODE_ENV='production' && export APP_ENV='development' && npm run build-quasar", @@ -20,8 +20,8 @@ "axios": "^0.19.0", "bowser": "^2.5.2", "chart.js": "^2.8.0", - "dot-prop": "5.2.0", - "lodash": "^4.17.15", + "dot-prop": "^5.2.0", + "lodash.isequal": "4.5.0", "moment": "^2.24.0", "quasar": "^1.4.4", "vh-check": "^2.0.5", @@ -31,11 +31,16 @@ "devDependencies": { "@quasar/app": "^1.2.4", "@vue/eslint-config-standard": "^4.0.0", + "@vue/test-utils": "^1.0.0-beta.29", "babel-eslint": "^10.0.1", + "chai": "4.2.0", "eslint": "^5.10.0", "eslint-loader": "^2.1.1", "eslint-plugin-prettier": "3.1.1", + "eslint-plugin-mocha": "6.2.1", "eslint-plugin-vue": "^5.0.0", + "mocha": "^6.2.2", + "mocha-webpack": "^2.0.0-beta.0", "node-sass": "^4.12.0", "prettier": "1.19.1", "sass-loader": "^7.1.0" diff --git a/webui/quasar.conf.js b/webui/quasar.conf.js index 1be691cf4..abe9a24ff 100644 --- a/webui/quasar.conf.js +++ b/webui/quasar.conf.js @@ -7,7 +7,6 @@ module.exports = function (ctx) { // --> boot files are part of "main.js" boot: [ '_globals', - 'lodash', 'api', '_hacks', '_init' diff --git a/webui/src/_helpers/Errors.js b/webui/src/_helpers/Errors.js index d1bc43f1e..749885076 100644 --- a/webui/src/_helpers/Errors.js +++ b/webui/src/_helpers/Errors.js @@ -1,5 +1,4 @@ import { Notify } from 'quasar' -import { APP } from './APP' class Errors { // Getters @@ -12,7 +11,7 @@ class Errors { // ------------------------------------------------------------------------ static showError (body) { - body = APP._.isString(body) ? JSON.parse(body) : body + body = typeof body === 'string' ? JSON.parse(body) : body Notify.create({ color: 'negative', position: 'top', diff --git a/webui/src/_helpers/Helps.js b/webui/src/_helpers/Helps.js index 0b378efa4..b8ba03d9e 100644 --- a/webui/src/_helpers/Helps.js +++ b/webui/src/_helpers/Helps.js @@ -1,4 +1,4 @@ -import { APP } from './APP' +import { get } from 'dot-prop' class Helps { // Getters @@ -11,7 +11,7 @@ class Helps { // ------------------------------------------------------------------------ static get (obj, prop, def = undefined) { - return APP._.get(obj, prop, def) + return get(obj, prop, def) } static hasIn (obj, prop) { diff --git a/webui/src/_helpers/Mutations.js b/webui/src/_helpers/Mutations.js new file mode 100644 index 000000000..71faeec30 --- /dev/null +++ b/webui/src/_helpers/Mutations.js @@ -0,0 +1,44 @@ +import { set, get } from 'dot-prop' + +export const withPagination = (type, opts = {}) => (state, data) => { + const { isSameContext, statePath } = opts + const currentState = get(state, statePath) + + let newState + + switch (type) { + case 'request': + newState = { + ...currentState, + loading: true + } + break + case 'success': + const { body, page } = data + newState = { + ...currentState, + items: [ + ...(isSameContext && currentState.items && page !== 1 ? currentState.items : []), + ...(body.data || []) + ], + currentPage: page, + total: isSameContext && currentState.items && page !== 1 + ? body.total + currentState.total + : body.total, + loading: false + } + break + case 'failure': + newState = { + ...currentState, + loading: false, + error: data, + endReached: data.message.includes('invalid request: page:') + } + break + } + + if (newState) { + set(state, statePath, newState) + } +} diff --git a/webui/src/_mixins/Pagination.js b/webui/src/_mixins/Pagination.js new file mode 100644 index 000000000..4c2091626 --- /dev/null +++ b/webui/src/_mixins/Pagination.js @@ -0,0 +1,74 @@ +import { get } from 'dot-prop' + +export default function PaginationMixin (opts = {}) { + const { pollingIntervalTime, rowsPerPage = 10 } = opts + let listLength = 0 + let currentPage = 1 + let currentLimit = rowsPerPage + + return { + methods: { + fetchWithInterval () { + this.initFetch({ limit: listLength }) + this.pollingInterval = setInterval( + () => { + this.fetchMore({ + limit: Math.ceil(listLength / rowsPerPage) * rowsPerPage, // round up to multiple of rowsPerPage + refresh: true + }) + }, + pollingIntervalTime + ) + }, + fetchMore ({ page = 1, limit = rowsPerPage, refresh, ...params } = {}) { + if (page === currentPage && limit === currentLimit && !refresh) { + return Promise.resolve() + } + + currentPage = page + currentLimit = limit || rowsPerPage + + const fetchMethod = get(this, opts.fetchMethod) + + return fetchMethod({ + ...params, + page, + limit: limit || rowsPerPage + }).then(res => { + listLength = page > 1 + ? listLength += res.data.length + : res.data.length + }) + }, + initFetch (params) { + const scrollerRef = get(this.$refs, opts.scrollerRef) + + if (scrollerRef) { + scrollerRef.stop() + scrollerRef.reset() + } + + return this.fetchMore({ + page: 1, + refresh: true, + ...params + }).then(() => { + if (scrollerRef) { + scrollerRef.resume() + scrollerRef.poll() + } + }) + } + }, + mounted () { + if (pollingIntervalTime) { + this.fetchWithInterval() + } else { + this.fetchMore() + } + }, + beforeDestroy () { + clearInterval(this.pollingInterval) + } + } +} diff --git a/webui/src/boot/lodash.js b/webui/src/boot/lodash.js deleted file mode 100644 index 4cf69bdd0..000000000 --- a/webui/src/boot/lodash.js +++ /dev/null @@ -1,7 +0,0 @@ -import lodash from 'lodash' - -import { APP } from '../_helpers/APP' - -export default async ({ app, Vue }) => { - Vue.prototype.$_ = app._ = APP._ = lodash -} diff --git a/webui/src/components/_commons/ChartDoughnut.vue b/webui/src/components/_commons/ChartDoughnut.vue index 060ca41f8..24b8f1f60 100644 --- a/webui/src/components/_commons/ChartDoughnut.vue +++ b/webui/src/components/_commons/ChartDoughnut.vue @@ -1,5 +1,6 @@ diff --git a/webui/src/pages/tcp/Services.vue b/webui/src/pages/tcp/Services.vue index 593c90c9f..e904f5e2e 100644 --- a/webui/src/pages/tcp/Services.vue +++ b/webui/src/pages/tcp/Services.vue @@ -27,13 +27,21 @@ diff --git a/webui/src/store/http/mutations.js b/webui/src/store/http/mutations.js index b4c7b589f..484a90d4a 100644 --- a/webui/src/store/http/mutations.js +++ b/webui/src/store/http/mutations.js @@ -1,37 +1,33 @@ +import { withPagination } from '../../_helpers/Mutations' + // ---------------------------- // Get All Routers // ---------------------------- export function getAllRoutersRequest (state) { - state.allRouters.loading = true + withPagination('request', { statePath: 'allRouters' })(state) } export function getAllRoutersSuccess (state, data) { - const { body, query = '', status = '', page } = data + const { query = '', status = '' } = data const currentState = state.allRouters + const { currentQuery = '', currentStatus = '' } = currentState - const isSameContext = currentState.currentQuery === query && currentState.currentStatus === status + const isSameContext = currentQuery === query && currentStatus === status state.allRouters = { ...state.allRouters, - items: [ - ...(isSameContext && currentState.items && page !== 1 ? currentState.items : []), - ...(body.data || []) - ], - currentPage: page, - total: body.total, - loading: false, currentQuery: query, currentStatus: status } + + withPagination('success', { + isSameContext, + statePath: 'allRouters' + })(state, data) } export function getAllRoutersFailure (state, error) { - state.allRouters = { - ...state.allRouters, - loading: false, - error, - endReached: error.message.includes('invalid request: page:') - } + withPagination('failure', { statePath: 'allRouters' })(state, error) } export function getAllRoutersClear (state) { @@ -61,36 +57,29 @@ export function getRouterByNameClear (state) { // Get All Services // ---------------------------- export function getAllServicesRequest (state) { - state.allServices.loading = true + withPagination('request', { statePath: 'allServices' })(state) } export function getAllServicesSuccess (state, data) { - const { body, query = '', status = '', page } = data + const { query = '', status = '' } = data const currentState = state.allServices const isSameContext = currentState.currentQuery === query && currentState.currentStatus === status state.allServices = { ...state.allServices, - items: [ - ...(isSameContext && currentState.items && page !== 1 ? currentState.items : []), - ...(body.data || []) - ], - currentPage: page, - total: body.total, - loading: false, currentQuery: query, currentStatus: status } + + withPagination('success', { + isSameContext, + statePath: 'allServices' + })(state, data) } export function getAllServicesFailure (state, error) { - state.allServices = { - ...state.allServices, - loading: false, - error, - endReached: error.message.includes('invalid request: page:') - } + withPagination('failure', { statePath: 'allServices' })(state, error) } export function getAllServicesClear (state) { @@ -120,36 +109,29 @@ export function getServiceByNameClear (state) { // Get All Middlewares // ---------------------------- export function getAllMiddlewaresRequest (state) { - state.allMiddlewares.loading = true + withPagination('request', { statePath: 'allMiddlewares' })(state) } export function getAllMiddlewaresSuccess (state, data) { - const { body, query = '', status = '', page } = data + const { query = '', status = '' } = data const currentState = state.allMiddlewares const isSameContext = currentState.currentQuery === query && currentState.currentStatus === status state.allMiddlewares = { ...state.allMiddlewares, - items: [ - ...(isSameContext && currentState.items && page !== 1 ? currentState.items : []), - ...(body.data || []) - ], - currentPage: page, - total: body.total, - loading: false, currentQuery: query, currentStatus: status } + + withPagination('success', { + isSameContext, + statePath: 'allMiddlewares' + })(state, data) } export function getAllMiddlewaresFailure (state, error) { - state.allMiddlewares = { - ...state.allMiddlewares, - loading: false, - error, - endReached: error.message.includes('invalid request: page:') - } + withPagination('failure', { statePath: 'allMiddlewares' })(state, error) } export function getAllMiddlewaresClear (state) { diff --git a/webui/src/store/http/mutations.spec.js b/webui/src/store/http/mutations.spec.js new file mode 100644 index 000000000..890fd1406 --- /dev/null +++ b/webui/src/store/http/mutations.spec.js @@ -0,0 +1,292 @@ +import { expect } from 'chai' +import store from './index.js' + +const { + getAllRoutersRequest, + getAllRoutersSuccess, + getAllRoutersFailure, + getAllServicesRequest, + getAllServicesSuccess, + getAllServicesFailure, + getAllMiddlewaresRequest, + getAllMiddlewaresSuccess, + getAllMiddlewaresFailure +} = store.mutations + +describe('http mutations', function () { + /* Routers */ + describe('http routers mutations', function () { + it('getAllRoutersRequest', function () { + const state = { + allRouters: { + items: [{}, {}, {}] + } + } + + getAllRoutersRequest(state) + + expect(state.allRouters.loading).to.equal(true) + expect(state.allRouters.items.length).to.equal(3) + }) + + it('getAllRoutersSuccess page 1', function () { + const state = { + allRouters: { + loading: true + } + } + + const data = { + body: { + data: [{}, {}, {}], + total: 3 + }, + query: 'test query', + status: 'warning', + page: 1 + } + + getAllRoutersSuccess(state, data) + + expect(state.allRouters.loading).to.equal(false) + expect(state.allRouters.total).to.equal(3) + expect(state.allRouters.items.length).to.equal(3) + expect(state.allRouters.currentPage).to.equal(1) + expect(state.allRouters.currentQuery).to.equal('test query') + expect(state.allRouters.currentStatus).to.equal('warning') + }) + + it('getAllRoutersSuccess page 2', function () { + const state = { + allRouters: { + loading: false, + items: [{ id: 1 }, { id: 2 }, { id: 3 }], + total: 3, + currentPage: 1, + currentQuery: 'test query', + currentStatus: 'warning' + } + } + + const data = { + body: { + data: [{ id: 4 }, { id: 5 }, { id: 6 }, { id: 7 }], + total: 4 + }, + query: 'test query', + status: 'warning', + page: 2 + } + + getAllRoutersSuccess(state, data) + + expect(state.allRouters.loading).to.equal(false) + expect(state.allRouters.total).to.equal(7) + expect(state.allRouters.items.length).to.equal(7) + expect(state.allRouters.currentPage).to.equal(2) + expect(state.allRouters.currentQuery).to.equal('test query') + expect(state.allRouters.currentStatus).to.equal('warning') + }) + + it('getAllRoutersFailing', function () { + const state = { + allRouters: { + items: [{}, {}, {}], + loading: true + } + } + + const error = { message: 'invalid request: page: 3, per_page: 10' } + + getAllRoutersFailure(state, error) + + expect(state.allRouters.loading).to.equal(false) + expect(state.allRouters.endReached).to.equal(true) + expect(state.allRouters.items.length).to.equal(3) + }) + }) + + /* Services */ + describe('http services mutations', function () { + it('getAllServicesRequest', function () { + const state = { + allServices: { + items: [{}, {}, {}] + } + } + + getAllServicesRequest(state) + + expect(state.allServices.loading).to.equal(true) + expect(state.allServices.items.length).to.equal(3) + }) + + it('getAllServicesSuccess page 1', function () { + const state = { + allServices: { + loading: true + } + } + + const data = { + body: { + data: [{}, {}, {}], + total: 3 + }, + query: 'test query', + status: 'warning', + page: 1 + } + + getAllServicesSuccess(state, data) + + expect(state.allServices.loading).to.equal(false) + expect(state.allServices.total).to.equal(3) + expect(state.allServices.items.length).to.equal(3) + expect(state.allServices.currentPage).to.equal(1) + expect(state.allServices.currentQuery).to.equal('test query') + expect(state.allServices.currentStatus).to.equal('warning') + }) + + it('getAllServicesSuccess page 2', function () { + const state = { + allServices: { + loading: false, + items: [{ id: 1 }, { id: 2 }, { id: 3 }], + total: 3, + currentPage: 1, + currentQuery: 'test query', + currentStatus: 'warning' + } + } + + const data = { + body: { + data: [{ id: 4 }, { id: 5 }, { id: 6 }, { id: 7 }], + total: 4 + }, + query: 'test query', + status: 'warning', + page: 2 + } + + getAllServicesSuccess(state, data) + + expect(state.allServices.loading).to.equal(false) + expect(state.allServices.total).to.equal(7) + expect(state.allServices.items.length).to.equal(7) + expect(state.allServices.currentPage).to.equal(2) + expect(state.allServices.currentQuery).to.equal('test query') + expect(state.allServices.currentStatus).to.equal('warning') + }) + + it('getAllServicesFailing', function () { + const state = { + allServices: { + items: [{}, {}, {}], + loading: true + } + } + + const error = { message: 'invalid request: page: 3, per_page: 10' } + + getAllServicesFailure(state, error) + + expect(state.allServices.loading).to.equal(false) + expect(state.allServices.endReached).to.equal(true) + expect(state.allServices.items.length).to.equal(3) + }) + }) + + /* Middlewares */ + describe('http middlewares mutations', function () { + it('getAllMiddlewaresRequest', function () { + const state = { + allMiddlewares: { + items: [{}, {}, {}] + } + } + + getAllMiddlewaresRequest(state) + + expect(state.allMiddlewares.loading).to.equal(true) + expect(state.allMiddlewares.items.length).to.equal(3) + }) + + it('getAllMiddlewaresSuccess page 1', function () { + const state = { + allMiddlewares: { + loading: true + } + } + + const data = { + body: { + data: [{}, {}, {}], + total: 3 + }, + query: 'test query', + status: 'warning', + page: 1 + } + + getAllMiddlewaresSuccess(state, data) + + expect(state.allMiddlewares.loading).to.equal(false) + expect(state.allMiddlewares.total).to.equal(3) + expect(state.allMiddlewares.items.length).to.equal(3) + expect(state.allMiddlewares.currentPage).to.equal(1) + expect(state.allMiddlewares.currentQuery).to.equal('test query') + expect(state.allMiddlewares.currentStatus).to.equal('warning') + }) + + it('getAllMiddlewaresSuccess page 2', function () { + const state = { + allMiddlewares: { + loading: false, + items: [{ id: 1 }, { id: 2 }, { id: 3 }], + total: 3, + currentPage: 1, + currentQuery: 'test query', + currentStatus: 'warning' + } + } + + const data = { + body: { + data: [{ id: 4 }, { id: 5 }, { id: 6 }, { id: 7 }], + total: 4 + }, + query: 'test query', + status: 'warning', + page: 2 + } + + getAllMiddlewaresSuccess(state, data) + + expect(state.allMiddlewares.loading).to.equal(false) + expect(state.allMiddlewares.total).to.equal(7) + expect(state.allMiddlewares.items.length).to.equal(7) + expect(state.allMiddlewares.currentPage).to.equal(2) + expect(state.allMiddlewares.currentQuery).to.equal('test query') + expect(state.allMiddlewares.currentStatus).to.equal('warning') + }) + + it('getAllMiddlewaresFailing', function () { + const state = { + allMiddlewares: { + items: [{}, {}, {}], + loading: true + } + } + + const error = { message: 'invalid request: page: 3, per_page: 10' } + + getAllMiddlewaresFailure(state, error) + + expect(state.allMiddlewares.loading).to.equal(false) + expect(state.allMiddlewares.endReached).to.equal(true) + expect(state.allMiddlewares.items.length).to.equal(3) + }) + }) +}) diff --git a/webui/src/store/tcp/mutations.js b/webui/src/store/tcp/mutations.js index 4ad95df19..69df42013 100644 --- a/webui/src/store/tcp/mutations.js +++ b/webui/src/store/tcp/mutations.js @@ -1,37 +1,32 @@ +import { withPagination } from '../../_helpers/Mutations' + // ---------------------------- // Get All Routers // ---------------------------- export function getAllRoutersRequest (state) { - state.allRouters.loading = true + withPagination('request', { statePath: 'allRouters' })(state) } export function getAllRoutersSuccess (state, data) { - const { body, query = '', status = '', page } = data + const { query = '', status = '' } = data const currentState = state.allRouters const isSameContext = currentState.currentQuery === query && currentState.currentStatus === status state.allRouters = { ...state.allRouters, - items: [ - ...(isSameContext && currentState.items && page !== 1 ? currentState.items : []), - ...(body.data || []) - ], - currentPage: page, - total: body.total, - loading: false, currentQuery: query, currentStatus: status } + + withPagination('success', { + isSameContext, + statePath: 'allRouters' + })(state, data) } export function getAllRoutersFailure (state, error) { - state.allRouters = { - ...state.allRouters, - loading: false, - error, - endReached: error.message.includes('invalid request: page:') - } + withPagination('failure', { statePath: 'allRouters' })(state, error) } export function getAllRoutersClear (state) { @@ -61,36 +56,29 @@ export function getRouterByNameClear (state) { // Get All Services // ---------------------------- export function getAllServicesRequest (state) { - state.allServices.loading = true + withPagination('request', { statePath: 'allServices' })(state) } export function getAllServicesSuccess (state, data) { - const { body, query = '', status = '', page } = data + const { query = '', status = '' } = data const currentState = state.allServices const isSameContext = currentState.currentQuery === query && currentState.currentStatus === status state.allServices = { ...state.allServices, - items: [ - ...(isSameContext && currentState.items && page !== 1 ? currentState.items : []), - ...(body.data || []) - ], - currentPage: page, - total: body.total, - loading: false, currentQuery: query, currentStatus: status } + + withPagination('success', { + isSameContext, + statePath: 'allServices' + })(state, data) } export function getAllServicesFailure (state, error) { - state.allServices = { - ...state.allServices, - loading: false, - error, - endReached: error.message.includes('invalid request: page:') - } + withPagination('failure', { statePath: 'allServices' })(state, error) } export function getAllServicesClear (state) { diff --git a/webui/src/store/tcp/mutations.spec.js b/webui/src/store/tcp/mutations.spec.js new file mode 100644 index 000000000..cd955b806 --- /dev/null +++ b/webui/src/store/tcp/mutations.spec.js @@ -0,0 +1,197 @@ +import { expect } from 'chai' +import store from './index.js' + +const { + getAllRoutersRequest, + getAllRoutersSuccess, + getAllRoutersFailure, + getAllServicesRequest, + getAllServicesSuccess, + getAllServicesFailure +} = store.mutations + +describe('tcp mutations', function () { + /* Routers */ + describe('tcp routers mutations', function () { + it('getAllRoutersRequest', function () { + const state = { + allRouters: { + items: [{}, {}, {}] + } + } + + getAllRoutersRequest(state) + + expect(state.allRouters.loading).to.equal(true) + expect(state.allRouters.items.length).to.equal(3) + }) + + it('getAllRoutersSuccess page 1', function () { + const state = { + allRouters: { + loading: true + } + } + + const data = { + body: { + data: [{}, {}, {}], + total: 3 + }, + query: 'test query', + status: 'warning', + page: 1 + } + + getAllRoutersSuccess(state, data) + + expect(state.allRouters.loading).to.equal(false) + expect(state.allRouters.total).to.equal(3) + expect(state.allRouters.items.length).to.equal(3) + expect(state.allRouters.currentPage).to.equal(1) + expect(state.allRouters.currentQuery).to.equal('test query') + expect(state.allRouters.currentStatus).to.equal('warning') + }) + + it('getAllRoutersSuccess page 2', function () { + const state = { + allRouters: { + loading: false, + items: [{ id: 1 }, { id: 2 }, { id: 3 }], + total: 3, + currentPage: 1, + currentQuery: 'test query', + currentStatus: 'warning' + } + } + + const data = { + body: { + data: [{ id: 4 }, { id: 5 }, { id: 6 }, { id: 7 }], + total: 4 + }, + query: 'test query', + status: 'warning', + page: 2 + } + + getAllRoutersSuccess(state, data) + + expect(state.allRouters.loading).to.equal(false) + expect(state.allRouters.total).to.equal(7) + expect(state.allRouters.items.length).to.equal(7) + expect(state.allRouters.currentPage).to.equal(2) + expect(state.allRouters.currentQuery).to.equal('test query') + expect(state.allRouters.currentStatus).to.equal('warning') + }) + + it('getAllRoutersFailing', function () { + const state = { + allRouters: { + items: [{}, {}, {}], + loading: true + } + } + + const error = { message: 'invalid request: page: 3, per_page: 10' } + + getAllRoutersFailure(state, error) + + expect(state.allRouters.loading).to.equal(false) + expect(state.allRouters.endReached).to.equal(true) + expect(state.allRouters.items.length).to.equal(3) + }) + }) + + /* Services */ + describe('tcp services mutations', function () { + it('getAllServicesRequest', function () { + const state = { + allServices: { + items: [{}, {}, {}] + } + } + + getAllServicesRequest(state) + + expect(state.allServices.loading).to.equal(true) + expect(state.allServices.items.length).to.equal(3) + }) + + it('getAllServicesSuccess page 1', function () { + const state = { + allServices: { + loading: true + } + } + + const data = { + body: { + data: [{}, {}, {}], + total: 3 + }, + query: 'test query', + status: 'warning', + page: 1 + } + + getAllServicesSuccess(state, data) + + expect(state.allServices.loading).to.equal(false) + expect(state.allServices.total).to.equal(3) + expect(state.allServices.items.length).to.equal(3) + expect(state.allServices.currentPage).to.equal(1) + expect(state.allServices.currentQuery).to.equal('test query') + expect(state.allServices.currentStatus).to.equal('warning') + }) + + it('getAllServicesSuccess page 2', function () { + const state = { + allServices: { + loading: false, + items: [{ id: 1 }, { id: 2 }, { id: 3 }], + total: 3, + currentPage: 1, + currentQuery: 'test query', + currentStatus: 'warning' + } + } + + const data = { + body: { + data: [{ id: 4 }, { id: 5 }, { id: 6 }, { id: 7 }], + total: 4 + }, + query: 'test query', + status: 'warning', + page: 2 + } + + getAllServicesSuccess(state, data) + + expect(state.allServices.loading).to.equal(false) + expect(state.allServices.total).to.equal(7) + expect(state.allServices.items.length).to.equal(7) + expect(state.allServices.currentPage).to.equal(2) + expect(state.allServices.currentQuery).to.equal('test query') + expect(state.allServices.currentStatus).to.equal('warning') + }) + + it('getAllServicesFailing', function () { + const state = { + allServices: { + items: [{}, {}, {}], + loading: true + } + } + + const error = { message: 'invalid request: page: 3, per_page: 10' } + + getAllServicesFailure(state, error) + + expect(state.allServices.loading).to.equal(false) + expect(state.allServices.endReached).to.equal(true) + expect(state.allServices.items.length).to.equal(3) + }) + }) +})