From 1dba0a88d4240e2549691ab4fd5329e18bfd4610 Mon Sep 17 00:00:00 2001 From: Chris <chris@chrissnijder.nl> Date: Wed, 3 Feb 2021 01:45:57 +0100 Subject: [PATCH] Finish installing jest and addons, make a tested component. --- jest.setup.js | 1 + package.json | 4 +- pnpm-lock.yaml | 165 ++++++++++++++++++++++++ src/components/spinner/Spinner.scss | 23 ++++ src/components/spinner/Spinner.test.tsx | 28 ++++ src/components/spinner/Spinner.tsx | 21 +++ 6 files changed, 241 insertions(+), 1 deletion(-) create mode 100644 src/components/spinner/Spinner.scss create mode 100644 src/components/spinner/Spinner.test.tsx create mode 100644 src/components/spinner/Spinner.tsx diff --git a/jest.setup.js b/jest.setup.js index e69de29..cbe7c3d 100644 --- a/jest.setup.js +++ b/jest.setup.js @@ -0,0 +1 @@ +import "@testing-library/jest-dom/extend-expect"; \ No newline at end of file diff --git a/package.json b/package.json index 7fc7c00..29c6341 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ "scripts": { "start": "snowpack dev", "build": "snowpack build", - "test": "jest \"src/**/*.test.tsx\" --coverage --watchAll", + "test": "jest src\/ --coverage --watchAll", "format": "prettier --write \"src/**/*.{js,jsx,ts,tsx}\"", "lint": "prettier --check \"src/**/*.{js,jsx,ts,tsx}\"" }, @@ -25,12 +25,14 @@ "@snowpack/plugin-dotenv": "^2.0.5", "@snowpack/plugin-react-refresh": "^2.4.0", "@snowpack/plugin-typescript": "^1.2.0", + "@testing-library/jest-dom": "^5.11.9", "@testing-library/react": "^11.0.0", "@types/jest": "^26.0.20", "@types/react": "^17.0.0", "@types/react-dom": "^17.0.0", "@types/snowpack-env": "^2.3.2", "jest-cli": "^26.6.3", + "jest-each": "^26.6.2", "prettier": "^2.0.5", "rxjs": "^6.6.3", "snowpack": "^3.0.11", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 0c06b1c..154297b 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -5,15 +5,19 @@ devDependencies: '@snowpack/app-scripts-react': 2.0.0_c39e9db791ea05e3ec4e0e74abb7a6b5 '@snowpack/plugin-dotenv': 2.0.5 '@snowpack/plugin-react-refresh': 2.4.0_react-dom@17.0.1+react@17.0.1 + '@snowpack/plugin-sass': 1.3.0 '@snowpack/plugin-typescript': 1.2.1_typescript@4.1.3 + '@testing-library/jest-dom': 5.11.9 '@testing-library/react': 11.2.3_react-dom@17.0.1+react@17.0.1 '@types/jest': 26.0.20 '@types/react': 17.0.0 '@types/react-dom': 17.0.0 '@types/snowpack-env': 2.3.3 jest-cli: 26.6.3 + jest-each: 26.6.2 prettier: 2.2.1 rxjs: 6.6.3 + sass: 1.32.6 snowpack: 3.0.11 typescript: 4.1.3 lockfileVersion: 5.2 @@ -1533,6 +1537,14 @@ packages: react-dom: '>=16.9.0' resolution: integrity: sha512-qz2BzdWa5DPK7teTRrh8/SY81mWt//NZmRUUzrQZS2I9d9St8GfSAbFgeJunpBCpPXW9QaaI7huNaoTx/+1/Ag== + /@snowpack/plugin-sass/1.3.0: + dependencies: + execa: 5.0.0 + npm-run-path: 4.0.1 + sass: 1.32.6 + dev: true + resolution: + integrity: sha512-MbUFwISnPMKc8CY0E1qbaxIHGTn0DiPhqIbyr+BBlwI3dBYJeEGzB9eEEttmOQ9WsZgoigeQcfO9IMvNkwRNFg== /@snowpack/plugin-typescript/1.2.1_typescript@4.1.3: dependencies: execa: 5.0.0 @@ -1558,6 +1570,23 @@ packages: node: '>=10' resolution: integrity: sha512-CtrJRiSYEfbtNGtEsd78mk1n1v2TUbeABlNIcOCJdDfkN5/JTOwQEbbQpoSRxGqzcWPgStMvJ4mNolSuBRv1NA== + /@testing-library/jest-dom/5.11.9: + dependencies: + '@babel/runtime': 7.12.5 + '@types/testing-library__jest-dom': 5.9.5 + aria-query: 4.2.2 + chalk: 3.0.0 + css: 3.0.0 + css.escape: 1.5.1 + lodash: 4.17.20 + redent: 3.0.0 + dev: true + engines: + node: '>=8' + npm: '>=6' + yarn: '>=1' + resolution: + integrity: sha512-Mn2gnA9d1wStlAIT2NU8J15LNob0YFBVjs2aEQ3j8rsfRQo+lAs7/ui1i2TGaJjapLmuNPLTsrm+nPjmZDwpcQ== /@testing-library/react/11.2.3_react-dom@17.0.1+react@17.0.1: dependencies: '@babel/runtime': 7.12.5 @@ -1675,6 +1704,12 @@ packages: dev: true resolution: integrity: sha512-RJJrrySY7A8havqpGObOB4W92QXKJo63/jFLLgpvOtsGUqbQZ9Sbgl35KMm1DjC6j7AvmmU2bIno+3IyEaemaw== + /@types/testing-library__jest-dom/5.9.5: + dependencies: + '@types/jest': 26.0.20 + dev: true + resolution: + integrity: sha512-ggn3ws+yRbOHog9GxnXiEZ/35Mow6YtPZpd7Z5mKDeZS/o7zx3yAle0ov/wjhVB5QT4N2Dt+GNoGCdqkBGCajQ== /@types/yargs-parser/20.2.0: dev: true resolution: @@ -1979,6 +2014,12 @@ packages: dev: true resolution: integrity: sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4= + /binary-extensions/2.2.0: + dev: true + engines: + node: '>=8' + resolution: + integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== /brace-expansion/1.1.11: dependencies: balanced-match: 1.0.0 @@ -2105,6 +2146,15 @@ packages: node: '>=4' resolution: integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== + /chalk/3.0.0: + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + dev: true + engines: + node: '>=8' + resolution: + integrity: sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg== /chalk/4.1.0: dependencies: ansi-styles: 4.3.0 @@ -2120,6 +2170,22 @@ packages: node: '>=10' resolution: integrity: sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw== + /chokidar/3.5.1: + dependencies: + anymatch: 3.1.1 + braces: 3.0.2 + glob-parent: 5.1.1 + is-binary-path: 2.1.0 + is-glob: 4.0.1 + normalize-path: 3.0.0 + readdirp: 3.5.0 + dev: true + engines: + node: '>= 8.10.0' + optionalDependencies: + fsevents: 2.3.1 + resolution: + integrity: sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw== /ci-info/2.0.0: dev: true resolution: @@ -2276,6 +2342,18 @@ packages: node: '>= 8' resolution: integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== + /css.escape/1.5.1: + dev: true + resolution: + integrity: sha1-QuJ9T6BK4y+TGktNQZH6nN3ul8s= + /css/3.0.0: + dependencies: + inherits: 2.0.4 + source-map: 0.6.1 + source-map-resolve: 0.6.0 + dev: true + resolution: + integrity: sha512-DG9pFfwOrzc+hawpmqX/dHYHJG+Bsdb0klhyi1sDneOgGOXy9wQIC8hzyVp1e4NRYDBdxcylvywPkkXCHAzTyQ== /cssom/0.3.8: dev: true resolution: @@ -2808,6 +2886,14 @@ packages: dev: true resolution: integrity: sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo= + /glob-parent/5.1.1: + dependencies: + is-glob: 4.0.1 + dev: true + engines: + node: '>= 6' + resolution: + integrity: sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ== /glob/7.1.6: dependencies: fs.realpath: 1.0.0 @@ -2983,6 +3069,12 @@ packages: node: '>=0.8.19' resolution: integrity: sha1-khi5srkoojixPcT7a21XbyMUU+o= + /indent-string/4.0.0: + dev: true + engines: + node: '>=8' + resolution: + integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg== /inflight/1.0.6: dependencies: once: 1.4.0 @@ -3026,6 +3118,14 @@ packages: dev: true resolution: integrity: sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0= + /is-binary-path/2.1.0: + dependencies: + binary-extensions: 2.2.0 + dev: true + engines: + node: '>=8' + resolution: + integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== /is-buffer/1.1.6: dev: true resolution: @@ -3100,6 +3200,12 @@ packages: node: '>=0.10.0' resolution: integrity: sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA== + /is-extglob/2.1.1: + dev: true + engines: + node: '>=0.10.0' + resolution: + integrity: sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= /is-fullwidth-code-point/3.0.0: dev: true engines: @@ -3112,6 +3218,14 @@ packages: node: '>=6' resolution: integrity: sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ== + /is-glob/4.0.1: + dependencies: + is-extglob: 2.1.1 + dev: true + engines: + node: '>=0.10.0' + resolution: + integrity: sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg== /is-number/3.0.0: dependencies: kind-of: 3.2.2 @@ -3932,6 +4046,12 @@ packages: node: '>=6' resolution: integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== + /min-indent/1.0.1: + dev: true + engines: + node: '>=4' + resolution: + integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg== /minimatch/3.0.4: dependencies: brace-expansion: 1.1.11 @@ -4403,6 +4523,23 @@ packages: node: '>=8' resolution: integrity: sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg== + /readdirp/3.5.0: + dependencies: + picomatch: 2.2.2 + dev: true + engines: + node: '>=8.10.0' + resolution: + integrity: sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ== + /redent/3.0.0: + dependencies: + indent-string: 4.0.0 + strip-indent: 3.0.0 + dev: true + engines: + node: '>=8' + resolution: + integrity: sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg== /regenerate-unicode-properties/8.2.0: dependencies: regenerate: 1.4.2 @@ -4640,6 +4777,15 @@ packages: hasBin: true resolution: integrity: sha512-hhbzAgTIX8O7SHfp2c8/kREfEn4qO/9q8C9beyY6+tvZ87EpoZ3i1RIEvp27YBswnNbY9mWd6paKVmKbAgLfZA== + /sass/1.32.6: + dependencies: + chokidar: 3.5.1 + dev: true + engines: + node: '>=8.9.0' + hasBin: true + resolution: + integrity: sha512-1bcDHDcSqeFtMr0JXI3xc/CXX6c4p0wHHivJdru8W7waM7a1WjKMm4m/Z5sY7CbVw4Whi2Chpcw6DFfSWwGLzQ== /saxes/5.0.1: dependencies: xmlchars: 2.2.0 @@ -4797,6 +4943,13 @@ packages: dev: true resolution: integrity: sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw== + /source-map-resolve/0.6.0: + dependencies: + atob: 2.1.2 + decode-uri-component: 0.2.0 + dev: true + resolution: + integrity: sha512-KXBr9d/fO/bWo97NXsPIAW1bFSBOuCnjbNTBMO7N59hsv5i9yzRDfcYwwt0l04+VqnKC+EwzvJZIP/qkuMgR/w== /source-map-support/0.5.19: dependencies: buffer-from: 1.1.1 @@ -4945,6 +5098,14 @@ packages: node: '>=6' resolution: integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA== + /strip-indent/3.0.0: + dependencies: + min-indent: 1.0.1 + dev: true + engines: + node: '>=8' + resolution: + integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ== /supports-color/5.5.0: dependencies: has-flag: 3.0.0 @@ -5407,16 +5568,20 @@ specifiers: '@snowpack/app-scripts-react': ^2.0.0 '@snowpack/plugin-dotenv': ^2.0.5 '@snowpack/plugin-react-refresh': ^2.4.0 + '@snowpack/plugin-sass': ^1.3.0 '@snowpack/plugin-typescript': ^1.2.0 + '@testing-library/jest-dom': ^5.11.9 '@testing-library/react': ^11.0.0 '@types/jest': ^26.0.20 '@types/react': ^17.0.0 '@types/react-dom': ^17.0.0 '@types/snowpack-env': ^2.3.2 jest-cli: ^26.6.3 + jest-each: ^26.6.2 prettier: ^2.0.5 react: ^17.0.0 react-dom: ^17.0.0 rxjs: ^6.6.3 + sass: ^1.32.6 snowpack: ^3.0.11 typescript: ^4.0.0 diff --git a/src/components/spinner/Spinner.scss b/src/components/spinner/Spinner.scss new file mode 100644 index 0000000..72d9273 --- /dev/null +++ b/src/components/spinner/Spinner.scss @@ -0,0 +1,23 @@ +@import "../../styles/colors.scss"; +$spinner-size: 1.75rem; +$spinner-size-big: 3rem; + +.spinner.loading { + border: $spinner-size/8 solid $spinner-background; + border-top: $spinner-size/8 solid $spinner-color; + width: $spinner-size; + height: $spinner-size; + &.big { + border: $spinner-size-big/8 solid $spinner-background; + border-top: $spinner-size-big/8 solid $spinner-color; + width: $spinner-size-big; + height: $spinner-size-big; + } + border-radius: 50%; + animation: spin .7s linear infinite; +} + +@keyframes spin { + 0% { transform: rotate(0deg); } + 100% { transform: rotate(360deg); } +} diff --git a/src/components/spinner/Spinner.test.tsx b/src/components/spinner/Spinner.test.tsx new file mode 100644 index 0000000..9cdce02 --- /dev/null +++ b/src/components/spinner/Spinner.test.tsx @@ -0,0 +1,28 @@ +import * as React from 'react'; +import { render } from '@testing-library/react'; +import Spinner from './Spinner'; +const each = require("jest-each").default; + +describe('<Spinner>', () => { + + it("renders spinning loading indicator: default", () => { + const { getByRole } = render(<Spinner />); + const spinner = getByRole("progressbar"); + expect(spinner).toBeVisible(); + expect(spinner).not.toHaveClass("big") + }) + + const variations = [["small", false], ["big", true]]; + each(variations).it(`renders spinning loading indicator: %s`, (big: boolean) => { + const { getByRole } = render(<Spinner loading={true} big={big} />); + const spinner = getByRole("progressbar"); + expect(spinner).toBeVisible(); + }) + + each(variations).it(`Does not render spinning loading indicator: %s`, (big: boolean) => { + const { queryByRole } = render(<Spinner loading={false} big={big} />); + const spinners = queryByRole("progressbar"); + expect(spinners).toBe(null); + }); +}); + diff --git a/src/components/spinner/Spinner.tsx b/src/components/spinner/Spinner.tsx new file mode 100644 index 0000000..ba280b9 --- /dev/null +++ b/src/components/spinner/Spinner.tsx @@ -0,0 +1,21 @@ +import React from 'react'; +import './Spinner.scss'; + +export interface SpinnerProps { + big?: boolean, + loading?: boolean +} + +function Spinner({ big = false, loading = true }: SpinnerProps) { + if (!loading) + return (<div className="spinner"></div>) + const classes = ["spinner", "loading"]; + if (big) + classes.push("big"); + return ( + <div className={classes.join(" ")} role="progressbar" aria-label="Loading"></div> + ); +} + +export default Spinner; + -- GitLab