test: add basic test suite (#130)

* test: add basic test for App component

* test: add basic test for Wallets component

* Debug log only in dev env (spare test environment)

* ci: enable tests in GitHub build workflow

Co-authored-by: Dennis Reimann <mail@dennisreimann.de>
This commit is contained in:
Thebora Kompanioni 2022-03-03 11:04:31 +01:00 committed by GitHub
parent 07621266ae
commit 90fa57374b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 559 additions and 121 deletions

View file

@ -30,8 +30,9 @@ jobs:
# Checks
- name: Lint
run: npm run lint
# - name: Test
# run: npm test
# Test
- name: Test
run: npm test
# Build
- name: Build
run: npm run build

419
package-lock.json generated
View file

@ -23,6 +23,8 @@
"conventional-changelog": "^3.1.25",
"http-proxy-middleware": "^2.0.1",
"husky": "^7.0.4",
"jest-watch-typeahead": "^0.6.5",
"jest-websocket-mock": "^2.3.0",
"lint-staged": "^12.3.1",
"moving-letters": "^1.0.1",
"nth-check": ">=2.0.1",
@ -11665,88 +11667,24 @@
"dev": true
},
"node_modules/jest-watch-typeahead": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/jest-watch-typeahead/-/jest-watch-typeahead-1.0.0.tgz",
"integrity": "sha512-jxoszalAb394WElmiJTFBMzie/RDCF+W7Q29n5LzOPtcoQoHWfdUtHFkbhgf5NwWe8uMOxvKb/g7ea7CshfkTw==",
"version": "0.6.5",
"resolved": "https://registry.npmjs.org/jest-watch-typeahead/-/jest-watch-typeahead-0.6.5.tgz",
"integrity": "sha512-GIbV6h37/isatMDtqZlA8Q5vC6T3w+5qdvtF+3LIkPc58zEWzbKmTHvlUIp3wvBm400RzrQWcVPcsAJqKWu7XQ==",
"dev": true,
"dependencies": {
"ansi-escapes": "^4.3.1",
"chalk": "^4.0.0",
"jest-regex-util": "^27.0.0",
"jest-watcher": "^27.0.0",
"slash": "^4.0.0",
"string-length": "^5.0.1",
"strip-ansi": "^7.0.1"
"slash": "^3.0.0",
"string-length": "^4.0.1",
"strip-ansi": "^6.0.0"
},
"engines": {
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
"node": ">=10"
},
"peerDependencies": {
"jest": "^27.0.0"
}
},
"node_modules/jest-watch-typeahead/node_modules/ansi-regex": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz",
"integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==",
"dev": true,
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/chalk/ansi-regex?sponsor=1"
}
},
"node_modules/jest-watch-typeahead/node_modules/char-regex": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/char-regex/-/char-regex-2.0.0.tgz",
"integrity": "sha512-oGu2QekBMXgyQNWPDRQ001bjvDnZe4/zBTz37TMbiKz1NbNiyiH5hRkobe7npRN6GfbGbxMYFck/vQ1r9c1VMA==",
"dev": true,
"engines": {
"node": ">=12.20"
}
},
"node_modules/jest-watch-typeahead/node_modules/slash": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz",
"integrity": "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==",
"dev": true,
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/jest-watch-typeahead/node_modules/string-length": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/string-length/-/string-length-5.0.1.tgz",
"integrity": "sha512-9Ep08KAMUn0OadnVaBuRdE2l615CQ508kr0XMadjClfYpdCyvrbFp6Taebo8yyxokQ4viUd/xPPUA4FGgUa0ow==",
"dev": true,
"dependencies": {
"char-regex": "^2.0.0",
"strip-ansi": "^7.0.1"
},
"engines": {
"node": ">=12.20"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/jest-watch-typeahead/node_modules/strip-ansi": {
"version": "7.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.0.1.tgz",
"integrity": "sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==",
"dev": true,
"dependencies": {
"ansi-regex": "^6.0.1"
},
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/chalk/strip-ansi?sponsor=1"
"jest": "^26.0.0 || ^27.0.0"
}
},
"node_modules/jest-watcher": {
@ -11792,6 +11730,81 @@
"@types/yargs-parser": "*"
}
},
"node_modules/jest-websocket-mock": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/jest-websocket-mock/-/jest-websocket-mock-2.3.0.tgz",
"integrity": "sha512-kXhRRApRdT4hLG/4rhsfcR0Ke0OzqIsDj0P5t0dl5aiAftShSgoRqp/0pyjS5bh+b9GrIzmfkrV2cn9LxxvSvA==",
"dev": true,
"dependencies": {
"jest-diff": "^27.0.2",
"mock-socket": "^9.1.0"
}
},
"node_modules/jest-websocket-mock/node_modules/ansi-styles": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz",
"integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==",
"dev": true,
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
}
},
"node_modules/jest-websocket-mock/node_modules/diff-sequences": {
"version": "27.5.1",
"resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-27.5.1.tgz",
"integrity": "sha512-k1gCAXAsNgLwEL+Y8Wvl+M6oEFj5bgazfZULpS5CneoPPXRaCCW7dm+q21Ky2VEE5X+VeRDBVg1Pcvvsr4TtNQ==",
"dev": true,
"engines": {
"node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0"
}
},
"node_modules/jest-websocket-mock/node_modules/jest-diff": {
"version": "27.5.1",
"resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-27.5.1.tgz",
"integrity": "sha512-m0NvkX55LDt9T4mctTEgnZk3fmEg3NRYutvMPWM/0iPnkFj2wIeF45O1718cMSOFO1vINkqmxqD8vE37uTEbqw==",
"dev": true,
"dependencies": {
"chalk": "^4.0.0",
"diff-sequences": "^27.5.1",
"jest-get-type": "^27.5.1",
"pretty-format": "^27.5.1"
},
"engines": {
"node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0"
}
},
"node_modules/jest-websocket-mock/node_modules/jest-get-type": {
"version": "27.5.1",
"resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-27.5.1.tgz",
"integrity": "sha512-2KY95ksYSaK7DMBWQn6dQz3kqAf3BB64y2udeG+hv4KfSOb9qwcYQstTJc1KCbsix+wLZWZYN8t7nwX3GOBLRw==",
"dev": true,
"engines": {
"node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0"
}
},
"node_modules/jest-websocket-mock/node_modules/pretty-format": {
"version": "27.5.1",
"resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz",
"integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==",
"dev": true,
"dependencies": {
"ansi-regex": "^5.0.1",
"ansi-styles": "^5.0.0",
"react-is": "^17.0.1"
},
"engines": {
"node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0"
}
},
"node_modules/jest-websocket-mock/node_modules/react-is": {
"version": "17.0.2",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz",
"integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==",
"dev": true
},
"node_modules/jest-worker": {
"version": "27.4.5",
"resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.4.5.tgz",
@ -12864,6 +12877,15 @@
"mkdirp": "bin/cmd.js"
}
},
"node_modules/mock-socket": {
"version": "9.1.2",
"resolved": "https://registry.npmjs.org/mock-socket/-/mock-socket-9.1.2.tgz",
"integrity": "sha512-XKZkCnQ9ISOlTnaPg4LYYSMj7+6i78HyadYzLA5JM4465ibLdjappZD9Csnqc3Tfzep/eEK/LCJ29BTaLHoB1A==",
"dev": true,
"engines": {
"node": ">= 8"
}
},
"node_modules/modify-values": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/modify-values/-/modify-values-1.0.1.tgz",
@ -15502,6 +15524,27 @@
}
}
},
"node_modules/react-scripts/node_modules/ansi-regex": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz",
"integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==",
"dev": true,
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/chalk/ansi-regex?sponsor=1"
}
},
"node_modules/react-scripts/node_modules/char-regex": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/char-regex/-/char-regex-2.0.1.tgz",
"integrity": "sha512-oSvEeo6ZUD7NepqAat3RqoucZ5SeqLJgOvVIwkafu6IP3V0pO38s/ypdVUmDDK6qIIHNlYHJAKX9E7R7HoKElw==",
"dev": true,
"engines": {
"node": ">=12.20"
}
},
"node_modules/react-scripts/node_modules/find-up": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
@ -15518,6 +15561,27 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/react-scripts/node_modules/jest-watch-typeahead": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/jest-watch-typeahead/-/jest-watch-typeahead-1.0.0.tgz",
"integrity": "sha512-jxoszalAb394WElmiJTFBMzie/RDCF+W7Q29n5LzOPtcoQoHWfdUtHFkbhgf5NwWe8uMOxvKb/g7ea7CshfkTw==",
"dev": true,
"dependencies": {
"ansi-escapes": "^4.3.1",
"chalk": "^4.0.0",
"jest-regex-util": "^27.0.0",
"jest-watcher": "^27.0.0",
"slash": "^4.0.0",
"string-length": "^5.0.1",
"strip-ansi": "^7.0.1"
},
"engines": {
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
},
"peerDependencies": {
"jest": "^27.0.0"
}
},
"node_modules/react-scripts/node_modules/locate-path": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
@ -15581,6 +15645,18 @@
"url": "https://opencollective.com/webpack"
}
},
"node_modules/react-scripts/node_modules/slash": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz",
"integrity": "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==",
"dev": true,
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/react-scripts/node_modules/source-map": {
"version": "0.7.3",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz",
@ -15590,6 +15666,37 @@
"node": ">= 8"
}
},
"node_modules/react-scripts/node_modules/string-length": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/string-length/-/string-length-5.0.1.tgz",
"integrity": "sha512-9Ep08KAMUn0OadnVaBuRdE2l615CQ508kr0XMadjClfYpdCyvrbFp6Taebo8yyxokQ4viUd/xPPUA4FGgUa0ow==",
"dev": true,
"dependencies": {
"char-regex": "^2.0.0",
"strip-ansi": "^7.0.1"
},
"engines": {
"node": ">=12.20"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/react-scripts/node_modules/strip-ansi": {
"version": "7.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.0.1.tgz",
"integrity": "sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==",
"dev": true,
"dependencies": {
"ansi-regex": "^6.0.1"
},
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/chalk/strip-ansi?sponsor=1"
}
},
"node_modules/react-scripts/node_modules/type-fest": {
"version": "2.8.0",
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.8.0.tgz",
@ -27894,57 +28001,18 @@
}
},
"jest-watch-typeahead": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/jest-watch-typeahead/-/jest-watch-typeahead-1.0.0.tgz",
"integrity": "sha512-jxoszalAb394WElmiJTFBMzie/RDCF+W7Q29n5LzOPtcoQoHWfdUtHFkbhgf5NwWe8uMOxvKb/g7ea7CshfkTw==",
"version": "0.6.5",
"resolved": "https://registry.npmjs.org/jest-watch-typeahead/-/jest-watch-typeahead-0.6.5.tgz",
"integrity": "sha512-GIbV6h37/isatMDtqZlA8Q5vC6T3w+5qdvtF+3LIkPc58zEWzbKmTHvlUIp3wvBm400RzrQWcVPcsAJqKWu7XQ==",
"dev": true,
"requires": {
"ansi-escapes": "^4.3.1",
"chalk": "^4.0.0",
"jest-regex-util": "^27.0.0",
"jest-watcher": "^27.0.0",
"slash": "^4.0.0",
"string-length": "^5.0.1",
"strip-ansi": "^7.0.1"
},
"dependencies": {
"ansi-regex": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz",
"integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==",
"dev": true
},
"char-regex": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/char-regex/-/char-regex-2.0.0.tgz",
"integrity": "sha512-oGu2QekBMXgyQNWPDRQ001bjvDnZe4/zBTz37TMbiKz1NbNiyiH5hRkobe7npRN6GfbGbxMYFck/vQ1r9c1VMA==",
"dev": true
},
"slash": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz",
"integrity": "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==",
"dev": true
},
"string-length": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/string-length/-/string-length-5.0.1.tgz",
"integrity": "sha512-9Ep08KAMUn0OadnVaBuRdE2l615CQ508kr0XMadjClfYpdCyvrbFp6Taebo8yyxokQ4viUd/xPPUA4FGgUa0ow==",
"dev": true,
"requires": {
"char-regex": "^2.0.0",
"strip-ansi": "^7.0.1"
}
},
"strip-ansi": {
"version": "7.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.0.1.tgz",
"integrity": "sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==",
"dev": true,
"requires": {
"ansi-regex": "^6.0.1"
}
}
"slash": "^3.0.0",
"string-length": "^4.0.1",
"strip-ansi": "^6.0.0"
}
},
"jest-watcher": {
@ -27986,6 +28054,65 @@
}
}
},
"jest-websocket-mock": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/jest-websocket-mock/-/jest-websocket-mock-2.3.0.tgz",
"integrity": "sha512-kXhRRApRdT4hLG/4rhsfcR0Ke0OzqIsDj0P5t0dl5aiAftShSgoRqp/0pyjS5bh+b9GrIzmfkrV2cn9LxxvSvA==",
"dev": true,
"requires": {
"jest-diff": "^27.0.2",
"mock-socket": "^9.1.0"
},
"dependencies": {
"ansi-styles": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz",
"integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==",
"dev": true
},
"diff-sequences": {
"version": "27.5.1",
"resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-27.5.1.tgz",
"integrity": "sha512-k1gCAXAsNgLwEL+Y8Wvl+M6oEFj5bgazfZULpS5CneoPPXRaCCW7dm+q21Ky2VEE5X+VeRDBVg1Pcvvsr4TtNQ==",
"dev": true
},
"jest-diff": {
"version": "27.5.1",
"resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-27.5.1.tgz",
"integrity": "sha512-m0NvkX55LDt9T4mctTEgnZk3fmEg3NRYutvMPWM/0iPnkFj2wIeF45O1718cMSOFO1vINkqmxqD8vE37uTEbqw==",
"dev": true,
"requires": {
"chalk": "^4.0.0",
"diff-sequences": "^27.5.1",
"jest-get-type": "^27.5.1",
"pretty-format": "^27.5.1"
}
},
"jest-get-type": {
"version": "27.5.1",
"resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-27.5.1.tgz",
"integrity": "sha512-2KY95ksYSaK7DMBWQn6dQz3kqAf3BB64y2udeG+hv4KfSOb9qwcYQstTJc1KCbsix+wLZWZYN8t7nwX3GOBLRw==",
"dev": true
},
"pretty-format": {
"version": "27.5.1",
"resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz",
"integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==",
"dev": true,
"requires": {
"ansi-regex": "^5.0.1",
"ansi-styles": "^5.0.0",
"react-is": "^17.0.1"
}
},
"react-is": {
"version": "17.0.2",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz",
"integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==",
"dev": true
}
}
},
"jest-worker": {
"version": "27.4.5",
"resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.4.5.tgz",
@ -28790,6 +28917,12 @@
"minimist": "^1.2.5"
}
},
"mock-socket": {
"version": "9.1.2",
"resolved": "https://registry.npmjs.org/mock-socket/-/mock-socket-9.1.2.tgz",
"integrity": "sha512-XKZkCnQ9ISOlTnaPg4LYYSMj7+6i78HyadYzLA5JM4465ibLdjappZD9Csnqc3Tfzep/eEK/LCJ29BTaLHoB1A==",
"dev": true
},
"modify-values": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/modify-values/-/modify-values-1.0.1.tgz",
@ -30590,6 +30723,18 @@
"source-map": "^0.7.3"
}
},
"ansi-regex": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz",
"integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==",
"dev": true
},
"char-regex": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/char-regex/-/char-regex-2.0.1.tgz",
"integrity": "sha512-oSvEeo6ZUD7NepqAat3RqoucZ5SeqLJgOvVIwkafu6IP3V0pO38s/ypdVUmDDK6qIIHNlYHJAKX9E7R7HoKElw==",
"dev": true
},
"find-up": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
@ -30600,6 +30745,21 @@
"path-exists": "^4.0.0"
}
},
"jest-watch-typeahead": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/jest-watch-typeahead/-/jest-watch-typeahead-1.0.0.tgz",
"integrity": "sha512-jxoszalAb394WElmiJTFBMzie/RDCF+W7Q29n5LzOPtcoQoHWfdUtHFkbhgf5NwWe8uMOxvKb/g7ea7CshfkTw==",
"dev": true,
"requires": {
"ansi-escapes": "^4.3.1",
"chalk": "^4.0.0",
"jest-regex-util": "^27.0.0",
"jest-watcher": "^27.0.0",
"slash": "^4.0.0",
"string-length": "^5.0.1",
"strip-ansi": "^7.0.1"
}
},
"locate-path": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
@ -30638,12 +30798,37 @@
"ajv-keywords": "^3.5.2"
}
},
"slash": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz",
"integrity": "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==",
"dev": true
},
"source-map": {
"version": "0.7.3",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz",
"integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==",
"dev": true
},
"string-length": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/string-length/-/string-length-5.0.1.tgz",
"integrity": "sha512-9Ep08KAMUn0OadnVaBuRdE2l615CQ508kr0XMadjClfYpdCyvrbFp6Taebo8yyxokQ4viUd/xPPUA4FGgUa0ow==",
"dev": true,
"requires": {
"char-regex": "^2.0.0",
"strip-ansi": "^7.0.1"
}
},
"strip-ansi": {
"version": "7.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.0.1.tgz",
"integrity": "sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==",
"dev": true,
"requires": {
"ansi-regex": "^6.0.1"
}
},
"type-fest": {
"version": "2.8.0",
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.8.0.tgz",

View file

@ -21,6 +21,8 @@
"conventional-changelog": "^3.1.25",
"http-proxy-middleware": "^2.0.1",
"husky": "^7.0.4",
"jest-watch-typeahead": "^0.6.5",
"jest-websocket-mock": "^2.3.0",
"lint-staged": "^12.3.1",
"moving-letters": "^1.0.1",
"nth-check": ">=2.0.1",
@ -72,5 +74,12 @@
},
"lint-staged": {
"src/**/*.{js,jsx,json,css,md}": "prettier --no-error-on-unmatched-pattern --write"
},
"jest": {
"extraGlobals": [
"Math",
"localStorage"
],
"clearMocks": true
}
}

View file

@ -0,0 +1,17 @@
import { BrowserRouter } from 'react-router-dom'
import { SettingsProvider } from '../context/SettingsContext'
import { WalletProvider } from '../context/WalletContext'
import { WebsocketProvider } from '../context/WebsocketContext'
export const AllTheProviders = ({ children }) => {
return (
<BrowserRouter>
<SettingsProvider>
<WalletProvider>
<WebsocketProvider>{children}</WebsocketProvider>
</WalletProvider>
</SettingsProvider>
</BrowserRouter>
)
}

View file

@ -0,0 +1,95 @@
import React from 'react'
import { render, screen } from '@testing-library/react'
import { act } from 'react-dom/test-utils'
import user from '@testing-library/user-event'
import { AllTheProviders } from '../__util__/AllTheProviders'
import App from './App'
it('should display Onboarding screen initially', () => {
act(() => {
render(<App />, {
wrapper: AllTheProviders,
})
})
// Onboarding screen
expect(screen.getByText('Get started')).toBeInTheDocument()
expect(screen.getByText('Skip intro')).toBeInTheDocument()
// Wallets screen shown after Intro is skipped
expect(screen.queryByText('Your wallets')).not.toBeInTheDocument()
act(() => {
const skipIntro = screen.getByText('Skip intro')
user.click(skipIntro)
})
expect(screen.getByText('Your wallets')).toBeInTheDocument()
})
it('should display Wallets screen directly when Onboarding screen has been shown', () => {
global.__DEV__.addToAppSettings({ showOnboarding: false })
act(() => {
render(<App />, {
wrapper: AllTheProviders,
})
})
// Wallets screen
expect(screen.getByText('Your wallets')).toBeInTheDocument()
expect(screen.getByText('Create new wallet')).toBeInTheDocument()
// footer
expect(screen.getByText('Docs')).toBeInTheDocument()
expect(screen.getByText('Features')).toBeInTheDocument()
expect(screen.getByText('GitHub')).toBeInTheDocument()
expect(screen.getByText('Twitter')).toBeInTheDocument()
})
it('should display a modal with alpha warning information', () => {
global.__DEV__.addToAppSettings({ showOnboarding: false })
act(() => {
render(<App />, {
wrapper: AllTheProviders,
})
})
expect(screen.getByText('Read this before using.')).toBeInTheDocument()
expect(
screen.queryByText(/While JoinMarket is tried and tested, this user interface is not./)
).not.toBeInTheDocument()
act(() => {
const readThis = screen.getByText('Read this before using.')
user.click(readThis)
})
expect(screen.getByText(/While JoinMarket is tried and tested, this user interface is not./)).toBeInTheDocument()
expect(screen.getByText('Fine with me.')).toBeInTheDocument()
})
it('should display a websocket connection indicator', async () => {
global.__DEV__.addToAppSettings({ showOnboarding: false })
act(() => {
render(<App />, {
wrapper: AllTheProviders,
})
})
expect(screen.getByText('•').classList.contains('text-danger')).toBe(true)
expect(screen.getByText('•').classList.contains('text-success')).toBe(false)
expect(screen.getByText('Disconnected')).toBeInTheDocument()
expect(screen.queryByText('Connected')).not.toBeInTheDocument()
await global.__DEV__.JM_WEBSOCKET_SERVER_MOCK.connected
expect(screen.queryByText('Disconnected')).not.toBeInTheDocument()
expect(screen.getByText('Connected')).toBeInTheDocument()
expect(screen.getByText('•').classList.contains('text-success')).toBe(true)
expect(screen.getByText('•').classList.contains('text-danger')).toBe(false)
})

View file

@ -60,7 +60,7 @@ export default function Wallets({ startWallet, stopWallet }) {
{isLoading && (
<div className="d-flex justify-content-center align-items-center">
<rb.Spinner as="span" animation="border" size="sm" role="status" aria-hidden="true" className="me-2" />
Loading wallets
<span>Loading wallets</span>
</div>
)}
{walletList?.map((wallet, index) => (

View file

@ -0,0 +1,95 @@
import React from 'react'
import { render, screen, waitForElementToBeRemoved } from '@testing-library/react'
import { act } from 'react-dom/test-utils'
import * as apiMock from '../libs/JmWalletApi'
import { AllTheProviders } from '../__util__/AllTheProviders'
import Wallets from './Wallets'
jest.mock('../libs/JmWalletApi')
it('should render without errors', () => {
apiMock.getWalletAll.mockResolvedValueOnce(new Promise((r) => setTimeout(r, 1_000)))
act(() => {
render(<Wallets />, {
wrapper: AllTheProviders,
})
})
expect(screen.getByText('Your wallets')).toBeInTheDocument()
expect(screen.getByText('Loading wallets')).toBeInTheDocument()
expect(screen.getByText('Create new wallet')).toBeInTheDocument()
})
it('should display error message when loading wallets fails', async () => {
apiMock.getWalletAll.mockResolvedValueOnce({
ok: false,
})
act(() => {
render(<Wallets />, {
wrapper: AllTheProviders,
})
})
expect(screen.getByText('Loading wallets')).toBeInTheDocument()
expect(screen.getByText('Create new wallet')).toBeInTheDocument()
await waitForElementToBeRemoved(screen.getByText('Loading wallets'))
expect(screen.getByText('Loading wallets failed.')).toBeInTheDocument()
expect(screen.getByText('Create new wallet')).toBeInTheDocument()
})
it('should display big call-to-action button if no wallet has been created yet', async () => {
apiMock.getWalletAll.mockResolvedValueOnce({
ok: true,
json: () => Promise.resolve({ wallets: [] }),
})
act(() => {
render(<Wallets />, {
wrapper: AllTheProviders,
})
})
expect(screen.getByText('Loading wallets')).toBeInTheDocument()
const callToActionButtonBefore = screen.getByText('Create new wallet')
expect(callToActionButtonBefore.classList.contains('btn')).toBe(true)
expect(callToActionButtonBefore.classList.contains('btn-lg')).toBe(false)
await waitForElementToBeRemoved(screen.getByText('Loading wallets'))
expect(screen.getByText('It looks like you do not have a wallet, yet.')).toBeInTheDocument()
const callToActionButtonAfter = screen.getByText('Create new wallet')
expect(callToActionButtonAfter.classList.contains('btn-lg')).toBe(true)
})
it('should display login for available wallets', async () => {
apiMock.getWalletAll.mockResolvedValueOnce({
ok: true,
json: () => Promise.resolve({ wallets: ['wallet0.jmdat', 'wallet1.jmdat'] }),
})
act(() => {
render(<Wallets />, {
wrapper: AllTheProviders,
})
})
expect(screen.getByText('Loading wallets')).toBeInTheDocument()
await waitForElementToBeRemoved(screen.getByText('Loading wallets'))
expect(screen.queryByText('It looks like you do not have a wallet, yet.')).not.toBeInTheDocument()
expect(screen.getByText('wallet0')).toBeInTheDocument()
expect(screen.getByText('wallet1')).toBeInTheDocument()
const callToActionButton = screen.getByText('Create new wallet')
expect(callToActionButton.classList.contains('btn')).toBe(true)
expect(callToActionButton.classList.contains('btn-lg')).toBe(false)
})

View file

@ -33,7 +33,7 @@ const createWebSocket = () => {
console.error('websocket error', error)
}
if (process.env.NODE_ENV !== 'production') {
if (process.env.NODE_ENV === 'development') {
websocket.onopen = () => {
console.debug('websocket connection openend')
}

36
src/setupTests.js Normal file
View file

@ -0,0 +1,36 @@
// react-testing-library renders your components to document.body,
// this adds jest-dom's custom assertions
import '@testing-library/jest-dom'
import { WS as WebSocketServer } from 'jest-websocket-mock'
global.JM = {
SETTINGS_STORE_KEY: 'jm-settings',
THEMES: ['light', 'dark'],
THEME_ROOT_ATTR: 'data-theme',
PUBLIC_PATH: '',
}
global.__DEV__ = {}
global.__DEV__.addToAppSettings = () => {
global.localStorage.setItem(
global.JM.SETTINGS_STORE_KEY,
JSON.stringify(
Object.assign({}, global.localStorage.getItem(global.JM.SETTINGS_STORE_KEY) || {}, {
showOnboarding: false,
})
)
)
}
;(function setupWebsocketServerMock() {
global.__DEV__.JM_WEBSOCKET_SERVER_MOCK = new WebSocketServer('ws://localhost/jmws', { jsonProtocol: true })
afterEach(() => {
// gracefully close all open connections and reset the environment between test runs
WebSocketServer.clean()
})
afterAll(() => {
global.__DEV__.JM_WEBSOCKET_SERVER_MOCK.close()
})
})()