From 942b2240a7cc583bb4a676f9234b9077f20ca4d8 Mon Sep 17 00:00:00 2001 From: orangemug Date: Fri, 5 Jan 2018 17:45:55 +0000 Subject: [PATCH 01/48] Added more webdriver tests testing against a real browser. --- .babelrc | 11 +- .circleci/config.yml | 27 + .gitignore | 2 + circle.yml | 6 - config/wdio.conf.js | 16 +- config/webpack.production.config.js | 10 +- package-lock.json | 1177 ++++++++++------- package.json | 23 +- src/components/App.jsx | 35 +- src/components/Button.jsx | 2 + src/components/Toolbar.jsx | 11 +- src/components/fields/FunctionSpecField.jsx | 3 +- src/components/fields/SpecField.jsx | 119 +- src/components/filter/FilterEditor.jsx | 3 +- src/components/icons/LayerIcon.jsx | 1 - src/components/inputs/AutocompleteInput.jsx | 10 +- src/components/inputs/InputBlock.jsx | 2 + src/components/inputs/SelectInput.jsx | 2 + src/components/inputs/StringInput.jsx | 11 +- src/components/layers/CommentBlock.jsx | 6 +- src/components/layers/JSONEditor.jsx | 1 - src/components/layers/LayerEditor.jsx | 8 +- src/components/layers/LayerEditorGroup.jsx | 2 + src/components/layers/LayerIdBlock.jsx | 5 +- src/components/layers/LayerList.jsx | 2 + src/components/layers/LayerListGroup.jsx | 2 + src/components/layers/LayerListItem.jsx | 7 +- src/components/layers/LayerSourceBlock.jsx | 6 +- .../layers/LayerSourceLayerBlock.jsx | 5 +- src/components/layers/LayerTypeBlock.jsx | 5 +- src/components/layers/MaxZoomBlock.jsx | 4 +- src/components/layers/MinZoomBlock.jsx | 4 +- src/components/modals/AddModal.jsx | 16 +- src/components/modals/ExportModal.jsx | 2 +- src/components/modals/Modal.jsx | 6 +- src/components/modals/OpenModal.jsx | 5 +- src/components/modals/SettingsModal.jsx | 8 + src/libs/debug.js | 44 + src/styles/index.scss | 12 + test/artifacts.js | 39 + test/example-style.json | 12 + test/functional/advanced.js | 1077 +++++++++++++++ test/geojson-server.js | 93 ++ test/sources/example.json | 15 + test/sources/index.js | 3 + test/specs/simple.js | 15 - test/wd-helper.js | 6 + 47 files changed, 2244 insertions(+), 637 deletions(-) create mode 100644 .circleci/config.yml delete mode 100644 circle.yml create mode 100644 src/libs/debug.js create mode 100644 test/artifacts.js create mode 100644 test/example-style.json create mode 100644 test/functional/advanced.js create mode 100644 test/geojson-server.js create mode 100644 test/sources/example.json create mode 100644 test/sources/index.js delete mode 100644 test/specs/simple.js create mode 100644 test/wd-helper.js diff --git a/.babelrc b/.babelrc index a3b237f0..adae42de 100644 --- a/.babelrc +++ b/.babelrc @@ -1,4 +1,13 @@ { "presets": ["env", "react"], - "plugins": ["transform-object-rest-spread", "transform-class-properties"] + "plugins": ["transform-object-rest-spread", "transform-class-properties"], + "env": { + "test": { + "plugins": [ + ["istanbul", { + exclude: ["node_modules/**", "test/**"] + }] + ] + } + } } diff --git a/.circleci/config.yml b/.circleci/config.yml new file mode 100644 index 00000000..f78c4ee5 --- /dev/null +++ b/.circleci/config.yml @@ -0,0 +1,27 @@ +version: 2 +jobs: + build: + docker: + # specify the version you desire here + - image: node:8 + - image: selenium/standalone-chrome:3.1.0 + working_directory: ~/repo + steps: + - checkout + - run: + name: "Create artifacts directory" + command: mkdir /tmp/artifacts + - restore_cache: + key: v1-dependencies-{{ checksum "package.json" }} + + - run: npm install + + - save_cache: + paths: + - node_modules + key: v1-dependencies-{{ checksum "package.json" }} + + - run: mkdir -p /tmp/artifacts/logs + - run: DOCKER_HOST=localhost npm test + - run: npm run build + - run: ./node_modules/.bin/istanbul report --include /tmp/artifacts/coverage/coverage.json --dir /tmp/artifacts/coverage html lcov diff --git a/.gitignore b/.gitignore index 99105f43..83a8308f 100644 --- a/.gitignore +++ b/.gitignore @@ -30,3 +30,5 @@ node_modules # Ignore build files public +/errorShots +/old diff --git a/circle.yml b/circle.yml deleted file mode 100644 index 5e66cd33..00000000 --- a/circle.yml +++ /dev/null @@ -1,6 +0,0 @@ -machine: - node: - version: 6 -test: - post: - - npm run build diff --git a/config/wdio.conf.js b/config/wdio.conf.js index f0d33317..41fe910d 100644 --- a/config/wdio.conf.js +++ b/config/wdio.conf.js @@ -2,36 +2,36 @@ var webpack = require("webpack"); var WebpackDevServer = require("webpack-dev-server"); var webpackConfig = require("./webpack.production.config"); var testConfig = require("../test/config/specs"); +var artifacts = require("../test/artifacts"); +var isDocker = require("is-docker"); var server; +var SCREENSHOT_PATH = artifacts.pathSync("screenshots"); exports.config = { specs: [ - './test/specs/**/*.js' + './test/functional/advanced.js' ], exclude: [ ], maxInstances: 10, capabilities: [{ maxInstances: 5, - browserName: 'firefox' + browserName: 'chrome' }], sync: true, logLevel: 'verbose', coloredLogs: true, bail: 0, - screenshotPath: './errorShots/', + screenshotPath: SCREENSHOT_PATH, + host: (isDocker() ? process.env.DOCKER_HOST : "127.0.0.1"), baseUrl: 'http://localhost', waitforTimeout: 10000, connectionRetryTimeout: 90000, connectionRetryCount: 3, - services: ['phantomjs'], framework: 'mocha', reporters: ['spec'], - phantomjsOpts: { - webdriverLogfile: 'phantomjs.log' - }, mochaOpts: { ui: 'bdd', // Because we don't know how long the initial build will take... @@ -43,6 +43,6 @@ exports.config = { server.listen(testConfig.port); }, onComplete: function(exitCode) { - server.close(); + server.close() } } diff --git a/config/webpack.production.config.js b/config/webpack.production.config.js index 01a5c4e9..383bb7d5 100644 --- a/config/webpack.production.config.js +++ b/config/webpack.production.config.js @@ -1,4 +1,3 @@ - var webpack = require('webpack'); var path = require('path'); var loaders = require('./webpack.loaders'); @@ -7,14 +6,9 @@ var HtmlWebpackPlugin = require('html-webpack-plugin'); var WebpackCleanupPlugin = require('webpack-cleanup-plugin'); var BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin; var CopyWebpackPlugin = require('copy-webpack-plugin'); +var artifacts = require("../test/artifacts"); -var OUTPATH; -if(process.env.CIRCLE_ARTIFACTS) { - OUTPATH = path.join(process.env.CIRCLE_ARTIFACTS, "build"); -} -else { - OUTPATH = path.join(__dirname, '..', 'public'); -} +var OUTPATH = artifacts.pathSync("/build"); module.exports = { entry: { diff --git a/package-lock.json b/package-lock.json index f539a8f1..51652f84 100644 --- a/package-lock.json +++ b/package-lock.json @@ -908,6 +908,17 @@ "babel-runtime": "6.26.0" } }, + "babel-plugin-istanbul": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-4.1.5.tgz", + "integrity": "sha1-Z2DN2Xf0EdPhdbsGTyvDJ9mbK24=", + "dev": true, + "requires": { + "find-up": "2.1.0", + "istanbul-lib-instrument": "1.9.1", + "test-exclude": "4.1.1" + } + }, "babel-plugin-syntax-async-functions": { "version": "6.13.0", "resolved": "https://registry.npmjs.org/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz", @@ -1879,6 +1890,45 @@ "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=" }, + "cacache": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-10.0.1.tgz", + "integrity": "sha512-dRHYcs9LvG9cHgdPzjiI+/eS7e1xRhULrcyOx04RZQsszNJXU2SL9CyG60yLnge282Qq5nwTv+ieK2fH+WPZmA==", + "dev": true, + "requires": { + "bluebird": "3.5.1", + "chownr": "1.0.1", + "glob": "7.1.2", + "graceful-fs": "4.1.11", + "lru-cache": "4.1.1", + "mississippi": "1.3.0", + "mkdirp": "0.5.1", + "move-concurrently": "1.0.1", + "promise-inflight": "1.0.1", + "rimraf": "2.6.2", + "ssri": "5.0.0", + "unique-filename": "1.1.0", + "y18n": "3.2.1" + }, + "dependencies": { + "lru-cache": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.1.tgz", + "integrity": "sha512-q4spe4KTfsAS1SUHLO0wz8Qiyf1+vMIAgpRYioFYDMNqKfHQbg+AVDH3i4fvpl71/P1L0dBl+fQi+P37UYf0ew==", + "dev": true, + "requires": { + "pseudomap": "1.0.2", + "yallist": "2.1.2" + } + }, + "yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", + "dev": true + } + } + }, "call-matcher": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/call-matcher/-/call-matcher-1.0.1.tgz", @@ -2069,6 +2119,12 @@ "readdirp": "2.1.0" } }, + "chownr": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.0.1.tgz", + "integrity": "sha1-4qdQQqlVGQi+vSW4Uj1fl2nXkYE=", + "dev": true + }, "cipher-base": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", @@ -2238,9 +2294,9 @@ "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" }, "codemirror": { - "version": "5.32.0", - "resolved": "https://registry.npmjs.org/codemirror/-/codemirror-5.32.0.tgz", - "integrity": "sha512-95OxAlYiigW0g4n4ixFdavG07clJGILp3MvHh2pKR3FvyrTuHHvqtKSVbrV3/Jz6o0YqGvyCDLDTbH4h6ciaSw==" + "version": "5.33.0", + "resolved": "https://registry.npmjs.org/codemirror/-/codemirror-5.33.0.tgz", + "integrity": "sha512-HT6PKVqkwpzwB3jl5hXFoQteEWXbSWMzG3Z8RVYlx8hZwCOLCy4NU7vkSB3dYX3e6ORwRfGw4uFOXaw4rn/a9Q==" }, "color": { "version": "2.0.1", @@ -2355,15 +2411,6 @@ "resolved": "https://registry.npmjs.org/colors/-/colors-1.1.2.tgz", "integrity": "sha1-FopHAXVran9RoSzgyXv6KMCE7WM=" }, - "combine-lists": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/combine-lists/-/combine-lists-1.0.1.tgz", - "integrity": "sha1-RYwH4J4NkA/Ci3Cj/sLazR0st/Y=", - "dev": true, - "requires": { - "lodash": "4.17.4" - } - }, "combined-stream": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz", @@ -2536,6 +2583,20 @@ "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=", "dev": true }, + "copy-concurrently": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/copy-concurrently/-/copy-concurrently-1.0.5.tgz", + "integrity": "sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A==", + "dev": true, + "requires": { + "aproba": "1.2.0", + "fs-write-stream-atomic": "1.0.10", + "iferr": "0.1.5", + "mkdirp": "0.5.1", + "rimraf": "2.6.2", + "run-queue": "1.0.3" + } + }, "copy-to-clipboard": { "version": "3.0.8", "resolved": "https://registry.npmjs.org/copy-to-clipboard/-/copy-to-clipboard-3.0.8.tgz", @@ -2545,19 +2606,37 @@ } }, "copy-webpack-plugin": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-4.2.3.tgz", - "integrity": "sha512-cL/Wl3Y1QmmKThl/mWeGB+HH3YH+25tn8nhqEGsZda4Yn7GqGnDZ+TbeKJ7A6zvrxyNhhuviYAxn/tCyyAqh8Q==", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-4.3.1.tgz", + "integrity": "sha512-xlcFiW/U7KrpS6dFuWq3r8Wb7koJx7QVc7LDFCosqkikaVSxkaYOnwDLwilbjrszZ0LYZXThDAJKcQCSrvdShQ==", "dev": true, "requires": { - "bluebird": "3.5.1", - "glob": "7.1.2", + "cacache": "10.0.1", + "find-cache-dir": "1.0.0", + "globby": "7.1.1", "is-glob": "4.0.0", "loader-utils": "0.2.17", "lodash": "4.17.4", - "minimatch": "3.0.4" + "minimatch": "3.0.4", + "p-limit": "1.1.0", + "pify": "3.0.0", + "serialize-javascript": "1.4.0" }, "dependencies": { + "globby": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/globby/-/globby-7.1.1.tgz", + "integrity": "sha1-+yzP+UAfhgCUXfral0QMypcrhoA=", + "dev": true, + "requires": { + "array-union": "1.0.2", + "dir-glob": "2.0.0", + "glob": "7.1.2", + "ignore": "3.3.7", + "pify": "3.0.0", + "slash": "1.0.0" + } + }, "is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", @@ -2597,6 +2676,16 @@ "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" }, + "cors": { + "version": "2.8.4", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.4.tgz", + "integrity": "sha1-K9OB8usgECAQXNUOpZ2mMJBpRoY=", + "dev": true, + "requires": { + "object-assign": "4.1.1", + "vary": "1.1.2" + } + }, "cosmiconfig": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-2.2.2.tgz", @@ -2672,6 +2761,16 @@ "sha.js": "2.4.9" } }, + "create-react-class": { + "version": "15.6.2", + "resolved": "https://registry.npmjs.org/create-react-class/-/create-react-class-15.6.2.tgz", + "integrity": "sha1-zx7RXxKq1/FO9fLf4F5sQvke8Co=", + "requires": { + "fbjs": "0.8.16", + "loose-envify": "1.3.1", + "object-assign": "4.1.1" + } + }, "cross-spawn": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", @@ -2992,6 +3091,12 @@ "resolved": "https://registry.npmjs.org/custom-event/-/custom-event-1.0.1.tgz", "integrity": "sha1-XQKkaFCt8bSjF5RqOSj8y1v9BCU=" }, + "cyclist": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-0.2.2.tgz", + "integrity": "sha1-GzN5LhHpFKL9bW7WRHRkRE5fpkA=", + "dev": true + }, "d": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/d/-/d-1.0.0.tgz", @@ -3194,6 +3299,27 @@ "randombytes": "2.0.5" } }, + "dir-glob": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-2.0.0.tgz", + "integrity": "sha512-37qirFDz8cA5fimp9feo43fSuRo2gHwaIn6dXL8Ber1dGwUosDrGZeCCXq57WnIqE4aQ+u3eQZzsk1yOzhdwag==", + "dev": true, + "requires": { + "arrify": "1.0.1", + "path-type": "3.0.0" + }, + "dependencies": { + "path-type": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "dev": true, + "requires": { + "pify": "3.0.0" + } + } + } + }, "dns-equal": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz", @@ -3446,6 +3572,18 @@ } } }, + "duplexify": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.5.1.tgz", + "integrity": "sha512-j5goxHTwVED1Fpe5hh3q9R93Kip0Bg2KVAt4f8CEYM3UEwYcPSvWbXaUQOzdX/HtiNomipv+gU7ASQPDbV7pGQ==", + "dev": true, + "requires": { + "end-of-stream": "1.4.0", + "inherits": "2.0.3", + "readable-stream": "2.3.3", + "stream-shift": "1.0.0" + } + }, "earcut": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/earcut/-/earcut-2.1.2.tgz", @@ -4543,6 +4681,16 @@ "vlq": "0.2.3" } }, + "flush-write-stream": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.0.2.tgz", + "integrity": "sha1-yBuQ2HRnZvGmCaRoCZRsRd2K5Bc=", + "dev": true, + "requires": { + "inherits": "2.0.3", + "readable-stream": "2.3.3" + } + }, "follow-redirects": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.0.0.tgz", @@ -4605,13 +4753,14 @@ "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.0.tgz", "integrity": "sha1-9HTKXmqSRtb9jglTz6m5yAWvp44=" }, - "fs-access": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/fs-access/-/fs-access-1.0.1.tgz", - "integrity": "sha1-1qh/JiJxzv6+wwxVNAf7mV2od3o=", + "from2": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", + "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=", "dev": true, "requires": { - "null-check": "1.0.0" + "inherits": "2.0.3", + "readable-stream": "2.3.3" } }, "fs-extra": { @@ -4624,6 +4773,18 @@ "universalify": "0.1.1" } }, + "fs-write-stream-atomic": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz", + "integrity": "sha1-tH31NJPvkR33VzHnCp3tAYnbQMk=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "iferr": "0.1.5", + "imurmurhash": "0.1.4", + "readable-stream": "2.3.3" + } + }, "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -4681,6 +4842,21 @@ "globule": "1.2.0" } }, + "generate-function": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.0.0.tgz", + "integrity": "sha1-aFj+fAlpt9TpCTM3ZHrHn2DfvnQ=", + "dev": true + }, + "generate-object-property": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz", + "integrity": "sha1-nA4cQDCM6AT0eDYYuTf6iPmdUNA=", + "dev": true, + "requires": { + "is-property": "1.0.2" + } + }, "geojson-area": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/geojson-area/-/geojson-area-0.1.0.tgz", @@ -5433,6 +5609,12 @@ "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.8.tgz", "integrity": "sha1-vjPUCsEO8ZJnAfbwii2G+/0a0+Q=" }, + "iferr": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/iferr/-/iferr-0.1.5.tgz", + "integrity": "sha1-xg7taebY/bazEEofy8ocGS3FtQE=", + "dev": true + }, "ignore": { "version": "3.3.7", "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.7.tgz", @@ -5676,6 +5858,12 @@ "integrity": "sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE=", "dev": true }, + "is-docker": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-1.1.0.tgz", + "integrity": "sha1-8EN01O7lMQ6ajhE78UlUEeRhdqE=", + "dev": true + }, "is-dotfile": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz", @@ -5738,6 +5926,18 @@ "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz", "integrity": "sha1-Mlj7afeMFNW4FdZkM2tM/7ZEFZE=" }, + "is-my-json-valid": { + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.16.1.tgz", + "integrity": "sha512-ochPsqWS1WXj8ZnMIV0vnNXooaMhp7cyL4FMSIPKTtnV0Ha/T19G2b9kkhcNsabV9bxYkze7/aLZJb/bYuFduQ==", + "dev": true, + "requires": { + "generate-function": "2.0.0", + "generate-object-property": "1.2.0", + "jsonpointer": "4.0.1", + "xtend": "4.0.1" + } + }, "is-number": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", @@ -5809,6 +6009,12 @@ "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=", "dev": true }, + "is-property": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", + "integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ=", + "dev": true + }, "is-regex": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", @@ -5923,6 +6129,146 @@ "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" }, + "istanbul": { + "version": "0.4.5", + "resolved": "https://registry.npmjs.org/istanbul/-/istanbul-0.4.5.tgz", + "integrity": "sha1-ZcfXPUxNqE1POsMQuRj7C4Azczs=", + "dev": true, + "requires": { + "abbrev": "1.0.9", + "async": "1.5.2", + "escodegen": "1.8.1", + "esprima": "2.7.3", + "glob": "5.0.15", + "handlebars": "4.0.10", + "js-yaml": "3.7.0", + "mkdirp": "0.5.1", + "nopt": "3.0.6", + "once": "1.4.0", + "resolve": "1.1.7", + "supports-color": "3.2.3", + "which": "1.3.0", + "wordwrap": "1.0.0" + }, + "dependencies": { + "abbrev": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz", + "integrity": "sha1-kbR5JYinc4wl813W9jdSovh3YTU=", + "dev": true + }, + "async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", + "dev": true + }, + "escodegen": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.8.1.tgz", + "integrity": "sha1-WltTr0aTEQvrsIZ6o0MN07cKEBg=", + "dev": true, + "requires": { + "esprima": "2.7.3", + "estraverse": "1.9.3", + "esutils": "2.0.2", + "optionator": "0.8.2", + "source-map": "0.2.0" + } + }, + "esprima": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", + "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=", + "dev": true + }, + "estraverse": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.9.3.tgz", + "integrity": "sha1-r2fy3JIlgkFZUJJgkaQAXSnJu0Q=", + "dev": true + }, + "esutils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", + "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", + "dev": true + }, + "glob": { + "version": "5.0.15", + "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", + "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", + "dev": true, + "requires": { + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", + "dev": true + }, + "resolve": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", + "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", + "dev": true + }, + "source-map": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.2.0.tgz", + "integrity": "sha1-2rc/vPwrqBm03gO9b26qSBZLP50=", + "dev": true, + "optional": true, + "requires": { + "amdefine": "1.0.1" + } + }, + "supports-color": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "dev": true, + "requires": { + "has-flag": "1.0.0" + } + } + } + }, + "istanbul-lib-coverage": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-1.1.1.tgz", + "integrity": "sha512-0+1vDkmzxqJIn5rcoEqapSB4DmPxE31EtI2dF2aCkV5esN9EWHxZ0dwgDClivMXJqE7zaYQxq30hj5L0nlTN5Q==", + "dev": true + }, + "istanbul-lib-instrument": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-1.9.1.tgz", + "integrity": "sha512-RQmXeQ7sphar7k7O1wTNzVczF9igKpaeGQAG9qR2L+BS4DCJNTI9nytRmIVYevwO0bbq+2CXvJmYDuz0gMrywA==", + "dev": true, + "requires": { + "babel-generator": "6.26.0", + "babel-template": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0", + "babylon": "6.18.0", + "istanbul-lib-coverage": "1.1.1", + "semver": "5.4.1" + }, + "dependencies": { + "semver": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", + "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==", + "dev": true + } + } + }, "js-base64": { "version": "2.3.2", "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.3.2.tgz", @@ -6134,6 +6480,12 @@ "integrity": "sha1-MwVCrT8KZUZlt3jz6y2an6UHrGQ=", "dev": true }, + "jsonpointer": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-4.0.1.tgz", + "integrity": "sha1-T9kss04OnbPInIYi7PUfm5eMbLk=", + "dev": true + }, "jsprim": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", @@ -6166,325 +6518,6 @@ "resolved": "https://registry.npmjs.org/junk/-/junk-2.1.0.tgz", "integrity": "sha1-9DG0t/By3FAKXxDOf07HGTDnATQ=" }, - "karma": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/karma/-/karma-1.7.1.tgz", - "integrity": "sha512-k5pBjHDhmkdaUccnC7gE3mBzZjcxyxYsYVaqiL2G5AqlfLyBO5nw2VdNK+O16cveEPd/gIOWULH7gkiYYwVNHg==", - "dev": true, - "requires": { - "bluebird": "3.5.1", - "body-parser": "1.18.2", - "chokidar": "1.7.0", - "colors": "1.1.2", - "combine-lists": "1.0.1", - "connect": "3.6.5", - "core-js": "2.5.1", - "di": "0.0.1", - "dom-serialize": "2.2.1", - "expand-braces": "0.1.2", - "glob": "7.1.2", - "graceful-fs": "4.1.11", - "http-proxy": "1.16.2", - "isbinaryfile": "3.0.2", - "lodash": "3.10.1", - "log4js": "0.6.38", - "mime": "1.3.4", - "minimatch": "3.0.4", - "optimist": "0.6.1", - "qjobs": "1.1.5", - "range-parser": "1.2.0", - "rimraf": "2.6.2", - "safe-buffer": "5.1.1", - "socket.io": "1.7.3", - "source-map": "0.5.7", - "tmp": "0.0.31", - "useragent": "2.2.1" - }, - "dependencies": { - "component-emitter": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.1.2.tgz", - "integrity": "sha1-KWWU8nU9qmOZbSrwjRWpURbJrsM=", - "dev": true - }, - "debug": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.3.3.tgz", - "integrity": "sha1-QMRT5n5uE8kB3ewxeviYbNqe/4w=", - "dev": true, - "requires": { - "ms": "0.7.2" - } - }, - "engine.io": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-1.8.3.tgz", - "integrity": "sha1-jef5eJXSDTm4X4ju7nd7K9QrE9Q=", - "dev": true, - "requires": { - "accepts": "1.3.3", - "base64id": "1.0.0", - "cookie": "0.3.1", - "debug": "2.3.3", - "engine.io-parser": "1.3.2", - "ws": "1.1.2" - } - }, - "engine.io-client": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-1.8.3.tgz", - "integrity": "sha1-F5jtk0USRkU9TG9jXXogH+lA1as=", - "dev": true, - "requires": { - "component-emitter": "1.2.1", - "component-inherit": "0.0.3", - "debug": "2.3.3", - "engine.io-parser": "1.3.2", - "has-cors": "1.1.0", - "indexof": "0.0.1", - "parsejson": "0.0.3", - "parseqs": "0.0.5", - "parseuri": "0.0.5", - "ws": "1.1.2", - "xmlhttprequest-ssl": "1.5.3", - "yeast": "0.1.2" - }, - "dependencies": { - "component-emitter": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", - "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=", - "dev": true - } - } - }, - "engine.io-parser": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-1.3.2.tgz", - "integrity": "sha1-k3sHnwAH0Ik+xW1GyyILjLQ1Igo=", - "dev": true, - "requires": { - "after": "0.8.2", - "arraybuffer.slice": "0.0.6", - "base64-arraybuffer": "0.1.5", - "blob": "0.0.4", - "has-binary": "0.1.7", - "wtf-8": "1.0.0" - } - }, - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "lodash": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz", - "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=", - "dev": true - }, - "ms": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.2.tgz", - "integrity": "sha1-riXPJRKziFodldfwN4aNhDESR2U=", - "dev": true - }, - "object-assign": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.0.tgz", - "integrity": "sha1-ejs9DpgGPUP0wD8uiubNUahog6A=", - "dev": true - }, - "socket.io": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-1.7.3.tgz", - "integrity": "sha1-uK+cq6AJSeVo42nxMn6pvp6iRhs=", - "dev": true, - "requires": { - "debug": "2.3.3", - "engine.io": "1.8.3", - "has-binary": "0.1.7", - "object-assign": "4.1.0", - "socket.io-adapter": "0.5.0", - "socket.io-client": "1.7.3", - "socket.io-parser": "2.3.1" - } - }, - "socket.io-adapter": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-0.5.0.tgz", - "integrity": "sha1-y21LuL7IHhB4uZZ3+c7QBGBmu4s=", - "dev": true, - "requires": { - "debug": "2.3.3", - "socket.io-parser": "2.3.1" - } - }, - "socket.io-client": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-1.7.3.tgz", - "integrity": "sha1-sw6GqhDV7zVGYBwJzeR2Xjgdo3c=", - "dev": true, - "requires": { - "backo2": "1.0.2", - "component-bind": "1.0.0", - "component-emitter": "1.2.1", - "debug": "2.3.3", - "engine.io-client": "1.8.3", - "has-binary": "0.1.7", - "indexof": "0.0.1", - "object-component": "0.0.3", - "parseuri": "0.0.5", - "socket.io-parser": "2.3.1", - "to-array": "0.1.4" - }, - "dependencies": { - "component-emitter": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", - "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=", - "dev": true - } - } - }, - "socket.io-parser": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-2.3.1.tgz", - "integrity": "sha1-3VMgJRA85Clpcya+/WQAX8/ltKA=", - "dev": true, - "requires": { - "component-emitter": "1.1.2", - "debug": "2.2.0", - "isarray": "0.0.1", - "json3": "3.3.2" - }, - "dependencies": { - "debug": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", - "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", - "dev": true, - "requires": { - "ms": "0.7.1" - } - }, - "ms": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", - "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", - "dev": true - } - } - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - }, - "ultron": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.0.2.tgz", - "integrity": "sha1-rOEWq1V80Zc4ak6I9GhTeMiy5Po=", - "dev": true - }, - "ws": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/ws/-/ws-1.1.2.tgz", - "integrity": "sha1-iiRPoFJAHgjJiGz0SoUYnh/UBn8=", - "dev": true, - "requires": { - "options": "0.0.6", - "ultron": "1.0.2" - } - }, - "xmlhttprequest-ssl": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.3.tgz", - "integrity": "sha1-GFqIjATspGw+QHDZn3tJ3jUomS0=", - "dev": true - } - } - }, - "karma-chrome-launcher": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/karma-chrome-launcher/-/karma-chrome-launcher-2.2.0.tgz", - "integrity": "sha512-uf/ZVpAabDBPvdPdveyk1EPgbnloPvFFGgmRhYLTDH7gEB4nZdSBk8yTU47w1g/drLSx5uMOkjKk7IWKfWg/+w==", - "dev": true, - "requires": { - "fs-access": "1.0.1", - "which": "1.3.0" - } - }, - "karma-firefox-launcher": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/karma-firefox-launcher/-/karma-firefox-launcher-1.0.1.tgz", - "integrity": "sha1-zlj0fCATqIFW1VpdYTN8CZz1u1E=", - "dev": true - }, - "karma-mocha": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/karma-mocha/-/karma-mocha-1.3.0.tgz", - "integrity": "sha1-7qrH/8DiAetjxGdEDStpx883eL8=", - "dev": true, - "requires": { - "minimist": "1.2.0" - }, - "dependencies": { - "minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true - } - } - }, - "karma-webpack": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/karma-webpack/-/karma-webpack-2.0.6.tgz", - "integrity": "sha512-dcKvtiW00caWrceCKwIvlKwHQu8zI+e3zWZYDLk7kr7nl1lYSp8uP+8fQoBvRCnZiPUGuwU5Psm20NbEIn7KlA==", - "dev": true, - "requires": { - "async": "0.9.2", - "loader-utils": "0.2.17", - "lodash": "3.10.1", - "source-map": "0.5.7", - "webpack-dev-middleware": "1.12.0" - }, - "dependencies": { - "async": { - "version": "0.9.2", - "resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz", - "integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0=", - "dev": true - }, - "loader-utils": { - "version": "0.2.17", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-0.2.17.tgz", - "integrity": "sha1-+G5jdNQyBabmxg6RlvF8Apm/s0g=", - "dev": true, - "requires": { - "big.js": "3.2.0", - "emojis-list": "2.1.0", - "json5": "0.5.1", - "object-assign": "4.1.1" - } - }, - "lodash": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz", - "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=", - "dev": true - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - } - } - }, "kdbush": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/kdbush/-/kdbush-1.0.1.tgz", @@ -6692,16 +6725,6 @@ "resolved": "https://registry.npmjs.org/lodash._bindcallback/-/lodash._bindcallback-3.0.1.tgz", "integrity": "sha1-5THCdkTPi1epnhftlbNcdIeJOS4=" }, - "lodash._createcompounder": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lodash._createcompounder/-/lodash._createcompounder-3.0.0.tgz", - "integrity": "sha1-XdLLVTctbnDg4jkvsjBNZjEJEHU=", - "dev": true, - "requires": { - "lodash.deburr": "3.2.0", - "lodash.words": "3.2.0" - } - }, "lodash._getnative": { "version": "3.9.1", "resolved": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz", @@ -6713,12 +6736,6 @@ "integrity": "sha1-UgOte6Ql+uhCRg5pbbnPPmqsBXw=", "dev": true }, - "lodash._root": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/lodash._root/-/lodash._root-3.0.1.tgz", - "integrity": "sha1-+6HEUkwZ7ppfgTa0YJ8BfPTe1pI=", - "dev": true - }, "lodash.assign": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-4.2.0.tgz", @@ -6752,15 +6769,6 @@ "lodash._isiterateecall": "3.0.9" } }, - "lodash.deburr": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/lodash.deburr/-/lodash.deburr-3.2.0.tgz", - "integrity": "sha1-baj1QzSjZqfPTEx2742Aqhs2XtU=", - "dev": true, - "requires": { - "lodash._root": "3.0.1" - } - }, "lodash.isarguments": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", @@ -6826,15 +6834,6 @@ "integrity": "sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=", "dev": true }, - "lodash.words": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/lodash.words/-/lodash.words-3.2.0.tgz", - "integrity": "sha1-TiqGSbwIdFsXxpWxo86P7llmI7M=", - "dev": true, - "requires": { - "lodash._root": "3.0.1" - } - }, "log-symbols": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-1.0.2.tgz", @@ -7244,6 +7243,24 @@ "minipass": "2.2.1" } }, + "mississippi": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-1.3.0.tgz", + "integrity": "sha1-0gFYPrEjJ+PFwWQqQEqcrPlONPU=", + "dev": true, + "requires": { + "concat-stream": "1.6.0", + "duplexify": "3.5.1", + "end-of-stream": "1.4.0", + "flush-write-stream": "1.0.2", + "from2": "2.3.0", + "parallel-transform": "1.1.0", + "pump": "1.0.3", + "pumpify": "1.3.5", + "stream-each": "1.2.2", + "through2": "2.0.3" + } + }, "mixin-object": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/mixin-object/-/mixin-object-2.0.1.tgz", @@ -7313,87 +7330,6 @@ } } }, - "mocha-loader": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/mocha-loader/-/mocha-loader-1.1.1.tgz", - "integrity": "sha1-Ocm3jErWmrxTPtAuLas5gkTKM6s=", - "dev": true, - "requires": { - "css-loader": "0.23.1", - "loader-utils": "1.1.0", - "script-loader": "0.7.2", - "style-loader": "0.13.2" - }, - "dependencies": { - "css-loader": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-0.23.1.tgz", - "integrity": "sha1-n6I/K1wJZSNZEK1ezvO4o2OQ/lA=", - "dev": true, - "requires": { - "css-selector-tokenizer": "0.5.4", - "cssnano": "3.10.0", - "loader-utils": "0.2.17", - "lodash.camelcase": "3.0.1", - "object-assign": "4.1.1", - "postcss": "5.2.18", - "postcss-modules-extract-imports": "1.1.0", - "postcss-modules-local-by-default": "1.2.0", - "postcss-modules-scope": "1.1.0", - "postcss-modules-values": "1.3.0", - "source-list-map": "0.1.8" - }, - "dependencies": { - "loader-utils": { - "version": "0.2.17", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-0.2.17.tgz", - "integrity": "sha1-+G5jdNQyBabmxg6RlvF8Apm/s0g=", - "dev": true, - "requires": { - "big.js": "3.2.0", - "emojis-list": "2.1.0", - "json5": "0.5.1", - "object-assign": "4.1.1" - } - } - } - }, - "css-selector-tokenizer": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/css-selector-tokenizer/-/css-selector-tokenizer-0.5.4.tgz", - "integrity": "sha1-E5uv00o1/QwUKEhwSeBpnm9qLCE=", - "dev": true, - "requires": { - "cssesc": "0.1.0", - "fastparse": "1.1.1" - } - }, - "lodash.camelcase": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-3.0.1.tgz", - "integrity": "sha1-kyyLh/ikN3iXxnGXUzKC+Xrqwpg=", - "dev": true, - "requires": { - "lodash._createcompounder": "3.0.0" - } - }, - "source-list-map": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-0.1.8.tgz", - "integrity": "sha1-xVCyq1Qn9rPyH1r+rYjE9Vh7IQY=", - "dev": true - }, - "style-loader": { - "version": "0.13.2", - "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-0.13.2.tgz", - "integrity": "sha1-dFMzhM9pjHEEx5URULSXF63C87s=", - "dev": true, - "requires": { - "loader-utils": "1.1.0" - } - } - } - }, "mousetrap": { "version": "1.6.1", "resolved": "https://registry.npmjs.org/mousetrap/-/mousetrap-1.6.1.tgz", @@ -7404,6 +7340,20 @@ "resolved": "https://registry.npmjs.org/mout/-/mout-1.0.0.tgz", "integrity": "sha1-m98dSvV9ZtR8s1OmM1oygQmOFQE=" }, + "move-concurrently": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz", + "integrity": "sha1-viwAX9oy4LKa8fBdfEszIUxwH5I=", + "dev": true, + "requires": { + "aproba": "1.2.0", + "copy-concurrently": "1.0.5", + "fs-write-stream-atomic": "1.0.10", + "mkdirp": "0.5.1", + "rimraf": "2.6.2", + "run-queue": "1.0.3" + } + }, "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", @@ -7758,12 +7708,6 @@ "boolbase": "1.0.0" } }, - "null-check": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/null-check/-/null-check-1.0.0.tgz", - "integrity": "sha1-l33/1xdgErnsMNKjnbXPcqBDnt0=", - "dev": true - }, "num2fraction": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/num2fraction/-/num2fraction-1.2.2.tgz", @@ -8079,6 +8023,17 @@ "integrity": "sha1-8/dSL073gjSNqBYbrZ7P1Rv4OnU=", "dev": true }, + "parallel-transform": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/parallel-transform/-/parallel-transform-1.1.0.tgz", + "integrity": "sha1-1BDwZbBdojCB/NEPKIVMKb2jOwY=", + "dev": true, + "requires": { + "cyclist": "0.2.2", + "inherits": "2.0.3", + "readable-stream": "2.3.3" + } + }, "param-case": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/param-case/-/param-case-2.1.1.tgz", @@ -9064,6 +9019,12 @@ "asap": "2.0.6" } }, + "promise-inflight": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", + "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=", + "dev": true + }, "prop-types": { "version": "15.6.0", "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.6.0.tgz", @@ -9114,6 +9075,27 @@ "randombytes": "2.0.5" } }, + "pump": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/pump/-/pump-1.0.3.tgz", + "integrity": "sha512-8k0JupWme55+9tCVE+FS5ULT3K6AbgqrGa58lTT49RpyfwwcGedHqaC5LlQNdEAumn/wFsu6aPwkuPMioy8kqw==", + "dev": true, + "requires": { + "end-of-stream": "1.4.0", + "once": "1.4.0" + } + }, + "pumpify": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.3.5.tgz", + "integrity": "sha1-G2ccYZlAq8rqwK0OOjwWS+dgmTs=", + "dev": true, + "requires": { + "duplexify": "3.5.1", + "inherits": "2.0.3", + "pump": "1.0.3" + } + }, "punycode": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", @@ -9124,12 +9106,6 @@ "resolved": "https://registry.npmjs.org/q/-/q-1.5.0.tgz", "integrity": "sha1-3QG6ydBtMObyGa7LglPunr3DCPE=" }, - "qjobs": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/qjobs/-/qjobs-1.1.5.tgz", - "integrity": "sha1-ZZ3p8s+NzCehSBJ28gU3cnI4LnM=", - "dev": true - }, "qs": { "version": "6.4.0", "resolved": "https://registry.npmjs.org/qs/-/qs-6.4.0.tgz", @@ -9276,12 +9252,6 @@ "unpipe": "1.0.0" } }, - "raw-loader": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/raw-loader/-/raw-loader-0.5.1.tgz", - "integrity": "sha1-DD0L6u2KAclm2Xh793goElKpeao=", - "dev": true - }, "rbush": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/rbush/-/rbush-2.0.1.tgz", @@ -9291,10 +9261,11 @@ } }, "react": { - "version": "16.0.0", - "resolved": "https://registry.npmjs.org/react/-/react-16.0.0.tgz", - "integrity": "sha1-zn348ZQbA28Cssyp29DLHw6FXi0=", + "version": "15.6.2", + "resolved": "https://registry.npmjs.org/react/-/react-15.6.2.tgz", + "integrity": "sha1-26BDSrQ5z+gvEI8PURZjkIF5qnI=", "requires": { + "create-react-class": "15.6.2", "fbjs": "0.8.16", "loose-envify": "1.3.1", "object-assign": "4.1.1", @@ -9360,9 +9331,9 @@ "dev": true }, "react-dom": { - "version": "16.0.0", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.0.0.tgz", - "integrity": "sha1-nMMHnD3NcNTG4BuEqrKn40wwP1g=", + "version": "15.6.2", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-15.6.2.tgz", + "integrity": "sha1-Qc+t9pO3V/rycIRDodH9WgK+9zA=", "requires": { "fbjs": "0.8.16", "loose-envify": "1.3.1", @@ -10329,6 +10300,15 @@ "is-promise": "2.1.0" } }, + "run-queue": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/run-queue/-/run-queue-1.0.3.tgz", + "integrity": "sha1-6Eg5bwV9Ij8kOGkkYY4laUFh7Ec=", + "dev": true, + "requires": { + "aproba": "1.2.0" + } + }, "rw": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/rw/-/rw-1.3.3.tgz", @@ -10448,15 +10428,6 @@ } } }, - "script-loader": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/script-loader/-/script-loader-0.7.2.tgz", - "integrity": "sha512-UMNLEvgOAQuzK8ji8qIscM3GIrRCWN6MmMXGD4SD5l6cSycgGsCo0tX5xRnfQcoghqct0tjHjcykgI1PyBE2aA==", - "dev": true, - "requires": { - "raw-loader": "0.5.1" - } - }, "scss-tokenizer": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/scss-tokenizer/-/scss-tokenizer-0.2.3.tgz", @@ -10489,6 +10460,111 @@ "integrity": "sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo=", "dev": true }, + "selenium-standalone": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/selenium-standalone/-/selenium-standalone-6.11.0.tgz", + "integrity": "sha512-MedSwbiyLkv/nxr7JpI9zFNSAmSDpcz+bCaVSJC1krXYeIzFuj6tKMMss57xwu4VHgfInTy3IIMM2HdjN87xXQ==", + "dev": true, + "requires": { + "async": "2.5.0", + "commander": "2.11.0", + "cross-spawn": "5.1.0", + "debug": "2.6.9", + "lodash": "4.17.4", + "minimist": "1.2.0", + "mkdirp": "0.5.1", + "progress": "1.1.8", + "request": "2.79.0", + "tar-stream": "1.5.2", + "urijs": "1.19.0", + "which": "1.3.0", + "yauzl": "2.9.1" + }, + "dependencies": { + "caseless": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.11.0.tgz", + "integrity": "sha1-cVuW6phBWTzDMGeSP17GDr2k99c=", + "dev": true + }, + "har-validator": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-2.0.6.tgz", + "integrity": "sha1-zcvAgYgmWtEZtqWnyKtw7s+10n0=", + "dev": true, + "requires": { + "chalk": "1.1.3", + "commander": "2.11.0", + "is-my-json-valid": "2.16.1", + "pinkie-promise": "2.0.1" + } + }, + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + }, + "progress": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/progress/-/progress-1.1.8.tgz", + "integrity": "sha1-4mDHj2Fhzdmw5WzD4Khd4Xx6V74=", + "dev": true + }, + "qs": { + "version": "6.3.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.3.2.tgz", + "integrity": "sha1-51vV9uJoEioqDgvaYwslUMFmUCw=", + "dev": true + }, + "request": { + "version": "2.79.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.79.0.tgz", + "integrity": "sha1-Tf5b9r6LjNw3/Pk+BLZVd3InEN4=", + "dev": true, + "requires": { + "aws-sign2": "0.6.0", + "aws4": "1.6.0", + "caseless": "0.11.0", + "combined-stream": "1.0.5", + "extend": "3.0.1", + "forever-agent": "0.6.1", + "form-data": "2.1.4", + "har-validator": "2.0.6", + "hawk": "3.1.3", + "http-signature": "1.1.1", + "is-typedarray": "1.0.0", + "isstream": "0.1.2", + "json-stringify-safe": "5.0.1", + "mime-types": "2.1.17", + "oauth-sign": "0.8.2", + "qs": "6.3.2", + "stringstream": "0.0.5", + "tough-cookie": "2.3.3", + "tunnel-agent": "0.4.3", + "uuid": "3.1.0" + } + }, + "tar-stream": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.5.2.tgz", + "integrity": "sha1-+8bG6DwaGdTLSMfZYXH8JI7/x78=", + "dev": true, + "requires": { + "bl": "1.2.1", + "end-of-stream": "1.4.0", + "readable-stream": "2.3.3", + "xtend": "4.0.1" + } + }, + "tunnel-agent": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.3.tgz", + "integrity": "sha1-Y3PbdpCf5XDgjXNYM2Xtgop07us=", + "dev": true + } + } + }, "selfsigned": { "version": "1.10.1", "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-1.10.1.tgz", @@ -10543,6 +10619,12 @@ "upper-case-first": "1.1.2" } }, + "serialize-javascript": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-1.4.0.tgz", + "integrity": "sha1-fJWFFNtqwkQ6irwGLcn3iGp/YAU=", + "dev": true + }, "serve-index": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", @@ -11099,6 +11181,15 @@ } } }, + "ssri": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-5.0.0.tgz", + "integrity": "sha512-728D4yoQcQm1ooZvSbywLkV1RjfITZXh0oWrhM/lnsx3nAHx7LsRGJWB/YyvoceAYRq98xqbstiN4JBv1/wNHg==", + "dev": true, + "requires": { + "safe-buffer": "5.1.1" + } + }, "stackframe": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/stackframe/-/stackframe-0.3.1.tgz", @@ -11241,6 +11332,16 @@ "through": "2.3.8" } }, + "stream-each": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/stream-each/-/stream-each-1.2.2.tgz", + "integrity": "sha512-mc1dbFhGBxvTM3bIWmAAINbqiuAk9TATcfIQC8P+/+HJefgaiTlMn2dHvkX8qlI12KeYKSQ1Ua9RrIqrn1VPoA==", + "dev": true, + "requires": { + "end-of-stream": "1.4.0", + "stream-shift": "1.0.0" + } + }, "stream-http": { "version": "2.7.2", "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.7.2.tgz", @@ -11254,6 +11355,12 @@ "xtend": "4.0.1" } }, + "stream-shift": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.0.tgz", + "integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=", + "dev": true + }, "strict-uri-encode": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz", @@ -11745,6 +11852,19 @@ } } }, + "test-exclude": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-4.1.1.tgz", + "integrity": "sha512-35+Asrsk3XHJDBgf/VRFexPgh3UyETv8IAn/LRTiZjVy6rjPVqdEk8dJcJYBzl1w0XCJM48lvTy8SfEsCWS4nA==", + "dev": true, + "requires": { + "arrify": "1.0.1", + "micromatch": "2.3.11", + "object-assign": "4.1.1", + "read-pkg-up": "1.0.1", + "require-main-filename": "1.0.1" + } + }, "text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", @@ -12126,6 +12246,24 @@ "integrity": "sha1-/+3ks2slKQaW5uFl1KWe25mOawI=", "dev": true }, + "unique-filename": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.0.tgz", + "integrity": "sha1-0F8v5AMlYIcfMOk8vnNe6iAVFPM=", + "dev": true, + "requires": { + "unique-slug": "2.0.0" + } + }, + "unique-slug": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.0.tgz", + "integrity": "sha1-22Z258fMBimHj/GWCXx4hVrp9Ks=", + "dev": true, + "requires": { + "imurmurhash": "0.1.4" + } + }, "universalify": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.1.tgz", @@ -12151,6 +12289,12 @@ "upper-case": "1.1.3" } }, + "urijs": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/urijs/-/urijs-1.19.0.tgz", + "integrity": "sha512-Qs2odXn0hST5VSPVjpi73CMqtbAoanahaqWBujGU+IyMrMqpWcIhDewxQRhCkmqYxuyvICDcSuLdv2O7ncWBGw==", + "dev": true + }, "urix": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", @@ -12459,6 +12603,49 @@ "phantomjs-prebuilt": "2.1.16" } }, + "wdio-selenium-standalone-service": { + "version": "0.0.9", + "resolved": "https://registry.npmjs.org/wdio-selenium-standalone-service/-/wdio-selenium-standalone-service-0.0.9.tgz", + "integrity": "sha1-yA1P9Il0TVoLkdUYl2SRbUwMhWQ=", + "dev": true, + "requires": { + "fs-extra": "0.30.0", + "selenium-standalone": "6.11.0" + }, + "dependencies": { + "fs-extra": { + "version": "0.30.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.30.0.tgz", + "integrity": "sha1-8jP/zAjU2n1DLapEl3aYnbHfk/A=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "jsonfile": "2.4.0", + "klaw": "1.3.1", + "path-is-absolute": "1.0.1", + "rimraf": "2.6.2" + } + }, + "jsonfile": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz", + "integrity": "sha1-NzaitCi4e72gzIO1P6PWM6NcKug=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11" + } + }, + "klaw": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/klaw/-/klaw-1.3.1.tgz", + "integrity": "sha1-QIhDO0azsbolnXh4XY6W9zugJDk=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11" + } + } + } + }, "wdio-spec-reporter": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/wdio-spec-reporter/-/wdio-spec-reporter-0.1.2.tgz", @@ -13170,6 +13357,16 @@ } } }, + "yauzl": { + "version": "2.9.1", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.9.1.tgz", + "integrity": "sha1-qBmB6nCleUYTOIPwKcWCGok1mn8=", + "dev": true, + "requires": { + "buffer-crc32": "0.2.13", + "fd-slicer": "1.0.1" + } + }, "yeast": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/yeast/-/yeast-0.1.2.tgz", diff --git a/package.json b/package.json index c358b4b7..ba5d9e03 100644 --- a/package.json +++ b/package.json @@ -39,14 +39,14 @@ "ol-mapbox-style": "^1.0.1", "openlayers": "^4.4.2", "prop-types": "^15.6.0", - "react": "16.0.0", + "react": "^15.6.2", "react-addons-pure-render-mixin": "^15.6.2", "react-autocomplete": "^1.7.2", "react-codemirror2": "^3.0.7", "react-collapse": "^4.0.3", "react-color": "^2.13.8", "react-copy-to-clipboard": "^5.0.1", - "react-dom": "16.0.0", + "react-dom": "^15.6.2", "react-file-reader-input": "^1.1.4", "react-height": "^3.0.0", "react-icon-base": "^2.1.1", @@ -90,6 +90,7 @@ "babel-core": "^6.26.0", "babel-eslint": "^8.0.2", "babel-loader": "7.1.1", + "babel-plugin-istanbul": "^4.1.5", "babel-plugin-transform-class-properties": "^6.24.1", "babel-plugin-transform-decorators-legacy": "^1.3.4", "babel-plugin-transform-flow-strip-types": "^6.22.0", @@ -97,34 +98,38 @@ "babel-plugin-transform-runtime": "^6.23.0", "babel-preset-env": "^1.6.1", "babel-preset-react": "^6.24.1", + "babel-register": "^6.26.0", "babel-runtime": "^6.26.0", "base64-loader": "^1.0.0", "copy-webpack-plugin": "^4.2.0", + "cors": "^2.8.4", "css-loader": "^0.28.7", "eslint": "^4.10.0", "eslint-plugin-react": "^7.4.0", + "express": "^4.16.2", "extract-text-webpack-plugin": "^3.0.2", "file-loader": "^1.1.5", "html-webpack-plugin": "^2.30.1", + "is-docker": "^1.1.0", + "istanbul": "^0.4.5", + "istanbul-lib-coverage": "^1.1.1", "json-loader": "^0.5.7", - "karma": "^1.7.1", - "karma-chrome-launcher": "^2.2.0", - "karma-firefox-launcher": "^1.0.1", - "karma-mocha": "^1.3.0", - "karma-webpack": "^2.0.5", + "mkdirp": "^0.5.1", "mocha": "^4.0.1", - "mocha-loader": "^1.1.1", "node-sass": "^4.6.0", "react-hot-loader": "^3.1.1", "sass-loader": "^6.0.6", + "selenium-standalone": "^6.11.0", "style-loader": "^0.19.0", "stylelint": "^7.13.0", "stylelint-config-standard": "^15.0.1", "transform-loader": "^0.2.4", + "uuid": "^3.1.0", "wdio-mocha-framework": "^0.5.11", "wdio-phantomjs-service": "^0.2.2", + "wdio-selenium-standalone-service": "0.0.9", "wdio-spec-reporter": "^0.1.2", - "webdriverio": "^4.8.0", + "webdriverio": "^4.9.8", "webpack": "^3.8.1", "webpack-bundle-analyzer": "^2.9.0", "webpack-cleanup-plugin": "^0.5.1", diff --git a/src/components/App.jsx b/src/components/App.jsx index d51f7248..cd74f747 100644 --- a/src/components/App.jsx +++ b/src/components/App.jsx @@ -20,6 +20,7 @@ import { RevisionStore } from '../libs/revisions' import LayerWatcher from '../libs/layerwatcher' import tokens from '../config/tokens.json' import isEqual from 'lodash.isequal' +import Debug from '../libs/debug' function updateRootSpec(spec, fieldName, newValues) { return { @@ -53,9 +54,19 @@ export default class App extends React.Component { this.styleStore = new StyleStore() } this.styleStore.latestStyle(mapStyle => this.onStyleChanged(mapStyle)) + + if(Debug.enabled()) { + Debug.set("maputnik", "styleStore", this.styleStore); + Debug.set("maputnik", "revisionStore", this.revisionStore); + } }) } + if(Debug.enabled()) { + Debug.set("maputnik", "revisionStore", this.revisionStore); + Debug.set("maputnik", "styleStore", this.styleStore); + } + this.state = { errors: [], infos: [], @@ -70,22 +81,28 @@ export default class App extends React.Component { this.layerWatcher = new LayerWatcher({ onVectorLayersChange: v => this.setState({ vectorLayers: v }) }) + + this.onKeyDown = this.onKeyDown.bind(this); + } + + onKeyDown(e) { + console.log("??? keyCode ctrlKey="+e.ctrlKey+", keyCode="+e.keyCode) + // Control + Z + if(e.ctrlKey && e.keyCode === 90) { + this.onUndo(e); + } + else if(e.ctrlKey && e.keyCode === 89) { + this.onRedo(e); + } } componentDidMount() { this.fetchSources(); - Mousetrap.bind(['ctrl+z'], this.onUndo.bind(this)); - Mousetrap.bind(['ctrl+y'], this.onRedo.bind(this)); + document.addEventListener("keydown", this.onKeyDown); } componentWillUnmount() { - Mousetrap.unbind(['ctrl+z'], this.onUndo.bind(this)); - Mousetrap.unbind(['ctrl+y'], this.onRedo.bind(this)); - } - - onReset() { - this.styleStore.purge() - loadDefaultStyle(mapStyle => this.onStyleOpen(mapStyle)) + document.removeEventListener("keydown", this.onKeyDown); } saveStyle(snapshotStyle) { diff --git a/src/components/Button.jsx b/src/components/Button.jsx index d87b8517..b1189c17 100644 --- a/src/components/Button.jsx +++ b/src/components/Button.jsx @@ -4,6 +4,7 @@ import classnames from 'classnames' class Button extends React.Component { static propTypes = { + "data-wd-key": PropTypes.string, onClick: PropTypes.func, style: PropTypes.object, className: PropTypes.string, @@ -14,6 +15,7 @@ class Button extends React.Component { return {this.props.children} diff --git a/src/components/Toolbar.jsx b/src/components/Toolbar.jsx index 6b30fb51..14fa0d13 100644 --- a/src/components/Toolbar.jsx +++ b/src/components/Toolbar.jsx @@ -63,6 +63,7 @@ class ToolbarAction extends React.Component { render() { return {this.props.children} @@ -139,23 +140,23 @@ export default class Toolbar extends React.Component {

Maputnik

- + Open - + Export - + Sources - + Style Settings - + { this.props.inspectModeEnabled && Map Mode } diff --git a/src/components/fields/FunctionSpecField.jsx b/src/components/fields/FunctionSpecField.jsx index 9772a33d..981bb1c9 100644 --- a/src/components/fields/FunctionSpecField.jsx +++ b/src/components/fields/FunctionSpecField.jsx @@ -131,8 +131,7 @@ export default class FunctionSpecProperty extends React.Component { /> ) } - - return
+ return
{specField}
} diff --git a/src/components/fields/SpecField.jsx b/src/components/fields/SpecField.jsx index 00796ef4..38c5675f 100644 --- a/src/components/fields/SpecField.jsx +++ b/src/components/fields/SpecField.jsx @@ -58,70 +58,79 @@ export default class SpecField extends React.Component { name: this.props.fieldName, onChange: newValue => this.props.onChange(this.props.fieldName, newValue) } - switch(this.props.fieldSpec.type) { - case 'number': return ( - - ) - case 'enum': - const options = Object.keys(this.props.fieldSpec.values).map(v => [v, capitalize(v)]) - if(options.length <= 3 && optionsLabelLength(options) <= 20) { - return - } else { - return - } - case 'string': - if(iconProperties.indexOf(this.props.fieldName) >= 0) { - return - } else { - return - } - case 'color': return ( - - ) - case 'boolean': return ( - - ) - case 'array': - if(this.props.fieldName === 'text-font') { - return - } else { - if (this.props.fieldSpec.length) { - return [v, capitalize(v)]) + + if(options.length <= 3 && optionsLabelLength(options) <= 20) { + return } else { - return } - } - default: return null + case 'string': + if(iconProperties.indexOf(this.props.fieldName) >= 0) { + return + } else { + return + } + case 'color': return ( + + ) + case 'boolean': return ( + + ) + case 'array': + if(this.props.fieldName === 'text-font') { + return + } else { + if (this.props.fieldSpec.length) { + return + } else { + return + } + } + default: return null + } } + + return ( +
+ {childNodes.call(this)} +
+ ); } } diff --git a/src/components/filter/FilterEditor.jsx b/src/components/filter/FilterEditor.jsx index 73cb2f13..02ee2a40 100644 --- a/src/components/filter/FilterEditor.jsx +++ b/src/components/filter/FilterEditor.jsx @@ -89,7 +89,7 @@ export default class CombiningFilterEditor extends React.Component { } return
-
+
diff --git a/src/components/modals/ExportModal.jsx b/src/components/modals/ExportModal.jsx index 13718357..d8b2a742 100644 --- a/src/components/modals/ExportModal.jsx +++ b/src/components/modals/ExportModal.jsx @@ -5,7 +5,6 @@ import { saveAs } from 'file-saver' import styleSpec from '@mapbox/mapbox-gl-style-spec/style-spec' import InputBlock from '../inputs/InputBlock' import StringInput from '../inputs/StringInput' -import SelectInput from '../inputs/SelectInput' import CheckboxInput from '../inputs/CheckboxInput' import Button from '../Button' import Modal from './Modal' @@ -215,6 +214,7 @@ class ExportModal extends React.Component { render() { return -
+

{this.props.title}

this.props.onOpenToggle(false)} + data-wd-key={this.props["data-wd-key"]+".close-modal"} > diff --git a/src/components/modals/OpenModal.jsx b/src/components/modals/OpenModal.jsx index bcd1ba8a..4ce76f56 100644 --- a/src/components/modals/OpenModal.jsx +++ b/src/components/modals/OpenModal.jsx @@ -133,6 +133,7 @@ class OpenModal extends React.Component { } return this.onOpenToggle()} title={'Open Style'} @@ -151,9 +152,9 @@ class OpenModal extends React.Component {

Load from a URL. Note that the URL must have CORS enabled.

- this.styleUrlElement = input} className="maputnik-input" placeholder="Enter URL..."/> + this.styleUrlElement = input} className="maputnik-input" placeholder="Enter URL..."/>
- +
diff --git a/src/components/modals/SettingsModal.jsx b/src/components/modals/SettingsModal.jsx index ef50ad26..941a8189 100644 --- a/src/components/modals/SettingsModal.jsx +++ b/src/components/modals/SettingsModal.jsx @@ -42,6 +42,7 @@ class SettingsModal extends React.Component { const metadata = this.props.mapStyle.metadata || {} const inputProps = { } return @@ -68,6 +72,7 @@ class SettingsModal extends React.Component { @@ -75,6 +80,7 @@ class SettingsModal extends React.Component { @@ -82,6 +88,7 @@ class SettingsModal extends React.Component { @@ -89,6 +96,7 @@ class SettingsModal extends React.Component { + */ +try { +browser.addCommand('setValueSafe', function(selector, text) { + for(var i=0; i<10; i++) { + console.log(">>>> waiting for visible"); + browser.waitForVisible(selector); + + var elements = browser.elements(selector); + if(elements.length > 1) { + console.error(">>> Too many elements found"); + throw "Too many elements found"; + } + + console.log(">>>> setting value"); + browser.setValue(selector, text); + var browserText = browser.getValue(selector); + + console.log("browserText='%s' test='%s'", browserText, text); + + if(browserText == text) { + return; + } + else { + console.error("Warning: setValue failed, trying again"); + } + } + + // Wait for change events to fire and state updated + browser.flushReactUpdates(); +}) + +browser.addCommand('takeScreenShot', function(filepath) { + var data = browser.screenshot(); + fs.writeFileSync(path.join(SCREENSHOTS_PATH, filepath), data.value, 'base64'); +}); + +browser.addCommand('flushReactUpdates', function() { + browser.executeAsync(function(done) { + // For any events to propogate + setImmediate(function() { + // For the DOM to be updated. + setImmediate(done); + }) + }) +}) + +} catch(err) { + console.error(err); +} + +describe('maputnik', function() { + var geoserver; + + before(function(done) { + // Start style server + geoserver = geoServer.listen(9002, done); + }); + + function getStyleStore(browser) { + var result = browser.executeAsync(function(done) { + window.debug.get("maputnik", "styleStore").latestStyle(done); + }) + return result.value; + } + + function getRevisionStore(browser) { + var result = browser.execute(function(done) { + var rs = window.debug.get("maputnik", "revisionStore") + + return { + currentIdx: rs.currentIdx, + revisions: rs.revisions + }; + }) + return result.value; + } + + function getStyleUrl(styles) { + var port = geoserver.address().port; + return "http://localhost:"+port+"/styles/empty/"+styles.join(","); + } + + function getGeoServerUrl(urlPath) { + var port = geoserver.address().port; + return "http://localhost:"+port+"/"+urlPath; + } + + beforeEach(function() { + browser.url(config.baseUrl+"?debug&style="+getStyleUrl([ + "geojson:example", + "raster:raster" + ])); + browser.waitForExist(".maputnik-toolbar-link"); + browser.flushReactUpdates(); + }); + + it('check logo exists', function () { + var src = browser.getAttribute(".maputnik-toolbar-link img", "src"); + assert.equal(src, config.baseUrl+'/img/logo-color.svg'); + }); + + function closeModal(wdKey) { + console.log(">> A"); + browser.waitUntil(function() { + return browser.isVisibleWithinViewport(wd.$(wdKey)); + }); + + console.log(">> B"); + var closeBtnSelector = wd.$(wdKey+".close-modal"); + browser.click(closeBtnSelector); + + console.log(">> C"); + browser.waitUntil(function() { + return !browser.isVisibleWithinViewport(wd.$(wdKey)); + }); + } + + describe("modal", function() { + describe("open", function() { + var styleFilePath = __dirname+"/../example-style.json"; + var styleFileData = JSON.parse(fs.readFileSync(styleFilePath)); + + beforeEach(function() { + browser.url(config.baseUrl+"?debug"); + + browser.waitForExist(".maputnik-toolbar-link"); + browser.flushReactUpdates(); + + browser.click(wd.$("nav:open")) + browser.flushReactUpdates(); + }); + + it("close", function() { + closeModal("open-modal"); + }); + + it("upload", function() { + browser.waitForExist("*[type='file']") + browser.chooseFile("*[type='file']", styleFilePath); + + var styleObj = getStyleStore(browser); + console.log("styleObj", styleObj); + assert.deepEqual(styleFileData, styleObj); + }); + + it("load from url", function() { + var styleFileUrl = getGeoServerUrl("example-style.json"); + + browser.setValueSafe(wd.$("open-modal.url.input"), styleFileUrl); + + var selector = wd.$("open-modal.url.button"); + console.log("selector", selector); + browser.click(selector); + + // Allow the network request to happen + // NOTE: Its localhost so this should be fast. + browser.pause(300); + + var styleObj = getStyleStore(browser); + console.log("styleObj", styleObj); + console.log("styleFileData", styleFileData); + assert.deepEqual(styleFileData, styleObj); + }); + + // TODO: Need to work out how to mock out the end points + it("gallery") + }) + + describe("export", function() { + + beforeEach(function() { + browser.url(config.baseUrl+"?debug"); + + browser.waitForExist(".maputnik-toolbar-link"); + browser.flushReactUpdates(); + + browser.click(wd.$("nav:export")) + browser.flushReactUpdates(); + }); + + it("close", function() { + closeModal("export-modal"); + }); + + // TODO: Work out how to download a file and check the contents + it("download") + // TODO: Work out how to mock the end git points + it("save to gist") + }) + + describe("sources", function() { + it("active sources") + it("public source") + it("add new source") + }) + + describe("inspect", function() { + it("toggle", function() { + browser.url(config.baseUrl+"?debug&style="+getStyleUrl([ + "geojson:example" + ])); + + browser.click(wd.$("nav:inspect")); + }) + }) + + describe("style settings", function() { + beforeEach(function() { + browser.url(config.baseUrl+"?debug"); + + browser.waitForExist(".maputnik-toolbar-link"); + browser.flushReactUpdates(); + + browser.click(wd.$("nav:settings")) + browser.flushReactUpdates(); + }); + + it("name", function() { + browser.setValueSafe(wd.$("modal-settings.name"), "foobar") + browser.click(wd.$("modal-settings.owner")) + browser.flushReactUpdates(); + + var styleObj = getStyleStore(browser); + console.log("styleObj", styleObj); + assert.equal(styleObj.name, "foobar"); + }) + it("owner", function() { + browser.setValueSafe(wd.$("modal-settings.owner"), "foobar") + browser.click(wd.$("modal-settings.name")) + browser.flushReactUpdates(); + + var styleObj = getStyleStore(browser); + console.log("styleObj", styleObj); + assert.equal(styleObj.owner, "foobar"); + }) + it("sprite url", function() { + browser.setValueSafe(wd.$("modal-settings.sprite"), "http://example.com") + browser.click(wd.$("modal-settings.name")) + browser.flushReactUpdates(); + + var styleObj = getStyleStore(browser); + console.log("styleObj", styleObj); + assert.equal(styleObj.sprite, "http://example.com"); + }) + it("glyphs url", function() { + var glyphsUrl = "http://example.com/{fontstack}/{range}.pbf" + browser.setValueSafe(wd.$("modal-settings.glyphs"), glyphsUrl) + browser.click(wd.$("modal-settings.name")) + browser.flushReactUpdates(); + + var styleObj = getStyleStore(browser); + console.log("styleObj", styleObj); + assert.equal(styleObj.glyphs, glyphsUrl); + }) + + it("mapbox access token", function() { + var apiKey = "testing123"; + browser.setValueSafe(wd.$("modal-settings.maputnik:mapbox_access_token"), apiKey); + browser.click(wd.$("modal-settings.name")) + browser.flushReactUpdates(); + + var styleObj = getStyleStore(browser); + console.log("styleObj", styleObj); + browser.waitUntil(function() { + return styleObj.metadata["maputnik:mapbox_access_token"] == apiKey; + }) + }) + + it("open map tiles access token", function() { + var apiKey = "testing123"; + browser.setValueSafe(wd.$("modal-settings.maputnik:openmaptiles_access_token"), apiKey); + browser.click(wd.$("modal-settings.name")) + browser.flushReactUpdates(); + + var styleObj = getStyleStore(browser); + console.log("styleObj", styleObj); + assert.equal(styleObj.metadata["maputnik:openmaptiles_access_token"], apiKey); + }) + + it("style renderer", function() { + var selector = wd.$("modal-settings.maputnik:renderer"); + browser.selectByValue(selector, "ol3"); + browser.click(wd.$("modal-settings.name")) + browser.flushReactUpdates(); + + var styleObj = getStyleStore(browser); + console.log("styleObj", styleObj); + assert.equal(styleObj.metadata["maputnik:renderer"], "ol3"); + }) + }) + + describe("sources", function() { + it("toggle") + }) + }) + + describe.skip("zoom level", function() { + it("via url", function() { + var zoomLevel = "12.37" + browser.url(config.baseUrl+"?debug&style="+getStyleUrl([ + "geojson:example" + ])+"#"+zoomLevel+"/41.3805/2.1635"); + + browser.waitUntil(function () { + return ( + browser.isVisible(".mapboxgl-ctrl-zoom") + && browser.getText(".mapboxgl-ctrl-zoom") === "Zoom level: "+(zoomLevel) + ); + }, 10*1000) + }) + it("via map controls", function() { + var zoomLevel = 12.37; + browser.url(config.baseUrl+"?debug&style="+getStyleUrl([ + "geojson:example" + ])+"#"+zoomLevel+"/41.3805/2.1635"); + + browser.click(".mapboxgl-ctrl-zoom-in") + browser.waitUntil(function () { + var text = browser.getText(".mapboxgl-ctrl-zoom") + return text === "Zoom level: "+(zoomLevel+1); + }, 10*1000) + }) + }) + + describe.skip("groups", function() { + it("simple", function() { + browser.url(config.baseUrl+"?debug&style="+getStyleUrl([ + "geojson:example" + ])); + + modelCommands.addLayer.open(); + var aId = modelCommands.addLayer.fill({ + id: "foo", + type: "background" + }) + + modelCommands.addLayer.open(); + var bId = modelCommands.addLayer.fill({ + id: "foo_bar", + type: "background" + }) + + modelCommands.addLayer.open(); + var bId = modelCommands.addLayer.fill({ + id: "foo_baz", + type: "background" + }) + + browser.waitForExist(wd.$("layer-list-group:foo-0")); + + assert.equal(browser.isVisibleWithinViewport(wd.$("layer-list-item:foo")), false); + assert.equal(browser.isVisibleWithinViewport(wd.$("layer-list-item:foo_bar")), false); + assert.equal(browser.isVisibleWithinViewport(wd.$("layer-list-item:foo_baz")), false); + + browser.click(wd.$("layer-list-group:foo-0")); + + assert.equal(browser.isVisibleWithinViewport(wd.$("layer-list-item:foo")), true); + assert.equal(browser.isVisibleWithinViewport(wd.$("layer-list-item:foo_bar")), true); + assert.equal(browser.isVisibleWithinViewport(wd.$("layer-list-item:foo_baz")), true); + }) + }) + + describe.skip("history", function() { + /** + * See + */ + it("undo/redo", function() { + var styleObj; + + browser.url(config.baseUrl+"?debug&style="+getStyleUrl([ + "geojson:example" + ])); + + modelCommands.addLayer.open(); + + styleObj = getStyleStore(browser); + assert.deepEqual(styleObj.layers, []); + + modelCommands.addLayer.fill({ + id: "step 1", + type: "background" + }) + + styleObj = getStyleStore(browser); + assert.deepEqual(styleObj.layers, [ + { + "id": "step 1", + "type": 'background' + } + ]); + + modelCommands.addLayer.open(); + modelCommands.addLayer.fill({ + id: "step 2", + type: "background" + }) + + styleObj = getStyleStore(browser); + assert.deepEqual(styleObj.layers, [ + { + "id": "step 1", + "type": 'background' + }, + { + "id": "step 2", + "type": 'background' + } + ]); + + console.log(">>> LOGS", JSON.stringify(browser.log("browser"), null, 2)) + + browser + .keys(['Control', 'z']) + .keys(['Control']); + styleObj = getStyleStore(browser); + assert.deepEqual(styleObj.layers, [ + { + "id": "step 1", + "type": 'background' + } + ]); + + console.log(">>> LOGS", JSON.stringify(browser.log("browser"), null, 2)) + + browser + .keys(['Control', 'z']) + .keys(['Control']); + styleObj = getStyleStore(browser); + assert.deepEqual(styleObj.layers, [ + ]); + + console.log(">>> LOGS", JSON.stringify(browser.log("browser"), null, 2)) + + browser + .keys(['Control', 'y']) + .keys(['Control']); + styleObj = getStyleStore(browser); + assert.deepEqual(styleObj.layers, [ + { + "id": "step 1", + "type": 'background' + } + ]); + + console.log(">>> LOGS", JSON.stringify(browser.log("browser"), null, 2)) + + browser + .keys(['Control', 'y']) + .keys(['Control']); + styleObj = getStyleStore(browser); + assert.deepEqual(styleObj.layers, [ + { + "id": "step 1", + "type": 'background' + }, + { + "id": "step 2", + "type": 'background' + } + ]); + + console.log(">>> LOGS", JSON.stringify(browser.log("browser"), null, 2)) + }); + }) + + describe("layers", function() { + beforeEach(function() { + modelCommands.addLayer.open(); + }); + + describe("ops", function() { + it("delete", function() { + var styleObj; + var id = modelCommands.addLayer.fill({ + type: "background" + }) + + styleObj = getStyleStore(browser); + assert.deepEqual(styleObj.layers, [ + { + "id": id, + "type": 'background' + }, + ]); + + browser.click(wd.$("layer-list-item:"+id+":delete", "")); + + styleObj = getStyleStore(browser); + assert.deepEqual(styleObj.layers, [ + ]); + }); + + it("duplicate", function() { + var styleObj; + var id = modelCommands.addLayer.fill({ + type: "background" + }) + + styleObj = getStyleStore(browser); + assert.deepEqual(styleObj.layers, [ + { + "id": id, + "type": 'background' + }, + ]); + + browser.click(wd.$("layer-list-item:"+id+":copy", "")); + + styleObj = getStyleStore(browser); + assert.deepEqual(styleObj.layers, [ + { + "id": id+"-copy", + "type": "background" + }, + { + "id": id, + "type": "background" + }, + ]); + }); + + it("hide", function() { + var styleObj; + var id = modelCommands.addLayer.fill({ + type: "background" + }) + + styleObj = getStyleStore(browser); + assert.deepEqual(styleObj.layers, [ + { + "id": id, + "type": 'background' + }, + ]); + + browser.click(wd.$("layer-list-item:"+id+":toggle-visibility", "")); + + styleObj = getStyleStore(browser); + assert.deepEqual(styleObj.layers, [ + { + "id": id, + "type": "background", + "layout": { + "visibility": "none" + } + }, + ]); + + browser.click(wd.$("layer-list-item:"+id+":toggle-visibility", "")); + + styleObj = getStyleStore(browser); + assert.deepEqual(styleObj.layers, [ + { + "id": id, + "type": "background", + "layout": { + "visibility": "visible" + } + }, + ]); + }) + }) + + describe("grouped", function() { + it("with underscore") + it("no without underscore") + it("double underscore only grouped once") + }) + + describe("tooltips", function() { + }) + + describe("help", function() { + }) + + + describe('background', function () { + + it.skip("add", function() { + var id = modelCommands.addLayer.fill({ + type: "background" + }) + + browser.waitUntil(function() { + var styleObj = getStyleStore(browser); + assert.deepEqual(styleObj.layers, [ + { + "id": id, + "type": 'background' + } + ]); + }); + }); + + describe("modify", function() { + function createBackground() { + // Setup + var id = uuid(); + + browser.selectByValue(wd.$("add-layer.layer-type", "select"), "background"); + browser.flushReactUpdates(); + browser.setValueSafe(wd.$("add-layer.layer-id", "input"), "background:"+id); + + browser.click(wd.$("add-layer")); + + var styleObj = getStyleStore(browser); + assert.deepEqual(styleObj.layers, [ + { + "id": 'background:'+id, + "type": 'background' + } + ]); + return id; + } + + // ====> THESE SHOULD BE FROM THE SPEC + describe("layer", function() { + it("expand/collapse"); + it("id", function() { + var bgId = createBackground(); + + browser.click(wd.$("layer-list-item:background:"+bgId)) + + var id = uuid(); + browser.setValueSafe(wd.$("layer-editor.layer-id", "input"), "foobar:"+id) + browser.click(wd.$("min-zoom")) + + var styleObj = getStyleStore(browser); + assert.deepEqual(styleObj.layers, [ + { + "id": 'foobar:'+id, + "type": 'background' + } + ]); + }); + + // NOTE: This needs to be removed from the code + it("type"); + + it("min-zoom", function() { + var bgId = createBackground(); + + browser.click(wd.$("layer-list-item:background:"+bgId)) + browser.setValueSafe(wd.$("min-zoom", "input"), 1) + browser.click(wd.$("layer-editor.layer-id", "input")); + + var styleObj = getStyleStore(browser); + console.log("styleObj", styleObj); + assert.deepEqual(styleObj.layers, [ + { + "id": 'background:'+bgId, + "type": 'background', + "minzoom": 1 + } + ]); + + // AND RESET! + // browser.setValueSafe(wd.$("min-zoom", "input"), "") + // browser.click(wd.$("max-zoom", "input")); + + // var styleObj = getStyleStore(browser); + // console.log("styleObj", styleObj); + + // assert.deepEqual(styleObj.layers, [ + // { + // "id": 'background:'+bgId, + // "type": 'background' + // } + // ]); + }); + + it("max-zoom", function() { + var bgId = createBackground(); + + browser.click(wd.$("layer-list-item:background:"+bgId)) + browser.setValueSafe(wd.$("max-zoom", "input"), 1) + browser.click(wd.$("layer-editor.layer-id", "input")); + + var styleObj = getStyleStore(browser); + console.log("styleObj", styleObj); + assert.deepEqual(styleObj.layers, [ + { + "id": 'background:'+bgId, + "type": 'background', + "maxzoom": 1 + } + ]); + }); + + it("comments", function() { + var bgId = createBackground(); + var id = uuid(); + + browser.click(wd.$("layer-list-item:background:"+bgId)); + browser.setValueSafe(wd.$("layer-comment", "textarea"), id); + browser.click(wd.$("layer-editor.layer-id", "input")); + + var styleObj = getStyleStore(browser); + console.log("styleObj", styleObj); + assert.deepEqual(styleObj.layers, [ + { + "id": 'background:'+bgId, + "type": 'background', + metadata: { + 'maputnik:comment': id + } + } + ]); + + // Unset it again. + // TODO: This fails + // browser.setValueSafe(wd.$("layer-comment", "textarea"), ""); + // browser.click(wd.$("min-zoom", "input")); + // browser.flushReactUpdates(); + + // var styleObj = getStyleStore(browser); + // console.log("styleObj", styleObj); + // assert.deepEqual(styleObj.layers, [ + // { + // "id": 'background:'+bgId, + // "type": 'background' + // } + // ]); + }); + + it("color", null, function() { + var bgId = createBackground(); + var id = uuid(); + + browser.click(wd.$("layer-list-item:background:"+bgId)); + + browser.click(wd.$("spec-field:background-color", "input")) + // browser.debug(); + + var styleObj = getStyleStore(browser); + console.log("styleObj", styleObj); + assert.deepEqual(styleObj.layers, [ + { + "id": 'background:'+bgId, + "type": 'background' + } + ]); + + }) + }) + + describe("filter", function() { + it("expand/collapse"); + it("compound filter"); + }) + + describe("paint", function() { + it("expand/collapse"); + it("color"); + it("pattern"); + it("opacity"); + }) + // <===== + + describe("json-editor", function() { + it("expand/collapse"); + it("modify"); + + // TODO + it.skip("parse error", function() { + var bgId = createBackground(); + var id = uuid(); + + browser.click(wd.$("layer-list-item:background:"+bgId)); + + var errorSelector = ".CodeMirror-lint-marker-error"; + assert.equal(browser.isExisting(errorSelector), false); + + browser.click(".CodeMirror") + browser.keys("\uE013\uE013\uE013\uE013\uE013\uE013\uE013\uE013\uE013\uE013\uE013\uE013 {"); + browser.waitForExist(errorSelector) + + browser.click(wd.$("layer-editor.layer-id")); + }); + }); + }) + }); + + describe('fill', function () { + it.skip("add", function() { + // browser.debug(); + + var id = modelCommands.addLayer.fill({ + type: "fill", + layer: "example" + }); + + var styleObj = getStyleStore(browser); + console.log("STYLEOBJ", styleObj); + assert.deepEqual(styleObj.layers, [ + { + "id": id, + "type": 'fill', + "source": "example" + } + ]); + }) + + // TODO: Change source + it("change source") + }); + + describe('line', function () { + it.skip("add", function() { + var id = modelCommands.addLayer.fill({ + type: "line", + layer: "example" + }); + + var styleObj = getStyleStore(browser); + assert.deepEqual(styleObj.layers, [ + { + "id": id, + "type": "line", + "source": "example", + } + ]); + }); + + it("groups", null, function() { + // TODO + // Click each of the layer groups. + }) + }); + + describe('symbol', function () { + it.skip("add", function() { + var id = modelCommands.addLayer.fill({ + type: "symbol", + layer: "example" + }); + + var styleObj = getStyleStore(browser); + assert.deepEqual(styleObj.layers, [ + { + "id": id, + "type": "symbol", + "source": "example", + } + ]); + }); + }); + + describe('raster', function () { + it.skip("add", function() { + var id = modelCommands.addLayer.fill({ + type: "raster", + layer: "raster" + }); + + var styleObj = getStyleStore(browser); + assert.deepEqual(styleObj.layers, [ + { + "id": id, + "type": "raster", + "source": "raster", + } + ]); + }); + }); + + describe('circle', function () { + it.skip("add", function() { + var id = modelCommands.addLayer.fill({ + type: "circle", + layer: "example" + }); + + var styleObj = getStyleStore(browser); + assert.deepEqual(styleObj.layers, [ + { + "id": id, + "type": "circle", + "source": "example", + } + ]); + }); + + }); + + describe('fill extrusion', function () { + it.skip("add", function() { + var id = modelCommands.addLayer.fill({ + type: "fill-extrusion", + layer: "example" + }); + + var styleObj = getStyleStore(browser); + assert.deepEqual(styleObj.layers, [ + { + "id": id, + "type": 'fill-extrusion', + "source": "example" + } + ]); + }); + }); + + // These get used in the marketing material. They are also useful to do a quick manual check of the styling across browsers + // NOTE: These duplicate some of the tests, however this is indended becuase it's likely these will change for aesthetic reasons over time + }); + + // describe('screenshots', function() { + + // beforeEach(function() { + // browser.windowHandleSize({ + // width: 1280, + // height: 800 + // }); + // }) + + // it("front_page", function() { + // browser.url(config.baseUrl+"?debug&style="+getStyleUrl([ + // "geojson:example" + // ])); + // browser.waitForExist(".maputnik-toolbar-link"); + // browser.flushReactUpdates(); + + // browser.takeScreenShot("/front_page.png") + // }) + + // it("open", function() { + // browser.url(config.baseUrl+"?debug&style="+getStyleUrl([ + // "geojson:example" + // ])); + // browser.waitForExist(".maputnik-toolbar-link"); + // browser.flushReactUpdates(); + + // browser.click(wd.$("nav:open")) + // browser.flushReactUpdates(); + + // browser.takeScreenShot("/open.png") + // }) + + // it("export", function() { + // browser.url(config.baseUrl+"?debug&style="+getStyleUrl([ + // "geojson:example" + // ])); + // browser.waitForExist(".maputnik-toolbar-link"); + // browser.flushReactUpdates(); + + // browser.click(wd.$("nav:export")) + // browser.flushReactUpdates(); + + // browser.takeScreenShot("/export.png") + // }) + + // it("sources", function() { + // browser.url(config.baseUrl+"?debug&style="+getStyleUrl([ + // "geojson:example" + // ])); + // browser.waitForExist(".maputnik-toolbar-link"); + // browser.flushReactUpdates(); + + // browser.click(wd.$("nav:sources")) + // browser.flushReactUpdates(); + + // browser.takeScreenShot("/sources.png") + // }) + + // it("style settings", function() { + // browser.url(config.baseUrl+"?debug&style="+getStyleUrl([ + // "geojson:example" + // ])); + // browser.waitForExist(".maputnik-toolbar-link"); + // browser.flushReactUpdates(); + + // browser.click(wd.$("nav:settings")) + // browser.flushReactUpdates(); + + // browser.takeScreenShot("/settings.png") + // }) + + // it("inspect", function() { + // browser.url(config.baseUrl+"?debug&style="+getStyleUrl([ + // "geojson:example" + // ])); + // browser.waitForExist(".maputnik-toolbar-link"); + // browser.flushReactUpdates(); + + // browser.click(wd.$("nav:inspect")) + // browser.flushReactUpdates(); + + // browser.takeScreenShot("/inspect.png") + // }) + // }) + + var coverage = istanbulCov.createCoverageMap({}); + + afterEach(function() { + // Code coverage + var results = browser.execute(function() { + return window.__coverage__; + }); + + coverage.merge(results.value); + }) + + after(function() { + var jsonStr = JSON.stringify(coverage, null, 2); + fs.writeFileSync(COVERAGE_PATH+"/coverage.json", jsonStr); + }) + +}); + diff --git a/test/geojson-server.js b/test/geojson-server.js new file mode 100644 index 00000000..cac65e11 --- /dev/null +++ b/test/geojson-server.js @@ -0,0 +1,93 @@ +const cors = require("cors"); +const express = require("express"); +const fs = require("fs"); +const sourceData = require("./sources"); + + +var app = express(); + +app.use(cors()); + + +function buildStyle(opts) { + opts = opts || {}; + opts = Object.assign({ + sources: {} + }, opts); + + return { + "id": "test-style", + "version": 8, + "name": "Test Style", + "metadata": { + "maputnik:renderer": "mbgljs" + }, + "sources": opts.sources, + "glyphs": "https://demo.tileserver.org/fonts/{fontstack}/{range}.pbf", + "sprites": "https://demo.tileserver.org/fonts/{fontstack}/{range}.pbf", + "layers": [] + } +} + +function buildGeoJSONSource(data) { + return { + type: "vector", + data: data + }; +} + +function buildResterSource(req, key) { + return { + "tileSize": 256, + "tiles": [ + req.protocol + '://' + req.get('host') + "/" + key + "/{x}/{y}/{z}" + ], + "type": "raster" + }; +} + + +app.get("/sources/raster/{x}/{y}/{z}", function(req, res) { + res.status(404).end(); +}) + +app.get("/styles/empty/:sources", function(req, res) { + var reqSources = req.params.sources.split(","); + + var sources = {}; + // reqSources.forEach(function(key) { + // sources[key] = buildGeoJSONSource(sourceData[key]); + // }); + reqSources.forEach(function(key) { + var parts = key.split(":"); + var type = parts[0]; + var key = parts[1]; + + if(type === "geojson") { + sources[key] = buildGeoJSONSource(sourceData[key]); + } + else if(type === "raster") { + sources[key] = buildResterSource(req, key); + } + else { + console.error("ERR: Invalid type: %s", type); + throw "Invalid type" + } + }); + + var json = buildStyle({ + sources: sources + }); + res.send(json); +}) + +app.get("/example-style.json", function(req, res) { + res.json( + JSON.parse( + fs.readFileSync(__dirname+"/example-style.json").toString() + ) + ); +}) + + +module.exports = app; diff --git a/test/sources/example.json b/test/sources/example.json new file mode 100644 index 00000000..43246f9b --- /dev/null +++ b/test/sources/example.json @@ -0,0 +1,15 @@ +{ + "type":"FeatureCollection", + "features":[ + { + "type":"Feature", + "properties": { + "name": "Dinagat Islands" + }, + "geometry":{ + "type": "Point", + "coordinates": [125.6, 10.1] + } + } + ] +} diff --git a/test/sources/index.js b/test/sources/index.js new file mode 100644 index 00000000..894cce78 --- /dev/null +++ b/test/sources/index.js @@ -0,0 +1,3 @@ +module.exports = { + example: require("./example") +}; diff --git a/test/specs/simple.js b/test/specs/simple.js deleted file mode 100644 index fb6ca499..00000000 --- a/test/specs/simple.js +++ /dev/null @@ -1,15 +0,0 @@ -var assert = require('assert'); -var config = require("../config/specs"); - - -describe('maputnik', function() { - - it('check logo exists', function () { - browser.url(config.baseUrl); - browser.waitForExist(".maputnik-toolbar-link"); - - var src = browser.getAttribute(".maputnik-toolbar-link img", "src"); - assert.equal(src, config.baseUrl+'/img/logo-color.svg'); - }); - -}); diff --git a/test/wd-helper.js b/test/wd-helper.js new file mode 100644 index 00000000..c1691295 --- /dev/null +++ b/test/wd-helper.js @@ -0,0 +1,6 @@ +module.exports = { + "$": function(key, selector) { + selector = selector || ""; + return "*[data-wd-key='"+key+"'] "+selector; + } +} From a7739584036a9a58f38636e75d3e4be6c7020304 Mon Sep 17 00:00:00 2001 From: orangemug Date: Wed, 10 Jan 2018 13:19:34 +0000 Subject: [PATCH 02/48] Tidy tests. --- config/wdio.conf.js | 2 +- test/functional/advanced.js | 1077 ----------------------- test/functional/helper.js | 79 ++ test/functional/history/index.js | 205 +++++ test/functional/index.js | 33 + test/functional/layers/index.js | 497 +++++++++++ test/functional/map/index.js | 35 + test/functional/modals/index.js | 203 +++++ test/functional/screenshots/index.js | 93 ++ test/functional/util/coverage.js | 26 + test/functional/util/webdriverio-ext.js | 56 ++ 11 files changed, 1228 insertions(+), 1078 deletions(-) delete mode 100644 test/functional/advanced.js create mode 100644 test/functional/helper.js create mode 100644 test/functional/history/index.js create mode 100644 test/functional/index.js create mode 100644 test/functional/layers/index.js create mode 100644 test/functional/map/index.js create mode 100644 test/functional/modals/index.js create mode 100644 test/functional/screenshots/index.js create mode 100644 test/functional/util/coverage.js create mode 100644 test/functional/util/webdriverio-ext.js diff --git a/config/wdio.conf.js b/config/wdio.conf.js index 41fe910d..9109e7a7 100644 --- a/config/wdio.conf.js +++ b/config/wdio.conf.js @@ -11,7 +11,7 @@ var SCREENSHOT_PATH = artifacts.pathSync("screenshots"); exports.config = { specs: [ - './test/functional/advanced.js' + './test/functional/index.js' ], exclude: [ ], diff --git a/test/functional/advanced.js b/test/functional/advanced.js deleted file mode 100644 index 0f77f106..00000000 --- a/test/functional/advanced.js +++ /dev/null @@ -1,1077 +0,0 @@ -var assert = require('assert'); -var config = require("../config/specs"); -var uuid = require('uuid/v1'); -var geoServer = require("../geojson-server"); -var wd = require("../wd-helper"); -var fs = require("fs"); -var path = require("path"); -var mkdirp = require("mkdirp"); -var artifacts = require("../artifacts"); -var istanbulCov = require('istanbul-lib-coverage'); - -var COVERAGE_PATH = artifacts.pathSync("/coverage"); -var SCREENSHOTS_PATH = artifacts.pathSync("/screenshots"); - - -browser.timeoutsAsyncScript(10*1000); -browser.timeoutsImplicitWait(10*1000); - - - -var modelCommands = { - addLayer: { - open: function() { - var selector = wd.$('layer-list:add-layer'); - browser.click(selector); - - // Wait for events - browser.flushReactUpdates(); - - browser.waitForExist(wd.$('modal:add-layer')); - browser.isVisible(wd.$('modal:add-layer')); - browser.isVisibleWithinViewport(wd.$('modal:add-layer')); - - // Wait for events - browser.flushReactUpdates(); - }, - fill: function(opts) { - var type = opts.type; - var layer = opts.layer; - var id; - if(opts.id) { - id = opts.id - } - else { - id = type+":"+uuid(); - } - - browser.selectByValue(wd.$("add-layer.layer-type", "select"), type); - browser.flushReactUpdates(); - - browser.setValueSafe(wd.$("add-layer.layer-id", "input"), id); - if(layer) { - browser.setValueSafe(wd.$("add-layer.layer-source-block", "input"), layer); - } - - browser.flushReactUpdates(); - browser.click(wd.$("add-layer")); - - return id; - } - } -} - -/** - * Sometimes chrome driver can result in the wrong text. - * - * See - */ -try { -browser.addCommand('setValueSafe', function(selector, text) { - for(var i=0; i<10; i++) { - console.log(">>>> waiting for visible"); - browser.waitForVisible(selector); - - var elements = browser.elements(selector); - if(elements.length > 1) { - console.error(">>> Too many elements found"); - throw "Too many elements found"; - } - - console.log(">>>> setting value"); - browser.setValue(selector, text); - var browserText = browser.getValue(selector); - - console.log("browserText='%s' test='%s'", browserText, text); - - if(browserText == text) { - return; - } - else { - console.error("Warning: setValue failed, trying again"); - } - } - - // Wait for change events to fire and state updated - browser.flushReactUpdates(); -}) - -browser.addCommand('takeScreenShot', function(filepath) { - var data = browser.screenshot(); - fs.writeFileSync(path.join(SCREENSHOTS_PATH, filepath), data.value, 'base64'); -}); - -browser.addCommand('flushReactUpdates', function() { - browser.executeAsync(function(done) { - // For any events to propogate - setImmediate(function() { - // For the DOM to be updated. - setImmediate(done); - }) - }) -}) - -} catch(err) { - console.error(err); -} - -describe('maputnik', function() { - var geoserver; - - before(function(done) { - // Start style server - geoserver = geoServer.listen(9002, done); - }); - - function getStyleStore(browser) { - var result = browser.executeAsync(function(done) { - window.debug.get("maputnik", "styleStore").latestStyle(done); - }) - return result.value; - } - - function getRevisionStore(browser) { - var result = browser.execute(function(done) { - var rs = window.debug.get("maputnik", "revisionStore") - - return { - currentIdx: rs.currentIdx, - revisions: rs.revisions - }; - }) - return result.value; - } - - function getStyleUrl(styles) { - var port = geoserver.address().port; - return "http://localhost:"+port+"/styles/empty/"+styles.join(","); - } - - function getGeoServerUrl(urlPath) { - var port = geoserver.address().port; - return "http://localhost:"+port+"/"+urlPath; - } - - beforeEach(function() { - browser.url(config.baseUrl+"?debug&style="+getStyleUrl([ - "geojson:example", - "raster:raster" - ])); - browser.waitForExist(".maputnik-toolbar-link"); - browser.flushReactUpdates(); - }); - - it('check logo exists', function () { - var src = browser.getAttribute(".maputnik-toolbar-link img", "src"); - assert.equal(src, config.baseUrl+'/img/logo-color.svg'); - }); - - function closeModal(wdKey) { - console.log(">> A"); - browser.waitUntil(function() { - return browser.isVisibleWithinViewport(wd.$(wdKey)); - }); - - console.log(">> B"); - var closeBtnSelector = wd.$(wdKey+".close-modal"); - browser.click(closeBtnSelector); - - console.log(">> C"); - browser.waitUntil(function() { - return !browser.isVisibleWithinViewport(wd.$(wdKey)); - }); - } - - describe("modal", function() { - describe("open", function() { - var styleFilePath = __dirname+"/../example-style.json"; - var styleFileData = JSON.parse(fs.readFileSync(styleFilePath)); - - beforeEach(function() { - browser.url(config.baseUrl+"?debug"); - - browser.waitForExist(".maputnik-toolbar-link"); - browser.flushReactUpdates(); - - browser.click(wd.$("nav:open")) - browser.flushReactUpdates(); - }); - - it("close", function() { - closeModal("open-modal"); - }); - - it("upload", function() { - browser.waitForExist("*[type='file']") - browser.chooseFile("*[type='file']", styleFilePath); - - var styleObj = getStyleStore(browser); - console.log("styleObj", styleObj); - assert.deepEqual(styleFileData, styleObj); - }); - - it("load from url", function() { - var styleFileUrl = getGeoServerUrl("example-style.json"); - - browser.setValueSafe(wd.$("open-modal.url.input"), styleFileUrl); - - var selector = wd.$("open-modal.url.button"); - console.log("selector", selector); - browser.click(selector); - - // Allow the network request to happen - // NOTE: Its localhost so this should be fast. - browser.pause(300); - - var styleObj = getStyleStore(browser); - console.log("styleObj", styleObj); - console.log("styleFileData", styleFileData); - assert.deepEqual(styleFileData, styleObj); - }); - - // TODO: Need to work out how to mock out the end points - it("gallery") - }) - - describe("export", function() { - - beforeEach(function() { - browser.url(config.baseUrl+"?debug"); - - browser.waitForExist(".maputnik-toolbar-link"); - browser.flushReactUpdates(); - - browser.click(wd.$("nav:export")) - browser.flushReactUpdates(); - }); - - it("close", function() { - closeModal("export-modal"); - }); - - // TODO: Work out how to download a file and check the contents - it("download") - // TODO: Work out how to mock the end git points - it("save to gist") - }) - - describe("sources", function() { - it("active sources") - it("public source") - it("add new source") - }) - - describe("inspect", function() { - it("toggle", function() { - browser.url(config.baseUrl+"?debug&style="+getStyleUrl([ - "geojson:example" - ])); - - browser.click(wd.$("nav:inspect")); - }) - }) - - describe("style settings", function() { - beforeEach(function() { - browser.url(config.baseUrl+"?debug"); - - browser.waitForExist(".maputnik-toolbar-link"); - browser.flushReactUpdates(); - - browser.click(wd.$("nav:settings")) - browser.flushReactUpdates(); - }); - - it("name", function() { - browser.setValueSafe(wd.$("modal-settings.name"), "foobar") - browser.click(wd.$("modal-settings.owner")) - browser.flushReactUpdates(); - - var styleObj = getStyleStore(browser); - console.log("styleObj", styleObj); - assert.equal(styleObj.name, "foobar"); - }) - it("owner", function() { - browser.setValueSafe(wd.$("modal-settings.owner"), "foobar") - browser.click(wd.$("modal-settings.name")) - browser.flushReactUpdates(); - - var styleObj = getStyleStore(browser); - console.log("styleObj", styleObj); - assert.equal(styleObj.owner, "foobar"); - }) - it("sprite url", function() { - browser.setValueSafe(wd.$("modal-settings.sprite"), "http://example.com") - browser.click(wd.$("modal-settings.name")) - browser.flushReactUpdates(); - - var styleObj = getStyleStore(browser); - console.log("styleObj", styleObj); - assert.equal(styleObj.sprite, "http://example.com"); - }) - it("glyphs url", function() { - var glyphsUrl = "http://example.com/{fontstack}/{range}.pbf" - browser.setValueSafe(wd.$("modal-settings.glyphs"), glyphsUrl) - browser.click(wd.$("modal-settings.name")) - browser.flushReactUpdates(); - - var styleObj = getStyleStore(browser); - console.log("styleObj", styleObj); - assert.equal(styleObj.glyphs, glyphsUrl); - }) - - it("mapbox access token", function() { - var apiKey = "testing123"; - browser.setValueSafe(wd.$("modal-settings.maputnik:mapbox_access_token"), apiKey); - browser.click(wd.$("modal-settings.name")) - browser.flushReactUpdates(); - - var styleObj = getStyleStore(browser); - console.log("styleObj", styleObj); - browser.waitUntil(function() { - return styleObj.metadata["maputnik:mapbox_access_token"] == apiKey; - }) - }) - - it("open map tiles access token", function() { - var apiKey = "testing123"; - browser.setValueSafe(wd.$("modal-settings.maputnik:openmaptiles_access_token"), apiKey); - browser.click(wd.$("modal-settings.name")) - browser.flushReactUpdates(); - - var styleObj = getStyleStore(browser); - console.log("styleObj", styleObj); - assert.equal(styleObj.metadata["maputnik:openmaptiles_access_token"], apiKey); - }) - - it("style renderer", function() { - var selector = wd.$("modal-settings.maputnik:renderer"); - browser.selectByValue(selector, "ol3"); - browser.click(wd.$("modal-settings.name")) - browser.flushReactUpdates(); - - var styleObj = getStyleStore(browser); - console.log("styleObj", styleObj); - assert.equal(styleObj.metadata["maputnik:renderer"], "ol3"); - }) - }) - - describe("sources", function() { - it("toggle") - }) - }) - - describe.skip("zoom level", function() { - it("via url", function() { - var zoomLevel = "12.37" - browser.url(config.baseUrl+"?debug&style="+getStyleUrl([ - "geojson:example" - ])+"#"+zoomLevel+"/41.3805/2.1635"); - - browser.waitUntil(function () { - return ( - browser.isVisible(".mapboxgl-ctrl-zoom") - && browser.getText(".mapboxgl-ctrl-zoom") === "Zoom level: "+(zoomLevel) - ); - }, 10*1000) - }) - it("via map controls", function() { - var zoomLevel = 12.37; - browser.url(config.baseUrl+"?debug&style="+getStyleUrl([ - "geojson:example" - ])+"#"+zoomLevel+"/41.3805/2.1635"); - - browser.click(".mapboxgl-ctrl-zoom-in") - browser.waitUntil(function () { - var text = browser.getText(".mapboxgl-ctrl-zoom") - return text === "Zoom level: "+(zoomLevel+1); - }, 10*1000) - }) - }) - - describe.skip("groups", function() { - it("simple", function() { - browser.url(config.baseUrl+"?debug&style="+getStyleUrl([ - "geojson:example" - ])); - - modelCommands.addLayer.open(); - var aId = modelCommands.addLayer.fill({ - id: "foo", - type: "background" - }) - - modelCommands.addLayer.open(); - var bId = modelCommands.addLayer.fill({ - id: "foo_bar", - type: "background" - }) - - modelCommands.addLayer.open(); - var bId = modelCommands.addLayer.fill({ - id: "foo_baz", - type: "background" - }) - - browser.waitForExist(wd.$("layer-list-group:foo-0")); - - assert.equal(browser.isVisibleWithinViewport(wd.$("layer-list-item:foo")), false); - assert.equal(browser.isVisibleWithinViewport(wd.$("layer-list-item:foo_bar")), false); - assert.equal(browser.isVisibleWithinViewport(wd.$("layer-list-item:foo_baz")), false); - - browser.click(wd.$("layer-list-group:foo-0")); - - assert.equal(browser.isVisibleWithinViewport(wd.$("layer-list-item:foo")), true); - assert.equal(browser.isVisibleWithinViewport(wd.$("layer-list-item:foo_bar")), true); - assert.equal(browser.isVisibleWithinViewport(wd.$("layer-list-item:foo_baz")), true); - }) - }) - - describe.skip("history", function() { - /** - * See - */ - it("undo/redo", function() { - var styleObj; - - browser.url(config.baseUrl+"?debug&style="+getStyleUrl([ - "geojson:example" - ])); - - modelCommands.addLayer.open(); - - styleObj = getStyleStore(browser); - assert.deepEqual(styleObj.layers, []); - - modelCommands.addLayer.fill({ - id: "step 1", - type: "background" - }) - - styleObj = getStyleStore(browser); - assert.deepEqual(styleObj.layers, [ - { - "id": "step 1", - "type": 'background' - } - ]); - - modelCommands.addLayer.open(); - modelCommands.addLayer.fill({ - id: "step 2", - type: "background" - }) - - styleObj = getStyleStore(browser); - assert.deepEqual(styleObj.layers, [ - { - "id": "step 1", - "type": 'background' - }, - { - "id": "step 2", - "type": 'background' - } - ]); - - console.log(">>> LOGS", JSON.stringify(browser.log("browser"), null, 2)) - - browser - .keys(['Control', 'z']) - .keys(['Control']); - styleObj = getStyleStore(browser); - assert.deepEqual(styleObj.layers, [ - { - "id": "step 1", - "type": 'background' - } - ]); - - console.log(">>> LOGS", JSON.stringify(browser.log("browser"), null, 2)) - - browser - .keys(['Control', 'z']) - .keys(['Control']); - styleObj = getStyleStore(browser); - assert.deepEqual(styleObj.layers, [ - ]); - - console.log(">>> LOGS", JSON.stringify(browser.log("browser"), null, 2)) - - browser - .keys(['Control', 'y']) - .keys(['Control']); - styleObj = getStyleStore(browser); - assert.deepEqual(styleObj.layers, [ - { - "id": "step 1", - "type": 'background' - } - ]); - - console.log(">>> LOGS", JSON.stringify(browser.log("browser"), null, 2)) - - browser - .keys(['Control', 'y']) - .keys(['Control']); - styleObj = getStyleStore(browser); - assert.deepEqual(styleObj.layers, [ - { - "id": "step 1", - "type": 'background' - }, - { - "id": "step 2", - "type": 'background' - } - ]); - - console.log(">>> LOGS", JSON.stringify(browser.log("browser"), null, 2)) - }); - }) - - describe("layers", function() { - beforeEach(function() { - modelCommands.addLayer.open(); - }); - - describe("ops", function() { - it("delete", function() { - var styleObj; - var id = modelCommands.addLayer.fill({ - type: "background" - }) - - styleObj = getStyleStore(browser); - assert.deepEqual(styleObj.layers, [ - { - "id": id, - "type": 'background' - }, - ]); - - browser.click(wd.$("layer-list-item:"+id+":delete", "")); - - styleObj = getStyleStore(browser); - assert.deepEqual(styleObj.layers, [ - ]); - }); - - it("duplicate", function() { - var styleObj; - var id = modelCommands.addLayer.fill({ - type: "background" - }) - - styleObj = getStyleStore(browser); - assert.deepEqual(styleObj.layers, [ - { - "id": id, - "type": 'background' - }, - ]); - - browser.click(wd.$("layer-list-item:"+id+":copy", "")); - - styleObj = getStyleStore(browser); - assert.deepEqual(styleObj.layers, [ - { - "id": id+"-copy", - "type": "background" - }, - { - "id": id, - "type": "background" - }, - ]); - }); - - it("hide", function() { - var styleObj; - var id = modelCommands.addLayer.fill({ - type: "background" - }) - - styleObj = getStyleStore(browser); - assert.deepEqual(styleObj.layers, [ - { - "id": id, - "type": 'background' - }, - ]); - - browser.click(wd.$("layer-list-item:"+id+":toggle-visibility", "")); - - styleObj = getStyleStore(browser); - assert.deepEqual(styleObj.layers, [ - { - "id": id, - "type": "background", - "layout": { - "visibility": "none" - } - }, - ]); - - browser.click(wd.$("layer-list-item:"+id+":toggle-visibility", "")); - - styleObj = getStyleStore(browser); - assert.deepEqual(styleObj.layers, [ - { - "id": id, - "type": "background", - "layout": { - "visibility": "visible" - } - }, - ]); - }) - }) - - describe("grouped", function() { - it("with underscore") - it("no without underscore") - it("double underscore only grouped once") - }) - - describe("tooltips", function() { - }) - - describe("help", function() { - }) - - - describe('background', function () { - - it.skip("add", function() { - var id = modelCommands.addLayer.fill({ - type: "background" - }) - - browser.waitUntil(function() { - var styleObj = getStyleStore(browser); - assert.deepEqual(styleObj.layers, [ - { - "id": id, - "type": 'background' - } - ]); - }); - }); - - describe("modify", function() { - function createBackground() { - // Setup - var id = uuid(); - - browser.selectByValue(wd.$("add-layer.layer-type", "select"), "background"); - browser.flushReactUpdates(); - browser.setValueSafe(wd.$("add-layer.layer-id", "input"), "background:"+id); - - browser.click(wd.$("add-layer")); - - var styleObj = getStyleStore(browser); - assert.deepEqual(styleObj.layers, [ - { - "id": 'background:'+id, - "type": 'background' - } - ]); - return id; - } - - // ====> THESE SHOULD BE FROM THE SPEC - describe("layer", function() { - it("expand/collapse"); - it("id", function() { - var bgId = createBackground(); - - browser.click(wd.$("layer-list-item:background:"+bgId)) - - var id = uuid(); - browser.setValueSafe(wd.$("layer-editor.layer-id", "input"), "foobar:"+id) - browser.click(wd.$("min-zoom")) - - var styleObj = getStyleStore(browser); - assert.deepEqual(styleObj.layers, [ - { - "id": 'foobar:'+id, - "type": 'background' - } - ]); - }); - - // NOTE: This needs to be removed from the code - it("type"); - - it("min-zoom", function() { - var bgId = createBackground(); - - browser.click(wd.$("layer-list-item:background:"+bgId)) - browser.setValueSafe(wd.$("min-zoom", "input"), 1) - browser.click(wd.$("layer-editor.layer-id", "input")); - - var styleObj = getStyleStore(browser); - console.log("styleObj", styleObj); - assert.deepEqual(styleObj.layers, [ - { - "id": 'background:'+bgId, - "type": 'background', - "minzoom": 1 - } - ]); - - // AND RESET! - // browser.setValueSafe(wd.$("min-zoom", "input"), "") - // browser.click(wd.$("max-zoom", "input")); - - // var styleObj = getStyleStore(browser); - // console.log("styleObj", styleObj); - - // assert.deepEqual(styleObj.layers, [ - // { - // "id": 'background:'+bgId, - // "type": 'background' - // } - // ]); - }); - - it("max-zoom", function() { - var bgId = createBackground(); - - browser.click(wd.$("layer-list-item:background:"+bgId)) - browser.setValueSafe(wd.$("max-zoom", "input"), 1) - browser.click(wd.$("layer-editor.layer-id", "input")); - - var styleObj = getStyleStore(browser); - console.log("styleObj", styleObj); - assert.deepEqual(styleObj.layers, [ - { - "id": 'background:'+bgId, - "type": 'background', - "maxzoom": 1 - } - ]); - }); - - it("comments", function() { - var bgId = createBackground(); - var id = uuid(); - - browser.click(wd.$("layer-list-item:background:"+bgId)); - browser.setValueSafe(wd.$("layer-comment", "textarea"), id); - browser.click(wd.$("layer-editor.layer-id", "input")); - - var styleObj = getStyleStore(browser); - console.log("styleObj", styleObj); - assert.deepEqual(styleObj.layers, [ - { - "id": 'background:'+bgId, - "type": 'background', - metadata: { - 'maputnik:comment': id - } - } - ]); - - // Unset it again. - // TODO: This fails - // browser.setValueSafe(wd.$("layer-comment", "textarea"), ""); - // browser.click(wd.$("min-zoom", "input")); - // browser.flushReactUpdates(); - - // var styleObj = getStyleStore(browser); - // console.log("styleObj", styleObj); - // assert.deepEqual(styleObj.layers, [ - // { - // "id": 'background:'+bgId, - // "type": 'background' - // } - // ]); - }); - - it("color", null, function() { - var bgId = createBackground(); - var id = uuid(); - - browser.click(wd.$("layer-list-item:background:"+bgId)); - - browser.click(wd.$("spec-field:background-color", "input")) - // browser.debug(); - - var styleObj = getStyleStore(browser); - console.log("styleObj", styleObj); - assert.deepEqual(styleObj.layers, [ - { - "id": 'background:'+bgId, - "type": 'background' - } - ]); - - }) - }) - - describe("filter", function() { - it("expand/collapse"); - it("compound filter"); - }) - - describe("paint", function() { - it("expand/collapse"); - it("color"); - it("pattern"); - it("opacity"); - }) - // <===== - - describe("json-editor", function() { - it("expand/collapse"); - it("modify"); - - // TODO - it.skip("parse error", function() { - var bgId = createBackground(); - var id = uuid(); - - browser.click(wd.$("layer-list-item:background:"+bgId)); - - var errorSelector = ".CodeMirror-lint-marker-error"; - assert.equal(browser.isExisting(errorSelector), false); - - browser.click(".CodeMirror") - browser.keys("\uE013\uE013\uE013\uE013\uE013\uE013\uE013\uE013\uE013\uE013\uE013\uE013 {"); - browser.waitForExist(errorSelector) - - browser.click(wd.$("layer-editor.layer-id")); - }); - }); - }) - }); - - describe('fill', function () { - it.skip("add", function() { - // browser.debug(); - - var id = modelCommands.addLayer.fill({ - type: "fill", - layer: "example" - }); - - var styleObj = getStyleStore(browser); - console.log("STYLEOBJ", styleObj); - assert.deepEqual(styleObj.layers, [ - { - "id": id, - "type": 'fill', - "source": "example" - } - ]); - }) - - // TODO: Change source - it("change source") - }); - - describe('line', function () { - it.skip("add", function() { - var id = modelCommands.addLayer.fill({ - type: "line", - layer: "example" - }); - - var styleObj = getStyleStore(browser); - assert.deepEqual(styleObj.layers, [ - { - "id": id, - "type": "line", - "source": "example", - } - ]); - }); - - it("groups", null, function() { - // TODO - // Click each of the layer groups. - }) - }); - - describe('symbol', function () { - it.skip("add", function() { - var id = modelCommands.addLayer.fill({ - type: "symbol", - layer: "example" - }); - - var styleObj = getStyleStore(browser); - assert.deepEqual(styleObj.layers, [ - { - "id": id, - "type": "symbol", - "source": "example", - } - ]); - }); - }); - - describe('raster', function () { - it.skip("add", function() { - var id = modelCommands.addLayer.fill({ - type: "raster", - layer: "raster" - }); - - var styleObj = getStyleStore(browser); - assert.deepEqual(styleObj.layers, [ - { - "id": id, - "type": "raster", - "source": "raster", - } - ]); - }); - }); - - describe('circle', function () { - it.skip("add", function() { - var id = modelCommands.addLayer.fill({ - type: "circle", - layer: "example" - }); - - var styleObj = getStyleStore(browser); - assert.deepEqual(styleObj.layers, [ - { - "id": id, - "type": "circle", - "source": "example", - } - ]); - }); - - }); - - describe('fill extrusion', function () { - it.skip("add", function() { - var id = modelCommands.addLayer.fill({ - type: "fill-extrusion", - layer: "example" - }); - - var styleObj = getStyleStore(browser); - assert.deepEqual(styleObj.layers, [ - { - "id": id, - "type": 'fill-extrusion', - "source": "example" - } - ]); - }); - }); - - // These get used in the marketing material. They are also useful to do a quick manual check of the styling across browsers - // NOTE: These duplicate some of the tests, however this is indended becuase it's likely these will change for aesthetic reasons over time - }); - - // describe('screenshots', function() { - - // beforeEach(function() { - // browser.windowHandleSize({ - // width: 1280, - // height: 800 - // }); - // }) - - // it("front_page", function() { - // browser.url(config.baseUrl+"?debug&style="+getStyleUrl([ - // "geojson:example" - // ])); - // browser.waitForExist(".maputnik-toolbar-link"); - // browser.flushReactUpdates(); - - // browser.takeScreenShot("/front_page.png") - // }) - - // it("open", function() { - // browser.url(config.baseUrl+"?debug&style="+getStyleUrl([ - // "geojson:example" - // ])); - // browser.waitForExist(".maputnik-toolbar-link"); - // browser.flushReactUpdates(); - - // browser.click(wd.$("nav:open")) - // browser.flushReactUpdates(); - - // browser.takeScreenShot("/open.png") - // }) - - // it("export", function() { - // browser.url(config.baseUrl+"?debug&style="+getStyleUrl([ - // "geojson:example" - // ])); - // browser.waitForExist(".maputnik-toolbar-link"); - // browser.flushReactUpdates(); - - // browser.click(wd.$("nav:export")) - // browser.flushReactUpdates(); - - // browser.takeScreenShot("/export.png") - // }) - - // it("sources", function() { - // browser.url(config.baseUrl+"?debug&style="+getStyleUrl([ - // "geojson:example" - // ])); - // browser.waitForExist(".maputnik-toolbar-link"); - // browser.flushReactUpdates(); - - // browser.click(wd.$("nav:sources")) - // browser.flushReactUpdates(); - - // browser.takeScreenShot("/sources.png") - // }) - - // it("style settings", function() { - // browser.url(config.baseUrl+"?debug&style="+getStyleUrl([ - // "geojson:example" - // ])); - // browser.waitForExist(".maputnik-toolbar-link"); - // browser.flushReactUpdates(); - - // browser.click(wd.$("nav:settings")) - // browser.flushReactUpdates(); - - // browser.takeScreenShot("/settings.png") - // }) - - // it("inspect", function() { - // browser.url(config.baseUrl+"?debug&style="+getStyleUrl([ - // "geojson:example" - // ])); - // browser.waitForExist(".maputnik-toolbar-link"); - // browser.flushReactUpdates(); - - // browser.click(wd.$("nav:inspect")) - // browser.flushReactUpdates(); - - // browser.takeScreenShot("/inspect.png") - // }) - // }) - - var coverage = istanbulCov.createCoverageMap({}); - - afterEach(function() { - // Code coverage - var results = browser.execute(function() { - return window.__coverage__; - }); - - coverage.merge(results.value); - }) - - after(function() { - var jsonStr = JSON.stringify(coverage, null, 2); - fs.writeFileSync(COVERAGE_PATH+"/coverage.json", jsonStr); - }) - -}); - diff --git a/test/functional/helper.js b/test/functional/helper.js new file mode 100644 index 00000000..310265a9 --- /dev/null +++ b/test/functional/helper.js @@ -0,0 +1,79 @@ +var wd = require("../wd-helper"); +var uuid = require('uuid/v1'); +var geoServer = require("../geojson-server"); + + +// This should be sync... +var geoserver = geoServer.listen(9002); + + +module.exports = { + getStyleUrl: function(styles) { + var port = geoserver.address().port; + return "http://localhost:"+port+"/styles/empty/"+styles.join(","); + }, + getGeoServerUrl: function(urlPath) { + var port = geoserver.address().port; + return "http://localhost:"+port+"/"+urlPath; + }, + getStyleStore: function(browser) { + var result = browser.executeAsync(function(done) { + window.debug.get("maputnik", "styleStore").latestStyle(done); + }) + return result.value; + }, + getRevisionStore: function(browser) { + var result = browser.execute(function(done) { + var rs = window.debug.get("maputnik", "revisionStore") + + return { + currentIdx: rs.currentIdx, + revisions: rs.revisions + }; + }) + return result.value; + }, + modal: { + addLayer: { + open: function() { + var selector = wd.$('layer-list:add-layer'); + browser.click(selector); + + // Wait for events + browser.flushReactUpdates(); + + browser.waitForExist(wd.$('modal:add-layer')); + browser.isVisible(wd.$('modal:add-layer')); + browser.isVisibleWithinViewport(wd.$('modal:add-layer')); + + // Wait for events + browser.flushReactUpdates(); + }, + fill: function(opts) { + var type = opts.type; + var layer = opts.layer; + var id; + if(opts.id) { + id = opts.id + } + else { + id = type+":"+uuid(); + } + + browser.selectByValue(wd.$("add-layer.layer-type", "select"), type); + browser.flushReactUpdates(); + + browser.setValueSafe(wd.$("add-layer.layer-id", "input"), id); + if(layer) { + browser.setValueSafe(wd.$("add-layer.layer-source-block", "input"), layer); + } + + browser.flushReactUpdates(); + browser.click(wd.$("add-layer")); + + return id; + } + } + } +} + diff --git a/test/functional/history/index.js b/test/functional/history/index.js new file mode 100644 index 00000000..41895562 --- /dev/null +++ b/test/functional/history/index.js @@ -0,0 +1,205 @@ +var assert = require("assert"); +var config = require("../../config/specs"); +var helper = require("../helper"); +var wd = require("../../wd-helper"); + + +describe.skip("history", function() { + /** + * See + */ + it("undo/redo", function() { + var styleObj; + + browser.url(config.baseUrl+"?debug&style="+helper.getStyleUrl([ + "geojson:example" + ])); + + helper.modal.addLayer.open(); + + styleObj = helper.getStyleStore(browser); + assert.deepEqual(styleObj.layers, []); + + helper.modal.addLayer.fill({ + id: "step 1", + type: "background" + }) + + styleObj = helper.getStyleStore(browser); + assert.deepEqual(styleObj.layers, [ + { + "id": "step 1", + "type": 'background' + } + ]); + + helper.modal.addLayer.open(); + helper.modal.addLayer.fill({ + id: "step 2", + type: "background" + }) + + styleObj = helper.getStyleStore(browser); + assert.deepEqual(styleObj.layers, [ + { + "id": "step 1", + "type": 'background' + }, + { + "id": "step 2", + "type": 'background' + } + ]); + + console.log(">>> LOGS", JSON.stringify(browser.log("browser"), null, 2)) + + browser + .keys(['Control', 'z']) + .keys(['Control']); + styleObj = helper.getStyleStore(browser); + assert.deepEqual(styleObj.layers, [ + { + "id": "step 1", + "type": 'background' + } + ]); + + console.log(">>> LOGS", JSON.stringify(browser.log("browser"), null, 2)) + + browser + .keys(['Control', 'z']) + .keys(['Control']); + styleObj = helper.getStyleStore(browser); + assert.deepEqual(styleObj.layers, [ + ]); + + console.log(">>> LOGS", JSON.stringify(browser.log("browser"), null, 2)) + + browser + .keys(['Control', 'y']) + .keys(['Control']); + styleObj = helper.getStyleStore(browser); + assert.deepEqual(styleObj.layers, [ + { + "id": "step 1", + "type": 'background' + } + ]); + + console.log(">>> LOGS", JSON.stringify(browser.log("browser"), null, 2)) + + browser + .keys(['Control', 'y']) + .keys(['Control']); + styleObj = helper.getStyleStore(browser); + assert.deepEqual(styleObj.layers, [ + { + "id": "step 1", + "type": 'background' + }, + { + "id": "step 2", + "type": 'background' + } + ]); + + console.log(">>> LOGS", JSON.stringify(browser.log("browser"), null, 2)) + }); + + + // /** + // * See + // */ + // it("undo/redo", function() { + // var styleObj; + + // browser.debug(); + + // browser.url(helper.config.baseUrl+"?debug&style="+helper.getStyleUrl([ + // "geojson:example" + // ])); + // browser.waitForExist(".maputnik-toolbar-link"); + + // helper.modalCommands.addLayer.open(browser); + + // styleObj = helper.helper.getStyleStore(browser); + // console.log("styleObj", styleObj); + // assert.deepEqual(styleObj.layers, []); + + // helper.modalCommands.addLayer.fill(browser, { + // id: "step 1", + // type: "background" + // }) + + // styleObj = helper.helper.getStyleStore(browser); + // assert.deepEqual(styleObj.layers, [ + // { + // "id": "step 1", + // "type": 'background' + // } + // ]); + + // helper.modalCommands.addLayer.open(browser); + // helper.modalCommands.addLayer.fill(browser, { + // id: "step 2", + // type: "background" + // }) + + // styleObj = helper.helper.getStyleStore(browser); + // assert.deepEqual(styleObj.layers, [ + // { + // "id": "step 1", + // "type": 'background' + // }, + // { + // "id": "step 2", + // "type": 'background' + // } + // ]); + + // browser + // .keys(['Control', 'z']) + // .keys(['Control']); + // styleObj = helper.helper.getStyleStore(browser); + // assert.deepEqual(styleObj.layers, [ + // { + // "id": "step 1", + // "type": 'background' + // } + // ]); + + // browser + // .keys(['Control', 'z']) + // .keys(['Control']); + // styleObj = helper.helper.getStyleStore(browser); + // assert.deepEqual(styleObj.layers, [ + // ]); + + // browser + // .keys(['Control', 'y']) + // .keys(['Control']); + // styleObj = helper.helper.getStyleStore(browser); + // assert.deepEqual(styleObj.layers, [ + // { + // "id": "step 1", + // "type": 'background' + // } + // ]); + + // browser + // .keys(['Control', 'y']) + // .keys(['Control']); + // styleObj = helper.helper.getStyleStore(browser); + // assert.deepEqual(styleObj.layers, [ + // { + // "id": "step 1", + // "type": 'background' + // }, + // { + // "id": "step 2", + // "type": 'background' + // } + // ]); + + // }) +}) diff --git a/test/functional/index.js b/test/functional/index.js new file mode 100644 index 00000000..34d5e626 --- /dev/null +++ b/test/functional/index.js @@ -0,0 +1,33 @@ +var assert = require('assert'); +var config = require("../config/specs"); +var geoServer = require("../geojson-server"); +var helper = require("./helper"); + +require("./util/webdriverio-ext"); + + +describe('maputnik', function() { + + beforeEach(function() { + browser.url(config.baseUrl+"?debug&style="+helper.getStyleUrl([ + "geojson:example", + "raster:raster" + ])); + browser.waitForExist(".maputnik-toolbar-link"); + browser.flushReactUpdates(); + }); + + // -------- setup -------- + require("./util/coverage"); + // ----------------------- + + // ---- All the tests ---- + require("./history"); + require("./layers"); + require("./map"); + require("./modals"); + // require("./screenshots"); + // ------------------------ + +}); + diff --git a/test/functional/layers/index.js b/test/functional/layers/index.js new file mode 100644 index 00000000..d8f4acfd --- /dev/null +++ b/test/functional/layers/index.js @@ -0,0 +1,497 @@ +var assert = require("assert"); +var config = require("../../config/specs"); +var helper = require("../helper"); +var uuid = require('uuid/v1'); +var wd = require("../../wd-helper"); + + +describe("layers", function() { + beforeEach(function() { + browser.url(config.baseUrl+"?debug&style="+helper.getStyleUrl([ + "geojson:example", + "raster:raster" + ])); + browser.waitForExist(".maputnik-toolbar-link"); + browser.flushReactUpdates(); + + helper.modal.addLayer.open(); + }); + + describe("ops", function() { + it("delete", function() { + var styleObj; + var id = helper.modal.addLayer.fill({ + type: "background" + }) + + styleObj = helper.getStyleStore(browser); + assert.deepEqual(styleObj.layers, [ + { + "id": id, + "type": 'background' + }, + ]); + + browser.click(wd.$("layer-list-item:"+id+":delete", "")); + + styleObj = helper.getStyleStore(browser); + assert.deepEqual(styleObj.layers, [ + ]); + }); + + it("duplicate", function() { + var styleObj; + var id = helper.modal.addLayer.fill({ + type: "background" + }) + + styleObj = helper.getStyleStore(browser); + assert.deepEqual(styleObj.layers, [ + { + "id": id, + "type": 'background' + }, + ]); + + browser.click(wd.$("layer-list-item:"+id+":copy", "")); + + styleObj = helper.getStyleStore(browser); + assert.deepEqual(styleObj.layers, [ + { + "id": id+"-copy", + "type": "background" + }, + { + "id": id, + "type": "background" + }, + ]); + }); + + it("hide", function() { + var styleObj; + var id = helper.modal.addLayer.fill({ + type: "background" + }) + + styleObj = helper.getStyleStore(browser); + assert.deepEqual(styleObj.layers, [ + { + "id": id, + "type": 'background' + }, + ]); + + browser.click(wd.$("layer-list-item:"+id+":toggle-visibility", "")); + + styleObj = helper.getStyleStore(browser); + assert.deepEqual(styleObj.layers, [ + { + "id": id, + "type": "background", + "layout": { + "visibility": "none" + } + }, + ]); + + browser.click(wd.$("layer-list-item:"+id+":toggle-visibility", "")); + + styleObj = helper.getStyleStore(browser); + assert.deepEqual(styleObj.layers, [ + { + "id": id, + "type": "background", + "layout": { + "visibility": "visible" + } + }, + ]); + }) + }) + + describe("grouped", function() { + it("with underscore") + it("no without underscore") + it("double underscore only grouped once") + }) + + describe("tooltips", function() { + }) + + describe("help", function() { + }) + + + describe('background', function () { + + it.skip("add", function() { + var id = helper.modal.addLayer.fill({ + type: "background" + }) + + browser.waitUntil(function() { + var styleObj = helper.getStyleStore(browser); + assert.deepEqual(styleObj.layers, [ + { + "id": id, + "type": 'background' + } + ]); + }); + }); + + describe("modify", function() { + function createBackground() { + // Setup + var id = uuid(); + + browser.selectByValue(wd.$("add-layer.layer-type", "select"), "background"); + browser.flushReactUpdates(); + browser.setValueSafe(wd.$("add-layer.layer-id", "input"), "background:"+id); + + browser.click(wd.$("add-layer")); + + var styleObj = helper.getStyleStore(browser); + assert.deepEqual(styleObj.layers, [ + { + "id": 'background:'+id, + "type": 'background' + } + ]); + return id; + } + + // ====> THESE SHOULD BE FROM THE SPEC + describe("layer", function() { + it("expand/collapse"); + it("id", function() { + var bgId = createBackground(); + + browser.click(wd.$("layer-list-item:background:"+bgId)) + + var id = uuid(); + browser.setValueSafe(wd.$("layer-editor.layer-id", "input"), "foobar:"+id) + browser.click(wd.$("min-zoom")) + + var styleObj = helper.getStyleStore(browser); + assert.deepEqual(styleObj.layers, [ + { + "id": 'foobar:'+id, + "type": 'background' + } + ]); + }); + + // NOTE: This needs to be removed from the code + it("type"); + + it("min-zoom", function() { + var bgId = createBackground(); + + browser.click(wd.$("layer-list-item:background:"+bgId)) + browser.setValueSafe(wd.$("min-zoom", "input"), 1) + browser.click(wd.$("layer-editor.layer-id", "input")); + + var styleObj = helper.getStyleStore(browser); + console.log("styleObj", styleObj); + assert.deepEqual(styleObj.layers, [ + { + "id": 'background:'+bgId, + "type": 'background', + "minzoom": 1 + } + ]); + + // AND RESET! + // browser.setValueSafe(wd.$("min-zoom", "input"), "") + // browser.click(wd.$("max-zoom", "input")); + + // var styleObj = helper.getStyleStore(browser); + // console.log("styleObj", styleObj); + + // assert.deepEqual(styleObj.layers, [ + // { + // "id": 'background:'+bgId, + // "type": 'background' + // } + // ]); + }); + + it("max-zoom", function() { + var bgId = createBackground(); + + browser.click(wd.$("layer-list-item:background:"+bgId)) + browser.setValueSafe(wd.$("max-zoom", "input"), 1) + browser.click(wd.$("layer-editor.layer-id", "input")); + + var styleObj = helper.getStyleStore(browser); + console.log("styleObj", styleObj); + assert.deepEqual(styleObj.layers, [ + { + "id": 'background:'+bgId, + "type": 'background', + "maxzoom": 1 + } + ]); + }); + + it("comments", function() { + var bgId = createBackground(); + var id = uuid(); + + browser.click(wd.$("layer-list-item:background:"+bgId)); + browser.setValueSafe(wd.$("layer-comment", "textarea"), id); + browser.click(wd.$("layer-editor.layer-id", "input")); + + var styleObj = helper.getStyleStore(browser); + console.log("styleObj", styleObj); + assert.deepEqual(styleObj.layers, [ + { + "id": 'background:'+bgId, + "type": 'background', + metadata: { + 'maputnik:comment': id + } + } + ]); + + // Unset it again. + // TODO: This fails + // browser.setValueSafe(wd.$("layer-comment", "textarea"), ""); + // browser.click(wd.$("min-zoom", "input")); + // browser.flushReactUpdates(); + + // var styleObj = helper.getStyleStore(browser); + // console.log("styleObj", styleObj); + // assert.deepEqual(styleObj.layers, [ + // { + // "id": 'background:'+bgId, + // "type": 'background' + // } + // ]); + }); + + it("color", null, function() { + var bgId = createBackground(); + var id = uuid(); + + browser.click(wd.$("layer-list-item:background:"+bgId)); + + browser.click(wd.$("spec-field:background-color", "input")) + // browser.debug(); + + var styleObj = helper.getStyleStore(browser); + console.log("styleObj", styleObj); + assert.deepEqual(styleObj.layers, [ + { + "id": 'background:'+bgId, + "type": 'background' + } + ]); + + }) + }) + + describe("filter", function() { + it("expand/collapse"); + it("compound filter"); + }) + + describe("paint", function() { + it("expand/collapse"); + it("color"); + it("pattern"); + it("opacity"); + }) + // <===== + + describe("json-editor", function() { + it("expand/collapse"); + it("modify"); + + // TODO + it.skip("parse error", function() { + var bgId = createBackground(); + var id = uuid(); + + browser.click(wd.$("layer-list-item:background:"+bgId)); + + var errorSelector = ".CodeMirror-lint-marker-error"; + assert.equal(browser.isExisting(errorSelector), false); + + browser.click(".CodeMirror") + browser.keys("\uE013\uE013\uE013\uE013\uE013\uE013\uE013\uE013\uE013\uE013\uE013\uE013 {"); + browser.waitForExist(errorSelector) + + browser.click(wd.$("layer-editor.layer-id")); + }); + }); + }) + }); + + describe('fill', function () { + it.skip("add", function() { + // browser.debug(); + + var id = helper.modal.addLayer.fill({ + type: "fill", + layer: "example" + }); + + var styleObj = helper.getStyleStore(browser); + console.log("STYLEOBJ", styleObj); + assert.deepEqual(styleObj.layers, [ + { + "id": id, + "type": 'fill', + "source": "example" + } + ]); + }) + + // TODO: Change source + it("change source") + }); + + describe('line', function () { + it.skip("add", function() { + var id = helper.modal.addLayer.fill({ + type: "line", + layer: "example" + }); + + var styleObj = helper.getStyleStore(browser); + assert.deepEqual(styleObj.layers, [ + { + "id": id, + "type": "line", + "source": "example", + } + ]); + }); + + it("groups", null, function() { + // TODO + // Click each of the layer groups. + }) + }); + + describe('symbol', function () { + it.skip("add", function() { + var id = helper.modal.addLayer.fill({ + type: "symbol", + layer: "example" + }); + + var styleObj = helper.getStyleStore(browser); + assert.deepEqual(styleObj.layers, [ + { + "id": id, + "type": "symbol", + "source": "example", + } + ]); + }); + }); + + describe('raster', function () { + it.skip("add", function() { + var id = helper.modal.addLayer.fill({ + type: "raster", + layer: "raster" + }); + + var styleObj = helper.getStyleStore(browser); + assert.deepEqual(styleObj.layers, [ + { + "id": id, + "type": "raster", + "source": "raster", + } + ]); + }); + }); + + describe('circle', function () { + it.skip("add", function() { + var id = helper.modal.addLayer.fill({ + type: "circle", + layer: "example" + }); + + var styleObj = helper.getStyleStore(browser); + assert.deepEqual(styleObj.layers, [ + { + "id": id, + "type": "circle", + "source": "example", + } + ]); + }); + + }); + + describe('fill extrusion', function () { + it.skip("add", function() { + var id = helper.modal.addLayer.fill({ + type: "fill-extrusion", + layer: "example" + }); + + var styleObj = helper.getStyleStore(browser); + assert.deepEqual(styleObj.layers, [ + { + "id": id, + "type": 'fill-extrusion', + "source": "example" + } + ]); + }); + }); + + // These get used in the marketing material. They are also useful to do a quick manual check of the styling across browsers + // NOTE: These duplicate some of the tests, however this is indended becuase it's likely these will change for aesthetic reasons over time + // + + + + describe.skip("groups", function() { + it("simple", function() { + browser.url(config.baseUrl+"?debug&style="+getStyleUrl([ + "geojson:example" + ])); + + helper.modal.addLayer.open(); + var aId = helper.modal.addLayer.fill({ + id: "foo", + type: "background" + }) + + helper.modal.addLayer.open(); + var bId = helper.modal.addLayer.fill({ + id: "foo_bar", + type: "background" + }) + + helper.modal.addLayer.open(); + var bId = helper.modal.addLayer.fill({ + id: "foo_baz", + type: "background" + }) + + browser.waitForExist(wd.$("layer-list-group:foo-0")); + + assert.equal(browser.isVisibleWithinViewport(wd.$("layer-list-item:foo")), false); + assert.equal(browser.isVisibleWithinViewport(wd.$("layer-list-item:foo_bar")), false); + assert.equal(browser.isVisibleWithinViewport(wd.$("layer-list-item:foo_baz")), false); + + browser.click(wd.$("layer-list-group:foo-0")); + + assert.equal(browser.isVisibleWithinViewport(wd.$("layer-list-item:foo")), true); + assert.equal(browser.isVisibleWithinViewport(wd.$("layer-list-item:foo_bar")), true); + assert.equal(browser.isVisibleWithinViewport(wd.$("layer-list-item:foo_baz")), true); + }) + }) +}); + diff --git a/test/functional/map/index.js b/test/functional/map/index.js new file mode 100644 index 00000000..498c0a1d --- /dev/null +++ b/test/functional/map/index.js @@ -0,0 +1,35 @@ +var assert = require('assert'); +var wd = require("../../wd-helper"); +var config = require("../../config/specs"); +var helper = require("../helper"); + + +describe("map", function() { + describe.skip("zoom level", function() { + it("via url", function() { + var zoomLevel = "12.37" + browser.url(config.baseUrl+"?debug&style="+helper.getStyleUrl([ + "geojson:example" + ])+"#"+zoomLevel+"/41.3805/2.1635"); + + browser.waitUntil(function () { + return ( + browser.isVisible(".mapboxgl-ctrl-zoom") + && browser.getText(".mapboxgl-ctrl-zoom") === "Zoom level: "+(zoomLevel) + ); + }, 10*1000) + }) + it("via map controls", function() { + var zoomLevel = 12.37; + browser.url(config.baseUrl+"?debug&style="+helper.getStyleUrl([ + "geojson:example" + ])+"#"+zoomLevel+"/41.3805/2.1635"); + + browser.click(".mapboxgl-ctrl-zoom-in") + browser.waitUntil(function () { + var text = browser.getText(".mapboxgl-ctrl-zoom") + return text === "Zoom level: "+(zoomLevel+1); + }, 10*1000) + }) + }) +}) diff --git a/test/functional/modals/index.js b/test/functional/modals/index.js new file mode 100644 index 00000000..3a5a897a --- /dev/null +++ b/test/functional/modals/index.js @@ -0,0 +1,203 @@ +var assert = require('assert'); +var fs = require("fs"); +var wd = require("../../wd-helper"); +var config = require("../../config/specs"); +var helper = require("../helper"); + + + +// TODO: Is this needed? +function closeModal(wdKey) { + console.log(">> A"); + browser.waitUntil(function() { + return browser.isVisibleWithinViewport(wd.$(wdKey)); + }); + + console.log(">> B"); + var closeBtnSelector = wd.$(wdKey+".close-modal"); + browser.click(closeBtnSelector); + + console.log(">> C"); + browser.waitUntil(function() { + return !browser.isVisibleWithinViewport(wd.$(wdKey)); + }); +} + +describe("modals", function() { + describe("open", function() { + var styleFilePath = __dirname+"/../../example-style.json"; + var styleFileData = JSON.parse(fs.readFileSync(styleFilePath)); + + beforeEach(function() { + browser.url(config.baseUrl+"?debug"); + + browser.waitForExist(".maputnik-toolbar-link"); + browser.flushReactUpdates(); + + browser.click(wd.$("nav:open")) + browser.flushReactUpdates(); + }); + + it("close", function() { + closeModal("open-modal"); + }); + + it("upload", function() { + browser.waitForExist("*[type='file']") + browser.chooseFile("*[type='file']", styleFilePath); + + var styleObj = helper.getStyleStore(browser); + console.log("styleObj", styleObj); + assert.deepEqual(styleFileData, styleObj); + }); + + it("load from url", function() { + var styleFileUrl = helper.getGeoServerUrl("example-style.json"); + + browser.setValueSafe(wd.$("open-modal.url.input"), styleFileUrl); + + var selector = wd.$("open-modal.url.button"); + console.log("selector", selector); + browser.click(selector); + + // Allow the network request to happen + // NOTE: Its localhost so this should be fast. + browser.pause(300); + + var styleObj = helper.getStyleStore(browser); + console.log("styleObj", styleObj); + console.log("styleFileData", styleFileData); + assert.deepEqual(styleFileData, styleObj); + }); + + // TODO: Need to work out how to mock out the end points + it("gallery") + }) + + describe("export", function() { + + beforeEach(function() { + browser.url(config.baseUrl+"?debug"); + + browser.waitForExist(".maputnik-toolbar-link"); + browser.flushReactUpdates(); + + browser.click(wd.$("nav:export")) + browser.flushReactUpdates(); + }); + + it("close", function() { + closeModal("export-modal"); + }); + + // TODO: Work out how to download a file and check the contents + it("download") + // TODO: Work out how to mock the end git points + it("save to gist") + }) + + describe("sources", function() { + it("active sources") + it("public source") + it("add new source") + }) + + describe("inspect", function() { + it("toggle", function() { + browser.url(config.baseUrl+"?debug&style="+helper.getStyleUrl([ + "geojson:example" + ])); + + browser.click(wd.$("nav:inspect")); + }) + }) + + describe("style settings", function() { + beforeEach(function() { + browser.url(config.baseUrl+"?debug"); + + browser.waitForExist(".maputnik-toolbar-link"); + browser.flushReactUpdates(); + + browser.click(wd.$("nav:settings")) + browser.flushReactUpdates(); + }); + + it("name", function() { + browser.setValueSafe(wd.$("modal-settings.name"), "foobar") + browser.click(wd.$("modal-settings.owner")) + browser.flushReactUpdates(); + + var styleObj = helper.getStyleStore(browser); + console.log("styleObj", styleObj); + assert.equal(styleObj.name, "foobar"); + }) + it("owner", function() { + browser.setValueSafe(wd.$("modal-settings.owner"), "foobar") + browser.click(wd.$("modal-settings.name")) + browser.flushReactUpdates(); + + var styleObj = helper.getStyleStore(browser); + console.log("styleObj", styleObj); + assert.equal(styleObj.owner, "foobar"); + }) + it("sprite url", function() { + browser.setValueSafe(wd.$("modal-settings.sprite"), "http://example.com") + browser.click(wd.$("modal-settings.name")) + browser.flushReactUpdates(); + + var styleObj = helper.getStyleStore(browser); + console.log("styleObj", styleObj); + assert.equal(styleObj.sprite, "http://example.com"); + }) + it("glyphs url", function() { + var glyphsUrl = "http://example.com/{fontstack}/{range}.pbf" + browser.setValueSafe(wd.$("modal-settings.glyphs"), glyphsUrl) + browser.click(wd.$("modal-settings.name")) + browser.flushReactUpdates(); + + var styleObj = helper.getStyleStore(browser); + console.log("styleObj", styleObj); + assert.equal(styleObj.glyphs, glyphsUrl); + }) + + it("mapbox access token", function() { + var apiKey = "testing123"; + browser.setValueSafe(wd.$("modal-settings.maputnik:mapbox_access_token"), apiKey); + browser.click(wd.$("modal-settings.name")) + browser.flushReactUpdates(); + + var styleObj = helper.getStyleStore(browser); + console.log("styleObj", styleObj); + browser.waitUntil(function() { + return styleObj.metadata["maputnik:mapbox_access_token"] == apiKey; + }) + }) + + it("open map tiles access token", function() { + var apiKey = "testing123"; + browser.setValueSafe(wd.$("modal-settings.maputnik:openmaptiles_access_token"), apiKey); + browser.click(wd.$("modal-settings.name")) + browser.flushReactUpdates(); + + var styleObj = helper.getStyleStore(browser); + console.log("styleObj", styleObj); + assert.equal(styleObj.metadata["maputnik:openmaptiles_access_token"], apiKey); + }) + + it("style renderer", function() { + var selector = wd.$("modal-settings.maputnik:renderer"); + browser.selectByValue(selector, "ol3"); + browser.click(wd.$("modal-settings.name")) + browser.flushReactUpdates(); + + var styleObj = helper.getStyleStore(browser); + console.log("styleObj", styleObj); + assert.equal(styleObj.metadata["maputnik:renderer"], "ol3"); + }) + }) + + describe("sources", function() { + it("toggle") + }) +}) diff --git a/test/functional/screenshots/index.js b/test/functional/screenshots/index.js new file mode 100644 index 00000000..ad206b48 --- /dev/null +++ b/test/functional/screenshots/index.js @@ -0,0 +1,93 @@ +var artifacts = require("../../artifacts"); +var config = require("../../config/specs"); +var helper = require("../helper"); +var wd = require("../../wd-helper"); + +var SCREENSHOTS_PATH = artifacts.pathSync("/screenshots"); + + +describe('screenshots', function() { + + beforeEach(function() { + browser.windowHandleSize({ + width: 1280, + height: 800 + }); + }) + + it("front_page", function() { + browser.url(config.baseUrl+"?debug&style="+helper.getStyleUrl([ + "geojson:example" + ])); + browser.waitForExist(".maputnik-toolbar-link"); + browser.flushReactUpdates(); + + browser.takeScreenShot("/front_page.png") + }) + + it("open", function() { + browser.url(config.baseUrl+"?debug&style="+helper.getStyleUrl([ + "geojson:example" + ])); + browser.waitForExist(".maputnik-toolbar-link"); + browser.flushReactUpdates(); + + browser.click(wd.$("nav:open")) + browser.flushReactUpdates(); + + browser.takeScreenShot("/open.png") + }) + + it("export", function() { + browser.url(config.baseUrl+"?debug&style="+helper.getStyleUrl([ + "geojson:example" + ])); + browser.waitForExist(".maputnik-toolbar-link"); + browser.flushReactUpdates(); + + browser.click(wd.$("nav:export")) + browser.flushReactUpdates(); + + browser.takeScreenShot("/export.png") + }) + + it("sources", function() { + browser.url(config.baseUrl+"?debug&style="+helper.getStyleUrl([ + "geojson:example" + ])); + browser.waitForExist(".maputnik-toolbar-link"); + browser.flushReactUpdates(); + + browser.click(wd.$("nav:sources")) + browser.flushReactUpdates(); + + browser.takeScreenShot("/sources.png") + }) + + it("style settings", function() { + browser.url(config.baseUrl+"?debug&style="+helper.getStyleUrl([ + "geojson:example" + ])); + browser.waitForExist(".maputnik-toolbar-link"); + browser.flushReactUpdates(); + + browser.click(wd.$("nav:settings")) + browser.flushReactUpdates(); + + browser.takeScreenShot("/settings.png") + }) + + it("inspect", function() { + browser.url(config.baseUrl+"?debug&style="+helper.getStyleUrl([ + "geojson:example" + ])); + browser.waitForExist(".maputnik-toolbar-link"); + browser.flushReactUpdates(); + + browser.click(wd.$("nav:inspect")) + browser.flushReactUpdates(); + + browser.takeScreenShot("/inspect.png") + }) +}) + diff --git a/test/functional/util/coverage.js b/test/functional/util/coverage.js new file mode 100644 index 00000000..335decd1 --- /dev/null +++ b/test/functional/util/coverage.js @@ -0,0 +1,26 @@ +var artifacts = require("../../artifacts"); +var fs = require("fs"); +var istanbulCov = require('istanbul-lib-coverage'); + +var COVERAGE_PATH = artifacts.pathSync("/coverage"); + + +var coverage = istanbulCov.createCoverageMap({}); + +describe("coverage", function() { + // Capture the coverage after each test + afterEach(function() { + // Code coverage + var results = browser.execute(function() { + return window.__coverage__; + }); + + coverage.merge(results.value); + }) + + // Dump the coverage to a file + after(function() { + var jsonStr = JSON.stringify(coverage, null, 2); + fs.writeFileSync(COVERAGE_PATH+"/coverage.json", jsonStr); + }) +}) diff --git a/test/functional/util/webdriverio-ext.js b/test/functional/util/webdriverio-ext.js new file mode 100644 index 00000000..bfd7fbbd --- /dev/null +++ b/test/functional/util/webdriverio-ext.js @@ -0,0 +1,56 @@ +browser.timeoutsAsyncScript(10*1000); +browser.timeoutsImplicitWait(10*1000); + +/** + * Sometimes chrome driver can result in the wrong text. + * + * See + */ +try { + browser.addCommand('setValueSafe', function(selector, text) { + for(var i=0; i<10; i++) { + console.log(">>>> waiting for visible"); + browser.waitForVisible(selector); + + var elements = browser.elements(selector); + if(elements.length > 1) { + console.error(">>> Too many elements found"); + throw "Too many elements found"; + } + + console.log(">>>> setting value"); + browser.setValue(selector, text); + var browserText = browser.getValue(selector); + + console.log("browserText='%s' test='%s'", browserText, text); + + if(browserText == text) { + return; + } + else { + console.error("Warning: setValue failed, trying again"); + } + } + + // Wait for change events to fire and state updated + browser.flushReactUpdates(); + }) + + browser.addCommand('takeScreenShot', function(filepath) { + var data = browser.screenshot(); + fs.writeFileSync(path.join(SCREENSHOTS_PATH, filepath), data.value, 'base64'); + }); + + browser.addCommand('flushReactUpdates', function() { + browser.executeAsync(function(done) { + // For any events to propogate + setImmediate(function() { + // For the DOM to be updated. + setImmediate(done); + }) + }) + }) + +} catch(err) { + console.error(">>> Ignored error: "+err); +} From 2e8a188bce82d9010ab65a2ddef5656fa27aac76 Mon Sep 17 00:00:00 2001 From: orangemug Date: Wed, 17 Jan 2018 14:51:25 +0000 Subject: [PATCH 03/48] Increased timeouts. --- test/functional/util/webdriverio-ext.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/functional/util/webdriverio-ext.js b/test/functional/util/webdriverio-ext.js index bfd7fbbd..26f91348 100644 --- a/test/functional/util/webdriverio-ext.js +++ b/test/functional/util/webdriverio-ext.js @@ -1,5 +1,5 @@ -browser.timeoutsAsyncScript(10*1000); -browser.timeoutsImplicitWait(10*1000); +browser.timeoutsAsyncScript(20*1000); +browser.timeoutsImplicitWait(20*1000); /** * Sometimes chrome driver can result in the wrong text. From 1eb6c28617f08afcdf8f53583bb9ea2a6166319d Mon Sep 17 00:00:00 2001 From: orangemug Date: Wed, 17 Jan 2018 14:59:48 +0000 Subject: [PATCH 04/48] Removed logging. --- test/functional/history/index.js | 10 ---------- test/functional/layers/index.js | 7 ------- test/functional/modals/index.js | 14 -------------- test/functional/util/webdriverio-ext.js | 5 ----- 4 files changed, 36 deletions(-) diff --git a/test/functional/history/index.js b/test/functional/history/index.js index 41895562..d699c075 100644 --- a/test/functional/history/index.js +++ b/test/functional/history/index.js @@ -51,8 +51,6 @@ describe.skip("history", function() { } ]); - console.log(">>> LOGS", JSON.stringify(browser.log("browser"), null, 2)) - browser .keys(['Control', 'z']) .keys(['Control']); @@ -64,8 +62,6 @@ describe.skip("history", function() { } ]); - console.log(">>> LOGS", JSON.stringify(browser.log("browser"), null, 2)) - browser .keys(['Control', 'z']) .keys(['Control']); @@ -73,8 +69,6 @@ describe.skip("history", function() { assert.deepEqual(styleObj.layers, [ ]); - console.log(">>> LOGS", JSON.stringify(browser.log("browser"), null, 2)) - browser .keys(['Control', 'y']) .keys(['Control']); @@ -86,8 +80,6 @@ describe.skip("history", function() { } ]); - console.log(">>> LOGS", JSON.stringify(browser.log("browser"), null, 2)) - browser .keys(['Control', 'y']) .keys(['Control']); @@ -103,7 +95,6 @@ describe.skip("history", function() { } ]); - console.log(">>> LOGS", JSON.stringify(browser.log("browser"), null, 2)) }); @@ -123,7 +114,6 @@ describe.skip("history", function() { // helper.modalCommands.addLayer.open(browser); // styleObj = helper.helper.getStyleStore(browser); - // console.log("styleObj", styleObj); // assert.deepEqual(styleObj.layers, []); // helper.modalCommands.addLayer.fill(browser, { diff --git a/test/functional/layers/index.js b/test/functional/layers/index.js index d8f4acfd..14c5d797 100644 --- a/test/functional/layers/index.js +++ b/test/functional/layers/index.js @@ -194,7 +194,6 @@ describe("layers", function() { browser.click(wd.$("layer-editor.layer-id", "input")); var styleObj = helper.getStyleStore(browser); - console.log("styleObj", styleObj); assert.deepEqual(styleObj.layers, [ { "id": 'background:'+bgId, @@ -208,7 +207,6 @@ describe("layers", function() { // browser.click(wd.$("max-zoom", "input")); // var styleObj = helper.getStyleStore(browser); - // console.log("styleObj", styleObj); // assert.deepEqual(styleObj.layers, [ // { @@ -226,7 +224,6 @@ describe("layers", function() { browser.click(wd.$("layer-editor.layer-id", "input")); var styleObj = helper.getStyleStore(browser); - console.log("styleObj", styleObj); assert.deepEqual(styleObj.layers, [ { "id": 'background:'+bgId, @@ -245,7 +242,6 @@ describe("layers", function() { browser.click(wd.$("layer-editor.layer-id", "input")); var styleObj = helper.getStyleStore(browser); - console.log("styleObj", styleObj); assert.deepEqual(styleObj.layers, [ { "id": 'background:'+bgId, @@ -263,7 +259,6 @@ describe("layers", function() { // browser.flushReactUpdates(); // var styleObj = helper.getStyleStore(browser); - // console.log("styleObj", styleObj); // assert.deepEqual(styleObj.layers, [ // { // "id": 'background:'+bgId, @@ -282,7 +277,6 @@ describe("layers", function() { // browser.debug(); var styleObj = helper.getStyleStore(browser); - console.log("styleObj", styleObj); assert.deepEqual(styleObj.layers, [ { "id": 'background:'+bgId, @@ -340,7 +334,6 @@ describe("layers", function() { }); var styleObj = helper.getStyleStore(browser); - console.log("STYLEOBJ", styleObj); assert.deepEqual(styleObj.layers, [ { "id": id, diff --git a/test/functional/modals/index.js b/test/functional/modals/index.js index 3a5a897a..24f9ffd5 100644 --- a/test/functional/modals/index.js +++ b/test/functional/modals/index.js @@ -8,16 +8,13 @@ var helper = require("../helper"); // TODO: Is this needed? function closeModal(wdKey) { - console.log(">> A"); browser.waitUntil(function() { return browser.isVisibleWithinViewport(wd.$(wdKey)); }); - console.log(">> B"); var closeBtnSelector = wd.$(wdKey+".close-modal"); browser.click(closeBtnSelector); - console.log(">> C"); browser.waitUntil(function() { return !browser.isVisibleWithinViewport(wd.$(wdKey)); }); @@ -47,7 +44,6 @@ describe("modals", function() { browser.chooseFile("*[type='file']", styleFilePath); var styleObj = helper.getStyleStore(browser); - console.log("styleObj", styleObj); assert.deepEqual(styleFileData, styleObj); }); @@ -57,7 +53,6 @@ describe("modals", function() { browser.setValueSafe(wd.$("open-modal.url.input"), styleFileUrl); var selector = wd.$("open-modal.url.button"); - console.log("selector", selector); browser.click(selector); // Allow the network request to happen @@ -65,8 +60,6 @@ describe("modals", function() { browser.pause(300); var styleObj = helper.getStyleStore(browser); - console.log("styleObj", styleObj); - console.log("styleFileData", styleFileData); assert.deepEqual(styleFileData, styleObj); }); @@ -129,7 +122,6 @@ describe("modals", function() { browser.flushReactUpdates(); var styleObj = helper.getStyleStore(browser); - console.log("styleObj", styleObj); assert.equal(styleObj.name, "foobar"); }) it("owner", function() { @@ -138,7 +130,6 @@ describe("modals", function() { browser.flushReactUpdates(); var styleObj = helper.getStyleStore(browser); - console.log("styleObj", styleObj); assert.equal(styleObj.owner, "foobar"); }) it("sprite url", function() { @@ -147,7 +138,6 @@ describe("modals", function() { browser.flushReactUpdates(); var styleObj = helper.getStyleStore(browser); - console.log("styleObj", styleObj); assert.equal(styleObj.sprite, "http://example.com"); }) it("glyphs url", function() { @@ -157,7 +147,6 @@ describe("modals", function() { browser.flushReactUpdates(); var styleObj = helper.getStyleStore(browser); - console.log("styleObj", styleObj); assert.equal(styleObj.glyphs, glyphsUrl); }) @@ -168,7 +157,6 @@ describe("modals", function() { browser.flushReactUpdates(); var styleObj = helper.getStyleStore(browser); - console.log("styleObj", styleObj); browser.waitUntil(function() { return styleObj.metadata["maputnik:mapbox_access_token"] == apiKey; }) @@ -181,7 +169,6 @@ describe("modals", function() { browser.flushReactUpdates(); var styleObj = helper.getStyleStore(browser); - console.log("styleObj", styleObj); assert.equal(styleObj.metadata["maputnik:openmaptiles_access_token"], apiKey); }) @@ -192,7 +179,6 @@ describe("modals", function() { browser.flushReactUpdates(); var styleObj = helper.getStyleStore(browser); - console.log("styleObj", styleObj); assert.equal(styleObj.metadata["maputnik:renderer"], "ol3"); }) }) diff --git a/test/functional/util/webdriverio-ext.js b/test/functional/util/webdriverio-ext.js index 26f91348..2a2edfd1 100644 --- a/test/functional/util/webdriverio-ext.js +++ b/test/functional/util/webdriverio-ext.js @@ -9,21 +9,16 @@ browser.timeoutsImplicitWait(20*1000); try { browser.addCommand('setValueSafe', function(selector, text) { for(var i=0; i<10; i++) { - console.log(">>>> waiting for visible"); browser.waitForVisible(selector); var elements = browser.elements(selector); if(elements.length > 1) { - console.error(">>> Too many elements found"); throw "Too many elements found"; } - console.log(">>>> setting value"); browser.setValue(selector, text); var browserText = browser.getValue(selector); - console.log("browserText='%s' test='%s'", browserText, text); - if(browserText == text) { return; } From ad34147f28458940726f086691ba0d8c81a4165c Mon Sep 17 00:00:00 2001 From: orangemug Date: Wed, 17 Jan 2018 15:39:17 +0000 Subject: [PATCH 05/48] Fixed screenshots. --- test/functional/index.js | 2 +- test/functional/screenshots/index.js | 2 -- test/functional/util/webdriverio-ext.js | 7 +++++++ 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/test/functional/index.js b/test/functional/index.js index 34d5e626..7f9b5322 100644 --- a/test/functional/index.js +++ b/test/functional/index.js @@ -26,7 +26,7 @@ describe('maputnik', function() { require("./layers"); require("./map"); require("./modals"); - // require("./screenshots"); + require("./screenshots"); // ------------------------ }); diff --git a/test/functional/screenshots/index.js b/test/functional/screenshots/index.js index ad206b48..b64d0c9c 100644 --- a/test/functional/screenshots/index.js +++ b/test/functional/screenshots/index.js @@ -3,8 +3,6 @@ var config = require("../../config/specs"); var helper = require("../helper"); var wd = require("../../wd-helper"); -var SCREENSHOTS_PATH = artifacts.pathSync("/screenshots"); - describe('screenshots', function() { diff --git a/test/functional/util/webdriverio-ext.js b/test/functional/util/webdriverio-ext.js index 2a2edfd1..ee35b486 100644 --- a/test/functional/util/webdriverio-ext.js +++ b/test/functional/util/webdriverio-ext.js @@ -1,6 +1,13 @@ +var artifacts = require("../../artifacts"); +var fs = require("fs"); +var path = require("path"); + + browser.timeoutsAsyncScript(20*1000); browser.timeoutsImplicitWait(20*1000); +var SCREENSHOTS_PATH = artifacts.pathSync("/screenshots"); + /** * Sometimes chrome driver can result in the wrong text. * From 0c2934c4899a2402c7099d0c934192be9ef257ca Mon Sep 17 00:00:00 2001 From: orangemug Date: Wed, 17 Jan 2018 15:44:00 +0000 Subject: [PATCH 06/48] Code to store artifacts on circle ci --- .circleci/config.yml | 2 ++ test/artifacts.js | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index f78c4ee5..d6e8922e 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -25,3 +25,5 @@ jobs: - run: DOCKER_HOST=localhost npm test - run: npm run build - run: ./node_modules/.bin/istanbul report --include /tmp/artifacts/coverage/coverage.json --dir /tmp/artifacts/coverage html lcov + - store_artifacts: + path: /tmp/artifacts diff --git a/test/artifacts.js b/test/artifacts.js index 73943aad..efebbe9b 100644 --- a/test/artifacts.js +++ b/test/artifacts.js @@ -6,8 +6,8 @@ function genPath(subPath) { subPath = subPath || "."; var buildPath; - if(process.env.CIRCLE_ARTIFACTS) { - buildPath = path.join(process.env.CIRCLE_ARTIFACTS, subPath); + if(process.env.CIRCLECI) { + buildPath = path.join("/tmp/artifacts", subPath); } else { buildPath = path.join(__dirname, '..', 'build', subPath); From c1312fb28816c5e92005296079234a79ca071c1c Mon Sep 17 00:00:00 2001 From: orangemug Date: Wed, 17 Jan 2018 15:46:48 +0000 Subject: [PATCH 07/48] Added '/build' to .gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 83a8308f..af33419d 100644 --- a/.gitignore +++ b/.gitignore @@ -32,3 +32,4 @@ node_modules public /errorShots /old +/build From 211850c81327b3b6308f8253a8c98d0a3b1c558c Mon Sep 17 00:00:00 2001 From: orangemug Date: Wed, 17 Jan 2018 16:53:42 +0000 Subject: [PATCH 08/48] Added cross-env --- package-lock.json | 16 ++++++++++++++++ package.json | 5 +++-- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 51652f84..cdf2cdd9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2771,6 +2771,16 @@ "object-assign": "4.1.1" } }, + "cross-env": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-5.1.3.tgz", + "integrity": "sha512-UOokgwvDzCT0mqRSLEkJzUhYXB1vK3E5UgDrD41QiXsm9UetcW2rCGHYz/O3p873lMJ1VZbFCF9Izkwh7nYR5A==", + "dev": true, + "requires": { + "cross-spawn": "5.1.0", + "is-windows": "1.0.1" + } + }, "cross-spawn": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", @@ -6085,6 +6095,12 @@ "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", "dev": true }, + "is-windows": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.1.tgz", + "integrity": "sha1-MQ23D3QtJZoWo2kgK1GvhCMzENk=", + "dev": true + }, "is-wsl": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", diff --git a/package.json b/package.json index ba5d9e03..7e8b5086 100644 --- a/package.json +++ b/package.json @@ -6,8 +6,8 @@ "scripts": { "stats": "webpack --config config/webpack.production.config.js --profile --json > stats.json", "build": "webpack --config config/webpack.production.config.js --progress --profile --colors", - "test": "wdio config/wdio.conf.js", - "test-watch": "wdio config/wdio.conf.js --watch", + "test": "cross-env NODE_ENV=test wdio config/wdio.conf.js", + "test-watch": "cross-env NODE_ENV=test wdio config/wdio.conf.js --watch", "start": "webpack-dev-server --progress --profile --colors --config config/webpack.config.js", "lint": "eslint --ext js --ext jsx {src,test}", "lint-styles": "stylelint 'src/styles/*.scss'" @@ -103,6 +103,7 @@ "base64-loader": "^1.0.0", "copy-webpack-plugin": "^4.2.0", "cors": "^2.8.4", + "cross-env": "^5.1.3", "css-loader": "^0.28.7", "eslint": "^4.10.0", "eslint-plugin-react": "^7.4.0", From bc19aea4387b29e4aabb34eb86a4512b855c2380 Mon Sep 17 00:00:00 2001 From: orangemug Date: Wed, 17 Jan 2018 17:01:55 +0000 Subject: [PATCH 09/48] CircleCI test now just calls npm test --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index d6e8922e..c194ce86 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -24,6 +24,6 @@ jobs: - run: mkdir -p /tmp/artifacts/logs - run: DOCKER_HOST=localhost npm test - run: npm run build - - run: ./node_modules/.bin/istanbul report --include /tmp/artifacts/coverage/coverage.json --dir /tmp/artifacts/coverage html lcov + - run: npm test - store_artifacts: path: /tmp/artifacts From 0cec0cf595670de0e1b2779c5ef7244f83d8b375 Mon Sep 17 00:00:00 2001 From: orangemug Date: Wed, 17 Jan 2018 17:36:46 +0000 Subject: [PATCH 10/48] Fix coverage in tests. --- .circleci/config.yml | 2 +- test/functional/util/coverage.js | 28 +++++++++++++--------------- 2 files changed, 14 insertions(+), 16 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index c194ce86..d6e8922e 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -24,6 +24,6 @@ jobs: - run: mkdir -p /tmp/artifacts/logs - run: DOCKER_HOST=localhost npm test - run: npm run build - - run: npm test + - run: ./node_modules/.bin/istanbul report --include /tmp/artifacts/coverage/coverage.json --dir /tmp/artifacts/coverage html lcov - store_artifacts: path: /tmp/artifacts diff --git a/test/functional/util/coverage.js b/test/functional/util/coverage.js index 335decd1..173e44a9 100644 --- a/test/functional/util/coverage.js +++ b/test/functional/util/coverage.js @@ -7,20 +7,18 @@ var COVERAGE_PATH = artifacts.pathSync("/coverage"); var coverage = istanbulCov.createCoverageMap({}); -describe("coverage", function() { - // Capture the coverage after each test - afterEach(function() { - // Code coverage - var results = browser.execute(function() { - return window.__coverage__; - }); +// Capture the coverage after each test +afterEach(function() { + // Code coverage + var results = browser.execute(function() { + return window.__coverage__; + }); - coverage.merge(results.value); - }) - - // Dump the coverage to a file - after(function() { - var jsonStr = JSON.stringify(coverage, null, 2); - fs.writeFileSync(COVERAGE_PATH+"/coverage.json", jsonStr); - }) + coverage.merge(results.value); +}) + +// Dump the coverage to a file +after(function() { + var jsonStr = JSON.stringify(coverage, null, 2); + fs.writeFileSync(COVERAGE_PATH+"/coverage.json", jsonStr); }) From 3f492e6208fb99a75a3f77ffadff28ff740059fb Mon Sep 17 00:00:00 2001 From: orangemug Date: Wed, 17 Jan 2018 17:43:26 +0000 Subject: [PATCH 11/48] Change artifacts destination. --- .circleci/config.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index d6e8922e..339d534d 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -27,3 +27,4 @@ jobs: - run: ./node_modules/.bin/istanbul report --include /tmp/artifacts/coverage/coverage.json --dir /tmp/artifacts/coverage html lcov - store_artifacts: path: /tmp/artifacts + destination: /artifacts From 383a1191272b071c8300b046c440799d1a9e42a5 Mon Sep 17 00:00:00 2001 From: orangemug Date: Wed, 17 Jan 2018 17:55:21 +0000 Subject: [PATCH 12/48] Added linting to circleci tests. --- .circleci/config.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 339d534d..68a5bdb3 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -22,8 +22,10 @@ jobs: key: v1-dependencies-{{ checksum "package.json" }} - run: mkdir -p /tmp/artifacts/logs - - run: DOCKER_HOST=localhost npm test - run: npm run build + - run: npm run lint + - run: npm run lint-styles + - run: DOCKER_HOST=localhost npm test - run: ./node_modules/.bin/istanbul report --include /tmp/artifacts/coverage/coverage.json --dir /tmp/artifacts/coverage html lcov - store_artifacts: path: /tmp/artifacts From dc40ce7d9e85b996597a46cc34e44c7e50420adc Mon Sep 17 00:00:00 2001 From: orangemug Date: Wed, 17 Jan 2018 17:58:01 +0000 Subject: [PATCH 13/48] Fixed lint errors. --- src/styles/index.scss | 1 - 1 file changed, 1 deletion(-) diff --git a/src/styles/index.scss b/src/styles/index.scss index 7f3583f9..32735cf4 100644 --- a/src/styles/index.scss +++ b/src/styles/index.scss @@ -37,7 +37,6 @@ $toolbar-offset: 0; @import 'popup'; @import 'map'; - /** * Hacks for webdriverio isVisibleWithinViewport */ From cb4f5ea9635b2a6d2923f52b4c7eba25c9438969 Mon Sep 17 00:00:00 2001 From: orangemug Date: Thu, 18 Jan 2018 23:15:59 +0000 Subject: [PATCH 14/48] Updated to react/react-dom v16.2.0 --- package-lock.json | 23 ++++++----------------- package.json | 4 ++-- 2 files changed, 8 insertions(+), 19 deletions(-) diff --git a/package-lock.json b/package-lock.json index 9bcc1e27..0ef5f7e8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2760,16 +2760,6 @@ "sha.js": "2.4.9" } }, - "create-react-class": { - "version": "15.6.2", - "resolved": "https://registry.npmjs.org/create-react-class/-/create-react-class-15.6.2.tgz", - "integrity": "sha1-zx7RXxKq1/FO9fLf4F5sQvke8Co=", - "requires": { - "fbjs": "0.8.16", - "loose-envify": "1.3.1", - "object-assign": "4.1.1" - } - }, "cross-env": { "version": "5.1.3", "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-5.1.3.tgz", @@ -10198,11 +10188,10 @@ } }, "react": { - "version": "15.6.2", - "resolved": "https://registry.npmjs.org/react/-/react-15.6.2.tgz", - "integrity": "sha1-26BDSrQ5z+gvEI8PURZjkIF5qnI=", + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/react/-/react-16.2.0.tgz", + "integrity": "sha512-ZmIomM7EE1DvPEnSFAHZn9Vs9zJl5A9H7el0EGTE6ZbW9FKe/14IYAlPbC8iH25YarEQxZL+E8VW7Mi7kfQrDQ==", "requires": { - "create-react-class": "15.6.2", "fbjs": "0.8.16", "loose-envify": "1.3.1", "object-assign": "4.1.1", @@ -10268,9 +10257,9 @@ "dev": true }, "react-dom": { - "version": "15.6.2", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-15.6.2.tgz", - "integrity": "sha1-Qc+t9pO3V/rycIRDodH9WgK+9zA=", + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.2.0.tgz", + "integrity": "sha512-zpGAdwHVn9K0091d+hr+R0qrjoJ84cIBFL2uU60KvWBPfZ7LPSrfqviTxGHWN0sjPZb2hxWzMexwrvJdKePvjg==", "requires": { "fbjs": "0.8.16", "loose-envify": "1.3.1", diff --git a/package.json b/package.json index 0390d832..0c046938 100644 --- a/package.json +++ b/package.json @@ -39,14 +39,14 @@ "ol-mapbox-style": "^1.0.1", "openlayers": "^4.4.2", "prop-types": "^15.6.0", - "react": "^15.6.2", + "react": "^16.2.0", "react-addons-pure-render-mixin": "^15.6.2", "react-autocomplete": "^1.7.2", "react-codemirror2": "^3.0.7", "react-collapse": "^4.0.3", "react-color": "^2.13.8", "react-copy-to-clipboard": "^5.0.1", - "react-dom": "^15.6.2", + "react-dom": "^16.2.0", "react-file-reader-input": "^1.1.4", "react-height": "^3.0.0", "react-icon-base": "^2.1.1", From e0ff342702e0e36432edb512286764a480dba9e8 Mon Sep 17 00:00:00 2001 From: orangemug Date: Fri, 19 Jan 2018 15:06:23 +0000 Subject: [PATCH 15/48] Added yaml inheritance to .circleci/config.yml --- .circleci/config.yml | 52 +++++++++++++++++++++++--------------------- 1 file changed, 27 insertions(+), 25 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 68a5bdb3..772c4c14 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1,32 +1,34 @@ version: 2 +templates: + steps: &steps + - checkout + - run: + name: "Create artifacts directory" + command: mkdir /tmp/artifacts + - restore_cache: + key: v1-dependencies-{{ checksum "package.json" }} + + - run: npm install + + - save_cache: + paths: + - node_modules + key: v1-dependencies-{{ checksum "package.json" }} + + - run: mkdir -p /tmp/artifacts/logs + - run: npm run build + - run: npm run lint + - run: npm run lint-styles + - run: DOCKER_HOST=localhost npm test + - run: ./node_modules/.bin/istanbul report --include /tmp/artifacts/coverage/coverage.json --dir /tmp/artifacts/coverage html lcov + - store_artifacts: + path: /tmp/artifacts + destination: /artifacts jobs: - build: + build-linux-node-v8: docker: # specify the version you desire here - image: node:8 - image: selenium/standalone-chrome:3.1.0 working_directory: ~/repo - steps: - - checkout - - run: - name: "Create artifacts directory" - command: mkdir /tmp/artifacts - - restore_cache: - key: v1-dependencies-{{ checksum "package.json" }} - - - run: npm install - - - save_cache: - paths: - - node_modules - key: v1-dependencies-{{ checksum "package.json" }} - - - run: mkdir -p /tmp/artifacts/logs - - run: npm run build - - run: npm run lint - - run: npm run lint-styles - - run: DOCKER_HOST=localhost npm test - - run: ./node_modules/.bin/istanbul report --include /tmp/artifacts/coverage/coverage.json --dir /tmp/artifacts/coverage html lcov - - store_artifacts: - path: /tmp/artifacts - destination: /artifacts + steps: *steps From ac519024359bcb0f3c4eb04b203ad0238b030dfd Mon Sep 17 00:00:00 2001 From: orangemug Date: Fri, 19 Jan 2018 15:08:45 +0000 Subject: [PATCH 16/48] Added missing workflow to .circleci/config.yml --- .circleci/config.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index 772c4c14..1a6bddcc 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -32,3 +32,9 @@ jobs: - image: selenium/standalone-chrome:3.1.0 working_directory: ~/repo steps: *steps + +workflows: + version: 2 + build: + jobs: + - build-linux-node-v8 From fe0e7af033f81a6c7f32b428ceb908e88207e1bd Mon Sep 17 00:00:00 2001 From: orangemug Date: Fri, 19 Jan 2018 15:13:46 +0000 Subject: [PATCH 17/48] Added multiple nodejs versions. --- .circleci/config.yml | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index 1a6bddcc..66b40f7c 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -25,6 +25,13 @@ templates: path: /tmp/artifacts destination: /artifacts jobs: + build-linux-node-v6: + docker: + # specify the version you desire here + - image: node:6 + - image: selenium/standalone-chrome:3.1.0 + working_directory: ~/repo + steps: *steps build-linux-node-v8: docker: # specify the version you desire here @@ -32,9 +39,19 @@ jobs: - image: selenium/standalone-chrome:3.1.0 working_directory: ~/repo steps: *steps + build-linux-node-v9: + docker: + # specify the version you desire here + - image: node:9 + - image: selenium/standalone-chrome:3.1.0 + working_directory: ~/repo + steps: *steps workflows: version: 2 build: jobs: + - build-linux-node-v6 - build-linux-node-v8 + - build-linux-node-v9 + From c82f38c1032d9c45b798c7e7a2fb55de2b4507b5 Mon Sep 17 00:00:00 2001 From: orangemug Date: Fri, 19 Jan 2018 17:14:56 +0000 Subject: [PATCH 18/48] Multiple working directories for test versions. --- .circleci/config.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 66b40f7c..b6af96d7 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -30,21 +30,21 @@ jobs: # specify the version you desire here - image: node:6 - image: selenium/standalone-chrome:3.1.0 - working_directory: ~/repo + working_directory: ~/repo-linux-node-v6 steps: *steps build-linux-node-v8: docker: # specify the version you desire here - image: node:8 - image: selenium/standalone-chrome:3.1.0 - working_directory: ~/repo + working_directory: ~/repo-linux-node-v8 steps: *steps build-linux-node-v9: docker: # specify the version you desire here - image: node:9 - image: selenium/standalone-chrome:3.1.0 - working_directory: ~/repo + working_directory: ~/repo-linux-node-v9 steps: *steps workflows: From f8dcbb8fb7dbd0cbefae93d99f4c62ba0df317be Mon Sep 17 00:00:00 2001 From: orangemug Date: Fri, 19 Jan 2018 17:24:29 +0000 Subject: [PATCH 19/48] Reduce to single job. --- .circleci/config.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index b6af96d7..9027fd62 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -51,7 +51,7 @@ workflows: version: 2 build: jobs: - - build-linux-node-v6 - build-linux-node-v8 - - build-linux-node-v9 + # - build-linux-node-v6 + # - build-linux-node-v9 From 3cab1dc49f127a8e77e5fec2bab15d2ababc62da Mon Sep 17 00:00:00 2001 From: orangemug Date: Fri, 19 Jan 2018 17:29:55 +0000 Subject: [PATCH 20/48] Remove special directory. --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 9027fd62..1a767d77 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -37,7 +37,7 @@ jobs: # specify the version you desire here - image: node:8 - image: selenium/standalone-chrome:3.1.0 - working_directory: ~/repo-linux-node-v8 + working_directory: ~/repo steps: *steps build-linux-node-v9: docker: From 18e7ead78a235ffcf052f6a4222d367f852fb940 Mon Sep 17 00:00:00 2001 From: orangemug Date: Fri, 19 Jan 2018 17:35:19 +0000 Subject: [PATCH 21/48] Revert to old config. --- .circleci/config.yml | 71 ++++++++++++++------------------------------ 1 file changed, 23 insertions(+), 48 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 1a767d77..68a5bdb3 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1,57 +1,32 @@ version: 2 -templates: - steps: &steps - - checkout - - run: - name: "Create artifacts directory" - command: mkdir /tmp/artifacts - - restore_cache: - key: v1-dependencies-{{ checksum "package.json" }} - - - run: npm install - - - save_cache: - paths: - - node_modules - key: v1-dependencies-{{ checksum "package.json" }} - - - run: mkdir -p /tmp/artifacts/logs - - run: npm run build - - run: npm run lint - - run: npm run lint-styles - - run: DOCKER_HOST=localhost npm test - - run: ./node_modules/.bin/istanbul report --include /tmp/artifacts/coverage/coverage.json --dir /tmp/artifacts/coverage html lcov - - store_artifacts: - path: /tmp/artifacts - destination: /artifacts jobs: - build-linux-node-v6: - docker: - # specify the version you desire here - - image: node:6 - - image: selenium/standalone-chrome:3.1.0 - working_directory: ~/repo-linux-node-v6 - steps: *steps - build-linux-node-v8: + build: docker: # specify the version you desire here - image: node:8 - image: selenium/standalone-chrome:3.1.0 working_directory: ~/repo - steps: *steps - build-linux-node-v9: - docker: - # specify the version you desire here - - image: node:9 - - image: selenium/standalone-chrome:3.1.0 - working_directory: ~/repo-linux-node-v9 - steps: *steps + steps: + - checkout + - run: + name: "Create artifacts directory" + command: mkdir /tmp/artifacts + - restore_cache: + key: v1-dependencies-{{ checksum "package.json" }} -workflows: - version: 2 - build: - jobs: - - build-linux-node-v8 - # - build-linux-node-v6 - # - build-linux-node-v9 + - run: npm install + - save_cache: + paths: + - node_modules + key: v1-dependencies-{{ checksum "package.json" }} + + - run: mkdir -p /tmp/artifacts/logs + - run: npm run build + - run: npm run lint + - run: npm run lint-styles + - run: DOCKER_HOST=localhost npm test + - run: ./node_modules/.bin/istanbul report --include /tmp/artifacts/coverage/coverage.json --dir /tmp/artifacts/coverage html lcov + - store_artifacts: + path: /tmp/artifacts + destination: /artifacts From 8062e304b774d948790aa86cb76a3eee1b3829e9 Mon Sep 17 00:00:00 2001 From: orangemug Date: Fri, 19 Jan 2018 17:51:08 +0000 Subject: [PATCH 22/48] Update selenium/standalone-chrome --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 68a5bdb3..dd03e082 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -4,7 +4,7 @@ jobs: docker: # specify the version you desire here - image: node:8 - - image: selenium/standalone-chrome:3.1.0 + - image: selenium/standalone-chrome:3.8.1 working_directory: ~/repo steps: - checkout From 62f08432838271d743c953c0d6f137fe5330c226 Mon Sep 17 00:00:00 2001 From: orangemug Date: Fri, 19 Jan 2018 17:55:37 +0000 Subject: [PATCH 23/48] Moved back to workflows. --- .circleci/config.yml | 75 +++++++++++++++++++++++++++++--------------- 1 file changed, 50 insertions(+), 25 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index dd03e082..9027fd62 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1,32 +1,57 @@ version: 2 +templates: + steps: &steps + - checkout + - run: + name: "Create artifacts directory" + command: mkdir /tmp/artifacts + - restore_cache: + key: v1-dependencies-{{ checksum "package.json" }} + + - run: npm install + + - save_cache: + paths: + - node_modules + key: v1-dependencies-{{ checksum "package.json" }} + + - run: mkdir -p /tmp/artifacts/logs + - run: npm run build + - run: npm run lint + - run: npm run lint-styles + - run: DOCKER_HOST=localhost npm test + - run: ./node_modules/.bin/istanbul report --include /tmp/artifacts/coverage/coverage.json --dir /tmp/artifacts/coverage html lcov + - store_artifacts: + path: /tmp/artifacts + destination: /artifacts jobs: - build: + build-linux-node-v6: + docker: + # specify the version you desire here + - image: node:6 + - image: selenium/standalone-chrome:3.1.0 + working_directory: ~/repo-linux-node-v6 + steps: *steps + build-linux-node-v8: docker: # specify the version you desire here - image: node:8 - - image: selenium/standalone-chrome:3.8.1 - working_directory: ~/repo - steps: - - checkout - - run: - name: "Create artifacts directory" - command: mkdir /tmp/artifacts - - restore_cache: - key: v1-dependencies-{{ checksum "package.json" }} + - image: selenium/standalone-chrome:3.1.0 + working_directory: ~/repo-linux-node-v8 + steps: *steps + build-linux-node-v9: + docker: + # specify the version you desire here + - image: node:9 + - image: selenium/standalone-chrome:3.1.0 + working_directory: ~/repo-linux-node-v9 + steps: *steps - - run: npm install +workflows: + version: 2 + build: + jobs: + - build-linux-node-v8 + # - build-linux-node-v6 + # - build-linux-node-v9 - - save_cache: - paths: - - node_modules - key: v1-dependencies-{{ checksum "package.json" }} - - - run: mkdir -p /tmp/artifacts/logs - - run: npm run build - - run: npm run lint - - run: npm run lint-styles - - run: DOCKER_HOST=localhost npm test - - run: ./node_modules/.bin/istanbul report --include /tmp/artifacts/coverage/coverage.json --dir /tmp/artifacts/coverage html lcov - - store_artifacts: - path: /tmp/artifacts - destination: /artifacts From 094c4747d3b140cd8a352c91ded3cb65d4c93961 Mon Sep 17 00:00:00 2001 From: orangemug Date: Fri, 19 Jan 2018 18:02:08 +0000 Subject: [PATCH 24/48] Update selenium/standalone-chrome to 3.8.1 --- .circleci/config.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 9027fd62..d408831b 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -29,21 +29,21 @@ jobs: docker: # specify the version you desire here - image: node:6 - - image: selenium/standalone-chrome:3.1.0 + - image: selenium/standalone-chrome:3.8.1 working_directory: ~/repo-linux-node-v6 steps: *steps build-linux-node-v8: docker: # specify the version you desire here - image: node:8 - - image: selenium/standalone-chrome:3.1.0 + - image: selenium/standalone-chrome:3.8.1 working_directory: ~/repo-linux-node-v8 steps: *steps build-linux-node-v9: docker: # specify the version you desire here - image: node:9 - - image: selenium/standalone-chrome:3.1.0 + - image: selenium/standalone-chrome:3.8.1 working_directory: ~/repo-linux-node-v9 steps: *steps From e64ca3eb93824247359ccdca665576051ca98757 Mon Sep 17 00:00:00 2001 From: orangemug Date: Fri, 19 Jan 2018 18:15:46 +0000 Subject: [PATCH 25/48] Added back in other jobs. --- .circleci/config.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index d408831b..9289fc54 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -52,6 +52,6 @@ workflows: build: jobs: - build-linux-node-v8 - # - build-linux-node-v6 - # - build-linux-node-v9 + - build-linux-node-v6 + - build-linux-node-v9 From 1de7ba7e861c42a67ab588c5121683aa05d5b89f Mon Sep 17 00:00:00 2001 From: orangemug Date: Tue, 6 Mar 2018 21:11:58 +0000 Subject: [PATCH 26/48] Use dev settings for test. --- config/wdio.conf.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/wdio.conf.js b/config/wdio.conf.js index c4a0c141..18bc7ad7 100644 --- a/config/wdio.conf.js +++ b/config/wdio.conf.js @@ -1,6 +1,6 @@ var webpack = require("webpack"); var WebpackDevServer = require("webpack-dev-server"); -var webpackConfig = require("./webpack.production.config"); +var webpackConfig = require("./webpack.config"); var testConfig = require("../test/config/specs"); var artifacts = require("../test/artifacts"); var isDocker = require("is-docker"); From dbe2c2637e5a0f65cc97a2bd39b97023ebfd060b Mon Sep 17 00:00:00 2001 From: orangemug Date: Mon, 9 Apr 2018 10:20:37 +0100 Subject: [PATCH 27/48] Better onPrepare for wdio --- config/wdio.conf.js | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/config/wdio.conf.js b/config/wdio.conf.js index 18bc7ad7..e8839dd0 100644 --- a/config/wdio.conf.js +++ b/config/wdio.conf.js @@ -38,9 +38,22 @@ exports.config = { timeout: 4*60*1000 }, onPrepare: function (config, capabilities) { - var compiler = webpack(webpackConfig); - server = new WebpackDevServer(compiler, {}); - server.listen(testConfig.port); + return new Promise(function(resolve, reject) { + var compiler = webpack(webpackConfig); + server = new WebpackDevServer(compiler, { + stats: { + colors: true + } + }); + server.listen(testConfig.port, "127.0.0.1", function(err) { + if(err) { + reject(); + } + else { + resolve(); + } + }); + }) }, onComplete: function(exitCode) { server.close() From 050e22918a4853641f950861d0dffc572005c2c4 Mon Sep 17 00:00:00 2001 From: orangemug Date: Mon, 9 Apr 2018 17:49:56 +0100 Subject: [PATCH 28/48] Fix for running within docker. --- config/wdio.conf.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/config/wdio.conf.js b/config/wdio.conf.js index e8839dd0..fad25495 100644 --- a/config/wdio.conf.js +++ b/config/wdio.conf.js @@ -25,7 +25,8 @@ exports.config = { coloredLogs: true, bail: 0, screenshotPath: SCREENSHOT_PATH, - host: (isDocker() ? process.env.DOCKER_HOST : "127.0.0.1"), + // Note: This is here because @orangemug currently runs Maputnik inside a docker container. + host: (isDocker() ? "host.docker.internal" : "0.0.0.0"), baseUrl: 'http://localhost', waitforTimeout: 10000, connectionRetryTimeout: 90000, @@ -45,9 +46,9 @@ exports.config = { colors: true } }); - server.listen(testConfig.port, "127.0.0.1", function(err) { + server.listen(testConfig.port, (isDocker() ? "0.0.0.0" : "localhost"), function(err) { if(err) { - reject(); + reject(err); } else { resolve(); From 84f39707300ed0db80edd3f2618705e9ab6f2697 Mon Sep 17 00:00:00 2001 From: orangemug Date: Mon, 9 Apr 2018 17:51:12 +0100 Subject: [PATCH 29/48] Updated selenium-standalone & webdriverio --- package-lock.json | 41 +++++++++++++++++++++++++++++++++-------- package.json | 4 ++-- 2 files changed, 35 insertions(+), 10 deletions(-) diff --git a/package-lock.json b/package-lock.json index 8a552bb9..716b19ff 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8580,6 +8580,12 @@ "integrity": "sha512-nJmSswG4As/MkRq7QZFuH/sf/yuv8ODdMZrY4Bedjp77a5MK4A6s7YbBB64c9u79EBUOfXUXBvArmvzTD0X+6g==", "dev": true }, + "nice-try": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.4.tgz", + "integrity": "sha512-2NpiFHqC87y/zFke0fC0spBXL3bBsoh/p5H1EFhshxjCR5+0g2d6BiXbUFz9v1sAcxsk2htp2eQnNIci2dIYcA==", + "dev": true + }, "no-case": { "version": "2.3.2", "resolved": "https://registry.npmjs.org/no-case/-/no-case-2.3.2.tgz", @@ -11612,14 +11618,14 @@ "dev": true }, "selenium-standalone": { - "version": "6.12.0", - "resolved": "https://registry.npmjs.org/selenium-standalone/-/selenium-standalone-6.12.0.tgz", - "integrity": "sha1-eJcw2wmhBfHM4SxkJNeV0RxUO9Q=", + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/selenium-standalone/-/selenium-standalone-6.13.0.tgz", + "integrity": "sha512-JV1+AySJ9RccsAIZlnDb8QUx/SDeVGK8j/zCJcNlbz/LCRiketU3Su0YE5Uc1raaBGpT/venof0+9Ry0oGuvYw==", "dev": true, "requires": { "async": "2.6.0", "commander": "2.14.1", - "cross-spawn": "5.1.0", + "cross-spawn": "6.0.5", "debug": "3.1.0", "lodash": "4.17.5", "minimist": "1.2.0", @@ -11659,6 +11665,19 @@ "integrity": "sha1-cVuW6phBWTzDMGeSP17GDr2k99c=", "dev": true }, + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "requires": { + "nice-try": "1.0.4", + "path-key": "2.0.1", + "semver": "5.5.0", + "shebang-command": "1.2.0", + "which": "1.3.0" + } + }, "cryptiles": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz", @@ -11769,6 +11788,12 @@ "uuid": "3.2.1" } }, + "semver": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", + "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==", + "dev": true + }, "sntp": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz", @@ -14440,7 +14465,7 @@ "dev": true, "requires": { "fs-extra": "0.30.0", - "selenium-standalone": "6.12.0" + "selenium-standalone": "6.13.0" }, "dependencies": { "fs-extra": { @@ -14512,9 +14537,9 @@ } }, "webdriverio": { - "version": "4.11.0", - "resolved": "https://registry.npmjs.org/webdriverio/-/webdriverio-4.11.0.tgz", - "integrity": "sha1-KJuq4iVzAdlc/s797CA4pqprlMU=", + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/webdriverio/-/webdriverio-4.12.0.tgz", + "integrity": "sha1-40De8nIYPIFopN0LOCMi+de+4Q0=", "dev": true, "requires": { "archiver": "2.1.1", diff --git a/package.json b/package.json index c74a97ca..decce6fa 100644 --- a/package.json +++ b/package.json @@ -124,7 +124,7 @@ "nsp": "^3.1.0", "react-hot-loader": "^3.1.1", "sass-loader": "^6.0.6", - "selenium-standalone": "^6.11.0", + "selenium-standalone": "^6.13.0", "style-loader": "^0.19.0", "stylelint": "^7.13.0", "stylelint-config-standard": "^15.0.1", @@ -135,7 +135,7 @@ "wdio-phantomjs-service": "^0.2.2", "wdio-selenium-standalone-service": "0.0.9", "wdio-spec-reporter": "^0.1.2", - "webdriverio": "^4.9.8", + "webdriverio": "^4.12.0", "webpack": "^3.8.1", "webpack-bundle-analyzer": "^2.9.0", "webpack-cleanup-plugin": "^0.5.1", From a346d757fdf716acaaf6cc6ad085c9b0f84456eb Mon Sep 17 00:00:00 2001 From: orangemug Date: Mon, 9 Apr 2018 18:18:15 +0100 Subject: [PATCH 30/48] Don't assume docker for mac. --- config/wdio.conf.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/wdio.conf.js b/config/wdio.conf.js index fad25495..b520bcfc 100644 --- a/config/wdio.conf.js +++ b/config/wdio.conf.js @@ -26,7 +26,7 @@ exports.config = { bail: 0, screenshotPath: SCREENSHOT_PATH, // Note: This is here because @orangemug currently runs Maputnik inside a docker container. - host: (isDocker() ? "host.docker.internal" : "0.0.0.0"), + host: process.env.DOCKER_HOST || "0.0.0.0", baseUrl: 'http://localhost', waitforTimeout: 10000, connectionRetryTimeout: 90000, From 0bd62985b9465a61728b70e644b963b68286e527 Mon Sep 17 00:00:00 2001 From: orangemug Date: Tue, 10 Apr 2018 12:45:44 +0100 Subject: [PATCH 31/48] Revert change to undo/redo --- src/components/App.jsx | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-) diff --git a/src/components/App.jsx b/src/components/App.jsx index f757f1fe..c7bf3fd2 100644 --- a/src/components/App.jsx +++ b/src/components/App.jsx @@ -85,28 +85,17 @@ export default class App extends React.Component { this.layerWatcher = new LayerWatcher({ onVectorLayersChange: v => this.setState({ vectorLayers: v }) }) - - this.onKeyDown = this.onKeyDown.bind(this); - } - - onKeyDown(e) { - console.log("??? keyCode ctrlKey="+e.ctrlKey+", keyCode="+e.keyCode) - // Control + Z - if(e.ctrlKey && e.keyCode === 90) { - this.onUndo(e); - } - else if(e.ctrlKey && e.keyCode === 89) { - this.onRedo(e); - } } componentDidMount() { this.fetchSources(); - document.addEventListener("keydown", this.onKeyDown); + Mousetrap.bind(['ctrl+z'], this.onUndo.bind(this)); + Mousetrap.bind(['ctrl+y'], this.onRedo.bind(this)); } componentWillUnmount() { - document.removeEventListener("keydown", this.onKeyDown); + Mousetrap.unbind(['ctrl+z'], this.onUndo.bind(this)); + Mousetrap.unbind(['ctrl+y'], this.onRedo.bind(this)); } saveStyle(snapshotStyle) { From 6138257a893ba657dff66d7a7ce449f1d5833132 Mon Sep 17 00:00:00 2001 From: orangemug Date: Tue, 10 Apr 2018 12:47:00 +0100 Subject: [PATCH 32/48] Remove logging. --- src/components/inputs/StringInput.jsx | 3 --- src/components/modals/AddModal.jsx | 1 - 2 files changed, 4 deletions(-) diff --git a/src/components/inputs/StringInput.jsx b/src/components/inputs/StringInput.jsx index 2f7bf1fe..6987b3cd 100644 --- a/src/components/inputs/StringInput.jsx +++ b/src/components/inputs/StringInput.jsx @@ -19,7 +19,6 @@ class StringInput extends React.Component { } componentWillReceiveProps(nextProps) { - console.log("@@ STRING componentWillReceiveProps", JSON.stringify(nextProps)) this.setState({ value: nextProps.value || '' }) } @@ -48,13 +47,11 @@ class StringInput extends React.Component { value: this.state.value, placeholder: this.props.default, onChange: e => { - console.log("@@ STRING CHANGE", JSON.stringify(e.target.value)); this.setState({ value: e.target.value }) }, onBlur: () => { - console.log("@@ STRING BLUR", JSON.stringify(this.state.value), "props:", JSON.stringify(this.props.value)); if(this.state.value!==this.props.value) this.props.onChange(this.state.value) } }); diff --git a/src/components/modals/AddModal.jsx b/src/components/modals/AddModal.jsx index 84cb6625..feb83434 100644 --- a/src/components/modals/AddModal.jsx +++ b/src/components/modals/AddModal.jsx @@ -125,7 +125,6 @@ class AddModal extends React.Component { value={this.state.id} wdKey="add-layer.layer-id" onChange={v => { - console.log("@@ upper_id_change", JSON.stringify(v)) this.setState({ id: v }) }} /> From 8c7a1f7075367be81f7f3366266ceed1aea642a8 Mon Sep 17 00:00:00 2001 From: orangemug Date: Tue, 10 Apr 2018 13:05:58 +0100 Subject: [PATCH 33/48] Updated build config for circleci to only test webdriver in one job --- .circleci/config.yml | 42 +++++++++++++++++++++++++++++++++++++----- 1 file changed, 37 insertions(+), 5 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 9289fc54..1a4a0738 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1,6 +1,30 @@ version: 2 templates: - steps: &steps + # Test the build **only** no webdriver + build-steps: &build-steps + - checkout + - run: + name: "Create artifacts directory" + command: mkdir /tmp/artifacts + - restore_cache: + key: v1-dependencies-{{ checksum "package.json" }} + + - run: npm install + + - save_cache: + paths: + - node_modules + key: v1-dependencies-{{ checksum "package.json" }} + + - run: mkdir -p /tmp/artifacts/logs + - run: npm run build + - run: npm run lint + - run: npm run lint-styles + - store_artifacts: + path: /tmp/artifacts + destination: /artifacts + # Test in webdriver + wdio-steps: &steps - checkout - run: name: "Create artifacts directory" @@ -31,27 +55,35 @@ jobs: - image: node:6 - image: selenium/standalone-chrome:3.8.1 working_directory: ~/repo-linux-node-v6 - steps: *steps + steps: *build-steps build-linux-node-v8: docker: # specify the version you desire here - image: node:8 - image: selenium/standalone-chrome:3.8.1 working_directory: ~/repo-linux-node-v8 - steps: *steps + steps: *wdio-steps build-linux-node-v9: docker: # specify the version you desire here - image: node:9 - image: selenium/standalone-chrome:3.8.1 working_directory: ~/repo-linux-node-v9 - steps: *steps + steps: *build-steps + build-linux-node-v10: + docker: + # specify the version you desire here + - image: node:10 + - image: selenium/standalone-chrome:3.8.1 + working_directory: ~/repo-linux-node-v10 + steps: *build-steps workflows: version: 2 build: jobs: - - build-linux-node-v8 - build-linux-node-v6 + - build-linux-node-v8 - build-linux-node-v9 + - build-linux-node-v10 From 3ae37f1c46a8b7a0020cda4e2f48d6eaf2fcdae0 Mon Sep 17 00:00:00 2001 From: orangemug Date: Tue, 10 Apr 2018 13:08:55 +0100 Subject: [PATCH 34/48] Updated appveyor to no longer test, only build/lint --- appveyor.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 1a33cc12..b50173eb 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,9 +1,9 @@ environment: matrix: - nodejs_version: "6" - - nodejs_version: "7" - nodejs_version: "8" - nodejs_version: "9" + - nodejs_version: "10" platform: - x86 - x64 @@ -16,4 +16,4 @@ build_script: - npm run build test_script: - npm run lint - - npm test + - npm run lint-styles From bd44e6d0716ee4d58a4e5ceb73370d6c602b50b2 Mon Sep 17 00:00:00 2001 From: orangemug Date: Tue, 10 Apr 2018 13:11:42 +0100 Subject: [PATCH 35/48] Fixed typo. --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 1a4a0738..a552d405 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -24,7 +24,7 @@ templates: path: /tmp/artifacts destination: /artifacts # Test in webdriver - wdio-steps: &steps + wdio-steps: &wdio-steps - checkout - run: name: "Create artifacts directory" From fb0e531f4a47da846dd7eefb5d19c509dcad84f6 Mon Sep 17 00:00:00 2001 From: orangemug Date: Tue, 10 Apr 2018 13:17:59 +0100 Subject: [PATCH 36/48] Removed node:10 as it doesn't exist yet. --- .circleci/config.yml | 8 -------- 1 file changed, 8 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index a552d405..f8179605 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -70,13 +70,6 @@ jobs: - image: selenium/standalone-chrome:3.8.1 working_directory: ~/repo-linux-node-v9 steps: *build-steps - build-linux-node-v10: - docker: - # specify the version you desire here - - image: node:10 - - image: selenium/standalone-chrome:3.8.1 - working_directory: ~/repo-linux-node-v10 - steps: *build-steps workflows: version: 2 @@ -85,5 +78,4 @@ workflows: - build-linux-node-v6 - build-linux-node-v8 - build-linux-node-v9 - - build-linux-node-v10 From 7ecbc14c3932c0c59db12697db33ecec5cfbb71c Mon Sep 17 00:00:00 2001 From: orangemug Date: Tue, 10 Apr 2018 13:29:48 +0100 Subject: [PATCH 37/48] Added OSX build to tests. --- .circleci/config.yml | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index f8179605..d01979f5 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -53,7 +53,6 @@ jobs: docker: # specify the version you desire here - image: node:6 - - image: selenium/standalone-chrome:3.8.1 working_directory: ~/repo-linux-node-v6 steps: *build-steps build-linux-node-v8: @@ -67,7 +66,14 @@ jobs: docker: # specify the version you desire here - image: node:9 - - image: selenium/standalone-chrome:3.8.1 + working_directory: ~/repo-linux-node-v9 + steps: *build-steps + build-osx-node-v9: + macos: + xcode: "9.0" + dependencies: + override: + - brew install node@9 working_directory: ~/repo-linux-node-v9 steps: *build-steps @@ -78,4 +84,5 @@ workflows: - build-linux-node-v6 - build-linux-node-v8 - build-linux-node-v9 + - build-osx-node-v9 From 6bf695cd4bb28bc9c11dad2c80ab09f1a654f739 Mon Sep 17 00:00:00 2001 From: orangemug Date: Tue, 10 Apr 2018 13:34:20 +0100 Subject: [PATCH 38/48] Removed linux from travis. CircleCI now takes care of that --- .travis.yml | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/.travis.yml b/.travis.yml index 30b303d4..9d83eff8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,30 +1,12 @@ language: node_js -addons: - firefox: latest matrix: include: - - os: linux - node_js: "6" - - os: linux - env: CXX=g++-4.8 - node_js: "7" - - os: linux - node_js: "8" - - os: linux - env: CXX=g++-4.8 - node_js: "9" - os: osx node_js: "6" - - os: osx - node_js: "7" - os: osx node_js: "8" - os: osx node_js: "9" -before_install: - - export CHROME_BIN=chromium-browser - - export DISPLAY=:99.0 - - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sh -e /etc/init.d/xvfb start; fi install: - npm install script: @@ -32,7 +14,6 @@ script: - node --stack_size=100000 $(which npm) run build - npm run lint - npm run lint-styles - - npm run test addons: apt: sources: From 15962481ee2c7d1abc0d75a7695230c69965ce83 Mon Sep 17 00:00:00 2001 From: orangemug Date: Tue, 10 Apr 2018 13:35:02 +0100 Subject: [PATCH 39/48] Disable OSX until we get a open source plan for maputnik/editor --- .circleci/config.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index d01979f5..776b2f98 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -84,5 +84,4 @@ workflows: - build-linux-node-v6 - build-linux-node-v8 - build-linux-node-v9 - - build-osx-node-v9 From 6fa06e54836ab3fb7c0f628102fd67e5e60e228b Mon Sep 17 00:00:00 2001 From: orangemug Date: Tue, 10 Apr 2018 14:02:36 +0100 Subject: [PATCH 40/48] Removed un-useful comments --- .circleci/config.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 776b2f98..1bf8bb3e 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -51,20 +51,17 @@ templates: jobs: build-linux-node-v6: docker: - # specify the version you desire here - image: node:6 working_directory: ~/repo-linux-node-v6 steps: *build-steps build-linux-node-v8: docker: - # specify the version you desire here - image: node:8 - image: selenium/standalone-chrome:3.8.1 working_directory: ~/repo-linux-node-v8 steps: *wdio-steps build-linux-node-v9: docker: - # specify the version you desire here - image: node:9 working_directory: ~/repo-linux-node-v9 steps: *build-steps From aee4a041fe5ac84d821a1f9e61469e7723401ef7 Mon Sep 17 00:00:00 2001 From: orangemug Date: Tue, 10 Apr 2018 14:03:09 +0100 Subject: [PATCH 41/48] Removed node:10 from appveyor --- appveyor.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index b50173eb..d469d985 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -3,7 +3,6 @@ environment: - nodejs_version: "6" - nodejs_version: "8" - nodejs_version: "9" - - nodejs_version: "10" platform: - x86 - x64 From 7a60df370e9df077c6166238787905122b3c4435 Mon Sep 17 00:00:00 2001 From: orangemug Date: Tue, 10 Apr 2018 14:20:13 +0100 Subject: [PATCH 42/48] Changed url to be local (although not used) --- test/example-style.json | 4 ++-- test/geojson-server.js | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/test/example-style.json b/test/example-style.json index adf11e41..f2ec9da7 100644 --- a/test/example-style.json +++ b/test/example-style.json @@ -6,7 +6,7 @@ "maputnik:renderer": "mbgljs" }, "sources": {}, - "glyphs": "https://demo.tileserver.org/fonts/{fontstack}/{range}.pbf", - "sprites": "https://demo.tileserver.org/fonts/{fontstack}/{range}.pbf", + "glyphs": "https://example.local/fonts/{fontstack}/{range}.pbf", + "sprites": "https://example.local/fonts/{fontstack}/{range}.pbf", "layers": [] } diff --git a/test/geojson-server.js b/test/geojson-server.js index cac65e11..56f1ba7b 100644 --- a/test/geojson-server.js +++ b/test/geojson-server.js @@ -23,8 +23,8 @@ function buildStyle(opts) { "maputnik:renderer": "mbgljs" }, "sources": opts.sources, - "glyphs": "https://demo.tileserver.org/fonts/{fontstack}/{range}.pbf", - "sprites": "https://demo.tileserver.org/fonts/{fontstack}/{range}.pbf", + "glyphs": "https://example.local/fonts/{fontstack}/{range}.pbf", + "sprites": "https://example.local/fonts/{fontstack}/{range}.pbf", "layers": [] } } From 9e82599464fcc37ec5454f1e5ebbd8f11e93d23c Mon Sep 17 00:00:00 2001 From: orangemug Date: Tue, 10 Apr 2018 14:23:11 +0100 Subject: [PATCH 43/48] Removed old comments. --- test/functional/helper.js | 2 - test/functional/history/index.js | 95 -------------------------------- test/functional/modals/index.js | 3 +- test/geojson-server.js | 3 - 4 files changed, 1 insertion(+), 102 deletions(-) diff --git a/test/functional/helper.js b/test/functional/helper.js index 310265a9..98324502 100644 --- a/test/functional/helper.js +++ b/test/functional/helper.js @@ -3,10 +3,8 @@ var uuid = require('uuid/v1'); var geoServer = require("../geojson-server"); -// This should be sync... var geoserver = geoServer.listen(9002); - module.exports = { getStyleUrl: function(styles) { var port = geoserver.address().port; diff --git a/test/functional/history/index.js b/test/functional/history/index.js index d699c075..2cd5b0e6 100644 --- a/test/functional/history/index.js +++ b/test/functional/history/index.js @@ -97,99 +97,4 @@ describe.skip("history", function() { }); - - // /** - // * See - // */ - // it("undo/redo", function() { - // var styleObj; - - // browser.debug(); - - // browser.url(helper.config.baseUrl+"?debug&style="+helper.getStyleUrl([ - // "geojson:example" - // ])); - // browser.waitForExist(".maputnik-toolbar-link"); - - // helper.modalCommands.addLayer.open(browser); - - // styleObj = helper.helper.getStyleStore(browser); - // assert.deepEqual(styleObj.layers, []); - - // helper.modalCommands.addLayer.fill(browser, { - // id: "step 1", - // type: "background" - // }) - - // styleObj = helper.helper.getStyleStore(browser); - // assert.deepEqual(styleObj.layers, [ - // { - // "id": "step 1", - // "type": 'background' - // } - // ]); - - // helper.modalCommands.addLayer.open(browser); - // helper.modalCommands.addLayer.fill(browser, { - // id: "step 2", - // type: "background" - // }) - - // styleObj = helper.helper.getStyleStore(browser); - // assert.deepEqual(styleObj.layers, [ - // { - // "id": "step 1", - // "type": 'background' - // }, - // { - // "id": "step 2", - // "type": 'background' - // } - // ]); - - // browser - // .keys(['Control', 'z']) - // .keys(['Control']); - // styleObj = helper.helper.getStyleStore(browser); - // assert.deepEqual(styleObj.layers, [ - // { - // "id": "step 1", - // "type": 'background' - // } - // ]); - - // browser - // .keys(['Control', 'z']) - // .keys(['Control']); - // styleObj = helper.helper.getStyleStore(browser); - // assert.deepEqual(styleObj.layers, [ - // ]); - - // browser - // .keys(['Control', 'y']) - // .keys(['Control']); - // styleObj = helper.helper.getStyleStore(browser); - // assert.deepEqual(styleObj.layers, [ - // { - // "id": "step 1", - // "type": 'background' - // } - // ]); - - // browser - // .keys(['Control', 'y']) - // .keys(['Control']); - // styleObj = helper.helper.getStyleStore(browser); - // assert.deepEqual(styleObj.layers, [ - // { - // "id": "step 1", - // "type": 'background' - // }, - // { - // "id": "step 2", - // "type": 'background' - // } - // ]); - - // }) }) diff --git a/test/functional/modals/index.js b/test/functional/modals/index.js index 24f9ffd5..9f262270 100644 --- a/test/functional/modals/index.js +++ b/test/functional/modals/index.js @@ -5,8 +5,6 @@ var config = require("../../config/specs"); var helper = require("../helper"); - -// TODO: Is this needed? function closeModal(wdKey) { browser.waitUntil(function() { return browser.isVisibleWithinViewport(wd.$(wdKey)); @@ -85,6 +83,7 @@ describe("modals", function() { // TODO: Work out how to download a file and check the contents it("download") + // TODO: Work out how to mock the end git points it("save to gist") }) diff --git a/test/geojson-server.js b/test/geojson-server.js index 56f1ba7b..457eb92f 100644 --- a/test/geojson-server.js +++ b/test/geojson-server.js @@ -55,9 +55,6 @@ app.get("/styles/empty/:sources", function(req, res) { var reqSources = req.params.sources.split(","); var sources = {}; - // reqSources.forEach(function(key) { - // sources[key] = buildGeoJSONSource(sourceData[key]); - // }); reqSources.forEach(function(key) { var parts = key.split(":"); var type = parts[0]; From f0744f024db8dde24b58b588f45e3e846ffddc86 Mon Sep 17 00:00:00 2001 From: orangemug Date: Tue, 10 Apr 2018 15:07:36 +0100 Subject: [PATCH 44/48] Moved commit. --- test/functional/layers/index.js | 5 ----- test/functional/screenshots/index.js | 2 ++ 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/test/functional/layers/index.js b/test/functional/layers/index.js index 14c5d797..012b6729 100644 --- a/test/functional/layers/index.js +++ b/test/functional/layers/index.js @@ -443,11 +443,6 @@ describe("layers", function() { }); }); - // These get used in the marketing material. They are also useful to do a quick manual check of the styling across browsers - // NOTE: These duplicate some of the tests, however this is indended becuase it's likely these will change for aesthetic reasons over time - // - - describe.skip("groups", function() { it("simple", function() { diff --git a/test/functional/screenshots/index.js b/test/functional/screenshots/index.js index b64d0c9c..9c5634c8 100644 --- a/test/functional/screenshots/index.js +++ b/test/functional/screenshots/index.js @@ -4,6 +4,8 @@ var helper = require("../helper"); var wd = require("../../wd-helper"); +// These will get used in the marketing material. They are also useful to do a quick manual check of the styling across browsers +// NOTE: These duplicate some of the tests, however this is indended becuase it's likely these will change for aesthetic reasons over time describe('screenshots', function() { beforeEach(function() { From 687c08527d0cddd862c786742616b438ee8b3345 Mon Sep 17 00:00:00 2001 From: orangemug Date: Tue, 10 Apr 2018 15:13:55 +0100 Subject: [PATCH 45/48] Added test docs. --- README.md | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/README.md b/README.md index 597d144d..fe3793c6 100644 --- a/README.md +++ b/README.md @@ -68,6 +68,25 @@ npm run lint npm run lint-styles ``` + +## Tests +For testing we use [webdriverio](http://webdriver.io) and [selenium-standalone](https://github.com/vvo/selenium-standalone) + +[selenium-standalone](https://github.com/vvo/selenium-standalone) starts a server that will launch browsers on your local machine. We use chrome so you **must** have chrome installed on your machine. Now open and terminal and run + +``` +./node_modules/.bin/selenium-standalone +``` + +Then open another terminal and run + +``` +npm test +``` + +After some time you should see a browser launch which will be automated by the test runner. + + ## Related Projects - [maputnik-dev-server](https://github.com/nycplanning/labs-maputnik-dev-server) - An express.js server that allows for quickly loading the style from any mapboxGL map into mapuntnik. From 8ba2123a26e7654155504e55e4d47e09f22c73ca Mon Sep 17 00:00:00 2001 From: orangemug Date: Tue, 10 Apr 2018 15:15:29 +0100 Subject: [PATCH 46/48] Added missing propType. --- src/components/Toolbar.jsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/components/Toolbar.jsx b/src/components/Toolbar.jsx index bad7de7f..efe47f68 100644 --- a/src/components/Toolbar.jsx +++ b/src/components/Toolbar.jsx @@ -58,7 +58,8 @@ class ToolbarLink extends React.Component { class ToolbarAction extends React.Component { static propTypes = { children: PropTypes.node, - onClick: PropTypes.func + onClick: PropTypes.func, + wdKey: PropTypes.string } render() { From 1805aee7ba559327b6aa068d7662120f62d65c62 Mon Sep 17 00:00:00 2001 From: orangemug Date: Tue, 10 Apr 2018 16:16:51 +0100 Subject: [PATCH 47/48] Removed lint-styles in appveyor It doesn't work in windows and should be addressed in another PR --- appveyor.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index d469d985..0b100cc9 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -15,4 +15,3 @@ build_script: - npm run build test_script: - npm run lint - - npm run lint-styles From c4b92fa0a90acb1fe21b2604ecd6ec59d5602882 Mon Sep 17 00:00:00 2001 From: orangemug Date: Sun, 15 Apr 2018 09:17:07 +0100 Subject: [PATCH 48/48] Updated test instructions in README --- README.md | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index fe3793c6..d8630aa8 100644 --- a/README.md +++ b/README.md @@ -72,10 +72,18 @@ npm run lint-styles ## Tests For testing we use [webdriverio](http://webdriver.io) and [selenium-standalone](https://github.com/vvo/selenium-standalone) -[selenium-standalone](https://github.com/vvo/selenium-standalone) starts a server that will launch browsers on your local machine. We use chrome so you **must** have chrome installed on your machine. Now open and terminal and run +[selenium-standalone](https://github.com/vvo/selenium-standalone) starts a server that will launch browsers on your local machine. We use chrome so you **must** have chrome installed on your machine. + +Now open and terminal and run the following. This will install the drivers on your local machine ``` -./node_modules/.bin/selenium-standalone +./node_modules/.bin/selenium-standalone install +``` + +Now start the standalone server + +``` +./node_modules/.bin/selenium-standalone start ``` Then open another terminal and run