diff --git a/.env.example b/.env.example index feb03b1..07ce82a 100644 --- a/.env.example +++ b/.env.example @@ -1,9 +1,12 @@ REACT_APP_VERSION=$npm_package_version REACT_APP_NAME=$npm_package_name + +# Fill in the following variables REACT_APP_DOMAIN=https://my-app-domain.com -REACT_APP_RAVEN_PUBLIC_DSN=https://ABC@sentry.io/ZYX REACT_APP_REPOSITORY_URL=https://github.com// +# Optional variables (only if you want to use Sentry) +REACT_APP_RAVEN_PUBLIC_DSN=https://ABC@sentry.io/ZYX SENTRY_ORG=MY_ORG SENTRY_PROJECT=MY_PROG SENTRY_AUTH_TOKEN=MY_TOKEN diff --git a/README.md b/README.md index 9c564e7..091fe20 100644 --- a/README.md +++ b/README.md @@ -4,46 +4,49 @@ [![codecov](https://codecov.io/gh/tohjustin/coincharts/branch/master/graph/badge.svg)](https://codecov.io/gh/tohjustin/coincharts) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) +

+ +

+ A cryptocurrency price chart based off [https://www.coinbase.com/charts](https://www.coinbase.com/charts) * Bootstrapped with [create-react-app](https://github.com/facebookincubator/create-react-app) -* Built with [React.js](https://facebook.github.io/react/), [Redux](https://redux.js.org/), [Redux-Saga](https://redux-saga.js.org/), [styled-components](https://www.styled-components.com/), [D3.js](https://d3js.org/) +* Built with [React.js](https://facebook.github.io/react/), [Redux](https://redux.js.org/)\*\*, [Redux-Saga](https://redux-saga.js.org/)\*\*, [styled-components](https://www.styled-components.com/), [D3.js](https://d3js.org/) * Prices retrieved from [Coinbase API](https://developers.coinbase.com/api/v2) * Deployed with [Now](https://zeit.co/now) -

- -

+*\*\* [Redux](https://redux.js.org/), [Redux-Saga](https://redux-saga.js.org/) is used for learning purposes since it's a slight overkill for this simple app* ## Installation -Prerequisites: [Node](https://nodejs.org/en/download/) & [npm](https://docs.npmjs.com/getting-started/installing-node) installed on your system. +**Prerequisites**: [Node](https://nodejs.org/en/download/) & [npm](https://docs.npmjs.com/getting-started/installing-node) installed on your system. ``` bash -git clone https://github.com/tohjustin/coincharts.git && cd ./coincharts +git clone https://github.com/tohjustin/coincharts.git +cd ./coincharts npm install ``` You might also want to install [Now](https://zeit.co/now) for deployment + ``` bash npm install now-cli -g ``` ## Getting Started +**\*\*NOTE\*\*** Make sure you create a `.env` file before proceeding on (see [.env.example](./.env.example) for list of environment variables to populate) + ``` bash # Runs the app in development mode at `localhost:3000` npm run start -# Takes a snapshot of responses from coinbase API & saves them into JSON files in `public/priceData` (for offline development) -npm run downloadPriceData - # Create production build in `/build` folder npm run build -# Serve production build at `localhost:5000` -npm run serve - # Deploy app with `now.sh` using configuration defined in `now.json` -npm run deploy +npm run script:deploy + +# Takes a snapshot of responses from coinbase API & saves them into JSON files in `public/priceData` (for offline development) +npm run script:downloadPriceData ``` diff --git a/package-lock.json b/package-lock.json index 630d933..7254722 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "coincharts", - "version": "2.0.0-development", + "version": "2.0.0", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -37,12 +37,6 @@ } } }, - "@types/node": { - "version": "9.6.4", - "resolved": "https://registry.npmjs.org/@types/node/-/node-9.6.4.tgz", - "integrity": "sha512-Awg4BcUYiZtNKoveGOu654JVPt11V/KIC77iBz8NweyoOAZpz5rUJfPDwwD+ajfTs2HndbTCEB8IuLfX9m/mmw==", - "dev": true - }, "abab": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/abab/-/abab-1.0.4.tgz", @@ -1848,54 +1842,6 @@ "integrity": "sha1-Ro9XGkQ1wkJI9f0MsOjYfDw0Hn0=", "dev": true }, - "cheerio": { - "version": "1.0.0-rc.2", - "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.2.tgz", - "integrity": "sha1-S59TqBsn5NXawxwP/Qz6A8xoMNs=", - "dev": true, - "requires": { - "css-select": "1.2.0", - "dom-serializer": "0.1.0", - "entities": "1.1.1", - "htmlparser2": "3.9.2", - "lodash": "4.17.5", - "parse5": "3.0.3" - }, - "dependencies": { - "domhandler": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.1.tgz", - "integrity": "sha1-iS5HAAqZvlW783dP/qBWHYh5wlk=", - "dev": true, - "requires": { - "domelementtype": "1.3.0" - } - }, - "htmlparser2": { - "version": "3.9.2", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.9.2.tgz", - "integrity": "sha1-G9+HrMoPP55T+k/M6w9LTLsAszg=", - "dev": true, - "requires": { - "domelementtype": "1.3.0", - "domhandler": "2.4.1", - "domutils": "1.5.1", - "entities": "1.1.1", - "inherits": "2.0.3", - "readable-stream": "2.3.6" - } - }, - "parse5": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-3.0.3.tgz", - "integrity": "sha512-rgO9Zg5LLLkfJF9E6CCmXlSE4UVceloys8JrFqCcHloC3usd/kJCyPDwH2SOlzix2j3xaP9sUX3e8+kvkuleAA==", - "dev": true, - "requires": { - "@types/node": "9.6.4" - } - } - } - }, "chokidar": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.0.3.tgz", @@ -1977,12 +1923,6 @@ "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz", "integrity": "sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A==" }, - "circular-json-es6": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/circular-json-es6/-/circular-json-es6-2.0.2.tgz", - "integrity": "sha512-ODYONMMNb3p658Zv+Pp+/XPa5s6q7afhz3Tzyvo+VRh9WIrJ64J76ZC4GQxnlye/NesTn09jvOiuE8+xxfpwhQ==", - "dev": true - }, "clap": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/clap/-/clap-1.2.3.tgz", @@ -3076,27 +3016,6 @@ "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz", "integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU=" }, - "deep-equal-ident": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/deep-equal-ident/-/deep-equal-ident-1.1.1.tgz", - "integrity": "sha1-BvS4nlNxDNbOpKd4HHqVZkLejck=", - "dev": true, - "requires": { - "lodash.isequal": "3.0.4" - }, - "dependencies": { - "lodash.isequal": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-3.0.4.tgz", - "integrity": "sha1-HDXrO27wzR/1F0Pj6jz3/f/ay2Q=", - "dev": true, - "requires": { - "lodash._baseisequal": "3.0.7", - "lodash._bindcallback": "3.0.1" - } - } - } - }, "deep-extend": { "version": "0.4.2", "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.4.2.tgz", @@ -3251,12 +3170,6 @@ "randombytes": "2.0.6" } }, - "discontinuous-range": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/discontinuous-range/-/discontinuous-range-1.0.0.tgz", - "integrity": "sha1-44Mx8IRLukm5qctxx3FYWqsbxlo=", - "dev": true - }, "dns-equal": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz", @@ -3498,75 +3411,6 @@ "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.1.tgz", "integrity": "sha1-blwtClYhtdra7O+AuQ7ftc13cvA=" }, - "enzyme": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/enzyme/-/enzyme-3.3.0.tgz", - "integrity": "sha512-l8csyPyLmtxskTz6pX9W8eDOyH1ckEtDttXk/vlFWCjv00SkjTjtoUrogqp4yEvMyneU9dUJoOLnqFoiHb8IHA==", - "dev": true, - "requires": { - "cheerio": "1.0.0-rc.2", - "function.prototype.name": "1.1.0", - "has": "1.0.1", - "is-boolean-object": "1.0.0", - "is-callable": "1.1.3", - "is-number-object": "1.0.3", - "is-string": "1.0.4", - "is-subset": "0.1.1", - "lodash": "4.17.5", - "object-inspect": "1.5.0", - "object-is": "1.0.1", - "object.assign": "4.1.0", - "object.entries": "1.0.4", - "object.values": "1.0.4", - "raf": "3.4.0", - "rst-selector-parser": "2.2.3" - } - }, - "enzyme-adapter-react-16": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/enzyme-adapter-react-16/-/enzyme-adapter-react-16-1.1.1.tgz", - "integrity": "sha512-kC8pAtU2Jk3OJ0EG8Y2813dg9Ol0TXi7UNxHzHiWs30Jo/hj7alc//G1YpKUsPP1oKl9X+Lkx+WlGJpPYA+nvw==", - "dev": true, - "requires": { - "enzyme-adapter-utils": "1.3.0", - "lodash": "4.17.5", - "object.assign": "4.1.0", - "object.values": "1.0.4", - "prop-types": "15.6.1", - "react-reconciler": "0.7.0", - "react-test-renderer": "16.3.1" - } - }, - "enzyme-adapter-utils": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/enzyme-adapter-utils/-/enzyme-adapter-utils-1.3.0.tgz", - "integrity": "sha512-vVXSt6uDv230DIv+ebCG66T1Pm36Kv+m74L1TrF4kaE7e1V7Q/LcxO0QRkajk5cA6R3uu9wJf5h13wOTezTbjA==", - "dev": true, - "requires": { - "lodash": "4.17.5", - "object.assign": "4.1.0", - "prop-types": "15.6.1" - } - }, - "enzyme-matchers": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/enzyme-matchers/-/enzyme-matchers-6.0.0.tgz", - "integrity": "sha1-uIooq61C7GncG6x8ZxUtui4VeVA=", - "dev": true, - "requires": { - "circular-json-es6": "2.0.2", - "deep-equal-ident": "1.1.1" - } - }, - "enzyme-to-json": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/enzyme-to-json/-/enzyme-to-json-3.3.3.tgz", - "integrity": "sha1-7eRZOPswnNh+vUOG9gx1RSVRWgc=", - "dev": true, - "requires": { - "lodash": "4.17.5" - } - }, "errno": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz", @@ -3844,7 +3688,7 @@ "integrity": "sha512-sfmTqJfPSizWu4aymbPr4Iidp5yKm8yDkHp+Ir3YiTHiiDfxh69mOUsmiqW6RZ9zRXFaF64GtYmN7e+8GHBv6Q==", "requires": { "debug": "2.6.9", - "resolve": "1.7.1" + "resolve": "1.6.0" }, "dependencies": { "debug": { @@ -5657,17 +5501,6 @@ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" }, - "function.prototype.name": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.0.tgz", - "integrity": "sha512-Bs0VRrTz4ghD8pTmbJQD1mZ8A/mN0ur/jGz+A6FBxPDUPkm1tNfF6bhTYPA7i7aF4lZJVr+OXTNNrnnIl58Wfg==", - "dev": true, - "requires": { - "define-properties": "1.1.2", - "function-bind": "1.1.1", - "is-callable": "1.1.3" - } - }, "functional-red-black-tree": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", @@ -5918,12 +5751,6 @@ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" }, - "has-symbols": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz", - "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=", - "dev": true - }, "has-value": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", @@ -6535,12 +6362,6 @@ "binary-extensions": "1.11.0" } }, - "is-boolean-object": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.0.0.tgz", - "integrity": "sha1-mPiygDBoQhmpXzdc+9iM40Bd/5M=", - "dev": true - }, "is-buffer": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", @@ -6694,12 +6515,6 @@ } } }, - "is-number-object": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.3.tgz", - "integrity": "sha1-8mWrian0RQNO9q/xWo8AsA9VF5k=", - "dev": true - }, "is-obj": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", @@ -6825,18 +6640,6 @@ "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" }, - "is-string": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.4.tgz", - "integrity": "sha1-zDqbaYV9Yh6WNyWiTK7shzuCbmQ=", - "dev": true - }, - "is-subset": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-subset/-/is-subset-0.1.1.tgz", - "integrity": "sha1-ilkRfZMt4d4A8kX83TnOQ/HpOaY=", - "dev": true - }, "is-svg": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-svg/-/is-svg-2.1.0.tgz", @@ -7228,228 +7031,6 @@ } } }, - "jest-environment-enzyme": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/jest-environment-enzyme/-/jest-environment-enzyme-6.0.0.tgz", - "integrity": "sha1-RpzqoKIVea+GywElXwWRo6XZX0A=", - "dev": true, - "requires": { - "jest-environment-jsdom": "22.4.3" - }, - "dependencies": { - "acorn-globals": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-4.1.0.tgz", - "integrity": "sha512-KjZwU26uG3u6eZcfGbTULzFcsoz6pegNKtHPksZPOUsiKo5bUmiBPa38FuHZ/Eun+XYh/JCCkS9AS3Lu4McQOQ==", - "dev": true, - "requires": { - "acorn": "5.5.3" - } - }, - "arr-diff": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", - "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", - "dev": true, - "requires": { - "arr-flatten": "1.1.0" - } - }, - "array-unique": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", - "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", - "dev": true - }, - "braces": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", - "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", - "dev": true, - "requires": { - "expand-range": "1.8.2", - "preserve": "0.2.0", - "repeat-element": "1.1.2" - } - }, - "callsites": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-2.0.0.tgz", - "integrity": "sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA=", - "dev": true - }, - "chalk": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.2.tgz", - "integrity": "sha512-ZM4j2/ld/YZDc3Ma8PgN7gyAk+kHMMMyzLNryCPGhWrsfAuDVeuid5bpRFTDgMH9JBK2lA4dyyAkkZYF/WcqDQ==", - "dev": true, - "requires": { - "ansi-styles": "3.2.1", - "escape-string-regexp": "1.0.5", - "supports-color": "5.3.0" - } - }, - "expand-brackets": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", - "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", - "dev": true, - "requires": { - "is-posix-bracket": "0.1.1" - } - }, - "extglob": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", - "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", - "dev": true, - "requires": { - "is-extglob": "1.0.0" - } - }, - "jest-environment-jsdom": { - "version": "22.4.3", - "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-22.4.3.tgz", - "integrity": "sha512-FviwfR+VyT3Datf13+ULjIMO5CSeajlayhhYQwpzgunswoaLIPutdbrnfUHEMyJCwvqQFaVtTmn9+Y8WCt6n1w==", - "dev": true, - "requires": { - "jest-mock": "22.4.3", - "jest-util": "22.4.3", - "jsdom": "11.7.0" - } - }, - "jest-message-util": { - "version": "22.4.3", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-22.4.3.tgz", - "integrity": "sha512-iAMeKxhB3Se5xkSjU0NndLLCHtP4n+GtCqV0bISKA5dmOXQfEbdEmYiu2qpnWBDCQdEafNDDU6Q+l6oBMd/+BA==", - "dev": true, - "requires": { - "@babel/code-frame": "7.0.0-beta.44", - "chalk": "2.3.2", - "micromatch": "2.3.11", - "slash": "1.0.0", - "stack-utils": "1.0.1" - } - }, - "jest-mock": { - "version": "22.4.3", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-22.4.3.tgz", - "integrity": "sha512-+4R6mH5M1G4NK16CKg9N1DtCaFmuxhcIqF4lQK/Q1CIotqMs/XBemfpDPeVZBFow6iyUNu6EBT9ugdNOTT5o5Q==", - "dev": true - }, - "jest-util": { - "version": "22.4.3", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-22.4.3.tgz", - "integrity": "sha512-rfDfG8wyC5pDPNdcnAlZgwKnzHvZDu8Td2NJI/jAGKEGxJPYiE4F0ss/gSAkG4778Y23Hvbz+0GMrDJTeo7RjQ==", - "dev": true, - "requires": { - "callsites": "2.0.0", - "chalk": "2.3.2", - "graceful-fs": "4.1.11", - "is-ci": "1.1.0", - "jest-message-util": "22.4.3", - "mkdirp": "0.5.1", - "source-map": "0.6.1" - } - }, - "jsdom": { - "version": "11.7.0", - "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-11.7.0.tgz", - "integrity": "sha512-9NzSc4Iz4gN9p4uoPbBUzro21QdgL32swaWIaWS8eEVQ2I69fRJAy/MKyvlEIk0V7HtKgfMbbOKyTZUrzR2Hsw==", - "dev": true, - "requires": { - "abab": "1.0.4", - "acorn": "5.5.3", - "acorn-globals": "4.1.0", - "array-equal": "1.0.0", - "cssom": "0.3.2", - "cssstyle": "0.2.37", - "data-urls": "1.0.0", - "domexception": "1.0.1", - "escodegen": "1.9.1", - "html-encoding-sniffer": "1.0.2", - "left-pad": "1.3.0", - "nwmatcher": "1.4.4", - "parse5": "4.0.0", - "pn": "1.1.0", - "request": "2.85.0", - "request-promise-native": "1.0.5", - "sax": "1.2.4", - "symbol-tree": "3.2.2", - "tough-cookie": "2.3.4", - "w3c-hr-time": "1.0.1", - "webidl-conversions": "4.0.2", - "whatwg-encoding": "1.0.3", - "whatwg-mimetype": "2.1.0", - "whatwg-url": "6.4.0", - "ws": "4.1.0", - "xml-name-validator": "3.0.0" - } - }, - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "1.1.6" - } - }, - "micromatch": { - "version": "2.3.11", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", - "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", - "dev": true, - "requires": { - "arr-diff": "2.0.0", - "array-unique": "0.2.1", - "braces": "1.8.5", - "expand-brackets": "0.1.5", - "extglob": "0.3.2", - "filename-regex": "2.0.1", - "is-extglob": "1.0.0", - "is-glob": "2.0.1", - "kind-of": "3.2.2", - "normalize-path": "2.1.1", - "object.omit": "2.0.1", - "parse-glob": "3.0.4", - "regex-cache": "0.4.4" - } - }, - "parse5": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-4.0.0.tgz", - "integrity": "sha512-VrZ7eOd3T1Fk4XWNXMgiGBK/z0MG48BWG2uQNU4I72fkQuKUTZpl+u9k+CxEG0twMVzSmXEEz12z5Fnw1jIQFA==", - "dev": true - }, - "tr46": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz", - "integrity": "sha1-qLE/1r/SSJUZZ0zN5VujaTtwbQk=", - "dev": true, - "requires": { - "punycode": "2.1.0" - } - }, - "whatwg-url": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-6.4.0.tgz", - "integrity": "sha512-Z0CVh/YE217Foyb488eo+iBv+r7eAQ0wSTyApi9n06jhcA3z6Nidg/EGvl0UFkg7kMdKxfBzzr+o9JF+cevgMg==", - "dev": true, - "requires": { - "lodash.sortby": "4.7.0", - "tr46": "1.0.1", - "webidl-conversions": "4.0.2" - } - }, - "xml-name-validator": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz", - "integrity": "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==", - "dev": true - } - } - }, "jest-environment-jsdom": { "version": "20.0.3", "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-20.0.3.tgz", @@ -7469,17 +7050,6 @@ "jest-util": "20.0.3" } }, - "jest-enzyme": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/jest-enzyme/-/jest-enzyme-6.0.0.tgz", - "integrity": "sha1-UY1OzF4yyMFWS0G3vIPqOGZ+hmE=", - "dev": true, - "requires": { - "enzyme-matchers": "6.0.0", - "enzyme-to-json": "3.3.3", - "jest-environment-enzyme": "6.0.0" - } - }, "jest-get-type": { "version": "22.4.3", "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-22.4.3.tgz", @@ -7700,7 +7270,7 @@ "requires": { "browser-resolve": "1.11.2", "is-builtin-module": "1.0.0", - "resolve": "1.7.1" + "resolve": "1.6.0" } }, "jest-resolve-dependencies": { @@ -8041,9 +7611,9 @@ } }, "lint-staged": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-7.0.2.tgz", - "integrity": "sha512-zn3hRm9AOy0Xuk9HoUl4zUA2wP2TbEQyTBwTeYIV20fBK1CQOrqhqNVYQZxoxTdgCQ1fiTfr0pi6GyG2c2PdZQ==", + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-7.0.4.tgz", + "integrity": "sha512-9w4vwNJ1A7o4mwKhz/5B0VateS24KJjeU1ppO2UOBdbTg/iiypF4U6F3yckEms0Fbf5uvfLiPVp9pG2lBbVA6g==", "dev": true, "requires": { "app-root-path": "2.0.1", @@ -8066,6 +7636,7 @@ "pify": "3.0.0", "please-upgrade-node": "3.0.1", "staged-git-files": "1.1.1", + "string-argv": "0.0.2", "stringify-object": "3.2.2" }, "dependencies": { @@ -8767,29 +8338,6 @@ "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.8.tgz", "integrity": "sha512-I9mjAxengFAleSThFhhAhvba6fsO0hunb9/0sQ6qQihSZsJRBofv2rYH58WXaOb/O++eUmYpCLywSQ22GfU+sA==" }, - "lodash._baseisequal": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/lodash._baseisequal/-/lodash._baseisequal-3.0.7.tgz", - "integrity": "sha1-2AJfdjOdKTQnZ9zIh85cuVpbUfE=", - "dev": true, - "requires": { - "lodash.isarray": "3.0.4", - "lodash.istypedarray": "3.0.6", - "lodash.keys": "3.1.2" - } - }, - "lodash._bindcallback": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/lodash._bindcallback/-/lodash._bindcallback-3.0.1.tgz", - "integrity": "sha1-5THCdkTPi1epnhftlbNcdIeJOS4=", - "dev": true - }, - "lodash._getnative": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz", - "integrity": "sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U=", - "dev": true - }, "lodash._reinterpolate": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", @@ -8810,51 +8358,11 @@ "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", "integrity": "sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw=" }, - "lodash.flattendeep": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz", - "integrity": "sha1-+wMJF/hqMTTlvJvsDWngAT3f7bI=", - "dev": true - }, "lodash.get": { "version": "4.4.2", "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=" }, - "lodash.isarguments": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", - "integrity": "sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo=", - "dev": true - }, - "lodash.isarray": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz", - "integrity": "sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U=", - "dev": true - }, - "lodash.isequal": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", - "integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA=" - }, - "lodash.istypedarray": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/lodash.istypedarray/-/lodash.istypedarray-3.0.6.tgz", - "integrity": "sha1-yaR3SYYHUB2OhJTSg7h8OSgc72I=", - "dev": true - }, - "lodash.keys": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz", - "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=", - "dev": true, - "requires": { - "lodash._getnative": "3.9.1", - "lodash.isarguments": "3.1.0", - "lodash.isarray": "3.0.4" - } - }, "lodash.memoize": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", @@ -9290,18 +8798,6 @@ "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=" }, - "nearley": { - "version": "2.13.0", - "resolved": "https://registry.npmjs.org/nearley/-/nearley-2.13.0.tgz", - "integrity": "sha512-ioYYogSaZhFlCpRizQgY3UT3G1qFXmHGY/5ozoFE3dMfiCRAeJfh+IPE3/eh9gCZvqLhPCWb4bLt7Bqzo+1mLQ==", - "dev": true, - "requires": { - "nomnom": "1.6.2", - "railroad-diagrams": "1.0.0", - "randexp": "0.4.6", - "semver": "5.5.0" - } - }, "negotiator": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", @@ -9392,24 +8888,6 @@ "which": "1.3.0" } }, - "nomnom": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/nomnom/-/nomnom-1.6.2.tgz", - "integrity": "sha1-hKZqJgF0QI/Ft3oY+IjszET7aXE=", - "dev": true, - "requires": { - "colors": "0.5.1", - "underscore": "1.4.4" - }, - "dependencies": { - "colors": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/colors/-/colors-0.5.1.tgz", - "integrity": "sha1-fQAj6usVTo7p/Oddy5I9DtFmd3Q=", - "dev": true - } - } - }, "normalize-package-data": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", @@ -9539,18 +9017,6 @@ "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-1.3.0.tgz", "integrity": "sha512-05KzQ70lSeGSrZJQXE5wNDiTkBJDlUT/myi6RX9dVIvz7a7Qh4oH93BQdiPMn27nldYvVQCKMUaM83AfizZlsQ==" }, - "object-inspect": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.5.0.tgz", - "integrity": "sha512-UmOFbHbwvv+XHj7BerrhVq+knjceBdkvU5AriwLMvhv2qi+e7DJzxfBeFpILEjVzCp+xA+W/pIf06RGPWlZNfw==", - "dev": true - }, - "object-is": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.0.1.tgz", - "integrity": "sha1-CqYOyZiaCz7Xlc9NBvYs8a1lObY=", - "dev": true - }, "object-keys": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.11.tgz", @@ -9564,30 +9030,6 @@ "isobject": "3.0.1" } }, - "object.assign": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", - "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", - "dev": true, - "requires": { - "define-properties": "1.1.2", - "function-bind": "1.1.1", - "has-symbols": "1.0.0", - "object-keys": "1.0.11" - } - }, - "object.entries": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.0.4.tgz", - "integrity": "sha1-G/mk3SKI9bM/Opk9JXZh8F0WGl8=", - "dev": true, - "requires": { - "define-properties": "1.1.2", - "es-abstract": "1.11.0", - "function-bind": "1.1.1", - "has": "1.0.1" - } - }, "object.omit": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", @@ -9605,18 +9047,6 @@ "isobject": "3.0.1" } }, - "object.values": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.0.4.tgz", - "integrity": "sha1-5STaCbT2b/Bd9FdUbscqyZ8TBpo=", - "dev": true, - "requires": { - "define-properties": "1.1.2", - "es-abstract": "1.11.0", - "function-bind": "1.1.1", - "has": "1.0.1" - } - }, "obuf": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", @@ -11186,9 +10616,9 @@ "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=" }, "prettier": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-1.11.1.tgz", - "integrity": "sha512-T/KD65Ot0PB97xTrG8afQ46x3oiVhnfGjGESSI9NWYcG92+OUPZKkwHqGWXH2t9jK1crnQjubECW0FuOth+hxw==", + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-1.12.0.tgz", + "integrity": "sha512-Wz0SMncgaglBzDcohH3ZIAi4nVpzOIEweFzCOmgVEoRSeO72b4dcKGfgxoRGVMaFlh1r7dlVaJ+f3CIHfeH6xg==", "dev": true }, "pretty-bytes": { @@ -11330,22 +10760,6 @@ "performance-now": "2.1.0" } }, - "railroad-diagrams": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/railroad-diagrams/-/railroad-diagrams-1.0.0.tgz", - "integrity": "sha1-635iZ1SN3t+4mcG5Dlc3RVnN234=", - "dev": true - }, - "randexp": { - "version": "0.4.6", - "resolved": "https://registry.npmjs.org/randexp/-/randexp-0.4.6.tgz", - "integrity": "sha512-80WNmd9DA0tmZrw9qQa62GPPWfuXJknrmVmLcxvq4uZBdYqb1wYoKTmnlGUchvVWe0XiLupYkBoXVOxz3C8DYQ==", - "dev": true, - "requires": { - "discontinuous-range": "1.0.0", - "ret": "0.1.15" - } - }, "randomatic": { "version": "1.1.7", "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-1.1.7.tgz", @@ -11388,9 +10802,9 @@ "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=" }, "raven-js": { - "version": "3.24.0", - "resolved": "https://registry.npmjs.org/raven-js/-/raven-js-3.24.0.tgz", - "integrity": "sha512-+/ygcWib8PXAE7Xq53j1tYxCgkzFyp9z05LYAKp2PA9KwO4Ek74q1tkGwZyPWI/FoXOgas6jNtQ7O3tdPif6uA==" + "version": "3.24.1", + "resolved": "https://registry.npmjs.org/raven-js/-/raven-js-3.24.1.tgz", + "integrity": "sha512-p+e+yoQbq4YgXDonYIRZNL/Kov6+t5L0UNEHZeYNzjOkNNCXcwQ1Vi3pulgGBaOjqXNipkFsbpmnH7YI+GPSjw==" }, "raw-body": { "version": "2.3.2", @@ -11450,9 +10864,9 @@ } }, "react": { - "version": "16.3.0", - "resolved": "https://registry.npmjs.org/react/-/react-16.3.0.tgz", - "integrity": "sha512-Qh35tNbwY8SLFELkN3PCLO16EARV+lgcmNkQnoZXfzAF1ASRpeucZYUwBlBzsRAzTb7KyfBaLQ4/K/DLC6MYeA==", + "version": "16.3.1", + "resolved": "https://registry.npmjs.org/react/-/react-16.3.1.tgz", + "integrity": "sha512-NbkxN9jsZ6+G+ICsLdC7/wUD26uNbvKU/RAxEWgc9kcdKvROt+5d5j2cNQm5PSFTQ4WNGsR3pa4qL2Q0/WSy1w==", "requires": { "fbjs": "0.8.16", "loose-envify": "1.3.1", @@ -11486,9 +10900,9 @@ } }, "react-dom": { - "version": "16.3.0", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.3.0.tgz", - "integrity": "sha512-xT/FxawAurL6AV8YtAP7LkdDJFFX2vvv17AqFLQRF81ZtWLXkV/0dcAaiFIy0lmoQEFT931TU9aaH+5dBUxTcw==", + "version": "16.3.1", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.3.1.tgz", + "integrity": "sha512-2Infg89vzahq8nfVi1GkjPqq0vrBvf0f3T0+dTtyjq4f6HKOqKixAK25Vr593O3QTx4kw/vmUtAJwerlevNWOA==", "requires": { "fbjs": "0.8.16", "loose-envify": "1.3.1", @@ -11512,24 +10926,6 @@ "react-side-effect": "1.1.5" } }, - "react-is": { - "version": "16.3.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.3.1.tgz", - "integrity": "sha512-3XpazGqS5DEOLiuR6JQ2Sg6URq/33d1BHJVaUvtMz579KRhd2D0pqabNEe5czv785yzKBPZimOf0UNIXa3jw1A==", - "dev": true - }, - "react-reconciler": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/react-reconciler/-/react-reconciler-0.7.0.tgz", - "integrity": "sha512-50JwZ3yNyMS8fchN+jjWEJOH3Oze7UmhxeoJLn2j6f3NjpfCRbcmih83XTWmzqtar/ivd5f7tvQhvvhism2fgg==", - "dev": true, - "requires": { - "fbjs": "0.8.16", - "loose-envify": "1.3.1", - "object-assign": "4.1.1", - "prop-types": "15.6.1" - } - }, "react-redux": { "version": "5.0.7", "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-5.0.7.tgz", @@ -11554,9 +10950,9 @@ } }, "react-scripts": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/react-scripts/-/react-scripts-1.1.2.tgz", - "integrity": "sha512-yE9sebMMW1it2AZxL8T3GDI5OE8yud0BIJzBGdmnJstid8020csOxlXDVYXiJG9vCenGLfclQTXhDjo+vAt73Q==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/react-scripts/-/react-scripts-1.1.4.tgz", + "integrity": "sha512-UVZIujEIT9BGbx+NGvyfS92eOrNIIpqqFi1FP7a0O9l94A/XV7bhPk70SfDKaXZouCX81tFdXo0948DjhCEgGw==", "requires": { "autoprefixer": "7.1.6", "babel-core": "6.26.0", @@ -11589,6 +10985,7 @@ "promise": "8.0.1", "raf": "3.4.0", "react-dev-utils": "5.0.1", + "resolve": "1.6.0", "style-loader": "0.19.0", "sw-precache-webpack-plugin": "0.11.4", "url-loader": "0.6.2", @@ -11641,18 +11038,6 @@ "shallowequal": "1.0.2" } }, - "react-test-renderer": { - "version": "16.3.1", - "resolved": "https://registry.npmjs.org/react-test-renderer/-/react-test-renderer-16.3.1.tgz", - "integrity": "sha512-emEcIPUowMjT5EQ+rrb0FAwVCzuJ+LKDweoYDh073v2/jHxrBDPUk8nzI5dofG3R+140+Bb9TMcT2Ez5OP6pQw==", - "dev": true, - "requires": { - "fbjs": "0.8.16", - "object-assign": "4.1.1", - "prop-types": "15.6.1", - "react-is": "16.3.1" - } - }, "react-testing-library": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/react-testing-library/-/react-testing-library-2.1.1.tgz", @@ -12016,9 +11401,9 @@ "integrity": "sha1-79qpjqdFEyTQkrKyFjpqHXqaIUc=" }, "resolve": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.7.1.tgz", - "integrity": "sha512-c7rwLofp8g1U+h1KNyHL/jicrKg1Ek4q+Lr33AL65uZTinUZHe30D5HlyN5V9NW0JX1D5dXQ4jqW5l7Sy/kGfw==", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.6.0.tgz", + "integrity": "sha512-mw7JQNu5ExIkcw4LPih0owX/TZXjD/ZUF/ZQ/pDnkw3ZKhDcZZw5klmBlj6gVMwjQ3Pz5Jgu7F3d0jcDVuEWdw==", "requires": { "path-parse": "1.0.5" } @@ -12106,16 +11491,6 @@ } } }, - "rst-selector-parser": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/rst-selector-parser/-/rst-selector-parser-2.2.3.tgz", - "integrity": "sha1-gbIw6i/MYGbInjRy3nlChdmwPZE=", - "dev": true, - "requires": { - "lodash.flattendeep": "4.4.0", - "nearley": "2.13.0" - } - }, "run-async": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", @@ -12820,6 +12195,12 @@ "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz", "integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=" }, + "string-argv": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.0.2.tgz", + "integrity": "sha1-2sMECGkMIfPDYwo/86BYd73L1zY=", + "dev": true + }, "string-length": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/string-length/-/string-length-1.0.1.tgz", @@ -13331,12 +12712,6 @@ } } }, - "underscore": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.4.4.tgz", - "integrity": "sha1-YaajIBBiKvoHljvzJSA88SI51gQ=", - "dev": true - }, "union-value": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.0.tgz", diff --git a/package.json b/package.json index 148db1e..dc2079c 100644 --- a/package.json +++ b/package.json @@ -1,20 +1,20 @@ { "name": "coincharts", - "version": "2.0.0", - "description": "Cryptocurrency price chart, powered by Coinbase API", + "version": "2.1.0", + "description": "Cryptocurrency Price Chart (GDAX)", "repository": "tohjustin/coincharts", "license": "MIT", "scripts": { "build": "source .env && react-scripts build", - "deploy": "scripts/deploy.sh", - "downloadPriceData": "scripts/downloadPriceData.sh ./public/priceData", "eject": "react-scripts eject", "lint": "eslint src", "precommit": "npm run lint && lint-staged", + "script:deploy": "scripts/deploy.sh", + "script:downloadPriceData": "scripts/downloadPriceData.sh ./public/priceData", "start": "react-scripts start", - "test": "TZ=America/Vancouver CI=true react-scripts test --env=jsdom", "test:coverage": "npm run test -- --coverage --verbose", - "test:watch": "TZ=America/Vancouver react-scripts test --env=jsdom" + "test:watch": "TZ=America/Vancouver react-scripts test --env=jsdom", + "test": "TZ=America/Vancouver CI=true react-scripts test --env=jsdom" }, "dependencies": { "axios": "0.18.0", @@ -28,7 +28,6 @@ "d3-time-format": "2.1.1", "d3-transition": "1.1.1", "lodash.get": "4.4.2", - "lodash.isequal": "4.5.0", "prop-types": "15.6.1", "raven-js": "3.24.1", "react": "16.3.1", @@ -45,17 +44,14 @@ "devDependencies": { "check-types": "7.3.0", "codecov": "3.0.0", - "enzyme": "3.3.0", - "enzyme-adapter-react-16": "1.1.1", - "eslint-config-airbnb": "^16.1.0", - "eslint-config-prettier": "^2.9.0", - "eslint-plugin-prettier": "^2.6.0", - "eslint-plugin-react": "^7.7.0", + "eslint-config-airbnb": "16.1.0", + "eslint-config-prettier": "2.9.0", + "eslint-plugin-prettier": "2.6.0", + "eslint-plugin-react": "7.7.0", "husky": "0.14.3", - "jest-enzyme": "6.0.0", "lint-staged": "7.0.4", "prettier": "1.12.0", - "react-testing-library": "^2.0.0" + "react-testing-library": "2.1.1" }, "lint-staged": { "*.js": [ diff --git a/scripts/deploy.sh b/scripts/deploy.sh index 0fd907b..663e71b 100755 --- a/scripts/deploy.sh +++ b/scripts/deploy.sh @@ -5,7 +5,7 @@ BUILD_DIRECTORY=./build DEPLOY_DIRECTORY=./deploy # Run tests & create production build -npm run check +npm run lint npm run build # Copy bundled files into `deploy` directory diff --git a/src/components/Chart/Chart.js b/src/components/Chart/Chart.js index e5da87e..b57051f 100644 --- a/src/components/Chart/Chart.js +++ b/src/components/Chart/Chart.js @@ -61,6 +61,11 @@ class Chart extends Component { this.handleResize(); } + shouldComponentUpdate(nextProps) { + const { isLoading } = nextProps; + return !isLoading; + } + componentWillUnmount() { window.removeEventListener("resize", this.handleResize); } @@ -116,7 +121,13 @@ class Chart extends Component { } render() { - const { dimensions, hoveredValue: { price, time }, hoverX, hoverY, hovered } = this.state; + const { + dimensions, + hoveredValue: { price, time }, + hoverX, + hoverY, + hovered, + } = this.state; const { color, currency, @@ -164,6 +175,7 @@ Chart.propTypes = { currency: PROPTYPES.CURRENCY.isRequired, data: PROPTYPES.PRICE_DATA.isRequired, durationType: PROPTYPES.DURATION.isRequired, + isLoading: PropTypes.bool.isRequired, disableCursor: PropTypes.bool, hideRightVerticalAxis: PropTypes.bool, horizontalAxisTickCount: PropTypes.number, diff --git a/src/components/Chart/Graph.js b/src/components/Chart/Graph.js index b6c7e05..22248fa 100644 --- a/src/components/Chart/Graph.js +++ b/src/components/Chart/Graph.js @@ -1,6 +1,5 @@ import React, { Component } from "react"; import PropTypes from "prop-types"; -import isEqual from "lodash.isequal"; import styled from "styled-components"; import { area as d3Area, line as d3Line } from "d3-shape"; import { extent } from "d3-array"; @@ -83,15 +82,6 @@ class Graph extends Component { }); } - shouldComponentUpdate(nextProps) { - // Don't update if next set of data is not ready - if (nextProps.data === undefined || nextProps.data.length === 0) { - return false; - } - - return !isEqual(this.props, nextProps); - } - componentDidUpdate() { const { color, height } = this.props; const { previousColor = color, previousScaledData, scaledData, skipTransition } = this.state; diff --git a/src/components/Chart/HorizontalAxis.js b/src/components/Chart/HorizontalAxis.js index bcfe451..6dfcbb8 100644 --- a/src/components/Chart/HorizontalAxis.js +++ b/src/components/Chart/HorizontalAxis.js @@ -1,6 +1,5 @@ import React, { Component } from "react"; import PropTypes from "prop-types"; -import isEqual from "lodash.isequal"; import { extent } from "d3-array"; import { timeFormat } from "d3-time-format"; import styled from "styled-components"; @@ -53,24 +52,6 @@ class HorizontalAxis extends Component { return generatedTicks; } - // Only update when we receive new data (delay changing labels until price data is ready) - shouldComponentUpdate(nextProps) { - const { data, tickCount } = this.props; - const { data: nextData, tickCount: nextTickCount } = nextProps; - - // Always update when tickCount changes - if (tickCount !== nextTickCount) { - return true; - } - - // Don't update if next set of data is not ready - if (nextData.length === 0) { - return false; - } - - return !isEqual(data, nextData); - } - render() { const { data, duration, tickCount, hideRightMargin } = this.props; const durationTicks = HorizontalAxis.generateTicks(data, tickCount); @@ -81,12 +62,7 @@ class HorizontalAxis extends Component { return ( - {axisTicks && - axisTicks.map(({ timestamp, label }) => ( - - {label} - - ))} + {axisTicks && axisTicks.map(({ timestamp, label }) => {label})} ); } diff --git a/src/components/Chart/__tests__/Chart.test.js b/src/components/Chart/__tests__/Chart.test.js index a0a1769..74af9b5 100644 --- a/src/components/Chart/__tests__/Chart.test.js +++ b/src/components/Chart/__tests__/Chart.test.js @@ -16,6 +16,7 @@ const TEST_PROPS = { stroke: "#666", }, durationType: "day", + isLoading: false, }; describe("", () => { @@ -25,6 +26,19 @@ describe("", () => { expect(container.firstChild).toMatchSnapshot(); }); + it("does not rerender when `props.isLoading` is true", () => { + const { container } = render(); + const { textContent } = container.firstChild; + + // Component should not rerender + render(, { container }); + expect(container.firstChild.textContent).toEqual(textContent); + + // Component should rerender + render(, { container }); + expect(container.firstChild.textContent).not.toEqual(textContent); + }); + it("renders child components correctly", () => { const { queryByTestId } = render(); expect(queryByTestId("Graph")).not.toBeNull(); diff --git a/src/components/Chart/__tests__/Graph.test.js b/src/components/Chart/__tests__/Graph.test.js index 1b8db94..c736d4b 100644 --- a/src/components/Chart/__tests__/Graph.test.js +++ b/src/components/Chart/__tests__/Graph.test.js @@ -39,13 +39,4 @@ describe("", () => { expect(container.firstChild.querySelectorAll("path")).toHaveLength(0); expect(container.firstChild).toMatchSnapshot(); }); - - it("does not render SVG 's when `props.data` does not change & other props changes", () => { - // Set to be initially empty & update props after initial render - const { container } = render(); - render(, { container }); - - expect(container.firstChild.querySelectorAll("path")).toHaveLength(0); - expect(container.firstChild).toMatchSnapshot(); - }); }); diff --git a/src/components/Chart/__tests__/HorizontalAxis.test.js b/src/components/Chart/__tests__/HorizontalAxis.test.js index 565c511..6cf2042 100644 --- a/src/components/Chart/__tests__/HorizontalAxis.test.js +++ b/src/components/Chart/__tests__/HorizontalAxis.test.js @@ -39,42 +39,6 @@ describe("", () => { expect(container.firstChild).toMatchSnapshot(); }); - it("does not update when `props.data`, `props.tickCount` does not change & other props changes", () => { - const { container } = render(); - const initialTextContent = container.firstChild.textContent; - expect(initialTextContent).toBeDefined(); - - // Change `props.duration` - render(, { container }); - expect(container.firstChild.children).toHaveLength(TEST_PROPS.tickCount); - expect(container.firstChild.textContent).toEqual(initialTextContent); - expect(container.firstChild).toMatchSnapshot(); - }); - - it("updates when `props.tickCount` changes", () => { - const { container } = render(); - const initialTextContent = container.firstChild.textContent; - expect(initialTextContent).toBeDefined(); - - // Change `props.tickCount` - render(, { container }); - expect(container.firstChild.children).toHaveLength(10); - expect(container.firstChild.textContent).not.toEqual(initialTextContent); - expect(container.firstChild).toMatchSnapshot(); - }); - - it("does not update when `props.data` is changed to []", () => { - const { container } = render(); - const initialTextContent = container.firstChild.textContent; - expect(initialTextContent).toBeDefined(); - - // Change `props.data` to [] - render(, { container }); - expect(container.firstChild.children).toHaveLength(TEST_PROPS.tickCount); - expect(container.firstChild.textContent).toEqual(initialTextContent); - expect(container.firstChild).toMatchSnapshot(); - }); - describe("formatTime()", () => { const timestamp0 = Date.parse("Sun, 31 Dec 2017 12:00:00"); const timestamp1 = Date.parse("Mon, 01 Jan 2018 00:00:00"); diff --git a/src/components/Chart/__tests__/__snapshots__/Chart.test.js.snap b/src/components/Chart/__tests__/__snapshots__/Chart.test.js.snap index 11760e2..b0dd34c 100644 --- a/src/components/Chart/__tests__/__snapshots__/Chart.test.js.snap +++ b/src/components/Chart/__tests__/__snapshots__/Chart.test.js.snap @@ -28,7 +28,18 @@ exports[` renders without crashing 1`] = ` class="sc-ifAKCX dCYFNS" data-testid="Graph" > - + + + + renders without crashing 1`] = ` data-testid="HorizontalAxis" >
04:16 PM
04:25 PM
04:33 PM
04:41 PM
04:50 PM
04:58 PM
05:06 PM
diff --git a/src/components/Chart/__tests__/__snapshots__/Graph.test.js.snap b/src/components/Chart/__tests__/__snapshots__/Graph.test.js.snap index 2c9dce3..c86d5c5 100644 --- a/src/components/Chart/__tests__/__snapshots__/Graph.test.js.snap +++ b/src/components/Chart/__tests__/__snapshots__/Graph.test.js.snap @@ -1,14 +1,5 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[` does not render SVG 's when \`props.data\` does not change & other props changes 1`] = ` - - - -`; - exports[` does not render SVG 's when \`props.data\` is [] 1`] = ` does not render ticks when \`TEST_PROPS.data\` is [] /> `; -exports[` does not update when \`props.data\` is changed to [] 1`] = ` -
-
- 04:16 PM -
-
- 05:15 PM -
-
- 06:13 PM -
-
-`; - -exports[` does not update when \`props.data\`, \`props.tickCount\` does not change & other props changes 1`] = ` -
-
- 04:16 PM -
-
- 05:15 PM -
-
- 06:13 PM -
-
-`; - exports[` renders without crashing 1`] = `
04:16 PM
05:15 PM
- 06:13 PM -
-
-`; - -exports[` updates when \`props.tickCount\` changes 1`] = ` -
-
- 04:16 PM -
-
- 04:29 PM -
-
- 04:42 PM -
-
- 04:55 PM -
-
- 05:08 PM -
-
- 05:21 PM -
-
- 05:34 PM -
-
- 05:47 PM -
-
- 06:00 PM -
-
06:13 PM
diff --git a/src/components/ErrorBoundary/ErrorBoundary.js b/src/components/ErrorBoundary/ErrorBoundary.js new file mode 100644 index 0000000..27f1679 --- /dev/null +++ b/src/components/ErrorBoundary/ErrorBoundary.js @@ -0,0 +1,47 @@ +import React, { Component } from "react"; +import PropTypes from "prop-types"; +import Raven from "raven-js"; +import styled from "styled-components"; + +import Flex from "../Flex"; +import GithubBanner from "../GithubBanner"; +import { color, fontFamily, fontSize, fontWeight } from "../../styles/constants"; + +const StyledErrorBoundary = styled(Flex)` + font-family: ${fontFamily.regular}; + color: ${color.white}; + font-size: ${fontSize.huge}; + font-weight: ${fontWeight.medium}; + width: 100vw; +`; + +const ERROR_MESSAGE_TEXT = "Uh-oh, Something went wrong..."; + +class ErrorBoundary extends Component { + constructor(props) { + super(props); + this.state = { hasError: false }; + } + + componentDidCatch(error, info) { + this.setState({ hasError: true }); + Raven.captureException(error, { extra: info }); + } + + render() { + return this.state.hasError ? ( + + +
{ERROR_MESSAGE_TEXT}
+
+ ) : ( + this.props.children + ); + } +} + +ErrorBoundary.propTypes = { + children: PropTypes.node.isRequired, +}; + +export default ErrorBoundary; diff --git a/src/components/ErrorBoundary/__tests__/ErrorBoundary.test.js b/src/components/ErrorBoundary/__tests__/ErrorBoundary.test.js new file mode 100644 index 0000000..fa8b2a1 --- /dev/null +++ b/src/components/ErrorBoundary/__tests__/ErrorBoundary.test.js @@ -0,0 +1,28 @@ +import React from "react"; +import { render } from "react-testing-library"; + +import ErrorBoundary from "../"; + +describe("", () => { + it("renders without crashing", () => { + const { container } = render( + +
Hello World
+
, + ); + + expect(container.firstChild).not.toBeNull(); + expect(container.firstChild).toMatchSnapshot(); + }); + + it("throws console.error if there's no `props.children`", () => { + console.error = jest.fn(); // eslint-disable-line no-console + + try { + render(); + throw new Error("should have thrown error"); + } catch (err) { + expect(console.error).toHaveBeenCalled(); // eslint-disable-line no-console + } + }); +}); diff --git a/src/components/ErrorBoundary/__tests__/__snapshots__/ErrorBoundary.test.js.snap b/src/components/ErrorBoundary/__tests__/__snapshots__/ErrorBoundary.test.js.snap new file mode 100644 index 0000000..a0aff35 --- /dev/null +++ b/src/components/ErrorBoundary/__tests__/__snapshots__/ErrorBoundary.test.js.snap @@ -0,0 +1,7 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` renders without crashing 1`] = ` +
+ Hello World +
+`; diff --git a/src/components/ErrorBoundary/index.js b/src/components/ErrorBoundary/index.js new file mode 100644 index 0000000..0989ee4 --- /dev/null +++ b/src/components/ErrorBoundary/index.js @@ -0,0 +1,3 @@ +import ErrorBoundary from "./ErrorBoundary"; + +export default ErrorBoundary; diff --git a/src/components/Footer/Footer.js b/src/components/Footer/Footer.js index 8ecad32..6fe6ac0 100644 --- a/src/components/Footer/Footer.js +++ b/src/components/Footer/Footer.js @@ -9,9 +9,9 @@ const StyledFooter = styled.div` font-family: ${fontFamily.regular}; font-size: ${fontSize.medium}; font-weight: ${fontWeight.medium}; - text-align: center; height: 0; line-height: 4em; + text-align: center; `; const Image = styled.img` diff --git a/src/components/Footer/__tests__/__snapshots__/Footer.test.js.snap b/src/components/Footer/__tests__/__snapshots__/Footer.test.js.snap index f8f36e9..6ee5b48 100644 --- a/src/components/Footer/__tests__/__snapshots__/Footer.test.js.snap +++ b/src/components/Footer/__tests__/__snapshots__/Footer.test.js.snap @@ -2,7 +2,7 @@ exports[`