Index: frontend/node_modules/eslint-plugin-jest/CHANGELOG.md
===================================================================
--- frontend/node_modules/eslint-plugin-jest/CHANGELOG.md	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/eslint-plugin-jest/CHANGELOG.md	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,846 @@
+# [25.7.0](https://github.com/jest-community/eslint-plugin-jest/compare/v25.6.0...v25.7.0) (2022-01-15)
+
+
+### Features
+
+* create `prefer-equality-matcher` rule ([#1016](https://github.com/jest-community/eslint-plugin-jest/issues/1016)) ([341353b](https://github.com/jest-community/eslint-plugin-jest/commit/341353bc7d57685cc5e0b31501d6ca336a0dbaf0))
+* **valid-expect:** support `asyncMatchers` option and default to `jest-extended` matchers ([#1018](https://github.com/jest-community/eslint-plugin-jest/issues/1018)) ([c82205a](https://github.com/jest-community/eslint-plugin-jest/commit/c82205a73a4e8de315a2ad4d413b146e27c14a34))
+
+# [25.6.0](https://github.com/jest-community/eslint-plugin-jest/compare/v25.5.0...v25.6.0) (2022-01-15)
+
+
+### Features
+
+* create `prefer-comparison-matcher` rule ([#1015](https://github.com/jest-community/eslint-plugin-jest/issues/1015)) ([eb11876](https://github.com/jest-community/eslint-plugin-jest/commit/eb118761a422b3589311113cd827a6be437f5bb5))
+
+# [25.5.0](https://github.com/jest-community/eslint-plugin-jest/compare/v25.4.0...v25.5.0) (2022-01-15)
+
+
+### Features
+
+* **prefer-expect-assertions:** support requiring only if `expect` is used in a callback ([#1028](https://github.com/jest-community/eslint-plugin-jest/issues/1028)) ([8d5fd33](https://github.com/jest-community/eslint-plugin-jest/commit/8d5fd33eed633f0c0bbdcb9e86bd2d8d7de79c4b))
+
+# [25.4.0](https://github.com/jest-community/eslint-plugin-jest/compare/v25.3.4...v25.4.0) (2022-01-15)
+
+
+### Features
+
+* **prefer-expect-assertions:** support requiring only if `expect` is used in a loop ([#1013](https://github.com/jest-community/eslint-plugin-jest/issues/1013)) ([e6f4f8a](https://github.com/jest-community/eslint-plugin-jest/commit/e6f4f8aaf7664bcf9d9d5549c3c43b1b09f49461))
+
+## [25.3.4](https://github.com/jest-community/eslint-plugin-jest/compare/v25.3.3...v25.3.4) (2022-01-01)
+
+
+### Bug Fixes
+
+* **prefer-lowercase-title:** ignore `it` and `test` separately ([#1011](https://github.com/jest-community/eslint-plugin-jest/issues/1011)) ([f1a7674](https://github.com/jest-community/eslint-plugin-jest/commit/f1a767400967bd923512f79e80f283b3b2afa772))
+
+## [25.3.3](https://github.com/jest-community/eslint-plugin-jest/compare/v25.3.2...v25.3.3) (2021-12-30)
+
+
+### Bug Fixes
+
+* **prefer-to-contain:** support square bracket accessors ([#1009](https://github.com/jest-community/eslint-plugin-jest/issues/1009)) ([73984a7](https://github.com/jest-community/eslint-plugin-jest/commit/73984a79f790986a17116589a587506bcc10efc0))
+* **prefer-to-have-length:** support square bracket accessors ([#1010](https://github.com/jest-community/eslint-plugin-jest/issues/1010)) ([9e70f55](https://github.com/jest-community/eslint-plugin-jest/commit/9e70f550e341432f69a1cd334c19df87513ea906))
+
+## [25.3.2](https://github.com/jest-community/eslint-plugin-jest/compare/v25.3.1...v25.3.2) (2021-12-27)
+
+
+### Bug Fixes
+
+* **no-large-snapshots:** only count size of template string for inline snapshots ([#1005](https://github.com/jest-community/eslint-plugin-jest/issues/1005)) ([5bea38f](https://github.com/jest-community/eslint-plugin-jest/commit/5bea38f9773ab686f08a7cc25247a782d50aa5ed))
+* **prefer-hooks-on-top:** improve message & docs ([#999](https://github.com/jest-community/eslint-plugin-jest/issues/999)) ([f9e7ae2](https://github.com/jest-community/eslint-plugin-jest/commit/f9e7ae29233daad7bfea2230bea7266659299328))
+
+## [25.3.1](https://github.com/jest-community/eslint-plugin-jest/compare/v25.3.0...v25.3.1) (2021-12-27)
+
+
+### Bug Fixes
+
+* **prefer-to-be:** support template literals ([#1006](https://github.com/jest-community/eslint-plugin-jest/issues/1006)) ([aa428e6](https://github.com/jest-community/eslint-plugin-jest/commit/aa428e6598d5f7b259d3cec1bc505989a0fe9885))
+
+# [25.3.0](https://github.com/jest-community/eslint-plugin-jest/compare/v25.2.4...v25.3.0) (2021-11-23)
+
+
+### Features
+
+* **require-hook:** add `allowedFunctionCalls` setting ([#983](https://github.com/jest-community/eslint-plugin-jest/issues/983)) ([9d9336a](https://github.com/jest-community/eslint-plugin-jest/commit/9d9336a7624c53c0bb3ee899b8cc336a0b3349cb))
+
+## [25.2.4](https://github.com/jest-community/eslint-plugin-jest/compare/v25.2.3...v25.2.4) (2021-11-08)
+
+
+### Bug Fixes
+
+* **prefer-to-be:** preserve `resolves` and `rejects` modifiers ([#980](https://github.com/jest-community/eslint-plugin-jest/issues/980)) ([a1296bd](https://github.com/jest-community/eslint-plugin-jest/commit/a1296bdee3a3a8ec5f64f95735ca01b91e8f4118))
+
+## [25.2.3](https://github.com/jest-community/eslint-plugin-jest/compare/v25.2.2...v25.2.3) (2021-11-04)
+
+
+### Bug Fixes
+
+* **no-deprecated-functions:** mark jest as an optional peer dependency ([#970](https://github.com/jest-community/eslint-plugin-jest/issues/970)) ([f468752](https://github.com/jest-community/eslint-plugin-jest/commit/f468752fc0aba89dd9bcce5fe676a04cb2fa6407))
+
+## [25.2.2](https://github.com/jest-community/eslint-plugin-jest/compare/v25.2.1...v25.2.2) (2021-10-17)
+
+
+### Bug Fixes
+
+* **require-hook:** check variables are either `const` or declarations ([#959](https://github.com/jest-community/eslint-plugin-jest/issues/959)) ([ce8cd61](https://github.com/jest-community/eslint-plugin-jest/commit/ce8cd612b7c4c16dc29934118b191d3fbe1ffc07))
+
+## [25.2.1](https://github.com/jest-community/eslint-plugin-jest/compare/v25.2.0...v25.2.1) (2021-10-15)
+
+
+### Bug Fixes
+
+* **expect-expect:** don't error on `it.todo` & `test.todo` calls ([#954](https://github.com/jest-community/eslint-plugin-jest/issues/954)) ([d3cc0db](https://github.com/jest-community/eslint-plugin-jest/commit/d3cc0db129f8d2021cf278f656b73b8c7efb2dc2))
+
+# [25.2.0](https://github.com/jest-community/eslint-plugin-jest/compare/v25.1.0...v25.2.0) (2021-10-14)
+
+
+### Features
+
+* **expect-expect:** support `additionalTestBlockFunctions` option ([#850](https://github.com/jest-community/eslint-plugin-jest/issues/850)) ([3b94c62](https://github.com/jest-community/eslint-plugin-jest/commit/3b94c62b81a50bc8b213c597bb59799cff1ef207))
+
+# [25.1.0](https://github.com/jest-community/eslint-plugin-jest/compare/v25.0.6...v25.1.0) (2021-10-14)
+
+
+### Features
+
+* support `eslint@8` ([#940](https://github.com/jest-community/eslint-plugin-jest/issues/940)) ([5a9e45f](https://github.com/jest-community/eslint-plugin-jest/commit/5a9e45f61888a3c32eac3cbfeaf3acdfaa5d9c83))
+
+## [25.0.6](https://github.com/jest-community/eslint-plugin-jest/compare/v25.0.5...v25.0.6) (2021-10-14)
+
+
+### Bug Fixes
+
+* **valid-expect-in-promise:** allow `expect.resolve` & `expect.reject` ([#948](https://github.com/jest-community/eslint-plugin-jest/issues/948)) ([71b7e17](https://github.com/jest-community/eslint-plugin-jest/commit/71b7e17953b4310a4f2845adc951c68cf062cdc1)), closes [#947](https://github.com/jest-community/eslint-plugin-jest/issues/947)
+* **valid-expect-in-promise:** support `await` in arrays ([#949](https://github.com/jest-community/eslint-plugin-jest/issues/949)) ([a62130c](https://github.com/jest-community/eslint-plugin-jest/commit/a62130c28d01dea065cc6900a062180de2079876))
+
+## [25.0.5](https://github.com/jest-community/eslint-plugin-jest/compare/v25.0.4...v25.0.5) (2021-10-11)
+
+
+### Bug Fixes
+
+* support `@typescript-eslint/eslint-plugin@5` ([#942](https://github.com/jest-community/eslint-plugin-jest/issues/942)) ([9b842a3](https://github.com/jest-community/eslint-plugin-jest/commit/9b842a309fb8e4263896f3e5b5150cf091d48698))
+
+## [25.0.4](https://github.com/jest-community/eslint-plugin-jest/compare/v25.0.3...v25.0.4) (2021-10-11)
+
+
+### Bug Fixes
+
+* update `@typescript-eslint/experimental-utils` to v5 ([#941](https://github.com/jest-community/eslint-plugin-jest/issues/941)) ([afad49a](https://github.com/jest-community/eslint-plugin-jest/commit/afad49a885eeb1ac52f00d8e1666259210a4b675))
+
+## [25.0.3](https://github.com/jest-community/eslint-plugin-jest/compare/v25.0.2...v25.0.3) (2021-10-11)
+
+
+### Bug Fixes
+
+* **valid-expect-in-promise:** support awaited promises in arguments ([#936](https://github.com/jest-community/eslint-plugin-jest/issues/936)) ([bd2c33c](https://github.com/jest-community/eslint-plugin-jest/commit/bd2c33c858573d5414d8bc0d401eb6f27801ad2b))
+
+## [25.0.2](https://github.com/jest-community/eslint-plugin-jest/compare/v25.0.1...v25.0.2) (2021-10-11)
+
+
+### Bug Fixes
+
+* **valid-expect-in-promise:** support out of order awaits ([#939](https://github.com/jest-community/eslint-plugin-jest/issues/939)) ([07d2137](https://github.com/jest-community/eslint-plugin-jest/commit/07d213719de974d6b5a1cab75e836dc39b432f87))
+
+## [25.0.1](https://github.com/jest-community/eslint-plugin-jest/compare/v25.0.0...v25.0.1) (2021-10-10)
+
+
+### Bug Fixes
+
+* specify peer dependency ranges correctly ([cb87458](https://github.com/jest-community/eslint-plugin-jest/commit/cb87458d5f7dc7f669ab0c4067d75fc06ee29553))
+
+# [25.0.0](https://github.com/jest-community/eslint-plugin-jest/compare/v24.7.0...v25.0.0) (2021-10-10)
+
+
+### Bug Fixes
+
+* stop testing ESLint 5 ([#893](https://github.com/jest-community/eslint-plugin-jest/issues/893)) ([47a0138](https://github.com/jest-community/eslint-plugin-jest/commit/47a0138856e6247cde00b17682e49865b8f5a1f6))
+* stop testing on Node 10 and 15 ([#891](https://github.com/jest-community/eslint-plugin-jest/issues/891)) ([bcd8d11](https://github.com/jest-community/eslint-plugin-jest/commit/bcd8d112fcd98a7652c767bd246d05101979239c))
+
+
+### Features
+
+* add `prefer-to-be` to style ruleset ([2a3376f](https://github.com/jest-community/eslint-plugin-jest/commit/2a3376fc9f5fe60d03d9aad0c4e5c7c423487e60))
+* **lowercase-name:** rename to `prefer-lowercase-title` ([b860084](https://github.com/jest-community/eslint-plugin-jest/commit/b8600841e371d5d9f36be4e50e53252fd8f62734))
+* **prefer-to-be-null:** remove rule ([809bcda](https://github.com/jest-community/eslint-plugin-jest/commit/809bcda12c555a24c764d152bcac9814ea55e72f))
+* **prefer-to-be-undefined:** remove rule ([3434d9b](https://github.com/jest-community/eslint-plugin-jest/commit/3434d9bd22b92bace6e0a50e2c72b401ac17704d))
+* remove deprecated rules ([#661](https://github.com/jest-community/eslint-plugin-jest/issues/661)) ([e8f16ec](https://github.com/jest-community/eslint-plugin-jest/commit/e8f16ec0e204a94a0e549cb9b415b3c6c8981aee))
+* **valid-describe:** rename to `valid-describe-callback` ([f3e9e9a](https://github.com/jest-community/eslint-plugin-jest/commit/f3e9e9a64e183a0fb8af3436611a7f70366a528d))
+
+
+### BREAKING CHANGES
+
+* **valid-describe:** renamed `valid-describe` to `valid-describe-callback`
+* **lowercase-name:** renamed `lowercase-name` to `prefer-lowercase-title`
+* **prefer-to-be-undefined:** removed `prefer-to-be-undefined` rule
+* **prefer-to-be-null:** removed `prefer-to-be-null` rule
+* recommend `prefer-to-be` rule
+* Removes rules `no-expect-resolves`, `no-truthy-falsy`, `no-try-expect`, and `prefer-inline-snapshots`
+* Drop support for ESLint 5
+* Drop support for Node 10 and 15
+
+# [25.0.0-next.7](https://github.com/jest-community/eslint-plugin-jest/compare/v25.0.0-next.6...v25.0.0-next.7) (2021-10-10)
+
+
+### Features
+
+* add `prefer-to-be` to style ruleset ([2a3376f](https://github.com/jest-community/eslint-plugin-jest/commit/2a3376fc9f5fe60d03d9aad0c4e5c7c423487e60))
+* **lowercase-name:** rename to `prefer-lowercase-title` ([b860084](https://github.com/jest-community/eslint-plugin-jest/commit/b8600841e371d5d9f36be4e50e53252fd8f62734))
+* **prefer-to-be-null:** remove rule ([809bcda](https://github.com/jest-community/eslint-plugin-jest/commit/809bcda12c555a24c764d152bcac9814ea55e72f))
+* **prefer-to-be-undefined:** remove rule ([3434d9b](https://github.com/jest-community/eslint-plugin-jest/commit/3434d9bd22b92bace6e0a50e2c72b401ac17704d))
+* **valid-describe:** rename to `valid-describe-callback` ([f3e9e9a](https://github.com/jest-community/eslint-plugin-jest/commit/f3e9e9a64e183a0fb8af3436611a7f70366a528d))
+
+
+### BREAKING CHANGES
+
+* **valid-describe:** renamed `valid-describe` to `valid-describe-callback`
+* **lowercase-name:** renamed `lowercase-name` to `prefer-lowercase-title`
+* **prefer-to-be-undefined:** removed `prefer-to-be-undefined` rule
+* **prefer-to-be-null:** removed `prefer-to-be-null` rule
+* recommend `prefer-to-be` rule
+
+# [25.0.0-next.6](https://github.com/jest-community/eslint-plugin-jest/compare/v25.0.0-next.5...v25.0.0-next.6) (2021-10-10)
+
+
+### Bug Fixes
+
+* **lowercase-name:** consider skip and only prefixes for ignores ([#923](https://github.com/jest-community/eslint-plugin-jest/issues/923)) ([8716c24](https://github.com/jest-community/eslint-plugin-jest/commit/8716c24678ea7dc7c9f692b573d1ea19a67efd84))
+* **prefer-to-be:** don't consider RegExp literals as `toBe`-able ([#922](https://github.com/jest-community/eslint-plugin-jest/issues/922)) ([99b6d42](https://github.com/jest-community/eslint-plugin-jest/commit/99b6d429e697d60645b4bc64ee4ae34d7016118c))
+
+
+### Features
+
+* create `require-hook` rule ([#929](https://github.com/jest-community/eslint-plugin-jest/issues/929)) ([6204b31](https://github.com/jest-community/eslint-plugin-jest/commit/6204b311e849b51a0e4705015575139f590ae7a4))
+* deprecate `prefer-to-be-null` rule ([4db9161](https://github.com/jest-community/eslint-plugin-jest/commit/4db91612e988e84ac2facbfe466331b22eeccec9))
+* deprecate `prefer-to-be-undefined` rule ([fa08f09](https://github.com/jest-community/eslint-plugin-jest/commit/fa08f0944e89915fb215bbeff970f12459121cb8))
+* **valid-expect-in-promise:** re-implement rule ([#916](https://github.com/jest-community/eslint-plugin-jest/issues/916)) ([7a49c58](https://github.com/jest-community/eslint-plugin-jest/commit/7a49c5831e3d85a60c11e385203b8f83d98ad580))
+
+# [25.0.0-next.5](https://github.com/jest-community/eslint-plugin-jest/compare/v25.0.0-next.4...v25.0.0-next.5) (2021-09-29)
+
+
+### Bug Fixes
+
+* **no-deprecated-functions:** remove `process.cwd` from resolve paths ([#889](https://github.com/jest-community/eslint-plugin-jest/issues/889)) ([6940488](https://github.com/jest-community/eslint-plugin-jest/commit/6940488d7b5a47577e2823e6d4385b511c5becf4))
+* **no-identical-title:** always consider `.each` titles unique ([#910](https://github.com/jest-community/eslint-plugin-jest/issues/910)) ([a41a40e](https://github.com/jest-community/eslint-plugin-jest/commit/a41a40eafaf1db444ba940cccd2014cb0dc41be9))
+* **valid-expect-in-promise:** support `finally` ([#914](https://github.com/jest-community/eslint-plugin-jest/issues/914)) ([9c89855](https://github.com/jest-community/eslint-plugin-jest/commit/9c89855d23534272230afe6d9e665b8e11ef3075))
+* **valid-expect-in-promise:** support additional test functions ([#915](https://github.com/jest-community/eslint-plugin-jest/issues/915)) ([4798005](https://github.com/jest-community/eslint-plugin-jest/commit/47980058d8d1ff86ee69a376c4edd182d462d594))
+
+
+### Features
+
+* create `prefer-expect-resolves` rule ([#822](https://github.com/jest-community/eslint-plugin-jest/issues/822)) ([2556020](https://github.com/jest-community/eslint-plugin-jest/commit/2556020a777f9daaf1d362a04e3f990415e82db8))
+* create `prefer-to-be` rule ([#864](https://github.com/jest-community/eslint-plugin-jest/issues/864)) ([3a64aea](https://github.com/jest-community/eslint-plugin-jest/commit/3a64aea5bdc55465f1ef34f1426ae626d6c8a230))
+* **require-top-level-describe:** support enforcing max num of describes ([#912](https://github.com/jest-community/eslint-plugin-jest/issues/912)) ([14a2d13](https://github.com/jest-community/eslint-plugin-jest/commit/14a2d1391c9f6f52509316542f45df35853c9b79))
+* **valid-title:** allow custom matcher messages ([#913](https://github.com/jest-community/eslint-plugin-jest/issues/913)) ([ffc9392](https://github.com/jest-community/eslint-plugin-jest/commit/ffc93921348b0d4a394125f665d2bb09148ea37e))
+
+# [25.0.0-next.4](https://github.com/jest-community/eslint-plugin-jest/compare/v25.0.0-next.3...v25.0.0-next.4) (2021-09-20)
+
+
+### Bug Fixes
+
+* mark rules that suggest fixes with `hasSuggestion` for ESLint v8 ([#898](https://github.com/jest-community/eslint-plugin-jest/issues/898)) ([ec0a21b](https://github.com/jest-community/eslint-plugin-jest/commit/ec0a21b0d98d043a9949138e495814e0935d5e31))
+* use correct property `hasSuggestions` rather than `hasSuggestion` ([#899](https://github.com/jest-community/eslint-plugin-jest/issues/899)) ([dfd2368](https://github.com/jest-community/eslint-plugin-jest/commit/dfd2368d1cb1789b6a95a11be24c36868bb8a819))
+
+# [25.0.0-next.3](https://github.com/jest-community/eslint-plugin-jest/compare/v25.0.0-next.2...v25.0.0-next.3) (2021-09-17)
+
+
+### Features
+
+* remove deprecated rules ([#661](https://github.com/jest-community/eslint-plugin-jest/issues/661)) ([e8f16ec](https://github.com/jest-community/eslint-plugin-jest/commit/e8f16ec0e204a94a0e549cb9b415b3c6c8981aee))
+
+
+### BREAKING CHANGES
+
+* Removes rules `no-expect-resolves`, `no-truthy-falsy`, `no-try-expect`, and `prefer-inline-snapshots`
+
+# [25.0.0-next.2](https://github.com/jest-community/eslint-plugin-jest/compare/v25.0.0-next.1...v25.0.0-next.2) (2021-09-13)
+
+
+### Bug Fixes
+
+* stop testing ESLint 5 ([#893](https://github.com/jest-community/eslint-plugin-jest/issues/893)) ([47a0138](https://github.com/jest-community/eslint-plugin-jest/commit/47a0138856e6247cde00b17682e49865b8f5a1f6))
+
+
+### BREAKING CHANGES
+
+* Drop support for ESLint 5
+
+# [25.0.0-next.1](https://github.com/jest-community/eslint-plugin-jest/compare/v24.4.0...v25.0.0-next.1) (2021-09-13)
+
+
+### Bug Fixes
+
+* stop testing on Node 10 and 15 ([#891](https://github.com/jest-community/eslint-plugin-jest/issues/891)) ([bcd8d11](https://github.com/jest-community/eslint-plugin-jest/commit/bcd8d112fcd98a7652c767bd246d05101979239c))
+
+
+### BREAKING CHANGES
+
+* Drop support for Node 10 and 15
+
+# [24.7.0](https://github.com/jest-community/eslint-plugin-jest/compare/v24.6.0...v24.7.0) (2021-10-10)
+
+
+### Features
+
+* create `require-hook` rule ([#929](https://github.com/jest-community/eslint-plugin-jest/issues/929)) ([6204b31](https://github.com/jest-community/eslint-plugin-jest/commit/6204b311e849b51a0e4705015575139f590ae7a4))
+* deprecate `prefer-to-be-null` rule ([4db9161](https://github.com/jest-community/eslint-plugin-jest/commit/4db91612e988e84ac2facbfe466331b22eeccec9))
+* deprecate `prefer-to-be-undefined` rule ([fa08f09](https://github.com/jest-community/eslint-plugin-jest/commit/fa08f0944e89915fb215bbeff970f12459121cb8))
+
+# [24.6.0](https://github.com/jest-community/eslint-plugin-jest/compare/v24.5.2...v24.6.0) (2021-10-09)
+
+
+### Features
+
+* **valid-expect-in-promise:** re-implement rule ([#916](https://github.com/jest-community/eslint-plugin-jest/issues/916)) ([7a49c58](https://github.com/jest-community/eslint-plugin-jest/commit/7a49c5831e3d85a60c11e385203b8f83d98ad580))
+
+## [24.5.2](https://github.com/jest-community/eslint-plugin-jest/compare/v24.5.1...v24.5.2) (2021-10-04)
+
+
+### Bug Fixes
+
+* **lowercase-name:** consider skip and only prefixes for ignores ([#923](https://github.com/jest-community/eslint-plugin-jest/issues/923)) ([8716c24](https://github.com/jest-community/eslint-plugin-jest/commit/8716c24678ea7dc7c9f692b573d1ea19a67efd84))
+
+## [24.5.1](https://github.com/jest-community/eslint-plugin-jest/compare/v24.5.0...v24.5.1) (2021-10-04)
+
+
+### Bug Fixes
+
+* **prefer-to-be:** don't consider RegExp literals as `toBe`-able ([#922](https://github.com/jest-community/eslint-plugin-jest/issues/922)) ([99b6d42](https://github.com/jest-community/eslint-plugin-jest/commit/99b6d429e697d60645b4bc64ee4ae34d7016118c))
+
+# [24.5.0](https://github.com/jest-community/eslint-plugin-jest/compare/v24.4.3...v24.5.0) (2021-09-29)
+
+
+### Bug Fixes
+
+* **no-deprecated-functions:** remove `process.cwd` from resolve paths ([#889](https://github.com/jest-community/eslint-plugin-jest/issues/889)) ([6940488](https://github.com/jest-community/eslint-plugin-jest/commit/6940488d7b5a47577e2823e6d4385b511c5becf4))
+* **no-identical-title:** always consider `.each` titles unique ([#910](https://github.com/jest-community/eslint-plugin-jest/issues/910)) ([a41a40e](https://github.com/jest-community/eslint-plugin-jest/commit/a41a40eafaf1db444ba940cccd2014cb0dc41be9))
+
+
+### Features
+
+* create `prefer-expect-resolves` rule ([#822](https://github.com/jest-community/eslint-plugin-jest/issues/822)) ([2556020](https://github.com/jest-community/eslint-plugin-jest/commit/2556020a777f9daaf1d362a04e3f990415e82db8))
+* create `prefer-to-be` rule ([#864](https://github.com/jest-community/eslint-plugin-jest/issues/864)) ([3a64aea](https://github.com/jest-community/eslint-plugin-jest/commit/3a64aea5bdc55465f1ef34f1426ae626d6c8a230))
+* **require-top-level-describe:** support enforcing max num of describes ([#912](https://github.com/jest-community/eslint-plugin-jest/issues/912)) ([14a2d13](https://github.com/jest-community/eslint-plugin-jest/commit/14a2d1391c9f6f52509316542f45df35853c9b79))
+* **valid-title:** allow custom matcher messages ([#913](https://github.com/jest-community/eslint-plugin-jest/issues/913)) ([ffc9392](https://github.com/jest-community/eslint-plugin-jest/commit/ffc93921348b0d4a394125f665d2bb09148ea37e))
+
+## [24.4.3](https://github.com/jest-community/eslint-plugin-jest/compare/v24.4.2...v24.4.3) (2021-09-28)
+
+
+### Bug Fixes
+
+* **valid-expect-in-promise:** support `finally` ([#914](https://github.com/jest-community/eslint-plugin-jest/issues/914)) ([9c89855](https://github.com/jest-community/eslint-plugin-jest/commit/9c89855d23534272230afe6d9e665b8e11ef3075))
+* **valid-expect-in-promise:** support additional test functions ([#915](https://github.com/jest-community/eslint-plugin-jest/issues/915)) ([4798005](https://github.com/jest-community/eslint-plugin-jest/commit/47980058d8d1ff86ee69a376c4edd182d462d594))
+
+## [24.4.2](https://github.com/jest-community/eslint-plugin-jest/compare/v24.4.1...v24.4.2) (2021-09-17)
+
+
+### Bug Fixes
+
+* use correct property `hasSuggestions` rather than `hasSuggestion` ([#899](https://github.com/jest-community/eslint-plugin-jest/issues/899)) ([dfd2368](https://github.com/jest-community/eslint-plugin-jest/commit/dfd2368d1cb1789b6a95a11be24c36868bb8a819))
+
+## [24.4.1](https://github.com/jest-community/eslint-plugin-jest/compare/v24.4.0...v24.4.1) (2021-09-17)
+
+
+### Bug Fixes
+
+* mark rules that suggest fixes with `hasSuggestion` for ESLint v8 ([#898](https://github.com/jest-community/eslint-plugin-jest/issues/898)) ([ec0a21b](https://github.com/jest-community/eslint-plugin-jest/commit/ec0a21b0d98d043a9949138e495814e0935d5e31))
+
+# [24.4.0](https://github.com/jest-community/eslint-plugin-jest/compare/v24.3.7...v24.4.0) (2021-07-21)
+
+
+### Features
+
+* create `max-nested-describe` rule ([#845](https://github.com/jest-community/eslint-plugin-jest/issues/845)) ([8067405](https://github.com/jest-community/eslint-plugin-jest/commit/8067405deb609cc1800bce596e929c1840d290ab))
+
+## [24.3.7](https://github.com/jest-community/eslint-plugin-jest/compare/v24.3.6...v24.3.7) (2021-07-21)
+
+
+### Bug Fixes
+
+* **valid-describe:** report on concise-body arrow functions ([#863](https://github.com/jest-community/eslint-plugin-jest/issues/863)) ([71c5299](https://github.com/jest-community/eslint-plugin-jest/commit/71c5299b14cac6d85ba8f8bd939461503a60468f))
+
+## [24.3.6](https://github.com/jest-community/eslint-plugin-jest/compare/v24.3.5...v24.3.6) (2021-04-26)
+
+
+### Bug Fixes
+
+* **no-conditional-expect:** check for expects in `catch`s on promises ([#819](https://github.com/jest-community/eslint-plugin-jest/issues/819)) ([1fee973](https://github.com/jest-community/eslint-plugin-jest/commit/1fee973429a74c60b14eead6a335623b4349b5f2))
+* **valid-expect:** support async `expect` in ternary statements ([#833](https://github.com/jest-community/eslint-plugin-jest/issues/833)) ([7b7a396](https://github.com/jest-community/eslint-plugin-jest/commit/7b7a396e12c46d3087b467227887ed64854480c0))
+* improve handling of `.each` calls and with tagged literals ([#814](https://github.com/jest-community/eslint-plugin-jest/issues/814)) ([040c605](https://github.com/jest-community/eslint-plugin-jest/commit/040c605cf7929a00980b3fa58331cd78ac6274f6))
+
+## [24.3.5](https://github.com/jest-community/eslint-plugin-jest/compare/v24.3.4...v24.3.5) (2021-04-10)
+
+
+### Bug Fixes
+
+* **valid-describe:** support using `each` with modifiers ([#820](https://github.com/jest-community/eslint-plugin-jest/issues/820)) ([cbdbcef](https://github.com/jest-community/eslint-plugin-jest/commit/cbdbcef47984eb01509493bd5b2423f518a2663d))
+
+## [24.3.4](https://github.com/jest-community/eslint-plugin-jest/compare/v24.3.3...v24.3.4) (2021-04-05)
+
+
+### Bug Fixes
+
+* support all variations of `describe`, `it`, & `test` ([#792](https://github.com/jest-community/eslint-plugin-jest/issues/792)) ([0968b55](https://github.com/jest-community/eslint-plugin-jest/commit/0968b557dd9cdb5cfcaf8a0d84e8a456825e6b25))
+
+## [24.3.3](https://github.com/jest-community/eslint-plugin-jest/compare/v24.3.2...v24.3.3) (2021-04-02)
+
+
+### Bug Fixes
+
+* **no-duplicate-hooks:** support `describe.each` ([#797](https://github.com/jest-community/eslint-plugin-jest/issues/797)) ([243cb4f](https://github.com/jest-community/eslint-plugin-jest/commit/243cb4f970e40aa195a3bffa0528dbdbfef7c4f5)), closes [#642](https://github.com/jest-community/eslint-plugin-jest/issues/642)
+* **prefer-expect-assertions:** support `.each` ([#798](https://github.com/jest-community/eslint-plugin-jest/issues/798)) ([f758243](https://github.com/jest-community/eslint-plugin-jest/commit/f75824359f2242f53997c59c238d83a59badeea3)), closes [#676](https://github.com/jest-community/eslint-plugin-jest/issues/676)
+
+## [24.3.2](https://github.com/jest-community/eslint-plugin-jest/compare/v24.3.1...v24.3.2) (2021-03-16)
+
+
+### Bug Fixes
+
+* **consistent-test-it:** properly handle `describe.each` ([#796](https://github.com/jest-community/eslint-plugin-jest/issues/796)) ([035bd30](https://github.com/jest-community/eslint-plugin-jest/commit/035bd30af43f1215e65bf1b26c2ef2e6d174d3c8)), closes [#795](https://github.com/jest-community/eslint-plugin-jest/issues/795)
+
+## [24.3.1](https://github.com/jest-community/eslint-plugin-jest/compare/v24.3.0...v24.3.1) (2021-03-13)
+
+
+### Bug Fixes
+
+* **no-focused-tests:** report on `skip` instead of `concurrent` ([#791](https://github.com/jest-community/eslint-plugin-jest/issues/791)) ([2b65b49](https://github.com/jest-community/eslint-plugin-jest/commit/2b65b491cea2c956e4ba314a809915b9ec62933b))
+
+# [24.3.0](https://github.com/jest-community/eslint-plugin-jest/compare/v24.2.1...v24.3.0) (2021-03-13)
+
+
+### Features
+
+* **unbound-method:** create rule ([#765](https://github.com/jest-community/eslint-plugin-jest/issues/765)) ([b1f4ed3](https://github.com/jest-community/eslint-plugin-jest/commit/b1f4ed3f6bb0264fdefb5138ba913fa2bacc725c))
+
+## [24.2.1](https://github.com/jest-community/eslint-plugin-jest/compare/v24.2.0...v24.2.1) (2021-03-10)
+
+
+### Bug Fixes
+
+* **no-identical-titles:** support nested describes ([#790](https://github.com/jest-community/eslint-plugin-jest/issues/790)) ([ce26621](https://github.com/jest-community/eslint-plugin-jest/commit/ce26621a06169fb6728d2d015645d31401de523f))
+
+# [24.2.0](https://github.com/jest-community/eslint-plugin-jest/compare/v24.1.10...v24.2.0) (2021-03-09)
+
+
+### Features
+
+* **no-focused-tests:** make fixable ([#787](https://github.com/jest-community/eslint-plugin-jest/issues/787)) ([040871a](https://github.com/jest-community/eslint-plugin-jest/commit/040871a866b7803e5c48b40715d48437d3906b0f))
+
+## [24.1.10](https://github.com/jest-community/eslint-plugin-jest/compare/v24.1.9...v24.1.10) (2021-03-09)
+
+
+### Bug Fixes
+
+* **no-identical-titles:** ignore .each template cases ([#788](https://github.com/jest-community/eslint-plugin-jest/issues/788)) ([d27a6e6](https://github.com/jest-community/eslint-plugin-jest/commit/d27a6e6e013c518a47b9f219edeb5e63d7a974f9))
+
+## [24.1.9](https://github.com/jest-community/eslint-plugin-jest/compare/v24.1.8...v24.1.9) (2021-03-08)
+
+
+### Bug Fixes
+
+* **valid-describe:** false positive with template describe.each ([#785](https://github.com/jest-community/eslint-plugin-jest/issues/785)) ([aa946a6](https://github.com/jest-community/eslint-plugin-jest/commit/aa946a6f7ae7106b78996587760d92ace33227ad))
+
+## [24.1.8](https://github.com/jest-community/eslint-plugin-jest/compare/v24.1.7...v24.1.8) (2021-03-07)
+
+
+### Bug Fixes
+
+* **consistent-test-it:** support `it.each` in `describe.each` ([#782](https://github.com/jest-community/eslint-plugin-jest/issues/782)) ([0014da0](https://github.com/jest-community/eslint-plugin-jest/commit/0014da0e2aeb13199a9da7f969e9eb376e026c8b))
+
+## [24.1.7](https://github.com/jest-community/eslint-plugin-jest/compare/v24.1.6...v24.1.7) (2021-03-06)
+
+
+### Bug Fixes
+
+* **no-disabled-tests:** adjust selector to match only test functions ([#777](https://github.com/jest-community/eslint-plugin-jest/issues/777)) ([c916902](https://github.com/jest-community/eslint-plugin-jest/commit/c9169022c7e4b9c7bd5f09060152f7136ee18521))
+* **no-disabled-tests:** support `describe.skip.each` & `xdescribe.each` ([#778](https://github.com/jest-community/eslint-plugin-jest/issues/778)) ([6a32e87](https://github.com/jest-community/eslint-plugin-jest/commit/6a32e870c016474687e238944933a96bfe1ca01b))
+
+## [24.1.6](https://github.com/jest-community/eslint-plugin-jest/compare/v24.1.5...v24.1.6) (2021-03-06)
+
+
+### Bug Fixes
+
+* proper support for it.each  ([#722](https://github.com/jest-community/eslint-plugin-jest/issues/722)) ([e1dc42d](https://github.com/jest-community/eslint-plugin-jest/commit/e1dc42d9f1ca59d59aca9be0a1473a1b1415e528))
+
+## [24.1.5](https://github.com/jest-community/eslint-plugin-jest/compare/v24.1.4...v24.1.5) (2021-02-17)
+
+
+### Bug Fixes
+
+* **require-top-level-describe:** import function that actually exists ([#763](https://github.com/jest-community/eslint-plugin-jest/issues/763)) ([d10dc07](https://github.com/jest-community/eslint-plugin-jest/commit/d10dc07d9dc933fe9584b3e13704001527896859))
+
+## [24.1.4](https://github.com/jest-community/eslint-plugin-jest/compare/v24.1.3...v24.1.4) (2021-02-16)
+
+
+### Bug Fixes
+
+* **lowercase-name:** support `.each` methods ([#746](https://github.com/jest-community/eslint-plugin-jest/issues/746)) ([3d847b2](https://github.com/jest-community/eslint-plugin-jest/commit/3d847b2164425a2afb754569dbfff52411c95610))
+* **require-top-level-describe:** handle `describe.each` properly ([#745](https://github.com/jest-community/eslint-plugin-jest/issues/745)) ([677be45](https://github.com/jest-community/eslint-plugin-jest/commit/677be4558a3954e364b0c4150678a4d3fd832337))
+
+## [24.1.3](https://github.com/jest-community/eslint-plugin-jest/compare/v24.1.2...v24.1.3) (2020-11-12)
+
+
+### Bug Fixes
+
+* revert change causing regressions for test.each ([#713](https://github.com/jest-community/eslint-plugin-jest/issues/713)) ([7c8d75a](https://github.com/jest-community/eslint-plugin-jest/commit/7c8d75a4fcbd2c6ce005cf4f57d676c7c44ce0b2)), closes [#710](https://github.com/jest-community/eslint-plugin-jest/issues/710) [#711](https://github.com/jest-community/eslint-plugin-jest/issues/711)
+
+## [24.1.2](https://github.com/jest-community/eslint-plugin-jest/compare/v24.1.1...v24.1.2) (2020-11-12)
+
+
+### Bug Fixes
+
+* **no-done-callback:** fix regression with it.each ([#708](https://github.com/jest-community/eslint-plugin-jest/issues/708)) ([2f032f8](https://github.com/jest-community/eslint-plugin-jest/commit/2f032f8d890e3717359d099b1e93e0cc6b52996a))
+
+## [24.1.1](https://github.com/jest-community/eslint-plugin-jest/compare/v24.1.0...v24.1.1) (2020-11-12)
+
+
+### Bug Fixes
+
+* improve support for it.each involving tagged template literals ([#701](https://github.com/jest-community/eslint-plugin-jest/issues/701)) ([2341814](https://github.com/jest-community/eslint-plugin-jest/commit/2341814060b38c55728c0b456d7b432f1e0e1a11))
+
+# [24.1.0](https://github.com/jest-community/eslint-plugin-jest/compare/v24.0.2...v24.1.0) (2020-10-05)
+
+
+### Features
+
+* **prefer-expect-assertions:** add `onlyFunctionsWithAsyncKeyword` option ([#677](https://github.com/jest-community/eslint-plugin-jest/issues/677)) ([d0cea37](https://github.com/jest-community/eslint-plugin-jest/commit/d0cea37ae0a8ab07b8082cedbaaf161bcc94c405))
+
+## [24.0.2](https://github.com/jest-community/eslint-plugin-jest/compare/v24.0.1...v24.0.2) (2020-09-20)
+
+
+### Bug Fixes
+
+* **no-if:** check both types of function expression ([#672](https://github.com/jest-community/eslint-plugin-jest/issues/672)) ([d462d50](https://github.com/jest-community/eslint-plugin-jest/commit/d462d50aed84ad4dc536a1f47bb7af6abd3dbe92)), closes [#670](https://github.com/jest-community/eslint-plugin-jest/issues/670)
+
+## [24.0.1](https://github.com/jest-community/eslint-plugin-jest/compare/v24.0.0...v24.0.1) (2020-09-12)
+
+
+### Bug Fixes
+
+* don't include deprecated rules in `all` config ([#664](https://github.com/jest-community/eslint-plugin-jest/issues/664)) ([f636021](https://github.com/jest-community/eslint-plugin-jest/commit/f636021c16215a713845c699858a2978211df49d)), closes [#663](https://github.com/jest-community/eslint-plugin-jest/issues/663)
+
+# [24.0.0](https://github.com/jest-community/eslint-plugin-jest/compare/v23.20.0...v24.0.0) (2020-09-04)
+
+
+### Bug Fixes
+
+* **no-large-snapshots:** run on all files regardless of type ([#637](https://github.com/jest-community/eslint-plugin-jest/issues/637)) ([22113db](https://github.com/jest-community/eslint-plugin-jest/commit/22113db4cdc2dab42a8e7fdb236d23e7e089741d)), closes [#370](https://github.com/jest-community/eslint-plugin-jest/issues/370)
+* remove Jasmine globals ([#596](https://github.com/jest-community/eslint-plugin-jest/issues/596)) ([a0e2bc5](https://github.com/jest-community/eslint-plugin-jest/commit/a0e2bc526c5c22bcf4d60160242b55d03edb571d))
+* update to typescript-eslint@4 ([1755965](https://github.com/jest-community/eslint-plugin-jest/commit/175596582b3643f36363ff444f987fac08ee0f61)), closes [#590](https://github.com/jest-community/eslint-plugin-jest/issues/590)
+
+
+### Code Refactoring
+
+* **no-test-callback:** rename rule to `no-done-callback` ([#653](https://github.com/jest-community/eslint-plugin-jest/issues/653)) ([e15a8d1](https://github.com/jest-community/eslint-plugin-jest/commit/e15a8d19234b267784f87fc7acd318dc4cfcdeae))
+
+
+### Features
+
+* **no-done-callback:** support hooks ([#656](https://github.com/jest-community/eslint-plugin-jest/issues/656)) ([3e6cb44](https://github.com/jest-community/eslint-plugin-jest/commit/3e6cb442a20b9aea710d30f81bf2eb192d193823)), closes [#649](https://github.com/jest-community/eslint-plugin-jest/issues/649) [#651](https://github.com/jest-community/eslint-plugin-jest/issues/651)
+* add `no-conditional-expect` to the recommended ruleset ([40cd89d](https://github.com/jest-community/eslint-plugin-jest/commit/40cd89ddf1d6ebbde8ad455f333dda7b61878ffe))
+* add `no-deprecated-functions` to the recommended ruleset ([5b2af00](https://github.com/jest-community/eslint-plugin-jest/commit/5b2af001b50059e4e7b6ababe0355d664e039046))
+* add `no-interpolation-in-snapshots` to the recommended ruleset ([3705dff](https://github.com/jest-community/eslint-plugin-jest/commit/3705dff9d4f77d21013e263478d8a374d9325acb))
+* add `valid-title` to recommended ruleset ([41f7873](https://github.com/jest-community/eslint-plugin-jest/commit/41f7873f734e0122264ace42f6d99733e7e25089))
+* drop support for node 8 ([#570](https://github.com/jest-community/eslint-plugin-jest/issues/570)) ([6788e72](https://github.com/jest-community/eslint-plugin-jest/commit/6788e72d842751400a970e72b115360ad0b12d2e))
+* set `no-jasmine-globals` to `error` in recommended ruleset ([7080952](https://github.com/jest-community/eslint-plugin-jest/commit/7080952a6baaae7a02c78f60016ee21693121416))
+* **no-large-snapshots:** remove `whitelistedSnapshots` option ([8c1c0c9](https://github.com/jest-community/eslint-plugin-jest/commit/8c1c0c9a3e858757b38225ccb4a624e0621b5ca2))
+
+
+### BREAKING CHANGES
+
+* **no-done-callback:** `no-done-callback` will now report hooks using callbacks as well, not just tests
+* **no-test-callback:** rename `no-test-callback` to `no-done-callback`
+* recommend `no-conditional-expect` rule
+* recommend `no-interpolation-in-snapshots` rule
+* recommend `no-deprecated-functions` rule
+* recommend `valid-title` rule
+* recommend erroring for `no-jasmine-globals` rule
+* **no-large-snapshots:** `no-large-snapshots` runs on all files regardless of type 
+* Jasmine globals are no marked as such
+* Node 10+ required
+
+# [23.20.0](https://github.com/jest-community/eslint-plugin-jest/compare/v23.19.0...v23.20.0) (2020-07-30)
+
+
+### Features
+
+* **no-large-snapshots:** deprecate `whitelistedSnapshots` for new name ([#632](https://github.com/jest-community/eslint-plugin-jest/issues/632)) ([706f5c2](https://github.com/jest-community/eslint-plugin-jest/commit/706f5c2bc54797f0f32178fab1d194d9a4309f70))
+
+# [23.19.0](https://github.com/jest-community/eslint-plugin-jest/compare/v23.18.2...v23.19.0) (2020-07-27)
+
+
+### Features
+
+* create `no-interpolation-in-snapshots` rule ([#553](https://github.com/jest-community/eslint-plugin-jest/issues/553)) ([8d2c17c](https://github.com/jest-community/eslint-plugin-jest/commit/8d2c17c449841465630bea5269de677455ef9a8d))
+
+## [23.18.2](https://github.com/jest-community/eslint-plugin-jest/compare/v23.18.1...v23.18.2) (2020-07-26)
+
+
+### Bug Fixes
+
+* **no-if:** report conditionals in call expressions ([4cfcf08](https://github.com/jest-community/eslint-plugin-jest/commit/4cfcf080893fbe89689bd4b283bb2f3ad09b19ff)), closes [#557](https://github.com/jest-community/eslint-plugin-jest/issues/557)
+
+## [23.18.1](https://github.com/jest-community/eslint-plugin-jest/compare/v23.18.0...v23.18.1) (2020-07-26)
+
+
+### Bug Fixes
+
+* **no-large-snapshots:** actually compare allowed name strings to name ([#625](https://github.com/jest-community/eslint-plugin-jest/issues/625)) ([622a08c](https://github.com/jest-community/eslint-plugin-jest/commit/622a08c86a37aa9490af20b488bd23246b8be752))
+
+# [23.18.0](https://github.com/jest-community/eslint-plugin-jest/compare/v23.17.1...v23.18.0) (2020-07-05)
+
+
+### Features
+
+* **valid-title:** support `mustMatch` & `mustNotMatch` options ([#608](https://github.com/jest-community/eslint-plugin-jest/issues/608)) ([4c7207e](https://github.com/jest-community/eslint-plugin-jest/commit/4c7207ebbb274f7b584225ad65ffb96a4328240e)), closes [#233](https://github.com/jest-community/eslint-plugin-jest/issues/233)
+
+## [23.17.1](https://github.com/jest-community/eslint-plugin-jest/compare/v23.17.0...v23.17.1) (2020-06-23)
+
+
+### Bug Fixes
+
+* **lowercase-name:** ignore all top level describes when option is true ([#614](https://github.com/jest-community/eslint-plugin-jest/issues/614)) ([624018a](https://github.com/jest-community/eslint-plugin-jest/commit/624018aa181e7c0ce87457a4f9c212c7891987a8)), closes [#613](https://github.com/jest-community/eslint-plugin-jest/issues/613)
+
+# [23.17.0](https://github.com/jest-community/eslint-plugin-jest/compare/v23.16.0...v23.17.0) (2020-06-23)
+
+
+### Features
+
+* **lowercase-name:** support `ignoreTopLevelDescribe` option ([#611](https://github.com/jest-community/eslint-plugin-jest/issues/611)) ([36fdcc5](https://github.com/jest-community/eslint-plugin-jest/commit/36fdcc553ca40bc2ca2e9ca7e04f8e9e4a315274)), closes [#247](https://github.com/jest-community/eslint-plugin-jest/issues/247)
+
+# [23.16.0](https://github.com/jest-community/eslint-plugin-jest/compare/v23.15.0...v23.16.0) (2020-06-21)
+
+
+### Features
+
+* create `no-conditional-expect` rule ([aba53e4](https://github.com/jest-community/eslint-plugin-jest/commit/aba53e4061f3b636ab0c0270e183c355c6f301e0))
+* deprecate `no-try-expect` in favor of `no-conditional-expect` ([6d07cad](https://github.com/jest-community/eslint-plugin-jest/commit/6d07cadd5f78ed7a64a86792931d49d3cd943d69))
+
+# [23.15.0](https://github.com/jest-community/eslint-plugin-jest/compare/v23.14.0...v23.15.0) (2020-06-21)
+
+
+### Features
+
+* **no-standalone-expect:** support `additionalTestBlockFunctions` ([#585](https://github.com/jest-community/eslint-plugin-jest/issues/585)) ([ed220b2](https://github.com/jest-community/eslint-plugin-jest/commit/ed220b2c515f2e97ce639dd1474c18a7f594c06c))
+
+# [23.14.0](https://github.com/jest-community/eslint-plugin-jest/compare/v23.13.2...v23.14.0) (2020-06-20)
+
+
+### Bug Fixes
+
+* **no-test-callback:** check argument is an identifier ([f70612d](https://github.com/jest-community/eslint-plugin-jest/commit/f70612d8b414575725a5831ed9dfad1eaf1e6548))
+* **no-test-callback:** provide suggestion instead of autofix ([782d8fa](https://github.com/jest-community/eslint-plugin-jest/commit/782d8fa00149143f453e7cb066f90c017e2d3f61))
+* **prefer-strict-equal:** provide suggestion instead of autofix ([2eaed2b](https://github.com/jest-community/eslint-plugin-jest/commit/2eaed2bf30c72b03ee205910887f8aab304047a5))
+
+
+### Features
+
+* **prefer-expect-assertions:** provide suggestions ([bad88a0](https://github.com/jest-community/eslint-plugin-jest/commit/bad88a006135258e8da18902a84bdb52a9bb9fa7))
+
+## [23.13.2](https://github.com/jest-community/eslint-plugin-jest/compare/v23.13.1...v23.13.2) (2020-05-26)
+
+
+### Bug Fixes
+
+* add `fail` to globals ([#595](https://github.com/jest-community/eslint-plugin-jest/issues/595)) ([aadc5ec](https://github.com/jest-community/eslint-plugin-jest/commit/aadc5ec5610ec024eac4b0aa6077cc012a0ba98e))
+
+## [23.13.1](https://github.com/jest-community/eslint-plugin-jest/compare/v23.13.0...v23.13.1) (2020-05-17)
+
+
+### Bug Fixes
+
+* **no-if:** use correct syntax for placeholder substitution in message ([6d1eda8](https://github.com/jest-community/eslint-plugin-jest/commit/6d1eda89ac48c93c2675dcf24a92574a20b2edb9))
+
+# [23.13.0](https://github.com/jest-community/eslint-plugin-jest/compare/v23.12.0...v23.13.0) (2020-05-16)
+
+
+### Features
+
+* **valid-expect:** support `minArgs` & `maxArgs` options ([#584](https://github.com/jest-community/eslint-plugin-jest/issues/584)) ([9e0e2fa](https://github.com/jest-community/eslint-plugin-jest/commit/9e0e2fa966b43c1099d11b2424acb1590c241c03))
+
+# [23.12.0](https://github.com/jest-community/eslint-plugin-jest/compare/v23.11.0...v23.12.0) (2020-05-16)
+
+
+### Features
+
+* deprecate `no-expect-resolves` rule ([b6a22e5](https://github.com/jest-community/eslint-plugin-jest/commit/b6a22e5aa98abcb57aac217c6d4583d0a3388e7b))
+* deprecate `no-truthy-falsy` rule ([a67d92d](https://github.com/jest-community/eslint-plugin-jest/commit/a67d92d2834568122f24bf3d8455999166da95ea))
+* deprecate `prefer-inline-snapshots` rule ([1360e9b](https://github.com/jest-community/eslint-plugin-jest/commit/1360e9b0e840f4f778a9d251371c943919f84600))
+
+# [23.11.0](https://github.com/jest-community/eslint-plugin-jest/compare/v23.10.0...v23.11.0) (2020-05-12)
+
+
+### Features
+
+* create `no-restricted-matchers` rule ([#575](https://github.com/jest-community/eslint-plugin-jest/issues/575)) ([ac926e7](https://github.com/jest-community/eslint-plugin-jest/commit/ac926e779958240506ee506047c9a5364bb70aea))
+
+# [23.10.0](https://github.com/jest-community/eslint-plugin-jest/compare/v23.9.0...v23.10.0) (2020-05-09)
+
+
+### Features
+
+* **no-deprecated-functions:** support jest `version` setting ([#564](https://github.com/jest-community/eslint-plugin-jest/issues/564)) ([05f20b8](https://github.com/jest-community/eslint-plugin-jest/commit/05f20b80ecd42b8d1f1f18ca19d4bc9cba45e22e))
+
+# [23.9.0](https://github.com/jest-community/eslint-plugin-jest/compare/v23.8.2...v23.9.0) (2020-05-04)
+
+
+### Features
+
+* create `no-deprecated-functions` ([#560](https://github.com/jest-community/eslint-plugin-jest/issues/560)) ([55d0504](https://github.com/jest-community/eslint-plugin-jest/commit/55d0504cadc945b770d7c3b6d3cab425c9b76d0f))
+
+## [23.8.2](https://github.com/jest-community/eslint-plugin-jest/compare/v23.8.1...v23.8.2) (2020-03-06)
+
+### Bug Fixes
+
+- **prefer-to-contain:** check that expect argument is defined before use
+  ([#542](https://github.com/jest-community/eslint-plugin-jest/issues/542))
+  ([56f909b](https://github.com/jest-community/eslint-plugin-jest/commit/56f909b326034236953d04b18dab3f64b16a2973))
+
+## [23.8.1](https://github.com/jest-community/eslint-plugin-jest/compare/v23.8.0...v23.8.1) (2020-02-29)
+
+### Bug Fixes
+
+- remove tests from published package
+  ([#541](https://github.com/jest-community/eslint-plugin-jest/issues/541))
+  ([099a150](https://github.com/jest-community/eslint-plugin-jest/commit/099a150b87fa693ccf1c512ee501aed1457ba656))
+
+# [23.8.0](https://github.com/jest-community/eslint-plugin-jest/compare/v23.7.0...v23.8.0) (2020-02-23)
+
+### Bug Fixes
+
+- **valid-title:** ensure argument node is defined before accessing props
+  ([#538](https://github.com/jest-community/eslint-plugin-jest/issues/538))
+  ([7730f75](https://github.com/jest-community/eslint-plugin-jest/commit/7730f757561100559509b756fd362ca33b9ab1d4))
+
+### Features
+
+- **no-large-snapshots:** add setting to define maxSize by snapshot type
+  ([#524](https://github.com/jest-community/eslint-plugin-jest/issues/524))
+  ([0d77300](https://github.com/jest-community/eslint-plugin-jest/commit/0d77300e61adc7a5aa84f34ff4ccc164075d5f41))
+
+# [23.7.0](https://github.com/jest-community/eslint-plugin-jest/compare/v23.6.0...v23.7.0) (2020-02-07)
+
+### Bug Fixes
+
+- **expect-expect:** use `u` flag in regex
+  ([#532](https://github.com/jest-community/eslint-plugin-jest/issues/532))
+  ([c12b725](https://github.com/jest-community/eslint-plugin-jest/commit/c12b7251ef1506073d268973b93c7fc9fbcf50af))
+
+### Features
+
+- **valid-title:** support `disallowedWords` option
+  ([#522](https://github.com/jest-community/eslint-plugin-jest/issues/522))
+  ([38bbe93](https://github.com/jest-community/eslint-plugin-jest/commit/38bbe93794ed456c6e9e5d7be848b2aeb55ce0ba))
+
+# [23.6.0](https://github.com/jest-community/eslint-plugin-jest/compare/v23.5.0...v23.6.0) (2020-01-12)
+
+### Features
+
+- **no-if:** support `switch` statements
+  ([#515](https://github.com/jest-community/eslint-plugin-jest/issues/515))
+  ([be4e49d](https://github.com/jest-community/eslint-plugin-jest/commit/be4e49dcecd64711e743f5e09d1ff24e4c6e1648))
+
+# [23.5.0](https://github.com/jest-community/eslint-plugin-jest/compare/v23.4.0...v23.5.0) (2020-01-12)
+
+### Features
+
+- **expect-expect:** support glob patterns for assertFunctionNames
+  ([#509](https://github.com/jest-community/eslint-plugin-jest/issues/509))
+  ([295ca9a](https://github.com/jest-community/eslint-plugin-jest/commit/295ca9a6969c77fadaa1a42d76e89cae992520a6))
+- **valid-expect:** refactor `valid-expect` linting messages
+  ([#501](https://github.com/jest-community/eslint-plugin-jest/issues/501))
+  ([7338362](https://github.com/jest-community/eslint-plugin-jest/commit/7338362420eb4970f99be2016bb4ded5732797e3))
+
+# [23.4.0](https://github.com/jest-community/eslint-plugin-jest/compare/v23.3.0...v23.4.0) (2020-01-10)
+
+### Features
+
+- **expect-expect:** support chained function names
+  ([#471](https://github.com/jest-community/eslint-plugin-jest/issues/471))
+  ([#508](https://github.com/jest-community/eslint-plugin-jest/issues/508))
+  ([beb1aec](https://github.com/jest-community/eslint-plugin-jest/commit/beb1aececee80589c182e95bc64ef01d97eb5e78))
+- **rules:** add support for function declaration as test case
+  ([#504](https://github.com/jest-community/eslint-plugin-jest/issues/504))
+  ([ac7fa48](https://github.com/jest-community/eslint-plugin-jest/commit/ac7fa487d05705bee1b2d5264d5096f0232ae1e1))
+
+# [23.3.0](https://github.com/jest-community/eslint-plugin-jest/compare/v23.2.0...v23.3.0) (2020-01-04)
+
+### Features
+
+- **rules:** add .concurrent support
+  ([#498](https://github.com/jest-community/eslint-plugin-jest/issues/498))
+  ([#502](https://github.com/jest-community/eslint-plugin-jest/issues/502))
+  ([dcba5f1](https://github.com/jest-community/eslint-plugin-jest/commit/dcba5f1f1c6429a8bce2ff9aae71c02a6ffa1c2b))
+
+# [23.2.0](https://github.com/jest-community/eslint-plugin-jest/compare/v23.1.1...v23.2.0) (2019-12-28)
+
+### Features
+
+- **valid-expect:** warn on `await expect()` with no assertions
+  ([#496](https://github.com/jest-community/eslint-plugin-jest/issues/496))
+  ([19798dd](https://github.com/jest-community/eslint-plugin-jest/commit/19798dd540c8a0f5ac7883f67a28ee67d9e5fc7a))
+
+## [23.1.1](https://github.com/jest-community/eslint-plugin-jest/compare/v23.1.0...v23.1.1) (2019-11-30)
+
+### Bug Fixes
+
+- **no-focused-tests:** detect table format uage of `.only.each`
+  ([#489](https://github.com/jest-community/eslint-plugin-jest/issues/489))
+  ([d03bcf4](https://github.com/jest-community/eslint-plugin-jest/commit/d03bcf49e9e4f068bead25a4bc4c962762d56c02))
+
+# [23.1.0](https://github.com/jest-community/eslint-plugin-jest/compare/v23.0.5...v23.1.0) (2019-11-29)
+
+### Features
+
+- **no-focused-tests:** check each with table format
+  ([#430](https://github.com/jest-community/eslint-plugin-jest/issues/430))
+  ([154c0b8](https://github.com/jest-community/eslint-plugin-jest/commit/154c0b8e5310f0c1bf715a8c60de5d84faa1bc48))
+
+## [23.0.5](https://github.com/jest-community/eslint-plugin-jest/compare/v23.0.4...v23.0.5) (2019-11-27)
+
+### Bug Fixes
+
+- typo in the `require-to-throw-message` docs
+  ([#487](https://github.com/jest-community/eslint-plugin-jest/issues/487))
+  ([3526213](https://github.com/jest-community/eslint-plugin-jest/commit/35262135e3bb407b9c40991d2651ca4b201eebff))
+
+## [23.0.4](https://github.com/jest-community/eslint-plugin-jest/compare/v23.0.3...v23.0.4) (2019-11-14)
+
+### Bug Fixes
+
+- get correct ruleName without specifying file extension
+  ([#473](https://github.com/jest-community/eslint-plugin-jest/issues/473))
+  ([f09203e](https://github.com/jest-community/eslint-plugin-jest/commit/f09203ed05a69c83baadf6149ae17513c85b170f))
+
+## [23.0.3](https://github.com/jest-community/eslint-plugin-jest/compare/v23.0.2...v23.0.3) (2019-11-08)
+
+### Bug Fixes
+
+- **no-test-callback:** don't provide fix for `async` functions
+  ([#469](https://github.com/jest-community/eslint-plugin-jest/issues/469))
+  ([09111e0](https://github.com/jest-community/eslint-plugin-jest/commit/09111e0c951aaa930c9a2c8e0ca84251b3196e94)),
+  closes [#466](https://github.com/jest-community/eslint-plugin-jest/issues/466)
+
+## [23.0.2](https://github.com/jest-community/eslint-plugin-jest/compare/v23.0.1...v23.0.2) (2019-10-28)
+
+### Bug Fixes
+
+- **prefer-todo:** ensure argument exists before trying to access it
+  ([#462](https://github.com/jest-community/eslint-plugin-jest/issues/462))
+  ([a87c8c2](https://github.com/jest-community/eslint-plugin-jest/commit/a87c8c29e1faf9d5364c9074d988aa95ef6cc987))
+
+## [23.0.1](https://github.com/jest-community/eslint-plugin-jest/compare/v23.0.0...v23.0.1) (2019-10-28)
+
+### Bug Fixes
+
+- **valid-title:** ignore string addition
+  ([#461](https://github.com/jest-community/eslint-plugin-jest/issues/461))
+  ([b7c1be2](https://github.com/jest-community/eslint-plugin-jest/commit/b7c1be2f279b87366332fb2d3a3e49a71aa75711))
+
+# [22.2.0](https://github.com/jest-community/eslint-plugin-jest/compare/v22.1.3...v22.2.0) (2019-01-29)
+
+### Features
+
+- **rules:** add prefer-todo rule
+  ([#218](https://github.com/jest-community/eslint-plugin-jest/issues/218))
+  ([0933d82](https://github.com/jest-community/eslint-plugin-jest/commit/0933d82)),
+  closes [#217](https://github.com/jest-community/eslint-plugin-jest/issues/217)
Index: frontend/node_modules/eslint-plugin-jest/LICENSE
===================================================================
--- frontend/node_modules/eslint-plugin-jest/LICENSE	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/eslint-plugin-jest/LICENSE	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2018 Jonathan Kim
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
Index: frontend/node_modules/eslint-plugin-jest/README.md
===================================================================
--- frontend/node_modules/eslint-plugin-jest/README.md	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/eslint-plugin-jest/README.md	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,252 @@
+<div align="center">
+  <a href="https://eslint.org/">
+    <img width="150" height="150" src="https://eslint.org/assets/img/logo.svg">
+  </a>
+  <a href="https://facebook.github.io/jest/">
+    <img width="150" height="150" vspace="" hspace="25" src="https://jestjs.io/img/jest.png">
+  </a>
+  <h1>eslint-plugin-jest</h1>
+  <p>ESLint plugin for Jest</p>
+</div>
+
+[![Actions Status](https://github.com/jest-community/eslint-plugin-jest/actions/workflows/nodejs.yml/badge.svg?branch=main)](https://github.com/jest-community/eslint-plugin-jest/actions)
+
+## Installation
+
+```bash
+yarn add --dev eslint eslint-plugin-jest
+```
+
+**Note:** If you installed ESLint globally then you must also install
+`eslint-plugin-jest` globally.
+
+## Usage
+
+Add `jest` to the plugins section of your `.eslintrc` configuration file. You
+can omit the `eslint-plugin-` prefix:
+
+```json
+{
+  "plugins": ["jest"]
+}
+```
+
+Then configure the rules you want to use under the rules section.
+
+```json
+{
+  "rules": {
+    "jest/no-disabled-tests": "warn",
+    "jest/no-focused-tests": "error",
+    "jest/no-identical-title": "error",
+    "jest/prefer-to-have-length": "warn",
+    "jest/valid-expect": "error"
+  }
+}
+```
+
+You can also tell ESLint about the environment variables provided by Jest by
+doing:
+
+```json
+{
+  "env": {
+    "jest/globals": true
+  }
+}
+```
+
+This is included in all configs shared by this plugin, so can be omitted if
+extending them.
+
+### Jest `version` setting
+
+The behaviour of some rules (specifically [`no-deprecated-functions`][]) change
+depending on the version of Jest being used.
+
+By default, this plugin will attempt to determine to locate Jest using
+`require.resolve`, meaning it will start looking in the closest `node_modules`
+folder to the file being linted and work its way up.
+
+Since we cache the automatically determined version, if you're linting
+sub-folders that have different versions of Jest, you may find that the wrong
+version of Jest is considered when linting. You can work around this by
+providing the Jest version explicitly in nested ESLint configs:
+
+```json
+{
+  "settings": {
+    "jest": {
+      "version": 27
+    }
+  }
+}
+```
+
+To avoid hard-coding a number, you can also fetch it from the installed version
+of Jest if you use a JavaScript config file such as `.eslintrc.js`:
+
+```js
+module.exports = {
+  settings: {
+    jest: {
+      version: require('jest/package.json').version,
+    },
+  },
+};
+```
+
+## Shareable configurations
+
+### Recommended
+
+This plugin exports a recommended configuration that enforces good testing
+practices.
+
+To enable this configuration use the `extends` property in your `.eslintrc`
+config file:
+
+```json
+{
+  "extends": ["plugin:jest/recommended"]
+}
+```
+
+### Style
+
+This plugin also exports a configuration named `style`, which adds some
+stylistic rules, such as `prefer-to-be-null`, which enforces usage of `toBeNull`
+over `toBe(null)`.
+
+To enable this configuration use the `extends` property in your `.eslintrc`
+config file:
+
+```json
+{
+  "extends": ["plugin:jest/style"]
+}
+```
+
+See
+[ESLint documentation](https://eslint.org/docs/user-guide/configuring/configuration-files#extending-configuration-files)
+for more information about extending configuration files.
+
+### All
+
+If you want to enable all rules instead of only some you can do so by adding the
+`all` configuration to your `.eslintrc` config file:
+
+```json
+{
+  "extends": ["plugin:jest/all"]
+}
+```
+
+While the `recommended` and `style` configurations only change in major versions
+the `all` configuration may change in any release and is thus unsuited for
+installations requiring long-term consistency.
+
+## Rules
+
+<!-- begin base rules list -->
+
+| Rule                                                                         | Description                                                         | Configurations   | Fixable      |
+| ---------------------------------------------------------------------------- | ------------------------------------------------------------------- | ---------------- | ------------ |
+| [consistent-test-it](docs/rules/consistent-test-it.md)                       | Have control over `test` and `it` usages                            |                  | ![fixable][] |
+| [expect-expect](docs/rules/expect-expect.md)                                 | Enforce assertion to be made in a test body                         | ![recommended][] |              |
+| [max-nested-describe](docs/rules/max-nested-describe.md)                     | Enforces a maximum depth to nested describe calls                   |                  |              |
+| [no-alias-methods](docs/rules/no-alias-methods.md)                           | Disallow alias methods                                              | ![style][]       | ![fixable][] |
+| [no-commented-out-tests](docs/rules/no-commented-out-tests.md)               | Disallow commented out tests                                        | ![recommended][] |              |
+| [no-conditional-expect](docs/rules/no-conditional-expect.md)                 | Prevent calling `expect` conditionally                              | ![recommended][] |              |
+| [no-deprecated-functions](docs/rules/no-deprecated-functions.md)             | Disallow use of deprecated functions                                | ![recommended][] | ![fixable][] |
+| [no-disabled-tests](docs/rules/no-disabled-tests.md)                         | Disallow disabled tests                                             | ![recommended][] |              |
+| [no-done-callback](docs/rules/no-done-callback.md)                           | Avoid using a callback in asynchronous tests and hooks              | ![recommended][] | ![suggest][] |
+| [no-duplicate-hooks](docs/rules/no-duplicate-hooks.md)                       | Disallow duplicate setup and teardown hooks                         |                  |              |
+| [no-export](docs/rules/no-export.md)                                         | Disallow using `exports` in files containing tests                  | ![recommended][] |              |
+| [no-focused-tests](docs/rules/no-focused-tests.md)                           | Disallow focused tests                                              | ![recommended][] | ![suggest][] |
+| [no-hooks](docs/rules/no-hooks.md)                                           | Disallow setup and teardown hooks                                   |                  |              |
+| [no-identical-title](docs/rules/no-identical-title.md)                       | Disallow identical titles                                           | ![recommended][] |              |
+| [no-if](docs/rules/no-if.md)                                                 | Disallow conditional logic                                          |                  |              |
+| [no-interpolation-in-snapshots](docs/rules/no-interpolation-in-snapshots.md) | Disallow string interpolation inside snapshots                      | ![recommended][] |              |
+| [no-jasmine-globals](docs/rules/no-jasmine-globals.md)                       | Disallow Jasmine globals                                            | ![recommended][] | ![fixable][] |
+| [no-jest-import](docs/rules/no-jest-import.md)                               | Disallow importing Jest                                             | ![recommended][] |              |
+| [no-large-snapshots](docs/rules/no-large-snapshots.md)                       | disallow large snapshots                                            |                  |              |
+| [no-mocks-import](docs/rules/no-mocks-import.md)                             | Disallow manually importing from `__mocks__`                        | ![recommended][] |              |
+| [no-restricted-matchers](docs/rules/no-restricted-matchers.md)               | Disallow specific matchers & modifiers                              |                  |              |
+| [no-standalone-expect](docs/rules/no-standalone-expect.md)                   | Disallow using `expect` outside of `it` or `test` blocks            | ![recommended][] |              |
+| [no-test-prefixes](docs/rules/no-test-prefixes.md)                           | Use `.only` and `.skip` over `f` and `x`                            | ![recommended][] | ![fixable][] |
+| [no-test-return-statement](docs/rules/no-test-return-statement.md)           | Disallow explicitly returning from tests                            |                  |              |
+| [prefer-called-with](docs/rules/prefer-called-with.md)                       | Suggest using `toBeCalledWith()` or `toHaveBeenCalledWith()`        |                  |              |
+| [prefer-comparison-matcher](docs/rules/prefer-comparison-matcher.md)         | Suggest using the built-in comparison matchers                      |                  | ![fixable][] |
+| [prefer-equality-matcher](docs/rules/prefer-equality-matcher.md)             | Suggest using the built-in equality matchers                        |                  | ![suggest][] |
+| [prefer-expect-assertions](docs/rules/prefer-expect-assertions.md)           | Suggest using `expect.assertions()` OR `expect.hasAssertions()`     |                  | ![suggest][] |
+| [prefer-expect-resolves](docs/rules/prefer-expect-resolves.md)               | Prefer `await expect(...).resolves` over `expect(await ...)` syntax |                  | ![fixable][] |
+| [prefer-hooks-on-top](docs/rules/prefer-hooks-on-top.md)                     | Suggest having hooks before any test cases                          |                  |              |
+| [prefer-lowercase-title](docs/rules/prefer-lowercase-title.md)               | Enforce lowercase test names                                        |                  | ![fixable][] |
+| [prefer-spy-on](docs/rules/prefer-spy-on.md)                                 | Suggest using `jest.spyOn()`                                        |                  | ![fixable][] |
+| [prefer-strict-equal](docs/rules/prefer-strict-equal.md)                     | Suggest using `toStrictEqual()`                                     |                  | ![suggest][] |
+| [prefer-to-be](docs/rules/prefer-to-be.md)                                   | Suggest using `toBe()` for primitive literals                       | ![style][]       | ![fixable][] |
+| [prefer-to-contain](docs/rules/prefer-to-contain.md)                         | Suggest using `toContain()`                                         | ![style][]       | ![fixable][] |
+| [prefer-to-have-length](docs/rules/prefer-to-have-length.md)                 | Suggest using `toHaveLength()`                                      | ![style][]       | ![fixable][] |
+| [prefer-todo](docs/rules/prefer-todo.md)                                     | Suggest using `test.todo`                                           |                  | ![fixable][] |
+| [require-hook](docs/rules/require-hook.md)                                   | Require setup and teardown code to be within a hook                 |                  |              |
+| [require-to-throw-message](docs/rules/require-to-throw-message.md)           | Require a message for `toThrow()`                                   |                  |              |
+| [require-top-level-describe](docs/rules/require-top-level-describe.md)       | Require test cases and hooks to be inside a `describe` block        |                  |              |
+| [valid-describe-callback](docs/rules/valid-describe-callback.md)             | Enforce valid `describe()` callback                                 | ![recommended][] |              |
+| [valid-expect](docs/rules/valid-expect.md)                                   | Enforce valid `expect()` usage                                      | ![recommended][] |              |
+| [valid-expect-in-promise](docs/rules/valid-expect-in-promise.md)             | Ensure promises that have expectations in their chain are valid     | ![recommended][] |              |
+| [valid-title](docs/rules/valid-title.md)                                     | Enforce valid titles                                                | ![recommended][] | ![fixable][] |
+
+<!-- end base rules list -->
+
+## TypeScript Rules
+
+In addition to the above rules, this plugin also includes a few advanced rules
+that are powered by type-checking information provided by TypeScript.
+
+In order to use these rules, you must be using `@typescript-eslint/parser` &
+adjust your eslint config as outlined
+[here](https://github.com/typescript-eslint/typescript-eslint/blob/master/docs/getting-started/linting/TYPED_LINTING.md)
+
+Note that unlike the type-checking rules in `@typescript-eslint/eslint-plugin`,
+the rules here will fallback to doing nothing if type information is not
+available, meaning its safe to include them in shared configs that could be used
+on JavaScript and TypeScript projects.
+
+Also note that `unbound-method` depends on `@typescript-eslint/eslint-plugin`,
+as it extends the original `unbound-method` rule from that plugin.
+
+<!-- begin type rules list -->
+
+| Rule                                           | Description                                                   | Configurations | Fixable |
+| ---------------------------------------------- | ------------------------------------------------------------- | -------------- | ------- |
+| [unbound-method](docs/rules/unbound-method.md) | Enforces unbound methods are called with their expected scope |                |         |
+
+<!-- end type rules list -->
+
+## Credit
+
+- [eslint-plugin-mocha](https://github.com/lo1tuma/eslint-plugin-mocha)
+- [eslint-plugin-jasmine](https://github.com/tlvince/eslint-plugin-jasmine)
+
+## Related Projects
+
+### eslint-plugin-jest-formatting
+
+This project aims to provide formatting rules (auto-fixable where possible) to
+ensure consistency and readability in jest test suites.
+
+https://github.com/dangreenisrael/eslint-plugin-jest-formatting
+
+### eslint-plugin-istanbul
+
+A set of rules to enforce good practices for Istanbul, one of the code coverage
+tools used by Jest.
+
+https://github.com/istanbuljs/eslint-plugin-istanbul
+
+[recommended]: https://img.shields.io/badge/-recommended-lightgrey.svg
+[suggest]: https://img.shields.io/badge/-suggest-yellow.svg
+[fixable]: https://img.shields.io/badge/-fixable-green.svg
+[style]: https://img.shields.io/badge/-style-blue.svg
+[`no-deprecated-functions`]: docs/rules/no-deprecated-functions.md
Index: frontend/node_modules/eslint-plugin-jest/docs/rules/consistent-test-it.md
===================================================================
--- frontend/node_modules/eslint-plugin-jest/docs/rules/consistent-test-it.md	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/eslint-plugin-jest/docs/rules/consistent-test-it.md	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,89 @@
+# Have control over `test` and `it` usages (`consistent-test-it`)
+
+Jest allows you to choose how you want to define your tests, using the `it` or
+the `test` keywords, with multiple permutations for each:
+
+- **it:** `it`, `xit`, `fit`, `it.only`, `it.skip`.
+- **test:** `test`, `xtest`, `test.only`, `test.skip`.
+
+This rule gives you control over the usage of these keywords in your codebase.
+
+## Rule Details
+
+This rule can be configured as follows
+
+```json5
+{
+  type: 'object',
+  properties: {
+    fn: {
+      enum: ['it', 'test'],
+    },
+    withinDescribe: {
+      enum: ['it', 'test'],
+    },
+  },
+  additionalProperties: false,
+}
+```
+
+#### fn
+
+Decides whether to use `test` or `it`.
+
+#### withinDescribe
+
+Decides whether to use `test` or `it` within a `describe` scope.
+
+```js
+/*eslint jest/consistent-test-it: ["error", {"fn": "test"}]*/
+
+test('foo'); // valid
+test.only('foo'); // valid
+
+it('foo'); // invalid
+it.only('foo'); // invalid
+```
+
+```js
+/*eslint jest/consistent-test-it: ["error", {"fn": "it"}]*/
+
+it('foo'); // valid
+it.only('foo'); // valid
+
+test('foo'); // invalid
+test.only('foo'); // invalid
+```
+
+```js
+/*eslint jest/consistent-test-it: ["error", {"fn": "it", "withinDescribe": "test"}]*/
+
+it('foo'); // valid
+describe('foo', function () {
+  test('bar'); // valid
+});
+
+test('foo'); // invalid
+describe('foo', function () {
+  it('bar'); // invalid
+});
+```
+
+### Default configuration
+
+The default configuration forces all top-level tests to use `test` and all tests
+nested within `describe` to use `it`.
+
+```js
+/*eslint jest/consistent-test-it: ["error"]*/
+
+test('foo'); // valid
+describe('foo', function () {
+  it('bar'); // valid
+});
+
+it('foo'); // invalid
+describe('foo', function () {
+  test('bar'); // invalid
+});
+```
Index: frontend/node_modules/eslint-plugin-jest/docs/rules/expect-expect.md
===================================================================
--- frontend/node_modules/eslint-plugin-jest/docs/rules/expect-expect.md	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/eslint-plugin-jest/docs/rules/expect-expect.md	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,145 @@
+# Enforce assertion to be made in a test body (`expect-expect`)
+
+Ensure that there is at least one `expect` call made in a test.
+
+## Rule details
+
+This rule triggers when there is no call made to `expect` in a test, to prevent
+users from forgetting to add assertions.
+
+Examples of **incorrect** code for this rule:
+
+```js
+it('should be a test', () => {
+  console.log('no assertion');
+});
+test('should assert something', () => {});
+```
+
+Examples of **correct** code for this rule:
+
+```js
+it('should be a test', () => {
+  expect(true).toBeDefined();
+});
+it('should work with callbacks/async', () => {
+  somePromise().then(res => expect(res).toBe('passed'));
+});
+```
+
+## Options
+
+```json
+{
+  "jest/expect-expect": [
+    "error",
+    {
+      "assertFunctionNames": ["expect"],
+      "additionalTestBlockFunctions": []
+    }
+  ]
+}
+```
+
+### `assertFunctionNames`
+
+This array option specifies the names of functions that should be considered to
+be asserting functions. Function names can use wildcards i.e `request.*.expect`,
+`request.**.expect`, `request.*.expect*`
+
+Examples of **incorrect** code for the `{ "assertFunctionNames": ["expect"] }`
+option:
+
+```js
+/* eslint jest/expect-expect: ["error", { "assertFunctionNames": ["expect"] }] */
+
+import { expectSaga } from 'redux-saga-test-plan';
+import { addSaga } from '../src/sagas';
+
+test('returns sum', () => {
+  expectSaga(addSaga, 1, 1).returns(2).run();
+});
+```
+
+Examples of **correct** code for the
+`{ "assertFunctionNames": ["expect", "expectSaga"] }` option:
+
+```js
+/* eslint jest/expect-expect: ["error", { "assertFunctionNames": ["expect", "expectSaga"] }] */
+
+import { expectSaga } from 'redux-saga-test-plan';
+import { addSaga } from '../src/sagas';
+
+test('returns sum', () => {
+  expectSaga(addSaga, 1, 1).returns(2).run();
+});
+```
+
+Since the string is compiled into a regular expression, you'll need to escape
+special characters such as `$` with a double backslash:
+
+```js
+/* eslint jest/expect-expect: ["error", { "assertFunctionNames": ["expect\\$"] }] */
+
+it('is money-like', () => {
+  expect$(1.0);
+});
+```
+
+Examples of **correct** code for working with the HTTP assertions library
+[SuperTest](https://www.npmjs.com/package/supertest) with the
+`{ "assertFunctionNames": ["expect", "request.**.expect"] }` option:
+
+```js
+/* eslint jest/expect-expect: ["error", { "assertFunctionNames": ["expect", "request.**.expect"] }] */
+const request = require('supertest');
+const express = require('express');
+
+const app = express();
+
+describe('GET /user', function () {
+  it('responds with json', function (done) {
+    request(app).get('/user').expect('Content-Type', /json/).expect(200, done);
+  });
+});
+```
+
+### `additionalTestBlockFunctions`
+
+This array can be used to specify the names of functions that should also be
+treated as test blocks:
+
+```json
+{
+  "rules": {
+    "jest/expect-expect": [
+      "error",
+      { "additionalTestBlockFunctions": ["theoretically"] }
+    ]
+  }
+}
+```
+
+The following is _correct_ when using the above configuration:
+
+```js
+import theoretically from 'jest-theories';
+
+describe('NumberToLongString', () => {
+  const theories = [
+    { input: 100, expected: 'One hundred' },
+    { input: 1000, expected: 'One thousand' },
+    { input: 10000, expected: 'Ten thousand' },
+    { input: 100000, expected: 'One hundred thousand' },
+  ];
+
+  theoretically(
+    'the number {input} is correctly translated to string',
+    theories,
+    theory => {
+      const output = NumberToLongString(theory.input);
+      expect(output).toBe(theory.expected);
+    },
+  );
+});
+```
Index: frontend/node_modules/eslint-plugin-jest/docs/rules/max-nested-describe.md
===================================================================
--- frontend/node_modules/eslint-plugin-jest/docs/rules/max-nested-describe.md	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/eslint-plugin-jest/docs/rules/max-nested-describe.md	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,130 @@
+# Enforces a maximum depth to nested describe calls (`max-nested-describe`)
+
+While it's useful to be able to group your tests together within the same file
+using `describe()`, having too many levels of nesting throughout your tests make
+them difficult to read.
+
+## Rule Details
+
+This rule enforces a maximum depth to nested `describe()` calls to improve code
+clarity in your tests.
+
+The following patterns are considered warnings (with the default option of
+`{ "max": 5 } `):
+
+```js
+describe('foo', () => {
+  describe('bar', () => {
+    describe('baz', () => {
+      describe('qux', () => {
+        describe('quxx', () => {
+          describe('too many', () => {
+            it('should get something', () => {
+              expect(getSomething()).toBe('Something');
+            });
+          });
+        });
+      });
+    });
+  });
+});
+
+describe('foo', function () {
+  describe('bar', function () {
+    describe('baz', function () {
+      describe('qux', function () {
+        describe('quxx', function () {
+          describe('too many', function () {
+            it('should get something', () => {
+              expect(getSomething()).toBe('Something');
+            });
+          });
+        });
+      });
+    });
+  });
+});
+```
+
+The following patterns are **not** considered warnings (with the default option
+of `{ "max": 5 } `):
+
+```js
+describe('foo', () => {
+  describe('bar', () => {
+    it('should get something', () => {
+      expect(getSomething()).toBe('Something');
+    });
+  });
+
+  describe('qux', () => {
+    it('should get something', () => {
+      expect(getSomething()).toBe('Something');
+    });
+  });
+});
+
+describe('foo2', function () {
+  it('should get something', () => {
+    expect(getSomething()).toBe('Something');
+  });
+});
+
+describe('foo', function () {
+  describe('bar', function () {
+    describe('baz', function () {
+      describe('qux', function () {
+        describe('this is the limit', function () {
+          it('should get something', () => {
+            expect(getSomething()).toBe('Something');
+          });
+        });
+      });
+    });
+  });
+});
+```
+
+## Options
+
+```json
+{
+  "jest/max-nested-describe": [
+    "error",
+    {
+      "max": 5
+    }
+  ]
+}
+```
+
+### `max`
+
+Enforces a maximum depth for nested `describe()`.
+
+This has a default value of `5`.
+
+Examples of patterns **not** considered warnings with options set to
+`{ "max": 2 }`:
+
+```js
+describe('foo', () => {
+  describe('bar', () => {
+    it('should get something', () => {
+      expect(getSomething()).toBe('Something');
+    });
+  });
+});
+
+describe('foo2', function () {
+  describe('bar2', function () {
+    it('should get something', function () {
+      expect(getSomething()).toBe('Something');
+    });
+
+    it('should get  else', function () {
+      expect(getSomething()).toBe('Something');
+    });
+  });
+});
+```
Index: frontend/node_modules/eslint-plugin-jest/docs/rules/no-alias-methods.md
===================================================================
--- frontend/node_modules/eslint-plugin-jest/docs/rules/no-alias-methods.md	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/eslint-plugin-jest/docs/rules/no-alias-methods.md	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,46 @@
+# Disallow alias methods (`no-alias-methods`)
+
+Several Jest methods have alias names, such as `toThrow` having the alias of
+`toThrowError`. This rule ensures that only the canonical name as used in the
+Jest documentation is used in the code. This makes it easier to search for all
+occurrences of the method within code, and it ensures consistency among the
+method names used.
+
+## Rule details
+
+This rule triggers a warning if the alias name, rather than the canonical name,
+of a method is used.
+
+### Default configuration
+
+The following patterns are considered warnings:
+
+```js
+expect(a).toBeCalled();
+expect(a).toBeCalledTimes();
+expect(a).toBeCalledWith();
+expect(a).lastCalledWith();
+expect(a).nthCalledWith();
+expect(a).toReturn();
+expect(a).toReturnTimes();
+expect(a).toReturnWith();
+expect(a).lastReturnedWith();
+expect(a).nthReturnedWith();
+expect(a).toThrowError();
+```
+
+The following patterns are not considered warnings:
+
+```js
+expect(a).toHaveBeenCalled();
+expect(a).toHaveBeenCalledTimes();
+expect(a).toHaveBeenCalledWith();
+expect(a).toHaveBeenLastCalledWith();
+expect(a).toHaveBeenNthCalledWith();
+expect(a).toHaveReturned();
+expect(a).toHaveReturnedTimes();
+expect(a).toHaveReturnedWith();
+expect(a).toHaveLastReturnedWith();
+expect(a).toHaveNthReturnedWith();
+expect(a).toThrow();
+```
Index: frontend/node_modules/eslint-plugin-jest/docs/rules/no-commented-out-tests.md
===================================================================
--- frontend/node_modules/eslint-plugin-jest/docs/rules/no-commented-out-tests.md	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/eslint-plugin-jest/docs/rules/no-commented-out-tests.md	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,61 @@
+# Disallow commented out tests (`no-commented-out-tests`)
+
+This rule raises a warning about commented out tests. It's similar to
+no-disabled-tests rule.
+
+## Rule Details
+
+The rule uses fuzzy matching to do its best to determine what constitutes a
+commented out test, checking for a presence of `it(`, `describe(`, `it.skip(`,
+etc. in code comments.
+
+The following patterns are considered warnings:
+
+```js
+// describe('foo', () => {});
+// it('foo', () => {});
+// test('foo', () => {});
+
+// describe.skip('foo', () => {});
+// it.skip('foo', () => {});
+// test.skip('foo', () => {});
+
+// describe['skip']('bar', () => {});
+// it['skip']('bar', () => {});
+// test['skip']('bar', () => {});
+
+// xdescribe('foo', () => {});
+// xit('foo', () => {});
+// xtest('foo', () => {});
+
+/*
+describe('foo', () => {});
+*/
+```
+
+These patterns would not be considered warnings:
+
+```js
+describe('foo', () => {});
+it('foo', () => {});
+test('foo', () => {});
+
+describe.only('bar', () => {});
+it.only('bar', () => {});
+test.only('bar', () => {});
+
+// foo('bar', () => {});
+```
+
+### Limitations
+
+The plugin looks at the literal function names within test code, so will not
+catch more complex examples of commented out tests, such as:
+
+```js
+// const testSkip = test.skip;
+// testSkip('skipped test', () => {});
+
+// const myTest = test;
+// myTest('does not have function body');
+```
Index: frontend/node_modules/eslint-plugin-jest/docs/rules/no-conditional-expect.md
===================================================================
--- frontend/node_modules/eslint-plugin-jest/docs/rules/no-conditional-expect.md	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/eslint-plugin-jest/docs/rules/no-conditional-expect.md	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,135 @@
+# Prevent calling `expect` conditionally (`no-conditional-expect`)
+
+This rule prevents the use of `expect` in conditional blocks, such as `if`s &
+`catch`s.
+
+This includes using `expect` in callbacks to functions named `catch`, which are
+assumed to be promises.
+
+## Rule Details
+
+Jest only considers a test to have failed if it throws an error, meaning if
+calls to assertion functions like `expect` occur in conditional code such as a
+`catch` statement, tests can end up passing but not actually test anything.
+
+Additionally, conditionals tend to make tests more brittle and complex, as they
+increase the amount of mental thinking needed to understand what is actually
+being tested.
+
+While `expect.assertions` & `expect.hasAssertions` can help prevent tests from
+silently being skipped, when combined with conditionals they typically result in
+even more complexity being introduced.
+
+The following patterns are warnings:
+
+```js
+it('foo', () => {
+  doTest && expect(1).toBe(2);
+});
+
+it('bar', () => {
+  if (!skipTest) {
+    expect(1).toEqual(2);
+  }
+});
+
+it('baz', async () => {
+  try {
+    await foo();
+  } catch (err) {
+    expect(err).toMatchObject({ code: 'MODULE_NOT_FOUND' });
+  }
+});
+
+it('throws an error', async () => {
+  await foo().catch(error => expect(error).toBeInstanceOf(error));
+});
+```
+
+The following patterns are not warnings:
+
+```js
+it('foo', () => {
+  expect(!value).toBe(false);
+});
+
+function getValue() {
+  if (process.env.FAIL) {
+    return 1;
+  }
+
+  return 2;
+}
+
+it('foo', () => {
+  expect(getValue()).toBe(2);
+});
+
+it('validates the request', () => {
+  try {
+    processRequest(request);
+  } catch {
+    // ignore errors
+  } finally {
+    expect(validRequest).toHaveBeenCalledWith(request);
+  }
+});
+
+it('throws an error', async () => {
+  await expect(foo).rejects.toThrow(Error);
+});
+```
+
+### How to catch a thrown error for testing without violating this rule
+
+A common situation that comes up with this rule is when wanting to test
+properties on a thrown error, as Jest's `toThrow` matcher only checks the
+`message` property.
+
+Most people write something like this:
+
+```typescript
+describe('when the http request fails', () => {
+  it('includes the status code in the error', async () => {
+    try {
+      await makeRequest(url);
+    } catch (error) {
+      expect(error).toHaveProperty('statusCode', 404);
+    }
+  });
+});
+```
+
+As stated above, the problem with this is that if `makeRequest()` doesn't throw
+the test will still pass as if the `expect` had been called.
+
+While you can use `expect.assertions` & `expect.hasAssertions` for these
+situations, they only work with `expect`.
+
+A better way to handle this situation is to introduce a wrapper to handle the
+catching, and otherwise returns a specific "no error thrown" error if nothing is
+thrown by the wrapped function:
+
+```typescript
+class NoErrorThrownError extends Error {}
+
+const getError = async <TError>(call: () => unknown): Promise<TError> => {
+  try {
+    await call();
+
+    throw new NoErrorThrownError();
+  } catch (error: unknown) {
+    return error as TError;
+  }
+};
+
+describe('when the http request fails', () => {
+  it('includes the status code in the error', async () => {
+    const error = await getError(async () => makeRequest(url));
+
+    // check that the returned error wasn't that no error was thrown
+    expect(error).not.toBeInstanceOf(NoErrorThrownError);
+    expect(error).toHaveProperty('statusCode', 404);
+  });
+});
+```
Index: frontend/node_modules/eslint-plugin-jest/docs/rules/no-deprecated-functions.md
===================================================================
--- frontend/node_modules/eslint-plugin-jest/docs/rules/no-deprecated-functions.md	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/eslint-plugin-jest/docs/rules/no-deprecated-functions.md	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,51 @@
+# Disallow use of deprecated functions (`no-deprecated-functions`)
+
+Over the years Jest has accrued some debt in the form of functions that have
+either been renamed for clarity, or replaced with more powerful APIs.
+
+While typically these deprecated functions are kept in the codebase for a number
+of majors, eventually they are removed completely.
+
+This rule requires knowing which version of Jest you're using - see
+[this section of the readme](../../README.md#jest-version-setting) for details
+on how that is obtained automatically and how you can explicitly provide a
+version if needed.
+
+## Rule details
+
+This rule warns about calls to deprecated functions, and provides details on
+what to replace them with, based on the version of Jest that is installed.
+
+This rule can also autofix a number of these deprecations for you.
+
+### `jest.resetModuleRegistry`
+
+This function was renamed to `resetModules` in Jest 15, and is scheduled for
+removal in Jest 27.
+
+### `jest.addMatchers`
+
+This function was replaced with `expect.extend` in Jest 17, and is scheduled for
+removal in Jest 27.
+
+### `require.requireActual` & `require.requireMock`
+
+These functions were replaced in Jest 21 and removed in Jest 26.
+
+Originally, the `requireActual` & `requireMock` the `requireActual`&
+`requireMock` functions were placed onto the `require` function.
+
+These functions were later moved onto the `jest` object in order to be easier
+for type checkers to handle, and their use via `require` deprecated. Finally,
+the release of Jest 26 saw them removed from the `require` function all
+together.
+
+### `jest.runTimersToTime`
+
+This function was renamed to `advanceTimersByTime` in Jest 22, and is scheduled
+for removal in Jest 27.
+
+### `jest.genMockFromModule`
+
+This function was renamed to `createMockFromModule` in Jest 26, and is scheduled
+for removal in a future version of Jest.
Index: frontend/node_modules/eslint-plugin-jest/docs/rules/no-disabled-tests.md
===================================================================
--- frontend/node_modules/eslint-plugin-jest/docs/rules/no-disabled-tests.md	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/eslint-plugin-jest/docs/rules/no-disabled-tests.md	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,65 @@
+# Disallow disabled tests (`no-disabled-tests`)
+
+Jest has a feature that allows you to temporarily mark tests as disabled. This
+feature is often helpful while debugging or to create placeholders for future
+tests. Before committing changes we may want to check that all tests are
+running.
+
+This rule raises a warning about disabled tests.
+
+## Rule Details
+
+There are a number of ways to disable tests in Jest:
+
+- by appending `.skip` to the test-suite or test-case
+- by prepending the test function name with `x`
+- by declaring a test with a name but no function body
+- by making a call to `pending()` anywhere within the test
+
+The following patterns are considered warnings:
+
+```js
+describe.skip('foo', () => {});
+it.skip('foo', () => {});
+test.skip('foo', () => {});
+
+describe['skip']('bar', () => {});
+it['skip']('bar', () => {});
+test['skip']('bar', () => {});
+
+xdescribe('foo', () => {});
+xit('foo', () => {});
+xtest('foo', () => {});
+
+it('bar');
+test('bar');
+
+it('foo', () => {
+  pending();
+});
+```
+
+These patterns would not be considered warnings:
+
+```js
+describe('foo', () => {});
+it('foo', () => {});
+test('foo', () => {});
+
+describe.only('bar', () => {});
+it.only('bar', () => {});
+test.only('bar', () => {});
+```
+
+### Limitations
+
+The plugin looks at the literal function names within test code, so will not
+catch more complex examples of disabled tests, such as:
+
+```js
+const testSkip = test.skip;
+testSkip('skipped test', () => {});
+
+const myTest = test;
+myTest('does not have function body');
+```
Index: frontend/node_modules/eslint-plugin-jest/docs/rules/no-done-callback.md
===================================================================
--- frontend/node_modules/eslint-plugin-jest/docs/rules/no-done-callback.md	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/eslint-plugin-jest/docs/rules/no-done-callback.md	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,90 @@
+# Avoid using a callback in asynchronous tests and hooks (`no-done-callback`)
+
+When calling asynchronous code in hooks and tests, `jest` needs to know when the
+asynchronous work is complete to progress the current run.
+
+Originally the most common pattern to achieve this was to use callbacks:
+
+```js
+test('the data is peanut butter', done => {
+  function callback(data) {
+    try {
+      expect(data).toBe('peanut butter');
+      done();
+    } catch (error) {
+      done(error);
+    }
+  }
+
+  fetchData(callback);
+});
+```
+
+This can be very error-prone however, as it requires careful understanding of
+how assertions work in tests or otherwise tests won't behave as expected.
+
+For example, if the `try/catch` was left out of the above code, the test would
+time out rather than fail. Even with the `try/catch`, forgetting to pass the
+caught error to `done` will result in `jest` believing the test has passed.
+
+A more straightforward way to handle asynchronous code is to use Promises:
+
+```js
+test('the data is peanut butter', () => {
+  return fetchData().then(data => {
+    expect(data).toBe('peanut butter');
+  });
+});
+```
+
+When a test or hook returns a promise, `jest` waits for that promise to resolve,
+as well as automatically failing should the promise reject.
+
+If your environment supports `async/await`, this becomes even simpler:
+
+```js
+test('the data is peanut butter', async () => {
+  const data = await fetchData();
+  expect(data).toBe('peanut butter');
+});
+```
+
+## Rule details
+
+This rule checks the function parameter of hooks & tests for use of the `done`
+argument, suggesting you return a promise instead.
+
+The following patterns are considered warnings:
+
+```js
+beforeEach(done => {
+  // ...
+});
+
+test('myFunction()', done => {
+  // ...
+});
+
+test('myFunction()', function (done) {
+  // ...
+});
+```
+
+The following patterns are not considered warnings:
+
+```js
+beforeEach(async () => {
+  await setupUsTheBomb();
+});
+
+test('myFunction()', () => {
+  expect(myFunction()).toBeTruthy();
+});
+
+test('myFunction()', () => {
+  return new Promise(done => {
+    expect(myFunction()).toBeTruthy();
+    done();
+  });
+});
+```
Index: frontend/node_modules/eslint-plugin-jest/docs/rules/no-duplicate-hooks.md
===================================================================
--- frontend/node_modules/eslint-plugin-jest/docs/rules/no-duplicate-hooks.md	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/eslint-plugin-jest/docs/rules/no-duplicate-hooks.md	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,75 @@
+# Disallow duplicate setup and teardown hooks (`no-duplicate-hooks`)
+
+A `describe` block should not contain duplicate hooks.
+
+## Rule Details
+
+Examples of **incorrect** code for this rule
+
+```js
+/* eslint jest/no-duplicate-hooks: "error" */
+
+describe('foo', () => {
+  beforeEach(() => {
+    // some setup
+  });
+  beforeEach(() => {
+    // some setup
+  });
+  test('foo_test', () => {
+    // some test
+  });
+});
+
+// Nested describe scenario
+describe('foo', () => {
+  beforeEach(() => {
+    // some setup
+  });
+  test('foo_test', () => {
+    // some test
+  });
+  describe('bar', () => {
+    test('bar_test', () => {
+      afterAll(() => {
+        // some teardown
+      });
+      afterAll(() => {
+        // some teardown
+      });
+    });
+  });
+});
+```
+
+Examples of **correct** code for this rule
+
+```js
+/* eslint jest/no-duplicate-hooks: "error" */
+
+describe('foo', () => {
+  beforeEach(() => {
+    // some setup
+  });
+  test('foo_test', () => {
+    // some test
+  });
+});
+
+// Nested describe scenario
+describe('foo', () => {
+  beforeEach(() => {
+    // some setup
+  });
+  test('foo_test', () => {
+    // some test
+  });
+  describe('bar', () => {
+    test('bar_test', () => {
+      beforeEach(() => {
+        // some setup
+      });
+    });
+  });
+});
+```
Index: frontend/node_modules/eslint-plugin-jest/docs/rules/no-export.md
===================================================================
--- frontend/node_modules/eslint-plugin-jest/docs/rules/no-export.md	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/eslint-plugin-jest/docs/rules/no-export.md	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,45 @@
+# Disallow using `exports` in files containing tests (`no-export`)
+
+Prevents using `exports` if a file has one or more tests in it.
+
+## Rule Details
+
+This rule aims to eliminate duplicate runs of tests by exporting things from
+test files. If you import from a test file, then all the tests in that file will
+be run in each imported instance, so bottom line, don't export from a test, but
+instead move helper functions into a separate file when they need to be shared
+across tests.
+
+Examples of **incorrect** code for this rule:
+
+```js
+export function myHelper() {}
+
+module.exports = function () {};
+
+module.exports = {
+  something: 'that should be moved to a non-test file',
+};
+
+describe('a test', () => {
+  expect(1).toBe(1);
+});
+```
+
+Examples of **correct** code for this rule:
+
+```js
+function myHelper() {}
+
+const myThing = {
+  something: 'that can live here',
+};
+
+describe('a test', () => {
+  expect(1).toBe(1);
+});
+```
+
+## When Not To Use It
+
+Don't use this rule on non-jest test files.
Index: frontend/node_modules/eslint-plugin-jest/docs/rules/no-focused-tests.md
===================================================================
--- frontend/node_modules/eslint-plugin-jest/docs/rules/no-focused-tests.md	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/eslint-plugin-jest/docs/rules/no-focused-tests.md	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,56 @@
+# Disallow focused tests (`no-focused-tests`)
+
+Jest has a feature that allows you to focus tests by appending `.only` or
+prepending `f` to a test-suite or a test-case. This feature is really helpful to
+debug a failing test, so you don’t have to execute all of your tests. After you
+have fixed your test and before committing the changes you have to remove
+`.only` to ensure all tests are executed on your build system.
+
+This rule reminds you to remove `.only` from your tests by raising a warning
+whenever you are using the exclusivity feature.
+
+## Rule Details
+
+This rule looks for every `describe.only`, `it.only`, `test.only`, `fdescribe`,
+and `fit` occurrences within the source code. Of course there are some
+edge-cases which can’t be detected by this rule e.g.:
+
+```js
+const describeOnly = describe.only;
+describeOnly.apply(describe);
+```
+
+The following patterns are considered warnings:
+
+```js
+describe.only('foo', () => {});
+it.only('foo', () => {});
+describe['only']('bar', () => {});
+it['only']('bar', () => {});
+test.only('foo', () => {});
+test['only']('bar', () => {});
+fdescribe('foo', () => {});
+fit('foo', () => {});
+fit.each`
+  table
+`();
+```
+
+These patterns would not be considered warnings:
+
+```js
+describe('foo', () => {});
+it('foo', () => {});
+describe.skip('bar', () => {});
+it.skip('bar', () => {});
+test('foo', () => {});
+test.skip('bar', () => {});
+it.each()();
+it.each`
+  table
+`();
+test.each()();
+test.each`
+  table
+`();
+```
Index: frontend/node_modules/eslint-plugin-jest/docs/rules/no-hooks.md
===================================================================
--- frontend/node_modules/eslint-plugin-jest/docs/rules/no-hooks.md	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/eslint-plugin-jest/docs/rules/no-hooks.md	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,174 @@
+# Disallow setup and teardown hooks (`no-hooks`)
+
+Jest provides global functions for setup and teardown tasks, which are called
+before/after each test case and each test suite. The use of these hooks promotes
+shared state between tests.
+
+## Rule Details
+
+This rule reports for the following function calls:
+
+- `beforeAll`
+- `beforeEach`
+- `afterAll`
+- `afterEach`
+
+Examples of **incorrect** code for this rule:
+
+```js
+/* eslint jest/no-hooks: "error" */
+
+function setupFoo(options) {
+  /* ... */
+}
+
+function setupBar(options) {
+  /* ... */
+}
+
+describe('foo', () => {
+  let foo;
+
+  beforeEach(() => {
+    foo = setupFoo();
+  });
+
+  afterEach(() => {
+    foo = null;
+  });
+
+  it('does something', () => {
+    expect(foo.doesSomething()).toBe(true);
+  });
+
+  describe('with bar', () => {
+    let bar;
+
+    beforeEach(() => {
+      bar = setupBar();
+    });
+
+    afterEach(() => {
+      bar = null;
+    });
+
+    it('does something with bar', () => {
+      expect(foo.doesSomething(bar)).toBe(true);
+    });
+  });
+});
+```
+
+Examples of **correct** code for this rule:
+
+```js
+/* eslint jest/no-hooks: "error" */
+
+function setupFoo(options) {
+  /* ... */
+}
+
+function setupBar(options) {
+  /* ... */
+}
+
+describe('foo', () => {
+  it('does something', () => {
+    const foo = setupFoo();
+    expect(foo.doesSomething()).toBe(true);
+  });
+
+  it('does something with bar', () => {
+    const foo = setupFoo();
+    const bar = setupBar();
+    expect(foo.doesSomething(bar)).toBe(true);
+  });
+});
+```
+
+## Options
+
+```json
+{
+  "jest/no-hooks": [
+    "error",
+    {
+      "allow": ["afterEach", "afterAll"]
+    }
+  ]
+}
+```
+
+### `allow`
+
+This array option controls which Jest hooks are checked by this rule. There are
+four possible values:
+
+- `"beforeAll"`
+- `"beforeEach"`
+- `"afterAll"`
+- `"afterEach"`
+
+By default, none of these options are enabled (the equivalent of
+`{ "allow": [] }`).
+
+Examples of **incorrect** code for the `{ "allow": ["afterEach"] }` option:
+
+```js
+/* eslint jest/no-hooks: ["error", { "allow": ["afterEach"] }] */
+
+function setupFoo(options) {
+  /* ... */
+}
+
+let foo;
+
+beforeEach(() => {
+  foo = setupFoo();
+});
+
+afterEach(() => {
+  jest.resetModules();
+});
+
+test('foo does this', () => {
+  // ...
+});
+
+test('foo does that', () => {
+  // ...
+});
+```
+
+Examples of **correct** code for the `{ "allow": ["afterEach"] }` option:
+
+```js
+/* eslint jest/no-hooks: ["error", { "allow": ["afterEach"] }] */
+
+function setupFoo(options) {
+  /* ... */
+}
+
+afterEach(() => {
+  jest.resetModules();
+});
+
+test('foo does this', () => {
+  const foo = setupFoo();
+  // ...
+});
+
+test('foo does that', () => {
+  const foo = setupFoo();
+  // ...
+});
+```
+
+## When Not To Use It
+
+If you prefer using the setup and teardown hooks provided by Jest, you can
+safely disable this rule.
+
+## Further Reading
+
+- [Jest docs - Setup and Teardown](https://facebook.github.io/jest/docs/en/setup-teardown.html)
Index: frontend/node_modules/eslint-plugin-jest/docs/rules/no-identical-title.md
===================================================================
--- frontend/node_modules/eslint-plugin-jest/docs/rules/no-identical-title.md	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/eslint-plugin-jest/docs/rules/no-identical-title.md	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,52 @@
+# Disallow identical titles (`no-identical-title`)
+
+Having identical titles for two different tests or test suites may create
+confusion. For example, when a test with the same title as another test in the
+same test suite fails, it is harder to know which one failed and thus harder to
+fix.
+
+## Rule Details
+
+This rule looks at the title of every test and test suites. It will report when
+two test suites or two test cases at the same level of a test suite have the
+same title.
+
+The following patterns are considered warnings:
+
+```js
+describe('foo', () => {
+  it('should do bar', () => {});
+  it('should do bar', () => {}); // Has the same title as the previous test
+
+  describe('baz', () => {
+    // ...
+  });
+
+  describe('baz', () => {
+    // Has the same title as a previous test suite
+    // ...
+  });
+});
+```
+
+These patterns would not be considered warnings:
+
+```js
+describe('foo', () => {
+  it('should do foo', () => {});
+  it('should do bar', () => {});
+
+  // Has the same name as a parent test suite, which is fine
+  describe('foo', () => {
+    // Has the same name as a test in a parent test suite, which is fine
+    it('should do foo', () => {});
+    it('should work', () => {});
+  });
+
+  describe('baz', () => {
+    // Has the same title as a previous test suite
+    // Has the same name as a test in a sibling test suite, which is fine
+    it('should work', () => {});
+  });
+});
+```
Index: frontend/node_modules/eslint-plugin-jest/docs/rules/no-if.md
===================================================================
--- frontend/node_modules/eslint-plugin-jest/docs/rules/no-if.md	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/eslint-plugin-jest/docs/rules/no-if.md	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,53 @@
+# Disallow conditional logic (`no-if`)
+
+Conditional logic in tests is usually an indication that a test is attempting to
+cover too much, and not testing the logic it intends to. Each branch of code
+executing within an if statement will usually be better served by a test devoted
+to it.
+
+Conditionals are often used to satisfy the typescript type checker. In these
+cases, using the non-null assertion operator (!) would be best.
+
+## Rule Details
+
+This rule prevents the use of if/ else statements and conditional (ternary)
+operations in tests.
+
+The following patterns are considered warnings:
+
+```js
+it('foo', () => {
+  if ('bar') {
+    // an if statement here is invalid
+    // you are probably testing too much
+  }
+});
+
+it('foo', () => {
+  const bar = foo ? 'bar' : null;
+});
+```
+
+These patterns would not be considered warnings:
+
+```js
+it('foo', () => {
+  // only test the 'foo' case
+});
+
+it('bar', () => {
+  // test the 'bar' case separately
+});
+
+it('foo', () => {
+  function foo(bar) {
+    // nested functions are valid
+    return foo ? bar : null;
+  }
+});
+```
+
+## When Not To Use It
+
+If you do not wish to prevent the use of if statements in tests, you can safely
+disable this rule.
Index: frontend/node_modules/eslint-plugin-jest/docs/rules/no-interpolation-in-snapshots.md
===================================================================
--- frontend/node_modules/eslint-plugin-jest/docs/rules/no-interpolation-in-snapshots.md	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/eslint-plugin-jest/docs/rules/no-interpolation-in-snapshots.md	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,60 @@
+# Disallow string interpolation inside snapshots (`no-interpolation-in-snapshots`)
+
+Prevents the use of string interpolations in snapshots.
+
+## Rule Details
+
+Interpolation prevents snapshots from being updated. Instead, properties should
+be overloaded with a matcher by using
+[property matchers](https://jestjs.io/docs/en/snapshot-testing#property-matchers).
+
+Examples of **incorrect** code for this rule:
+
+```js
+expect(something).toMatchInlineSnapshot(
+  `Object {
+    property: ${interpolated}
+  }`,
+);
+
+expect(something).toMatchInlineSnapshot(
+  { other: expect.any(Number) },
+  `Object {
+    other: Any<Number>,
+    property: ${interpolated}
+  }`,
+);
+
+expect(errorThrowingFunction).toThrowErrorMatchingInlineSnapshot(
+  `${interpolated}`,
+);
+```
+
+Examples of **correct** code for this rule:
+
+```js
+expect(something).toMatchInlineSnapshot();
+
+expect(something).toMatchInlineSnapshot(
+  `Object {
+    property: 1
+  }`,
+);
+
+expect(something).toMatchInlineSnapshot(
+  { property: expect.any(Date) },
+  `Object {
+    property: Any<Date>
+  }`,
+);
+
+expect(errorThrowingFunction).toThrowErrorMatchingInlineSnapshot();
+
+expect(errorThrowingFunction).toThrowErrorMatchingInlineSnapshot(
+  `Error Message`,
+);
+```
+
+## When Not To Use It
+
+Don't use this rule on non-jest test files.
Index: frontend/node_modules/eslint-plugin-jest/docs/rules/no-jasmine-globals.md
===================================================================
--- frontend/node_modules/eslint-plugin-jest/docs/rules/no-jasmine-globals.md	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/eslint-plugin-jest/docs/rules/no-jasmine-globals.md	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,59 @@
+# Disallow Jasmine globals (`no-jasmine-globals`)
+
+`jest` uses `jasmine` as a test runner. A side effect of this is that both a
+`jasmine` object, and some jasmine-specific globals, are exposed to the test
+environment. Most functionality offered by Jasmine has been ported to Jest, and
+the Jasmine globals will stop working in the future. Developers should therefore
+migrate to Jest's documented API instead of relying on the undocumented Jasmine
+API.
+
+### Rule details
+
+This rule reports on any usage of Jasmine globals which is not ported to Jest,
+and suggests alternative from Jest's own API.
+
+### Default configuration
+
+The following patterns are considered warnings:
+
+```js
+jasmine.DEFAULT_TIMEOUT_INTERVAL = 5000;
+
+test('my test', () => {
+  pending();
+});
+
+test('my test', () => {
+  fail();
+});
+
+test('my test', () => {
+  spyOn(some, 'object');
+});
+
+test('my test', () => {
+  jasmine.createSpy();
+});
+
+test('my test', () => {
+  expect('foo').toEqual(jasmine.anything());
+});
+```
+
+The following patterns would not be considered warnings:
+
+```js
+jest.setTimeout(5000);
+
+test('my test', () => {
+  jest.spyOn(some, 'object');
+});
+
+test('my test', () => {
+  jest.fn();
+});
+
+test('my test', () => {
+  expect('foo').toEqual(expect.anything());
+});
+```
Index: frontend/node_modules/eslint-plugin-jest/docs/rules/no-jest-import.md
===================================================================
--- frontend/node_modules/eslint-plugin-jest/docs/rules/no-jest-import.md	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/eslint-plugin-jest/docs/rules/no-jest-import.md	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,20 @@
+# Disallow importing Jest (`no-jest-import`)
+
+The `jest` object is automatically in scope within every test file. The methods
+in the `jest` object help create mocks and let you control Jest's overall
+behavior. It is therefore completely unnecessary to import in `jest`, as Jest
+doesn't export anything in the first place.
+
+### Rule details
+
+This rule reports on any importing of Jest.
+
+To name a few: `var jest = require('jest');` `const jest = require('jest');`
+`import jest from 'jest';` `import {jest as test} from 'jest';`
+
+There is no correct usage of this code, other than to not import `jest` in the
+first place.
+
+## Further Reading
+
+\*[The Jest Object](https://facebook.github.io/jest/docs/en/jest-object.html)
Index: frontend/node_modules/eslint-plugin-jest/docs/rules/no-large-snapshots.md
===================================================================
--- frontend/node_modules/eslint-plugin-jest/docs/rules/no-large-snapshots.md	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/eslint-plugin-jest/docs/rules/no-large-snapshots.md	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,172 @@
+# disallow large snapshots (`no-large-snapshots`)
+
+When using Jest's snapshot capability one should be mindful of the size of
+created snapshots. As a general best practice snapshots should be limited in
+size in order to be more manageable and reviewable. A stored snapshot is only as
+good as its review and as such keeping it short, sweet, and readable is
+important to allow for thorough reviews.
+
+## Usage
+
+Because Jest snapshots are written with back-ticks (\` \`) which are only valid
+with
+[ES2015 onwards](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals)
+you should set `parserOptions` in your config to at least allow ES2015 in order
+to use this rule:
+
+```js
+module.exports = {
+  parserOptions: {
+    ecmaVersion: 2015,
+  },
+};
+```
+
+## Rule Details
+
+This rule looks at all Jest inline and external snapshots (files with `.snap`
+extension) and validates that each stored snapshot within those files does not
+exceed 50 lines (by default, this is configurable as explained in `Options`
+section below).
+
+Example of **incorrect** code for this rule:
+
+```js
+exports[`a large snapshot 1`] = `
+line 1
+line 2
+line 3
+line 4
+line 5
+line 6
+line 7
+line 8
+line 9
+line 10
+line 11
+line 12
+line 13
+line 14
+line 15
+line 16
+line 17
+line 18
+line 19
+line 20
+line 21
+line 22
+line 23
+line 24
+line 25
+line 26
+line 27
+line 28
+line 29
+line 30
+line 31
+line 32
+line 33
+line 34
+line 35
+line 36
+line 37
+line 38
+line 39
+line 40
+line 41
+line 42
+line 43
+line 44
+line 45
+line 46
+line 47
+line 48
+line 49
+line 50
+line 51
+`;
+```
+
+Example of **correct** code for this rule:
+
+```js
+exports[`a more manageable and readable snapshot 1`] = `
+line 1
+line 2
+line 3
+line 4
+`;
+```
+
+## Options
+
+This rule has options for modifying the max number of lines allowed for a
+snapshot:
+
+In an `eslintrc` file:
+
+```json
+{
+  "rules": {
+    "jest/no-large-snapshots": ["warn", { "maxSize": 12, "inlineMaxSize": 6 }]
+  }
+}
+```
+
+Max number of lines allowed could be defined by snapshot type (Inline and
+External). Use `inlineMaxSize` for
+[Inline Snapshots](https://jestjs.io/docs/en/snapshot-testing#inline-snapshots)
+size and `maxSize` for
+[External Snapshots](https://jestjs.io/docs/en/snapshot-testing#snapshot-testing-with-jest).
+If only `maxSize` is provided on options, the value of `maxSize` will be used to
+both snapshot types (Inline and External).
+
+Since `eslint-disable` comments are not preserved by Jest when updating
+snapshots, you can use the `allowedSnapshots` option to have specific snapshots
+allowed regardless of their size.
+
+This option takes a map, with the key being the absolute filepath to a snapshot
+file, and the value an array of values made up of strings and regular
+expressions to compare to the names of the snapshots in the `.snap` file when
+checking if the snapshots size should be allowed.
+
+Note that regular expressions can only be passed in via `.eslintrc.js` as
+instances of `RegExp`.
+
+In an `.eslintrc.js` file:
+
+```javascript
+module.exports = {
+  rules: {
+    'jest/no-large-snapshots': [
+      'error',
+      {
+        allowedSnapshots: {
+          '/path/to/file.js.snap': ['snapshot name 1', /a big snapshot \d+/],
+        },
+      },
+    ],
+  },
+};
+```
+
+Since absolute paths are typically not very portable, you can use the builtin
+`path.resolve` function to expand relative paths into absolutes like so:
+
+```javascript
+const path = require('path');
+
+module.exports = {
+  rules: {
+    'jest/no-large-snapshots': [
+      'error',
+      {
+        allowedSnapshots: {
+          [path.resolve('test/__snapshots__/get.js.snap')]: ['full request'],
+          [path.resolve('test/__snapshots__/put.js.snap')]: ['full request'],
+        },
+      },
+    ],
+  },
+};
+```
Index: frontend/node_modules/eslint-plugin-jest/docs/rules/no-mocks-import.md
===================================================================
--- frontend/node_modules/eslint-plugin-jest/docs/rules/no-mocks-import.md	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/eslint-plugin-jest/docs/rules/no-mocks-import.md	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,27 @@
+# Disallow manually importing from `__mocks__` (`no-mocks-import`)
+
+When using `jest.mock`, your tests (just like the code being tested) should
+import from `./x`, not `./__mocks__/x`. Not following this rule can lead to
+confusion, because you will have multiple instances of the mocked module:
+
+```js
+jest.mock('./x');
+const x1 = require('./x');
+const x2 = require('./__mocks__/x');
+
+test('x', () => {
+  expect(x1).toBe(x2); // fails! They are both instances of `./__mocks__/x`, but not referentially equal
+});
+```
+
+### Rule details
+
+This rule reports imports from a path containing a `__mocks__` component.
+
+Example violations:
+
+```js
+import thing from './__mocks__/index';
+require('./__mocks__/index');
+require('__mocks__');
+```
Index: frontend/node_modules/eslint-plugin-jest/docs/rules/no-restricted-matchers.md
===================================================================
--- frontend/node_modules/eslint-plugin-jest/docs/rules/no-restricted-matchers.md	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/eslint-plugin-jest/docs/rules/no-restricted-matchers.md	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,47 @@
+# Disallow specific matchers & modifiers (`no-restricted-matchers`)
+
+This rule bans specific matchers & modifiers from being used, and can suggest
+alternatives.
+
+## Rule Details
+
+Bans are expressed in the form of a map, with the value being either a string
+message to be shown, or `null` if the default rule message should be used.
+
+Both matchers, modifiers, and chains of the two are checked, allowing for
+specific variations of a matcher to be banned if desired.
+
+By default, this map is empty, meaning no matchers or modifiers are banned.
+
+For example:
+
+```json
+{
+  "jest/no-restricted-matchers": [
+    "error",
+    {
+      "toBeFalsy": null,
+      "resolves": "Use `expect(await promise)` instead.",
+      "not.toHaveBeenCalledWith": null
+    }
+  ]
+}
+```
+
+Examples of **incorrect** code for this rule with the above configuration
+
+```js
+it('is false', () => {
+  expect(a).toBeFalsy();
+});
+
+it('resolves', async () => {
+  await expect(myPromise()).resolves.toBe(true);
+});
+
+describe('when an error happens', () => {
+  it('does not upload the file', async () => {
+    expect(uploadFileMock).not.toHaveBeenCalledWith('file.name');
+  });
+});
+```
Index: frontend/node_modules/eslint-plugin-jest/docs/rules/no-standalone-expect.md
===================================================================
--- frontend/node_modules/eslint-plugin-jest/docs/rules/no-standalone-expect.md	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/eslint-plugin-jest/docs/rules/no-standalone-expect.md	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,99 @@
+# Disallow using `expect` outside of `it` or `test` blocks (`no-standalone-expect`)
+
+Prevents `expect` statements outside of a `test` or `it` block. An `expect`
+within a helper function (but outside of a `test` or `it` block) will not
+trigger this rule.
+
+## Rule Details
+
+This rule aims to eliminate `expect` statements that will not be executed. An
+`expect` inside of a `describe` block but outside of a `test` or `it` block or
+outside a `describe` will not execute and therefore will trigger this rule. It
+is viable, however, to have an `expect` in a helper function that is called from
+within a `test` or `it` block so `expect` statements in a function will not
+trigger this rule.
+
+Statements like `expect.hasAssertions()` will NOT trigger this rule since these
+calls will execute if they are not in a test block.
+
+Examples of **incorrect** code for this rule:
+
+```js
+// in describe
+describe('a test', () => {
+  expect(1).toBe(1);
+});
+
+// below other tests
+describe('a test', () => {
+  it('an it', () => {
+    expect(1).toBe(1);
+  });
+
+  expect(1).toBe(1);
+});
+```
+
+Examples of **correct** code for this rule:
+
+```js
+// in it block
+describe('a test', () => {
+  it('an it', () => {
+    expect(1).toBe(1);
+  });
+});
+
+// in helper function
+describe('a test', () => {
+  const helper = () => {
+    expect(1).toBe(1);
+  };
+
+  it('an it', () => {
+    helper();
+  });
+});
+
+describe('a test', () => {
+  expect.hasAssertions(1);
+});
+```
+
+\*Note that this rule will not trigger if the helper function is never used even
+thought the `expect` will not execute. Rely on a rule like no-unused-vars for
+this case.
+
+### Options
+
+#### `additionalTestBlockFunctions`
+
+This array can be used to specify the names of functions that should also be
+treated as test blocks:
+
+```json
+{
+  "rules": {
+    "jest/no-standalone-expect": [
+      "error",
+      { "additionalTestBlockFunctions": ["each.test"] }
+    ]
+  }
+}
+```
+
+The following is _correct_ when using the above configuration:
+
+```js
+each([
+  [1, 1, 2],
+  [1, 2, 3],
+  [2, 1, 3],
+]).test('returns the result of adding %d to %d', (a, b, expected) => {
+  expect(a + b).toBe(expected);
+});
+```
+
+## When Not To Use It
+
+Don't use this rule on non-jest test files.
Index: frontend/node_modules/eslint-plugin-jest/docs/rules/no-test-prefixes.md
===================================================================
--- frontend/node_modules/eslint-plugin-jest/docs/rules/no-test-prefixes.md	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/eslint-plugin-jest/docs/rules/no-test-prefixes.md	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,32 @@
+# Use `.only` and `.skip` over `f` and `x` (`no-test-prefixes`)
+
+Jest allows you to choose how you want to define focused and skipped tests, with
+multiple permutations for each:
+
+- **only & skip:** `it.only`, `test.only`, `describe.only`, `it.skip`,
+  `test.skip`, `describe.skip`.
+- **'f' & 'x':** `fit`, `fdescribe`, `xit`, `xtest`, `xdescribe`.
+
+This rule enforces usages from the **only & skip** list.
+
+## Rule details
+
+This rule triggers a warning if you use one of the keywords from the **'f' &
+'x'** list to focus/skip a test.
+
+```js
+/*eslint jest/no-test-prefixes: "error"*/
+
+it.only('foo'); // valid
+test.only('foo'); // valid
+describe.only('foo'); // valid
+it.skip('foo'); // valid
+test.skip('foo'); // valid
+describe.skip('foo'); // valid
+
+fit('foo'); // invalid
+fdescribe('foo'); // invalid
+xit('foo'); // invalid
+xtest('foo'); // invalid
+xdescribe('foo'); // invalid
+```
Index: frontend/node_modules/eslint-plugin-jest/docs/rules/no-test-return-statement.md
===================================================================
--- frontend/node_modules/eslint-plugin-jest/docs/rules/no-test-return-statement.md	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/eslint-plugin-jest/docs/rules/no-test-return-statement.md	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,46 @@
+# Disallow explicitly returning from tests (`no-test-return-statement`)
+
+Tests in Jest should be void and not return values.
+
+If you are returning Promises then you should update the test to use
+`async/await`.
+
+## Rule details
+
+This rule triggers a warning if you use a return statement inside a test body.
+
+```js
+/*eslint jest/no-test-return-statement: "error"*/
+
+// valid:
+
+it('noop', function () {});
+
+test('noop', () => {});
+
+test('one arrow', () => expect(1).toBe(1));
+
+test('empty');
+
+test('one', () => {
+  expect(1).toBe(1);
+});
+
+it('one', function () {
+  expect(1).toBe(1);
+});
+
+it('returning a promise', async () => {
+  await new Promise(res => setTimeout(res, 100));
+  expect(1).toBe(1);
+});
+
+// invalid:
+test('return an expect', () => {
+  return expect(1).toBe(1);
+});
+
+it('returning a promise', function () {
+  return new Promise(res => setTimeout(res, 100)).then(() => expect(1).toBe(1));
+});
+```
Index: frontend/node_modules/eslint-plugin-jest/docs/rules/prefer-called-with.md
===================================================================
--- frontend/node_modules/eslint-plugin-jest/docs/rules/prefer-called-with.md	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/eslint-plugin-jest/docs/rules/prefer-called-with.md	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,32 @@
+# Suggest using `toBeCalledWith()` or `toHaveBeenCalledWith()` (`prefer-called-with`)
+
+The `toBeCalled()` matcher is used to assert that a mock function has been
+called one or more times, without checking the arguments passed. The assertion
+is stronger when arguments are also validated using the `toBeCalledWith()`
+matcher. When some arguments are difficult to check, using generic match like
+`expect.anything()` at least enforces number and position of arguments.
+
+This rule warns if the form without argument checking is used, except for `.not`
+enforcing a function has never been called.
+
+## Rule details
+
+The following patterns are warnings:
+
+```js
+expect(someFunction).toBeCalled();
+
+expect(someFunction).toHaveBeenCalled();
+```
+
+The following patterns are not warnings:
+
+```js
+expect(noArgsFunction).toBeCalledWith();
+
+expect(roughArgsFunction).toBeCalledWith(expect.anything(), expect.any(Date));
+
+expect(anyArgsFunction).toBeCalledTimes(1);
+
+expect(uncalledFunction).not.toBeCalled();
+```
Index: frontend/node_modules/eslint-plugin-jest/docs/rules/prefer-comparison-matcher.md
===================================================================
--- frontend/node_modules/eslint-plugin-jest/docs/rules/prefer-comparison-matcher.md	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/eslint-plugin-jest/docs/rules/prefer-comparison-matcher.md	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,55 @@
+# Suggest using the built-in comparison matchers (`prefer-comparison-matcher`)
+
+Jest has a number of built-in matchers for comparing numbers which allow for
+more readable tests and error messages if an expectation fails.
+
+## Rule details
+
+This rule checks for comparisons in tests that could be replaced with one of the
+following built-in comparison matchers:
+
+- `toBeGreaterThan`
+- `toBeGreaterThanOrEqual`
+- `toBeLessThan`
+- `toBeLessThanOrEqual`
+
+Examples of **incorrect** code for this rule:
+
+```js
+expect(x > 5).toBe(true);
+expect(x < 7).not.toEqual(true);
+expect(x <= y).toStrictEqual(true);
+```
+
+Examples of **correct** code for this rule:
+
+```js
+expect(x).toBeGreaterThan(5);
+expect(x).not.toBeLessThanOrEqual(7);
+expect(x).toBeLessThanOrEqual(y);
+
+// special case - see below
+expect(x < 'Carl').toBe(true);
+```
+
+Note that these matchers only work with numbers and bigints, and that the rule
+assumes that any variables on either side of the comparison operator are of one
+of those types - this means if you're using the comparison operator with
+strings, the fix applied by this rule will result in an error.
+
+```js
+expect(myName).toBeGreaterThanOrEqual(theirName); // Matcher error: received value must be a number or bigint
+```
+
+The reason for this is that comparing strings with these operators is expected
+to be very rare and would mean not being able to have an automatic fixer for
+this rule.
+
+If for some reason you are using these operators to compare strings, you can
+disable this rule using an inline
+[configuration comment](https://eslint.org/docs/user-guide/configuring/rules#disabling-rules):
+
+```js
+// eslint-disable-next-line jest/prefer-comparison-matcher
+expect(myName > theirName).toBe(true);
+```
Index: frontend/node_modules/eslint-plugin-jest/docs/rules/prefer-equality-matcher.md
===================================================================
--- frontend/node_modules/eslint-plugin-jest/docs/rules/prefer-equality-matcher.md	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/eslint-plugin-jest/docs/rules/prefer-equality-matcher.md	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,29 @@
+# Suggest using the built-in equality matchers (`prefer-equality-matcher`)
+
+Jest has built-in matchers for expecting equality which allow for more readable
+tests and error messages if an expectation fails.
+
+## Rule details
+
+This rule checks for _strict_ equality checks (`===` & `!==`) in tests that
+could be replaced with one of the following built-in equality matchers:
+
+- `toBe`
+- `toEqual`
+- `toStrictEqual`
+
+Examples of **incorrect** code for this rule:
+
+```js
+expect(x === 5).toBe(true);
+expect(name === 'Carl').not.toEqual(true);
+expect(myObj !== thatObj).toStrictEqual(true);
+```
+
+Examples of **correct** code for this rule:
+
+```js
+expect(x).toBe(5);
+expect(name).not.toEqual('Carl');
+expect(myObj).toStrictEqual(thatObj);
+```
Index: frontend/node_modules/eslint-plugin-jest/docs/rules/prefer-expect-assertions.md
===================================================================
--- frontend/node_modules/eslint-plugin-jest/docs/rules/prefer-expect-assertions.md	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/eslint-plugin-jest/docs/rules/prefer-expect-assertions.md	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,225 @@
+# Suggest using `expect.assertions()` OR `expect.hasAssertions()` (`prefer-expect-assertions`)
+
+Ensure every test to have either `expect.assertions(<number of assertions>)` OR
+`expect.hasAssertions()` as its first expression.
+
+## Rule details
+
+This rule triggers a warning if,
+
+- `expect.assertions(<number of assertions>)` OR `expect.hasAssertions()` is not
+  present as first statement in a test, e.g.:
+
+```js
+test('my test', () => {
+  expect(someThing()).toEqual('foo');
+});
+```
+
+- `expect.assertions(<number of assertions>)` is the first statement in a test
+  where argument passed to `expect.assertions(<number of assertions>)` is not a
+  valid number, e.g.:
+
+```js
+test('my test', () => {
+  expect.assertions('1');
+  expect(someThing()).toEqual('foo');
+});
+```
+
+### Default configuration
+
+The following patterns are considered warnings:
+
+```js
+test('my test', () => {
+  expect.assertions('1');
+  expect(someThing()).toEqual('foo');
+});
+
+test('my test', () => {
+  expect(someThing()).toEqual('foo');
+});
+```
+
+The following patterns would not be considered warnings:
+
+```js
+test('my test', () => {
+  expect.assertions(1);
+  expect(someThing()).toEqual('foo');
+});
+
+test('my test', () => {
+  expect.hasAssertions();
+  expect(someThing()).toEqual('foo');
+});
+```
+
+## Options
+
+This rule can be configured to only check tests that match certain patterns that
+typically look like `expect` calls might be missed, such as in promises or
+loops.
+
+By default, none of these options are enabled meaning the rule checks _every_
+test for a call to either `expect.hasAssertions` or `expect.assertions`. If any
+of the options are enabled the rule checks any test that matches _at least one_
+of the patterns represented by the enabled options (think "OR" rather than
+"AND").
+
+#### `onlyFunctionsWithAsyncKeyword`
+
+When `true`, this rule will only warn for tests that use the `async` keyword.
+
+```json
+{
+  "rules": {
+    "jest/prefer-expect-assertions": [
+      "warn",
+      { "onlyFunctionsWithAsyncKeyword": true }
+    ]
+  }
+}
+```
+
+When `onlyFunctionsWithAsyncKeyword` option is set to `true`, the following
+pattern would be a warning:
+
+```js
+test('my test', async () => {
+  const result = await someAsyncFunc();
+  expect(result).toBe('foo');
+});
+```
+
+While the following patterns would not be considered warnings:
+
+```js
+test('my test', () => {
+  const result = someFunction();
+  expect(result).toBe('foo');
+});
+
+test('my test', async () => {
+  expect.assertions(1);
+  const result = await someAsyncFunc();
+  expect(result).toBe('foo');
+});
+```
+
+#### `onlyFunctionsWithExpectInLoop`
+
+When `true`, this rule will only warn for tests that have `expect` calls within
+a native loop.
+
+```json
+{
+  "rules": {
+    "jest/prefer-expect-assertions": [
+      "warn",
+      { "onlyFunctionsWithAsyncKeyword": true }
+    ]
+  }
+}
+```
+
+Examples of **incorrect** code when `'onlyFunctionsWithExpectInLoop'` is `true`:
+
+```js
+describe('getNumbers', () => {
+  it('only returns numbers that are greater than zero', () => {
+    const numbers = getNumbers();
+
+    for (const number in numbers) {
+      expect(number).toBeGreaterThan(0);
+    }
+  });
+});
+```
+
+Examples of **correct** code when `'onlyFunctionsWithExpectInLoop'` is `true`:
+
+```js
+describe('getNumbers', () => {
+  it('only returns numbers that are greater than zero', () => {
+    expect.hasAssertions();
+
+    const numbers = getNumbers();
+
+    for (const number in numbers) {
+      expect(number).toBeGreaterThan(0);
+    }
+  });
+
+  it('returns more than one number', () => {
+    expect(getNumbers().length).toBeGreaterThan(1);
+  });
+});
+```
+
+#### `onlyFunctionsWithExpectInCallback`
+
+When `true`, this rule will only warn for tests that have `expect` calls within
+a callback.
+
+```json
+{
+  "rules": {
+    "jest/prefer-expect-assertions": [
+      "warn",
+      { "onlyFunctionsWithExpectInCallback": true }
+    ]
+  }
+}
+```
+
+Examples of **incorrect** code when `'onlyFunctionsWithExpectInCallback'` is
+`true`:
+
+```js
+describe('getNumbers', () => {
+  it('only returns numbers that are greater than zero', () => {
+    const numbers = getNumbers();
+
+    getNumbers().forEach(number => {
+      expect(number).toBeGreaterThan(0);
+    });
+  });
+});
+
+describe('/users', () => {
+  it.each([1, 2, 3])('returns ok', id => {
+    client.get(`/users/${id}`, response => {
+      expect(response.status).toBe(200);
+    });
+  });
+});
+```
+
+Examples of **correct** code when `'onlyFunctionsWithExpectInCallback'` is
+`true`:
+
+```js
+describe('getNumbers', () => {
+  it('only returns numbers that are greater than zero', () => {
+    expect.hasAssertions();
+
+    const numbers = getNumbers();
+
+    getNumbers().forEach(number => {
+      expect(number).toBeGreaterThan(0);
+    });
+  });
+});
+
+describe('/users', () => {
+  it.each([1, 2, 3])('returns ok', id => {
+    expect.assertions(3);
+
+    client.get(`/users/${id}`, response => {
+      expect(response.status).toBe(200);
+    });
+  });
+});
+```
Index: frontend/node_modules/eslint-plugin-jest/docs/rules/prefer-expect-resolves.md
===================================================================
--- frontend/node_modules/eslint-plugin-jest/docs/rules/prefer-expect-resolves.md	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/eslint-plugin-jest/docs/rules/prefer-expect-resolves.md	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,53 @@
+# Prefer `await expect(...).resolves` over `expect(await ...)` syntax (`prefer-expect-resolves`)
+
+When working with promises, there are two primary ways you can test the resolved
+value:
+
+1. use the `resolve` modifier on `expect`
+   (`await expect(...).resolves.<matcher>` style)
+2. `await` the promise and assert against its result
+   (`expect(await ...).<matcher>` style)
+
+While the second style is arguably less dependent on `jest`, if the promise
+rejects it will be treated as a general error, resulting in less predictable
+behaviour and output from `jest`.
+
+Additionally, favoring the first style ensures consistency with its `rejects`
+counterpart, as there is no way of "awaiting" a rejection.
+
+## Rule details
+
+This rule triggers a warning if an `await` is done within an `expect`, and
+recommends using `resolves` instead.
+
+Examples of **incorrect** code for this rule
+
+```js
+it('passes', async () => {
+  expect(await someValue()).toBe(true);
+});
+
+it('is true', async () => {
+  const myPromise = Promise.resolve(true);
+
+  expect(await myPromise).toBe(true);
+});
+```
+
+Examples of **correct** code for this rule
+
+```js
+it('passes', async () => {
+  await expect(someValue()).resolves.toBe(true);
+});
+
+it('is true', async () => {
+  const myPromise = Promise.resolve(true);
+
+  await expect(myPromise).resolves.toBe(true);
+});
+
+it('errors', async () => {
+  await expect(Promise.rejects('oh noes!')).rejects.toThrow('oh noes!');
+});
+```
Index: frontend/node_modules/eslint-plugin-jest/docs/rules/prefer-hooks-on-top.md
===================================================================
--- frontend/node_modules/eslint-plugin-jest/docs/rules/prefer-hooks-on-top.md	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/eslint-plugin-jest/docs/rules/prefer-hooks-on-top.md	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,120 @@
+# Suggest having hooks before any test cases (`prefer-hooks-on-top`)
+
+While hooks can be setup anywhere in a test file, they are always called in a
+specific order which means it can be confusing if they're intermixed with test
+cases.
+
+This rule helps to ensure that hooks are always defined before test cases.
+
+## Rule Details
+
+Examples of **incorrect** code for this rule
+
+```js
+/* eslint jest/prefer-hooks-on-top: "error" */
+
+describe('foo', () => {
+  beforeEach(() => {
+    seedMyDatabase();
+  });
+
+  it('accepts this input', () => {
+    // ...
+  });
+
+  beforeAll(() => {
+    createMyDatabase();
+  });
+
+  it('returns that value', () => {
+    // ...
+  });
+
+  describe('when the database has specific values', () => {
+    const specificValue = '...';
+
+    beforeEach(() => {
+      seedMyDatabase(specificValue);
+    });
+
+    it('accepts that input', () => {
+      // ...
+    });
+
+    it('throws an error', () => {
+      // ...
+    });
+
+    afterEach(() => {
+      clearLogger();
+    });
+    beforeEach(() => {
+      mockLogger();
+    });
+
+    it('logs a message', () => {
+      // ...
+    });
+  });
+
+  afterAll(() => {
+    removeMyDatabase();
+  });
+});
+```
+
+Examples of **correct** code for this rule
+
+```js
+/* eslint jest/prefer-hooks-on-top: "error" */
+
+describe('foo', () => {
+  beforeAll(() => {
+    createMyDatabase();
+  });
+
+  beforeEach(() => {
+    seedMyDatabase();
+  });
+
+  afterAll(() => {
+    clearMyDatabase();
+  });
+
+  it('accepts this input', () => {
+    // ...
+  });
+
+  it('returns that value', () => {
+    // ...
+  });
+
+  describe('when the database has specific values', () => {
+    const specificValue = '...';
+
+    beforeEach(() => {
+      seedMyDatabase(specificValue);
+    });
+
+    beforeEach(() => {
+      mockLogger();
+    });
+
+    afterEach(() => {
+      clearLogger();
+    });
+
+    it('accepts that input', () => {
+      // ...
+    });
+
+    it('throws an error', () => {
+      // ...
+    });
+
+    it('logs a message', () => {
+      // ...
+    });
+  });
+});
+```
Index: frontend/node_modules/eslint-plugin-jest/docs/rules/prefer-lowercase-title.md
===================================================================
--- frontend/node_modules/eslint-plugin-jest/docs/rules/prefer-lowercase-title.md	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/eslint-plugin-jest/docs/rules/prefer-lowercase-title.md	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,106 @@
+# Enforce lowercase test names (`prefer-lowercase-title`)
+
+## Rule details
+
+Enforce `it`, `test` and `describe` to have descriptions that begin with a
+lowercase letter. This provides more readable test failures. This rule is not
+enabled by default.
+
+The following pattern is considered a warning:
+
+```js
+it('Adds 1 + 2 to equal 3', () => {
+  expect(sum(1, 2)).toBe(3);
+});
+```
+
+The following pattern is not considered a warning:
+
+```js
+it('adds 1 + 2 to equal 3', () => {
+  expect(sum(1, 2)).toBe(3);
+});
+```
+
+## Options
+
+```json
+{
+  "jest/prefer-lowercase-title": [
+    "error",
+    {
+      "ignore": ["describe", "test"]
+    }
+  ]
+}
+```
+
+### `ignore`
+
+This array option controls which Jest functions are checked by this rule. There
+are three possible values:
+
+- `"describe"`
+- `"test"`
+- `"it"`
+
+By default, none of these options are enabled (the equivalent of
+`{ "ignore": [] }`).
+
+Example of **correct** code for the `{ "ignore": ["describe"] }` option:
+
+```js
+/* eslint jest/prefer-lowercase-title: ["error", { "ignore": ["describe"] }] */
+
+describe('Uppercase description');
+```
+
+Example of **correct** code for the `{ "ignore": ["test"] }` option:
+
+```js
+/* eslint jest/prefer-lowercase-title: ["error", { "ignore": ["test"] }] */
+
+test('Uppercase description');
+```
+
+Example of **correct** code for the `{ "ignore": ["it"] }` option:
+
+```js
+/* eslint jest/prefer-lowercase-title: ["error", { "ignore": ["it"] }] */
+
+it('Uppercase description');
+```
+
+### `allowedPrefixes`
+
+This array option allows specifying prefixes which contain capitals that titles
+can start with. This can be useful when writing tests for api endpoints, where
+you'd like to prefix with the HTTP method.
+
+By default, nothing is allowed (the equivalent of `{ "allowedPrefixes": [] }`).
+
+Example of **correct** code for the `{ "allowedPrefixes": ["GET"] }` option:
+
+```js
+/* eslint jest/prefer-lowercase-title: ["error", { "allowedPrefixes": ["GET"] }] */
+
+describe('GET /live');
+```
+
+### `ignoreTopLevelDescribe`
+
+This option can be set to allow only the top-level `describe` blocks to have a
+title starting with an upper-case letter.
+
+Example of **correct** code for the `{ "ignoreTopLevelDescribe": true }` option:
+
+```js
+/* eslint jest/prefer-lowercase-title: ["error", { "ignoreTopLevelDescribe": true }] */
+describe('MyClass', () => {
+  describe('#myMethod', () => {
+    it('does things', () => {
+      //
+    });
+  });
+});
+```
Index: frontend/node_modules/eslint-plugin-jest/docs/rules/prefer-spy-on.md
===================================================================
--- frontend/node_modules/eslint-plugin-jest/docs/rules/prefer-spy-on.md	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/eslint-plugin-jest/docs/rules/prefer-spy-on.md	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,41 @@
+# Suggest using `jest.spyOn()` (`prefer-spy-on`)
+
+When mocking a function by overwriting a property you have to manually restore
+the original implementation when cleaning up. When using `jest.spyOn()` Jest
+keeps track of changes, and they can be restored with `jest.restoreAllMocks()`,
+`mockFn.mockRestore()` or by setting `restoreMocks` to `true` in the Jest
+config.
+
+Note: The mock created by `jest.spyOn()` still behaves the same as the original
+function. The original function can be overwritten with
+`mockFn.mockImplementation()` or by some of the
+[other mock functions](https://jestjs.io/docs/en/mock-function-api).
+
+```js
+Date.now = jest.fn(); // Original behaviour lost, returns undefined
+
+jest.spyOn(Date, 'now'); // Turned into a mock function but behaviour hasn't changed
+jest.spyOn(Date, 'now').mockImplementation(() => 10); // Will always return 10
+jest.spyOn(Date, 'now').mockReturnValue(10); // Will always return 10
+```
+
+## Rule details
+
+This rule triggers a warning if an object's property is overwritten with a jest
+mock.
+
+### Default configuration
+
+The following patterns are considered warnings:
+
+```js
+Date.now = jest.fn();
+Date.now = jest.fn(() => 10);
+```
+
+These patterns would not be considered warnings:
+
+```js
+jest.spyOn(Date, 'now');
+jest.spyOn(Date, 'now').mockImplementation(() => 10);
+```
Index: frontend/node_modules/eslint-plugin-jest/docs/rules/prefer-strict-equal.md
===================================================================
--- frontend/node_modules/eslint-plugin-jest/docs/rules/prefer-strict-equal.md	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/eslint-plugin-jest/docs/rules/prefer-strict-equal.md	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,24 @@
+# Suggest using `toStrictEqual()` (`prefer-strict-equal`)
+
+`toStrictEqual` not only checks that two objects contain the same data but also
+that they have the same structure. It is common to expect objects to not only
+have identical values but also to have identical keys. A stricter equality will
+catch cases where two objects do not have identical keys.
+
+## Rule details
+
+This rule triggers a warning if `toEqual()` is used to assert equality.
+
+### Default configuration
+
+The following pattern is considered warning:
+
+```js
+expect({ a: 'a', b: undefined }).toEqual({ a: 'a' }); // true
+```
+
+The following pattern is not warning:
+
+```js
+expect({ a: 'a', b: undefined }).toStrictEqual({ a: 'a' }); // false
+```
Index: frontend/node_modules/eslint-plugin-jest/docs/rules/prefer-to-be.md
===================================================================
--- frontend/node_modules/eslint-plugin-jest/docs/rules/prefer-to-be.md	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/eslint-plugin-jest/docs/rules/prefer-to-be.md	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,53 @@
+# Suggest using `toBe()` for primitive literals (`prefer-to-be`)
+
+When asserting against primitive literals such as numbers and strings, the
+equality matchers all operate the same, but read slightly differently in code.
+
+This rule recommends using the `toBe` matcher in these situations, as it forms
+the most grammatically natural sentence. For `null`, `undefined`, and `NaN` this
+rule recommends using their specific `toBe` matchers, as they give better error
+messages as well.
+
+## Rule details
+
+This rule triggers a warning if `toEqual()` or `toStrictEqual()` are used to
+assert a primitive literal value such as numbers, strings, and booleans.
+
+The following patterns are considered warnings:
+
+```js
+expect(value).not.toEqual(5);
+expect(getMessage()).toStrictEqual('hello world');
+expect(loadMessage()).resolves.toEqual('hello world');
+```
+
+The following pattern is not warning:
+
+```js
+expect(value).not.toBe(5);
+expect(getMessage()).toBe('hello world');
+expect(loadMessage()).resolves.toBe('hello world');
+expect(didError).not.toBe(true);
+
+expect(catchError()).toStrictEqual({ message: 'oh noes!' });
+```
+
+For `null`, `undefined`, and `NaN`, this rule triggers a warning if `toBe` is
+used to assert against those literal values instead of their more specific
+`toBe` counterparts:
+
+```js
+expect(value).not.toBe(undefined);
+expect(getMessage()).toBe(null);
+expect(countMessages()).resolves.not.toBe(NaN);
+```
+
+The following pattern is not warning:
+
+```js
+expect(value).toBeDefined();
+expect(getMessage()).toBeNull();
+expect(countMessages()).resolves.not.toBeNaN();
+
+expect(catchError()).toStrictEqual({ message: undefined });
+```
Index: frontend/node_modules/eslint-plugin-jest/docs/rules/prefer-to-contain.md
===================================================================
--- frontend/node_modules/eslint-plugin-jest/docs/rules/prefer-to-contain.md	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/eslint-plugin-jest/docs/rules/prefer-to-contain.md	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,45 @@
+# Suggest using `toContain()` (`prefer-to-contain`)
+
+In order to have a better failure message, `toContain()` should be used upon
+asserting expectations on an array containing an object.
+
+## Rule details
+
+This rule triggers a warning if `toBe()`, `toEqual()` or `toStrictEqual()` is
+used to assert object inclusion in an array
+
+```js
+expect(a.includes(b)).toBe(true);
+```
+
+```js
+expect(a.includes(b)).not.toBe(true);
+```
+
+```js
+expect(a.includes(b)).toBe(false);
+```
+
+### Default configuration
+
+The following patterns are considered warnings:
+
+```js
+expect(a.includes(b)).toBe(true);
+
+expect(a.includes(b)).not.toBe(true);
+
+expect(a.includes(b)).toBe(false);
+
+expect(a.includes(b)).toEqual(true);
+
+expect(a.includes(b)).toStrictEqual(true);
+```
+
+The following patterns are not considered warnings:
+
+```js
+expect(a).toContain(b);
+
+expect(a).not.toContain(b);
+```
Index: frontend/node_modules/eslint-plugin-jest/docs/rules/prefer-to-have-length.md
===================================================================
--- frontend/node_modules/eslint-plugin-jest/docs/rules/prefer-to-have-length.md	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/eslint-plugin-jest/docs/rules/prefer-to-have-length.md	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,33 @@
+# Suggest using `toHaveLength()` (`prefer-to-have-length`)
+
+In order to have a better failure message, `toHaveLength()` should be used upon
+asserting expectations on objects length property.
+
+## Rule details
+
+This rule triggers a warning if `toBe()`, `toEqual()` or `toStrictEqual()` is
+used to assert objects length property.
+
+```js
+expect(files.length).toBe(1);
+```
+
+This rule is enabled by default.
+
+### Default configuration
+
+The following patterns are considered warnings:
+
+```js
+expect(files.length).toBe(1);
+
+expect(files.length).toEqual(1);
+
+expect(files.length).toStrictEqual(1);
+```
+
+The following pattern is not warning:
+
+```js
+expect(files).toHaveLength(1);
+```
Index: frontend/node_modules/eslint-plugin-jest/docs/rules/prefer-todo.md
===================================================================
--- frontend/node_modules/eslint-plugin-jest/docs/rules/prefer-todo.md	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/eslint-plugin-jest/docs/rules/prefer-todo.md	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,28 @@
+# Suggest using `test.todo` (`prefer-todo`)
+
+When test cases are empty then it is better to mark them as `test.todo` as it
+will be highlighted in the summary output.
+
+## Rule details
+
+This rule triggers a warning if empty test cases are used without 'test.todo'.
+
+```js
+test('i need to write this test');
+```
+
+### Default configuration
+
+The following pattern is considered warning:
+
+```js
+test('i need to write this test'); // Unimplemented test case
+test('i need to write this test', () => {}); // Empty test case body
+test.skip('i need to write this test', () => {}); // Empty test case body
+```
+
+The following pattern is not warning:
+
+```js
+test.todo('i need to write this test');
+```
Index: frontend/node_modules/eslint-plugin-jest/docs/rules/require-hook.md
===================================================================
--- frontend/node_modules/eslint-plugin-jest/docs/rules/require-hook.md	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/eslint-plugin-jest/docs/rules/require-hook.md	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,187 @@
+# Require setup and teardown code to be within a hook (`require-hook`)
+
+Often while writing tests you have some setup work that needs to happen before
+tests run, and you have some finishing work that needs to happen after tests
+run. Jest provides helper functions to handle this.
+
+It's common when writing tests to need to perform setup work that needs to
+happen before tests run, and finishing work after tests run.
+
+Because Jest executes all `describe` handlers in a test file _before_ it
+executes any of the actual tests, it's important to ensure setup and teardown
+work is done inside `before*` and `after*` handlers respectively, rather than
+inside the `describe` blocks.
+
+## Rule details
+
+This rule flags any expression that is either at the toplevel of a test file or
+directly within the body of a `describe`, _except_ for the following:
+
+- `import` statements
+- `const` variables
+- `let` _declarations_, and initializations to `null` or `undefined`
+- Classes
+- Types
+- Calls to the standard Jest globals
+
+This rule flags any function calls within test files that are directly within
+the body of a `describe`, and suggests wrapping them in one of the four
+lifecycle hooks.
+
+Here is a slightly contrived test file showcasing some common cases that would
+be flagged:
+
+```js
+import { database, isCity } from '../database';
+import { Logger } from '../../../src/Logger';
+import { loadCities } from '../api';
+
+jest.mock('../api');
+
+const initializeCityDatabase = () => {
+  database.addCity('Vienna');
+  database.addCity('San Juan');
+  database.addCity('Wellington');
+};
+
+const clearCityDatabase = () => {
+  database.clear();
+};
+
+initializeCityDatabase();
+
+test('that persists cities', () => {
+  expect(database.cities.length).toHaveLength(3);
+});
+
+test('city database has Vienna', () => {
+  expect(isCity('Vienna')).toBeTruthy();
+});
+
+test('city database has San Juan', () => {
+  expect(isCity('San Juan')).toBeTruthy();
+});
+
+describe('when loading cities from the api', () => {
+  let consoleWarnSpy = jest.spyOn(console, 'warn');
+
+  loadCities.mockResolvedValue(['Wellington', 'London']);
+
+  it('does not duplicate cities', async () => {
+    await database.loadCities();
+
+    expect(database.cities).toHaveLength(4);
+  });
+
+  it('logs any duplicates', async () => {
+    await database.loadCities();
+
+    expect(consoleWarnSpy).toHaveBeenCalledWith(
+      'Ignored duplicate cities: Wellington',
+    );
+  });
+});
+
+clearCityDatabase();
+```
+
+Here is the same slightly contrived test file showcasing the same common cases
+but in ways that would be **not** flagged:
+
+```js
+import { database, isCity } from '../database';
+import { Logger } from '../../../src/Logger';
+import { loadCities } from '../api';
+
+jest.mock('../api');
+
+const initializeCityDatabase = () => {
+  database.addCity('Vienna');
+  database.addCity('San Juan');
+  database.addCity('Wellington');
+};
+
+const clearCityDatabase = () => {
+  database.clear();
+};
+
+beforeEach(() => {
+  initializeCityDatabase();
+});
+
+test('that persists cities', () => {
+  expect(database.cities.length).toHaveLength(3);
+});
+
+test('city database has Vienna', () => {
+  expect(isCity('Vienna')).toBeTruthy();
+});
+
+test('city database has San Juan', () => {
+  expect(isCity('San Juan')).toBeTruthy();
+});
+
+describe('when loading cities from the api', () => {
+  let consoleWarnSpy;
+
+  beforeEach(() => {
+    consoleWarnSpy = jest.spyOn(console, 'warn');
+    loadCities.mockResolvedValue(['Wellington', 'London']);
+  });
+
+  it('does not duplicate cities', async () => {
+    await database.loadCities();
+
+    expect(database.cities).toHaveLength(4);
+  });
+
+  it('logs any duplicates', async () => {
+    await database.loadCities();
+
+    expect(consoleWarnSpy).toHaveBeenCalledWith(
+      'Ignored duplicate cities: Wellington',
+    );
+  });
+});
+
+afterEach(() => {
+  clearCityDatabase();
+});
+```
+
+## Options
+
+If there are methods that you want to call outside of hooks and tests, you can
+mark them as allowed using the `allowedFunctionCalls` option.
+
+```json
+{
+  "jest/require-hook": [
+    "error",
+    {
+      "allowedFunctionCalls": ["enableAutoDestroy"]
+    }
+  ]
+}
+```
+
+Examples of **correct** code when using
+`{ "allowedFunctionCalls": ["enableAutoDestroy"] }` option:
+
+```js
+/* eslint jest/require-hook: ["error", { "allowedFunctionCalls": ["enableAutoDestroy"] }] */
+
+import { enableAutoDestroy, mount } from '@vue/test-utils';
+import { initDatabase, tearDownDatabase } from './databaseUtils';
+
+enableAutoDestroy(afterEach);
+
+beforeEach(initDatabase);
+afterEach(tearDownDatabase);
+
+describe('Foo', () => {
+  test('always returns 42', () => {
+    expect(global.getAnswer()).toBe(42);
+  });
+});
+```
Index: frontend/node_modules/eslint-plugin-jest/docs/rules/require-to-throw-message.md
===================================================================
--- frontend/node_modules/eslint-plugin-jest/docs/rules/require-to-throw-message.md	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/eslint-plugin-jest/docs/rules/require-to-throw-message.md	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,41 @@
+# Require a message for `toThrow()` (`require-to-throw-message`)
+
+`toThrow()` (and its alias `toThrowError()`) is used to check if an error is
+thrown by a function call, such as in `expect(() => a()).toThrow()`. However, if
+no message is defined, then the test will pass for any thrown error. Requiring a
+message ensures that the intended error is thrown.
+
+## Rule details
+
+This rule triggers a warning if `toThrow()` or `toThrowError()` is used without
+an error message.
+
+### Default configuration
+
+The following patterns are considered warnings:
+
+```js
+test('all the things', async () => {
+  expect(() => a()).toThrow();
+
+  expect(() => a()).toThrowError();
+
+  await expect(a()).rejects.toThrow();
+
+  await expect(a()).rejects.toThrowError();
+});
+```
+
+The following patterns are not considered warnings:
+
+```js
+test('all the things', async () => {
+  expect(() => a()).toThrow('a');
+
+  expect(() => a()).toThrowError('a');
+
+  await expect(a()).rejects.toThrow('a');
+
+  await expect(a()).rejects.toThrowError('a');
+});
+```
Index: frontend/node_modules/eslint-plugin-jest/docs/rules/require-top-level-describe.md
===================================================================
--- frontend/node_modules/eslint-plugin-jest/docs/rules/require-top-level-describe.md	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/eslint-plugin-jest/docs/rules/require-top-level-describe.md	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,80 @@
+# Require test cases and hooks to be inside a `describe` block (`require-top-level-describe`)
+
+Jest allows you to organise your test files the way you want it. However, the
+more your codebase grows, the more it becomes hard to navigate in your test
+files. This rule makes sure you provide at least a top-level `describe` block in
+your test file.
+
+## Rule Details
+
+This rule triggers a warning if a test case (`test` and `it`) or a hook
+(`beforeAll`, `beforeEach`, `afterEach`, `afterAll`) is not located in a
+top-level `describe` block.
+
+The following patterns are considered warnings:
+
+```js
+// Above a describe block
+test('my test', () => {});
+describe('test suite', () => {
+  it('test', () => {});
+});
+
+// Below a describe block
+describe('test suite', () => {});
+test('my test', () => {});
+
+// Same for hooks
+beforeAll('my beforeAll', () => {});
+describe('test suite', () => {});
+afterEach('my afterEach', () => {});
+```
+
+The following patterns are **not** considered warnings:
+
+```js
+// In a describe block
+describe('test suite', () => {
+  test('my test', () => {});
+});
+
+// In a nested describe block
+describe('test suite', () => {
+  test('my test', () => {});
+  describe('another test suite', () => {
+    test('my other test', () => {});
+  });
+});
+```
+
+You can also enforce a limit on the number of describes allowed at the top-level
+using the `maxNumberOfTopLevelDescribes` option:
+
+```json
+{
+  "jest/require-top-level-describe": [
+    "error",
+    {
+      "maxNumberOfTopLevelDescribes": 2
+    }
+  ]
+}
+```
+
+Examples of **incorrect** code with the above config:
+
+```js
+describe('test suite', () => {
+  it('test', () => {});
+});
+
+describe('test suite', () => {});
+
+describe('test suite', () => {});
+```
+
+This option defaults to `Infinity`, allowing any number of top-level describes.
+
+## When Not To Use It
+
+Don't use this rule on non-jest test files.
Index: frontend/node_modules/eslint-plugin-jest/docs/rules/unbound-method.md
===================================================================
--- frontend/node_modules/eslint-plugin-jest/docs/rules/unbound-method.md	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/eslint-plugin-jest/docs/rules/unbound-method.md	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,54 @@
+# Enforces unbound methods are called with their expected scope (`unbound-method`)
+
+## Rule Details
+
+This rule extends the base [`@typescript-eslint/unbound-method`][original-rule]
+rule, meaning you must depend on `@typescript-eslint/eslint-plugin` for it to
+work. It adds support for understanding when it's ok to pass an unbound method
+to `expect` calls.
+
+See the [`@typescript-eslint` documentation][original-rule] for more details on
+the `unbound-method` rule.
+
+Note that while this rule requires type information to work, it will fail
+silently when not available allowing you to safely enable it on projects that
+are not using TypeScript.
+
+## How to use
+
+```json5
+{
+  parser: '@typescript-eslint/parser',
+  parserOptions: {
+    project: 'tsconfig.json',
+    ecmaVersion: 2020,
+    sourceType: 'module',
+  },
+  overrides: [
+    {
+      files: ['test/**'],
+      plugins: ['jest'],
+      rules: {
+        // you should turn the original rule off *only* for test files
+        '@typescript-eslint/unbound-method': 'off',
+        'jest/unbound-method': 'error',
+      },
+    },
+  ],
+  rules: {
+    '@typescript-eslint/unbound-method': 'error',
+  },
+}
+```
+
+This rule should be applied to your test files in place of the original rule,
+which should be applied to the rest of your codebase.
+
+## Options
+
+See [`@typescript-eslint/unbound-method`][original-rule] options.
+
+<sup>Taken with ❤️ [from `@typescript-eslint` core][original-rule]</sup>
+
+[original-rule]:
+  https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/unbound-method.md
Index: frontend/node_modules/eslint-plugin-jest/docs/rules/valid-describe-callback.md
===================================================================
--- frontend/node_modules/eslint-plugin-jest/docs/rules/valid-describe-callback.md	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/eslint-plugin-jest/docs/rules/valid-describe-callback.md	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,62 @@
+# Enforce valid `describe()` callback (`valid-describe-callback`)
+
+Using an improper `describe()` callback function can lead to unexpected test
+errors.
+
+## Rule Details
+
+This rule validates that the second parameter of a `describe()` function is a
+callback function. This callback function:
+
+- should not be
+  [async](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function)
+- should not contain any parameters
+- should not contain any `return` statements
+
+The following `describe` function aliases are also validated:
+
+- `describe`
+- `describe.only`
+- `describe.skip`
+- `fdescribe`
+- `xdescribe`
+
+The following patterns are considered warnings:
+
+```js
+// Async callback functions are not allowed
+describe('myFunction()', async () => {
+  // ...
+});
+
+// Callback function parameters are not allowed
+describe('myFunction()', done => {
+  // ...
+});
+
+//
+describe('myFunction', () => {
+  // No return statements are allowed in block of a callback function
+  return Promise.resolve().then(() => {
+    it('breaks', () => {
+      throw new Error('Fail');
+    });
+  });
+});
+
+// Returning a value from a describe block is not allowed
+describe('myFunction', () =>
+  it('returns a truthy value', () => {
+    expect(myFunction()).toBeTruthy();
+  }));
+```
+
+The following patterns are not considered warnings:
+
+```js
+describe('myFunction()', () => {
+  it('returns a truthy value', () => {
+    expect(myFunction()).toBeTruthy();
+  });
+});
+```
Index: frontend/node_modules/eslint-plugin-jest/docs/rules/valid-expect-in-promise.md
===================================================================
--- frontend/node_modules/eslint-plugin-jest/docs/rules/valid-expect-in-promise.md	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/eslint-plugin-jest/docs/rules/valid-expect-in-promise.md	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,72 @@
+# Ensure promises that have expectations in their chain are valid (`valid-expect-in-promise`)
+
+Ensure promises that include expectations are returned or awaited.
+
+## Rule details
+
+This rule flags any promises within the body of a test that include expectations
+that have either not been returned or awaited.
+
+The following patterns is considered warning:
+
+```js
+it('promises a person', () => {
+  api.getPersonByName('bob').then(person => {
+    expect(person).toHaveProperty('name', 'Bob');
+  });
+});
+
+it('promises a counted person', () => {
+  const promise = api.getPersonByName('bob').then(person => {
+    expect(person).toHaveProperty('name', 'Bob');
+  });
+
+  promise.then(() => {
+    expect(analytics.gottenPeopleCount).toBe(1);
+  });
+});
+
+it('promises multiple people', () => {
+  const firstPromise = api.getPersonByName('bob').then(person => {
+    expect(person).toHaveProperty('name', 'Bob');
+  });
+  const secondPromise = api.getPersonByName('alice').then(person => {
+    expect(person).toHaveProperty('name', 'Alice');
+  });
+
+  return Promise.any([firstPromise, secondPromise]);
+});
+```
+
+The following pattern is not warning:
+
+```js
+it('promises a person', async () => {
+  await api.getPersonByName('bob').then(person => {
+    expect(person).toHaveProperty('name', 'Bob');
+  });
+});
+
+it('promises a counted person', () => {
+  let promise = api.getPersonByName('bob').then(person => {
+    expect(person).toHaveProperty('name', 'Bob');
+  });
+
+  promise = promise.then(() => {
+    expect(analytics.gottenPeopleCount).toBe(1);
+  });
+
+  return promise;
+});
+
+it('promises multiple people', () => {
+  const firstPromise = api.getPersonByName('bob').then(person => {
+    expect(person).toHaveProperty('name', 'Bob');
+  });
+  const secondPromise = api.getPersonByName('alice').then(person => {
+    expect(person).toHaveProperty('name', 'Alice');
+  });
+
+  return Promise.allSettled([firstPromise, secondPromise]);
+});
+```
Index: frontend/node_modules/eslint-plugin-jest/docs/rules/valid-expect.md
===================================================================
--- frontend/node_modules/eslint-plugin-jest/docs/rules/valid-expect.md	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/eslint-plugin-jest/docs/rules/valid-expect.md	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,144 @@
+# Enforce valid `expect()` usage (`valid-expect`)
+
+Ensure `expect()` is called with a single argument and there is an actual
+expectation made.
+
+## Rule details
+
+This rule triggers a warning if `expect()` is called with more than one argument
+or without arguments. It would also issue a warning if there is nothing called
+on `expect()`, e.g.:
+
+```js
+expect();
+expect('something');
+```
+
+or when a matcher function was not called, e.g.:
+
+```js
+expect(true).toBeDefined;
+```
+
+or when an async assertion was not `await`ed or returned, e.g.:
+
+```js
+expect(Promise.resolve('Hi!')).resolves.toBe('Hi!');
+```
+
+This rule is enabled by default.
+
+## Options
+
+```json5
+{
+  type: 'object',
+  properties: {
+    alwaysAwait: {
+      type: 'boolean',
+      default: false,
+    },
+    asyncMatchers: {
+      type: 'array',
+      items: { type: 'string' },
+      default: ['toResolve', 'toReject'],
+    },
+    minArgs: {
+      type: 'number',
+      minimum: 1,
+    },
+    maxArgs: {
+      type: 'number',
+      minimum: 1,
+    },
+  },
+  additionalProperties: false,
+}
+```
+
+### `alwaysAwait`
+
+Enforces to use `await` inside block statements. Using `return` will trigger a
+warning. Returning one line statements with arrow functions is _always allowed_.
+
+Examples of **incorrect** code for the { "alwaysAwait": **true** } option:
+
+```js
+// alwaysAwait: true
+test('test1', async () => {
+  await expect(Promise.resolve(2)).resolves.toBeDefined();
+  return expect(Promise.resolve(1)).resolves.toBe(1); // `return` statement will trigger a warning
+});
+```
+
+Examples of **correct** code for the { "alwaysAwait": **true** } option:
+
+```js
+// alwaysAwait: true
+test('test1', async () => {
+  await expect(Promise.resolve(2)).resolves.toBeDefined();
+  await expect(Promise.resolve(1)).resolves.toBe(1);
+});
+
+test('test2', () => expect(Promise.resolve(2)).resolves.toBe(2));
+```
+
+### `asyncMatchers`
+
+Allows specifying which matchers return promises, and so should be considered
+async when checking if an `expect` should be returned or awaited.
+
+By default, this has a list of all the async matchers provided by
+`jest-extended` (namely, `toResolve` and `toReject`).
+
+### `minArgs` & `maxArgs`
+
+Enforces the minimum and maximum number of arguments that `expect` can take, and
+is required to take.
+
+Both of these properties have a default value of `1`, which is the number of
+arguments supported by vanilla `expect`.
+
+This is useful when you're using libraries that increase the number of arguments
+supported by `expect`, such as
+[`jest-expect-message`](https://www.npmjs.com/package/jest-expect-message).
+
+### Default configuration
+
+The following patterns are considered warnings:
+
+```js
+test('all the things', async () => {
+  expect();
+  expect().toEqual('something');
+  expect('something', 'else');
+  expect('something');
+  await expect('something');
+  expect(true).toBeDefined;
+  expect(Promise.resolve('hello')).resolves;
+  expect(Promise.resolve('hello')).resolves.toEqual('hello');
+  Promise.resolve(expect(Promise.resolve('hello')).resolves.toEqual('hello'));
+  Promise.all([
+    expect(Promise.resolve('hello')).resolves.toEqual('hello'),
+    expect(Promise.resolve('hi')).resolves.toEqual('hi'),
+  ]);
+});
+```
+
+The following patterns are not warnings:
+
+```js
+test('all the things', async () => {
+  expect('something').toEqual('something');
+  expect([1, 2, 3]).toEqual([1, 2, 3]);
+  expect(true).toBeDefined();
+  await expect(Promise.resolve('hello')).resolves.toEqual('hello');
+  await Promise.resolve(
+    expect(Promise.resolve('hello')).resolves.toEqual('hello'),
+  );
+  await Promise.all(
+    expect(Promise.resolve('hello')).resolves.toEqual('hello'),
+    expect(Promise.resolve('hi')).resolves.toEqual('hi'),
+  );
+});
+```
Index: frontend/node_modules/eslint-plugin-jest/docs/rules/valid-title.md
===================================================================
--- frontend/node_modules/eslint-plugin-jest/docs/rules/valid-title.md	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/eslint-plugin-jest/docs/rules/valid-title.md	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,256 @@
+# Enforce valid titles (`valid-title`)
+
+Checks that the title of Jest blocks are valid by ensuring that titles are:
+
+- not empty,
+- is a string,
+- not prefixed with their block name,
+- have no leading or trailing spaces
+
+## Rule Details
+
+**emptyTitle**
+
+An empty title is not informative, and serves little purpose.
+
+Examples of **incorrect** code for this rule:
+
+```js
+describe('', () => {});
+describe('foo', () => {
+  it('', () => {});
+});
+it('', () => {});
+test('', () => {});
+xdescribe('', () => {});
+xit('', () => {});
+xtest('', () => {});
+```
+
+Examples of **correct** code for this rule:
+
+```js
+describe('foo', () => {});
+describe('foo', () => {
+  it('bar', () => {});
+});
+test('foo', () => {});
+it('foo', () => {});
+xdescribe('foo', () => {});
+xit('foo', () => {});
+xtest('foo', () => {});
+```
+
+**titleMustBeString**
+
+Titles for test blocks should always be a string.
+
+This is also applied to `describe` blocks by default, but can be turned off via
+the `ignoreTypeOfDescribeName` option:
+
+Examples of **incorrect** code for this rule:
+
+```js
+it(123, () => {});
+describe(String(/.+/), () => {});
+describe(myFunction, () => {});
+xdescribe(myFunction, () => {});
+describe(6, function () {});
+```
+
+Examples of **correct** code for this rule:
+
+```js
+it('is a string', () => {});
+test('is a string', () => {});
+xtest('is a string', () => {});
+describe('is a string', () => {});
+describe.skip('is a string', () => {});
+fdescribe('is a string', () => {});
+```
+
+Examples of **correct** code when `ignoreTypeOfDescribeName` is `true`:
+
+```js
+it('is a string', () => {});
+test('is a string', () => {});
+xtest('is a string', () => {});
+describe('is a string', () => {});
+describe.skip('is a string', () => {});
+fdescribe('is a string', () => {});
+
+describe(String(/.+/), () => {});
+describe(myFunction, () => {});
+xdescribe(myFunction, () => {});
+describe(6, function () {});
+```
+
+**duplicatePrefix**
+
+A `describe` / `test` block should not start with `duplicatePrefix`
+
+Examples of **incorrect** code for this rule
+
+```js
+test('test foo', () => {});
+it('it foo', () => {});
+
+describe('foo', () => {
+  test('test bar', () => {});
+});
+
+describe('describe foo', () => {
+  test('bar', () => {});
+});
+```
+
+Examples of **correct** code for this rule
+
+```js
+test('foo', () => {});
+it('foo', () => {});
+
+describe('foo', () => {
+  test('bar', () => {});
+});
+```
+
+**accidentalSpace**
+
+A `describe` / `test` block should not contain accidentalSpace
+
+Examples of **incorrect** code for this rule
+
+```js
+test(' foo', () => {});
+it(' foo', () => {});
+
+describe('foo', () => {
+  test(' bar', () => {});
+});
+
+describe(' foo', () => {
+  test('bar', () => {});
+});
+
+describe('foo  ', () => {
+  test('bar', () => {});
+});
+```
+
+Examples of **correct** code for this rule
+
+```js
+test('foo', () => {});
+it('foo', () => {});
+
+describe('foo', () => {
+  test('bar', () => {});
+});
+```
+
+## Options
+
+```ts
+interface Options {
+  ignoreTypeOfDescribeName?: boolean;
+  disallowedWords?: string[];
+  mustNotMatch?: Partial<Record<'describe' | 'test' | 'it', string>> | string;
+  mustMatch?: Partial<Record<'describe' | 'test' | 'it', string>> | string;
+}
+```
+
+#### `ignoreTypeOfDescribeName`
+
+Default: `false`
+
+When enabled, the type of the first argument to `describe` blocks won't be
+checked.
+
+#### `disallowedWords`
+
+Default: `[]`
+
+A string array of words that are not allowed to be used in test titles. Matching
+is not case-sensitive, and looks for complete words:
+
+Examples of **incorrect** code when using `disallowedWords`:
+
+```js
+// with disallowedWords: ['correct', 'all', 'every', 'properly']
+describe('the correct way to do things', () => {});
+it('has ALL the things', () => {});
+xdescribe('every single one of them', () => {});
+test(`that the value is set properly`, () => {});
+```
+
+Examples of **correct** code when using `disallowedWords`:
+
+```js
+// with disallowedWords: ['correct', 'all', 'every', 'properly']
+it('correctly sets the value', () => {});
+test('that everything is as it should be', () => {});
+describe('the proper way to handle things', () => {});
+```
+
+#### `mustMatch` & `mustNotMatch`
+
+Defaults: `{}`
+
+Allows enforcing that titles must match or must not match a given Regular
+Expression, with an optional message. An object can be provided to apply
+different Regular Expressions (with optional messages) to specific Jest test
+function groups (`describe`, `test`, and `it`).
+
+Examples of **incorrect** code when using `mustMatch`:
+
+```js
+// with mustMatch: '^that'
+describe('the correct way to do things', () => {});
+fit('this there!', () => {});
+
+// with mustMatch: { test: '^that' }
+describe('the tests that will be run', () => {});
+test('the stuff works', () => {});
+xtest('errors that are thrown have messages', () => {});
+```
+
+Examples of **correct** code when using `mustMatch`:
+
+```js
+// with mustMatch: '^that'
+describe('that thing that needs to be done', () => {});
+fit('that this there!', () => {});
+
+// with mustMatch: { test: '^that' }
+describe('the tests that will be run', () => {});
+test('that the stuff works', () => {});
+xtest('that errors that thrown have messages', () => {});
+```
+
+Optionally you can provide a custom message to show for a particular matcher by
+using a tuple at any level where you can provide a matcher:
+
+```js
+const prefixes = ['when', 'with', 'without', 'if', 'unless', 'for'];
+const prefixesList = prefixes.join('  - \n');
+
+module.exports = {
+  rules: {
+    'jest/valid-title': [
+      'error',
+      {
+        mustNotMatch: ['\\.$', 'Titles should not end with a full-stop'],
+        mustMatch: {
+          describe: [
+            new RegExp(`^(?:[A-Z]|\\b(${prefixes.join('|')})\\b`, 'u').source,
+            `Describe titles should either start with a capital letter or one of the following prefixes: ${prefixesList}`,
+          ],
+          test: [/[^A-Z]/u.source],
+          it: /[^A-Z]/u.source,
+        },
+      },
+    ],
+  },
+};
+```
Index: frontend/node_modules/eslint-plugin-jest/lib/globals.json
===================================================================
--- frontend/node_modules/eslint-plugin-jest/lib/globals.json	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/eslint-plugin-jest/lib/globals.json	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,15 @@
+{
+  "afterAll": false,
+  "afterEach": false,
+  "beforeAll": false,
+  "beforeEach": false,
+  "describe": false,
+  "expect": false,
+  "fit": false,
+  "it": false,
+  "jest": false,
+  "test": false,
+  "xdescribe": false,
+  "xit": false,
+  "xtest": false
+}
Index: frontend/node_modules/eslint-plugin-jest/lib/index.js
===================================================================
--- frontend/node_modules/eslint-plugin-jest/lib/index.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/eslint-plugin-jest/lib/index.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,70 @@
+"use strict";
+
+var _fs = require("fs");
+
+var _path = require("path");
+
+var _globals = _interopRequireDefault(require("./globals.json"));
+
+var snapshotProcessor = _interopRequireWildcard(require("./processors/snapshot-processor"));
+
+function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
+
+function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+// copied from https://github.com/babel/babel/blob/d8da63c929f2d28c401571e2a43166678c555bc4/packages/babel-helpers/src/helpers.js#L602-L606
+
+/* istanbul ignore next */
+const interopRequireDefault = obj => obj && obj.__esModule ? obj : {
+  default: obj
+};
+
+const importDefault = moduleName => // eslint-disable-next-line @typescript-eslint/no-require-imports
+interopRequireDefault(require(moduleName)).default;
+
+const rulesDir = (0, _path.join)(__dirname, 'rules');
+const excludedFiles = ['__tests__', 'detectJestVersion', 'utils'];
+const rules = (0, _fs.readdirSync)(rulesDir).map(rule => (0, _path.parse)(rule).name).filter(rule => !excludedFiles.includes(rule)).reduce((acc, curr) => ({ ...acc,
+  [curr]: importDefault((0, _path.join)(rulesDir, curr))
+}), {});
+const recommendedRules = Object.entries(rules).filter(([, rule]) => rule.meta.docs.recommended).reduce((acc, [name, rule]) => ({ ...acc,
+  [`jest/${name}`]: rule.meta.docs.recommended
+}), {});
+const allRules = Object.entries(rules).filter(([, rule]) => !rule.meta.deprecated).reduce((acc, [name]) => ({ ...acc,
+  [`jest/${name}`]: 'error'
+}), {});
+
+const createConfig = rules => ({
+  plugins: ['jest'],
+  env: {
+    'jest/globals': true
+  },
+  rules
+});
+
+module.exports = {
+  configs: {
+    all: createConfig(allRules),
+    recommended: createConfig(recommendedRules),
+    style: {
+      plugins: ['jest'],
+      rules: {
+        'jest/no-alias-methods': 'warn',
+        'jest/prefer-to-be': 'error',
+        'jest/prefer-to-contain': 'error',
+        'jest/prefer-to-have-length': 'error'
+      }
+    }
+  },
+  environments: {
+    globals: {
+      globals: _globals.default
+    }
+  },
+  processors: {
+    '.snap': snapshotProcessor
+  },
+  rules
+};
Index: frontend/node_modules/eslint-plugin-jest/lib/processors/snapshot-processor.js
===================================================================
--- frontend/node_modules/eslint-plugin-jest/lib/processors/snapshot-processor.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/eslint-plugin-jest/lib/processors/snapshot-processor.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,17 @@
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.preprocess = exports.postprocess = void 0;
+
+// https://eslint.org/docs/developer-guide/working-with-plugins#processors-in-plugins
+// https://github.com/typescript-eslint/typescript-eslint/issues/808
+const preprocess = source => [source];
+
+exports.preprocess = preprocess;
+
+const postprocess = messages => // snapshot files should only be linted with snapshot specific rules
+messages[0].filter(message => message.ruleId === 'jest/no-large-snapshots');
+
+exports.postprocess = postprocess;
Index: frontend/node_modules/eslint-plugin-jest/lib/rules/consistent-test-it.js
===================================================================
--- frontend/node_modules/eslint-plugin-jest/lib/rules/consistent-test-it.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/eslint-plugin-jest/lib/rules/consistent-test-it.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,119 @@
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.default = void 0;
+
+var _experimentalUtils = require("@typescript-eslint/experimental-utils");
+
+var _utils = require("./utils");
+
+const buildFixer = (callee, nodeName, preferredTestKeyword) => fixer => [fixer.replaceText(callee.type === _experimentalUtils.AST_NODE_TYPES.MemberExpression ? callee.object : callee, getPreferredNodeName(nodeName, preferredTestKeyword))];
+
+var _default = (0, _utils.createRule)({
+  name: __filename,
+  meta: {
+    docs: {
+      category: 'Best Practices',
+      description: 'Have control over `test` and `it` usages',
+      recommended: false
+    },
+    fixable: 'code',
+    messages: {
+      consistentMethod: "Prefer using '{{ testKeyword }}' instead of '{{ oppositeTestKeyword }}'",
+      consistentMethodWithinDescribe: "Prefer using '{{ testKeywordWithinDescribe }}' instead of '{{ oppositeTestKeyword }}' within describe"
+    },
+    schema: [{
+      type: 'object',
+      properties: {
+        fn: {
+          enum: [_utils.TestCaseName.it, _utils.TestCaseName.test]
+        },
+        withinDescribe: {
+          enum: [_utils.TestCaseName.it, _utils.TestCaseName.test]
+        }
+      },
+      additionalProperties: false
+    }],
+    type: 'suggestion'
+  },
+  defaultOptions: [{
+    fn: _utils.TestCaseName.test,
+    withinDescribe: _utils.TestCaseName.it
+  }],
+
+  create(context) {
+    const configObj = context.options[0] || {};
+    const testKeyword = configObj.fn || _utils.TestCaseName.test;
+    const testKeywordWithinDescribe = configObj.withinDescribe || configObj.fn || _utils.TestCaseName.it;
+    let describeNestingLevel = 0;
+    return {
+      CallExpression(node) {
+        const nodeName = (0, _utils.getNodeName)(node.callee);
+
+        if (!nodeName) {
+          return;
+        }
+
+        if ((0, _utils.isDescribeCall)(node)) {
+          describeNestingLevel++;
+        }
+
+        const funcNode = node.callee.type === _experimentalUtils.AST_NODE_TYPES.TaggedTemplateExpression ? node.callee.tag : node.callee.type === _experimentalUtils.AST_NODE_TYPES.CallExpression ? node.callee.callee : node.callee;
+
+        if ((0, _utils.isTestCaseCall)(node) && describeNestingLevel === 0 && !nodeName.includes(testKeyword)) {
+          const oppositeTestKeyword = getOppositeTestKeyword(testKeyword);
+          context.report({
+            messageId: 'consistentMethod',
+            node: node.callee,
+            data: {
+              testKeyword,
+              oppositeTestKeyword
+            },
+            fix: buildFixer(funcNode, nodeName, testKeyword)
+          });
+        }
+
+        if ((0, _utils.isTestCaseCall)(node) && describeNestingLevel > 0 && !nodeName.includes(testKeywordWithinDescribe)) {
+          const oppositeTestKeyword = getOppositeTestKeyword(testKeywordWithinDescribe);
+          context.report({
+            messageId: 'consistentMethodWithinDescribe',
+            node: node.callee,
+            data: {
+              testKeywordWithinDescribe,
+              oppositeTestKeyword
+            },
+            fix: buildFixer(funcNode, nodeName, testKeywordWithinDescribe)
+          });
+        }
+      },
+
+      'CallExpression:exit'(node) {
+        if ((0, _utils.isDescribeCall)(node)) {
+          describeNestingLevel--;
+        }
+      }
+
+    };
+  }
+
+});
+
+exports.default = _default;
+
+function getPreferredNodeName(nodeName, preferredTestKeyword) {
+  if (nodeName === _utils.TestCaseName.fit) {
+    return 'test.only';
+  }
+
+  return nodeName.startsWith('f') || nodeName.startsWith('x') ? nodeName.charAt(0) + preferredTestKeyword : preferredTestKeyword;
+}
+
+function getOppositeTestKeyword(test) {
+  if (test === _utils.TestCaseName.test) {
+    return _utils.TestCaseName.it;
+  }
+
+  return _utils.TestCaseName.test;
+}
Index: frontend/node_modules/eslint-plugin-jest/lib/rules/detectJestVersion.js
===================================================================
--- frontend/node_modules/eslint-plugin-jest/lib/rules/detectJestVersion.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/eslint-plugin-jest/lib/rules/detectJestVersion.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,29 @@
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.detectJestVersion = void 0;
+let cachedJestVersion = null;
+
+const detectJestVersion = () => {
+  if (cachedJestVersion) {
+    return cachedJestVersion;
+  }
+
+  try {
+    const jestPath = require.resolve('jest/package.json');
+
+    const jestPackageJson = // eslint-disable-next-line @typescript-eslint/no-require-imports
+    require(jestPath);
+
+    if (jestPackageJson.version) {
+      const [majorVersion] = jestPackageJson.version.split('.');
+      return cachedJestVersion = parseInt(majorVersion, 10);
+    }
+  } catch {}
+
+  throw new Error('Unable to detect Jest version - please ensure jest package is installed, or otherwise set version explicitly');
+};
+
+exports.detectJestVersion = detectJestVersion;
Index: frontend/node_modules/eslint-plugin-jest/lib/rules/expect-expect.js
===================================================================
--- frontend/node_modules/eslint-plugin-jest/lib/rules/expect-expect.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/eslint-plugin-jest/lib/rules/expect-expect.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,120 @@
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.default = void 0;
+
+var _experimentalUtils = require("@typescript-eslint/experimental-utils");
+
+var _utils = require("./utils");
+
+/*
+ * This implementation is adapted from eslint-plugin-jasmine.
+ * MIT license, Remco Haszing.
+ */
+
+/**
+ * Checks if node names returned by getNodeName matches any of the given star patterns
+ * Pattern examples:
+ *   request.*.expect
+ *   request.**.expect
+ *   request.**.expect*
+ */
+function matchesAssertFunctionName(nodeName, patterns) {
+  return patterns.some(p => new RegExp(`^${p.split('.').map(x => {
+    if (x === '**') return '[a-z\\.]*';
+    return x.replace(/\*/gu, '[a-z]*');
+  }).join('\\.')}(\\.|$)`, 'ui').test(nodeName));
+}
+
+var _default = (0, _utils.createRule)({
+  name: __filename,
+  meta: {
+    docs: {
+      category: 'Best Practices',
+      description: 'Enforce assertion to be made in a test body',
+      recommended: 'warn'
+    },
+    messages: {
+      noAssertions: 'Test has no assertions'
+    },
+    schema: [{
+      type: 'object',
+      properties: {
+        assertFunctionNames: {
+          type: 'array',
+          items: [{
+            type: 'string'
+          }]
+        },
+        additionalTestBlockFunctions: {
+          type: 'array',
+          items: {
+            type: 'string'
+          }
+        }
+      },
+      additionalProperties: false
+    }],
+    type: 'suggestion'
+  },
+  defaultOptions: [{
+    assertFunctionNames: ['expect'],
+    additionalTestBlockFunctions: []
+  }],
+
+  create(context, [{
+    assertFunctionNames = ['expect'],
+    additionalTestBlockFunctions = []
+  }]) {
+    const unchecked = [];
+
+    function checkCallExpressionUsed(nodes) {
+      for (const node of nodes) {
+        const index = node.type === _experimentalUtils.AST_NODE_TYPES.CallExpression ? unchecked.indexOf(node) : -1;
+
+        if (node.type === _experimentalUtils.AST_NODE_TYPES.FunctionDeclaration) {
+          const declaredVariables = context.getDeclaredVariables(node);
+          const testCallExpressions = (0, _utils.getTestCallExpressionsFromDeclaredVariables)(declaredVariables);
+          checkCallExpressionUsed(testCallExpressions);
+        }
+
+        if (index !== -1) {
+          unchecked.splice(index, 1);
+          break;
+        }
+      }
+    }
+
+    return {
+      CallExpression(node) {
+        var _getNodeName;
+
+        const name = (_getNodeName = (0, _utils.getNodeName)(node.callee)) !== null && _getNodeName !== void 0 ? _getNodeName : '';
+
+        if ((0, _utils.isTestCaseCall)(node) || additionalTestBlockFunctions.includes(name)) {
+          if (node.callee.type === _experimentalUtils.AST_NODE_TYPES.MemberExpression && (0, _utils.isSupportedAccessor)(node.callee.property, 'todo')) {
+            return;
+          }
+
+          unchecked.push(node);
+        } else if (matchesAssertFunctionName(name, assertFunctionNames)) {
+          // Return early in case of nested `it` statements.
+          checkCallExpressionUsed(context.getAncestors());
+        }
+      },
+
+      'Program:exit'() {
+        unchecked.forEach(node => context.report({
+          messageId: 'noAssertions',
+          node
+        }));
+      }
+
+    };
+  }
+
+});
+
+exports.default = _default;
Index: frontend/node_modules/eslint-plugin-jest/lib/rules/max-nested-describe.js
===================================================================
--- frontend/node_modules/eslint-plugin-jest/lib/rules/max-nested-describe.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/eslint-plugin-jest/lib/rules/max-nested-describe.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,87 @@
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.default = void 0;
+
+var _experimentalUtils = require("@typescript-eslint/experimental-utils");
+
+var _utils = require("./utils");
+
+var _default = (0, _utils.createRule)({
+  name: __filename,
+  meta: {
+    docs: {
+      category: 'Best Practices',
+      description: 'Enforces a maximum depth to nested describe calls',
+      recommended: false
+    },
+    messages: {
+      exceededMaxDepth: 'Too many nested describe calls ({{ depth }}). Maximum allowed is {{ max }}.'
+    },
+    type: 'suggestion',
+    schema: [{
+      type: 'object',
+      properties: {
+        max: {
+          type: 'integer',
+          minimum: 0
+        }
+      },
+      additionalProperties: false
+    }]
+  },
+  defaultOptions: [{
+    max: 5
+  }],
+
+  create(context, [{
+    max
+  }]) {
+    const describeCallbackStack = [];
+
+    function pushDescribeCallback(node) {
+      const {
+        parent
+      } = node;
+
+      if ((parent === null || parent === void 0 ? void 0 : parent.type) !== _experimentalUtils.AST_NODE_TYPES.CallExpression || !(0, _utils.isDescribeCall)(parent)) {
+        return;
+      }
+
+      describeCallbackStack.push(0);
+
+      if (describeCallbackStack.length > max) {
+        context.report({
+          node: parent,
+          messageId: 'exceededMaxDepth',
+          data: {
+            depth: describeCallbackStack.length,
+            max
+          }
+        });
+      }
+    }
+
+    function popDescribeCallback(node) {
+      const {
+        parent
+      } = node;
+
+      if ((parent === null || parent === void 0 ? void 0 : parent.type) === _experimentalUtils.AST_NODE_TYPES.CallExpression && (0, _utils.isDescribeCall)(parent)) {
+        describeCallbackStack.pop();
+      }
+    }
+
+    return {
+      FunctionExpression: pushDescribeCallback,
+      'FunctionExpression:exit': popDescribeCallback,
+      ArrowFunctionExpression: pushDescribeCallback,
+      'ArrowFunctionExpression:exit': popDescribeCallback
+    };
+  }
+
+});
+
+exports.default = _default;
Index: frontend/node_modules/eslint-plugin-jest/lib/rules/no-alias-methods.js
===================================================================
--- frontend/node_modules/eslint-plugin-jest/lib/rules/no-alias-methods.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/eslint-plugin-jest/lib/rules/no-alias-methods.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,77 @@
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.default = void 0;
+
+var _utils = require("./utils");
+
+var _default = (0, _utils.createRule)({
+  name: __filename,
+  meta: {
+    docs: {
+      category: 'Best Practices',
+      description: 'Disallow alias methods',
+      recommended: false
+    },
+    messages: {
+      replaceAlias: `Replace {{ alias }}() with its canonical name of {{ canonical }}()`
+    },
+    fixable: 'code',
+    type: 'suggestion',
+    schema: []
+  },
+  defaultOptions: [],
+
+  create(context) {
+    // map of jest matcher aliases & their canonical names
+    const methodNames = {
+      toBeCalled: 'toHaveBeenCalled',
+      toBeCalledTimes: 'toHaveBeenCalledTimes',
+      toBeCalledWith: 'toHaveBeenCalledWith',
+      lastCalledWith: 'toHaveBeenLastCalledWith',
+      nthCalledWith: 'toHaveBeenNthCalledWith',
+      toReturn: 'toHaveReturned',
+      toReturnTimes: 'toHaveReturnedTimes',
+      toReturnWith: 'toHaveReturnedWith',
+      lastReturnedWith: 'toHaveLastReturnedWith',
+      nthReturnedWith: 'toHaveNthReturnedWith',
+      toThrowError: 'toThrow'
+    };
+    return {
+      CallExpression(node) {
+        if (!(0, _utils.isExpectCall)(node)) {
+          return;
+        }
+
+        const {
+          matcher
+        } = (0, _utils.parseExpectCall)(node);
+
+        if (!matcher) {
+          return;
+        }
+
+        const alias = matcher.name;
+
+        if (alias in methodNames) {
+          const canonical = methodNames[alias];
+          context.report({
+            messageId: 'replaceAlias',
+            data: {
+              alias,
+              canonical
+            },
+            node: matcher.node.property,
+            fix: fixer => [fixer.replaceText(matcher.node.property, canonical)]
+          });
+        }
+      }
+
+    };
+  }
+
+});
+
+exports.default = _default;
Index: frontend/node_modules/eslint-plugin-jest/lib/rules/no-commented-out-tests.js
===================================================================
--- frontend/node_modules/eslint-plugin-jest/lib/rules/no-commented-out-tests.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/eslint-plugin-jest/lib/rules/no-commented-out-tests.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,55 @@
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.default = void 0;
+
+var _utils = require("./utils");
+
+function hasTests(node) {
+  return /^\s*[xf]?(test|it|describe)(\.\w+|\[['"]\w+['"]\])?\s*\(/mu.test(node.value);
+}
+
+var _default = (0, _utils.createRule)({
+  name: __filename,
+  meta: {
+    docs: {
+      category: 'Best Practices',
+      description: 'Disallow commented out tests',
+      recommended: 'warn'
+    },
+    messages: {
+      commentedTests: 'Some tests seem to be commented'
+    },
+    schema: [],
+    type: 'suggestion'
+  },
+  defaultOptions: [],
+
+  create(context) {
+    const sourceCode = context.getSourceCode();
+
+    function checkNode(node) {
+      if (!hasTests(node)) {
+        return;
+      }
+
+      context.report({
+        messageId: 'commentedTests',
+        node
+      });
+    }
+
+    return {
+      Program() {
+        const comments = sourceCode.getAllComments();
+        comments.forEach(checkNode);
+      }
+
+    };
+  }
+
+});
+
+exports.default = _default;
Index: frontend/node_modules/eslint-plugin-jest/lib/rules/no-conditional-expect.js
===================================================================
--- frontend/node_modules/eslint-plugin-jest/lib/rules/no-conditional-expect.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/eslint-plugin-jest/lib/rules/no-conditional-expect.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,98 @@
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.default = void 0;
+
+var _experimentalUtils = require("@typescript-eslint/experimental-utils");
+
+var _utils = require("./utils");
+
+const isCatchCall = node => node.callee.type === _experimentalUtils.AST_NODE_TYPES.MemberExpression && (0, _utils.isSupportedAccessor)(node.callee.property, 'catch');
+
+var _default = (0, _utils.createRule)({
+  name: __filename,
+  meta: {
+    docs: {
+      description: 'Prevent calling `expect` conditionally',
+      category: 'Best Practices',
+      recommended: 'error'
+    },
+    messages: {
+      conditionalExpect: 'Avoid calling `expect` conditionally`'
+    },
+    type: 'problem',
+    schema: []
+  },
+  defaultOptions: [],
+
+  create(context) {
+    let conditionalDepth = 0;
+    let inTestCase = false;
+    let inPromiseCatch = false;
+
+    const increaseConditionalDepth = () => inTestCase && conditionalDepth++;
+
+    const decreaseConditionalDepth = () => inTestCase && conditionalDepth--;
+
+    return {
+      FunctionDeclaration(node) {
+        const declaredVariables = context.getDeclaredVariables(node);
+        const testCallExpressions = (0, _utils.getTestCallExpressionsFromDeclaredVariables)(declaredVariables);
+
+        if (testCallExpressions.length > 0) {
+          inTestCase = true;
+        }
+      },
+
+      CallExpression(node) {
+        if ((0, _utils.isTestCaseCall)(node)) {
+          inTestCase = true;
+        }
+
+        if (isCatchCall(node)) {
+          inPromiseCatch = true;
+        }
+
+        if (inTestCase && (0, _utils.isExpectCall)(node) && conditionalDepth > 0) {
+          context.report({
+            messageId: 'conditionalExpect',
+            node
+          });
+        }
+
+        if (inPromiseCatch && (0, _utils.isExpectCall)(node)) {
+          context.report({
+            messageId: 'conditionalExpect',
+            node
+          });
+        }
+      },
+
+      'CallExpression:exit'(node) {
+        if ((0, _utils.isTestCaseCall)(node)) {
+          inTestCase = false;
+        }
+
+        if (isCatchCall(node)) {
+          inPromiseCatch = false;
+        }
+      },
+
+      CatchClause: increaseConditionalDepth,
+      'CatchClause:exit': decreaseConditionalDepth,
+      IfStatement: increaseConditionalDepth,
+      'IfStatement:exit': decreaseConditionalDepth,
+      SwitchStatement: increaseConditionalDepth,
+      'SwitchStatement:exit': decreaseConditionalDepth,
+      ConditionalExpression: increaseConditionalDepth,
+      'ConditionalExpression:exit': decreaseConditionalDepth,
+      LogicalExpression: increaseConditionalDepth,
+      'LogicalExpression:exit': decreaseConditionalDepth
+    };
+  }
+
+});
+
+exports.default = _default;
Index: frontend/node_modules/eslint-plugin-jest/lib/rules/no-deprecated-functions.js
===================================================================
--- frontend/node_modules/eslint-plugin-jest/lib/rules/no-deprecated-functions.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/eslint-plugin-jest/lib/rules/no-deprecated-functions.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,103 @@
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.default = void 0;
+
+var _experimentalUtils = require("@typescript-eslint/experimental-utils");
+
+var _detectJestVersion = require("./detectJestVersion");
+
+var _utils = require("./utils");
+
+const parseJestVersion = rawVersion => {
+  if (typeof rawVersion === 'number') {
+    return rawVersion;
+  }
+
+  const [majorVersion] = rawVersion.split('.');
+  return parseInt(majorVersion, 10);
+};
+
+var _default = (0, _utils.createRule)({
+  name: __filename,
+  meta: {
+    docs: {
+      category: 'Best Practices',
+      description: 'Disallow use of deprecated functions',
+      recommended: 'error'
+    },
+    messages: {
+      deprecatedFunction: '`{{ deprecation }}` has been deprecated in favor of `{{ replacement }}`'
+    },
+    type: 'suggestion',
+    schema: [],
+    fixable: 'code'
+  },
+  defaultOptions: [],
+
+  create(context) {
+    var _context$settings, _context$settings$jes;
+
+    const jestVersion = parseJestVersion(((_context$settings = context.settings) === null || _context$settings === void 0 ? void 0 : (_context$settings$jes = _context$settings.jest) === null || _context$settings$jes === void 0 ? void 0 : _context$settings$jes.version) || (0, _detectJestVersion.detectJestVersion)());
+    const deprecations = { ...(jestVersion >= 15 && {
+        'jest.resetModuleRegistry': 'jest.resetModules'
+      }),
+      ...(jestVersion >= 17 && {
+        'jest.addMatchers': 'expect.extend'
+      }),
+      ...(jestVersion >= 21 && {
+        'require.requireMock': 'jest.requireMock',
+        'require.requireActual': 'jest.requireActual'
+      }),
+      ...(jestVersion >= 22 && {
+        'jest.runTimersToTime': 'jest.advanceTimersByTime'
+      }),
+      ...(jestVersion >= 26 && {
+        'jest.genMockFromModule': 'jest.createMockFromModule'
+      })
+    };
+    return {
+      CallExpression(node) {
+        if (node.callee.type !== _experimentalUtils.AST_NODE_TYPES.MemberExpression) {
+          return;
+        }
+
+        const deprecation = (0, _utils.getNodeName)(node);
+
+        if (!deprecation || !(deprecation in deprecations)) {
+          return;
+        }
+
+        const replacement = deprecations[deprecation];
+        const {
+          callee
+        } = node;
+        context.report({
+          messageId: 'deprecatedFunction',
+          data: {
+            deprecation,
+            replacement
+          },
+          node,
+
+          fix(fixer) {
+            let [name, func] = replacement.split('.');
+
+            if (callee.property.type === _experimentalUtils.AST_NODE_TYPES.Literal) {
+              func = `'${func}'`;
+            }
+
+            return [fixer.replaceText(callee.object, name), fixer.replaceText(callee.property, func)];
+          }
+
+        });
+      }
+
+    };
+  }
+
+});
+
+exports.default = _default;
Index: frontend/node_modules/eslint-plugin-jest/lib/rules/no-disabled-tests.js
===================================================================
--- frontend/node_modules/eslint-plugin-jest/lib/rules/no-disabled-tests.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/eslint-plugin-jest/lib/rules/no-disabled-tests.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,135 @@
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.default = void 0;
+
+var _utils = require("./utils");
+
+var _default = (0, _utils.createRule)({
+  name: __filename,
+  meta: {
+    docs: {
+      category: 'Best Practices',
+      description: 'Disallow disabled tests',
+      recommended: 'warn'
+    },
+    messages: {
+      missingFunction: 'Test is missing function argument',
+      skippedTestSuite: 'Skipped test suite',
+      skippedTest: 'Skipped test',
+      pending: 'Call to pending()',
+      pendingSuite: 'Call to pending() within test suite',
+      pendingTest: 'Call to pending() within test',
+      disabledSuite: 'Disabled test suite',
+      disabledTest: 'Disabled test'
+    },
+    schema: [],
+    type: 'suggestion'
+  },
+  defaultOptions: [],
+
+  create(context) {
+    let suiteDepth = 0;
+    let testDepth = 0;
+    return {
+      'CallExpression[callee.name="describe"]'() {
+        suiteDepth++;
+      },
+
+      'CallExpression[callee.name=/^(it|test)$/]'() {
+        testDepth++;
+      },
+
+      'CallExpression[callee.name=/^(it|test)$/][arguments.length<2]'(node) {
+        context.report({
+          messageId: 'missingFunction',
+          node
+        });
+      },
+
+      CallExpression(node) {
+        const functionName = (0, _utils.getNodeName)(node.callee); // prevent duplicate warnings for it.each()()
+
+        if (node.callee.type === 'CallExpression') {
+          return;
+        }
+
+        switch (functionName) {
+          case 'describe.skip.each':
+          case 'xdescribe.each':
+          case 'describe.skip':
+            context.report({
+              messageId: 'skippedTestSuite',
+              node
+            });
+            break;
+
+          case 'it.skip':
+          case 'it.concurrent.skip':
+          case 'test.skip':
+          case 'test.concurrent.skip':
+          case 'it.skip.each':
+          case 'test.skip.each':
+          case 'xit.each':
+          case 'xtest.each':
+            context.report({
+              messageId: 'skippedTest',
+              node
+            });
+            break;
+        }
+      },
+
+      'CallExpression[callee.name="pending"]'(node) {
+        if ((0, _utils.scopeHasLocalReference)(context.getScope(), 'pending')) {
+          return;
+        }
+
+        if (testDepth > 0) {
+          context.report({
+            messageId: 'pendingTest',
+            node
+          });
+        } else if (suiteDepth > 0) {
+          context.report({
+            messageId: 'pendingSuite',
+            node
+          });
+        } else {
+          context.report({
+            messageId: 'pending',
+            node
+          });
+        }
+      },
+
+      'CallExpression[callee.name="xdescribe"]'(node) {
+        context.report({
+          messageId: 'disabledSuite',
+          node
+        });
+      },
+
+      'CallExpression[callee.name=/^(xit|xtest)$/]'(node) {
+        context.report({
+          messageId: 'disabledTest',
+          node
+        });
+      },
+
+      'CallExpression[callee.name="describe"]:exit'() {
+        suiteDepth--;
+      },
+
+      'CallExpression[callee.name=/^(it|test)$/]:exit'() {
+        testDepth--;
+      }
+
+    };
+  }
+
+});
+
+exports.default = _default;
Index: frontend/node_modules/eslint-plugin-jest/lib/rules/no-done-callback.js
===================================================================
--- frontend/node_modules/eslint-plugin-jest/lib/rules/no-done-callback.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/eslint-plugin-jest/lib/rules/no-done-callback.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,148 @@
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.default = void 0;
+
+var _experimentalUtils = require("@typescript-eslint/experimental-utils");
+
+var _utils = require("./utils");
+
+const findCallbackArg = (node, isJestEach) => {
+  if (isJestEach) {
+    return node.arguments[1];
+  }
+
+  if ((0, _utils.isHook)(node) && node.arguments.length >= 1) {
+    return node.arguments[0];
+  }
+
+  if ((0, _utils.isTestCaseCall)(node) && node.arguments.length >= 2) {
+    return node.arguments[1];
+  }
+
+  return null;
+};
+
+var _default = (0, _utils.createRule)({
+  name: __filename,
+  meta: {
+    docs: {
+      category: 'Best Practices',
+      description: 'Avoid using a callback in asynchronous tests and hooks',
+      recommended: 'error',
+      suggestion: true
+    },
+    messages: {
+      noDoneCallback: 'Return a Promise instead of relying on callback parameter',
+      suggestWrappingInPromise: 'Wrap in `new Promise({{ callback }} => ...`',
+      useAwaitInsteadOfCallback: 'Use await instead of callback in async functions'
+    },
+    schema: [],
+    type: 'suggestion',
+    hasSuggestions: true
+  },
+  defaultOptions: [],
+
+  create(context) {
+    return {
+      CallExpression(node) {
+        var _getNodeName$endsWith, _getNodeName;
+
+        // done is the second argument for it.each, not the first
+        const isJestEach = (_getNodeName$endsWith = (_getNodeName = (0, _utils.getNodeName)(node.callee)) === null || _getNodeName === void 0 ? void 0 : _getNodeName.endsWith('.each')) !== null && _getNodeName$endsWith !== void 0 ? _getNodeName$endsWith : false;
+
+        if (isJestEach && node.callee.type !== _experimentalUtils.AST_NODE_TYPES.TaggedTemplateExpression) {
+          // isJestEach but not a TaggedTemplateExpression, so this must be
+          // the `jest.each([])()` syntax which this rule doesn't support due
+          // to its complexity (see jest-community/eslint-plugin-jest#710)
+          return;
+        }
+
+        const callback = findCallbackArg(node, isJestEach);
+        const callbackArgIndex = Number(isJestEach);
+
+        if (!callback || !(0, _utils.isFunction)(callback) || callback.params.length !== 1 + callbackArgIndex) {
+          return;
+        }
+
+        const argument = callback.params[callbackArgIndex];
+
+        if (argument.type !== _experimentalUtils.AST_NODE_TYPES.Identifier) {
+          context.report({
+            node: argument,
+            messageId: 'noDoneCallback'
+          });
+          return;
+        }
+
+        if (callback.async) {
+          context.report({
+            node: argument,
+            messageId: 'useAwaitInsteadOfCallback'
+          });
+          return;
+        }
+
+        context.report({
+          node: argument,
+          messageId: 'noDoneCallback',
+          suggest: [{
+            messageId: 'suggestWrappingInPromise',
+            data: {
+              callback: argument.name
+            },
+
+            fix(fixer) {
+              const {
+                body
+              } = callback;
+              const sourceCode = context.getSourceCode();
+              const firstBodyToken = sourceCode.getFirstToken(body);
+              const lastBodyToken = sourceCode.getLastToken(body);
+              const tokenBeforeArgument = sourceCode.getTokenBefore(argument);
+              const tokenAfterArgument = sourceCode.getTokenAfter(argument);
+              /* istanbul ignore if */
+
+              if (!firstBodyToken || !lastBodyToken || !tokenBeforeArgument || !tokenAfterArgument) {
+                throw new Error(`Unexpected null when attempting to fix ${context.getFilename()} - please file a github issue at https://github.com/jest-community/eslint-plugin-jest`);
+              }
+
+              const argumentInParens = tokenBeforeArgument.value === '(' && tokenAfterArgument.value === ')';
+              let argumentFix = fixer.replaceText(argument, '()');
+
+              if (argumentInParens) {
+                argumentFix = fixer.remove(argument);
+              }
+
+              let newCallback = argument.name;
+
+              if (argumentInParens) {
+                newCallback = `(${newCallback})`;
+              }
+
+              let beforeReplacement = `new Promise(${newCallback} => `;
+              let afterReplacement = ')';
+              let replaceBefore = true;
+
+              if (body.type === _experimentalUtils.AST_NODE_TYPES.BlockStatement) {
+                const keyword = 'return';
+                beforeReplacement = `${keyword} ${beforeReplacement}{`;
+                afterReplacement += '}';
+                replaceBefore = false;
+              }
+
+              return [argumentFix, replaceBefore ? fixer.insertTextBefore(firstBodyToken, beforeReplacement) : fixer.insertTextAfter(firstBodyToken, beforeReplacement), fixer.insertTextAfter(lastBodyToken, afterReplacement)];
+            }
+
+          }]
+        });
+      }
+
+    };
+  }
+
+});
+
+exports.default = _default;
Index: frontend/node_modules/eslint-plugin-jest/lib/rules/no-duplicate-hooks.js
===================================================================
--- frontend/node_modules/eslint-plugin-jest/lib/rules/no-duplicate-hooks.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/eslint-plugin-jest/lib/rules/no-duplicate-hooks.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,68 @@
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.default = void 0;
+
+var _utils = require("./utils");
+
+const newHookContext = () => ({
+  beforeAll: 0,
+  beforeEach: 0,
+  afterAll: 0,
+  afterEach: 0
+});
+
+var _default = (0, _utils.createRule)({
+  name: __filename,
+  meta: {
+    docs: {
+      category: 'Best Practices',
+      description: 'Disallow duplicate setup and teardown hooks',
+      recommended: false
+    },
+    messages: {
+      noDuplicateHook: 'Duplicate {{hook}} in describe block'
+    },
+    schema: [],
+    type: 'suggestion'
+  },
+  defaultOptions: [],
+
+  create(context) {
+    const hookContexts = [newHookContext()];
+    return {
+      CallExpression(node) {
+        if ((0, _utils.isDescribeCall)(node)) {
+          hookContexts.push(newHookContext());
+        }
+
+        if ((0, _utils.isHook)(node)) {
+          const currentLayer = hookContexts[hookContexts.length - 1];
+          currentLayer[node.callee.name] += 1;
+
+          if (currentLayer[node.callee.name] > 1) {
+            context.report({
+              messageId: 'noDuplicateHook',
+              data: {
+                hook: node.callee.name
+              },
+              node
+            });
+          }
+        }
+      },
+
+      'CallExpression:exit'(node) {
+        if ((0, _utils.isDescribeCall)(node)) {
+          hookContexts.pop();
+        }
+      }
+
+    };
+  }
+
+});
+
+exports.default = _default;
Index: frontend/node_modules/eslint-plugin-jest/lib/rules/no-export.js
===================================================================
--- frontend/node_modules/eslint-plugin-jest/lib/rules/no-export.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/eslint-plugin-jest/lib/rules/no-export.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,76 @@
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.default = void 0;
+
+var _experimentalUtils = require("@typescript-eslint/experimental-utils");
+
+var _utils = require("./utils");
+
+var _default = (0, _utils.createRule)({
+  name: __filename,
+  meta: {
+    docs: {
+      category: 'Best Practices',
+      description: 'Disallow using `exports` in files containing tests',
+      recommended: 'error'
+    },
+    messages: {
+      unexpectedExport: `Do not export from a test file.`
+    },
+    type: 'suggestion',
+    schema: []
+  },
+  defaultOptions: [],
+
+  create(context) {
+    const exportNodes = [];
+    let hasTestCase = false;
+    return {
+      'Program:exit'() {
+        if (hasTestCase && exportNodes.length > 0) {
+          for (const node of exportNodes) {
+            context.report({
+              node,
+              messageId: 'unexpectedExport'
+            });
+          }
+        }
+      },
+
+      CallExpression(node) {
+        if ((0, _utils.isTestCaseCall)(node)) {
+          hasTestCase = true;
+        }
+      },
+
+      'ExportNamedDeclaration, ExportDefaultDeclaration'(node) {
+        exportNodes.push(node);
+      },
+
+      'AssignmentExpression > MemberExpression'(node) {
+        let {
+          object,
+          property
+        } = node;
+
+        if (object.type === _experimentalUtils.AST_NODE_TYPES.MemberExpression) {
+          ({
+            object,
+            property
+          } = object);
+        }
+
+        if ('name' in object && object.name === 'module' && property.type === _experimentalUtils.AST_NODE_TYPES.Identifier && /^exports?$/u.test(property.name)) {
+          exportNodes.push(node);
+        }
+      }
+
+    };
+  }
+
+});
+
+exports.default = _default;
Index: frontend/node_modules/eslint-plugin-jest/lib/rules/no-focused-tests.js
===================================================================
--- frontend/node_modules/eslint-plugin-jest/lib/rules/no-focused-tests.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/eslint-plugin-jest/lib/rules/no-focused-tests.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,85 @@
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.default = void 0;
+
+var _experimentalUtils = require("@typescript-eslint/experimental-utils");
+
+var _utils = require("./utils");
+
+const findOnlyNode = node => {
+  const callee = node.callee.type === _experimentalUtils.AST_NODE_TYPES.TaggedTemplateExpression ? node.callee.tag : node.callee.type === _experimentalUtils.AST_NODE_TYPES.CallExpression ? node.callee.callee : node.callee;
+
+  if (callee.type === _experimentalUtils.AST_NODE_TYPES.MemberExpression) {
+    if (callee.object.type === _experimentalUtils.AST_NODE_TYPES.MemberExpression) {
+      if ((0, _utils.isSupportedAccessor)(callee.object.property, 'only')) {
+        return callee.object.property;
+      }
+    }
+
+    if ((0, _utils.isSupportedAccessor)(callee.property, 'only')) {
+      return callee.property;
+    }
+  }
+
+  return null;
+};
+
+var _default = (0, _utils.createRule)({
+  name: __filename,
+  meta: {
+    docs: {
+      category: 'Best Practices',
+      description: 'Disallow focused tests',
+      recommended: 'error',
+      suggestion: true
+    },
+    messages: {
+      focusedTest: 'Unexpected focused test.',
+      suggestRemoveFocus: 'Remove focus from test.'
+    },
+    schema: [],
+    type: 'suggestion',
+    hasSuggestions: true
+  },
+  defaultOptions: [],
+  create: context => ({
+    CallExpression(node) {
+      if (!(0, _utils.isDescribeCall)(node) && !(0, _utils.isTestCaseCall)(node)) {
+        return;
+      }
+
+      if ((0, _utils.getNodeName)(node).startsWith('f')) {
+        context.report({
+          messageId: 'focusedTest',
+          node,
+          suggest: [{
+            messageId: 'suggestRemoveFocus',
+            fix: fixer => fixer.removeRange([node.range[0], node.range[0] + 1])
+          }]
+        });
+        return;
+      }
+
+      const onlyNode = findOnlyNode(node);
+
+      if (!onlyNode) {
+        return;
+      }
+
+      context.report({
+        messageId: 'focusedTest',
+        node: onlyNode,
+        suggest: [{
+          messageId: 'suggestRemoveFocus',
+          fix: fixer => fixer.removeRange([onlyNode.range[0] - 1, onlyNode.range[1] + Number(onlyNode.type !== _experimentalUtils.AST_NODE_TYPES.Identifier)])
+        }]
+      });
+    }
+
+  })
+});
+
+exports.default = _default;
Index: frontend/node_modules/eslint-plugin-jest/lib/rules/no-hooks.js
===================================================================
--- frontend/node_modules/eslint-plugin-jest/lib/rules/no-hooks.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/eslint-plugin-jest/lib/rules/no-hooks.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,58 @@
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.default = void 0;
+
+var _utils = require("./utils");
+
+var _default = (0, _utils.createRule)({
+  name: __filename,
+  meta: {
+    docs: {
+      category: 'Best Practices',
+      description: 'Disallow setup and teardown hooks',
+      recommended: false
+    },
+    messages: {
+      unexpectedHook: "Unexpected '{{ hookName }}' hook"
+    },
+    schema: [{
+      type: 'object',
+      properties: {
+        allow: {
+          type: 'array',
+          contains: ['beforeAll', 'beforeEach', 'afterAll', 'afterEach']
+        }
+      },
+      additionalProperties: false
+    }],
+    type: 'suggestion'
+  },
+  defaultOptions: [{
+    allow: []
+  }],
+
+  create(context, [{
+    allow = []
+  }]) {
+    return {
+      CallExpression(node) {
+        if ((0, _utils.isHook)(node) && !allow.includes(node.callee.name)) {
+          context.report({
+            node,
+            messageId: 'unexpectedHook',
+            data: {
+              hookName: node.callee.name
+            }
+          });
+        }
+      }
+
+    };
+  }
+
+});
+
+exports.default = _default;
Index: frontend/node_modules/eslint-plugin-jest/lib/rules/no-identical-title.js
===================================================================
--- frontend/node_modules/eslint-plugin-jest/lib/rules/no-identical-title.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/eslint-plugin-jest/lib/rules/no-identical-title.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,92 @@
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.default = void 0;
+
+var _utils = require("./utils");
+
+const newDescribeContext = () => ({
+  describeTitles: [],
+  testTitles: []
+});
+
+var _default = (0, _utils.createRule)({
+  name: __filename,
+  meta: {
+    docs: {
+      category: 'Best Practices',
+      description: 'Disallow identical titles',
+      recommended: 'error'
+    },
+    messages: {
+      multipleTestTitle: 'Test title is used multiple times in the same describe block.',
+      multipleDescribeTitle: 'Describe block title is used multiple times in the same describe block.'
+    },
+    schema: [],
+    type: 'suggestion'
+  },
+  defaultOptions: [],
+
+  create(context) {
+    const contexts = [newDescribeContext()];
+    return {
+      CallExpression(node) {
+        var _getNodeName;
+
+        const currentLayer = contexts[contexts.length - 1];
+
+        if ((0, _utils.isDescribeCall)(node)) {
+          contexts.push(newDescribeContext());
+        }
+
+        if ((_getNodeName = (0, _utils.getNodeName)(node.callee)) !== null && _getNodeName !== void 0 && _getNodeName.endsWith('.each')) {
+          return;
+        }
+
+        const [argument] = node.arguments;
+
+        if (!argument || !(0, _utils.isStringNode)(argument)) {
+          return;
+        }
+
+        const title = (0, _utils.getStringValue)(argument);
+
+        if ((0, _utils.isTestCaseCall)(node)) {
+          if (currentLayer.testTitles.includes(title)) {
+            context.report({
+              messageId: 'multipleTestTitle',
+              node: argument
+            });
+          }
+
+          currentLayer.testTitles.push(title);
+        }
+
+        if (!(0, _utils.isDescribeCall)(node)) {
+          return;
+        }
+
+        if (currentLayer.describeTitles.includes(title)) {
+          context.report({
+            messageId: 'multipleDescribeTitle',
+            node: argument
+          });
+        }
+
+        currentLayer.describeTitles.push(title);
+      },
+
+      'CallExpression:exit'(node) {
+        if ((0, _utils.isDescribeCall)(node)) {
+          contexts.pop();
+        }
+      }
+
+    };
+  }
+
+});
+
+exports.default = _default;
Index: frontend/node_modules/eslint-plugin-jest/lib/rules/no-if.js
===================================================================
--- frontend/node_modules/eslint-plugin-jest/lib/rules/no-if.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/eslint-plugin-jest/lib/rules/no-if.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,107 @@
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.default = void 0;
+
+var _experimentalUtils = require("@typescript-eslint/experimental-utils");
+
+var _utils = require("./utils");
+
+const testCaseNames = new Set([...Object.keys(_utils.TestCaseName), 'it.only', 'it.concurrent.only', 'it.skip', 'it.concurrent.skip', 'test.only', 'test.concurrent.only', 'test.skip', 'test.concurrent.skip', 'fit.concurrent']);
+
+const isTestFunctionExpression = node => node.parent !== undefined && node.parent.type === _experimentalUtils.AST_NODE_TYPES.CallExpression && testCaseNames.has((0, _utils.getNodeName)(node.parent.callee));
+
+const conditionName = {
+  [_experimentalUtils.AST_NODE_TYPES.ConditionalExpression]: 'conditional',
+  [_experimentalUtils.AST_NODE_TYPES.SwitchStatement]: 'switch',
+  [_experimentalUtils.AST_NODE_TYPES.IfStatement]: 'if'
+};
+
+var _default = (0, _utils.createRule)({
+  name: __filename,
+  meta: {
+    docs: {
+      description: 'Disallow conditional logic',
+      category: 'Best Practices',
+      recommended: false
+    },
+    messages: {
+      conditionalInTest: 'Test should not contain {{ condition }} statements.'
+    },
+    schema: [],
+    type: 'suggestion'
+  },
+  defaultOptions: [],
+
+  create(context) {
+    const stack = [];
+
+    function validate(node) {
+      const lastElementInStack = stack[stack.length - 1];
+
+      if (stack.length === 0 || !lastElementInStack) {
+        return;
+      }
+
+      context.report({
+        data: {
+          condition: conditionName[node.type]
+        },
+        messageId: 'conditionalInTest',
+        node
+      });
+    }
+
+    return {
+      CallExpression(node) {
+        if ((0, _utils.isTestCaseCall)(node)) {
+          stack.push(true);
+
+          if ((0, _utils.getNodeName)(node).endsWith('each')) {
+            stack.push(true);
+          }
+        }
+      },
+
+      FunctionExpression(node) {
+        stack.push(isTestFunctionExpression(node));
+      },
+
+      FunctionDeclaration(node) {
+        const declaredVariables = context.getDeclaredVariables(node);
+        const testCallExpressions = (0, _utils.getTestCallExpressionsFromDeclaredVariables)(declaredVariables);
+        stack.push(testCallExpressions.length > 0);
+      },
+
+      ArrowFunctionExpression(node) {
+        stack.push(isTestFunctionExpression(node));
+      },
+
+      IfStatement: validate,
+      SwitchStatement: validate,
+      ConditionalExpression: validate,
+
+      'CallExpression:exit'() {
+        stack.pop();
+      },
+
+      'FunctionExpression:exit'() {
+        stack.pop();
+      },
+
+      'FunctionDeclaration:exit'() {
+        stack.pop();
+      },
+
+      'ArrowFunctionExpression:exit'() {
+        stack.pop();
+      }
+
+    };
+  }
+
+});
+
+exports.default = _default;
Index: frontend/node_modules/eslint-plugin-jest/lib/rules/no-interpolation-in-snapshots.js
===================================================================
--- frontend/node_modules/eslint-plugin-jest/lib/rules/no-interpolation-in-snapshots.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/eslint-plugin-jest/lib/rules/no-interpolation-in-snapshots.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,63 @@
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.default = void 0;
+
+var _experimentalUtils = require("@typescript-eslint/experimental-utils");
+
+var _utils = require("./utils");
+
+var _default = (0, _utils.createRule)({
+  name: __filename,
+  meta: {
+    docs: {
+      category: 'Best Practices',
+      description: 'Disallow string interpolation inside snapshots',
+      recommended: 'error'
+    },
+    messages: {
+      noInterpolation: 'Do not use string interpolation inside of snapshots'
+    },
+    schema: [],
+    type: 'problem'
+  },
+  defaultOptions: [],
+
+  create(context) {
+    return {
+      CallExpression(node) {
+        if (!(0, _utils.isExpectCall)(node)) {
+          return;
+        }
+
+        const {
+          matcher
+        } = (0, _utils.parseExpectCall)(node);
+
+        if (!matcher) {
+          return;
+        }
+
+        if (['toMatchInlineSnapshot', 'toThrowErrorMatchingInlineSnapshot'].includes(matcher.name)) {
+          var _matcher$arguments;
+
+          // Check all since the optional 'propertyMatchers' argument might be present
+          (_matcher$arguments = matcher.arguments) === null || _matcher$arguments === void 0 ? void 0 : _matcher$arguments.forEach(argument => {
+            if (argument.type === _experimentalUtils.AST_NODE_TYPES.TemplateLiteral && argument.expressions.length > 0) {
+              context.report({
+                messageId: 'noInterpolation',
+                node: argument
+              });
+            }
+          });
+        }
+      }
+
+    };
+  }
+
+});
+
+exports.default = _default;
Index: frontend/node_modules/eslint-plugin-jest/lib/rules/no-jasmine-globals.js
===================================================================
--- frontend/node_modules/eslint-plugin-jest/lib/rules/no-jasmine-globals.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/eslint-plugin-jest/lib/rules/no-jasmine-globals.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,165 @@
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.default = void 0;
+
+var _experimentalUtils = require("@typescript-eslint/experimental-utils");
+
+var _utils = require("./utils");
+
+var _default = (0, _utils.createRule)({
+  name: __filename,
+  meta: {
+    docs: {
+      category: 'Best Practices',
+      description: 'Disallow Jasmine globals',
+      recommended: 'error'
+    },
+    messages: {
+      illegalGlobal: 'Illegal usage of global `{{ global }}`, prefer `{{ replacement }}`',
+      illegalMethod: 'Illegal usage of `{{ method }}`, prefer `{{ replacement }}`',
+      illegalFail: 'Illegal usage of `fail`, prefer throwing an error, or the `done.fail` callback',
+      illegalPending: 'Illegal usage of `pending`, prefer explicitly skipping a test using `test.skip`',
+      illegalJasmine: 'Illegal usage of jasmine global'
+    },
+    fixable: 'code',
+    schema: [],
+    type: 'suggestion'
+  },
+  defaultOptions: [],
+
+  create(context) {
+    return {
+      CallExpression(node) {
+        const {
+          callee
+        } = node;
+        const calleeName = (0, _utils.getNodeName)(callee);
+
+        if (!calleeName) {
+          return;
+        }
+
+        if (calleeName === 'spyOn' || calleeName === 'spyOnProperty' || calleeName === 'fail' || calleeName === 'pending') {
+          if ((0, _utils.scopeHasLocalReference)(context.getScope(), calleeName)) {
+            // It's a local variable, not a jasmine global.
+            return;
+          }
+
+          switch (calleeName) {
+            case 'spyOn':
+            case 'spyOnProperty':
+              context.report({
+                node,
+                messageId: 'illegalGlobal',
+                data: {
+                  global: calleeName,
+                  replacement: 'jest.spyOn'
+                }
+              });
+              break;
+
+            case 'fail':
+              context.report({
+                node,
+                messageId: 'illegalFail'
+              });
+              break;
+
+            case 'pending':
+              context.report({
+                node,
+                messageId: 'illegalPending'
+              });
+              break;
+          }
+
+          return;
+        }
+
+        if (callee.type === _experimentalUtils.AST_NODE_TYPES.MemberExpression && calleeName.startsWith('jasmine.')) {
+          const functionName = calleeName.replace('jasmine.', '');
+
+          if (functionName === 'any' || functionName === 'anything' || functionName === 'arrayContaining' || functionName === 'objectContaining' || functionName === 'stringMatching') {
+            context.report({
+              fix: fixer => [fixer.replaceText(callee.object, 'expect')],
+              node,
+              messageId: 'illegalMethod',
+              data: {
+                method: calleeName,
+                replacement: `expect.${functionName}`
+              }
+            });
+            return;
+          }
+
+          if (functionName === 'addMatchers') {
+            context.report({
+              node,
+              messageId: 'illegalMethod',
+              data: {
+                method: calleeName,
+                replacement: 'expect.extend'
+              }
+            });
+            return;
+          }
+
+          if (functionName === 'createSpy') {
+            context.report({
+              node,
+              messageId: 'illegalMethod',
+              data: {
+                method: calleeName,
+                replacement: 'jest.fn'
+              }
+            });
+            return;
+          }
+
+          context.report({
+            node,
+            messageId: 'illegalJasmine'
+          });
+        }
+      },
+
+      MemberExpression(node) {
+        if ((0, _utils.isSupportedAccessor)(node.object, 'jasmine')) {
+          const {
+            parent,
+            property
+          } = node;
+
+          if (parent && parent.type === _experimentalUtils.AST_NODE_TYPES.AssignmentExpression) {
+            if ((0, _utils.isSupportedAccessor)(property, 'DEFAULT_TIMEOUT_INTERVAL')) {
+              const {
+                right
+              } = parent;
+
+              if (right.type === _experimentalUtils.AST_NODE_TYPES.Literal) {
+                context.report({
+                  fix: fixer => [fixer.replaceText(parent, `jest.setTimeout(${right.value})`)],
+                  node,
+                  messageId: 'illegalJasmine'
+                });
+                return;
+              }
+            }
+
+            context.report({
+              node,
+              messageId: 'illegalJasmine'
+            });
+          }
+        }
+      }
+
+    };
+  }
+
+});
+
+exports.default = _default;
Index: frontend/node_modules/eslint-plugin-jest/lib/rules/no-jest-import.js
===================================================================
--- frontend/node_modules/eslint-plugin-jest/lib/rules/no-jest-import.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/eslint-plugin-jest/lib/rules/no-jest-import.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,48 @@
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.default = void 0;
+
+var _utils = require("./utils");
+
+var _default = (0, _utils.createRule)({
+  name: __filename,
+  meta: {
+    type: 'problem',
+    docs: {
+      description: 'Disallow importing Jest',
+      category: 'Best Practices',
+      recommended: 'error'
+    },
+    messages: {
+      unexpectedImport: `Jest is automatically in scope. Do not import "jest", as Jest doesn't export anything.`
+    },
+    schema: []
+  },
+  defaultOptions: [],
+
+  create(context) {
+    return {
+      'ImportDeclaration[source.value="jest"]'(node) {
+        context.report({
+          node,
+          messageId: 'unexpectedImport'
+        });
+      },
+
+      'CallExpression[callee.name="require"][arguments.0.value="jest"]'(node) {
+        context.report({
+          loc: node.arguments[0].loc,
+          messageId: 'unexpectedImport',
+          node
+        });
+      }
+
+    };
+  }
+
+});
+
+exports.default = _default;
Index: frontend/node_modules/eslint-plugin-jest/lib/rules/no-large-snapshots.js
===================================================================
--- frontend/node_modules/eslint-plugin-jest/lib/rules/no-large-snapshots.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/eslint-plugin-jest/lib/rules/no-large-snapshots.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,131 @@
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.default = void 0;
+
+var _path = require("path");
+
+var _experimentalUtils = require("@typescript-eslint/experimental-utils");
+
+var _utils = require("./utils");
+
+const reportOnViolation = (context, node, {
+  maxSize: lineLimit = 50,
+  allowedSnapshots = {}
+}) => {
+  const startLine = node.loc.start.line;
+  const endLine = node.loc.end.line;
+  const lineCount = endLine - startLine;
+  const allPathsAreAbsolute = Object.keys(allowedSnapshots).every(_path.isAbsolute);
+
+  if (!allPathsAreAbsolute) {
+    throw new Error('All paths for allowedSnapshots must be absolute. You can use JS config and `path.resolve`');
+  }
+
+  let isAllowed = false;
+
+  if (node.type === _experimentalUtils.AST_NODE_TYPES.ExpressionStatement && 'left' in node.expression && (0, _utils.isExpectMember)(node.expression.left)) {
+    const fileName = context.getFilename();
+    const allowedSnapshotsInFile = allowedSnapshots[fileName];
+
+    if (allowedSnapshotsInFile) {
+      const snapshotName = (0, _utils.getAccessorValue)(node.expression.left.property);
+      isAllowed = allowedSnapshotsInFile.some(name => {
+        if (name instanceof RegExp) {
+          return name.test(snapshotName);
+        }
+
+        return snapshotName === name;
+      });
+    }
+  }
+
+  if (!isAllowed && lineCount > lineLimit) {
+    context.report({
+      messageId: lineLimit === 0 ? 'noSnapshot' : 'tooLongSnapshots',
+      data: {
+        lineLimit,
+        lineCount
+      },
+      node
+    });
+  }
+};
+
+var _default = (0, _utils.createRule)({
+  name: __filename,
+  meta: {
+    docs: {
+      category: 'Best Practices',
+      description: 'disallow large snapshots',
+      recommended: false
+    },
+    messages: {
+      noSnapshot: '`{{ lineCount }}`s should begin with lowercase',
+      tooLongSnapshots: 'Expected Jest snapshot to be smaller than {{ lineLimit }} lines but was {{ lineCount }} lines long'
+    },
+    type: 'suggestion',
+    schema: [{
+      type: 'object',
+      properties: {
+        maxSize: {
+          type: 'number'
+        },
+        inlineMaxSize: {
+          type: 'number'
+        },
+        allowedSnapshots: {
+          type: 'object',
+          additionalProperties: {
+            type: 'array'
+          }
+        }
+      },
+      additionalProperties: false
+    }]
+  },
+  defaultOptions: [{}],
+
+  create(context, [options]) {
+    if (context.getFilename().endsWith('.snap')) {
+      return {
+        ExpressionStatement(node) {
+          reportOnViolation(context, node, options);
+        }
+
+      };
+    }
+
+    return {
+      CallExpression(node) {
+        var _matcher$arguments;
+
+        if (!(0, _utils.isExpectCall)(node)) {
+          return;
+        }
+
+        const {
+          matcher
+        } = (0, _utils.parseExpectCall)(node);
+
+        if ((matcher === null || matcher === void 0 ? void 0 : matcher.node.parent.type) !== _experimentalUtils.AST_NODE_TYPES.CallExpression) {
+          return;
+        }
+
+        if (['toMatchInlineSnapshot', 'toThrowErrorMatchingInlineSnapshot'].includes(matcher.name) && (_matcher$arguments = matcher.arguments) !== null && _matcher$arguments !== void 0 && _matcher$arguments.length) {
+          var _options$inlineMaxSiz;
+
+          reportOnViolation(context, matcher.arguments[0], { ...options,
+            maxSize: (_options$inlineMaxSiz = options.inlineMaxSize) !== null && _options$inlineMaxSiz !== void 0 ? _options$inlineMaxSiz : options.maxSize
+          });
+        }
+      }
+
+    };
+  }
+
+});
+
+exports.default = _default;
Index: frontend/node_modules/eslint-plugin-jest/lib/rules/no-mocks-import.js
===================================================================
--- frontend/node_modules/eslint-plugin-jest/lib/rules/no-mocks-import.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/eslint-plugin-jest/lib/rules/no-mocks-import.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,61 @@
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.default = void 0;
+
+var _path = require("path");
+
+var _utils = require("./utils");
+
+const mocksDirName = '__mocks__';
+
+const isMockPath = path => path.split(_path.posix.sep).includes(mocksDirName);
+
+const isMockImportLiteral = expression => (0, _utils.isStringNode)(expression) && isMockPath((0, _utils.getStringValue)(expression));
+
+var _default = (0, _utils.createRule)({
+  name: __filename,
+  meta: {
+    type: 'problem',
+    docs: {
+      category: 'Best Practices',
+      description: 'Disallow manually importing from `__mocks__`',
+      recommended: 'error'
+    },
+    messages: {
+      noManualImport: `Mocks should not be manually imported from a ${mocksDirName} directory. Instead use \`jest.mock\` and import from the original module path.`
+    },
+    schema: []
+  },
+  defaultOptions: [],
+
+  create(context) {
+    return {
+      ImportDeclaration(node) {
+        if (isMockImportLiteral(node.source)) {
+          context.report({
+            node,
+            messageId: 'noManualImport'
+          });
+        }
+      },
+
+      'CallExpression[callee.name="require"]'(node) {
+        const [arg] = node.arguments;
+
+        if (arg && isMockImportLiteral(arg)) {
+          context.report({
+            node: arg,
+            messageId: 'noManualImport'
+          });
+        }
+      }
+
+    };
+  }
+
+});
+
+exports.default = _default;
Index: frontend/node_modules/eslint-plugin-jest/lib/rules/no-restricted-matchers.js
===================================================================
--- frontend/node_modules/eslint-plugin-jest/lib/rules/no-restricted-matchers.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/eslint-plugin-jest/lib/rules/no-restricted-matchers.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,104 @@
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.default = void 0;
+
+var _utils = require("./utils");
+
+var _default = (0, _utils.createRule)({
+  name: __filename,
+  meta: {
+    docs: {
+      category: 'Best Practices',
+      description: 'Disallow specific matchers & modifiers',
+      recommended: false
+    },
+    type: 'suggestion',
+    schema: [{
+      type: 'object',
+      additionalProperties: {
+        type: ['string', 'null']
+      }
+    }],
+    messages: {
+      restrictedChain: 'Use of `{{ chain }}` is disallowed',
+      restrictedChainWithMessage: '{{ message }}'
+    }
+  },
+  defaultOptions: [{}],
+
+  create(context, [restrictedChains]) {
+    return {
+      CallExpression(node) {
+        if (!(0, _utils.isExpectCall)(node)) {
+          return;
+        }
+
+        const {
+          matcher,
+          modifier
+        } = (0, _utils.parseExpectCall)(node);
+
+        if (matcher) {
+          const chain = matcher.name;
+
+          if (chain in restrictedChains) {
+            const message = restrictedChains[chain];
+            context.report({
+              messageId: message ? 'restrictedChainWithMessage' : 'restrictedChain',
+              data: {
+                message,
+                chain
+              },
+              node: matcher.node.property
+            });
+            return;
+          }
+        }
+
+        if (modifier) {
+          const chain = modifier.name;
+
+          if (chain in restrictedChains) {
+            const message = restrictedChains[chain];
+            context.report({
+              messageId: message ? 'restrictedChainWithMessage' : 'restrictedChain',
+              data: {
+                message,
+                chain
+              },
+              node: modifier.node.property
+            });
+            return;
+          }
+        }
+
+        if (matcher && modifier) {
+          const chain = `${modifier.name}.${matcher.name}`;
+
+          if (chain in restrictedChains) {
+            const message = restrictedChains[chain];
+            context.report({
+              messageId: message ? 'restrictedChainWithMessage' : 'restrictedChain',
+              data: {
+                message,
+                chain
+              },
+              loc: {
+                start: modifier.node.property.loc.start,
+                end: matcher.node.property.loc.end
+              }
+            });
+            return;
+          }
+        }
+      }
+
+    };
+  }
+
+});
+
+exports.default = _default;
Index: frontend/node_modules/eslint-plugin-jest/lib/rules/no-standalone-expect.js
===================================================================
--- frontend/node_modules/eslint-plugin-jest/lib/rules/no-standalone-expect.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/eslint-plugin-jest/lib/rules/no-standalone-expect.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,143 @@
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.default = void 0;
+
+var _experimentalUtils = require("@typescript-eslint/experimental-utils");
+
+var _utils = require("./utils");
+
+const getBlockType = statement => {
+  const func = statement.parent;
+  /* istanbul ignore if */
+
+  if (!func) {
+    throw new Error(`Unexpected BlockStatement. No parent defined. - please file a github issue at https://github.com/jest-community/eslint-plugin-jest`);
+  } // functionDeclaration: function func() {}
+
+
+  if (func.type === _experimentalUtils.AST_NODE_TYPES.FunctionDeclaration) {
+    return 'function';
+  }
+
+  if ((0, _utils.isFunction)(func) && func.parent) {
+    const expr = func.parent; // arrow function or function expr
+
+    if (expr.type === _experimentalUtils.AST_NODE_TYPES.VariableDeclarator) {
+      return 'function';
+    } // if it's not a variable, it will be callExpr, we only care about describe
+
+
+    if (expr.type === _experimentalUtils.AST_NODE_TYPES.CallExpression && (0, _utils.isDescribeCall)(expr)) {
+      return 'describe';
+    }
+  }
+
+  return null;
+};
+
+var _default = (0, _utils.createRule)({
+  name: __filename,
+  meta: {
+    docs: {
+      category: 'Best Practices',
+      description: 'Disallow using `expect` outside of `it` or `test` blocks',
+      recommended: 'error'
+    },
+    messages: {
+      unexpectedExpect: 'Expect must be inside of a test block.'
+    },
+    type: 'suggestion',
+    schema: [{
+      properties: {
+        additionalTestBlockFunctions: {
+          type: 'array',
+          items: {
+            type: 'string'
+          }
+        }
+      },
+      additionalProperties: false
+    }]
+  },
+  defaultOptions: [{
+    additionalTestBlockFunctions: []
+  }],
+
+  create(context, [{
+    additionalTestBlockFunctions = []
+  }]) {
+    const callStack = [];
+
+    const isCustomTestBlockFunction = node => additionalTestBlockFunctions.includes((0, _utils.getNodeName)(node) || '');
+
+    const isTestBlock = node => (0, _utils.isTestCaseCall)(node) || isCustomTestBlockFunction(node);
+
+    return {
+      CallExpression(node) {
+        if ((0, _utils.isExpectCall)(node)) {
+          const parent = callStack[callStack.length - 1];
+
+          if (!parent || parent === _utils.DescribeAlias.describe) {
+            context.report({
+              node,
+              messageId: 'unexpectedExpect'
+            });
+          }
+
+          return;
+        }
+
+        if (isTestBlock(node)) {
+          callStack.push('test');
+        }
+
+        if (node.callee.type === _experimentalUtils.AST_NODE_TYPES.TaggedTemplateExpression) {
+          callStack.push('template');
+        }
+      },
+
+      'CallExpression:exit'(node) {
+        const top = callStack[callStack.length - 1];
+
+        if (top === 'test' && isTestBlock(node) && node.callee.type !== _experimentalUtils.AST_NODE_TYPES.MemberExpression || top === 'template' && node.callee.type === _experimentalUtils.AST_NODE_TYPES.TaggedTemplateExpression) {
+          callStack.pop();
+        }
+      },
+
+      BlockStatement(statement) {
+        const blockType = getBlockType(statement);
+
+        if (blockType) {
+          callStack.push(blockType);
+        }
+      },
+
+      'BlockStatement:exit'(statement) {
+        if (callStack[callStack.length - 1] === getBlockType(statement)) {
+          callStack.pop();
+        }
+      },
+
+      ArrowFunctionExpression(node) {
+        var _node$parent;
+
+        if (((_node$parent = node.parent) === null || _node$parent === void 0 ? void 0 : _node$parent.type) !== _experimentalUtils.AST_NODE_TYPES.CallExpression) {
+          callStack.push('arrow');
+        }
+      },
+
+      'ArrowFunctionExpression:exit'() {
+        if (callStack[callStack.length - 1] === 'arrow') {
+          callStack.pop();
+        }
+      }
+
+    };
+  }
+
+});
+
+exports.default = _default;
Index: frontend/node_modules/eslint-plugin-jest/lib/rules/no-test-prefixes.js
===================================================================
--- frontend/node_modules/eslint-plugin-jest/lib/rules/no-test-prefixes.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/eslint-plugin-jest/lib/rules/no-test-prefixes.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,71 @@
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.default = void 0;
+
+var _experimentalUtils = require("@typescript-eslint/experimental-utils");
+
+var _utils = require("./utils");
+
+var _default = (0, _utils.createRule)({
+  name: __filename,
+  meta: {
+    docs: {
+      category: 'Best Practices',
+      description: 'Use `.only` and `.skip` over `f` and `x`',
+      recommended: 'error'
+    },
+    messages: {
+      usePreferredName: 'Use "{{ preferredNodeName }}" instead'
+    },
+    fixable: 'code',
+    schema: [],
+    type: 'suggestion'
+  },
+  defaultOptions: [],
+
+  create(context) {
+    return {
+      CallExpression(node) {
+        const nodeName = (0, _utils.getNodeName)(node.callee);
+        if (!nodeName || !(0, _utils.isDescribeCall)(node) && !(0, _utils.isTestCaseCall)(node)) return;
+        const preferredNodeName = getPreferredNodeName(nodeName);
+        if (!preferredNodeName) return;
+        const funcNode = node.callee.type === _experimentalUtils.AST_NODE_TYPES.TaggedTemplateExpression ? node.callee.tag : node.callee.type === _experimentalUtils.AST_NODE_TYPES.CallExpression ? node.callee.callee : node.callee;
+        context.report({
+          messageId: 'usePreferredName',
+          node: node.callee,
+          data: {
+            preferredNodeName
+          },
+
+          fix(fixer) {
+            return [fixer.replaceText(funcNode, preferredNodeName)];
+          }
+
+        });
+      }
+
+    };
+  }
+
+});
+
+exports.default = _default;
+
+function getPreferredNodeName(nodeName) {
+  const firstChar = nodeName.charAt(0);
+  const suffix = nodeName.endsWith('.each') ? '.each' : '';
+
+  if (firstChar === 'f') {
+    return `${nodeName.slice(1).replace('.each', '')}.only${suffix}`;
+  }
+
+  if (firstChar === 'x') {
+    return `${nodeName.slice(1).replace('.each', '')}.skip${suffix}`;
+  }
+
+  return null;
+}
Index: frontend/node_modules/eslint-plugin-jest/lib/rules/no-test-return-statement.js
===================================================================
--- frontend/node_modules/eslint-plugin-jest/lib/rules/no-test-return-statement.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/eslint-plugin-jest/lib/rules/no-test-return-statement.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,68 @@
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.default = void 0;
+
+var _experimentalUtils = require("@typescript-eslint/experimental-utils");
+
+var _utils = require("./utils");
+
+const getBody = args => {
+  const [, secondArg] = args;
+
+  if (secondArg && (0, _utils.isFunction)(secondArg) && secondArg.body.type === _experimentalUtils.AST_NODE_TYPES.BlockStatement) {
+    return secondArg.body.body;
+  }
+
+  return [];
+};
+
+var _default = (0, _utils.createRule)({
+  name: __filename,
+  meta: {
+    docs: {
+      category: 'Best Practices',
+      description: 'Disallow explicitly returning from tests',
+      recommended: false
+    },
+    messages: {
+      noReturnValue: 'Jest tests should not return a value.'
+    },
+    schema: [],
+    type: 'suggestion'
+  },
+  defaultOptions: [],
+
+  create(context) {
+    return {
+      CallExpression(node) {
+        if (!(0, _utils.isTestCaseCall)(node)) return;
+        const body = getBody(node.arguments);
+        const returnStmt = body.find(t => t.type === _experimentalUtils.AST_NODE_TYPES.ReturnStatement);
+        if (!returnStmt) return;
+        context.report({
+          messageId: 'noReturnValue',
+          node: returnStmt
+        });
+      },
+
+      FunctionDeclaration(node) {
+        const declaredVariables = context.getDeclaredVariables(node);
+        const testCallExpressions = (0, _utils.getTestCallExpressionsFromDeclaredVariables)(declaredVariables);
+        if (testCallExpressions.length === 0) return;
+        const returnStmt = node.body.body.find(t => t.type === _experimentalUtils.AST_NODE_TYPES.ReturnStatement);
+        if (!returnStmt) return;
+        context.report({
+          messageId: 'noReturnValue',
+          node: returnStmt
+        });
+      }
+
+    };
+  }
+
+});
+
+exports.default = _default;
Index: frontend/node_modules/eslint-plugin-jest/lib/rules/prefer-called-with.js
===================================================================
--- frontend/node_modules/eslint-plugin-jest/lib/rules/prefer-called-with.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/eslint-plugin-jest/lib/rules/prefer-called-with.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,57 @@
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.default = void 0;
+
+var _utils = require("./utils");
+
+var _default = (0, _utils.createRule)({
+  name: __filename,
+  meta: {
+    docs: {
+      category: 'Best Practices',
+      description: 'Suggest using `toBeCalledWith()` or `toHaveBeenCalledWith()`',
+      recommended: false
+    },
+    messages: {
+      preferCalledWith: 'Prefer {{name}}With(/* expected args */)'
+    },
+    type: 'suggestion',
+    schema: []
+  },
+  defaultOptions: [],
+
+  create(context) {
+    return {
+      CallExpression(node) {
+        if (!(0, _utils.isExpectCall)(node)) {
+          return;
+        }
+
+        const {
+          modifier,
+          matcher
+        } = (0, _utils.parseExpectCall)(node); // Could check resolves/rejects here but not a likely idiom.
+
+        if (matcher && !modifier) {
+          if (['toBeCalled', 'toHaveBeenCalled'].includes(matcher.name)) {
+            context.report({
+              data: {
+                name: matcher.name
+              },
+              // todo: rename to 'matcherName'
+              messageId: 'preferCalledWith',
+              node: matcher.node.property
+            });
+          }
+        }
+      }
+
+    };
+  }
+
+});
+
+exports.default = _default;
Index: frontend/node_modules/eslint-plugin-jest/lib/rules/prefer-comparison-matcher.js
===================================================================
--- frontend/node_modules/eslint-plugin-jest/lib/rules/prefer-comparison-matcher.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/eslint-plugin-jest/lib/rules/prefer-comparison-matcher.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,139 @@
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.default = void 0;
+
+var _experimentalUtils = require("@typescript-eslint/experimental-utils");
+
+var _utils = require("./utils");
+
+const isBooleanLiteral = node => node.type === _experimentalUtils.AST_NODE_TYPES.Literal && typeof node.value === 'boolean';
+
+/**
+ * Checks if the given `ParsedExpectMatcher` is a call to one of the equality matchers,
+ * with a boolean literal as the sole argument.
+ *
+ * @example javascript
+ * toBe(true);
+ * toEqual(false);
+ *
+ * @param {ParsedExpectMatcher} matcher
+ *
+ * @return {matcher is ParsedBooleanEqualityMatcher}
+ */
+const isBooleanEqualityMatcher = matcher => (0, _utils.isParsedEqualityMatcherCall)(matcher) && isBooleanLiteral((0, _utils.followTypeAssertionChain)(matcher.arguments[0]));
+
+const isString = node => {
+  return (0, _utils.isStringNode)(node) || node.type === _experimentalUtils.AST_NODE_TYPES.TemplateLiteral;
+};
+
+const isComparingToString = expression => {
+  return isString(expression.left) || isString(expression.right);
+};
+
+const invertOperator = operator => {
+  switch (operator) {
+    case '>':
+      return '<=';
+
+    case '<':
+      return '>=';
+
+    case '>=':
+      return '<';
+
+    case '<=':
+      return '>';
+  }
+
+  return null;
+};
+
+const determineMatcher = (operator, negated) => {
+  const op = negated ? invertOperator(operator) : operator;
+
+  switch (op) {
+    case '>':
+      return 'toBeGreaterThan';
+
+    case '<':
+      return 'toBeLessThan';
+
+    case '>=':
+      return 'toBeGreaterThanOrEqual';
+
+    case '<=':
+      return 'toBeLessThanOrEqual';
+  }
+
+  return null;
+};
+
+var _default = (0, _utils.createRule)({
+  name: __filename,
+  meta: {
+    docs: {
+      category: 'Best Practices',
+      description: 'Suggest using the built-in comparison matchers',
+      recommended: false
+    },
+    messages: {
+      useToBeComparison: 'Prefer using `{{ preferredMatcher }}` instead'
+    },
+    fixable: 'code',
+    type: 'suggestion',
+    schema: []
+  },
+  defaultOptions: [],
+
+  create(context) {
+    return {
+      CallExpression(node) {
+        if (!(0, _utils.isExpectCall)(node)) {
+          return;
+        }
+
+        const {
+          expect: {
+            arguments: [comparison],
+            range: [, expectCallEnd]
+          },
+          matcher,
+          modifier
+        } = (0, _utils.parseExpectCall)(node);
+
+        if (!matcher || (comparison === null || comparison === void 0 ? void 0 : comparison.type) !== _experimentalUtils.AST_NODE_TYPES.BinaryExpression || isComparingToString(comparison) || !isBooleanEqualityMatcher(matcher)) {
+          return;
+        }
+
+        const preferredMatcher = determineMatcher(comparison.operator, (0, _utils.followTypeAssertionChain)(matcher.arguments[0]).value === !!modifier);
+
+        if (!preferredMatcher) {
+          return;
+        }
+
+        context.report({
+          fix(fixer) {
+            const sourceCode = context.getSourceCode();
+            return [// replace the comparison argument with the left-hand side of the comparison
+            fixer.replaceText(comparison, sourceCode.getText(comparison.left)), // replace the current matcher & modifier with the preferred matcher
+            fixer.replaceTextRange([expectCallEnd, matcher.node.range[1]], `.${preferredMatcher}`), // replace the matcher argument with the right-hand side of the comparison
+            fixer.replaceText(matcher.arguments[0], sourceCode.getText(comparison.right))];
+          },
+
+          messageId: 'useToBeComparison',
+          data: {
+            preferredMatcher
+          },
+          node: (modifier || matcher).node.property
+        });
+      }
+
+    };
+  }
+
+});
+
+exports.default = _default;
Index: frontend/node_modules/eslint-plugin-jest/lib/rules/prefer-equality-matcher.js
===================================================================
--- frontend/node_modules/eslint-plugin-jest/lib/rules/prefer-equality-matcher.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/eslint-plugin-jest/lib/rules/prefer-equality-matcher.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,98 @@
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.default = void 0;
+
+var _experimentalUtils = require("@typescript-eslint/experimental-utils");
+
+var _utils = require("./utils");
+
+const isBooleanLiteral = node => node.type === _experimentalUtils.AST_NODE_TYPES.Literal && typeof node.value === 'boolean';
+
+/**
+ * Checks if the given `ParsedExpectMatcher` is a call to one of the equality matchers,
+ * with a boolean literal as the sole argument.
+ *
+ * @example javascript
+ * toBe(true);
+ * toEqual(false);
+ *
+ * @param {ParsedExpectMatcher} matcher
+ *
+ * @return {matcher is ParsedBooleanEqualityMatcher}
+ */
+const isBooleanEqualityMatcher = matcher => (0, _utils.isParsedEqualityMatcherCall)(matcher) && isBooleanLiteral((0, _utils.followTypeAssertionChain)(matcher.arguments[0]));
+
+var _default = (0, _utils.createRule)({
+  name: __filename,
+  meta: {
+    docs: {
+      category: 'Best Practices',
+      description: 'Suggest using the built-in equality matchers',
+      recommended: false,
+      suggestion: true
+    },
+    messages: {
+      useEqualityMatcher: 'Prefer using one of the equality matchers instead',
+      suggestEqualityMatcher: 'Use `{{ equalityMatcher }}`'
+    },
+    hasSuggestions: true,
+    type: 'suggestion',
+    schema: []
+  },
+  defaultOptions: [],
+
+  create(context) {
+    return {
+      CallExpression(node) {
+        if (!(0, _utils.isExpectCall)(node)) {
+          return;
+        }
+
+        const {
+          expect: {
+            arguments: [comparison],
+            range: [, expectCallEnd]
+          },
+          matcher,
+          modifier
+        } = (0, _utils.parseExpectCall)(node);
+
+        if (!matcher || (comparison === null || comparison === void 0 ? void 0 : comparison.type) !== _experimentalUtils.AST_NODE_TYPES.BinaryExpression || comparison.operator !== '===' && comparison.operator !== '!==' || !isBooleanEqualityMatcher(matcher)) {
+          return;
+        }
+
+        const matcherValue = (0, _utils.followTypeAssertionChain)(matcher.arguments[0]).value; // we need to negate the expectation if the current expected
+        // value is itself negated by the "not" modifier
+
+        const addNotModifier = (comparison.operator === '!==' ? !matcherValue : matcherValue) === !!modifier;
+
+        const buildFixer = equalityMatcher => fixer => {
+          const sourceCode = context.getSourceCode();
+          return [// replace the comparison argument with the left-hand side of the comparison
+          fixer.replaceText(comparison, sourceCode.getText(comparison.left)), // replace the current matcher & modifier with the preferred matcher
+          fixer.replaceTextRange([expectCallEnd, matcher.node.range[1]], addNotModifier ? `.${_utils.ModifierName.not}.${equalityMatcher}` : `.${equalityMatcher}`), // replace the matcher argument with the right-hand side of the comparison
+          fixer.replaceText(matcher.arguments[0], sourceCode.getText(comparison.right))];
+        };
+
+        context.report({
+          messageId: 'useEqualityMatcher',
+          suggest: ['toBe', 'toEqual', 'toStrictEqual'].map(equalityMatcher => ({
+            messageId: 'suggestEqualityMatcher',
+            data: {
+              equalityMatcher
+            },
+            fix: buildFixer(equalityMatcher)
+          })),
+          node: (modifier || matcher).node.property
+        });
+      }
+
+    };
+  }
+
+});
+
+exports.default = _default;
Index: frontend/node_modules/eslint-plugin-jest/lib/rules/prefer-expect-assertions.js
===================================================================
--- frontend/node_modules/eslint-plugin-jest/lib/rules/prefer-expect-assertions.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/eslint-plugin-jest/lib/rules/prefer-expect-assertions.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,232 @@
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.default = void 0;
+
+var _experimentalUtils = require("@typescript-eslint/experimental-utils");
+
+var _utils = require("./utils");
+
+const isExpectAssertionsOrHasAssertionsCall = expression => expression.type === _experimentalUtils.AST_NODE_TYPES.CallExpression && expression.callee.type === _experimentalUtils.AST_NODE_TYPES.MemberExpression && (0, _utils.isSupportedAccessor)(expression.callee.object, 'expect') && (0, _utils.isSupportedAccessor)(expression.callee.property) && ['assertions', 'hasAssertions'].includes((0, _utils.getAccessorValue)(expression.callee.property));
+
+const isFirstLineExprStmt = functionBody => functionBody[0] && functionBody[0].type === _experimentalUtils.AST_NODE_TYPES.ExpressionStatement;
+
+const suggestRemovingExtraArguments = (args, extraArgsStartAt) => ({
+  messageId: 'suggestRemovingExtraArguments',
+  fix: fixer => fixer.removeRange([args[extraArgsStartAt].range[0] - Math.sign(extraArgsStartAt), args[args.length - 1].range[1]])
+});
+
+const suggestions = [['suggestAddingHasAssertions', 'expect.hasAssertions();'], ['suggestAddingAssertions', 'expect.assertions();']];
+
+var _default = (0, _utils.createRule)({
+  name: __filename,
+  meta: {
+    docs: {
+      category: 'Best Practices',
+      description: 'Suggest using `expect.assertions()` OR `expect.hasAssertions()`',
+      recommended: false,
+      suggestion: true
+    },
+    messages: {
+      hasAssertionsTakesNoArguments: '`expect.hasAssertions` expects no arguments',
+      assertionsRequiresOneArgument: '`expect.assertions` excepts a single argument of type number',
+      assertionsRequiresNumberArgument: 'This argument should be a number',
+      haveExpectAssertions: 'Every test should have either `expect.assertions(<number of assertions>)` or `expect.hasAssertions()` as its first expression',
+      suggestAddingHasAssertions: 'Add `expect.hasAssertions()`',
+      suggestAddingAssertions: 'Add `expect.assertions(<number of assertions>)`',
+      suggestRemovingExtraArguments: 'Remove extra arguments'
+    },
+    type: 'suggestion',
+    hasSuggestions: true,
+    schema: [{
+      type: 'object',
+      properties: {
+        onlyFunctionsWithAsyncKeyword: {
+          type: 'boolean'
+        },
+        onlyFunctionsWithExpectInLoop: {
+          type: 'boolean'
+        },
+        onlyFunctionsWithExpectInCallback: {
+          type: 'boolean'
+        }
+      },
+      additionalProperties: false
+    }]
+  },
+  defaultOptions: [{
+    onlyFunctionsWithAsyncKeyword: false,
+    onlyFunctionsWithExpectInLoop: false,
+    onlyFunctionsWithExpectInCallback: false
+  }],
+
+  create(context, [options]) {
+    let expressionDepth = 0;
+    let hasExpectInCallback = false;
+    let hasExpectInLoop = false;
+    let inTestCaseCall = false;
+    let inForLoop = false;
+
+    const shouldCheckFunction = testFunction => {
+      if (!options.onlyFunctionsWithAsyncKeyword && !options.onlyFunctionsWithExpectInLoop && !options.onlyFunctionsWithExpectInCallback) {
+        return true;
+      }
+
+      if (options.onlyFunctionsWithAsyncKeyword) {
+        if (testFunction.async) {
+          return true;
+        }
+      }
+
+      if (options.onlyFunctionsWithExpectInLoop) {
+        if (hasExpectInLoop) {
+          return true;
+        }
+      }
+
+      if (options.onlyFunctionsWithExpectInCallback) {
+        if (hasExpectInCallback) {
+          return true;
+        }
+      }
+
+      return false;
+    };
+
+    const enterExpression = () => inTestCaseCall && expressionDepth++;
+
+    const exitExpression = () => inTestCaseCall && expressionDepth--;
+
+    const enterForLoop = () => inForLoop = true;
+
+    const exitForLoop = () => inForLoop = false;
+
+    return {
+      FunctionExpression: enterExpression,
+      'FunctionExpression:exit': exitExpression,
+      ArrowFunctionExpression: enterExpression,
+      'ArrowFunctionExpression:exit': exitExpression,
+      ForStatement: enterForLoop,
+      'ForStatement:exit': exitForLoop,
+      ForInStatement: enterForLoop,
+      'ForInStatement:exit': exitForLoop,
+      ForOfStatement: enterForLoop,
+      'ForOfStatement:exit': exitForLoop,
+
+      CallExpression(node) {
+        if ((0, _utils.isTestCaseCall)(node)) {
+          inTestCaseCall = true;
+          return;
+        }
+
+        if ((0, _utils.isExpectCall)(node) && inTestCaseCall) {
+          if (inForLoop) {
+            hasExpectInLoop = true;
+          }
+
+          if (expressionDepth > 1) {
+            hasExpectInCallback = true;
+          }
+        }
+      },
+
+      'CallExpression:exit'(node) {
+        if (!(0, _utils.isTestCaseCall)(node)) {
+          return;
+        }
+
+        if (node.arguments.length < 2) {
+          return;
+        }
+
+        const [, testFn] = node.arguments;
+
+        if (!(0, _utils.isFunction)(testFn) || testFn.body.type !== _experimentalUtils.AST_NODE_TYPES.BlockStatement) {
+          return;
+        }
+
+        if (!shouldCheckFunction(testFn)) {
+          return;
+        }
+
+        hasExpectInLoop = false;
+        hasExpectInCallback = false;
+        const testFuncBody = testFn.body.body;
+
+        if (!isFirstLineExprStmt(testFuncBody)) {
+          context.report({
+            messageId: 'haveExpectAssertions',
+            node,
+            suggest: suggestions.map(([messageId, text]) => ({
+              messageId,
+              fix: fixer => fixer.insertTextBeforeRange([testFn.body.range[0] + 1, testFn.body.range[1]], text)
+            }))
+          });
+          return;
+        }
+
+        const testFuncFirstLine = testFuncBody[0].expression;
+
+        if (!isExpectAssertionsOrHasAssertionsCall(testFuncFirstLine)) {
+          context.report({
+            messageId: 'haveExpectAssertions',
+            node,
+            suggest: suggestions.map(([messageId, text]) => ({
+              messageId,
+              fix: fixer => fixer.insertTextBefore(testFuncBody[0], text)
+            }))
+          });
+          return;
+        }
+
+        if ((0, _utils.isSupportedAccessor)(testFuncFirstLine.callee.property, 'hasAssertions')) {
+          if (testFuncFirstLine.arguments.length) {
+            context.report({
+              messageId: 'hasAssertionsTakesNoArguments',
+              node: testFuncFirstLine.callee.property,
+              suggest: [suggestRemovingExtraArguments(testFuncFirstLine.arguments, 0)]
+            });
+          }
+
+          return;
+        }
+
+        if (!(0, _utils.hasOnlyOneArgument)(testFuncFirstLine)) {
+          let {
+            loc
+          } = testFuncFirstLine.callee.property;
+          const suggest = [];
+
+          if (testFuncFirstLine.arguments.length) {
+            loc = testFuncFirstLine.arguments[1].loc;
+            suggest.push(suggestRemovingExtraArguments(testFuncFirstLine.arguments, 1));
+          }
+
+          context.report({
+            messageId: 'assertionsRequiresOneArgument',
+            suggest,
+            loc
+          });
+          return;
+        }
+
+        const [arg] = testFuncFirstLine.arguments;
+
+        if (arg.type === _experimentalUtils.AST_NODE_TYPES.Literal && typeof arg.value === 'number' && Number.isInteger(arg.value)) {
+          return;
+        }
+
+        context.report({
+          messageId: 'assertionsRequiresNumberArgument',
+          node: arg
+        });
+      }
+
+    };
+  }
+
+});
+
+exports.default = _default;
Index: frontend/node_modules/eslint-plugin-jest/lib/rules/prefer-expect-resolves.js
===================================================================
--- frontend/node_modules/eslint-plugin-jest/lib/rules/prefer-expect-resolves.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/eslint-plugin-jest/lib/rules/prefer-expect-resolves.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,48 @@
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.default = void 0;
+
+var _experimentalUtils = require("@typescript-eslint/experimental-utils");
+
+var _utils = require("./utils");
+
+var _default = (0, _utils.createRule)({
+  name: __filename,
+  meta: {
+    docs: {
+      category: 'Best Practices',
+      description: 'Prefer `await expect(...).resolves` over `expect(await ...)` syntax',
+      recommended: false
+    },
+    fixable: 'code',
+    messages: {
+      expectResolves: 'Use `await expect(...).resolves instead.'
+    },
+    schema: [],
+    type: 'suggestion'
+  },
+  defaultOptions: [],
+  create: context => ({
+    CallExpression(node) {
+      const [awaitNode] = node.arguments;
+
+      if ((0, _utils.isExpectCall)(node) && (awaitNode === null || awaitNode === void 0 ? void 0 : awaitNode.type) === _experimentalUtils.AST_NODE_TYPES.AwaitExpression) {
+        context.report({
+          node: node.arguments[0],
+          messageId: 'expectResolves',
+
+          fix(fixer) {
+            return [fixer.insertTextBefore(node, 'await '), fixer.removeRange([awaitNode.range[0], awaitNode.argument.range[0]]), fixer.insertTextAfter(node, '.resolves')];
+          }
+
+        });
+      }
+    }
+
+  })
+});
+
+exports.default = _default;
Index: frontend/node_modules/eslint-plugin-jest/lib/rules/prefer-hooks-on-top.js
===================================================================
--- frontend/node_modules/eslint-plugin-jest/lib/rules/prefer-hooks-on-top.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/eslint-plugin-jest/lib/rules/prefer-hooks-on-top.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,53 @@
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.default = void 0;
+
+var _utils = require("./utils");
+
+var _default = (0, _utils.createRule)({
+  name: __filename,
+  meta: {
+    docs: {
+      category: 'Best Practices',
+      description: 'Suggest having hooks before any test cases',
+      recommended: false
+    },
+    messages: {
+      noHookOnTop: 'Hooks should come before test cases'
+    },
+    schema: [],
+    type: 'suggestion'
+  },
+  defaultOptions: [],
+
+  create(context) {
+    const hooksContext = [false];
+    return {
+      CallExpression(node) {
+        if (!(0, _utils.isHook)(node) && (0, _utils.isTestCaseCall)(node)) {
+          hooksContext[hooksContext.length - 1] = true;
+        }
+
+        if (hooksContext[hooksContext.length - 1] && (0, _utils.isHook)(node)) {
+          context.report({
+            messageId: 'noHookOnTop',
+            node
+          });
+        }
+
+        hooksContext.push(false);
+      },
+
+      'CallExpression:exit'() {
+        hooksContext.pop();
+      }
+
+    };
+  }
+
+});
+
+exports.default = _default;
Index: frontend/node_modules/eslint-plugin-jest/lib/rules/prefer-lowercase-title.js
===================================================================
--- frontend/node_modules/eslint-plugin-jest/lib/rules/prefer-lowercase-title.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/eslint-plugin-jest/lib/rules/prefer-lowercase-title.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,150 @@
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.default = void 0;
+
+var _utils = require("./utils");
+
+const hasStringAsFirstArgument = node => node.arguments[0] && (0, _utils.isStringNode)(node.arguments[0]);
+
+const findNodeNameAndArgument = node => {
+  if (!((0, _utils.isTestCaseCall)(node) || (0, _utils.isDescribeCall)(node))) {
+    return null;
+  }
+
+  if (!hasStringAsFirstArgument(node)) {
+    return null;
+  }
+
+  return [(0, _utils.getNodeName)(node).split('.')[0], node.arguments[0]];
+};
+
+const populateIgnores = ignore => {
+  const ignores = [];
+
+  if (ignore.includes(_utils.DescribeAlias.describe)) {
+    ignores.push(...Object.keys(_utils.DescribeAlias));
+  }
+
+  if (ignore.includes(_utils.TestCaseName.test)) {
+    ignores.push(...Object.keys(_utils.TestCaseName).filter(k => k.endsWith(_utils.TestCaseName.test)));
+  }
+
+  if (ignore.includes(_utils.TestCaseName.it)) {
+    ignores.push(...Object.keys(_utils.TestCaseName).filter(k => k.endsWith(_utils.TestCaseName.it)));
+  }
+
+  return ignores;
+};
+
+var _default = (0, _utils.createRule)({
+  name: __filename,
+  meta: {
+    type: 'suggestion',
+    docs: {
+      description: 'Enforce lowercase test names',
+      category: 'Best Practices',
+      recommended: false
+    },
+    fixable: 'code',
+    messages: {
+      unexpectedLowercase: '`{{ method }}`s should begin with lowercase'
+    },
+    schema: [{
+      type: 'object',
+      properties: {
+        ignore: {
+          type: 'array',
+          items: {
+            enum: [_utils.DescribeAlias.describe, _utils.TestCaseName.test, _utils.TestCaseName.it]
+          },
+          additionalItems: false
+        },
+        allowedPrefixes: {
+          type: 'array',
+          items: {
+            type: 'string'
+          },
+          additionalItems: false
+        },
+        ignoreTopLevelDescribe: {
+          type: 'boolean',
+          default: false
+        }
+      },
+      additionalProperties: false
+    }]
+  },
+  defaultOptions: [{
+    ignore: [],
+    allowedPrefixes: [],
+    ignoreTopLevelDescribe: false
+  }],
+
+  create(context, [{
+    ignore = [],
+    allowedPrefixes = [],
+    ignoreTopLevelDescribe
+  }]) {
+    const ignores = populateIgnores(ignore);
+    let numberOfDescribeBlocks = 0;
+    return {
+      CallExpression(node) {
+        if ((0, _utils.isDescribeCall)(node)) {
+          numberOfDescribeBlocks++;
+
+          if (ignoreTopLevelDescribe && numberOfDescribeBlocks === 1) {
+            return;
+          }
+        }
+
+        const results = findNodeNameAndArgument(node);
+
+        if (!results) {
+          return;
+        }
+
+        const [name, firstArg] = results;
+        const description = (0, _utils.getStringValue)(firstArg);
+
+        if (allowedPrefixes.some(name => description.startsWith(name))) {
+          return;
+        }
+
+        const firstCharacter = description.charAt(0);
+
+        if (!firstCharacter || firstCharacter === firstCharacter.toLowerCase() || ignores.includes(name)) {
+          return;
+        }
+
+        context.report({
+          messageId: 'unexpectedLowercase',
+          node: node.arguments[0],
+          data: {
+            method: name
+          },
+
+          fix(fixer) {
+            const description = (0, _utils.getStringValue)(firstArg);
+            const rangeIgnoringQuotes = [firstArg.range[0] + 1, firstArg.range[1] - 1];
+            const newDescription = description.substring(0, 1).toLowerCase() + description.substring(1);
+            return [fixer.replaceTextRange(rangeIgnoringQuotes, newDescription)];
+          }
+
+        });
+      },
+
+      'CallExpression:exit'(node) {
+        if ((0, _utils.isDescribeCall)(node)) {
+          numberOfDescribeBlocks--;
+        }
+      }
+
+    };
+  }
+
+});
+
+exports.default = _default;
Index: frontend/node_modules/eslint-plugin-jest/lib/rules/prefer-spy-on.js
===================================================================
--- frontend/node_modules/eslint-plugin-jest/lib/rules/prefer-spy-on.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/eslint-plugin-jest/lib/rules/prefer-spy-on.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,89 @@
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.default = void 0;
+
+var _experimentalUtils = require("@typescript-eslint/experimental-utils");
+
+var _utils = require("./utils");
+
+const findNodeObject = node => {
+  if ('object' in node) {
+    return node.object;
+  }
+
+  if (node.callee.type === _experimentalUtils.AST_NODE_TYPES.MemberExpression) {
+    return node.callee.object;
+  }
+
+  return null;
+};
+
+const getJestFnCall = node => {
+  if (node.type !== _experimentalUtils.AST_NODE_TYPES.CallExpression && node.type !== _experimentalUtils.AST_NODE_TYPES.MemberExpression) {
+    return null;
+  }
+
+  const obj = findNodeObject(node);
+
+  if (!obj) {
+    return null;
+  }
+
+  if (obj.type === _experimentalUtils.AST_NODE_TYPES.Identifier) {
+    return node.type === _experimentalUtils.AST_NODE_TYPES.CallExpression && (0, _utils.getNodeName)(node.callee) === 'jest.fn' ? node : null;
+  }
+
+  return getJestFnCall(obj);
+};
+
+var _default = (0, _utils.createRule)({
+  name: __filename,
+  meta: {
+    docs: {
+      category: 'Best Practices',
+      description: 'Suggest using `jest.spyOn()`',
+      recommended: false
+    },
+    messages: {
+      useJestSpyOn: 'Use jest.spyOn() instead.'
+    },
+    fixable: 'code',
+    schema: [],
+    type: 'suggestion'
+  },
+  defaultOptions: [],
+
+  create(context) {
+    return {
+      AssignmentExpression(node) {
+        const {
+          left,
+          right
+        } = node;
+        if (left.type !== _experimentalUtils.AST_NODE_TYPES.MemberExpression) return;
+        const jestFnCall = getJestFnCall(right);
+        if (!jestFnCall) return;
+        context.report({
+          node,
+          messageId: 'useJestSpyOn',
+
+          fix(fixer) {
+            const leftPropQuote = left.property.type === _experimentalUtils.AST_NODE_TYPES.Identifier ? "'" : '';
+            const [arg] = jestFnCall.arguments;
+            const argSource = arg && context.getSourceCode().getText(arg);
+            const mockImplementation = argSource ? `.mockImplementation(${argSource})` : '.mockImplementation()';
+            return [fixer.insertTextBefore(left, `jest.spyOn(`), fixer.replaceTextRange([left.object.range[1], left.property.range[0]], `, ${leftPropQuote}`), fixer.replaceTextRange([left.property.range[1], jestFnCall.range[1]], `${leftPropQuote})${mockImplementation}`)];
+          }
+
+        });
+      }
+
+    };
+  }
+
+});
+
+exports.default = _default;
Index: frontend/node_modules/eslint-plugin-jest/lib/rules/prefer-strict-equal.js
===================================================================
--- frontend/node_modules/eslint-plugin-jest/lib/rules/prefer-strict-equal.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/eslint-plugin-jest/lib/rules/prefer-strict-equal.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,57 @@
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.default = void 0;
+
+var _utils = require("./utils");
+
+var _default = (0, _utils.createRule)({
+  name: __filename,
+  meta: {
+    docs: {
+      category: 'Best Practices',
+      description: 'Suggest using `toStrictEqual()`',
+      recommended: false,
+      suggestion: true
+    },
+    messages: {
+      useToStrictEqual: 'Use `toStrictEqual()` instead',
+      suggestReplaceWithStrictEqual: 'Replace with `toStrictEqual()`'
+    },
+    type: 'suggestion',
+    schema: [],
+    hasSuggestions: true
+  },
+  defaultOptions: [],
+
+  create(context) {
+    return {
+      CallExpression(node) {
+        if (!(0, _utils.isExpectCall)(node)) {
+          return;
+        }
+
+        const {
+          matcher
+        } = (0, _utils.parseExpectCall)(node);
+
+        if (matcher && (0, _utils.isParsedEqualityMatcherCall)(matcher, _utils.EqualityMatcher.toEqual)) {
+          context.report({
+            messageId: 'useToStrictEqual',
+            node: matcher.node.property,
+            suggest: [{
+              messageId: 'suggestReplaceWithStrictEqual',
+              fix: fixer => [fixer.replaceText(matcher.node.property, _utils.EqualityMatcher.toStrictEqual)]
+            }]
+          });
+        }
+      }
+
+    };
+  }
+
+});
+
+exports.default = _default;
Index: frontend/node_modules/eslint-plugin-jest/lib/rules/prefer-to-be.js
===================================================================
--- frontend/node_modules/eslint-plugin-jest/lib/rules/prefer-to-be.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/eslint-plugin-jest/lib/rules/prefer-to-be.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,136 @@
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.default = void 0;
+
+var _experimentalUtils = require("@typescript-eslint/experimental-utils");
+
+var _utils = require("./utils");
+
+const isNullLiteral = node => node.type === _experimentalUtils.AST_NODE_TYPES.Literal && node.value === null;
+/**
+ * Checks if the given `ParsedEqualityMatcherCall` is a call to one of the equality matchers,
+ * with a `null` literal as the sole argument.
+ */
+
+
+const isNullEqualityMatcher = matcher => isNullLiteral(getFirstArgument(matcher));
+
+const isFirstArgumentIdentifier = (matcher, name) => (0, _utils.isIdentifier)(getFirstArgument(matcher), name);
+
+const shouldUseToBe = matcher => {
+  const firstArg = getFirstArgument(matcher);
+
+  if (firstArg.type === _experimentalUtils.AST_NODE_TYPES.Literal) {
+    // regex literals are classed as literals, but they're actually objects
+    // which means "toBe" will give different results than other matchers
+    return !('regex' in firstArg);
+  }
+
+  return firstArg.type === _experimentalUtils.AST_NODE_TYPES.TemplateLiteral;
+};
+
+const getFirstArgument = matcher => {
+  return (0, _utils.followTypeAssertionChain)(matcher.arguments[0]);
+};
+
+const reportPreferToBe = (context, whatToBe, matcher, modifier) => {
+  const modifierNode = (modifier === null || modifier === void 0 ? void 0 : modifier.negation) || (modifier === null || modifier === void 0 ? void 0 : modifier.name) === _utils.ModifierName.not && (modifier === null || modifier === void 0 ? void 0 : modifier.node);
+  context.report({
+    messageId: `useToBe${whatToBe}`,
+
+    fix(fixer) {
+      var _matcher$arguments;
+
+      const fixes = [fixer.replaceText(matcher.node.property, `toBe${whatToBe}`)];
+
+      if ((_matcher$arguments = matcher.arguments) !== null && _matcher$arguments !== void 0 && _matcher$arguments.length && whatToBe !== '') {
+        fixes.push(fixer.remove(matcher.arguments[0]));
+      }
+
+      if (modifierNode) {
+        fixes.push(fixer.removeRange([modifierNode.property.range[0] - 1, modifierNode.property.range[1]]));
+      }
+
+      return fixes;
+    },
+
+    node: matcher.node.property
+  });
+};
+
+var _default = (0, _utils.createRule)({
+  name: __filename,
+  meta: {
+    docs: {
+      category: 'Best Practices',
+      description: 'Suggest using `toBe()` for primitive literals',
+      recommended: false
+    },
+    messages: {
+      useToBe: 'Use `toBe` when expecting primitive literals',
+      useToBeUndefined: 'Use `toBeUndefined` instead',
+      useToBeDefined: 'Use `toBeDefined` instead',
+      useToBeNull: 'Use `toBeNull` instead',
+      useToBeNaN: 'Use `toBeNaN` instead'
+    },
+    fixable: 'code',
+    type: 'suggestion',
+    schema: []
+  },
+  defaultOptions: [],
+
+  create(context) {
+    return {
+      CallExpression(node) {
+        if (!(0, _utils.isExpectCall)(node)) {
+          return;
+        }
+
+        const {
+          matcher,
+          modifier
+        } = (0, _utils.parseExpectCall)(node);
+
+        if (!matcher) {
+          return;
+        }
+
+        if (((modifier === null || modifier === void 0 ? void 0 : modifier.name) === _utils.ModifierName.not || modifier !== null && modifier !== void 0 && modifier.negation) && ['toBeUndefined', 'toBeDefined'].includes(matcher.name)) {
+          reportPreferToBe(context, matcher.name === 'toBeDefined' ? 'Undefined' : 'Defined', matcher, modifier);
+          return;
+        }
+
+        if (!(0, _utils.isParsedEqualityMatcherCall)(matcher)) {
+          return;
+        }
+
+        if (isNullEqualityMatcher(matcher)) {
+          reportPreferToBe(context, 'Null', matcher);
+          return;
+        }
+
+        if (isFirstArgumentIdentifier(matcher, 'undefined')) {
+          const name = (modifier === null || modifier === void 0 ? void 0 : modifier.name) === _utils.ModifierName.not || modifier !== null && modifier !== void 0 && modifier.negation ? 'Defined' : 'Undefined';
+          reportPreferToBe(context, name, matcher, modifier);
+          return;
+        }
+
+        if (isFirstArgumentIdentifier(matcher, 'NaN')) {
+          reportPreferToBe(context, 'NaN', matcher);
+          return;
+        }
+
+        if (shouldUseToBe(matcher) && matcher.name !== _utils.EqualityMatcher.toBe) {
+          reportPreferToBe(context, '', matcher);
+        }
+      }
+
+    };
+  }
+
+});
+
+exports.default = _default;
Index: frontend/node_modules/eslint-plugin-jest/lib/rules/prefer-to-contain.js
===================================================================
--- frontend/node_modules/eslint-plugin-jest/lib/rules/prefer-to-contain.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/eslint-plugin-jest/lib/rules/prefer-to-contain.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,98 @@
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.default = void 0;
+
+var _experimentalUtils = require("@typescript-eslint/experimental-utils");
+
+var _utils = require("./utils");
+
+const isBooleanLiteral = node => node.type === _experimentalUtils.AST_NODE_TYPES.Literal && typeof node.value === 'boolean';
+
+/**
+ * Checks if the given `ParsedExpectMatcher` is a call to one of the equality matchers,
+ * with a boolean literal as the sole argument.
+ *
+ * @example javascript
+ * toBe(true);
+ * toEqual(false);
+ *
+ * @param {ParsedExpectMatcher} matcher
+ *
+ * @return {matcher is ParsedBooleanEqualityMatcher}
+ */
+const isBooleanEqualityMatcher = matcher => (0, _utils.isParsedEqualityMatcherCall)(matcher) && isBooleanLiteral((0, _utils.followTypeAssertionChain)(matcher.arguments[0]));
+
+/**
+ * Checks if the given `node` is a `CallExpression` representing the calling
+ * of an `includes`-like method that can be 'fixed' (using `toContain`).
+ *
+ * @param {CallExpression} node
+ *
+ * @return {node is FixableIncludesCallExpression}
+ */
+const isFixableIncludesCallExpression = node => node.type === _experimentalUtils.AST_NODE_TYPES.CallExpression && node.callee.type === _experimentalUtils.AST_NODE_TYPES.MemberExpression && (0, _utils.isSupportedAccessor)(node.callee.property, 'includes') && (0, _utils.hasOnlyOneArgument)(node); // expect(array.includes(<value>)[not.]{toBe,toEqual}(<boolean>)
+
+
+var _default = (0, _utils.createRule)({
+  name: __filename,
+  meta: {
+    docs: {
+      category: 'Best Practices',
+      description: 'Suggest using `toContain()`',
+      recommended: false
+    },
+    messages: {
+      useToContain: 'Use toContain() instead'
+    },
+    fixable: 'code',
+    type: 'suggestion',
+    schema: []
+  },
+  defaultOptions: [],
+
+  create(context) {
+    return {
+      CallExpression(node) {
+        if (!(0, _utils.isExpectCall)(node)) {
+          return;
+        }
+
+        const {
+          expect: {
+            arguments: [includesCall],
+            range: [, expectCallEnd]
+          },
+          matcher,
+          modifier
+        } = (0, _utils.parseExpectCall)(node);
+
+        if (!matcher || !includesCall || modifier && modifier.name !== _utils.ModifierName.not || !isBooleanEqualityMatcher(matcher) || !isFixableIncludesCallExpression(includesCall)) {
+          return;
+        }
+
+        context.report({
+          fix(fixer) {
+            const sourceCode = context.getSourceCode(); // we need to negate the expectation if the current expected
+            // value is itself negated by the "not" modifier
+
+            const addNotModifier = (0, _utils.followTypeAssertionChain)(matcher.arguments[0]).value === !!modifier;
+            return [// remove the "includes" call entirely
+            fixer.removeRange([includesCall.callee.property.range[0] - 1, includesCall.range[1]]), // replace the current matcher with "toContain", adding "not" if needed
+            fixer.replaceTextRange([expectCallEnd, matcher.node.range[1]], addNotModifier ? `.${_utils.ModifierName.not}.toContain` : '.toContain'), // replace the matcher argument with the value from the "includes"
+            fixer.replaceText(matcher.arguments[0], sourceCode.getText(includesCall.arguments[0]))];
+          },
+
+          messageId: 'useToContain',
+          node: (modifier || matcher).node.property
+        });
+      }
+
+    };
+  }
+
+});
+
+exports.default = _default;
Index: frontend/node_modules/eslint-plugin-jest/lib/rules/prefer-to-have-length.js
===================================================================
--- frontend/node_modules/eslint-plugin-jest/lib/rules/prefer-to-have-length.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/eslint-plugin-jest/lib/rules/prefer-to-have-length.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,64 @@
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.default = void 0;
+
+var _experimentalUtils = require("@typescript-eslint/experimental-utils");
+
+var _utils = require("./utils");
+
+var _default = (0, _utils.createRule)({
+  name: __filename,
+  meta: {
+    docs: {
+      category: 'Best Practices',
+      description: 'Suggest using `toHaveLength()`',
+      recommended: false
+    },
+    messages: {
+      useToHaveLength: 'Use toHaveLength() instead'
+    },
+    fixable: 'code',
+    type: 'suggestion',
+    schema: []
+  },
+  defaultOptions: [],
+
+  create(context) {
+    return {
+      CallExpression(node) {
+        if (!(0, _utils.isExpectCall)(node)) {
+          return;
+        }
+
+        const {
+          expect: {
+            arguments: [argument]
+          },
+          matcher
+        } = (0, _utils.parseExpectCall)(node);
+
+        if (!matcher || !(0, _utils.isParsedEqualityMatcherCall)(matcher) || (argument === null || argument === void 0 ? void 0 : argument.type) !== _experimentalUtils.AST_NODE_TYPES.MemberExpression || !(0, _utils.isSupportedAccessor)(argument.property, 'length')) {
+          return;
+        }
+
+        context.report({
+          fix(fixer) {
+            return [// remove the "length" property accessor
+            fixer.removeRange([argument.property.range[0] - 1, argument.range[1]]), // replace the current matcher with "toHaveLength"
+            fixer.replaceTextRange([matcher.node.object.range[1], matcher.node.range[1]], '.toHaveLength')];
+          },
+
+          messageId: 'useToHaveLength',
+          node: matcher.node.property
+        });
+      }
+
+    };
+  }
+
+});
+
+exports.default = _default;
Index: frontend/node_modules/eslint-plugin-jest/lib/rules/prefer-todo.js
===================================================================
--- frontend/node_modules/eslint-plugin-jest/lib/rules/prefer-todo.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/eslint-plugin-jest/lib/rules/prefer-todo.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,76 @@
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.default = void 0;
+
+var _experimentalUtils = require("@typescript-eslint/experimental-utils");
+
+var _utils = require("./utils");
+
+function isEmptyFunction(node) {
+  if (!(0, _utils.isFunction)(node)) {
+    return false;
+  }
+
+  return node.body.type === _experimentalUtils.AST_NODE_TYPES.BlockStatement && !node.body.body.length;
+}
+
+function createTodoFixer(node, fixer) {
+  const testName = (0, _utils.getNodeName)(node).split('.').shift();
+  return fixer.replaceText(node.callee, `${testName}.todo`);
+}
+
+const isTargetedTestCase = node => (0, _utils.isTestCaseCall)(node) && [_utils.TestCaseName.it, _utils.TestCaseName.test, 'it.skip', 'test.skip'].includes((0, _utils.getNodeName)(node));
+
+var _default = (0, _utils.createRule)({
+  name: __filename,
+  meta: {
+    docs: {
+      category: 'Best Practices',
+      description: 'Suggest using `test.todo`',
+      recommended: false
+    },
+    messages: {
+      emptyTest: 'Prefer todo test case over empty test case',
+      unimplementedTest: 'Prefer todo test case over unimplemented test case'
+    },
+    fixable: 'code',
+    schema: [],
+    type: 'layout'
+  },
+  defaultOptions: [],
+
+  create(context) {
+    return {
+      CallExpression(node) {
+        const [title, callback] = node.arguments;
+
+        if (!title || !isTargetedTestCase(node) || !(0, _utils.isStringNode)(title)) {
+          return;
+        }
+
+        if (callback && isEmptyFunction(callback)) {
+          context.report({
+            messageId: 'emptyTest',
+            node,
+            fix: fixer => [fixer.removeRange([title.range[1], callback.range[1]]), createTodoFixer(node, fixer)]
+          });
+        }
+
+        if ((0, _utils.hasOnlyOneArgument)(node)) {
+          context.report({
+            messageId: 'unimplementedTest',
+            node,
+            fix: fixer => [createTodoFixer(node, fixer)]
+          });
+        }
+      }
+
+    };
+  }
+
+});
+
+exports.default = _default;
Index: frontend/node_modules/eslint-plugin-jest/lib/rules/require-hook.js
===================================================================
--- frontend/node_modules/eslint-plugin-jest/lib/rules/require-hook.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/eslint-plugin-jest/lib/rules/require-hook.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,121 @@
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.default = void 0;
+
+var _experimentalUtils = require("@typescript-eslint/experimental-utils");
+
+var _utils = require("./utils");
+
+const isJestFnCall = node => {
+  var _getNodeName;
+
+  if ((0, _utils.isDescribeCall)(node) || (0, _utils.isTestCaseCall)(node) || (0, _utils.isHook)(node)) {
+    return true;
+  }
+
+  return !!((_getNodeName = (0, _utils.getNodeName)(node)) !== null && _getNodeName !== void 0 && _getNodeName.startsWith('jest.'));
+};
+
+const isNullOrUndefined = node => {
+  return node.type === _experimentalUtils.AST_NODE_TYPES.Literal && node.value === null || (0, _utils.isIdentifier)(node, 'undefined');
+};
+
+const shouldBeInHook = (node, allowedFunctionCalls = []) => {
+  switch (node.type) {
+    case _experimentalUtils.AST_NODE_TYPES.ExpressionStatement:
+      return shouldBeInHook(node.expression, allowedFunctionCalls);
+
+    case _experimentalUtils.AST_NODE_TYPES.CallExpression:
+      return !(isJestFnCall(node) || allowedFunctionCalls.includes((0, _utils.getNodeName)(node)));
+
+    case _experimentalUtils.AST_NODE_TYPES.VariableDeclaration:
+      {
+        if (node.kind === 'const') {
+          return false;
+        }
+
+        return node.declarations.some(({
+          init
+        }) => init !== null && !isNullOrUndefined(init));
+      }
+
+    default:
+      return false;
+  }
+};
+
+var _default = (0, _utils.createRule)({
+  name: __filename,
+  meta: {
+    docs: {
+      category: 'Best Practices',
+      description: 'Require setup and teardown code to be within a hook',
+      recommended: false
+    },
+    messages: {
+      useHook: 'This should be done within a hook'
+    },
+    type: 'suggestion',
+    schema: [{
+      type: 'object',
+      properties: {
+        allowedFunctionCalls: {
+          type: 'array',
+          items: {
+            type: 'string'
+          }
+        }
+      },
+      additionalProperties: false
+    }]
+  },
+  defaultOptions: [{
+    allowedFunctionCalls: []
+  }],
+
+  create(context) {
+    var _context$options$;
+
+    const {
+      allowedFunctionCalls
+    } = (_context$options$ = context.options[0]) !== null && _context$options$ !== void 0 ? _context$options$ : {};
+
+    const checkBlockBody = body => {
+      for (const statement of body) {
+        if (shouldBeInHook(statement, allowedFunctionCalls)) {
+          context.report({
+            node: statement,
+            messageId: 'useHook'
+          });
+        }
+      }
+    };
+
+    return {
+      Program(program) {
+        checkBlockBody(program.body);
+      },
+
+      CallExpression(node) {
+        if (!(0, _utils.isDescribeCall)(node) || node.arguments.length < 2) {
+          return;
+        }
+
+        const [, testFn] = node.arguments;
+
+        if (!(0, _utils.isFunction)(testFn) || testFn.body.type !== _experimentalUtils.AST_NODE_TYPES.BlockStatement) {
+          return;
+        }
+
+        checkBlockBody(testFn.body.body);
+      }
+
+    };
+  }
+
+});
+
+exports.default = _default;
Index: frontend/node_modules/eslint-plugin-jest/lib/rules/require-to-throw-message.js
===================================================================
--- frontend/node_modules/eslint-plugin-jest/lib/rules/require-to-throw-message.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/eslint-plugin-jest/lib/rules/require-to-throw-message.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,57 @@
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.default = void 0;
+
+var _utils = require("./utils");
+
+var _default = (0, _utils.createRule)({
+  name: __filename,
+  meta: {
+    docs: {
+      category: 'Best Practices',
+      description: 'Require a message for `toThrow()`',
+      recommended: false
+    },
+    messages: {
+      addErrorMessage: 'Add an error message to {{ matcherName }}()'
+    },
+    type: 'suggestion',
+    schema: []
+  },
+  defaultOptions: [],
+
+  create(context) {
+    return {
+      CallExpression(node) {
+        var _matcher$arguments;
+
+        if (!(0, _utils.isExpectCall)(node)) {
+          return;
+        }
+
+        const {
+          matcher,
+          modifier
+        } = (0, _utils.parseExpectCall)(node);
+
+        if ((matcher === null || matcher === void 0 ? void 0 : (_matcher$arguments = matcher.arguments) === null || _matcher$arguments === void 0 ? void 0 : _matcher$arguments.length) === 0 && ['toThrow', 'toThrowError'].includes(matcher.name) && (!modifier || !(modifier.name === _utils.ModifierName.not || modifier.negation))) {
+          // Look for `toThrow` calls with no arguments.
+          context.report({
+            messageId: 'addErrorMessage',
+            data: {
+              matcherName: matcher.name
+            },
+            node: matcher.node.property
+          });
+        }
+      }
+
+    };
+  }
+
+});
+
+exports.default = _default;
Index: frontend/node_modules/eslint-plugin-jest/lib/rules/require-top-level-describe.js
===================================================================
--- frontend/node_modules/eslint-plugin-jest/lib/rules/require-top-level-describe.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/eslint-plugin-jest/lib/rules/require-top-level-describe.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,100 @@
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.default = void 0;
+
+var _utils = require("./utils");
+
+const messages = {
+  tooManyDescribes: 'There should not be more than {{ max }} describe{{ s }} at the top level',
+  unexpectedTestCase: 'All test cases must be wrapped in a describe block.',
+  unexpectedHook: 'All hooks must be wrapped in a describe block.'
+};
+
+var _default = (0, _utils.createRule)({
+  name: __filename,
+  meta: {
+    docs: {
+      category: 'Best Practices',
+      description: 'Require test cases and hooks to be inside a `describe` block',
+      recommended: false
+    },
+    messages,
+    type: 'suggestion',
+    schema: [{
+      type: 'object',
+      properties: {
+        maxNumberOfTopLevelDescribes: {
+          type: 'number',
+          minimum: 1
+        }
+      },
+      additionalProperties: false
+    }]
+  },
+  defaultOptions: [{}],
+
+  create(context) {
+    var _context$options$;
+
+    const {
+      maxNumberOfTopLevelDescribes = Infinity
+    } = (_context$options$ = context.options[0]) !== null && _context$options$ !== void 0 ? _context$options$ : {};
+    let numberOfTopLevelDescribeBlocks = 0;
+    let numberOfDescribeBlocks = 0;
+    return {
+      CallExpression(node) {
+        if ((0, _utils.isDescribeCall)(node)) {
+          numberOfDescribeBlocks++;
+
+          if (numberOfDescribeBlocks === 1) {
+            numberOfTopLevelDescribeBlocks++;
+
+            if (numberOfTopLevelDescribeBlocks > maxNumberOfTopLevelDescribes) {
+              context.report({
+                node,
+                messageId: 'tooManyDescribes',
+                data: {
+                  max: maxNumberOfTopLevelDescribes,
+                  s: maxNumberOfTopLevelDescribes === 1 ? '' : 's'
+                }
+              });
+            }
+          }
+
+          return;
+        }
+
+        if (numberOfDescribeBlocks === 0) {
+          if ((0, _utils.isTestCaseCall)(node)) {
+            context.report({
+              node,
+              messageId: 'unexpectedTestCase'
+            });
+            return;
+          }
+
+          if ((0, _utils.isHook)(node)) {
+            context.report({
+              node,
+              messageId: 'unexpectedHook'
+            });
+            return;
+          }
+        }
+      },
+
+      'CallExpression:exit'(node) {
+        if ((0, _utils.isDescribeCall)(node)) {
+          numberOfDescribeBlocks--;
+        }
+      }
+
+    };
+  }
+
+});
+
+exports.default = _default;
Index: frontend/node_modules/eslint-plugin-jest/lib/rules/unbound-method.js
===================================================================
--- frontend/node_modules/eslint-plugin-jest/lib/rules/unbound-method.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/eslint-plugin-jest/lib/rules/unbound-method.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,113 @@
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.default = void 0;
+
+var _utils = require("./utils");
+
+const toThrowMatchers = ['toThrow', 'toThrowError', 'toThrowErrorMatchingSnapshot', 'toThrowErrorMatchingInlineSnapshot'];
+
+const isJestExpectToThrowCall = node => {
+  if (!(0, _utils.isExpectCall)(node)) {
+    return false;
+  }
+
+  const {
+    matcher
+  } = (0, _utils.parseExpectCall)(node);
+
+  if (!matcher) {
+    return false;
+  }
+
+  return !toThrowMatchers.includes(matcher.name);
+};
+
+const baseRule = (() => {
+  try {
+    // eslint-disable-next-line @typescript-eslint/no-require-imports
+    const TSESLintPlugin = require('@typescript-eslint/eslint-plugin');
+
+    return TSESLintPlugin.rules['unbound-method'];
+  } catch (e) {
+    const error = e;
+
+    if (error.code === 'MODULE_NOT_FOUND') {
+      return null;
+    }
+
+    throw error;
+  }
+})();
+
+const tryCreateBaseRule = context => {
+  try {
+    return baseRule === null || baseRule === void 0 ? void 0 : baseRule.create(context);
+  } catch {
+    return null;
+  }
+};
+
+const DEFAULT_MESSAGE = 'This rule requires `@typescript-eslint/eslint-plugin`';
+
+var _default = (0, _utils.createRule)({
+  defaultOptions: [{
+    ignoreStatic: false
+  }],
+  ...baseRule,
+  name: __filename,
+  meta: {
+    messages: {
+      unbound: DEFAULT_MESSAGE,
+      unboundWithoutThisAnnotation: DEFAULT_MESSAGE
+    },
+    schema: [],
+    type: 'problem',
+    ...(baseRule === null || baseRule === void 0 ? void 0 : baseRule.meta),
+    docs: {
+      category: 'Best Practices',
+      description: 'Enforces unbound methods are called with their expected scope',
+      requiresTypeChecking: true,
+      ...(baseRule === null || baseRule === void 0 ? void 0 : baseRule.meta.docs),
+      recommended: false
+    }
+  },
+
+  create(context) {
+    const baseSelectors = tryCreateBaseRule(context);
+
+    if (!baseSelectors) {
+      return {};
+    }
+
+    let inExpectToThrowCall = false;
+    return { ...baseSelectors,
+
+      CallExpression(node) {
+        inExpectToThrowCall = isJestExpectToThrowCall(node);
+      },
+
+      'CallExpression:exit'(node) {
+        if (inExpectToThrowCall && isJestExpectToThrowCall(node)) {
+          inExpectToThrowCall = false;
+        }
+      },
+
+      MemberExpression(node) {
+        var _baseSelectors$Member;
+
+        if (inExpectToThrowCall) {
+          return;
+        }
+
+        (_baseSelectors$Member = baseSelectors.MemberExpression) === null || _baseSelectors$Member === void 0 ? void 0 : _baseSelectors$Member.call(baseSelectors, node);
+      }
+
+    };
+  }
+
+});
+
+exports.default = _default;
Index: frontend/node_modules/eslint-plugin-jest/lib/rules/utils.js
===================================================================
--- frontend/node_modules/eslint-plugin-jest/lib/rules/utils.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/eslint-plugin-jest/lib/rules/utils.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,513 @@
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.getAccessorValue = exports.followTypeAssertionChain = exports.createRule = exports.TestCaseProperty = exports.TestCaseName = exports.ModifierName = exports.HookName = exports.EqualityMatcher = exports.DescribeProperty = exports.DescribeAlias = void 0;
+exports.getNodeName = getNodeName;
+exports.scopeHasLocalReference = exports.parseExpectCall = exports.isTestCaseCall = exports.isSupportedAccessor = exports.isStringNode = exports.isParsedEqualityMatcherCall = exports.isIdentifier = exports.isHook = exports.isFunction = exports.isExpectMember = exports.isExpectCall = exports.isDescribeCall = exports.hasOnlyOneArgument = exports.getTestCallExpressionsFromDeclaredVariables = exports.getStringValue = void 0;
+
+var _path = require("path");
+
+var _experimentalUtils = require("@typescript-eslint/experimental-utils");
+
+var _package = require("../../package.json");
+
+const REPO_URL = 'https://github.com/jest-community/eslint-plugin-jest';
+
+const createRule = _experimentalUtils.ESLintUtils.RuleCreator(name => {
+  const ruleName = (0, _path.parse)(name).name;
+  return `${REPO_URL}/blob/v${_package.version}/docs/rules/${ruleName}.md`;
+});
+
+exports.createRule = createRule;
+
+const isTypeCastExpression = node => node.type === _experimentalUtils.AST_NODE_TYPES.TSAsExpression || node.type === _experimentalUtils.AST_NODE_TYPES.TSTypeAssertion;
+
+const followTypeAssertionChain = expression => isTypeCastExpression(expression) ? followTypeAssertionChain(expression.expression) : expression;
+/**
+ * A `Literal` with a `value` of type `string`.
+ */
+
+
+exports.followTypeAssertionChain = followTypeAssertionChain;
+
+/**
+ * Checks if the given `node` is a `StringLiteral`.
+ *
+ * If a `value` is provided & the `node` is a `StringLiteral`,
+ * the `value` will be compared to that of the `StringLiteral`.
+ *
+ * @param {Node} node
+ * @param {V} [value]
+ *
+ * @return {node is StringLiteral<V>}
+ *
+ * @template V
+ */
+const isStringLiteral = (node, value) => node.type === _experimentalUtils.AST_NODE_TYPES.Literal && typeof node.value === 'string' && (value === undefined || node.value === value);
+
+/**
+ * Checks if the given `node` is a `TemplateLiteral`.
+ *
+ * Complex `TemplateLiteral`s are not considered specific, and so will return `false`.
+ *
+ * If a `value` is provided & the `node` is a `TemplateLiteral`,
+ * the `value` will be compared to that of the `TemplateLiteral`.
+ *
+ * @param {Node} node
+ * @param {V} [value]
+ *
+ * @return {node is TemplateLiteral<V>}
+ *
+ * @template V
+ */
+const isTemplateLiteral = (node, value) => node.type === _experimentalUtils.AST_NODE_TYPES.TemplateLiteral && node.quasis.length === 1 && ( // bail out if not simple
+value === undefined || node.quasis[0].value.raw === value);
+
+/**
+ * Checks if the given `node` is a {@link StringNode}.
+ *
+ * @param {Node} node
+ * @param {V} [specifics]
+ *
+ * @return {node is StringNode}
+ *
+ * @template V
+ */
+const isStringNode = (node, specifics) => isStringLiteral(node, specifics) || isTemplateLiteral(node, specifics);
+/**
+ * Gets the value of the given `StringNode`.
+ *
+ * If the `node` is a `TemplateLiteral`, the `raw` value is used;
+ * otherwise, `value` is returned instead.
+ *
+ * @param {StringNode<S>} node
+ *
+ * @return {S}
+ *
+ * @template S
+ */
+
+
+exports.isStringNode = isStringNode;
+
+const getStringValue = node => isTemplateLiteral(node) ? node.quasis[0].value.raw : node.value;
+/**
+ * Represents a `MemberExpression` with a "known" `property`.
+ */
+
+
+exports.getStringValue = getStringValue;
+
+/**
+ * Guards that the given `call` has only one `argument`.
+ *
+ * @param {CallExpression} call
+ *
+ * @return {call is CallExpressionWithSingleArgument}
+ */
+const hasOnlyOneArgument = call => call.arguments.length === 1;
+/**
+ * An `Identifier` with a known `name` value - i.e `expect`.
+ */
+
+
+exports.hasOnlyOneArgument = hasOnlyOneArgument;
+
+/**
+ * Checks if the given `node` is an `Identifier`.
+ *
+ * If a `name` is provided, & the `node` is an `Identifier`,
+ * the `name` will be compared to that of the `identifier`.
+ *
+ * @param {Node} node
+ * @param {V} [name]
+ *
+ * @return {node is KnownIdentifier<Name>}
+ *
+ * @template V
+ */
+const isIdentifier = (node, name) => node.type === _experimentalUtils.AST_NODE_TYPES.Identifier && (name === undefined || node.name === name);
+/**
+ * Checks if the given `node` is a "supported accessor".
+ *
+ * This means that it's a node can be used to access properties,
+ * and who's "value" can be statically determined.
+ *
+ * `MemberExpression` nodes most commonly contain accessors,
+ * but it's possible for other nodes to contain them.
+ *
+ * If a `value` is provided & the `node` is an `AccessorNode`,
+ * the `value` will be compared to that of the `AccessorNode`.
+ *
+ * Note that `value` here refers to the normalised value.
+ * The property that holds the value is not always called `name`.
+ *
+ * @param {Node} node
+ * @param {V} [value]
+ *
+ * @return {node is AccessorNode<V>}
+ *
+ * @template V
+ */
+
+
+exports.isIdentifier = isIdentifier;
+
+const isSupportedAccessor = (node, value) => isIdentifier(node, value) || isStringNode(node, value);
+/**
+ * Gets the value of the given `AccessorNode`,
+ * account for the different node types.
+ *
+ * @param {AccessorNode<S>} accessor
+ *
+ * @return {S}
+ *
+ * @template S
+ */
+
+
+exports.isSupportedAccessor = isSupportedAccessor;
+
+const getAccessorValue = accessor => accessor.type === _experimentalUtils.AST_NODE_TYPES.Identifier ? accessor.name : getStringValue(accessor);
+
+exports.getAccessorValue = getAccessorValue;
+
+/**
+ * Checks if the given `node` is a valid `ExpectCall`.
+ *
+ * In order to be an `ExpectCall`, the `node` must:
+ *  * be a `CallExpression`,
+ *  * have an accessor named 'expect',
+ *  * have a `parent`.
+ *
+ * @param {Node} node
+ *
+ * @return {node is ExpectCall}
+ */
+const isExpectCall = node => node.type === _experimentalUtils.AST_NODE_TYPES.CallExpression && isSupportedAccessor(node.callee, 'expect') && node.parent !== undefined;
+
+exports.isExpectCall = isExpectCall;
+
+const isExpectMember = (node, name) => node.type === _experimentalUtils.AST_NODE_TYPES.MemberExpression && isSupportedAccessor(node.property, name);
+/**
+ * Represents all the jest matchers.
+ */
+
+
+exports.isExpectMember = isExpectMember;
+let ModifierName;
+exports.ModifierName = ModifierName;
+
+(function (ModifierName) {
+  ModifierName["not"] = "not";
+  ModifierName["rejects"] = "rejects";
+  ModifierName["resolves"] = "resolves";
+})(ModifierName || (exports.ModifierName = ModifierName = {}));
+
+let EqualityMatcher;
+exports.EqualityMatcher = EqualityMatcher;
+
+(function (EqualityMatcher) {
+  EqualityMatcher["toBe"] = "toBe";
+  EqualityMatcher["toEqual"] = "toEqual";
+  EqualityMatcher["toStrictEqual"] = "toStrictEqual";
+})(EqualityMatcher || (exports.EqualityMatcher = EqualityMatcher = {}));
+
+const isParsedEqualityMatcherCall = (matcher, name) => (name ? matcher.name === name : EqualityMatcher.hasOwnProperty(matcher.name)) && matcher.arguments !== null && matcher.arguments.length === 1;
+/**
+ * Represents a parsed expect matcher, such as `toBe`, `toContain`, and so on.
+ */
+
+
+exports.isParsedEqualityMatcherCall = isParsedEqualityMatcherCall;
+
+const parseExpectMember = expectMember => ({
+  name: getAccessorValue(expectMember.property),
+  node: expectMember
+});
+
+const reparseAsMatcher = parsedMember => ({ ...parsedMember,
+
+  /**
+   * The arguments being passed to this `Matcher`, if any.
+   *
+   * If this matcher isn't called, this will be `null`.
+   */
+  arguments: parsedMember.node.parent.type === _experimentalUtils.AST_NODE_TYPES.CallExpression ? parsedMember.node.parent.arguments : null
+});
+/**
+ * Re-parses the given `parsedMember` as a `ParsedExpectModifier`.
+ *
+ * If the given `parsedMember` does not have a `name` of a valid `Modifier`,
+ * an exception will be thrown.
+ *
+ * @param {ParsedExpectMember<ModifierName>} parsedMember
+ *
+ * @return {ParsedExpectModifier}
+ */
+
+
+const reparseMemberAsModifier = parsedMember => {
+  if (isSpecificMember(parsedMember, ModifierName.not)) {
+    return parsedMember;
+  }
+  /* istanbul ignore if */
+
+
+  if (!isSpecificMember(parsedMember, ModifierName.resolves) && !isSpecificMember(parsedMember, ModifierName.rejects)) {
+    // ts doesn't think that the ModifierName.not check is the direct inverse as the above two checks
+    // todo: impossible at runtime, but can't be typed w/o negation support
+    throw new Error(`modifier name must be either "${ModifierName.resolves}" or "${ModifierName.rejects}" (got "${parsedMember.name}")`);
+  }
+
+  const negation = isExpectMember(parsedMember.node.parent, ModifierName.not) ? parsedMember.node.parent : undefined;
+  return { ...parsedMember,
+    negation
+  };
+};
+
+const isSpecificMember = (member, specific) => member.name === specific;
+/**
+ * Checks if the given `ParsedExpectMember` should be re-parsed as an `ParsedExpectModifier`.
+ *
+ * @param {ParsedExpectMember} member
+ *
+ * @return {member is ParsedExpectMember<ModifierName>}
+ */
+
+
+const shouldBeParsedExpectModifier = member => ModifierName.hasOwnProperty(member.name);
+
+const parseExpectCall = expect => {
+  const expectation = {
+    expect
+  };
+
+  if (!isExpectMember(expect.parent)) {
+    return expectation;
+  }
+
+  const parsedMember = parseExpectMember(expect.parent);
+
+  if (!shouldBeParsedExpectModifier(parsedMember)) {
+    expectation.matcher = reparseAsMatcher(parsedMember);
+    return expectation;
+  }
+
+  const modifier = expectation.modifier = reparseMemberAsModifier(parsedMember);
+  const memberNode = modifier.negation || modifier.node;
+
+  if (!isExpectMember(memberNode.parent)) {
+    return expectation;
+  }
+
+  expectation.matcher = reparseAsMatcher(parseExpectMember(memberNode.parent));
+  return expectation;
+};
+
+exports.parseExpectCall = parseExpectCall;
+let DescribeAlias;
+exports.DescribeAlias = DescribeAlias;
+
+(function (DescribeAlias) {
+  DescribeAlias["describe"] = "describe";
+  DescribeAlias["fdescribe"] = "fdescribe";
+  DescribeAlias["xdescribe"] = "xdescribe";
+})(DescribeAlias || (exports.DescribeAlias = DescribeAlias = {}));
+
+let TestCaseName;
+exports.TestCaseName = TestCaseName;
+
+(function (TestCaseName) {
+  TestCaseName["fit"] = "fit";
+  TestCaseName["it"] = "it";
+  TestCaseName["test"] = "test";
+  TestCaseName["xit"] = "xit";
+  TestCaseName["xtest"] = "xtest";
+})(TestCaseName || (exports.TestCaseName = TestCaseName = {}));
+
+let HookName;
+exports.HookName = HookName;
+
+(function (HookName) {
+  HookName["beforeAll"] = "beforeAll";
+  HookName["beforeEach"] = "beforeEach";
+  HookName["afterAll"] = "afterAll";
+  HookName["afterEach"] = "afterEach";
+})(HookName || (exports.HookName = HookName = {}));
+
+let DescribeProperty;
+exports.DescribeProperty = DescribeProperty;
+
+(function (DescribeProperty) {
+  DescribeProperty["each"] = "each";
+  DescribeProperty["only"] = "only";
+  DescribeProperty["skip"] = "skip";
+})(DescribeProperty || (exports.DescribeProperty = DescribeProperty = {}));
+
+let TestCaseProperty;
+exports.TestCaseProperty = TestCaseProperty;
+
+(function (TestCaseProperty) {
+  TestCaseProperty["each"] = "each";
+  TestCaseProperty["concurrent"] = "concurrent";
+  TestCaseProperty["only"] = "only";
+  TestCaseProperty["skip"] = "skip";
+  TestCaseProperty["todo"] = "todo";
+})(TestCaseProperty || (exports.TestCaseProperty = TestCaseProperty = {}));
+
+const joinNames = (a, b) => a && b ? `${a}.${b}` : null;
+
+function getNodeName(node) {
+  if (isSupportedAccessor(node)) {
+    return getAccessorValue(node);
+  }
+
+  switch (node.type) {
+    case _experimentalUtils.AST_NODE_TYPES.TaggedTemplateExpression:
+      return getNodeName(node.tag);
+
+    case _experimentalUtils.AST_NODE_TYPES.MemberExpression:
+      return joinNames(getNodeName(node.object), getNodeName(node.property));
+
+    case _experimentalUtils.AST_NODE_TYPES.NewExpression:
+    case _experimentalUtils.AST_NODE_TYPES.CallExpression:
+      return getNodeName(node.callee);
+  }
+
+  return null;
+}
+
+const isFunction = node => node.type === _experimentalUtils.AST_NODE_TYPES.FunctionExpression || node.type === _experimentalUtils.AST_NODE_TYPES.ArrowFunctionExpression;
+
+exports.isFunction = isFunction;
+
+const isHook = node => node.callee.type === _experimentalUtils.AST_NODE_TYPES.Identifier && HookName.hasOwnProperty(node.callee.name);
+
+exports.isHook = isHook;
+
+const getTestCallExpressionsFromDeclaredVariables = declaredVariables => {
+  return declaredVariables.reduce((acc, {
+    references
+  }) => acc.concat(references.map(({
+    identifier
+  }) => identifier.parent).filter(node => !!node && node.type === _experimentalUtils.AST_NODE_TYPES.CallExpression && isTestCaseCall(node))), []);
+};
+
+exports.getTestCallExpressionsFromDeclaredVariables = getTestCallExpressionsFromDeclaredVariables;
+
+const isTestCaseName = node => node.type === _experimentalUtils.AST_NODE_TYPES.Identifier && TestCaseName.hasOwnProperty(node.name);
+
+const isTestCaseProperty = node => isSupportedAccessor(node) && TestCaseProperty.hasOwnProperty(getAccessorValue(node));
+/**
+ * Checks if the given `node` is a *call* to a test case function that would
+ * result in tests being run by `jest`.
+ *
+ * Note that `.each()` does not count as a call in this context, as it will not
+ * result in `jest` running any tests.
+ *
+ * @param {TSESTree.CallExpression} node
+ *
+ * @return {node is JestFunctionCallExpression<TestCaseName>}
+ */
+
+
+const isTestCaseCall = node => {
+  if (isTestCaseName(node.callee)) {
+    return true;
+  }
+
+  const callee = node.callee.type === _experimentalUtils.AST_NODE_TYPES.TaggedTemplateExpression ? node.callee.tag : node.callee.type === _experimentalUtils.AST_NODE_TYPES.CallExpression ? node.callee.callee : node.callee;
+
+  if (callee.type === _experimentalUtils.AST_NODE_TYPES.MemberExpression && isTestCaseProperty(callee.property)) {
+    // if we're an `each()`, ensure we're the outer CallExpression (i.e `.each()()`)
+    if (getAccessorValue(callee.property) === 'each' && node.callee.type !== _experimentalUtils.AST_NODE_TYPES.TaggedTemplateExpression && node.callee.type !== _experimentalUtils.AST_NODE_TYPES.CallExpression) {
+      return false;
+    }
+
+    return callee.object.type === _experimentalUtils.AST_NODE_TYPES.MemberExpression ? isTestCaseName(callee.object.object) : isTestCaseName(callee.object);
+  }
+
+  return false;
+};
+
+exports.isTestCaseCall = isTestCaseCall;
+
+const isDescribeAlias = node => node.type === _experimentalUtils.AST_NODE_TYPES.Identifier && DescribeAlias.hasOwnProperty(node.name);
+
+const isDescribeProperty = node => isSupportedAccessor(node) && DescribeProperty.hasOwnProperty(getAccessorValue(node));
+/**
+ * Checks if the given `node` is a *call* to a `describe` function that would
+ * result in a `describe` block being created by `jest`.
+ *
+ * Note that `.each()` does not count as a call in this context, as it will not
+ * result in `jest` creating any `describe` blocks.
+ *
+ * @param {TSESTree.CallExpression} node
+ *
+ * @return {node is JestFunctionCallExpression<TestCaseName>}
+ */
+
+
+const isDescribeCall = node => {
+  if (isDescribeAlias(node.callee)) {
+    return true;
+  }
+
+  const callee = node.callee.type === _experimentalUtils.AST_NODE_TYPES.TaggedTemplateExpression ? node.callee.tag : node.callee.type === _experimentalUtils.AST_NODE_TYPES.CallExpression ? node.callee.callee : node.callee;
+
+  if (callee.type === _experimentalUtils.AST_NODE_TYPES.MemberExpression && isDescribeProperty(callee.property)) {
+    // if we're an `each()`, ensure we're the outer CallExpression (i.e `.each()()`)
+    if (getAccessorValue(callee.property) === 'each' && node.callee.type !== _experimentalUtils.AST_NODE_TYPES.TaggedTemplateExpression && node.callee.type !== _experimentalUtils.AST_NODE_TYPES.CallExpression) {
+      return false;
+    }
+
+    return callee.object.type === _experimentalUtils.AST_NODE_TYPES.MemberExpression ? isDescribeAlias(callee.object.object) : isDescribeAlias(callee.object);
+  }
+
+  return false;
+};
+
+exports.isDescribeCall = isDescribeCall;
+
+const collectReferences = scope => {
+  const locals = new Set();
+  const unresolved = new Set();
+  let currentScope = scope;
+
+  while (currentScope !== null) {
+    for (const ref of currentScope.variables) {
+      const isReferenceDefined = ref.defs.some(def => {
+        return def.type !== 'ImplicitGlobalVariable';
+      });
+
+      if (isReferenceDefined) {
+        locals.add(ref.name);
+      }
+    }
+
+    for (const ref of currentScope.through) {
+      unresolved.add(ref.identifier.name);
+    }
+
+    currentScope = currentScope.upper;
+  }
+
+  return {
+    locals,
+    unresolved
+  };
+};
+
+const scopeHasLocalReference = (scope, referenceName) => {
+  const references = collectReferences(scope);
+  return (// referenceName was found as a local variable or function declaration.
+    references.locals.has(referenceName) || // referenceName was not found as an unresolved reference,
+    // meaning it is likely not an implicit global reference.
+    !references.unresolved.has(referenceName)
+  );
+};
+
+exports.scopeHasLocalReference = scopeHasLocalReference;
Index: frontend/node_modules/eslint-plugin-jest/lib/rules/valid-describe-callback.js
===================================================================
--- frontend/node_modules/eslint-plugin-jest/lib/rules/valid-describe-callback.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/eslint-plugin-jest/lib/rules/valid-describe-callback.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,111 @@
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.default = void 0;
+
+var _experimentalUtils = require("@typescript-eslint/experimental-utils");
+
+var _utils = require("./utils");
+
+const paramsLocation = params => {
+  const [first] = params;
+  const last = params[params.length - 1];
+  return {
+    start: first.loc.start,
+    end: last.loc.end
+  };
+};
+
+var _default = (0, _utils.createRule)({
+  name: __filename,
+  meta: {
+    type: 'problem',
+    docs: {
+      category: 'Possible Errors',
+      description: 'Enforce valid `describe()` callback',
+      recommended: 'error'
+    },
+    messages: {
+      nameAndCallback: 'Describe requires name and callback arguments',
+      secondArgumentMustBeFunction: 'Second argument must be function',
+      noAsyncDescribeCallback: 'No async describe callback',
+      unexpectedDescribeArgument: 'Unexpected argument(s) in describe callback',
+      unexpectedReturnInDescribe: 'Unexpected return statement in describe callback'
+    },
+    schema: []
+  },
+  defaultOptions: [],
+
+  create(context) {
+    return {
+      CallExpression(node) {
+        if (!(0, _utils.isDescribeCall)(node)) {
+          return;
+        }
+
+        if (node.arguments.length < 1) {
+          return context.report({
+            messageId: 'nameAndCallback',
+            loc: node.loc
+          });
+        }
+
+        const [, callback] = node.arguments;
+
+        if (!callback) {
+          context.report({
+            messageId: 'nameAndCallback',
+            loc: paramsLocation(node.arguments)
+          });
+          return;
+        }
+
+        if (!(0, _utils.isFunction)(callback)) {
+          context.report({
+            messageId: 'secondArgumentMustBeFunction',
+            loc: paramsLocation(node.arguments)
+          });
+          return;
+        }
+
+        if (callback.async) {
+          context.report({
+            messageId: 'noAsyncDescribeCallback',
+            node: callback
+          });
+        }
+
+        if (!(0, _utils.getNodeName)(node).endsWith('each') && callback.params.length) {
+          context.report({
+            messageId: 'unexpectedDescribeArgument',
+            loc: paramsLocation(callback.params)
+          });
+        }
+
+        if (callback.body.type === _experimentalUtils.AST_NODE_TYPES.CallExpression) {
+          context.report({
+            messageId: 'unexpectedReturnInDescribe',
+            node: callback
+          });
+        }
+
+        if (callback.body.type === _experimentalUtils.AST_NODE_TYPES.BlockStatement) {
+          callback.body.body.forEach(node => {
+            if (node.type === _experimentalUtils.AST_NODE_TYPES.ReturnStatement) {
+              context.report({
+                messageId: 'unexpectedReturnInDescribe',
+                node
+              });
+            }
+          });
+        }
+      }
+
+    };
+  }
+
+});
+
+exports.default = _default;
Index: frontend/node_modules/eslint-plugin-jest/lib/rules/valid-expect-in-promise.js
===================================================================
--- frontend/node_modules/eslint-plugin-jest/lib/rules/valid-expect-in-promise.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/eslint-plugin-jest/lib/rules/valid-expect-in-promise.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,409 @@
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.default = void 0;
+
+var _experimentalUtils = require("@typescript-eslint/experimental-utils");
+
+var _utils = require("./utils");
+
+const isPromiseChainCall = node => {
+  if (node.type === _experimentalUtils.AST_NODE_TYPES.CallExpression && node.callee.type === _experimentalUtils.AST_NODE_TYPES.MemberExpression && (0, _utils.isSupportedAccessor)(node.callee.property)) {
+    // promise methods should have at least 1 argument
+    if (node.arguments.length === 0) {
+      return false;
+    }
+
+    switch ((0, _utils.getAccessorValue)(node.callee.property)) {
+      case 'then':
+        return node.arguments.length < 3;
+
+      case 'catch':
+      case 'finally':
+        return node.arguments.length < 2;
+    }
+  }
+
+  return false;
+};
+
+const findTopMostCallExpression = node => {
+  let topMostCallExpression = node;
+  let {
+    parent
+  } = node;
+
+  while (parent) {
+    if (parent.type === _experimentalUtils.AST_NODE_TYPES.CallExpression) {
+      topMostCallExpression = parent;
+      parent = parent.parent;
+      continue;
+    }
+
+    if (parent.type !== _experimentalUtils.AST_NODE_TYPES.MemberExpression) {
+      break;
+    }
+
+    parent = parent.parent;
+  }
+
+  return topMostCallExpression;
+};
+
+const isTestCaseCallWithCallbackArg = node => {
+  if (!(0, _utils.isTestCaseCall)(node)) {
+    return false;
+  }
+
+  const isJestEach = (0, _utils.getNodeName)(node).endsWith('.each');
+
+  if (isJestEach && node.callee.type !== _experimentalUtils.AST_NODE_TYPES.TaggedTemplateExpression) {
+    // isJestEach but not a TaggedTemplateExpression, so this must be
+    // the `jest.each([])()` syntax which this rule doesn't support due
+    // to its complexity (see jest-community/eslint-plugin-jest#710)
+    // so we return true to trigger bailout
+    return true;
+  }
+
+  if (isJestEach || node.arguments.length >= 2) {
+    const [, callback] = node.arguments;
+    const callbackArgIndex = Number(isJestEach);
+    return callback && (0, _utils.isFunction)(callback) && callback.params.length === 1 + callbackArgIndex;
+  }
+
+  return false;
+};
+
+const isPromiseMethodThatUsesValue = (node, identifier) => {
+  const {
+    name
+  } = identifier;
+
+  if (node.argument === null) {
+    return false;
+  }
+
+  if (node.argument.type === _experimentalUtils.AST_NODE_TYPES.CallExpression && node.argument.arguments.length > 0) {
+    const nodeName = (0, _utils.getNodeName)(node.argument);
+
+    if (['Promise.all', 'Promise.allSettled'].includes(nodeName)) {
+      const [firstArg] = node.argument.arguments;
+
+      if (firstArg.type === _experimentalUtils.AST_NODE_TYPES.ArrayExpression && firstArg.elements.some(nod => (0, _utils.isIdentifier)(nod, name))) {
+        return true;
+      }
+    }
+
+    if (['Promise.resolve', 'Promise.reject'].includes(nodeName) && node.argument.arguments.length === 1) {
+      return (0, _utils.isIdentifier)(node.argument.arguments[0], name);
+    }
+  }
+
+  return (0, _utils.isIdentifier)(node.argument, name);
+};
+/**
+ * Attempts to determine if the runtime value represented by the given `identifier`
+ * is `await`ed within the given array of elements
+ */
+
+
+const isValueAwaitedInElements = (name, elements) => {
+  for (const element of elements) {
+    if (element.type === _experimentalUtils.AST_NODE_TYPES.AwaitExpression && (0, _utils.isIdentifier)(element.argument, name)) {
+      return true;
+    }
+
+    if (element.type === _experimentalUtils.AST_NODE_TYPES.ArrayExpression && isValueAwaitedInElements(name, element.elements)) {
+      return true;
+    }
+  }
+
+  return false;
+};
+/**
+ * Attempts to determine if the runtime value represented by the given `identifier`
+ * is `await`ed as an argument along the given call expression
+ */
+
+
+const isValueAwaitedInArguments = (name, call) => {
+  let node = call;
+
+  while (node) {
+    if (node.type === _experimentalUtils.AST_NODE_TYPES.CallExpression) {
+      if (isValueAwaitedInElements(name, node.arguments)) {
+        return true;
+      }
+
+      node = node.callee;
+    }
+
+    if (node.type !== _experimentalUtils.AST_NODE_TYPES.MemberExpression) {
+      break;
+    }
+
+    node = node.object;
+  }
+
+  return false;
+};
+
+const getLeftMostCallExpression = call => {
+  let leftMostCallExpression = call;
+  let node = call;
+
+  while (node) {
+    if (node.type === _experimentalUtils.AST_NODE_TYPES.CallExpression) {
+      leftMostCallExpression = node;
+      node = node.callee;
+    }
+
+    if (node.type !== _experimentalUtils.AST_NODE_TYPES.MemberExpression) {
+      break;
+    }
+
+    node = node.object;
+  }
+
+  return leftMostCallExpression;
+};
+/**
+ * Attempts to determine if the runtime value represented by the given `identifier`
+ * is `await`ed or `return`ed within the given `body` of statements
+ */
+
+
+const isValueAwaitedOrReturned = (identifier, body) => {
+  const {
+    name
+  } = identifier;
+
+  for (const node of body) {
+    // skip all nodes that are before this identifier, because they'd probably
+    // be affecting a different runtime value (e.g. due to reassignment)
+    if (node.range[0] <= identifier.range[0]) {
+      continue;
+    }
+
+    if (node.type === _experimentalUtils.AST_NODE_TYPES.ReturnStatement) {
+      return isPromiseMethodThatUsesValue(node, identifier);
+    }
+
+    if (node.type === _experimentalUtils.AST_NODE_TYPES.ExpressionStatement) {
+      // it's possible that we're awaiting the value as an argument
+      if (node.expression.type === _experimentalUtils.AST_NODE_TYPES.CallExpression) {
+        if (isValueAwaitedInArguments(name, node.expression)) {
+          return true;
+        }
+
+        const leftMostCall = getLeftMostCallExpression(node.expression);
+
+        if ((0, _utils.isExpectCall)(leftMostCall) && leftMostCall.arguments.length > 0 && (0, _utils.isIdentifier)(leftMostCall.arguments[0], name)) {
+          const {
+            modifier
+          } = (0, _utils.parseExpectCall)(leftMostCall);
+
+          if ((modifier === null || modifier === void 0 ? void 0 : modifier.name) === _utils.ModifierName.resolves || (modifier === null || modifier === void 0 ? void 0 : modifier.name) === _utils.ModifierName.rejects) {
+            return true;
+          }
+        }
+      }
+
+      if (node.expression.type === _experimentalUtils.AST_NODE_TYPES.AwaitExpression && isPromiseMethodThatUsesValue(node.expression, identifier)) {
+        return true;
+      } // (re)assignment changes the runtime value, so if we've not found an
+      // await or return already we act as if we've reached the end of the body
+
+
+      if (node.expression.type === _experimentalUtils.AST_NODE_TYPES.AssignmentExpression) {
+        var _getNodeName;
+
+        // unless we're assigning to the same identifier, in which case
+        // we might be chaining off the existing promise value
+        if ((0, _utils.isIdentifier)(node.expression.left, name) && (_getNodeName = (0, _utils.getNodeName)(node.expression.right)) !== null && _getNodeName !== void 0 && _getNodeName.startsWith(`${name}.`) && isPromiseChainCall(node.expression.right)) {
+          continue;
+        }
+
+        break;
+      }
+    }
+
+    if (node.type === _experimentalUtils.AST_NODE_TYPES.BlockStatement && isValueAwaitedOrReturned(identifier, node.body)) {
+      return true;
+    }
+  }
+
+  return false;
+};
+
+const findFirstBlockBodyUp = node => {
+  let parent = node;
+
+  while (parent) {
+    if (parent.type === _experimentalUtils.AST_NODE_TYPES.BlockStatement) {
+      return parent.body;
+    }
+
+    parent = parent.parent;
+  }
+  /* istanbul ignore next */
+
+
+  throw new Error(`Could not find BlockStatement - please file a github issue at https://github.com/jest-community/eslint-plugin-jest`);
+};
+
+const isDirectlyWithinTestCaseCall = node => {
+  let parent = node;
+
+  while (parent) {
+    if ((0, _utils.isFunction)(parent)) {
+      var _parent;
+
+      parent = parent.parent;
+      return !!(((_parent = parent) === null || _parent === void 0 ? void 0 : _parent.type) === _experimentalUtils.AST_NODE_TYPES.CallExpression && (0, _utils.isTestCaseCall)(parent));
+    }
+
+    parent = parent.parent;
+  }
+
+  return false;
+};
+
+const isVariableAwaitedOrReturned = variable => {
+  const body = findFirstBlockBodyUp(variable); // it's pretty much impossible for us to track destructuring assignments,
+  // so we return true to bailout gracefully
+
+  if (!(0, _utils.isIdentifier)(variable.id)) {
+    return true;
+  }
+
+  return isValueAwaitedOrReturned(variable.id, body);
+};
+
+var _default = (0, _utils.createRule)({
+  name: __filename,
+  meta: {
+    docs: {
+      category: 'Best Practices',
+      description: 'Ensure promises that have expectations in their chain are valid',
+      recommended: 'error'
+    },
+    messages: {
+      expectInFloatingPromise: "This promise should either be returned or awaited to ensure the expects in it's chain are called"
+    },
+    type: 'suggestion',
+    schema: []
+  },
+  defaultOptions: [],
+
+  create(context) {
+    let inTestCaseWithDoneCallback = false; // an array of booleans representing each promise chain we enter, with the
+    // boolean value representing if we think a given chain contains an expect
+    // in it's body.
+    //
+    // since we only care about the inner-most chain, we represent the state in
+    // reverse with the inner-most being the first item, as that makes it
+    // slightly less code to assign to by not needing to know the length
+
+    const chains = [];
+    return {
+      CallExpression(node) {
+        // there are too many ways that the done argument could be used with
+        // promises that contain expect that would make the promise safe for us
+        if (isTestCaseCallWithCallbackArg(node)) {
+          inTestCaseWithDoneCallback = true;
+          return;
+        } // if this call expression is a promise chain, add it to the stack with
+        // value of "false", as we assume there are no expect calls initially
+
+
+        if (isPromiseChainCall(node)) {
+          chains.unshift(false);
+          return;
+        } // if we're within a promise chain, and this call expression looks like
+        // an expect call, mark the deepest chain as having an expect call
+
+
+        if (chains.length > 0 && (0, _utils.isExpectCall)(node)) {
+          chains[0] = true;
+        }
+      },
+
+      'CallExpression:exit'(node) {
+        // there are too many ways that the "done" argument could be used to
+        // make promises containing expects safe in a test for us to be able to
+        // accurately check, so we just bail out completely if it's present
+        if (inTestCaseWithDoneCallback) {
+          if ((0, _utils.isTestCaseCall)(node)) {
+            inTestCaseWithDoneCallback = false;
+          }
+
+          return;
+        }
+
+        if (!isPromiseChainCall(node)) {
+          return;
+        } // since we're exiting this call expression (which is a promise chain)
+        // we remove it from the stack of chains, since we're unwinding
+
+
+        const hasExpectCall = chains.shift(); // if the promise chain we're exiting doesn't contain an expect,
+        // then we don't need to check it for anything
+
+        if (!hasExpectCall) {
+          return;
+        }
+
+        const {
+          parent
+        } = findTopMostCallExpression(node); // if we don't have a parent (which is technically impossible at runtime)
+        // or our parent is not directly within the test case, we stop checking
+        // because we're most likely in the body of a function being defined
+        // within the test, which we can't track
+
+        if (!parent || !isDirectlyWithinTestCaseCall(parent)) {
+          return;
+        }
+
+        switch (parent.type) {
+          case _experimentalUtils.AST_NODE_TYPES.VariableDeclarator:
+            {
+              if (isVariableAwaitedOrReturned(parent)) {
+                return;
+              }
+
+              break;
+            }
+
+          case _experimentalUtils.AST_NODE_TYPES.AssignmentExpression:
+            {
+              if (parent.left.type === _experimentalUtils.AST_NODE_TYPES.Identifier && isValueAwaitedOrReturned(parent.left, findFirstBlockBodyUp(parent))) {
+                return;
+              }
+
+              break;
+            }
+
+          case _experimentalUtils.AST_NODE_TYPES.ExpressionStatement:
+            break;
+
+          case _experimentalUtils.AST_NODE_TYPES.ReturnStatement:
+          case _experimentalUtils.AST_NODE_TYPES.AwaitExpression:
+          default:
+            return;
+        }
+
+        context.report({
+          messageId: 'expectInFloatingPromise',
+          node: parent
+        });
+      }
+
+    };
+  }
+
+});
+
+exports.default = _default;
Index: frontend/node_modules/eslint-plugin-jest/lib/rules/valid-expect.js
===================================================================
--- frontend/node_modules/eslint-plugin-jest/lib/rules/valid-expect.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/eslint-plugin-jest/lib/rules/valid-expect.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,293 @@
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.default = void 0;
+
+var _experimentalUtils = require("@typescript-eslint/experimental-utils");
+
+var _utils = require("./utils");
+
+/*
+ * This implementation is ported from from eslint-plugin-jasmine.
+ * MIT license, Tom Vincent.
+ */
+
+/**
+ * Async assertions might be called in Promise
+ * methods like `Promise.x(expect1)` or `Promise.x([expect1, expect2])`.
+ * If that's the case, Promise node have to be awaited or returned.
+ *
+ * @Returns CallExpressionNode
+ */
+const getPromiseCallExpressionNode = node => {
+  if (node.type === _experimentalUtils.AST_NODE_TYPES.ArrayExpression && node.parent && node.parent.type === _experimentalUtils.AST_NODE_TYPES.CallExpression) {
+    node = node.parent;
+  }
+
+  if (node.type === _experimentalUtils.AST_NODE_TYPES.CallExpression && node.callee.type === _experimentalUtils.AST_NODE_TYPES.MemberExpression && (0, _utils.isSupportedAccessor)(node.callee.object) && (0, _utils.getAccessorValue)(node.callee.object) === 'Promise' && node.parent) {
+    return node;
+  }
+
+  return null;
+};
+
+const findPromiseCallExpressionNode = node => {
+  var _node$parent;
+
+  return (_node$parent = node.parent) !== null && _node$parent !== void 0 && _node$parent.parent && [_experimentalUtils.AST_NODE_TYPES.CallExpression, _experimentalUtils.AST_NODE_TYPES.ArrayExpression].includes(node.parent.type) ? getPromiseCallExpressionNode(node.parent) : null;
+};
+
+const getParentIfThenified = node => {
+  var _node$parent2;
+
+  const grandParentNode = (_node$parent2 = node.parent) === null || _node$parent2 === void 0 ? void 0 : _node$parent2.parent;
+
+  if (grandParentNode && grandParentNode.type === _experimentalUtils.AST_NODE_TYPES.CallExpression && (0, _utils.isExpectMember)(grandParentNode.callee) && ['then', 'catch'].includes((0, _utils.getAccessorValue)(grandParentNode.callee.property)) && grandParentNode.parent) {
+    // Just in case `then`s are chained look one above.
+    return getParentIfThenified(grandParentNode);
+  }
+
+  return node;
+};
+
+const isAcceptableReturnNode = (node, allowReturn) => {
+  if (allowReturn && node.type === _experimentalUtils.AST_NODE_TYPES.ReturnStatement) {
+    return true;
+  }
+
+  if (node.type === _experimentalUtils.AST_NODE_TYPES.ConditionalExpression && node.parent) {
+    return isAcceptableReturnNode(node.parent, allowReturn);
+  }
+
+  return [_experimentalUtils.AST_NODE_TYPES.ArrowFunctionExpression, _experimentalUtils.AST_NODE_TYPES.AwaitExpression].includes(node.type);
+};
+
+const isNoAssertionsParentNode = node => node.type === _experimentalUtils.AST_NODE_TYPES.ExpressionStatement || node.type === _experimentalUtils.AST_NODE_TYPES.AwaitExpression && node.parent !== undefined && node.parent.type === _experimentalUtils.AST_NODE_TYPES.ExpressionStatement;
+
+const promiseArrayExceptionKey = ({
+  start,
+  end
+}) => `${start.line}:${start.column}-${end.line}:${end.column}`;
+
+const defaultAsyncMatchers = ['toReject', 'toResolve'];
+
+var _default = (0, _utils.createRule)({
+  name: __filename,
+  meta: {
+    docs: {
+      category: 'Best Practices',
+      description: 'Enforce valid `expect()` usage',
+      recommended: 'error'
+    },
+    messages: {
+      tooManyArgs: 'Expect takes at most {{ amount }} argument{{ s }}.',
+      notEnoughArgs: 'Expect requires at least {{ amount }} argument{{ s }}.',
+      modifierUnknown: 'Expect has no modifier named "{{ modifierName }}".',
+      matcherNotFound: 'Expect must have a corresponding matcher call.',
+      matcherNotCalled: 'Matchers must be called to assert.',
+      asyncMustBeAwaited: 'Async assertions must be awaited{{ orReturned }}.',
+      promisesWithAsyncAssertionsMustBeAwaited: 'Promises which return async assertions must be awaited{{ orReturned }}.'
+    },
+    type: 'suggestion',
+    schema: [{
+      type: 'object',
+      properties: {
+        alwaysAwait: {
+          type: 'boolean',
+          default: false
+        },
+        asyncMatchers: {
+          type: 'array',
+          items: {
+            type: 'string'
+          }
+        },
+        minArgs: {
+          type: 'number',
+          minimum: 1
+        },
+        maxArgs: {
+          type: 'number',
+          minimum: 1
+        }
+      },
+      additionalProperties: false
+    }]
+  },
+  defaultOptions: [{
+    alwaysAwait: false,
+    asyncMatchers: defaultAsyncMatchers,
+    minArgs: 1,
+    maxArgs: 1
+  }],
+
+  create(context, [{
+    alwaysAwait,
+    asyncMatchers = defaultAsyncMatchers,
+    minArgs = 1,
+    maxArgs = 1
+  }]) {
+    // Context state
+    const arrayExceptions = new Set();
+
+    const pushPromiseArrayException = loc => arrayExceptions.add(promiseArrayExceptionKey(loc));
+    /**
+     * Promise method that accepts an array of promises,
+     * (eg. Promise.all), will throw warnings for the each
+     * unawaited or non-returned promise. To avoid throwing
+     * multiple warnings, we check if there is a warning in
+     * the given location.
+     */
+
+
+    const promiseArrayExceptionExists = loc => arrayExceptions.has(promiseArrayExceptionKey(loc));
+
+    return {
+      CallExpression(node) {
+        if (!(0, _utils.isExpectCall)(node)) {
+          return;
+        }
+
+        const {
+          expect,
+          modifier,
+          matcher
+        } = (0, _utils.parseExpectCall)(node);
+
+        if (expect.arguments.length < minArgs) {
+          const expectLength = (0, _utils.getAccessorValue)(expect.callee).length;
+          const loc = {
+            start: {
+              column: node.loc.start.column + expectLength,
+              line: node.loc.start.line
+            },
+            end: {
+              column: node.loc.start.column + expectLength + 1,
+              line: node.loc.start.line
+            }
+          };
+          context.report({
+            messageId: 'notEnoughArgs',
+            data: {
+              amount: minArgs,
+              s: minArgs === 1 ? '' : 's'
+            },
+            node,
+            loc
+          });
+        }
+
+        if (expect.arguments.length > maxArgs) {
+          const {
+            start
+          } = expect.arguments[maxArgs].loc;
+          const {
+            end
+          } = expect.arguments[node.arguments.length - 1].loc;
+          const loc = {
+            start,
+            end: {
+              column: end.column - 1,
+              line: end.line
+            }
+          };
+          context.report({
+            messageId: 'tooManyArgs',
+            data: {
+              amount: maxArgs,
+              s: maxArgs === 1 ? '' : 's'
+            },
+            node,
+            loc
+          });
+        } // something was called on `expect()`
+
+
+        if (!matcher) {
+          if (modifier) {
+            context.report({
+              messageId: 'matcherNotFound',
+              node: modifier.node.property
+            });
+          }
+
+          return;
+        }
+
+        if ((0, _utils.isExpectMember)(matcher.node.parent)) {
+          context.report({
+            messageId: 'modifierUnknown',
+            data: {
+              modifierName: matcher.name
+            },
+            node: matcher.node.property
+          });
+          return;
+        }
+
+        if (!matcher.arguments) {
+          context.report({
+            messageId: 'matcherNotCalled',
+            node: matcher.node.property
+          });
+        }
+
+        const parentNode = matcher.node.parent;
+        const shouldBeAwaited = modifier && modifier.name !== _utils.ModifierName.not || asyncMatchers.includes(matcher.name);
+
+        if (!parentNode.parent || !shouldBeAwaited) {
+          return;
+        }
+        /**
+         * If parent node is an array expression, we'll report the warning,
+         * for the array object, not for each individual assertion.
+         */
+
+
+        const isParentArrayExpression = parentNode.parent.type === _experimentalUtils.AST_NODE_TYPES.ArrayExpression;
+        const orReturned = alwaysAwait ? '' : ' or returned';
+        /**
+         * An async assertion can be chained with `then` or `catch` statements.
+         * In that case our target CallExpression node is the one with
+         * the last `then` or `catch` statement.
+         */
+
+        const targetNode = getParentIfThenified(parentNode);
+        const finalNode = findPromiseCallExpressionNode(targetNode) || targetNode;
+
+        if (finalNode.parent && // If node is not awaited or returned
+        !isAcceptableReturnNode(finalNode.parent, !alwaysAwait) && // if we didn't warn user already
+        !promiseArrayExceptionExists(finalNode.loc)) {
+          context.report({
+            loc: finalNode.loc,
+            data: {
+              orReturned
+            },
+            messageId: finalNode === targetNode ? 'asyncMustBeAwaited' : 'promisesWithAsyncAssertionsMustBeAwaited',
+            node
+          });
+
+          if (isParentArrayExpression) {
+            pushPromiseArrayException(finalNode.loc);
+          }
+        }
+      },
+
+      // nothing called on "expect()"
+      'CallExpression:exit'(node) {
+        if ((0, _utils.isExpectCall)(node) && isNoAssertionsParentNode(node.parent)) {
+          context.report({
+            messageId: 'matcherNotFound',
+            node
+          });
+        }
+      }
+
+    };
+  }
+
+});
+
+exports.default = _default;
Index: frontend/node_modules/eslint-plugin-jest/lib/rules/valid-title.js
===================================================================
--- frontend/node_modules/eslint-plugin-jest/lib/rules/valid-title.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/eslint-plugin-jest/lib/rules/valid-title.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,246 @@
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.default = void 0;
+
+var _experimentalUtils = require("@typescript-eslint/experimental-utils");
+
+var _utils = require("./utils");
+
+const trimFXprefix = word => ['f', 'x'].includes(word.charAt(0)) ? word.substr(1) : word;
+
+const doesBinaryExpressionContainStringNode = binaryExp => {
+  if ((0, _utils.isStringNode)(binaryExp.right)) {
+    return true;
+  }
+
+  if (binaryExp.left.type === _experimentalUtils.AST_NODE_TYPES.BinaryExpression) {
+    return doesBinaryExpressionContainStringNode(binaryExp.left);
+  }
+
+  return (0, _utils.isStringNode)(binaryExp.left);
+};
+
+const quoteStringValue = node => node.type === _experimentalUtils.AST_NODE_TYPES.TemplateLiteral ? `\`${node.quasis[0].value.raw}\`` : node.raw;
+
+const compileMatcherPattern = matcherMaybeWithMessage => {
+  const [matcher, message] = Array.isArray(matcherMaybeWithMessage) ? matcherMaybeWithMessage : [matcherMaybeWithMessage];
+  return [new RegExp(matcher, 'u'), message];
+};
+
+const compileMatcherPatterns = matchers => {
+  if (typeof matchers === 'string' || Array.isArray(matchers)) {
+    const compiledMatcher = compileMatcherPattern(matchers);
+    return {
+      describe: compiledMatcher,
+      test: compiledMatcher,
+      it: compiledMatcher
+    };
+  }
+
+  return {
+    describe: matchers.describe ? compileMatcherPattern(matchers.describe) : null,
+    test: matchers.test ? compileMatcherPattern(matchers.test) : null,
+    it: matchers.it ? compileMatcherPattern(matchers.it) : null
+  };
+};
+
+const MatcherAndMessageSchema = {
+  type: 'array',
+  items: {
+    type: 'string'
+  },
+  minItems: 1,
+  maxItems: 2,
+  additionalItems: false
+};
+
+var _default = (0, _utils.createRule)({
+  name: __filename,
+  meta: {
+    docs: {
+      category: 'Best Practices',
+      description: 'Enforce valid titles',
+      recommended: 'error'
+    },
+    messages: {
+      titleMustBeString: 'Title must be a string',
+      emptyTitle: '{{ jestFunctionName }} should not have an empty title',
+      duplicatePrefix: 'should not have duplicate prefix',
+      accidentalSpace: 'should not have leading or trailing spaces',
+      disallowedWord: '"{{ word }}" is not allowed in test titles.',
+      mustNotMatch: '{{ jestFunctionName }} should not match {{ pattern }}',
+      mustMatch: '{{ jestFunctionName }} should match {{ pattern }}',
+      mustNotMatchCustom: '{{ message }}',
+      mustMatchCustom: '{{ message }}'
+    },
+    type: 'suggestion',
+    schema: [{
+      type: 'object',
+      properties: {
+        ignoreTypeOfDescribeName: {
+          type: 'boolean',
+          default: false
+        },
+        disallowedWords: {
+          type: 'array',
+          items: {
+            type: 'string'
+          }
+        }
+      },
+      patternProperties: {
+        [/^must(?:Not)?Match$/u.source]: {
+          oneOf: [{
+            type: 'string'
+          }, MatcherAndMessageSchema, {
+            type: 'object',
+            propertyNames: {
+              enum: ['describe', 'test', 'it']
+            },
+            additionalProperties: {
+              oneOf: [{
+                type: 'string'
+              }, MatcherAndMessageSchema]
+            }
+          }]
+        }
+      },
+      additionalProperties: false
+    }],
+    fixable: 'code'
+  },
+  defaultOptions: [{
+    ignoreTypeOfDescribeName: false,
+    disallowedWords: []
+  }],
+
+  create(context, [{
+    ignoreTypeOfDescribeName,
+    disallowedWords = [],
+    mustNotMatch,
+    mustMatch
+  }]) {
+    const disallowedWordsRegexp = new RegExp(`\\b(${disallowedWords.join('|')})\\b`, 'iu');
+    const mustNotMatchPatterns = compileMatcherPatterns(mustNotMatch !== null && mustNotMatch !== void 0 ? mustNotMatch : {});
+    const mustMatchPatterns = compileMatcherPatterns(mustMatch !== null && mustMatch !== void 0 ? mustMatch : {});
+    return {
+      CallExpression(node) {
+        var _mustNotMatchPatterns, _mustMatchPatterns$je;
+
+        if (!(0, _utils.isDescribeCall)(node) && !(0, _utils.isTestCaseCall)(node)) {
+          return;
+        }
+
+        const [argument] = node.arguments;
+
+        if (!argument) {
+          return;
+        }
+
+        if (!(0, _utils.isStringNode)(argument)) {
+          if (argument.type === _experimentalUtils.AST_NODE_TYPES.BinaryExpression && doesBinaryExpressionContainStringNode(argument)) {
+            return;
+          }
+
+          if (argument.type !== _experimentalUtils.AST_NODE_TYPES.TemplateLiteral && !(ignoreTypeOfDescribeName && (0, _utils.isDescribeCall)(node))) {
+            context.report({
+              messageId: 'titleMustBeString',
+              loc: argument.loc
+            });
+          }
+
+          return;
+        }
+
+        const title = (0, _utils.getStringValue)(argument);
+
+        if (!title) {
+          context.report({
+            messageId: 'emptyTitle',
+            data: {
+              jestFunctionName: (0, _utils.isDescribeCall)(node) ? _utils.DescribeAlias.describe : _utils.TestCaseName.test
+            },
+            node
+          });
+          return;
+        }
+
+        if (disallowedWords.length > 0) {
+          const disallowedMatch = disallowedWordsRegexp.exec(title);
+
+          if (disallowedMatch) {
+            context.report({
+              data: {
+                word: disallowedMatch[1]
+              },
+              messageId: 'disallowedWord',
+              node: argument
+            });
+            return;
+          }
+        }
+
+        if (title.trim().length !== title.length) {
+          context.report({
+            messageId: 'accidentalSpace',
+            node: argument,
+            fix: fixer => [fixer.replaceTextRange(argument.range, quoteStringValue(argument).replace(/^([`'"]) +?/u, '$1').replace(/ +?([`'"])$/u, '$1'))]
+          });
+        }
+
+        const nodeName = trimFXprefix((0, _utils.getNodeName)(node));
+        const [firstWord] = title.split(' ');
+
+        if (firstWord.toLowerCase() === nodeName) {
+          context.report({
+            messageId: 'duplicatePrefix',
+            node: argument,
+            fix: fixer => [fixer.replaceTextRange(argument.range, quoteStringValue(argument).replace(/^([`'"]).+? /u, '$1'))]
+          });
+        }
+
+        const [jestFunctionName] = nodeName.split('.');
+        const [mustNotMatchPattern, mustNotMatchMessage] = (_mustNotMatchPatterns = mustNotMatchPatterns[jestFunctionName]) !== null && _mustNotMatchPatterns !== void 0 ? _mustNotMatchPatterns : [];
+
+        if (mustNotMatchPattern) {
+          if (mustNotMatchPattern.test(title)) {
+            context.report({
+              messageId: mustNotMatchMessage ? 'mustNotMatchCustom' : 'mustNotMatch',
+              node: argument,
+              data: {
+                jestFunctionName,
+                pattern: mustNotMatchPattern,
+                message: mustNotMatchMessage
+              }
+            });
+            return;
+          }
+        }
+
+        const [mustMatchPattern, mustMatchMessage] = (_mustMatchPatterns$je = mustMatchPatterns[jestFunctionName]) !== null && _mustMatchPatterns$je !== void 0 ? _mustMatchPatterns$je : [];
+
+        if (mustMatchPattern) {
+          if (!mustMatchPattern.test(title)) {
+            context.report({
+              messageId: mustMatchMessage ? 'mustMatchCustom' : 'mustMatch',
+              node: argument,
+              data: {
+                jestFunctionName,
+                pattern: mustMatchPattern,
+                message: mustMatchMessage
+              }
+            });
+            return;
+          }
+        }
+      }
+
+    };
+  }
+
+});
+
+exports.default = _default;
Index: frontend/node_modules/eslint-plugin-jest/package.json
===================================================================
--- frontend/node_modules/eslint-plugin-jest/package.json	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/eslint-plugin-jest/package.json	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,165 @@
+{
+  "name": "eslint-plugin-jest",
+  "version": "25.7.0",
+  "description": "Eslint rules for Jest",
+  "keywords": [
+    "eslint",
+    "eslintplugin",
+    "eslint-plugin"
+  ],
+  "repository": "jest-community/eslint-plugin-jest",
+  "license": "MIT",
+  "author": {
+    "name": "Jonathan Kim",
+    "email": "hello@jkimbo.com",
+    "url": "jkimbo.com"
+  },
+  "main": "lib/",
+  "files": [
+    "docs/",
+    "lib/"
+  ],
+  "scripts": {
+    "build": "babel --extensions .js,.ts src --out-dir lib --copy-files && rimraf lib/__tests__ 'lib/**/__tests__'",
+    "lint": "eslint . --ignore-pattern '!.eslintrc.js' --ext js,ts",
+    "prepack": "rimraf lib && yarn build",
+    "prettier:check": "prettier --check 'docs/**/*.md' README.md '.github/**' package.json tsconfig.json src/globals.json .yarnrc.yml",
+    "prettier:write": "prettier --write 'docs/**/*.md' README.md '.github/**' package.json tsconfig.json src/globals.json .yarnrc.yml",
+    "test": "jest",
+    "tools:regenerate-docs": "ts-node -T tools/regenerate-docs",
+    "typecheck": "tsc -p .",
+    "_postinstall": "is-ci || husky install",
+    "prepublishOnly": "pinst --disable",
+    "postpublish": "pinst --enable"
+  },
+  "commitlint": {
+    "extends": [
+      "@commitlint/config-conventional"
+    ]
+  },
+  "lint-staged": {
+    "*.{js,ts}": "eslint --fix",
+    "*.{md,json,yml}": "prettier --write"
+  },
+  "prettier": {
+    "arrowParens": "avoid",
+    "endOfLine": "auto",
+    "proseWrap": "always",
+    "singleQuote": true,
+    "trailingComma": "all"
+  },
+  "jest": {
+    "coverageThreshold": {
+      "global": {
+        "branches": 100,
+        "functions": 100,
+        "lines": 100,
+        "statements": 100
+      }
+    },
+    "projects": [
+      {
+        "displayName": "test",
+        "moduleNameMapper": {
+          "eslint/use-at-your-own-risk": "eslint/lib/unsupported-api.js"
+        },
+        "testPathIgnorePatterns": [
+          "<rootDir>/lib/.*",
+          "<rootDir>/src/rules/__tests__/fixtures/*",
+          "<rootDir>/src/rules/__tests__/test-utils.ts"
+        ]
+      },
+      {
+        "displayName": "lint",
+        "runner": "jest-runner-eslint",
+        "testMatch": [
+          "<rootDir>/**/*.{js,ts}"
+        ],
+        "testPathIgnorePatterns": [
+          "<rootDir>/lib/.*"
+        ]
+      }
+    ]
+  },
+  "dependencies": {
+    "@typescript-eslint/experimental-utils": "^5.0.0"
+  },
+  "devDependencies": {
+    "@babel/cli": "^7.4.4",
+    "@babel/core": "^7.4.4",
+    "@babel/preset-env": "^7.4.4",
+    "@babel/preset-typescript": "^7.3.3",
+    "@commitlint/cli": "^16.0.0",
+    "@commitlint/config-conventional": "^16.0.0",
+    "@schemastore/package": "^0.0.6",
+    "@semantic-release/changelog": "^6.0.0",
+    "@semantic-release/git": "^10.0.0",
+    "@types/dedent": "^0.7.0",
+    "@types/jest": "^27.0.0",
+    "@types/node": "^16.0.0",
+    "@types/prettier": "^2.0.0",
+    "@typescript-eslint/eslint-plugin": "^5.0.0",
+    "@typescript-eslint/parser": "^5.0.0",
+    "babel-jest": "^27.0.0",
+    "babel-plugin-replace-ts-export-assignment": "^0.0.2",
+    "dedent": "^0.7.0",
+    "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0",
+    "eslint-config-prettier": "^8.3.0",
+    "eslint-plugin-eslint-comments": "^3.1.2",
+    "eslint-plugin-eslint-config": "^2.0.0",
+    "eslint-plugin-eslint-plugin": "^4.0.1",
+    "eslint-plugin-import": "^2.25.1",
+    "eslint-plugin-node": "^11.0.0",
+    "eslint-plugin-prettier": "^3.4.1",
+    "eslint-remote-tester": "^2.1.0",
+    "eslint-remote-tester-repositories": "^0.0.3",
+    "husky": "^7.0.2",
+    "is-ci": "^3.0.0",
+    "jest": "^27.0.0",
+    "jest-runner-eslint": "^1.0.0",
+    "lint-staged": "^12.0.0",
+    "pinst": "^2.0.0",
+    "prettier": "^2.0.5",
+    "rimraf": "^3.0.0",
+    "semantic-release": "^18.0.0",
+    "semver": "^7.3.5",
+    "ts-node": "^10.2.1",
+    "typescript": "^4.4.0"
+  },
+  "peerDependencies": {
+    "@typescript-eslint/eslint-plugin": "^4.0.0 || ^5.0.0",
+    "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0"
+  },
+  "peerDependenciesMeta": {
+    "@typescript-eslint/eslint-plugin": {
+      "optional": true
+    },
+    "jest": {
+      "optional": true
+    }
+  },
+  "engines": {
+    "node": "^12.13.0 || ^14.15.0 || >=16.0.0"
+  },
+  "release": {
+    "branches": [
+      "main",
+      {
+        "name": "next",
+        "prerelease": true
+      }
+    ],
+    "plugins": [
+      "@semantic-release/commit-analyzer",
+      "@semantic-release/release-notes-generator",
+      "@semantic-release/changelog",
+      "@semantic-release/npm",
+      "@semantic-release/git",
+      "@semantic-release/github"
+    ]
+  },
+  "resolutions": {
+    "@typescript-eslint/experimental-utils": "^5.0.0"
+  },
+  "packageManager": "yarn@3.1.1"
+}
