diff --git a/.githooks/pre-commit b/.githooks/pre-commit deleted file mode 100755 index 827a97b32..000000000 --- a/.githooks/pre-commit +++ /dev/null @@ -1,60 +0,0 @@ -# #!/bin/sh -# # -# # An example hook script to verify what is about to be committed. -# # Called by "git commit" with no arguments. The hook should -# # exit with non-zero status after issuing an appropriate message if -# # it wants to stop the commit. -# # -# # To enable this hook, rename this file to "pre-commit". - -# # if git rev-parse --verify HEAD >/dev/null 2>&1 -# # then -# # against=HEAD -# # else -# # # Initial commit: diff against an empty tree object -# # against=$(git hash-object -t tree /dev/null) -# # fi - -# # # If you want to allow non-ASCII filenames set this variable to true. -# # allownonascii=$(git config --type=bool hooks.allownonascii) - -# # # Redirect output to stderr. -# # exec 1>&2 - -# # # Cross platform projects tend to avoid non-ASCII filenames; prevent -# # # them from being added to the repository. We exploit the fact that the -# # # printable range starts at the space character and ends with tilde. -# # if [ "$allownonascii" != "true" ] && -# # # Note that the use of brackets around a tr range is ok here, (it's -# # # even required, for portability to Solaris 10's /usr/bin/tr), since -# # # the square bracket bytes happen to fall in the designated range. -# # test $(git diff --cached --name-only --diff-filter=A -z $against | -# # LC_ALL=C tr -d '[ -~]\0' | wc -c) != 0 -# # then -# # cat <<\EOF -# # Error: Attempt to add a non-ASCII file name. - -# # This can cause problems if you want to work with people on other platforms. - -# # To be portable it is advisable to rename the file. - -# # If you know what you are doing you can disable this check using: - -# # git config hooks.allownonascii true -# # EOF -# # exit 1 -# # fi - -# # # If there are whitespace errors, print the offending file names and fail. -# # exec git diff-index --check --cached $against -- - -# yarn audit --groups=dependencies --level=critical - -# # if [ $? -ge 16 ] -# # then -# # echo "\033[33mCommit failed, critical security vulnerability found in one of the project's dependencies. Please resolve as per the audit report above, then re-commit.\033[0m" -# # exit 1 -# # fi - -# yarn test-cov -# yarn lint --quiet \ No newline at end of file diff --git a/__mocks__/css.js b/__mocks__/css.js new file mode 100644 index 000000000..f053ebf79 --- /dev/null +++ b/__mocks__/css.js @@ -0,0 +1 @@ +module.exports = {}; diff --git a/__mocks__/scss.js b/__mocks__/scss.js index ae4f5cb45..accfb8153 100644 --- a/__mocks__/scss.js +++ b/__mocks__/scss.js @@ -1,7 +1,7 @@ module.exports = new Proxy( {}, { - get: (target, key) => { + get: (_target, key) => { if (key === '__esModule') { return true; } diff --git a/__mocks__/svg.js b/__mocks__/svg.js new file mode 100644 index 000000000..f21d89f4c --- /dev/null +++ b/__mocks__/svg.js @@ -0,0 +1,5 @@ +const svgURL = 'SvgrURL'; + +export default svgURL; + +export const ReactComponent = 'div'; diff --git a/package.json b/package.json index 3df8dfe37..a2fd3929e 100644 --- a/package.json +++ b/package.json @@ -29,7 +29,6 @@ "bootstrap": "5.3.5", "browserslist": "^4.18.1", "buffer": "^6.0.3", - "camelcase": "^6.3.0", "case-sensitive-paths-webpack-plugin": "^2.4.0", "css-loader": "^7.1.2", "css-minimizer-webpack-plugin": "^7.0.2", @@ -38,21 +37,20 @@ "dotenv-expand": "^12.0.1", "eslint": "^8.10.0", "eslint-config-react-app": "^7.0.1", - "eslint-webpack-plugin": "^5.0.0", + "eslint-webpack-plugin": "^5.0.1", "file-loader": "^6.2.0", "fs-extra": "^11.3.0", "geodesy": "^2.4.0", "html-webpack-plugin": "^5.5.0", "humanize-duration": "^3.32.1", - "i18next": "^24.0.2", + "i18next": "^25.0.0", "i18next-browser-languagedetector": "^8.0.0", "i18next-chained-backend": "^4.6.2", "i18next-http-backend": "^3.0.1", "i18next-localstorage-backend": "^4.2.0", - "identity-obj-proxy": "^3.0.0", - "jest": "^27.4.3", - "jest-resolve": "^27.4.2", - "jest-watch-typeahead": "^1.0.0", + "jest": "^29.7.0", + "jest-resolve": "^29.7.0", + "jest-watch-typeahead": "^2.2.2", "legacy-socket.io-client": "npm:socket.io-client@2.2.0", "localforage": "^1.10.0", "lodash-es": "^4.17.21", @@ -66,7 +64,6 @@ "postcss-preset-env": "^10.1.5", "prompts": "^2.4.2", "react": "^19.1.0", - "react-app-polyfill": "^3.0.0", "react-bootstrap": "2.10.9", "react-collapsible": "^2.10.0", "react-datepicker": "^8.3.0", @@ -85,7 +82,7 @@ "react-refresh": "^0.17.0", "react-router-dom": "^7.0.1", "react-select": "^5.8.3", - "react-spinners": "^0.15.0", + "react-spinners": "^0.16.1", "react-to-print": "^3.0.6", "react-toastify": "^11.0.5", "react-window": "^1.8.10", @@ -102,7 +99,7 @@ "source-map-loader": "^5.0.0", "style-loader": "^4.0.0", "suncalc": "^1.9.0", - "tailwindcss": "^4.1.3", + "tailwindcss": "^4.1.4", "terser-webpack-plugin": "^5.2.5", "use-sound": "^5.0.0", "uuid": "^11.0.3", @@ -116,12 +113,10 @@ "build-sw": "node ./src/sw-build.js", "clean-cra-sw": "rm -f build/precache-manifest.*.js && rm -f build/service-worker.js", "build": "GENERATE_SOURCEMAP=false node react-scripts/build.js && yarn build-sw && yarn clean-cra-sw", - "test": "node react-scripts/test.js --transformIgnorePatterns \"node_modules/(?!geodesy)/\"", + "test": "node react-scripts/test.js", "lint": "CI=true eslint src", "stylelint": "node ./node_modules/stylelint/bin/stylelint.js ./src/**/*.scss", - "test-ci": "CI=true node react-scripts/test.js --silent --detectOpenHandles --forceExit --transformIgnorePatterns \"node_modules/(?!geodesy)/\"", - "test-cov": "yarn test-ci --coverage", - "posttest-cov": "jest-coverage-thresholds-bumper --margin=1", + "test-ci": "CI=true node react-scripts/test.js --silent --detectOpenHandles --forceExit", "postinstall": "sh setUpLocalGitConfig.sh" }, "devDependencies": { @@ -130,87 +125,47 @@ "@testing-library/dom": "^10.4.0", "@testing-library/jest-dom": "^6.6.3", "@testing-library/react": "^16.3.0", - "@testing-library/react-hooks": "^8.0.1", "@testing-library/user-event": "^14.6.1", "eslint-config-airbnb": "^19.0.4", "eslint-plugin-react": "^7.12.4", "eslint-plugin-react-hooks": "^5.2.0", - "jest-coverage-thresholds-bumper": "^1.0.1", - "jest-webgl-canvas-mock": "^0.2.3", - "madge": "^8.0.0", - "msw": "^2.7.3", + "jest-environment-jsdom": "^29.7.0", + "jest-fixed-jsdom": "^0.0.9", + "jest-webgl-canvas-mock": "^2.5.3", + "msw": "^2.7.4", "redux-mock-store": "^1.5.3", "sass": "^1.86.0", "socket.io-mock": "^1.3.2", "stylelint": "^16.17.0", "stylelint-config-css-modules": "^4.4.0", "stylelint-config-standard": "^38.0.0", - "stylelint-scss": "^6.11.1", - "undici": "5.0.0" + "stylelint-scss": "^6.11.1" }, "jest": { - "roots": [ - "/src" - ], - "collectCoverageFrom": [ - "src/**/*.{js,jsx,ts,tsx}", - "!src/**/*.d.ts" - ], - "setupFiles": [ - "react-app-polyfill/jsdom" - ], + "moduleNameMapper": { + "\\.css": "/__mocks__/css.js", + ".+\\.module\\.scss": "/__mocks__/scss.js", + "\\.svg": "/__mocks__/svg.js" + }, + "resetMocks": true, "setupFilesAfterEnv": [ "/src/setupTests.js" ], + "testEnvironment": "jest-fixed-jsdom", "testMatch": [ - "/src/**/__tests__/**/*.{js,jsx,ts,tsx}", - "/src/**/*.{spec,test}.{js,jsx,ts,tsx}" + "/src/**/*.test.{js,jsx}" ], - "testEnvironment": "jsdom", "transform": { "^.+\\.(js|jsx|mjs|cjs|ts|tsx)$": "/react-app-config/jest/babelTransform.js", - "^.+\\.css$": "/react-app-config/jest/cssTransform.js", - "^(?!.*\\.(js|jsx|mjs|cjs|ts|tsx|css|json)$)": "/react-app-config/jest/fileTransform.js" + "^(?!.*\\.(js|jsx|mjs|cjs|ts|tsx|json)$)": "/react-app-config/jest/fileTransform.js" }, "transformIgnorePatterns": [ - "[/\\\\]node_modules[/\\\\].+\\.(js|jsx|mjs|cjs|ts|tsx)$", - "^.+\\.module\\.(css|sass|scss)$" - ], - "modulePaths": [], - "moduleNameMapper": { - "^react-native$": "react-native-web", - ".+\\.module\\.scss": "/__mocks__/scss.js", - "^.+\\.module\\.(css|sass)$": "identity-obj-proxy" - }, - "moduleFileExtensions": [ - "web.js", - "js", - "web.ts", - "ts", - "web.tsx", - "tsx", - "json", - "web.jsx", - "jsx", - "node" + "/node_modules/(?!(geodesy|lodash-es|nanoid|react-debounce-render|uuid)/)" ], "watchPlugins": [ "jest-watch-typeahead/filename", "jest-watch-typeahead/testname" - ], - "resetMocks": true, - "coverageReporters": [ - "html", - "json-summary" - ], - "coverageThreshold": { - "global": { - "branches": 45.52, - "functions": 49.78, - "lines": 59.28, - "statements": 58.03 - } - } + ] }, "browserslist": [ "last 1 chrome version", diff --git a/react-app-config/jest/cssTransform.js b/react-app-config/jest/cssTransform.js deleted file mode 100644 index 8f6511481..000000000 --- a/react-app-config/jest/cssTransform.js +++ /dev/null @@ -1,14 +0,0 @@ -'use strict'; - -// This is a custom Jest transformer turning style imports into empty objects. -// http://facebook.github.io/jest/docs/en/webpack.html - -module.exports = { - process() { - return 'module.exports = {};'; - }, - getCacheKey() { - // The output is always the same. - return 'cssTransform'; - }, -}; diff --git a/react-app-config/jest/fileTransform.js b/react-app-config/jest/fileTransform.js index aab67618c..b4ed4f5cc 100644 --- a/react-app-config/jest/fileTransform.js +++ b/react-app-config/jest/fileTransform.js @@ -1,40 +1,11 @@ 'use strict'; const path = require('path'); -const camelcase = require('camelcase'); - -// This is a custom Jest transformer turning file imports into filenames. -// http://facebook.github.io/jest/docs/en/webpack.html module.exports = { - process(src, filename) { + process(_src, filename) { const assetFilename = JSON.stringify(path.basename(filename)); - if (filename.match(/\.svg$/)) { - // Based on how SVGR generates a component name: - // https://github.com/smooth-code/svgr/blob/01b194cf967347d43d4cbe6b434404731b87cf27/packages/core/src/state.js#L6 - const pascalCaseFilename = camelcase(path.parse(filename).name, { - pascalCase: true, - }); - const componentName = `Svg${pascalCaseFilename}`; - return `const React = require('react'); - module.exports = { - __esModule: true, - default: ${assetFilename}, - ReactComponent: React.forwardRef(function ${componentName}(props, ref) { - return { - $$typeof: Symbol.for('react.element'), - type: 'svg', - ref: ref, - key: null, - props: Object.assign({}, props, { - children: ${assetFilename} - }) - }; - }), - };`; - } - - return `module.exports = ${assetFilename};`; + return { code: `module.exports = ${assetFilename};` }; }, }; diff --git a/src/AddAttachmentButton/index.js b/src/AddAttachmentButton/index.js index c065f9ad7..98a8c720a 100644 --- a/src/AddAttachmentButton/index.js +++ b/src/AddAttachmentButton/index.js @@ -72,7 +72,7 @@ const AddAttachmentButton = ({ className = '', onAddAttachments }) => { setDraggingOver(false); onAddAttachments(event.dataTransfer.files); - fileInputRef.current.value = null; + fileInputRef.current.value = ''; }, [analytics, onAddAttachments]); const onChangeFileInput = useCallback((event) => { @@ -81,7 +81,7 @@ const AddAttachmentButton = ({ className = '', onAddAttachments }) => { analytics?.track('Add attachment'); onAddAttachments(fileInputRef.current.files); - fileInputRef.current.value = null; + fileInputRef.current.value = ''; }, [analytics, onAddAttachments]); return <> diff --git a/src/AddAttachmentButton/index.test.js b/src/AddAttachmentButton/index.test.js index 6d7c5f736..95076d1aa 100644 --- a/src/AddAttachmentButton/index.test.js +++ b/src/AddAttachmentButton/index.test.js @@ -19,7 +19,7 @@ describe('ReportManager - AddAttachmentButton', () => { const addAttachmentButton = await screen.findByTestId('addAttachmentButton'); const fakeFile = new File(['fake'], 'fake.txt', { type: 'text/plain' }); - userEvent.upload(addAttachmentButton, fakeFile); + await userEvent.upload(addAttachmentButton, fakeFile); expect(onAddAttachments).toHaveBeenCalledTimes(1); expect(onAddAttachments.mock.calls[0][0][0].name).toBe('fake.txt'); diff --git a/src/AddItemButton/AddItemModal/AddPatrolTab/index.test.js b/src/AddItemButton/AddItemModal/AddPatrolTab/index.test.js index 0f0286425..ecfa2d931 100644 --- a/src/AddItemButton/AddItemModal/AddPatrolTab/index.test.js +++ b/src/AddItemButton/AddItemModal/AddPatrolTab/index.test.js @@ -70,7 +70,7 @@ describe('AddItemButton - AddItemModal - AddPatrolTab', () => { expect((await screen.findAllByTestId((content) => content.startsWith('categoryList-button-')))).toHaveLength(4); const searchBar = await screen.findByTestId('search-input'); - userEvent.type(searchBar, 'routine'); + await userEvent.type(searchBar, 'routine'); const typeListItems = await screen.findAllByTestId((content) => content.startsWith('categoryList-button-')); @@ -82,12 +82,12 @@ describe('AddItemButton - AddItemModal - AddPatrolTab', () => { renderAddPatrolTab(); const searchBar = await screen.findByTestId('search-input'); - userEvent.type(searchBar, 'routine'); + await userEvent.type(searchBar, 'routine'); expect((await screen.findAllByTestId((content) => content.startsWith('categoryList-button-')))).toHaveLength(1); const clearSearchBarButton = await screen.findByTestId('reset-search-button'); - userEvent.click(clearSearchBarButton); + await userEvent.click(clearSearchBarButton); expect((await screen.findAllByTestId((content) => content.startsWith('categoryList-button-')))).toHaveLength(4); }); @@ -100,7 +100,7 @@ describe('AddItemButton - AddItemModal - AddPatrolTab', () => { expect(onAddPatrol).toHaveBeenCalledTimes(0); const typeButton = await screen.findByTestId('categoryList-button-c6f88fd2-2b87-477a-9c23-3bc4b3eb845d'); - userEvent.click(typeButton); + await userEvent.click(typeButton); expect(onHideModal).toHaveBeenCalledTimes(1); expect(onAddPatrol).toHaveBeenCalledTimes(1); @@ -113,7 +113,7 @@ describe('AddItemButton - AddItemModal - AddPatrolTab', () => { expect(navigate).toHaveBeenCalledTimes(0); const typeButton = await screen.findByTestId('categoryList-button-c6f88fd2-2b87-477a-9c23-3bc4b3eb845d'); - userEvent.click(typeButton); + await userEvent.click(typeButton); expect(onHideModal).toHaveBeenCalledTimes(1); expect(navigate).toHaveBeenCalledTimes(1); diff --git a/src/AddItemButton/AddItemModal/AddReportTab/index.test.js b/src/AddItemButton/AddItemModal/AddReportTab/index.test.js index 58f6bfcc1..1d4d76dfd 100644 --- a/src/AddItemButton/AddItemModal/AddReportTab/index.test.js +++ b/src/AddItemButton/AddItemModal/AddReportTab/index.test.js @@ -59,7 +59,7 @@ describe('AddItemButton - AddItemModal - AddReportTab', () => { expect((await screen.findAllByTestId((content) => content.startsWith('categoryList-button-')))).toHaveLength(106); const searchBar = await screen.findByTestId('search-input'); - userEvent.type(searchBar, 'fire'); + await userEvent.type(searchBar, 'fire'); const typeListItems = await screen.findAllByTestId((content) => content.startsWith('categoryList-button-')); @@ -71,12 +71,12 @@ describe('AddItemButton - AddItemModal - AddReportTab', () => { renderAddReportTab(); const searchBar = await screen.findByTestId('search-input'); - userEvent.type(searchBar, 'fire'); + await userEvent.type(searchBar, 'fire'); expect((await screen.findAllByTestId((content) => content.startsWith('categoryList-button-')))).toHaveLength(3); const clearSearchBarButton = await screen.findByTestId('reset-search-button'); - userEvent.click(clearSearchBarButton); + await userEvent.click(clearSearchBarButton); expect((await screen.findAllByTestId((content) => content.startsWith('categoryList-button-')))).toHaveLength(106); }); @@ -89,7 +89,7 @@ describe('AddItemButton - AddItemModal - AddReportTab', () => { expect(onAddReport).toHaveBeenCalledTimes(0); const typeButton = await screen.findByTestId('categoryList-button-74941f0d-4b89-48be-a62a-a74c78db8383'); - userEvent.click(typeButton); + await userEvent.click(typeButton); expect(onHideModal).toHaveBeenCalledTimes(1); expect(onAddReport).toHaveBeenCalledTimes(1); @@ -111,7 +111,7 @@ describe('AddItemButton - AddItemModal - AddReportTab', () => { }); const pointTypeButton = await screen.findByTestId('categoryList-button-74941f0d-4b89-48be-a62a-a74c78db8383'); - userEvent.click(pointTypeButton); + await userEvent.click(pointTypeButton); expect(onHideModal).toHaveBeenCalledTimes(1); expect(navigate).toHaveBeenCalledTimes(1); @@ -121,7 +121,7 @@ describe('AddItemButton - AddItemModal - AddReportTab', () => { expect(mockNavState.state.reportData).toEqual(reportData); const polygonTypeButton = await screen.findByTestId('categoryList-button-3ff27054-da2a-41a5-8785-a10a90e57486'); // a known event type fixture with a Polygon geometry_type - userEvent.click(polygonTypeButton); + await userEvent.click(polygonTypeButton); expect(onHideModal).toHaveBeenCalledTimes(2); expect(navigate).toHaveBeenCalledTimes(2); @@ -136,7 +136,7 @@ describe('AddItemButton - AddItemModal - AddReportTab', () => { expect(navigate).toHaveBeenCalledTimes(0); const typeButton = await screen.findByTestId('categoryList-button-74941f0d-4b89-48be-a62a-a74c78db8383'); - userEvent.click(typeButton); + await userEvent.click(typeButton); expect(onHideModal).toHaveBeenCalledTimes(1); expect(navigate).toHaveBeenCalledTimes(1); diff --git a/src/AddItemButton/AddItemModal/TypesList/index.test.js b/src/AddItemButton/AddItemModal/TypesList/index.test.js index a4f8713d8..805ffb7e7 100644 --- a/src/AddItemButton/AddItemModal/TypesList/index.test.js +++ b/src/AddItemButton/AddItemModal/TypesList/index.test.js @@ -68,7 +68,7 @@ describe('AddItemButton - AddItemModal - TypesList', () => { expect(onClickType).toHaveBeenCalledTimes(0); const type2Button = await screen.findByTestId('categoryList-button-typ2'); - userEvent.click(type2Button); + await userEvent.click(type2Button); expect(onClickType).toHaveBeenCalledTimes(1); expect(onClickType).toHaveBeenCalledWith({ display: 'Type 2', id: 'typ2' }); diff --git a/src/AddItemButton/AddItemModal/index.test.js b/src/AddItemButton/AddItemModal/index.test.js index 0b5d460a4..e3b3e98c8 100644 --- a/src/AddItemButton/AddItemModal/index.test.js +++ b/src/AddItemButton/AddItemModal/index.test.js @@ -114,7 +114,7 @@ describe('AddItemButton - AddItemModal', () => { getStoredTab.mockImplementation(() => ADD_TAB_KEYS.ADD_PATROL); - userEvent.click(tabs[1]); + await userEvent.click(tabs[1]); expect(tabs[0]).toHaveTextContent('Add Event'); expect(tabs[0]).not.toHaveClass('active'); @@ -125,7 +125,7 @@ describe('AddItemButton - AddItemModal', () => { getStoredTab.mockImplementation(() => ADD_TAB_KEYS.ADD_REPORT); - userEvent.click(tabs[0]); + await userEvent.click(tabs[0]); expect(tabs[0]).toHaveTextContent('Add Event'); expect(tabs[0]).toHaveClass('active'); @@ -181,7 +181,7 @@ describe('AddItemButton - AddItemModal', () => { expect(onHide).toHaveBeenCalledTimes(0); const closeButton = await screen.findByLabelText('Close'); - userEvent.click(closeButton); + await userEvent.click(closeButton); expect(onHide).toHaveBeenCalledTimes(1); }); @@ -194,7 +194,7 @@ describe('AddItemButton - AddItemModal', () => { expect(onAddReport).toHaveBeenCalledTimes(0); const reportTypeButton = await screen.findByTestId('categoryList-button-74941f0d-4b89-48be-a62a-a74c78db8383'); - userEvent.click(reportTypeButton); + await userEvent.click(reportTypeButton); expect(onAddReport).toHaveBeenCalledTimes(1); expect(onAddReport.mock.calls[0][2]).toBe('74941f0d-4b89-48be-a62a-a74c78db8383'); @@ -208,9 +208,9 @@ describe('AddItemButton - AddItemModal', () => { expect(onAddPatrol).toHaveBeenCalledTimes(0); const addPatrolTab = (await screen.findAllByRole('tab'))[1]; - userEvent.click(addPatrolTab); + await userEvent.click(addPatrolTab); const patrolTypeButton = await screen.findByTestId('categoryList-button-c6f88fd2-2b87-477a-9c23-3bc4b3eb845d'); - userEvent.click(patrolTypeButton); + await userEvent.click(patrolTypeButton); expect(onAddPatrol).toHaveBeenCalledTimes(1); expect(onAddPatrol.mock.calls[0][2]).toBe('c6f88fd2-2b87-477a-9c23-3bc4b3eb845d'); diff --git a/src/AddItemButton/index.test.js b/src/AddItemButton/index.test.js index 820930fa5..861bd8a94 100644 --- a/src/AddItemButton/index.test.js +++ b/src/AddItemButton/index.test.js @@ -42,7 +42,7 @@ describe('AddItemButton', () => { expect((await screen.queryByTestId('addItemButton-addItemModal'))).toBeNull(); const addItemButton = await screen.findByTestId('addItemButton'); - userEvent.click(addItemButton); + await userEvent.click(addItemButton); expect((await screen.findByTestId('addItemButton-addItemModal'))).toBeDefined(); }); @@ -51,12 +51,12 @@ describe('AddItemButton', () => { renderAddItemButton(); const addItemButton = await screen.findByTestId('addItemButton'); - userEvent.click(addItemButton); + await userEvent.click(addItemButton); expect((await screen.findByTestId('addItemButton-addItemModal'))).toBeDefined(); const closeButton = await screen.findByLabelText('Close'); - userEvent.click(closeButton); + await userEvent.click(closeButton); await waitFor(async () => { expect((await screen.queryByTestId('addItemButton-addItemModal'))).toBeNull(); @@ -87,12 +87,12 @@ describe('AddItemButton', () => { renderAddItemButton({ onAddReport }); const addItemButton = await screen.findByTestId('addItemButton'); - userEvent.click(addItemButton); + await userEvent.click(addItemButton); expect(onAddReport).toHaveBeenCalledTimes(0); const reportTypeButton = await screen.findByTestId('categoryList-button-74941f0d-4b89-48be-a62a-a74c78db8383'); - userEvent.click(reportTypeButton); + await userEvent.click(reportTypeButton); expect(onAddReport).toHaveBeenCalledTimes(1); expect(onAddReport.mock.calls[0][2]).toBe('74941f0d-4b89-48be-a62a-a74c78db8383'); @@ -104,14 +104,14 @@ describe('AddItemButton', () => { renderAddItemButton({ onAddPatrol }); const addItemButton = await screen.findByTestId('addItemButton'); - userEvent.click(addItemButton); + await userEvent.click(addItemButton); expect(onAddPatrol).toHaveBeenCalledTimes(0); const addPatrolTab = (await screen.findAllByRole('tab'))[1]; - userEvent.click(addPatrolTab); + await userEvent.click(addPatrolTab); const patrolTypeButton = await screen.findByTestId('categoryList-button-c6f88fd2-2b87-477a-9c23-3bc4b3eb845d'); - userEvent.click(patrolTypeButton); + await userEvent.click(patrolTypeButton); expect(onAddPatrol).toHaveBeenCalledTimes(1); expect(onAddPatrol.mock.calls[0][2]).toBe('c6f88fd2-2b87-477a-9c23-3bc4b3eb845d'); diff --git a/src/AddNoteButton/index.test.js b/src/AddNoteButton/index.test.js index 4029e8876..55569d3a6 100644 --- a/src/AddNoteButton/index.test.js +++ b/src/AddNoteButton/index.test.js @@ -17,7 +17,7 @@ describe('ReportManager - AddNoteButton', () => { expect(onAddNote).toHaveBeenCalledTimes(0); const addNoteButton = await screen.findByTestId('addNoteButton'); - userEvent.click(addNoteButton); + await userEvent.click(addNoteButton); expect(onAddNote).toHaveBeenCalledTimes(1); }); diff --git a/src/AddToPatrolModal/AddToPatrolModal.test.js b/src/AddToPatrolModal/AddToPatrolModal.test.js index 1eaf83923..6fbc2cfef 100644 --- a/src/AddToPatrolModal/AddToPatrolModal.test.js +++ b/src/AddToPatrolModal/AddToPatrolModal.test.js @@ -151,7 +151,7 @@ describe('the "add to patrol" modal within a report form', () => { const firstListItem = await screen.findByTestId('add-patrol-list-item-0'); const button = firstListItem.querySelector('button'); - userEvent.click(button); + await userEvent.click(button); expect(onAddToPatrol).toHaveBeenCalled(); }); @@ -164,7 +164,7 @@ describe('the "add to patrol" modal within a report form', () => { renderAddToPatrolModal(undefined, TEST_MODAL_ID); const cancelBtn = await screen.findByTestId('close-modal-button'); - userEvent.click(cancelBtn); + await userEvent.click(cancelBtn); expect(removeModalSpy).toHaveBeenCalledWith(TEST_MODAL_ID); diff --git a/src/CheckboxList/index.test.js b/src/CheckboxList/index.test.js index 9872f8489..fe34214e5 100644 --- a/src/CheckboxList/index.test.js +++ b/src/CheckboxList/index.test.js @@ -33,12 +33,12 @@ describe('CheckboxList', () => { expect(onItemChange).toHaveBeenCalledTimes(0); - userEvent.click(checkboxes[1]); + await userEvent.click(checkboxes[1]); expect(onItemChange).toHaveBeenCalledTimes(1); expect(onItemChange).toHaveBeenCalledWith(options[1], 1); - userEvent.click(checkboxes[2]); + await userEvent.click(checkboxes[2]); expect(onItemChange).toHaveBeenCalledTimes(2); expect(onItemChange).toHaveBeenCalledWith(options[2], 2); diff --git a/src/ColumnSort/index.test.js b/src/ColumnSort/index.test.js index 1c0f6d49a..6abfe3367 100644 --- a/src/ColumnSort/index.test.js +++ b/src/ColumnSort/index.test.js @@ -31,7 +31,7 @@ afterEach(() => { onSortChange.mockClear(); }); -test('rendering without crashing', () => { +test('rendering without crashing', async () => { render(); }); @@ -62,30 +62,30 @@ describe('ColumnSort control', () => { await screen.findByTestId('sort-options'); }); - test('clicking a sort option selects a new sort property', () => { + test('clicking a sort option selects a new sort property', async () => { const sortOptionsContainer = screen.getByTestId('sort-options'); const sortOptions = within(sortOptionsContainer).getAllByRole('button'); - userEvent.click(sortOptions[2]); + await userEvent.click(sortOptions[2]); expect(onSortChange).toHaveBeenCalledWith([SORT_DIRECTION.up, SORT_OPTIONS[2]]); }); - test('it should not change the sort option if the user clicks on same option in the popover', () => { + test('it should not change the sort option if the user clicks on same option in the popover', async () => { const sortOptionsContainer = screen.getByTestId('sort-options'); const sortOptions = within(sortOptionsContainer).getAllByRole('button'); // clicking on current selected value - userEvent.click(sortOptions[0]); + await userEvent.click(sortOptions[0]); expect(onSortChange).not.toHaveBeenCalled(); }); - test('it should change the sort option if the user clicks in different option in the popover', () => { + test('it should change the sort option if the user clicks in different option in the popover', async () => { const sortOptionsContainer = screen.getByTestId('sort-options'); const sortOptions = within(sortOptionsContainer).getAllByRole('button'); // clicking in a different value - userEvent.click(sortOptions[1]); + await userEvent.click(sortOptions[1]); expect(onSortChange).toHaveBeenCalledWith([SORT_DIRECTION.up, SORT_OPTIONS[1]]); }); }); @@ -96,40 +96,40 @@ describe('ColumnSort control', () => { await screen.findByTestId('order-options'); }); - test('clicking a order option selects a new sort order', () => { + test('clicking a order option selects a new sort order', async () => { const orderOptionsContainer = screen.getByTestId('order-options'); const orderOptions = within(orderOptionsContainer).getAllByRole('button'); - userEvent.click(orderOptions[0]); + await userEvent.click(orderOptions[0]); expect(onSortChange).toHaveBeenCalledWith([SORT_DIRECTION.down, SORT_OPTIONS[0]]); }); - test('it should not change the order option if the user clicks on same option in the popover', () => { + test('it should not change the order option if the user clicks on same option in the popover', async () => { const orderOptionsContainer = screen.getByTestId('order-options'); const orderOptions = within(orderOptionsContainer).getAllByRole('button'); // by clicking on current selected value - userEvent.click(orderOptions[1]); + await userEvent.click(orderOptions[1]); expect(onSortChange).not.toHaveBeenCalled(); // by clicking in a different value - userEvent.click(orderOptions[0]); + await userEvent.click(orderOptions[0]); expect(onSortChange).toHaveBeenCalledWith([SORT_DIRECTION.down, SORT_OPTIONS[0]]); }); - test('positive sorting', () => { + test('positive sorting', async () => { const sortDirectionControl = screen.getByTestId('sort-direction-toggle'); - userEvent.click(sortDirectionControl); + await userEvent.click(sortDirectionControl); expect(onSortChange).toHaveBeenCalledWith([SORT_DIRECTION.down, SORT_OPTIONS[0]]); }); - test('negative sorting', () => { + test('negative sorting', async () => { rendered.rerender(); const sortDirectionControl = screen.getByTestId('sort-direction-toggle'); - userEvent.click(sortDirectionControl); + await userEvent.click(sortDirectionControl); expect(onSortChange).toHaveBeenCalledWith([SORT_DIRECTION.up, SORT_OPTIONS[2]]); }); }); diff --git a/src/ContextMenu/index.test.js b/src/ContextMenu/index.test.js index c547f975a..9a620c02e 100644 --- a/src/ContextMenu/index.test.js +++ b/src/ContextMenu/index.test.js @@ -29,7 +29,7 @@ describe('ContextMenu', () => { expect(screen.getByTestId('contextMenu-positionReference')).not.toHaveClass('hidden'); - userEvent.click(screen.getByTestId('contextMenu-area')); + await userEvent.click(screen.getByTestId('contextMenu-area')); expect(screen.getByTestId('contextMenu-positionReference')).toHaveClass('hidden'); }); diff --git a/src/CursorGpsDisplay/MenuPopover/index.test.js b/src/CursorGpsDisplay/MenuPopover/index.test.js index 61fdd0504..d00b66f14 100644 --- a/src/CursorGpsDisplay/MenuPopover/index.test.js +++ b/src/CursorGpsDisplay/MenuPopover/index.test.js @@ -20,13 +20,15 @@ jest.mock('../../hooks/useJumpToLocation', () => jest.fn()); describe('CursorGpsDisplay - MenuPopover', () => { const onClose = jest.fn(); - let jumpToLocationMock, showPopupMock, store; - beforeEach(() => { + let jumpToLocationMock, showPopupMock, store, user; + beforeEach(async () => { showPopupMock = jest.fn(() => () => {}); showPopup.mockImplementation(showPopupMock); jumpToLocationMock = jest.fn(); useJumpToLocation.mockImplementation(() => jumpToLocationMock); + user = await userEvent.setup({ delay: null }); + store = { data: {}, view: { @@ -59,16 +61,16 @@ describe('CursorGpsDisplay - MenuPopover', () => { ); - test('jumps to the typed coordinates by pressing enter', () => { + test('jumps to the typed coordinates by pressing enter', async () => { renderMenuPopover(); - userEvent.type(screen.getByLabelText('GPS location'), '10,10'); + await user.type(screen.getByLabelText('GPS location'), '10,10'); expect(jumpToLocationMock).not.toHaveBeenCalled(); expect(showPopup).not.toHaveBeenCalled(); expect(onClose).not.toHaveBeenCalled(); - userEvent.keyboard('{Enter}'); + await user.keyboard('{Enter}'); expect(jumpToLocationMock).toHaveBeenCalledTimes(1); expect(jumpToLocationMock).toHaveBeenCalledWith([10, 10]); @@ -89,41 +91,41 @@ describe('CursorGpsDisplay - MenuPopover', () => { }); }); - test('closes the menu if the user presses escape', () => { + test('closes the menu if the user presses escape', async () => { renderMenuPopover(); expect(onClose).not.toHaveBeenCalled(); - userEvent.type(screen.getByLabelText('GPS location'), '10,10'); - userEvent.keyboard('{Escape}'); + await user.type(screen.getByLabelText('GPS location'), '10,10'); + await user.keyboard('{Escape}'); expect(onClose).toHaveBeenCalledTimes(1); }); - test('disables the GPS input button if there is no value', () => { + test('disables the GPS input button if there is no value', async () => { renderMenuPopover(); expect(screen.getByLabelText('Jump to coordinates')).toBeDisabled(); }); - test('enables the GPS input button if there is a value', () => { + test('enables the GPS input button if there is a value', async () => { renderMenuPopover(); - userEvent.type(screen.getByLabelText('GPS location'), '10,10'); + await user.type(screen.getByLabelText('GPS location'), '10,10'); expect(screen.getByLabelText('Jump to coordinates')).toBeEnabled(); }); - test('jumps to the typed coordinates by clicking the GPS input button', () => { + test('jumps to the typed coordinates by clicking the GPS input button', async () => { renderMenuPopover(); - userEvent.type(screen.getByLabelText('GPS location'), '10,10'); + await user.type(screen.getByLabelText('GPS location'), '10,10'); expect(jumpToLocationMock).not.toHaveBeenCalled(); expect(showPopup).not.toHaveBeenCalled(); expect(onClose).not.toHaveBeenCalled(); - userEvent.click(screen.getByLabelText('Jump to coordinates')); + await user.click(screen.getByLabelText('Jump to coordinates')); expect(jumpToLocationMock).toHaveBeenCalledTimes(1); expect(jumpToLocationMock).toHaveBeenCalledWith([10, 10]); @@ -144,7 +146,7 @@ describe('CursorGpsDisplay - MenuPopover', () => { }); }); - test('closes the menu if the user clicks outside', () => { + test('closes the menu if the user clicks outside', async () => { render(<>
@@ -163,7 +165,7 @@ describe('CursorGpsDisplay - MenuPopover', () => { expect(onClose).not.toHaveBeenCalled(); - userEvent.click(screen.getByTestId('outside')); + await user.click(screen.getByTestId('outside')); expect(onClose).toHaveBeenCalledTimes(1); }); diff --git a/src/CursorGpsDisplay/index.test.js b/src/CursorGpsDisplay/index.test.js index 2f469d6e1..ae8fb8101 100644 --- a/src/CursorGpsDisplay/index.test.js +++ b/src/CursorGpsDisplay/index.test.js @@ -2,7 +2,7 @@ import React from 'react'; import { Provider } from 'react-redux'; import userEvent from '@testing-library/user-event'; -import { render, screen, waitFor } from '../test-utils'; +import { act, render, screen, waitFor } from '../test-utils'; import { createMapMock } from '../__test-helpers/mocks'; import { GPS_FORMATS } from '../utils/location'; import { MapContext } from '../App'; @@ -47,14 +47,14 @@ describe('CursorGpsDisplay', () => { ); - test('does not track the cursor coordinates if the map is not ready', () => { + test('does not track the cursor coordinates if the map is not ready', async () => { renderCursorGpsDisplay(undefined, undefined, null); expect(map.on).toHaveBeenCalledTimes(0); expect(map.off).toHaveBeenCalledTimes(0); }); - test('tracks the cursor coordinates', () => { + test('tracks the cursor coordinates', async () => { expect(map.on).toHaveBeenCalledTimes(0); const { unmount } = renderCursorGpsDisplay(); @@ -69,20 +69,20 @@ describe('CursorGpsDisplay', () => { expect(map.off.mock.calls[0][0]).toBe('mousemove'); }); - test('shows the cursor GPS display with the cursor coordinates', () => { + test('shows the cursor GPS display with the cursor coordinates', async () => { renderCursorGpsDisplay(); - map.__test__.fireHandlers('mousemove', { lngLat: { lng: 10.012657, lat: 11.666666 } }); + act(() => map.__test__.fireHandlers('mousemove', { lngLat: { lng: 10.012657, lat: 11.666666 } })); expect(screen.getByLabelText('Open the GPS display menu')).toHaveTextContent(('11.666666°, 10.012657°')); }); - test('opens the menu', () => { + test('opens the menu', async () => { renderCursorGpsDisplay(); expect(screen.queryByRole('presentation')).toBeNull(); - userEvent.click(screen.getByLabelText('Open the GPS display menu')); + await userEvent.click(screen.getByLabelText('Open the GPS display menu')); expect(screen.getByRole('presentation')).toBeVisible(); }); @@ -91,12 +91,12 @@ describe('CursorGpsDisplay', () => { renderCursorGpsDisplay(); const button = screen.getByLabelText('Open the GPS display menu'); - userEvent.click(button); + await userEvent.click(button); const menu = screen.getByRole('presentation'); expect(menu).toBeVisible(); - userEvent.click(button); + await userEvent.click(button); await waitFor(() => { expect(menu).not.toBeVisible(); diff --git a/src/DatePicker/CalendarPopper/MonthPicker/index.test.js b/src/DatePicker/CalendarPopper/MonthPicker/index.test.js index 2502693c3..ad8b4676c 100644 --- a/src/DatePicker/CalendarPopper/MonthPicker/index.test.js +++ b/src/DatePicker/CalendarPopper/MonthPicker/index.test.js @@ -34,118 +34,118 @@ describe('DatePicker - CalendarPopper - MonthPicker', () => { jest.restoreAllMocks(); }); - test('decreases the year', () => { + test('decreases the year', async () => { renderMonthPicker(); expect(decreaseYear).not.toHaveBeenCalled(); - userEvent.click(screen.getByLabelText('Previous year')); + await userEvent.click(screen.getByLabelText('Previous year')); expect(decreaseYear).toHaveBeenCalledTimes(1); }); - test('decreases the month', () => { + test('decreases the month', async () => { renderMonthPicker(); expect(decreaseMonth).not.toHaveBeenCalled(); - userEvent.click(screen.getByLabelText('Previous month')); + await userEvent.click(screen.getByLabelText('Previous month')); expect(decreaseMonth).toHaveBeenCalledTimes(1); }); - test('increases the month', () => { + test('increases the month', async () => { renderMonthPicker(); expect(increaseMonth).not.toHaveBeenCalled(); - userEvent.click(screen.getByLabelText('Next month')); + await userEvent.click(screen.getByLabelText('Next month')); expect(increaseMonth).toHaveBeenCalledTimes(1); }); - test('increases the year', () => { + test('increases the year', async () => { renderMonthPicker(); expect(increaseYear).not.toHaveBeenCalled(); - userEvent.click(screen.getByLabelText('Next year')); + await userEvent.click(screen.getByLabelText('Next year')); expect(increaseYear).toHaveBeenCalledTimes(1); }); - test('opens the month picker', () => { + test('opens the month picker', async () => { renderMonthPicker(); - userEvent.click(screen.getByLabelText('Open month picker')); + await userEvent.click(screen.getByLabelText('Open month picker')); expect(screen.getByLabelText('Choose Date')).toBeVisible(); }); - test('closes the month picker by clicking the button', () => { + test('closes the month picker by clicking the button', async () => { renderMonthPicker(); const openMonthPickerButton = screen.getByLabelText('Open month picker'); - userEvent.click(openMonthPickerButton); + await userEvent.click(openMonthPickerButton); const monthPicker = screen.getByLabelText('Choose Date'); expect(monthPicker).toBeVisible(); - userEvent.click(openMonthPickerButton); + await userEvent.click(openMonthPickerButton); expect(monthPicker).not.toBeVisible(); }); - test('closes the month picker by pressing escape', () => { + test('closes the month picker by pressing escape', async () => { renderMonthPicker(); - userEvent.click(screen.getByLabelText('Open month picker')); + await userEvent.click(screen.getByLabelText('Open month picker')); const monthPicker = screen.getByLabelText('Choose Date'); expect(monthPicker).toBeVisible(); - userEvent.keyboard('{escape}'); + await userEvent.keyboard('{escape}'); expect(monthPicker).not.toBeVisible(); }); - test('decreases the year of the month picker', () => { + test('decreases the year of the month picker', async () => { renderMonthPicker(); - userEvent.click(screen.getByLabelText('Open month picker')); + await userEvent.click(screen.getByLabelText('Open month picker')); const monthPickerHeader = screen.getByTestId('datePicker-calendarPopper-monthPicker-header'); expect(monthPickerHeader).toHaveTextContent('2020'); - userEvent.click(within(monthPickerHeader).getByLabelText('Previous year')); + await userEvent.click(within(monthPickerHeader).getByLabelText('Previous year')); expect(monthPickerHeader).toHaveTextContent('2019'); }); - test('increases the year of the month picker', () => { + test('increases the year of the month picker', async () => { renderMonthPicker(); - userEvent.click(screen.getByLabelText('Open month picker')); + await userEvent.click(screen.getByLabelText('Open month picker')); const monthPickerHeader = screen.getByTestId('datePicker-calendarPopper-monthPicker-header'); expect(monthPickerHeader).toHaveTextContent('2020'); - userEvent.click(within(monthPickerHeader).getByLabelText('Next year')); + await userEvent.click(within(monthPickerHeader).getByLabelText('Next year')); expect(monthPickerHeader).toHaveTextContent('2021'); }); - test('changes the date when the user clicks an option from the calendar', () => { + test('changes the date when the user clicks an option from the calendar', async () => { renderMonthPicker(); - userEvent.click(screen.getByLabelText('Open month picker')); + await userEvent.click(screen.getByLabelText('Open month picker')); const monthPicker = screen.getByLabelText('Choose Date'); expect(changeMonth).not.toHaveBeenCalled(); expect(changeYear).not.toHaveBeenCalled(); expect(monthPicker).toBeVisible(); - userEvent.click(screen.getByLabelText('Choose March 2020')); + await userEvent.click(screen.getByLabelText('Choose March 2020')); expect(changeMonth).toHaveBeenCalledTimes(1); expect(changeMonth).toHaveBeenCalledWith(2); diff --git a/src/DatePicker/CalendarPopper/index.test.js b/src/DatePicker/CalendarPopper/index.test.js index 2ef8d032c..3ee5eb56d 100644 --- a/src/DatePicker/CalendarPopper/index.test.js +++ b/src/DatePicker/CalendarPopper/index.test.js @@ -26,58 +26,58 @@ describe('DatePicker - CalendarPopper', () => { jest.restoreAllMocks(); }); - test('does not disable the calendar popper', () => { + test('does not disable the calendar popper', async () => { renderCalendarPopper(); expect(screen.getByLabelText('Open calendar')).not.toBeDisabled(); }); - test('disables the calendar popper', () => { + test('disables the calendar popper', async () => { renderCalendarPopper({ disabled: true }); expect(screen.getByLabelText('Open calendar')).toBeDisabled(); }); - test('opens the calendar', () => { + test('opens the calendar', async () => { renderCalendarPopper(); expect(setIsOpen).not.toHaveBeenCalled(); - userEvent.click(screen.getByLabelText('Open calendar')); + await userEvent.click(screen.getByLabelText('Open calendar')); expect(setIsOpen).toHaveBeenCalledTimes(1); expect(setIsOpen).toHaveBeenCalledWith(true); }); - test('closes the calendar by clicking the button', () => { + test('closes the calendar by clicking the button', async () => { renderCalendarPopper({ isOpen: true }); expect(setIsOpen).not.toHaveBeenCalled(); - userEvent.click(screen.getByLabelText('Open calendar')); + await userEvent.click(screen.getByLabelText('Open calendar')); expect(setIsOpen).toHaveBeenCalledTimes(1); expect(setIsOpen).toHaveBeenCalledWith(false); }); - test('closes the calendar by pressing escape', () => { + test('closes the calendar by pressing escape', async () => { renderCalendarPopper({ isOpen: true }); expect(setIsOpen).not.toHaveBeenCalled(); - userEvent.keyboard('{escape}'); + await userEvent.keyboard('{escape}'); expect(setIsOpen).toHaveBeenCalledTimes(1); expect(setIsOpen).toHaveBeenCalledWith(false); }); - test('changes the date when the user clicks an option from the calendar', () => { + test('changes the date when the user clicks an option from the calendar', async () => { renderCalendarPopper({ isOpen: true, value: '2020-01-01' }); expect(onChange).not.toHaveBeenCalled(); expect(setIsOpen).not.toHaveBeenCalled(); - userEvent.click(screen.getByLabelText('Choose Monday, January 13th, 2020')); + await userEvent.click(screen.getByLabelText('Choose Monday, January 13th, 2020')); expect(onChange).toHaveBeenCalledTimes(1); expect(onChange).toHaveBeenCalledWith('2020-01-13'); diff --git a/src/DatePicker/index.test.js b/src/DatePicker/index.test.js index 247e64dad..bce43d157 100644 --- a/src/DatePicker/index.test.js +++ b/src/DatePicker/index.test.js @@ -19,13 +19,13 @@ describe('DatePicker', () => { jest.restoreAllMocks(); }); - test('adds a custom class name', () => { + test('adds a custom class name', async () => { renderDatePicker({ className: 'className' }); expect(screen.getByTestId('datePicker')).toHaveClass('className'); }); - test('sets the default date separator', () => { + test('sets the default date separator', async () => { renderDatePicker(); const dateSeparators = screen.getAllByText('/'); @@ -35,7 +35,7 @@ describe('DatePicker', () => { expect(dateSeparators[1]).toHaveClass('dateSeparator'); }); - test('sets a custom date separator', () => { + test('sets a custom date separator', async () => { renderDatePicker({ dateSeparator: '-' }); const dateSeparators = screen.getAllByText('-'); @@ -45,7 +45,7 @@ describe('DatePicker', () => { expect(dateSeparators[1]).toHaveClass('dateSeparator'); }); - test('does not disable the date picker', () => { + test('does not disable the date picker', async () => { renderDatePicker(); const datePicker = screen.getByTestId('datePicker'); @@ -57,7 +57,7 @@ describe('DatePicker', () => { expect(screen.getByLabelText('Open calendar')).not.toBeDisabled(); }); - test('disables the date picker', () => { + test('disables the date picker', async () => { renderDatePicker({ disabled: true }); const datePicker = screen.getByTestId('datePicker'); @@ -69,7 +69,7 @@ describe('DatePicker', () => { expect(screen.getByLabelText('Open calendar')).toBeDisabled(); }); - test('sets the name to an input with the date picker value', () => { + test('sets the name to an input with the date picker value', async () => { renderDatePicker({ name: 'date-picker-name', value: '2020-01-01' }); const datePickerInput = screen.getByTestId('datePicker-input'); @@ -78,13 +78,13 @@ describe('DatePicker', () => { expect(datePickerInput).toHaveValue('2020-01-01'); }); - test('blurs the date picker', () => { + test('blurs the date picker', async () => { const onBlur = jest.fn(); renderDatePicker({ onBlur }); const datePicker = screen.getByTestId('datePicker'); - userEvent.click(datePicker); + await userEvent.click(datePicker); expect(onBlur).not.toHaveBeenCalled(); @@ -93,19 +93,19 @@ describe('DatePicker', () => { expect(onBlur).toHaveBeenCalledTimes(1); }); - test('focuses the date picker when focusing one of the inner elements', () => { + test('focuses the date picker when focusing one of the inner elements', async () => { const onFocus = jest.fn(); renderDatePicker({ onFocus }); expect(onFocus).not.toHaveBeenCalled(); - userEvent.click(screen.getByLabelText('Year')); + await userEvent.click(screen.getByLabelText('Year')); expect(onFocus).toHaveBeenCalledTimes(1); }); - test('does not set the date picker as read only', () => { + test('does not set the date picker as read only', async () => { renderDatePicker(); expect(screen.getByLabelText('Year')).not.toHaveAttribute('readonly'); @@ -114,7 +114,7 @@ describe('DatePicker', () => { expect(screen.getByLabelText('Open calendar')).not.toBeDisabled(); }); - test('sets the date picker as read only', () => { + test('sets the date picker as read only', async () => { renderDatePicker({ readOnly: true, value: '2020-01-01' }); const yearInput = screen.getByLabelText('Year'); @@ -126,22 +126,22 @@ describe('DatePicker', () => { expect(dayInput).toHaveAttribute('readonly'); expect(screen.getByLabelText('Open calendar')).toBeDisabled(); - userEvent.click(yearInput); - userEvent.keyboard('[ArrowDown]'); - userEvent.keyboard('[ArrowUp]'); + await userEvent.click(yearInput); + await userEvent.keyboard('[ArrowDown]'); + await userEvent.keyboard('[ArrowUp]'); - userEvent.click(montInput); - userEvent.keyboard('[ArrowDown]'); - userEvent.keyboard('[ArrowUp]'); + await userEvent.click(montInput); + await userEvent.keyboard('[ArrowDown]'); + await userEvent.keyboard('[ArrowUp]'); - userEvent.click(dayInput); - userEvent.keyboard('[ArrowDown]'); - userEvent.keyboard('[ArrowUp]'); + await userEvent.click(dayInput); + await userEvent.keyboard('[ArrowDown]'); + await userEvent.keyboard('[ArrowUp]'); expect(onChange).not.toHaveBeenCalled(); }); - test('does not set the date picker as required', () => { + test('does not set the date picker as required', async () => { renderDatePicker(); expect(screen.getByLabelText('Year')).not.toBeRequired(); @@ -149,7 +149,7 @@ describe('DatePicker', () => { expect(screen.getByLabelText('Day')).not.toBeRequired(); }); - test('sets the date picker as required', () => { + test('sets the date picker as required', async () => { renderDatePicker({ required: true }); expect(screen.getByLabelText('Year')).toBeRequired(); @@ -157,42 +157,42 @@ describe('DatePicker', () => { expect(screen.getByLabelText('Day')).toBeRequired(); }); - test('changes when the user modifies the year input with a valid value', () => { + test('changes when the user modifies the year input with a valid value', async () => { renderDatePicker(); expect(onChange).not.toHaveBeenCalled(); - userEvent.type(screen.getByLabelText('Year'), '2'); + await userEvent.type(screen.getByLabelText('Year'), '2'); expect(onChange).toHaveBeenCalledTimes(1); expect(onChange).toHaveBeenCalledWith('2--'); }); - test('changes when the user clears the year input', () => { + test('changes when the user clears the year input', async () => { renderDatePicker({ value: '2--' }); expect(onChange).not.toHaveBeenCalled(); - userEvent.type(screen.getByLabelText('Year'), '{backspace}'); + await userEvent.type(screen.getByLabelText('Year'), '{backspace}'); expect(onChange).toHaveBeenCalledTimes(1); expect(onChange).toHaveBeenCalledWith(EMPTY_DATE_VALUE); }); - test('does not change when the user modifies the year input with an invalid value', () => { + test('does not change when the user modifies the year input with an invalid value', async () => { renderDatePicker(); expect(onChange).not.toHaveBeenCalled(); - userEvent.type(screen.getByLabelText('Year'), 'a'); + await userEvent.type(screen.getByLabelText('Year'), 'a'); expect(onChange).not.toHaveBeenCalled(); }); - test('sets the max year as the new year value if the new year is over the max year', () => { + test('sets the max year as the new year value if the new year is over the max year', async () => { const { rerender } = renderDatePicker({ max: '2021-06-01' }); - userEvent.click(screen.getByLabelText('Year')); + await userEvent.click(screen.getByLabelText('Year')); rerender( { expect(onChange).not.toHaveBeenCalled(); - userEvent.keyboard('2'); + await userEvent.keyboard('2'); expect(onChange).toHaveBeenCalledTimes(1); expect(onChange).toHaveBeenCalledWith('2021--'); }); - test('sets the max month as the new month value if the new year is the max year and the old month was above the max month', () => { + test('sets the max month as the new month value if the new year is the max year and the old month was above the max month', async () => { const { rerender } = renderDatePicker({ max: '2021-06-01' }); - userEvent.click(screen.getByLabelText('Year')); + await userEvent.click(screen.getByLabelText('Year')); rerender( { expect(onChange).not.toHaveBeenCalled(); - userEvent.keyboard('1'); + await userEvent.keyboard('1'); expect(onChange).toHaveBeenCalledTimes(1); expect(onChange).toHaveBeenCalledWith('2021-06-'); }); - test('sets the max day as the new day value if the new year and month are the max values and the old day was above the max day', () => { + test('sets the max day as the new day value if the new year and month are the max values and the old day was above the max day', async () => { const { rerender } = renderDatePicker({ max: '2021-06-01' }); - userEvent.click(screen.getByLabelText('Year')); + await userEvent.click(screen.getByLabelText('Year')); rerender( { expect(onChange).not.toHaveBeenCalled(); - userEvent.keyboard('1'); + await userEvent.keyboard('1'); expect(onChange).toHaveBeenCalledTimes(1); expect(onChange).toHaveBeenCalledWith('2021-06-01'); }); - test('sets the min year as the new year value if the new year is below the min year', () => { + test('sets the min year as the new year value if the new year is below the min year', async () => { const { rerender } = renderDatePicker({ min: '2021-06-01' }); - userEvent.click(screen.getByLabelText('Year')); + await userEvent.click(screen.getByLabelText('Year')); rerender( { expect(onChange).not.toHaveBeenCalled(); - userEvent.keyboard('0'); + await userEvent.keyboard('0'); expect(onChange).toHaveBeenCalledTimes(1); expect(onChange).toHaveBeenCalledWith('2021--'); }); - test('sets the min month as the new month value if the new year is the min year and the old month was below the min month', () => { + test('sets the min month as the new month value if the new year is the min year and the old month was below the min month', async () => { const { rerender } = renderDatePicker({ min: '2021-06-01' }); - userEvent.click(screen.getByLabelText('Year')); + await userEvent.click(screen.getByLabelText('Year')); rerender( { expect(onChange).not.toHaveBeenCalled(); - userEvent.keyboard('1'); + await userEvent.keyboard('1'); expect(onChange).toHaveBeenCalledTimes(1); expect(onChange).toHaveBeenCalledWith('2021-06-'); }); - test('sets the min day as the new day value if the new year and month are the min values and the old day was below the min day', () => { + test('sets the min day as the new day value if the new year and month are the min values and the old day was below the min day', async () => { const { rerender } = renderDatePicker({ min: '2021-06-05' }); - userEvent.click(screen.getByLabelText('Year')); + await userEvent.click(screen.getByLabelText('Year')); rerender( { expect(onChange).not.toHaveBeenCalled(); - userEvent.keyboard('1'); + await userEvent.keyboard('1'); expect(onChange).toHaveBeenCalledTimes(1); expect(onChange).toHaveBeenCalledWith('2021-06-05'); }); - test('focuses the month input if the focus is on the year input and the user presses the right arrow', () => { + test('focuses the month input if the focus is on the year input and the user presses the right arrow', async () => { renderDatePicker(); - userEvent.click(screen.getByLabelText('Year')); + await userEvent.click(screen.getByLabelText('Year')); const monthInput = screen.getByLabelText('Month'); expect(monthInput).not.toHaveFocus(); - userEvent.keyboard('[ArrowRight]'); + await userEvent.keyboard('[ArrowRight]'); expect(monthInput).toHaveFocus(); }); - test('focuses the month input automatically when the user finishes typing a valid year', () => { + test('focuses the month input automatically when the user finishes typing a valid year', async () => { const { rerender } = renderDatePicker(); - userEvent.click(screen.getByLabelText('Year')); + await userEvent.click(screen.getByLabelText('Year')); const monthInput = screen.getByLabelText('Month'); expect(monthInput).not.toHaveFocus(); rerender(); - userEvent.keyboard('0'); + await userEvent.keyboard('0'); expect(monthInput).toHaveFocus(); }); - test('does not increment the year when the user presses the up arrow if the input is empty', () => { + test('does not increment the year when the user presses the up arrow if the input is empty', async () => { renderDatePicker(); - userEvent.click(screen.getByLabelText('Year')); + await userEvent.click(screen.getByLabelText('Year')); expect(onChange).not.toHaveBeenCalled(); - userEvent.keyboard('[ArrowUp]'); + await userEvent.keyboard('[ArrowUp]'); expect(onChange).not.toHaveBeenCalled(); }); - test('does not increment the year when the user presses the up arrow if the input is 9999', () => { + test('does not increment the year when the user presses the up arrow if the input is 9999', async () => { renderDatePicker({ value: '9999-' }); - userEvent.click(screen.getByLabelText('Year')); + await userEvent.click(screen.getByLabelText('Year')); expect(onChange).not.toHaveBeenCalled(); - userEvent.keyboard('[ArrowUp]'); + await userEvent.keyboard('[ArrowUp]'); expect(onChange).not.toHaveBeenCalled(); }); - test('increments the year if the input has a valid value and is focused and the user presses the up arrow', () => { + test('increments the year if the input has a valid value and is focused and the user presses the up arrow', async () => { renderDatePicker({ value: '2020--' }); - userEvent.click(screen.getByLabelText('Year')); + await userEvent.click(screen.getByLabelText('Year')); expect(onChange).not.toHaveBeenCalled(); - userEvent.keyboard('[ArrowUp]'); + await userEvent.keyboard('[ArrowUp]'); expect(onChange).toHaveBeenCalledTimes(1); expect(onChange).toHaveBeenCalledWith('2021--'); }); - test('does not decrement the year when the user presses the down arrow if the input is empty', () => { + test('does not decrement the year when the user presses the down arrow if the input is empty', async () => { renderDatePicker(); - userEvent.click(screen.getByLabelText('Year')); + await userEvent.click(screen.getByLabelText('Year')); expect(onChange).not.toHaveBeenCalled(); - userEvent.keyboard('[ArrowDown]'); + await userEvent.keyboard('[ArrowDown]'); expect(onChange).not.toHaveBeenCalled(); }); - test('does not decrement the year when the user presses the down arrow if the input is 0', () => { + test('does not decrement the year when the user presses the down arrow if the input is 0', async () => { renderDatePicker({ value: '0-' }); - userEvent.click(screen.getByLabelText('Year')); + await userEvent.click(screen.getByLabelText('Year')); expect(onChange).not.toHaveBeenCalled(); - userEvent.keyboard('[ArrowDown]'); + await userEvent.keyboard('[ArrowDown]'); expect(onChange).not.toHaveBeenCalled(); }); - test('decrements the year if the input has a valid value and is focused and the user presses the down arrow', () => { + test('decrements the year if the input has a valid value and is focused and the user presses the down arrow', async () => { renderDatePicker({ value: '2020--' }); - userEvent.click(screen.getByLabelText('Year')); + await userEvent.click(screen.getByLabelText('Year')); expect(onChange).not.toHaveBeenCalled(); - userEvent.keyboard('[ArrowDown]'); + await userEvent.keyboard('[ArrowDown]'); expect(onChange).toHaveBeenCalledTimes(1); expect(onChange).toHaveBeenCalledWith('2019--'); }); - test('autofills the first digit when the user modifies the month input with a number over 1', () => { + test('autofills the first digit when the user modifies the month input with a number over 1', async () => { renderDatePicker(); expect(onChange).not.toHaveBeenCalled(); - userEvent.type(screen.getByLabelText('Month'), '2'); + await userEvent.type(screen.getByLabelText('Month'), '2'); expect(onChange).toHaveBeenCalledTimes(1); expect(onChange).toHaveBeenCalledWith('-02-'); }); - test('autofills the first digit when the month input is blurred and it has a digit below 2', () => { + test('autofills the first digit when the month input is blurred and it has a digit below 2', async () => { renderDatePicker({ value: '-1-' }); expect(onChange).not.toHaveBeenCalled(); @@ -432,7 +432,7 @@ describe('DatePicker', () => { expect(onChange).toHaveBeenCalledWith('-01-'); }); - test('does not autofill the first digit when the month input is blurred and it has a digit below 2 if the field is readonly', () => { + test('does not autofill the first digit when the month input is blurred and it has a digit below 2 if the field is readonly', async () => { renderDatePicker({ readOnly: true, value: '-1-' }); fireEvent.blur(screen.getByLabelText('Month')); @@ -440,42 +440,42 @@ describe('DatePicker', () => { expect(onChange).not.toHaveBeenCalled(); }); - test('changes when the user modifies the month input with a valid value', () => { + test('changes when the user modifies the month input with a valid value', async () => { renderDatePicker(); expect(onChange).not.toHaveBeenCalled(); - userEvent.type(screen.getByLabelText('Month'), '1'); + await userEvent.type(screen.getByLabelText('Month'), '1'); expect(onChange).toHaveBeenCalledTimes(1); expect(onChange).toHaveBeenCalledWith('-1-'); }); - test('changes when the user clears the month input', () => { + test('changes when the user clears the month input', async () => { renderDatePicker({ value: '-1-' }); expect(onChange).not.toHaveBeenCalled(); - userEvent.type(screen.getByLabelText('Month'), '{backspace}'); + await userEvent.type(screen.getByLabelText('Month'), '{backspace}'); expect(onChange).toHaveBeenCalledTimes(1); expect(onChange).toHaveBeenCalledWith(EMPTY_DATE_VALUE); }); - test('does not change when the user modifies the month input with an invalid value', () => { + test('does not change when the user modifies the month input with an invalid value', async () => { renderDatePicker(); expect(onChange).not.toHaveBeenCalled(); - userEvent.type(screen.getByLabelText('Month'), 'a'); + await userEvent.type(screen.getByLabelText('Month'), 'a'); expect(onChange).not.toHaveBeenCalled(); }); - test('sets the max month as the new month value if the year is the max year and the new month is above the max month', () => { + test('sets the max month as the new month value if the year is the max year and the new month is above the max month', async () => { const { rerender } = renderDatePicker({ max: '2021-06-01' }); - userEvent.click(screen.getByLabelText('Month')); + await userEvent.click(screen.getByLabelText('Month')); rerender( { expect(onChange).not.toHaveBeenCalled(); - userEvent.keyboard('8'); + await userEvent.keyboard('8'); expect(onChange).toHaveBeenCalledTimes(1); expect(onChange).toHaveBeenCalledWith('2021-06-'); }); - test('sets the max day as the new day value if the year and new month are the max values and the old day was above the max day', () => { + test('sets the max day as the new day value if the year and new month are the max values and the old day was above the max day', async () => { const { rerender } = renderDatePicker({ max: '2021-06-01' }); - userEvent.click(screen.getByLabelText('Month')); + await userEvent.click(screen.getByLabelText('Month')); rerender( { expect(onChange).not.toHaveBeenCalled(); - userEvent.keyboard('6'); + await userEvent.keyboard('6'); expect(onChange).toHaveBeenCalledTimes(1); expect(onChange).toHaveBeenCalledWith('2021-06-01'); }); - test('sets the min month as the new month value if the year is the min year and the new month is below the min month', () => { + test('sets the min month as the new month value if the year is the min year and the new month is below the min month', async () => { const { rerender } = renderDatePicker({ min: '2021-06-01' }); - userEvent.click(screen.getByLabelText('Month')); + await userEvent.click(screen.getByLabelText('Month')); rerender( { expect(onChange).not.toHaveBeenCalled(); - userEvent.keyboard('4'); + await userEvent.keyboard('4'); expect(onChange).toHaveBeenCalledTimes(1); expect(onChange).toHaveBeenCalledWith('2021-06-'); }); - test('sets the min day as the new day value if the year and new month are the min values and the old day was below the min day', () => { + test('sets the min day as the new day value if the year and new month are the min values and the old day was below the min day', async () => { const { rerender } = renderDatePicker({ min: '2021-06-05' }); - userEvent.click(screen.getByLabelText('Month')); + await userEvent.click(screen.getByLabelText('Month')); rerender( { expect(onChange).not.toHaveBeenCalled(); - userEvent.keyboard('6'); + await userEvent.keyboard('6'); expect(onChange).toHaveBeenCalledTimes(1); expect(onChange).toHaveBeenCalledWith('2021-06-05'); }); - test('focuses the day input if the focus is on the month input and the user presses the right arrow', () => { + test('focuses the day input if the focus is on the month input and the user presses the right arrow', async () => { renderDatePicker(); - userEvent.click(screen.getByLabelText('Month')); + await userEvent.click(screen.getByLabelText('Month')); const dayInput = screen.getByLabelText('Day'); expect(dayInput).not.toHaveFocus(); - userEvent.keyboard('[ArrowRight]'); + await userEvent.keyboard('[ArrowRight]'); expect(dayInput).toHaveFocus(); }); - test('focuses the year input if the focus is on the month input and the user presses the left arrow', () => { + test('focuses the year input if the focus is on the month input and the user presses the left arrow', async () => { renderDatePicker(); - userEvent.click(screen.getByLabelText('Month')); + await userEvent.click(screen.getByLabelText('Month')); const yearInput = screen.getByLabelText('Year'); expect(yearInput).not.toHaveFocus(); - userEvent.keyboard('[ArrowLeft]'); + await userEvent.keyboard('[ArrowLeft]'); expect(yearInput).toHaveFocus(); }); - test('focuses the day input automatically when the user finishes typing a valid month', () => { + test('focuses the day input automatically when the user finishes typing a valid month', async () => { const { rerender } = renderDatePicker(); - userEvent.click(screen.getByLabelText('Month')); + await userEvent.click(screen.getByLabelText('Month')); const dayInput = screen.getByLabelText('Day'); expect(dayInput).not.toHaveFocus(); rerender(); - userEvent.keyboard('2'); + await userEvent.keyboard('2'); expect(dayInput).toHaveFocus(); }); - test('sets the month to 01 if the input is empty and focused and the user presses the up arrow', () => { + test('sets the month to 01 if the input is empty and focused and the user presses the up arrow', async () => { renderDatePicker(); - userEvent.click(screen.getByLabelText('Month')); + await userEvent.click(screen.getByLabelText('Month')); expect(onChange).not.toHaveBeenCalled(); - userEvent.keyboard('[ArrowUp]'); + await userEvent.keyboard('[ArrowUp]'); expect(onChange).toHaveBeenCalledTimes(1); expect(onChange).toHaveBeenCalledWith('-01-'); }); - test('sets the month to 01 if the input has the value 12 and is focused and the user presses the up arrow', () => { + test('sets the month to 01 if the input has the value 12 and is focused and the user presses the up arrow', async () => { renderDatePicker({ value: '-12-' }); - userEvent.click(screen.getByLabelText('Month')); + await userEvent.click(screen.getByLabelText('Month')); expect(onChange).not.toHaveBeenCalled(); - userEvent.keyboard('[ArrowUp]'); + await userEvent.keyboard('[ArrowUp]'); expect(onChange).toHaveBeenCalledTimes(1); expect(onChange).toHaveBeenCalledWith('-01-'); }); - test('increments the month if the input has a valid value and is focused and the user presses the up arrow', () => { + test('increments the month if the input has a valid value and is focused and the user presses the up arrow', async () => { renderDatePicker({ value: '-05-' }); - userEvent.click(screen.getByLabelText('Month')); + await userEvent.click(screen.getByLabelText('Month')); expect(onChange).not.toHaveBeenCalled(); - userEvent.keyboard('[ArrowUp]'); + await userEvent.keyboard('[ArrowUp]'); expect(onChange).toHaveBeenCalledTimes(1); expect(onChange).toHaveBeenCalledWith('-06-'); }); - test('sets the month to 12 if the input is empty and focused and the user presses the down arrow', () => { + test('sets the month to 12 if the input is empty and focused and the user presses the down arrow', async () => { renderDatePicker(); - userEvent.click(screen.getByLabelText('Month')); + await userEvent.click(screen.getByLabelText('Month')); expect(onChange).not.toHaveBeenCalled(); - userEvent.keyboard('[ArrowDown]'); + await userEvent.keyboard('[ArrowDown]'); expect(onChange).toHaveBeenCalledTimes(1); expect(onChange).toHaveBeenCalledWith('-12-'); }); - test('sets the month to 12 if the input has the value 01 and is focused and the user presses the down arrow', () => { + test('sets the month to 12 if the input has the value 01 and is focused and the user presses the down arrow', async () => { renderDatePicker({ value: '-01-' }); - userEvent.click(screen.getByLabelText('Month')); + await userEvent.click(screen.getByLabelText('Month')); expect(onChange).not.toHaveBeenCalled(); - userEvent.keyboard('[ArrowDown]'); + await userEvent.keyboard('[ArrowDown]'); expect(onChange).toHaveBeenCalledTimes(1); expect(onChange).toHaveBeenCalledWith('-12-'); }); - test('decrements the month if the input has a valid value and is focused and the user presses the down arrow', () => { + test('decrements the month if the input has a valid value and is focused and the user presses the down arrow', async () => { renderDatePicker({ value: '-05-' }); - userEvent.click(screen.getByLabelText('Month')); + await userEvent.click(screen.getByLabelText('Month')); expect(onChange).not.toHaveBeenCalled(); - userEvent.keyboard('[ArrowDown]'); + await userEvent.keyboard('[ArrowDown]'); expect(onChange).toHaveBeenCalledTimes(1); expect(onChange).toHaveBeenCalledWith('-04-'); }); - test('autofills the first digit when the user modifies the day input with a number over 3', () => { + test('autofills the first digit when the user modifies the day input with a number over 3', async () => { renderDatePicker(); expect(onChange).not.toHaveBeenCalled(); - userEvent.type(screen.getByLabelText('Day'), '4'); + await userEvent.type(screen.getByLabelText('Day'), '4'); expect(onChange).toHaveBeenCalledTimes(1); expect(onChange).toHaveBeenCalledWith('--04'); }); - test('autofills the first digit when the day input is blurred and it has a digit below 4', () => { + test('autofills the first digit when the day input is blurred and it has a digit below 4', async () => { renderDatePicker({ value: '--3' }); expect(onChange).not.toHaveBeenCalled(); @@ -692,7 +692,7 @@ describe('DatePicker', () => { expect(onChange).toHaveBeenCalledWith('--03'); }); - test('does not autofill the first digit when the day input is blurred and it has a digit below 4 if the field is readonly', () => { + test('does not autofill the first digit when the day input is blurred and it has a digit below 4 if the field is readonly', async () => { renderDatePicker({ readOnly: true, value: '--3' }); fireEvent.blur(screen.getByLabelText('Day')); @@ -700,42 +700,42 @@ describe('DatePicker', () => { expect(onChange).not.toHaveBeenCalled(); }); - test('changes when the user modifies the day input with a valid value', () => { + test('changes when the user modifies the day input with a valid value', async () => { renderDatePicker(); expect(onChange).not.toHaveBeenCalled(); - userEvent.type(screen.getByLabelText('Day'), '1'); + await userEvent.type(screen.getByLabelText('Day'), '1'); expect(onChange).toHaveBeenCalledTimes(1); expect(onChange).toHaveBeenCalledWith('--1'); }); - test('changes when the user clears the day input', () => { + test('changes when the user clears the day input', async () => { renderDatePicker({ value: '--1' }); expect(onChange).not.toHaveBeenCalled(); - userEvent.type(screen.getByLabelText('Day'), '{backspace}'); + await userEvent.type(screen.getByLabelText('Day'), '{backspace}'); expect(onChange).toHaveBeenCalledTimes(1); expect(onChange).toHaveBeenCalledWith(EMPTY_DATE_VALUE); }); - test('does not change when the user modifies the day input with an invalid value', () => { + test('does not change when the user modifies the day input with an invalid value', async () => { renderDatePicker(); expect(onChange).not.toHaveBeenCalled(); - userEvent.type(screen.getByLabelText('Day'), 'a'); + await userEvent.type(screen.getByLabelText('Day'), 'a'); expect(onChange).not.toHaveBeenCalled(); }); - test('sets the max day as the new day value if the year and month are the max values and the new day is above the max day', () => { + test('sets the max day as the new day value if the year and month are the max values and the new day is above the max day', async () => { const { rerender } = renderDatePicker({ max: '2021-06-01' }); - userEvent.click(screen.getByLabelText('Day')); + await userEvent.click(screen.getByLabelText('Day')); rerender( { expect(onChange).not.toHaveBeenCalled(); - userEvent.keyboard('3'); + await userEvent.keyboard('3'); expect(onChange).toHaveBeenCalledTimes(1); expect(onChange).toHaveBeenCalledWith('2021-06-01'); }); - test('sets the min day as the new day value if the year and month are the min values and the new day is below the min day', () => { + test('sets the min day as the new day value if the year and month are the min values and the new day is below the min day', async () => { const { rerender } = renderDatePicker({ min: '2021-06-05' }); - userEvent.click(screen.getByLabelText('Day')); + await userEvent.click(screen.getByLabelText('Day')); rerender( { expect(onChange).not.toHaveBeenCalled(); - userEvent.keyboard('3'); + await userEvent.keyboard('3'); expect(onChange).toHaveBeenCalledTimes(1); expect(onChange).toHaveBeenCalledWith('2021-06-05'); }); - test('focuses the month input if the focus is on the day input and the user presses the left arrow', () => { + test('focuses the month input if the focus is on the day input and the user presses the left arrow', async () => { renderDatePicker(); - userEvent.click(screen.getByLabelText('Day')); + await userEvent.click(screen.getByLabelText('Day')); const monthInput = screen.getByLabelText('Month'); expect(monthInput).not.toHaveFocus(); - userEvent.keyboard('[ArrowLeft]'); + await userEvent.keyboard('[ArrowLeft]'); expect(monthInput).toHaveFocus(); }); - test('sets the day to 01 if the input is empty and focused and the user presses the up arrow', () => { + test('sets the day to 01 if the input is empty and focused and the user presses the up arrow', async () => { renderDatePicker(); - userEvent.click(screen.getByLabelText('Day')); + await userEvent.click(screen.getByLabelText('Day')); expect(onChange).not.toHaveBeenCalled(); - userEvent.keyboard('[ArrowUp]'); + await userEvent.keyboard('[ArrowUp]'); expect(onChange).toHaveBeenCalledTimes(1); expect(onChange).toHaveBeenCalledWith('--01'); }); - test('sets the day to 01 if the input has the value 31 and is focused and the user presses the up arrow', () => { + test('sets the day to 01 if the input has the value 31 and is focused and the user presses the up arrow', async () => { renderDatePicker({ value: '--31' }); - userEvent.click(screen.getByLabelText('Day')); + await userEvent.click(screen.getByLabelText('Day')); expect(onChange).not.toHaveBeenCalled(); - userEvent.keyboard('[ArrowUp]'); + await userEvent.keyboard('[ArrowUp]'); expect(onChange).toHaveBeenCalledTimes(1); expect(onChange).toHaveBeenCalledWith('--01'); }); - test('increments the day if the input has a valid value and is focused and the user presses the up arrow', () => { + test('increments the day if the input has a valid value and is focused and the user presses the up arrow', async () => { renderDatePicker({ value: '--18' }); - userEvent.click(screen.getByLabelText('Day')); + await userEvent.click(screen.getByLabelText('Day')); expect(onChange).not.toHaveBeenCalled(); - userEvent.keyboard('[ArrowUp]'); + await userEvent.keyboard('[ArrowUp]'); expect(onChange).toHaveBeenCalledTimes(1); expect(onChange).toHaveBeenCalledWith('--19'); }); - test('sets the day to 31 if the input is empty and focused and the user presses the down arrow', () => { + test('sets the day to 31 if the input is empty and focused and the user presses the down arrow', async () => { renderDatePicker(); - userEvent.click(screen.getByLabelText('Day')); + await userEvent.click(screen.getByLabelText('Day')); expect(onChange).not.toHaveBeenCalled(); - userEvent.keyboard('[ArrowDown]'); + await userEvent.keyboard('[ArrowDown]'); expect(onChange).toHaveBeenCalledTimes(1); expect(onChange).toHaveBeenCalledWith('--31'); }); - test('sets the day to 31 if the input has the value 01 and is focused and the user presses the down arrow', () => { + test('sets the day to 31 if the input has the value 01 and is focused and the user presses the down arrow', async () => { renderDatePicker({ value: '--01' }); - userEvent.click(screen.getByLabelText('Day')); + await userEvent.click(screen.getByLabelText('Day')); expect(onChange).not.toHaveBeenCalled(); - userEvent.keyboard('[ArrowDown]'); + await userEvent.keyboard('[ArrowDown]'); expect(onChange).toHaveBeenCalledTimes(1); expect(onChange).toHaveBeenCalledWith('--31'); }); - test('decrements the day if the input has a valid value and is focused and the user presses the down arrow', () => { + test('decrements the day if the input has a valid value and is focused and the user presses the down arrow', async () => { renderDatePicker({ value: '--18' }); - userEvent.click(screen.getByLabelText('Day')); + await userEvent.click(screen.getByLabelText('Day')); expect(onChange).not.toHaveBeenCalled(); - userEvent.keyboard('[ArrowDown]'); + await userEvent.keyboard('[ArrowDown]'); expect(onChange).toHaveBeenCalledTimes(1); expect(onChange).toHaveBeenCalledWith('--17'); }); - test('opens the calendar', () => { + test('opens the calendar', async () => { renderDatePicker(); - userEvent.click(screen.getByLabelText('Open calendar')); + await userEvent.click(screen.getByLabelText('Open calendar')); expect(screen.getByLabelText('Choose Date')).toBeVisible(); }); - test('closes the calendar', () => { + test('closes the calendar', async () => { renderDatePicker(); const openCalendarButton = screen.getByLabelText('Open calendar'); - userEvent.click(openCalendarButton); + await userEvent.click(openCalendarButton); const calendar = screen.getByLabelText('Choose Date'); expect(calendar).toBeVisible(); - userEvent.click(openCalendarButton); + await userEvent.click(openCalendarButton); expect(calendar).not.toBeVisible(); }); diff --git a/src/DateRangeSelector/index.test.js b/src/DateRangeSelector/index.test.js index cdd6df972..ff73f97d0 100644 --- a/src/DateRangeSelector/index.test.js +++ b/src/DateRangeSelector/index.test.js @@ -21,7 +21,7 @@ describe('presets', () => { render(); const yesterdayBtn = await screen.findByTestId('yesterday-btn'); - userEvent.click(yesterdayBtn); + await userEvent.click(yesterdayBtn); expect(dateRangePresetFn.mock.calls.length).toEqual(1); diff --git a/src/DateTimePicker/index.test.js b/src/DateTimePicker/index.test.js index daabadcf9..17f44093c 100644 --- a/src/DateTimePicker/index.test.js +++ b/src/DateTimePicker/index.test.js @@ -19,25 +19,25 @@ describe('DateTimePicker', () => { jest.restoreAllMocks(); }); - test('adds a custom class name', () => { + test('adds a custom class name', async () => { renderDateTimePicker({ className: 'className' }); expect(screen.getByTestId('dateTimePicker')).toHaveClass('className'); }); - test('customizes the date picker', () => { + test('customizes the date picker', async () => { renderDateTimePicker({ datePickerProps: { className: 'className', 'data-testid': 'datePicker' } }); expect(screen.getByTestId('datePicker')).toHaveClass('className'); }); - test('customizes the time picker', () => { + test('customizes the time picker', async () => { renderDateTimePicker({ timePickerProps: { className: 'className', 'data-testid': 'timePicker' } }); expect(screen.getByTestId('timePicker')).toHaveClass('className'); }); - test('does not disable the date time picker', () => { + test('does not disable the date time picker', async () => { renderDateTimePicker({ datePickerProps: { 'data-testid': 'datePicker' }, timePickerProps: { 'data-testid': 'timePicker' }, @@ -50,7 +50,7 @@ describe('DateTimePicker', () => { expect(screen.getByTestId('timePicker')).not.toHaveClass('disabled'); }); - test('disables the date time picker', () => { + test('disables the date time picker', async () => { renderDateTimePicker({ datePickerProps: { 'data-testid': 'datePicker' }, disabled: true, @@ -61,7 +61,7 @@ describe('DateTimePicker', () => { expect(screen.getByTestId('timePicker')).toHaveClass('disabled'); }); - test('sets the name to an input with the date time picker value', () => { + test('sets the name to an input with the date time picker value', async () => { renderDateTimePicker({ name: 'date-time-picker-name', value: '2020-01-01T06:30' }); const dateTimePickerInput = screen.getByTestId('dateTimePicker-input'); @@ -70,13 +70,13 @@ describe('DateTimePicker', () => { expect(dateTimePickerInput).toHaveValue('2020-01-01T06:30'); }); - test('blurs the date picker', () => { + test('blurs the date picker', async () => { const onBlur = jest.fn(); renderDateTimePicker({ onBlur }); const dateTimePicker = screen.getByTestId('dateTimePicker'); - userEvent.click(dateTimePicker); + await userEvent.click(dateTimePicker); expect(onBlur).not.toHaveBeenCalled(); @@ -85,140 +85,140 @@ describe('DateTimePicker', () => { expect(onBlur).toHaveBeenCalledTimes(1); }); - test('focuses the date time picker when focusing one of the inner elements', () => { + test('focuses the date time picker when focusing one of the inner elements', async () => { const onFocus = jest.fn(); renderDateTimePicker({ onFocus }); expect(onFocus).not.toHaveBeenCalled(); - userEvent.click(screen.getByLabelText('Year')); + await userEvent.click(screen.getByLabelText('Year')); expect(onFocus).toHaveBeenCalledTimes(1); }); - test('does not set the date time picker as read only', () => { + test('does not set the date time picker as read only', async () => { renderDateTimePicker(); expect(screen.getByLabelText('Year')).not.toHaveAttribute('readonly'); expect(screen.getByLabelText('Hour')).not.toHaveAttribute('readonly'); }); - test('sets the date time picker as read only', () => { + test('sets the date time picker as read only', async () => { renderDateTimePicker({ readOnly: true }); expect(screen.getByLabelText('Year')).toHaveAttribute('readonly'); expect(screen.getByLabelText('Hour')).toHaveAttribute('readonly'); }); - test('does not set the date time picker as required', () => { + test('does not set the date time picker as required', async () => { renderDateTimePicker(); expect(screen.getByLabelText('Year')).not.toBeRequired(); expect(screen.getByLabelText('Hour')).not.toBeRequired(); }); - test('sets the date time picker as required', () => { + test('sets the date time picker as required', async () => { renderDateTimePicker({ required: true }); expect(screen.getByLabelText('Year')).toBeRequired(); expect(screen.getByLabelText('Hour')).toBeRequired(); }); - test('changes when the user modifies the date', () => { + test('changes when the user modifies the date', async () => { renderDateTimePicker({ value: '2020-01-01T06:30' }); expect(onChange).not.toHaveBeenCalled(); - userEvent.click(screen.getByLabelText('Open calendar')); - userEvent.click(screen.getByLabelText('Choose Monday, January 13th, 2020')); + await userEvent.click(screen.getByLabelText('Open calendar')); + await userEvent.click(screen.getByLabelText('Choose Monday, January 13th, 2020')); expect(onChange).toHaveBeenCalledTimes(1); expect(onChange).toHaveBeenCalledWith('2020-01-13T06:30'); }); - test('autofills the time to 00:00 when changing the date if the time is empty', () => { + test('autofills the time to 00:00 when changing the date if the time is empty', async () => { renderDateTimePicker({ value: '2020-01-01T:' }); expect(onChange).not.toHaveBeenCalled(); - userEvent.click(screen.getByLabelText('Open calendar')); - userEvent.click(screen.getByLabelText('Choose Monday, January 13th, 2020')); + await userEvent.click(screen.getByLabelText('Open calendar')); + await userEvent.click(screen.getByLabelText('Choose Monday, January 13th, 2020')); expect(onChange).toHaveBeenCalledTimes(1); expect(onChange).toHaveBeenCalledWith('2020-01-13T00:00'); }); - test('changes when the user modifies the time', () => { + test('changes when the user modifies the time', async () => { renderDateTimePicker({ value: '--T06:30' }); expect(onChange).not.toHaveBeenCalled(); - userEvent.click(screen.getByLabelText('Open time options')); - userEvent.click(screen.getByText('08:00 AM')); + await userEvent.click(screen.getByLabelText('Open time options')); + await userEvent.click(screen.getByText('08:00 AM')); expect(onChange).toHaveBeenCalledTimes(1); expect(onChange).toHaveBeenCalledWith('--T08:00'); }); - test('applies the max to the date picker', () => { + test('applies the max to the date picker', async () => { renderDateTimePicker({ max: '2020-01-15T15:00', value: '2020-01-01T06:30' }); expect(onChange).not.toHaveBeenCalled(); - userEvent.click(screen.getByLabelText('Open calendar')); - userEvent.click(screen.getByLabelText('Not available Thursday, January 16th, 2020')); + await userEvent.click(screen.getByLabelText('Open calendar')); + await userEvent.click(screen.getByLabelText('Not available Thursday, January 16th, 2020')); expect(onChange).not.toHaveBeenCalled(); }); - test('applies the min to the date picker', () => { + test('applies the min to the date picker', async () => { renderDateTimePicker({ min: '2020-01-15T15:00', value: '2020-01-25T06:30' }); expect(onChange).not.toHaveBeenCalled(); - userEvent.click(screen.getByLabelText('Open calendar')); - userEvent.click(screen.getByLabelText('Not available Monday, January 13th, 2020')); + await userEvent.click(screen.getByLabelText('Open calendar')); + await userEvent.click(screen.getByLabelText('Not available Monday, January 13th, 2020')); expect(onChange).not.toHaveBeenCalled(); }); - test('applies the max to the time picker if the date is the max value', () => { + test('applies the max to the time picker if the date is the max value', async () => { renderDateTimePicker({ max: '2020-01-15T15:00', value: '2020-01-15T06:30' }); expect(onChange).not.toHaveBeenCalled(); - userEvent.click(screen.getByLabelText('Open time options')); + await userEvent.click(screen.getByLabelText('Open time options')); expect(screen.queryByText('03:30 PM')).toBeNull(); }); - test('does not apply the max to the time picker if the date is below the max value', () => { + test('does not apply the max to the time picker if the date is below the max value', async () => { renderDateTimePicker({ max: '2020-01-15T15:00', value: '2020-01-14T06:30' }); expect(onChange).not.toHaveBeenCalled(); - userEvent.click(screen.getByLabelText('Open time options')); + await userEvent.click(screen.getByLabelText('Open time options')); expect(screen.getByText('03:30 PM')).toBeVisible(); }); - test('applies the min to the time picker if the date is the min value', () => { + test('applies the min to the time picker if the date is the min value', async () => { renderDateTimePicker({ min: '2020-01-15T15:00', value: '2020-01-15T20:30' }); expect(onChange).not.toHaveBeenCalled(); - userEvent.click(screen.getByLabelText('Open time options')); + await userEvent.click(screen.getByLabelText('Open time options')); expect(screen.queryByText('02:30 PM')).toBeNull(); }); - test('does not apply the min to the time picker if the date is above the max value', () => { + test('does not apply the min to the time picker if the date is above the max value', async () => { renderDateTimePicker({ max: '2020-01-15T15:00', value: '2020-01-16T20:30' }); expect(onChange).not.toHaveBeenCalled(); - userEvent.click(screen.getByLabelText('Open time options')); + await userEvent.click(screen.getByLabelText('Open time options')); expect(screen.getByText('02:30 PM')).toBeVisible(); }); diff --git a/src/DetailViewComponents/ActivitySection/AttachmentListItem/index.js b/src/DetailViewComponents/ActivitySection/AttachmentListItem/index.js index a885ea5d6..0245e8d28 100644 --- a/src/DetailViewComponents/ActivitySection/AttachmentListItem/index.js +++ b/src/DetailViewComponents/ActivitySection/AttachmentListItem/index.js @@ -123,7 +123,7 @@ const AttachmentListItem = ({
- +
@@ -160,7 +160,7 @@ const AttachmentListItem = ({ return
  • - +
    diff --git a/src/DetailViewComponents/ActivitySection/AttachmentListItem/index.test.js b/src/DetailViewComponents/ActivitySection/AttachmentListItem/index.test.js index 5154dc629..d190da6b7 100644 --- a/src/DetailViewComponents/ActivitySection/AttachmentListItem/index.test.js +++ b/src/DetailViewComponents/ActivitySection/AttachmentListItem/index.test.js @@ -116,8 +116,8 @@ describe('ActivitySection - AttachmentListItem', () => { expect(downloadFileFromUrl).toHaveBeenCalledTimes(0); - const downloadButton = await screen.findByText('download-arrow.svg'); - userEvent.click(downloadButton); + const downloadButton = await screen.findByTestId('activitySection-downloadArrow-1234'); + await userEvent.click(downloadButton); expect(downloadFileFromUrl).toHaveBeenCalledTimes(1); expect(downloadFileFromUrl).toHaveBeenCalledWith('/file.txt', { filename: 'file.txt' }); @@ -135,7 +135,7 @@ describe('ActivitySection - AttachmentListItem', () => { /> ); - expect((await screen.queryByText('trash-can.svg'))).toBeNull(); + expect((await screen.queryByTestId('activitySection-trashCan-file.txt'))).toBeNull(); }); test('user can not download new attachments', async () => { @@ -143,7 +143,7 @@ describe('ActivitySection - AttachmentListItem', () => { ); - expect((await screen.queryByText('download-arrow.svg'))).toBeNull(); + expect((await screen.queryByTestId('activitySection-downloadArrow-1234'))).toBeNull(); }); test('user can delete new attachments', async () => { @@ -154,8 +154,8 @@ describe('ActivitySection - AttachmentListItem', () => { expect(onDelete).toHaveBeenCalledTimes(0); - const deleteButton = await screen.findByText('trash-can.svg'); - userEvent.click(deleteButton); + const deleteButton = await screen.findByTestId('activitySection-trashCan-file.txt'); + await userEvent.click(deleteButton); expect(onDelete).toHaveBeenCalledTimes(1); }); @@ -201,8 +201,8 @@ describe('ActivitySection - AttachmentListItem', () => { expect(mockStoreInstance.getActions()).toHaveLength(0); - const expandArrowIcon = await screen.findByText('expand-arrow.svg'); - userEvent.click(expandArrowIcon); + const expandArrowIcon = await screen.findByTestId('expand-arrow-icon'); + await userEvent.click(expandArrowIcon); await waitFor(() => { expect(mockStoreInstance.getActions()).toHaveLength(1); @@ -221,8 +221,8 @@ describe('ActivitySection - AttachmentListItem', () => { expect(mockStoreInstance.getActions()).toHaveLength(0); - const expandArrowIcon = await screen.findByText('expand-arrow.svg'); - userEvent.click(expandArrowIcon); + const expandArrowIcon = await screen.findByTestId('expand-arrow-icon'); + await userEvent.click(expandArrowIcon); expect(mockStoreInstance.getActions()).toHaveLength(1); expect(mockStoreInstance.getActions()[0].type).toEqual('ADD_MODAL'); @@ -237,8 +237,8 @@ describe('ActivitySection - AttachmentListItem', () => { expect(onExpand).toHaveBeenCalledTimes(0); expect((await screen.findByTestId('activitySection-collapse-1234'))).toHaveClass('collapse'); - const expandAttachmentButton = await screen.findByText('arrow-down-simple.svg'); - userEvent.click(expandAttachmentButton); + const expandAttachmentButton = await screen.findByTestId('activitySection-arrowDown-1234'); + await userEvent.click(expandAttachmentButton); expect(onExpand).toHaveBeenCalledTimes(1); }); @@ -256,8 +256,8 @@ describe('ActivitySection - AttachmentListItem', () => { expect(onCollapse).toHaveBeenCalledTimes(0); expect((await screen.findByTestId('activitySection-collapse-1234'))).toHaveClass('show'); - const colapseAttachmentButton = await screen.findByText('arrow-up-simple.svg'); - userEvent.click(colapseAttachmentButton); + const colapseAttachmentButton = await screen.findByTestId('activitySection-arrowUp-1234'); + await userEvent.click(colapseAttachmentButton); expect(onCollapse).toHaveBeenCalledTimes(1); }); @@ -273,7 +273,7 @@ describe('ActivitySection - AttachmentListItem', () => { expect(mockStoreInstance.getActions()).toHaveLength(0); const expandedImage = await screen.findByRole('img'); - userEvent.click(expandedImage); + await userEvent.click(expandedImage); expect(mockStoreInstance.getActions()).toHaveLength(1); expect(mockStoreInstance.getActions()[0].type).toEqual('ADD_MODAL'); diff --git a/src/DetailViewComponents/ActivitySection/ContainedReportListItem/index.js b/src/DetailViewComponents/ActivitySection/ContainedReportListItem/index.js index d8d3c4903..1723ab39a 100644 --- a/src/DetailViewComponents/ActivitySection/ContainedReportListItem/index.js +++ b/src/DetailViewComponents/ActivitySection/ContainedReportListItem/index.js @@ -68,7 +68,7 @@ const ContainedReportListItem = ({ cardsExpanded, onCollapse, onExpand, report }
    {!!reportFromEventStore && - + }
    diff --git a/src/DetailViewComponents/ActivitySection/ContainedReportListItem/index.test.js b/src/DetailViewComponents/ActivitySection/ContainedReportListItem/index.test.js index 0629baf74..b07f88d94 100644 --- a/src/DetailViewComponents/ActivitySection/ContainedReportListItem/index.test.js +++ b/src/DetailViewComponents/ActivitySection/ContainedReportListItem/index.test.js @@ -112,7 +112,7 @@ describe('ActivitySection - ContainedReportListItem', () => { const mockedStore = mockStore(store); renderCursorGpsDisplay(undefined, mockedStore); - expect((await screen.queryByText('arrow-into.svg'))).toBeNull(); + expect((await screen.queryByTestId('arrow-into-icon'))).toBeNull(); }); test('once the report is loaded, link to navigate into it shows up', async () => { @@ -120,7 +120,7 @@ describe('ActivitySection - ContainedReportListItem', () => { const mockedStore = mockStore(store); renderCursorGpsDisplay(undefined, mockedStore); - expect((await screen.findByText('arrow-into.svg'))).toBeDefined(); + expect((await screen.findByTestId('arrow-into-icon'))).toBeDefined(); }); test('user can open the report collapsible', async () => { @@ -131,8 +131,8 @@ describe('ActivitySection - ContainedReportListItem', () => { expect((await screen.findByTestId('activitySection-collapse-d45cb504-4612-41fe-9ea5-f1b423ac3ba4'))) .toHaveClass('collapse'); - const expandNoteButton = await screen.findByText('arrow-down-simple.svg'); - userEvent.click(expandNoteButton); + const expandNoteButton = await screen.findByTestId('activitySection-arrowDown-d45cb504-4612-41fe-9ea5-f1b423ac3ba4'); + await userEvent.click(expandNoteButton); expect(onExpand).toHaveBeenCalledTimes(1); }); @@ -145,8 +145,8 @@ describe('ActivitySection - ContainedReportListItem', () => { expect((await screen.findByTestId('activitySection-collapse-d45cb504-4612-41fe-9ea5-f1b423ac3ba4'))) .toHaveClass('show'); - const colapseNoteButton = await screen.findByText('arrow-up-simple.svg'); - userEvent.click(colapseNoteButton); + const colapseNoteButton = await screen.findByTestId('activitySection-arrowUp-d45cb504-4612-41fe-9ea5-f1b423ac3ba4'); + await userEvent.click(colapseNoteButton); expect(onCollapse).toHaveBeenCalledTimes(1); }); diff --git a/src/DetailViewComponents/ActivitySection/ItemActionButton/index.test.js b/src/DetailViewComponents/ActivitySection/ItemActionButton/index.test.js index c883b3b24..6bc5b816d 100644 --- a/src/DetailViewComponents/ActivitySection/ItemActionButton/index.test.js +++ b/src/DetailViewComponents/ActivitySection/ItemActionButton/index.test.js @@ -18,7 +18,7 @@ describe('ActivitySection - ItemActionButton', () => { expect(onClick).toHaveBeenCalledTimes(0); const button = await screen.findByRole('button'); - userEvent.click(button); + await userEvent.click(button); expect(onClick).toHaveBeenCalledTimes(1); }); @@ -27,7 +27,7 @@ describe('ActivitySection - ItemActionButton', () => { expect((await screen.queryByRole('tooltip'))).toBeNull(); const button = await screen.findByRole('button'); - userEvent.hover(button); + await userEvent.hover(button); expect((await screen.findByRole('tooltip'))).toHaveTextContent('tooltip'); }); diff --git a/src/DetailViewComponents/ActivitySection/NoteListItem/index.js b/src/DetailViewComponents/ActivitySection/NoteListItem/index.js index ba6d10b6c..bc19b3b36 100644 --- a/src/DetailViewComponents/ActivitySection/NoteListItem/index.js +++ b/src/DetailViewComponents/ActivitySection/NoteListItem/index.js @@ -92,7 +92,7 @@ const NoteListItem = ({ return
  • - +
    diff --git a/src/DetailViewComponents/ActivitySection/NoteListItem/index.test.js b/src/DetailViewComponents/ActivitySection/NoteListItem/index.test.js index e09bfc359..34e5e19d3 100644 --- a/src/DetailViewComponents/ActivitySection/NoteListItem/index.test.js +++ b/src/DetailViewComponents/ActivitySection/NoteListItem/index.test.js @@ -86,7 +86,7 @@ describe('ActivitySection - Note', () => { expect(onDelete).toHaveBeenCalledTimes(0); const deleteButton = await screen.findByTestId('activitySection-deleteIcon-note'); - userEvent.click(deleteButton); + await userEvent.click(deleteButton); expect(onDelete).toHaveBeenCalledTimes(1); }); @@ -99,7 +99,7 @@ describe('ActivitySection - Note', () => { expect(onDone).toHaveBeenCalledTimes(0); const cancelButton = await screen.findByTestId('activitySection-noteDone-note'); - userEvent.click(cancelButton); + await userEvent.click(cancelButton); expect(onDone).toHaveBeenCalledTimes(1); }); @@ -112,7 +112,7 @@ describe('ActivitySection - Note', () => { expect(onCancel).toHaveBeenCalledTimes(0); const cancelButton = await screen.findByTestId('activitySection-noteCancel-note'); - userEvent.click(cancelButton); + await userEvent.click(cancelButton); expect(onCancel).toHaveBeenCalledTimes(1); }); @@ -134,7 +134,7 @@ describe('ActivitySection - Note', () => { expect((await screen.findByRole('textbox'))).toHaveProperty('readOnly', true); const editButton = await screen.findByTestId('activitySection-editIcon-someID'); - userEvent.click(editButton); + await userEvent.click(editButton); expect(onExpand).toHaveBeenCalledTimes(1); expect((await screen.findByText(saveButtonText))).toBeDefined(); @@ -149,8 +149,8 @@ describe('ActivitySection - Note', () => { expect(onExpand).toHaveBeenCalledTimes(0); expect((await screen.findByTestId('activitySection-collapse-note'))).toHaveClass('collapse'); - const expandNoteButton = await screen.findByText('arrow-down-simple.svg'); - userEvent.click(expandNoteButton); + const expandNoteButton = await screen.findByTestId('activitySection-arrowDown-note'); + await userEvent.click(expandNoteButton); expect(onExpand).toHaveBeenCalledTimes(1); }); @@ -163,8 +163,8 @@ describe('ActivitySection - Note', () => { expect(onCollapse).toHaveBeenCalledTimes(0); expect((await screen.findByTestId('activitySection-collapse-note'))).toHaveClass('show'); - const colapseNoteButton = await screen.findByText('arrow-up-simple.svg'); - userEvent.click(colapseNoteButton); + const colapseNoteButton = await screen.findByTestId('activitySection-arrowUp-note'); + await userEvent.click(colapseNoteButton); expect(onCollapse).toHaveBeenCalledTimes(1); }); @@ -178,8 +178,8 @@ describe('ActivitySection - Note', () => { const noteTextArea = await screen.findByRole('textbox'); const editButton = await screen.findByTestId('activitySection-editIcon-'); - userEvent.click(editButton); - userEvent.type(noteTextArea, ' '); + await userEvent.click(editButton); + await userEvent.type(noteTextArea, ' '); expect(noteTextArea).toHaveTextContent(''); }); diff --git a/src/DetailViewComponents/ActivitySection/index.test.js b/src/DetailViewComponents/ActivitySection/index.test.js index 7a042eeee..13fe2773a 100644 --- a/src/DetailViewComponents/ActivitySection/index.test.js +++ b/src/DetailViewComponents/ActivitySection/index.test.js @@ -95,7 +95,7 @@ describe('DetailViewComponents - ActivitySection', () => { expect(reportCollapse).toHaveClass('collapse'); const expandButton = await screen.findByTestId(`activitySection-arrowDown-${id}`); - userEvent.click(expandButton); + await userEvent.click(expandButton); await waitFor(() => { expect(reportCollapse).toHaveClass('show'); @@ -108,9 +108,9 @@ describe('DetailViewComponents - ActivitySection', () => { const { id } = containedReports[0]; const expandButton = await screen.findByTestId(`activitySection-arrowDown-${id}`); - userEvent.click(expandButton); + await userEvent.click(expandButton); const collapseButton = await screen.findByTestId(`activitySection-arrowUp-${id}`); - userEvent.click(collapseButton); + await userEvent.click(collapseButton); const reportCollapse = await screen.findByTestId(`activitySection-collapse-${id}`); @@ -129,7 +129,7 @@ describe('DetailViewComponents - ActivitySection', () => { expect(imageCollapse).toHaveClass('collapse'); const expandButton = await screen.findByTestId(`activitySection-arrowDown-${id}`); - userEvent.click(expandButton); + await userEvent.click(expandButton); await waitFor(() => { expect(imageCollapse).toHaveClass('show'); @@ -143,9 +143,9 @@ describe('DetailViewComponents - ActivitySection', () => { const { id } = imageAttachment; const expandButton = await screen.findByTestId(`activitySection-arrowDown-${id}`); - userEvent.click(expandButton); + await userEvent.click(expandButton); const collapseButton = await screen.findByTestId(`activitySection-arrowUp-${id}`); - userEvent.click(collapseButton); + await userEvent.click(collapseButton); const imageCollapse = await screen.findByTestId(`activitySection-collapse-${id}`); @@ -160,7 +160,7 @@ describe('DetailViewComponents - ActivitySection', () => { expect(onDeleteAttachment).toHaveBeenCalledTimes(0); const deleteNewAttachmentButton = await screen.findByTestId('activitySection-trashCan-newFile1.pdf'); - userEvent.click(deleteNewAttachmentButton); + await userEvent.click(deleteNewAttachmentButton); expect(onDeleteAttachment).toHaveBeenCalledTimes(1); }); @@ -175,7 +175,7 @@ describe('DetailViewComponents - ActivitySection', () => { expect(noteCollapse).toHaveClass('collapse'); const expandButton = await screen.findByTestId(`activitySection-arrowDown-${noteId}`); - userEvent.click(expandButton); + await userEvent.click(expandButton); await waitFor(() => { expect(noteCollapse).toHaveClass('show'); @@ -188,9 +188,9 @@ describe('DetailViewComponents - ActivitySection', () => { const [ note ] = notes; const { id: noteId } = note; const expandButton = await screen.findByTestId(`activitySection-arrowDown-${noteId}`); - userEvent.click(expandButton); + await userEvent.click(expandButton); const collapseButton = await screen.findByTestId(`activitySection-arrowUp-${noteId}`); - userEvent.click(collapseButton); + await userEvent.click(collapseButton); const noteCollapse = await screen.findByTestId(`activitySection-collapse-${noteId}`); @@ -207,7 +207,7 @@ describe('DetailViewComponents - ActivitySection', () => { expect(noteCollapse).toHaveClass('collapse'); const expandButton = await screen.findByTestId('activitySection-arrowDown-noteToAdd1'); - userEvent.click(expandButton); + await userEvent.click(expandButton); await waitFor(() => { expect(noteCollapse).toHaveClass('show'); @@ -218,9 +218,9 @@ describe('DetailViewComponents - ActivitySection', () => { renderActivitySection(); const expandButton = await screen.findByTestId('activitySection-arrowDown-noteToAdd1'); - userEvent.click(expandButton); + await userEvent.click(expandButton); const collapseButton = await screen.findByTestId('activitySection-arrowUp-noteToAdd1'); - userEvent.click(collapseButton); + await userEvent.click(collapseButton); const noteCollapse = await screen.findByTestId('activitySection-collapse-noteToAdd1'); @@ -235,7 +235,7 @@ describe('DetailViewComponents - ActivitySection', () => { expect(onDeleteNote).toHaveBeenCalledTimes(0); const deleteButton = await screen.findByTestId('activitySection-deleteIcon-noteToAdd1'); - userEvent.click(deleteButton); + await userEvent.click(deleteButton); expect(onDeleteNote).toHaveBeenCalledTimes(1); }); @@ -250,13 +250,13 @@ describe('DetailViewComponents - ActivitySection', () => { expect(onChangeNote).toHaveBeenCalledTimes(0); const editNoteIcon = await screen.findByTestId(`activitySection-editIcon-${text}`); - userEvent.click(editNoteIcon); + await userEvent.click(editNoteIcon); const noteTextArea = await screen.findByTestId(`activitySection-noteTextArea-${text}`); - userEvent.type(noteTextArea, updatedText); + await userEvent.type(noteTextArea, updatedText); expect(onChangeNote).toHaveBeenCalledTimes(updatedText.length); const doneNoteButton = await screen.findByTestId(`activitySection-noteDone-${text}`); - userEvent.click(doneNoteButton); + await userEvent.click(doneNoteButton); expect(onDoneNote).toHaveBeenCalledWith(note); }); @@ -270,13 +270,13 @@ describe('DetailViewComponents - ActivitySection', () => { expect(onDoneNote).toHaveBeenCalledTimes(0); const editNoteIcon = await screen.findByTestId(`activitySection-editIcon-${note.id}`); - userEvent.click(editNoteIcon); + await userEvent.click(editNoteIcon); const noteTextArea = await screen.findByTestId(`activitySection-noteTextArea-${note.id}`); - userEvent.type(noteTextArea, updatedText); + await userEvent.type(noteTextArea, updatedText); const doneNoteButton = await screen.findByTestId(`activitySection-noteDone-${note.id}`); - userEvent.click(doneNoteButton); + await userEvent.click(doneNoteButton); expect(onDoneNote).toHaveBeenCalledTimes(1); expect(onDoneNote).toHaveBeenCalledWith(expect.objectContaining(note)); @@ -299,7 +299,7 @@ describe('DetailViewComponents - ActivitySection', () => { renderActivitySection(); const timeSortButton = await screen.findByTestId('time-sort-btn'); - userEvent.click(timeSortButton); + await userEvent.click(timeSortButton); const items = await screen.findAllByRole('listitem'); @@ -314,7 +314,7 @@ describe('DetailViewComponents - ActivitySection', () => { renderActivitySection(); const expandCollapseButton = await screen.findByTestId('detailView-activitySection-expandCollapseButton'); - userEvent.click(expandCollapseButton); + await userEvent.click(expandCollapseButton); const collapses = await screen.findAllByTestId((content) => content.startsWith('activitySection-collapse')); @@ -327,7 +327,7 @@ describe('DetailViewComponents - ActivitySection', () => { renderActivitySection(); const expandCollapseButton = await screen.findByTestId('detailView-activitySection-expandCollapseButton'); - userEvent.click(expandCollapseButton); + await userEvent.click(expandCollapseButton); const collapses = await screen.findAllByTestId((content) => content.startsWith('activitySection-collapse')); @@ -335,7 +335,7 @@ describe('DetailViewComponents - ActivitySection', () => { collapses.forEach((collapse) => expect(collapse).toHaveClass('show')); }); - userEvent.click(expandCollapseButton); + await userEvent.click(expandCollapseButton); await waitFor(() => { collapses.forEach((collapse) => expect(collapse).toHaveClass('collapse')); diff --git a/src/DetailViewComponents/HistorySection/index.test.js b/src/DetailViewComponents/HistorySection/index.test.js index 2333ac9de..85bc9870d 100644 --- a/src/DetailViewComponents/HistorySection/index.test.js +++ b/src/DetailViewComponents/HistorySection/index.test.js @@ -40,7 +40,7 @@ describe('DetailViewComponents - HistorySection', () => { render(, { wrapper: Wrapper }); const sortButton = await screen.findByRole('button'); - userEvent.click(sortButton); + await userEvent.click(sortButton); const items = await screen.findAllByRole('listitem'); expect((await within(items[0]).findByText('Kim Johanna'))).toBeDefined(); diff --git a/src/Drawer/index.js b/src/Drawer/index.js index 07b4757db..7ef06ed06 100644 --- a/src/Drawer/index.js +++ b/src/Drawer/index.js @@ -7,8 +7,6 @@ import GlobalMenuDrawer from '../GlobalMenuDrawer'; import * as styles from './styles.module.scss'; -const ESC_KEY_CODE = 27; - export const globalMenuDrawerId = 'global-menu'; const Drawer = () => { @@ -18,7 +16,7 @@ const Drawer = () => { useEffect(() => { const onKeydown = (event) => { - if (event.keyCode === ESC_KEY_CODE) { + if (event.key === 'Escape') { dispatch(hideDrawer()); } }; diff --git a/src/Drawer/index.test.js b/src/Drawer/index.test.js index ad4998895..f12f96c71 100644 --- a/src/Drawer/index.test.js +++ b/src/Drawer/index.test.js @@ -75,7 +75,7 @@ describe('Drawer', () => { expect(hideDrawer).toHaveBeenCalledTimes(0); const overlay = await screen.findByTestId('overlay'); - userEvent.click(overlay); + await userEvent.click(overlay); expect(hideDrawer).toHaveBeenCalledTimes(1); }); @@ -90,7 +90,7 @@ describe('Drawer', () => { expect(hideDrawer).toHaveBeenCalledTimes(0); - userEvent.keyboard('{Escape}'); + await userEvent.keyboard('{Escape}'); expect(hideDrawer).toHaveBeenCalledTimes(1); }); diff --git a/src/EarthRangerMap/index.js b/src/EarthRangerMap/index.js index c93a85e59..c61980f4d 100644 --- a/src/EarthRangerMap/index.js +++ b/src/EarthRangerMap/index.js @@ -1,4 +1,4 @@ -import React, { memo, useCallback, useContext, useEffect, useRef, useState } from 'react'; +import React, { memo, useCallback, useEffect, useRef, useState } from 'react'; import mapboxgl from 'mapbox-gl'; import { useSelector } from 'react-redux'; import { useTranslation } from 'react-i18next'; @@ -24,13 +24,6 @@ import '../Map/Map.scss'; mapboxgl.accessToken = REACT_APP_MAPBOX_TOKEN; -// eslint-disable-next-line react/display-name -export const withMap = (Component) => (props) => { - const map = useContext(MapContext); - - return ; -}; - const getStartingMapPositionValues = (mapPosition) => mapPosition?.center && mapPosition.zoom ? { bearing: mapPosition.bearing, center: mapPosition.center, pitch: mapPosition.pitch, zoom: mapPosition.zoom } : {}; diff --git a/src/ErrorMessages/index.test.js b/src/ErrorMessages/index.test.js index ad8996a7d..e8597dfa0 100644 --- a/src/ErrorMessages/index.test.js +++ b/src/ErrorMessages/index.test.js @@ -41,7 +41,7 @@ test('rendering without crashing', () => { }); describe('Error messages', () => { - beforeEach(async () => { + beforeEach(() => { render(); }); @@ -64,17 +64,17 @@ describe('Error messages', () => { expect(detailsButton).toBeDefined(); - userEvent.click(detailsButton); + await userEvent.click(detailsButton); expect(await screen.findByText('Hide details')).toBeDefined(); expect(await screen.queryByText('See details')).toBeNull(); }); - test('clicking on close icon should dismiss the alert', () => { + test('clicking on close icon should dismiss the alert', async () => { const errorAlert = screen.getByTestId('errors-alert'); const closeButton = within(errorAlert).getAllByRole('button'); - userEvent.click(closeButton[0]); + await userEvent.click(closeButton[0]); expect(clearErrors).toHaveBeenCalledTimes(1); }); @@ -83,7 +83,7 @@ describe('Error messages', () => { const detailsButton = await screen.getByText('See details', { selector: 'button' }); expect(detailsButton).toBeDefined(); - userEvent.click(detailsButton); + await userEvent.click(detailsButton); const expandedDetailsButton = await screen.getByText('Hide details', { selector: 'button' }); expect(expandedDetailsButton).toBeDefined(); diff --git a/src/EventFilter/index.test.js b/src/EventFilter/index.test.js index 4fbd58149..8011b9f71 100644 --- a/src/EventFilter/index.test.js +++ b/src/EventFilter/index.test.js @@ -82,7 +82,7 @@ describe('EventFilter', () => { renderEventFilter(mockStore(initialState)); const filterBtn = screen.getByTestId('filter-btn'); - filterBtn.click(); + await userEvent.click(filterBtn); const filterPopover = screen.getByTestId('filter-popover'); expect(filterPopover).toBeDefined(); @@ -92,7 +92,7 @@ describe('EventFilter', () => { renderEventFilter(mockStore(initialState)); const dateFilterBtn = screen.getByTestId('date-filter-btn'); - dateFilterBtn.click(); + await userEvent.click(dateFilterBtn); const dateFilterPopover = screen.getByTestId('filter-date-popover'); expect(dateFilterPopover).toBeDefined(); @@ -152,14 +152,12 @@ describe('EventFilter', () => { const resetWrapper = await screen.getByTestId('general-reset-wrapper'); const resetButton = within(resetWrapper).queryByText('Reset'); - userEvent.click(resetButton); + await userEvent.click(resetButton); expect(resetMock).toHaveBeenCalledTimes(1); }); test('clicking on reset button should erase the search text value', async () => { - jest.useFakeTimers(); - initialState.data.eventFilter.filter.text = 'text'; const mockedStore = mockStore(initialState); renderEventFilter(mockedStore); @@ -167,7 +165,7 @@ describe('EventFilter', () => { const resetWrapper = await screen.getByTestId('general-reset-wrapper'); const resetButton = await within(resetWrapper).queryByText('Reset'); - userEvent.click(resetButton); + await userEvent.click(resetButton); await waitFor(() => { const actions = mockedStore.getActions(); @@ -175,8 +173,6 @@ describe('EventFilter', () => { expect(actions[0].type).toBe(UPDATE_EVENT_FILTER); expect(actions[0].payload.filter.text).toBe(''); }); - - jest.useRealTimers(); }); }); }); diff --git a/src/FeatureLayer/index.js b/src/FeatureLayer/index.js index 8b54a0245..f03ec0843 100644 --- a/src/FeatureLayer/index.js +++ b/src/FeatureLayer/index.js @@ -1,6 +1,5 @@ -import React, { memo, useCallback, useEffect } from 'react'; +import { memo, useCallback, useContext, useEffect } from 'react'; -import { withMap } from '../EarthRangerMap'; import withMapViewConfig from '../WithMapViewConfig'; import { getFeatureSymbolGeoJsonAtPoint } from '../utils/features'; @@ -11,6 +10,7 @@ import MarkerImage from '../common/images/icons/mapbox-blue-marker-icon.png'; import RangerStationsImage from '../common/images/icons/ranger-stations.png'; import { useMapEventBinding } from '../hooks'; import useMapSources from '../hooks/useMapSources'; +import { MapContext } from '../App'; import useMapLayers from '../hooks/useMapLayers'; const { FEATURE_FILLS, FEATURE_LINES, FEATURE_SYMBOLS, SKY_LAYER } = LAYER_IDS; @@ -78,7 +78,9 @@ const symbolPaint = { ...DEFAULT_SYMBOL_PAINT, }; -const FeatureLayer = ({ symbols, lines, polygons, onFeatureSymbolClick, mapUserLayoutConfig, minZoom, map }) => { +const FeatureLayer = ({ symbols, lines, polygons, onFeatureSymbolClick, mapUserLayoutConfig, minZoom }) => { + const map = useContext(MapContext); + const layout = { ...symbolLayout, ...mapUserLayoutConfig, @@ -155,4 +157,4 @@ const FeatureLayer = ({ symbols, lines, polygons, onFeatureSymbolClick, mapUserL return null; }; -export default memo(withMap(withMapViewConfig(FeatureLayer))); +export default memo(withMapViewConfig(FeatureLayer)); diff --git a/src/GetUserLocationButton/index.js b/src/GetUserLocationButton/index.js index e064cd9a4..cc328e2ad 100644 --- a/src/GetUserLocationButton/index.js +++ b/src/GetUserLocationButton/index.js @@ -61,7 +61,7 @@ const GetUserLocationButton = ({ onClick = null, onGet, ref, renderContent = nul type="button" {...otherProps} > - {renderContent?.() || } + {renderContent?.() || } {isLoading && } diff --git a/src/GetUserLocationButton/index.test.js b/src/GetUserLocationButton/index.test.js index 688357537..e069cfe8d 100644 --- a/src/GetUserLocationButton/index.test.js +++ b/src/GetUserLocationButton/index.test.js @@ -3,7 +3,7 @@ import { Provider } from 'react-redux'; import { toast } from 'react-toastify'; import userEvent from '@testing-library/user-event'; -import { render, screen, within } from '../test-utils'; +import { act, render, screen, within } from '../test-utils'; import { mockStore } from '../__test-helpers/MockStore'; import { setCurrentUserLocation } from '../ducks/location'; @@ -44,13 +44,13 @@ describe('GetUserLocationButton', () => { ); - test('configures the button with other props', () => { + test('configures the button with other props', async () => { renderGetUserLocationButton({ className: 'className' }); expect(screen.getByLabelText('Get current position')).toHaveClass('className'); }); - test('returns the user position from the store if it is available', () => { + test('returns the user position from the store if it is available', async () => { store.view.userLocation = { coords: { latitude: 10, longitude: 10 } }; const onClick = jest.fn(); renderGetUserLocationButton({ onClick }); @@ -58,14 +58,14 @@ describe('GetUserLocationButton', () => { expect(onClick).not.toHaveBeenCalled(); expect(onGet).not.toHaveBeenCalled(); - userEvent.click(screen.getByLabelText('Get current position')); + await userEvent.click(screen.getByLabelText('Get current position')); expect(onClick).toHaveBeenCalledTimes(1); expect(onGet).toHaveBeenCalledTimes(1); expect(onGet).toHaveBeenCalledWith({ latitude: 10, longitude: 10 }); }); - test('requests the user position from the window.navigator.geolocation API and returns it', () => { + test('requests the user position from the window.navigator.geolocation API and returns it', async () => { const onClick = jest.fn(); window.navigator.geolocation = { getCurrentPosition: jest.fn((successCallback) => { @@ -77,14 +77,14 @@ describe('GetUserLocationButton', () => { expect(onClick).not.toHaveBeenCalled(); expect(onGet).not.toHaveBeenCalled(); - userEvent.click(screen.getByLabelText('Get current position')); + await userEvent.click(screen.getByLabelText('Get current position')); expect(onClick).toHaveBeenCalledTimes(1); expect(onGet).toHaveBeenCalledTimes(1); expect(onGet).toHaveBeenCalledWith({ latitude: 15, longitude: 15 }); }); - test('shows an error if window.navigator.geolocation API fails', () => { + test('shows an error if window.navigator.geolocation API fails', async () => { const onClick = jest.fn(); window.navigator.geolocation = { getCurrentPosition: jest.fn((_, errorCallback) => { @@ -96,7 +96,7 @@ describe('GetUserLocationButton', () => { expect(onClick).not.toHaveBeenCalled(); expect(toast.error).not.toHaveBeenCalled(); - userEvent.click(screen.getByLabelText('Get current position')); + await userEvent.click(screen.getByLabelText('Get current position')); expect(onGet).not.toHaveBeenCalled(); expect(onClick).toHaveBeenCalledTimes(1); @@ -104,7 +104,7 @@ describe('GetUserLocationButton', () => { expect(toast.error).toHaveBeenCalledWith('Could not read your current location: Error'); }); - test('shows a loading overlay while fetching the user location', () => { + test('shows a loading overlay while fetching the user location', async () => { jest.useFakeTimers(); window.navigator.geolocation = { @@ -114,18 +114,19 @@ describe('GetUserLocationButton', () => { }; renderGetUserLocationButton(); - userEvent.click(screen.getByLabelText('Get current position')); + const user = userEvent.setup({ delay: null }); + await user.click(screen.getByLabelText('Get current position')); expect(screen.getByText('Trying to read your location...')).toBeVisible(); - jest.runOnlyPendingTimers(); + act(() => jest.runOnlyPendingTimers()); expect(screen.queryByText('Trying to read your location...')).toBeNull(); jest.useRealTimers(); }); - test('renders the button content', () => { + test('renders the button content', async () => { renderGetUserLocationButton({ renderContent: () =>
    }); const button = screen.getByLabelText('Get current position'); @@ -133,9 +134,9 @@ describe('GetUserLocationButton', () => { expect(within(button).getByTestId('content')).toBeVisible(); }); - test('renders a default button content', () => { + test('renders a default button content', async () => { renderGetUserLocationButton(); - expect(screen.getByLabelText('Get current position')).toHaveTextContent('gps-location-icon.svg'); + expect(screen.getByTestId('gps-location-icon')).toBeVisible(); }); }); diff --git a/src/GlobalMenuDrawer/index.test.js b/src/GlobalMenuDrawer/index.test.js index 8a53ba9d9..1a1952577 100644 --- a/src/GlobalMenuDrawer/index.test.js +++ b/src/GlobalMenuDrawer/index.test.js @@ -85,7 +85,7 @@ describe('GlobalMenuDrawer', () => { expect(hideDrawer).toHaveBeenCalledTimes(0); const crossButton = (await screen.findAllByRole('button'))[0]; - userEvent.click(crossButton); + await userEvent.click(crossButton); expect(hideDrawer).toHaveBeenCalledTimes(1); }); @@ -126,7 +126,7 @@ describe('GlobalMenuDrawer', () => { expect(navigate).toHaveBeenCalledTimes(0); const reportsNavigationButton = await screen.findByText('Events'); - userEvent.click(reportsNavigationButton); + await userEvent.click(reportsNavigationButton); expect(navigate).toHaveBeenCalledTimes(1); expect(navigate).toHaveBeenCalledWith('/events'); @@ -156,7 +156,7 @@ describe('GlobalMenuDrawer', () => { expect(navigate).toHaveBeenCalledTimes(0); const patrolsNavigationButton = await screen.findByText('Patrols'); - userEvent.click(patrolsNavigationButton); + await userEvent.click(patrolsNavigationButton); expect(navigate).toHaveBeenCalledTimes(1); expect(navigate).toHaveBeenCalledWith('/patrols'); @@ -173,7 +173,7 @@ describe('GlobalMenuDrawer', () => { expect(navigate).toHaveBeenCalledTimes(0); const mapLayersNavigationButton = await screen.findByText('Map Layers'); - userEvent.click(mapLayersNavigationButton); + await userEvent.click(mapLayersNavigationButton); expect(navigate).toHaveBeenCalledTimes(1); expect(navigate).toHaveBeenCalledWith('/layers'); @@ -202,7 +202,7 @@ describe('GlobalMenuDrawer', () => { expect(global.open).toHaveBeenCalledTimes(0); const tableauButton = await screen.findByText('Tableau'); - userEvent.click(tableauButton); + await userEvent.click(tableauButton); expect(fetchTableauDashboard).toHaveBeenCalledTimes(1); @@ -233,7 +233,7 @@ describe('GlobalMenuDrawer', () => { expect(addModal).toHaveBeenCalledTimes(0); const alertsButton = await screen.findByText('Alerts'); - userEvent.click(alertsButton); + await userEvent.click(alertsButton); expect(addModal).toHaveBeenCalledTimes(1); expect(addModal.mock.calls[0][0].title).toBe('Alerts'); @@ -253,7 +253,7 @@ describe('GlobalMenuDrawer', () => { expect(global.open).toHaveBeenCalledTimes(0); const supportButton = await screen.findByText('Contact Support'); - userEvent.click(supportButton); + await userEvent.click(supportButton); expect(mockHelpButton.click).toHaveBeenCalled(); }); @@ -268,7 +268,7 @@ describe('GlobalMenuDrawer', () => { expect(global.open).toHaveBeenCalledTimes(0); const helpCenterButton = await screen.findByText('Help Center'); - userEvent.click(helpCenterButton); + await userEvent.click(helpCenterButton); expect(global.open).toHaveBeenCalledTimes(1); expect(global.open).toHaveBeenCalledWith('https://support.earthranger.com/', '_blank', 'noopener,noreferrer'); @@ -284,7 +284,7 @@ describe('GlobalMenuDrawer', () => { expect(global.open).toHaveBeenCalledTimes(0); const communityButton = await screen.findByText('Community'); - userEvent.click(communityButton); + await userEvent.click(communityButton); expect(global.open).toHaveBeenCalledTimes(1); expect(global.open).toHaveBeenCalledWith('https://Community.EarthRanger.com', '_blank', 'noopener,noreferrer'); @@ -300,7 +300,7 @@ describe('GlobalMenuDrawer', () => { expect(global.open).toHaveBeenCalledTimes(0); const usersGuideButton = await screen.findByText('User\'s Guide'); - userEvent.click(usersGuideButton); + await userEvent.click(usersGuideButton); expect(global.open).toHaveBeenCalledTimes(1); expect(global.open).toHaveBeenCalledWith('https://support.earthranger.com/en_US/earthranger-web', '_blank', 'noopener,noreferrer'); @@ -316,7 +316,7 @@ describe('GlobalMenuDrawer', () => { expect(addModal).toHaveBeenCalledTimes(0); const dailyReportButton = await screen.findByText('Daily Report'); - userEvent.click(dailyReportButton); + await userEvent.click(dailyReportButton); expect(addModal).toHaveBeenCalledTimes(1); expect(addModal.mock.calls[0][0].title).toBe('Daily Report'); @@ -325,7 +325,7 @@ describe('GlobalMenuDrawer', () => { describe('exporting field reports', () => { const getFieldEventsButton = () => screen.queryByText('Field Events'); - test('does not show the Field Reports button if a user doesn\'t have export event data permissions', () => { + test('does not show the Field Reports button if a user doesn\'t have export event data permissions', async () => { delete store.data.user.permissions[PERMISSION_KEYS.EVENTS]; render( @@ -339,7 +339,7 @@ describe('GlobalMenuDrawer', () => { expect(fieldEventsButton).toBeNull(); }); - test('opens the field reports modal when clicking the Field Reports button', () => { + test('opens the field reports modal when clicking the Field Reports button', async () => { render( @@ -349,7 +349,7 @@ describe('GlobalMenuDrawer', () => { expect(addModal).toHaveBeenCalledTimes(0); const fieldEventsButton = getFieldEventsButton(); - userEvent.click(fieldEventsButton); + await userEvent.click(fieldEventsButton); expect(addModal).toHaveBeenCalledTimes(1); expect(addModal.mock.calls[0][0].title).toBe('Field Events'); @@ -367,7 +367,7 @@ describe('GlobalMenuDrawer', () => { expect(addModal).toHaveBeenCalledTimes(0); const masterKMLButton = await screen.findByText('Subject KML'); - userEvent.click(masterKMLButton); + await userEvent.click(masterKMLButton); expect(addModal).toHaveBeenCalledTimes(1); expect(addModal.mock.calls[0][0].title).toBe('Subject KML'); @@ -377,7 +377,7 @@ describe('GlobalMenuDrawer', () => { describe('exporting subject information', () => { const getSubjectInfoButton = () => screen.queryByText('Subject Summary'); - test('does not show the subject information link if a user doesn\'t have export observation data permissions', () => { + test('does not show the subject information link if a user doesn\'t have export observation data permissions', async () => { delete store.data.user.permissions[PERMISSION_KEYS.OBSERVATIONS]; render( @@ -390,7 +390,7 @@ describe('GlobalMenuDrawer', () => { expect(subjectInfoButton).toBeNull(); }); - test('opens the subject information modal when clicking the Subject Information button', () => { + test('opens the subject information modal when clicking the Subject Information button', async () => { render( @@ -400,7 +400,7 @@ describe('GlobalMenuDrawer', () => { expect(addModal).toHaveBeenCalledTimes(0); const subjectInfoButton = getSubjectInfoButton(); - userEvent.click(subjectInfoButton); + await userEvent.click(subjectInfoButton); expect(addModal).toHaveBeenCalledTimes(1); expect(addModal.mock.calls[0][0].title).toBe('Subject Summary'); @@ -410,7 +410,7 @@ describe('GlobalMenuDrawer', () => { describe('exporting subject reports', () => { const getSubjectReportsButton = () => screen.queryByText('Observations'); - test('does not show the subject reports link if a user doesn\'t have export observation data permissions', () => { + test('does not show the subject reports link if a user doesn\'t have export observation data permissions', async () => { delete store.data.user.permissions[PERMISSION_KEYS.OBSERVATIONS]; render( @@ -423,7 +423,7 @@ describe('GlobalMenuDrawer', () => { expect(subjectReportsButton).toBeNull(); }); - test('opens the subject reports modal when clicking the Subject Reports button', () => { + test('opens the subject reports modal when clicking the Subject Reports button', async () => { render( @@ -433,7 +433,7 @@ describe('GlobalMenuDrawer', () => { expect(addModal).toHaveBeenCalledTimes(0); const subjectReportsButton = getSubjectReportsButton(); - userEvent.click(subjectReportsButton); + await userEvent.click(subjectReportsButton); expect(addModal).toHaveBeenCalledTimes(1); expect(addModal.mock.calls[0][0].title).toBe('Observations'); diff --git a/src/GpsFormatToggle/index.test.js b/src/GpsFormatToggle/index.test.js index c227b51f7..128881ae8 100644 --- a/src/GpsFormatToggle/index.test.js +++ b/src/GpsFormatToggle/index.test.js @@ -35,7 +35,7 @@ describe('GpsFormatToggle', () => { ); - test('checks the GPS format option that is currently selected', () => { + test('checks the GPS format option that is currently selected', async () => { renderGpsFormatToggle(); expect(screen.getByLabelText(GPS_FORMATS.DEG)).toBeChecked(); @@ -50,37 +50,37 @@ describe('GpsFormatToggle', () => { expect(screen.getByText(GPS_FORMATS.UTM)).not.toHaveClass('active'); }); - test('updates the GPS format when clicking an option', () => { + test('updates the GPS format when clicking an option', async () => { renderGpsFormatToggle(); expect(updateUserPreferences).toHaveBeenCalledTimes(0); - userEvent.click(screen.getByLabelText('DMS')); + await userEvent.click(screen.getByLabelText('DMS')); expect(updateUserPreferences).toHaveBeenCalledTimes(1); expect(updateUserPreferences).toHaveBeenCalledWith({ gpsFormat: GPS_FORMATS.DMS }); - userEvent.click(screen.getByLabelText('UTM')); + await userEvent.click(screen.getByLabelText('UTM')); expect(updateUserPreferences).toHaveBeenCalledTimes(2); expect(updateUserPreferences).toHaveBeenCalledWith({ gpsFormat: GPS_FORMATS.UTM }); }); - test('shows the GPS string and the copy button if there are valid lat and lng values', () => { + test('shows the GPS string and the copy button if there are valid lat and lng values', async () => { renderGpsFormatToggle(); expect(screen.getByText('11.666666°, 10.012657°')).toBeVisible(); expect(screen.getByLabelText('Copy GPS value to clipboard')).toBeVisible(); }); - test('does not show either the GPS string nor the copy button if there are not valid lat and lng values set', () => { + test('does not show either the GPS string nor the copy button if there are not valid lat and lng values set', async () => { renderGpsFormatToggle({ lat: null, lng: null }); expect(screen.queryByText('11.666666°, 10.012657°')).toBeNull(); expect(screen.queryByLabelText('Copy GPS value to clipboard')).toBeNull(); }); - test('does not show either the GPS string nor the copy button if the showGpsString is false', () => { + test('does not show either the GPS string nor the copy button if the showGpsString is false', async () => { renderGpsFormatToggle({ showGpsString: false }); expect(screen.queryByText('11.666666°, 10.012657°')).toBeNull(); diff --git a/src/GpsInput/index.test.js b/src/GpsInput/index.test.js index 9422d7986..fa793f08d 100644 --- a/src/GpsInput/index.test.js +++ b/src/GpsInput/index.test.js @@ -41,7 +41,7 @@ describe('GpsInput', () => { jest.restoreAllMocks(); }); - test('shows the value by default in the input formatted to the current GPS location', () => { + test('shows the value by default in the input formatted to the current GPS location', async () => { renderGpsInput({ value: { latitude: 10, @@ -52,7 +52,7 @@ describe('GpsInput', () => { expect(screen.getByLabelText('GPS location')).toHaveValue('10.000000°, 10.000000°'); }); - test('updates the displayed value to the new GPS format when the user changes the toggle', () => { + test('updates the displayed value to the new GPS format when the user changes the toggle', async () => { const { rerender } = renderGpsInput({ value: { latitude: 10, @@ -74,32 +74,32 @@ describe('GpsInput', () => { expect(gpsInput).toHaveValue('10° 00.000000′ N, 010° 00.000000′ E'); }); - test('focuses the text input if the user presses enter from the GPS format toggle', () => { + test('focuses the text input if the user presses enter from the GPS format toggle', async () => { renderGpsInput(); - userEvent.click(screen.getByLabelText(GPS_FORMATS.DMS)); + await userEvent.click(screen.getByLabelText(GPS_FORMATS.DMS)); const gpsInput = screen.getByLabelText('GPS location'); expect(gpsInput).not.toHaveFocus(); - userEvent.keyboard('{Enter}'); + await userEvent.keyboard('{Enter}'); expect(gpsInput).toHaveFocus(); }); - test('updates the input', () => { + test('updates the input', async () => { renderGpsInput(); const gpsInput = screen.getByLabelText('GPS location'); expect(gpsInput).toHaveValue(''); - userEvent.type(gpsInput, '123'); + await userEvent.type(gpsInput, '123'); expect(gpsInput).toHaveValue('123'); }); - test('notifies a change when the user clears the input', () => { + test('notifies a change when the user clears the input', async () => { renderGpsInput({ value: { latitude: 10, @@ -112,7 +112,7 @@ describe('GpsInput', () => { expect(gpsInput).toHaveValue('10.000000°, 10.000000°'); expect(onChange).not.toHaveBeenCalled(); - userEvent.clear(gpsInput); + await userEvent.clear(gpsInput); expect(gpsInput).toHaveValue(''); expect(gpsInput).not.toHaveAccessibleErrorMessage(); @@ -120,7 +120,7 @@ describe('GpsInput', () => { expect(onChange).toHaveBeenCalledWith(null); }); - test('does not notify a change and shows an error if the user types an invalid value', () => { + test('does not notify a change and shows an error if the user types an invalid value', async () => { renderGpsInput(); const gpsInput = screen.getByLabelText('GPS location'); @@ -128,7 +128,7 @@ describe('GpsInput', () => { expect(gpsInput).toHaveValue(''); expect(onChange).not.toHaveBeenCalled(); - userEvent.type(gpsInput, 'a'); + await userEvent.type(gpsInput, 'a'); expect(gpsInput).toHaveValue('a'); expect(gpsInput).toHaveAccessibleErrorMessage('Invalid location'); @@ -140,7 +140,7 @@ describe('GpsInput', () => { expect(errorMessage).toHaveClass('error'); }); - test('notifies a change when the user types a valid GPS value', () => { + test('notifies a change when the user types a valid GPS value', async () => { renderGpsInput(); const gpsInput = screen.getByLabelText('GPS location'); @@ -148,7 +148,7 @@ describe('GpsInput', () => { expect(gpsInput).toHaveValue(''); expect(onChange).not.toHaveBeenCalled(); - userEvent.type(gpsInput, '10, 10'); + await userEvent.type(gpsInput, '10, 10'); expect(gpsInput).toHaveValue('10, 10'); expect(gpsInput).not.toHaveAccessibleErrorMessage(); @@ -156,7 +156,7 @@ describe('GpsInput', () => { expect(onChange).toHaveBeenCalledWith({ latitude: 10, longitude: 10 }); }); - test('sets the value in the input on blur', () => { + test('sets the value in the input on blur', async () => { renderGpsInput({ value: { latitude: 10, @@ -168,8 +168,8 @@ describe('GpsInput', () => { expect(gpsInput).toHaveValue('10.000000°, 10.000000°'); - userEvent.clear(gpsInput); - userEvent.type(gpsInput, 'a'); + await userEvent.clear(gpsInput); + await userEvent.type(gpsInput, 'a'); expect(gpsInput).toHaveValue('a'); expect(gpsInput).toHaveAccessibleErrorMessage(); @@ -180,26 +180,26 @@ describe('GpsInput', () => { expect(gpsInput).not.toHaveAccessibleErrorMessage(); }); - test('sets a default placeholder to the input', () => { + test('sets a default placeholder to the input', async () => { store.view.userPreferences.gpsFormat = null; renderGpsInput(); expect(screen.getByLabelText('GPS location')).toHaveAttribute('placeholder', 'Location'); }); - test('sets a placeholder based on the GPS format', () => { + test('sets a placeholder based on the GPS format', async () => { renderGpsInput(); expect(screen.getByLabelText('GPS location')).toHaveAttribute('placeholder', 'Latitude, Longitude'); }); - test('renders a button', () => { + test('renders a button', async () => { renderGpsInput({ renderButton: () => }); expect(screen.getByTestId('button')).toBeVisible(); }); - test('shows an input description based on the GPS format', () => { + test('shows an input description based on the GPS format', async () => { renderGpsInput(); expect(screen.getByLabelText('GPS location')).toHaveAccessibleDescription('Example: -0.15293, 37.30906'); diff --git a/src/KebabMenu/index.test.js b/src/KebabMenu/index.test.js index ff6b93343..e5fd5827d 100644 --- a/src/KebabMenu/index.test.js +++ b/src/KebabMenu/index.test.js @@ -15,7 +15,7 @@ describe('', () => { expect( await screen.queryByText(optionText) ).not.toBeInTheDocument(); const kebab = await screen.getByRole('button'); - userEvent.click(kebab); + await userEvent.click(kebab); expect( await screen.findByText(optionText) ).toBeInTheDocument(); }); @@ -29,9 +29,9 @@ describe('', () => { ); const kebab = await screen.getByRole('button'); - userEvent.click(kebab); + await userEvent.click(kebab); const option = await screen.findByText(optionText); - userEvent.click(option); + await userEvent.click(option); expect( handleOnClick ).toHaveBeenCalled(); }); diff --git a/src/LabeledPatrolSymbolLayer/index.js b/src/LabeledPatrolSymbolLayer/index.js index 699f5a725..4baec1a05 100644 --- a/src/LabeledPatrolSymbolLayer/index.js +++ b/src/LabeledPatrolSymbolLayer/index.js @@ -1,23 +1,13 @@ import React, { memo } from 'react'; -import { withMap } from '../EarthRangerMap'; -import LabeledSymbolLayer from '../LabeledSymbolLayer'; - import withMapViewConfig from '../WithMapViewConfig'; -function LabeledPatrolSymbolLayer( - { id, ...rest } -) { - const symbolLayout = { - 'text-field': '{ticker}', - 'text-offset': [1.1, -1.1], - }; +import LabeledSymbolLayer from '../LabeledSymbolLayer'; - return ; -} +const LabeledPatrolSymbolLayer = ({ id, ...otherProps }) => ; -export default memo(withMapViewConfig(withMap(LabeledPatrolSymbolLayer))); +export default memo(withMapViewConfig(LabeledPatrolSymbolLayer)); diff --git a/src/LabeledSymbolLayer/index.js b/src/LabeledSymbolLayer/index.js index a91d2d7eb..cd1280cfb 100644 --- a/src/LabeledSymbolLayer/index.js +++ b/src/LabeledSymbolLayer/index.js @@ -1,18 +1,16 @@ -import { memo, useCallback, useEffect } from 'react'; -import { DEFAULT_SYMBOL_LAYOUT, DEFAULT_SYMBOL_PAINT } from '../constants'; - -import { withMap } from '../EarthRangerMap'; -import withMapViewConfig from '../WithMapViewConfig'; +import { memo, useCallback, useContext, useEffect } from 'react'; +import { DEFAULT_SYMBOL_LAYOUT, DEFAULT_SYMBOL_PAINT } from '../constants'; +import { MapContext } from '../App'; import { useMapEventBinding } from '../hooks'; import useMapLayers from '../hooks/useMapLayers'; +import withMapViewConfig from '../WithMapViewConfig'; const LabeledSymbolLayer = ({ before, filter, id, layout, - map, mapUserLayoutConfigByLayerId, onClick, onInit = null, @@ -23,6 +21,8 @@ const LabeledSymbolLayer = ({ textLayout, textPaint, }) => { + const map = useContext(MapContext); + const textLayerId = `${id}-labels`; const handleMouseEnter = (e) => { @@ -110,4 +110,4 @@ const LabeledSymbolLayer = ({ return null; }; -export default memo(withMapViewConfig(withMap(LabeledSymbolLayer))); +export default memo(withMapViewConfig(LabeledSymbolLayer)); diff --git a/src/LayerSelectorPopup/index.test.js b/src/LayerSelectorPopup/index.test.js index df5fe74d5..20f47b7f3 100644 --- a/src/LayerSelectorPopup/index.test.js +++ b/src/LayerSelectorPopup/index.test.js @@ -80,7 +80,7 @@ describe('LayerSelectorPopup', () => { expect(await screen.findAllByRole('listitem')).toHaveLength(6); const searchBar = await screen.findByRole('textbox'); - userEvent.type(searchBar, 'Jenae One Field'); + await userEvent.type(searchBar, 'Jenae One Field'); expect(await screen.findAllByRole('listitem')).toHaveLength(4); }); @@ -99,12 +99,12 @@ describe('LayerSelectorPopup', () => { ); const searchBar = await screen.findByRole('textbox'); - userEvent.type(searchBar, 'Jenae One Field'); + await userEvent.type(searchBar, 'Jenae One Field'); expect(await screen.findAllByRole('listitem')).toHaveLength(4); const clearButton = await screen.findByRole('button'); - userEvent.click(clearButton); + await userEvent.click(clearButton); expect(await screen.findAllByRole('listitem')).toHaveLength(6); }); @@ -126,7 +126,7 @@ describe('LayerSelectorPopup', () => { expect(onSelectSubject).toHaveBeenCalledTimes(0); const subjectLayer = (await screen.findAllByRole('listitem'))[0]; - userEvent.click(subjectLayer); + await userEvent.click(subjectLayer); expect(hidePopup).toHaveBeenCalledTimes(1); expect(onSelectSubject).toHaveBeenCalledTimes(1); @@ -150,7 +150,7 @@ describe('LayerSelectorPopup', () => { expect(onSelectEvent).toHaveBeenCalledTimes(0); const eventLayer = (await screen.findAllByRole('listitem'))[0]; - userEvent.click(eventLayer); + await userEvent.click(eventLayer); expect(hidePopup).toHaveBeenCalledTimes(1); expect(onSelectEvent).toHaveBeenCalledTimes(1); diff --git a/src/Link/index.test.js b/src/Link/index.test.js index 7c5169e55..1de8100e1 100644 --- a/src/Link/index.test.js +++ b/src/Link/index.test.js @@ -25,7 +25,7 @@ describe('Link', () => { ); const link = await screen.findByRole('link'); - userEvent.click(link); + await userEvent.click(link); expect((await screen.findByTestId('location-display'))).toHaveTextContent('/route'); }); @@ -44,7 +44,7 @@ describe('Link', () => { ); const link = await screen.findByRole('link'); - userEvent.click(link); + await userEvent.click(link); expect((await screen.findByTestId('location-display'))).toHaveTextContent('/'); }); @@ -65,7 +65,7 @@ describe('Link', () => { ); const link = await screen.findByRole('link'); - userEvent.click(link); + await userEvent.click(link); expect((await screen.findByTestId('location-display'))).toHaveTextContent('/'); diff --git a/src/LocationJumpButton/index.test.js b/src/LocationJumpButton/index.test.js index c2e11e672..223cdcac7 100644 --- a/src/LocationJumpButton/index.test.js +++ b/src/LocationJumpButton/index.test.js @@ -48,7 +48,7 @@ describe('AddReport', () => { expect(navigate).toHaveBeenCalledTimes(0); const jumpButton = await screen.findByTitle('Jump to this location'); - userEvent.click(jumpButton); + await userEvent.click(jumpButton); expect(navigate).toHaveBeenCalledTimes(1); expect(navigate).toHaveBeenCalledWith('/'); diff --git a/src/LocationPicker/MenuPopover/index.test.js b/src/LocationPicker/MenuPopover/index.test.js index caf2f47ac..70c7f6870 100644 --- a/src/LocationPicker/MenuPopover/index.test.js +++ b/src/LocationPicker/MenuPopover/index.test.js @@ -79,7 +79,7 @@ describe('LocationPicker - MenuPopover', () => { jest.restoreAllMocks(); }); - test('matches the width of the target while is less than 380 and more than 280', () => { + test('matches the width of the target while is less than 380 and more than 280', async () => { renderMenuPopover(); const menuPopover = screen.getByRole('presentation'); @@ -88,7 +88,7 @@ describe('LocationPicker - MenuPopover', () => { expect(menuPopover).toHaveStyle('width: 320px;'); }); - test('sets the popover width to 280 if the target is smaller', () => { + test('sets the popover width to 280 if the target is smaller', async () => { renderMenuPopover({ target: { current: { @@ -104,7 +104,7 @@ describe('LocationPicker - MenuPopover', () => { expect(menuPopover).toHaveStyle('width: 280px;'); }); - test('sets the popover width to 380 if the target is bigger', () => { + test('sets the popover width to 380 if the target is bigger', async () => { renderMenuPopover({ target: { current: { @@ -120,69 +120,69 @@ describe('LocationPicker - MenuPopover', () => { expect(menuPopover).toHaveStyle('width: 380px;'); }); - test('changes the location when the user types in the GPS input', () => { + test('changes the location when the user types in the GPS input', async () => { renderMenuPopover(); expect(onChange).not.toHaveBeenCalled(); - userEvent.type(screen.getByLabelText('GPS location'), '10,10'); + await userEvent.type(screen.getByLabelText('GPS location'), '10,10'); expect(onChange).toHaveBeenCalledTimes(2); expect(onChange).toHaveBeenCalledWith({ latitude: 10, longitude: 10 }); }); - test('closes the menu and focuses the set location button if the user presses enter while focusing the GPS input', () => { + test('closes the menu and focuses the set location button if the user presses enter while focusing the GPS input', async () => { renderMenuPopover(); expect(onClose).not.toHaveBeenCalled(); expect(setLocationButtonRefFocus).not.toHaveBeenCalled(); - userEvent.type(screen.getByLabelText('GPS location'), '10,10'); - userEvent.keyboard('{Enter}'); + await userEvent.type(screen.getByLabelText('GPS location'), '10,10'); + await userEvent.keyboard('{Enter}'); expect(onClose).toHaveBeenCalledTimes(1); expect(setLocationButtonRefFocus).toHaveBeenCalledTimes(1); }); - test('does neither close the menu nor focuse the set location button if the user presses enter while picking a location', () => { + test('does neither close the menu nor focuse the set location button if the user presses enter while picking a location', async () => { store.view.mapLocationSelection.isPickingLocation = true; renderMenuPopover(); - userEvent.type(screen.getByLabelText('GPS location'), '10,10'); - userEvent.keyboard('{Enter}'); + await userEvent.type(screen.getByLabelText('GPS location'), '10,10'); + await userEvent.keyboard('{Enter}'); expect(onClose).not.toHaveBeenCalled(); expect(setLocationButtonRefFocus).not.toHaveBeenCalled(); }); - test('closes the menu and focuses the set location button if the user presses escape', () => { + test('closes the menu and focuses the set location button if the user presses escape', async () => { renderMenuPopover(); expect(onClose).not.toHaveBeenCalled(); expect(setLocationButtonRefFocus).not.toHaveBeenCalled(); - userEvent.type(screen.getByLabelText('GPS location'), '10,10'); - userEvent.keyboard('{Escape}'); + await userEvent.type(screen.getByLabelText('GPS location'), '10,10'); + await userEvent.keyboard('{Escape}'); expect(onClose).toHaveBeenCalledTimes(1); expect(setLocationButtonRefFocus).toHaveBeenCalledTimes(1); }); - test('does neither close the menu nor focuse the set location button if the user presses escape while picking a location', () => { + test('does neither close the menu nor focuse the set location button if the user presses escape while picking a location', async () => { store.view.mapLocationSelection.isPickingLocation = true; renderMenuPopover(); - userEvent.type(screen.getByLabelText('GPS location'), '10,10'); - userEvent.keyboard('{Escape}'); + await userEvent.type(screen.getByLabelText('GPS location'), '10,10'); + await userEvent.keyboard('{Escape}'); expect(onClose).not.toHaveBeenCalled(); expect(setLocationButtonRefFocus).not.toHaveBeenCalled(); }); - test('changes the location when the user picks a location in the map', () => { + test('changes the location when the user picks a location in the map', async () => { renderMenuPopover(); - userEvent.click(screen.getByLabelText('Pick a location on the map')); + await userEvent.click(screen.getByLabelText('Pick a location on the map')); expect(onChange).not.toHaveBeenCalled(); expect(onClose).not.toHaveBeenCalled(); @@ -196,20 +196,20 @@ describe('LocationPicker - MenuPopover', () => { expect(setLocationButtonRefFocus).toHaveBeenCalledTimes(1); }); - test('does not show the get user location button if the user location is not active', () => { + test('does not show the get user location button if the user location is not active', async () => { renderMenuPopover(); expect(screen.queryByLabelText('Get current position')).toBeNull(); }); - test('shows the get user location button if the user location is active', () => { + test('shows the get user location button if the user location is active', async () => { store.view.showUserLocation = true; renderMenuPopover(); expect(screen.getByLabelText('Get current position')).toBeVisible(); }); - test('changes the location when the user clicks the button to get its location', () => { + test('changes the location when the user clicks the button to get its location', async () => { store.view.showUserLocation = true; store.view.userLocation = { coords: { latitude: 10, longitude: 10 } }; renderMenuPopover(); @@ -218,7 +218,7 @@ describe('LocationPicker - MenuPopover', () => { expect(onClose).not.toHaveBeenCalled(); expect(setLocationButtonRefFocus).not.toHaveBeenCalled(); - userEvent.click(screen.getByLabelText('Get current position')); + await userEvent.click(screen.getByLabelText('Get current position')); expect(onChange).toHaveBeenCalledTimes(1); expect(onChange).toHaveBeenCalledWith({ latitude: 10, longitude: 10 }); @@ -226,7 +226,7 @@ describe('LocationPicker - MenuPopover', () => { expect(setLocationButtonRefFocus).toHaveBeenCalledTimes(1); }); - test('closes the menu if the user clicks outside and triggers the blur callback if the click was outside of the picker', () => { + test('closes the menu if the user clicks outside and triggers the blur callback if the click was outside of the picker', async () => { render(<>
    @@ -260,13 +260,13 @@ describe('LocationPicker - MenuPopover', () => { expect(onClose).not.toHaveBeenCalled(); expect(onBlur).not.toHaveBeenCalled(); - userEvent.click(screen.getByTestId('outside')); + await userEvent.click(screen.getByTestId('outside')); expect(onClose).toHaveBeenCalledTimes(1); expect(onBlur).toHaveBeenCalledTimes(1); }); - test('closes the menu if the user clicks outside but does not trigger the blur callback if the click was inside the picker', () => { + test('closes the menu if the user clicks outside but does not trigger the blur callback if the click was inside the picker', async () => { render(<>
    @@ -299,13 +299,13 @@ describe('LocationPicker - MenuPopover', () => { expect(onClose).not.toHaveBeenCalled(); - userEvent.click(screen.getByTestId('outside')); + await userEvent.click(screen.getByTestId('outside')); expect(onClose).toHaveBeenCalledTimes(1); expect(onBlur).not.toHaveBeenCalled(); }); - test('does not close the menu if the user clicks outside while picking a location', () => { + test('does not close the menu if the user clicks outside while picking a location', async () => { store.view.mapLocationSelection.isPickingLocation = true; render(<> @@ -338,7 +338,7 @@ describe('LocationPicker - MenuPopover', () => { ); - userEvent.click(screen.getByTestId('outside')); + await userEvent.click(screen.getByTestId('outside')); expect(onClose).not.toHaveBeenCalled(); expect(onBlur).not.toHaveBeenCalled(); diff --git a/src/LocationPicker/index.test.js b/src/LocationPicker/index.test.js index fbf6af3a3..27c28809c 100644 --- a/src/LocationPicker/index.test.js +++ b/src/LocationPicker/index.test.js @@ -43,13 +43,13 @@ describe('LocationPicker', () => { ); - test('adds a custom class name', () => { + test('adds a custom class name', async () => { renderLocationPicker({ className: 'className' }); expect(screen.getByTestId('locationPicker')).toHaveClass('className'); }); - test('does not disable the location picker', () => { + test('does not disable the location picker', async () => { renderLocationPicker({ value: { latitude: 10, @@ -66,7 +66,7 @@ describe('LocationPicker', () => { expect(screen.getByLabelText('Jump to location')).not.toBeDisabled(); }); - test('disables the location picker', () => { + test('disables the location picker', async () => { renderLocationPicker({ disabled: true, value: { @@ -84,7 +84,7 @@ describe('LocationPicker', () => { expect(screen.getByLabelText('Jump to location')).toBeDisabled(); }); - test('sets the name to an input with the location picker value', () => { + test('sets the name to an input with the location picker value', async () => { renderLocationPicker({ name: 'location-picker-name', value: { @@ -99,13 +99,13 @@ describe('LocationPicker', () => { expect(locationPickerInput).toHaveValue('15,10'); }); - test('blurs the location picker', () => { + test('blurs the location picker', async () => { const onBlur = jest.fn(); renderLocationPicker({ onBlur }); const locationPicker = screen.getByTestId('locationPicker'); - userEvent.click(locationPicker); + await userEvent.click(locationPicker); expect(onBlur).not.toHaveBeenCalled(); @@ -114,31 +114,31 @@ describe('LocationPicker', () => { expect(onBlur).toHaveBeenCalledTimes(1); }); - test('focuses the location picker when focusing one of the inner elements', () => { + test('focuses the location picker when focusing one of the inner elements', async () => { const onFocus = jest.fn(); renderLocationPicker({ onFocus }); expect(onFocus).not.toHaveBeenCalled(); - userEvent.click(screen.getByLabelText('Open the location picker menu to set a value')); + await userEvent.click(screen.getByLabelText('Open the location picker menu to set a value')); expect(onFocus).toHaveBeenCalledTimes(1); }); - test('shows a default placeholder', () => { + test('shows a default placeholder', async () => { renderLocationPicker(); expect(screen.getByLabelText('Location')).toHaveAttribute('placeholder', 'Set Location'); }); - test('shows a custom placeholder', () => { + test('shows a custom placeholder', async () => { renderLocationPicker({ placeholder: 'placeholder' }); expect(screen.getByLabelText('Location')).toHaveAttribute('placeholder', 'placeholder'); }); - test('does not set the location picker as read only', () => { + test('does not set the location picker as read only', async () => { renderLocationPicker(); expect(screen.getByLabelText('Open the location picker menu to set a value')).not.toHaveClass('readOnly'); @@ -146,7 +146,7 @@ describe('LocationPicker', () => { expect(screen.getByLabelText('Location')).not.toHaveClass('readOnly'); }); - test('sets the location picker as read only', () => { + test('sets the location picker as read only', async () => { renderLocationPicker({ readOnly: true }); expect(screen.getByLabelText('Open the location picker menu to set a value')).toHaveClass('readOnly'); @@ -154,19 +154,19 @@ describe('LocationPicker', () => { expect(screen.getByLabelText('Location')).toHaveClass('readOnly'); }); - test('does not set the location picker as required', () => { + test('does not set the location picker as required', async () => { renderLocationPicker(); expect(screen.getByLabelText('Location')).not.toBeRequired(); }); - test('sets the location picker as required', () => { + test('sets the location picker as required', async () => { renderLocationPicker({ required: true }); expect(screen.getByLabelText('Location')).toBeRequired(); }); - test('forwards the focusing of the input to the set location button', () => { + test('forwards the focusing of the input to the set location button', async () => { renderLocationPicker(); fireEvent.focus(screen.getByLabelText('Location')); @@ -174,7 +174,7 @@ describe('LocationPicker', () => { expect(screen.getByLabelText('Open the location picker menu to set a value')).toHaveFocus(); }); - test('shows a display value in the input', () => { + test('shows a display value in the input', async () => { renderLocationPicker({ value: { latitude: 15, @@ -185,13 +185,13 @@ describe('LocationPicker', () => { expect(screen.getByLabelText('Location')).toHaveValue('15.000000°, 10.000000°'); }); - test('does not show a text copy button if there is no value yet', () => { + test('does not show a text copy button if there is no value yet', async () => { renderLocationPicker(); expect(screen.queryByLabelText('Copy location to clipboard')).toBeNull(); }); - test('shows a text copy button if there is a value', () => { + test('shows a text copy button if there is a value', async () => { renderLocationPicker({ value: { latitude: 15, @@ -202,13 +202,13 @@ describe('LocationPicker', () => { expect(screen.getByLabelText('Copy location to clipboard')).toBeVisible(); }); - test('disables the jump to location button if there is no value yet', () => { + test('disables the jump to location button if there is no value yet', async () => { renderLocationPicker(); expect(screen.getByLabelText('Jump to location')).toBeDisabled(); }); - test('enables the jump to location button if there is a value', () => { + test('enables the jump to location button if there is a value', async () => { renderLocationPicker({ value: { latitude: 15, @@ -219,7 +219,7 @@ describe('LocationPicker', () => { expect(screen.getByLabelText('Jump to location')).toBeEnabled(); }); - test('jumps to the location in the value when the user clicks the jump to location button', () => { + test('jumps to the location in the value when the user clicks the jump to location button', async () => { renderLocationPicker({ value: { latitude: 15, @@ -229,13 +229,13 @@ describe('LocationPicker', () => { expect(jumpToLocationMock).not.toHaveBeenCalled(); - userEvent.click(screen.getByLabelText('Jump to location')); + await userEvent.click(screen.getByLabelText('Jump to location')); expect(jumpToLocationMock).toHaveBeenCalledTimes(1); expect(jumpToLocationMock).toHaveBeenCalledWith([10, 15], undefined); }); - test('jumps to the location with a custom zoom', () => { + test('jumps to the location with a custom zoom', async () => { renderLocationPicker({ jumpToLocationButtonZoom: 20, value: { @@ -246,20 +246,20 @@ describe('LocationPicker', () => { expect(jumpToLocationMock).not.toHaveBeenCalled(); - userEvent.click(screen.getByLabelText('Jump to location')); + await userEvent.click(screen.getByLabelText('Jump to location')); expect(jumpToLocationMock).toHaveBeenCalledTimes(1); expect(jumpToLocationMock).toHaveBeenCalledWith([10, 15], 20); }); - test('opens the menu popover', () => { + test('opens the menu popover', async () => { renderLocationPicker(); const setLocationButton = screen.getByLabelText('Open the location picker menu to set a value'); expect(setLocationButton).toHaveAttribute('aria-expanded', 'false'); - userEvent.click(setLocationButton); + await userEvent.click(setLocationButton); expect(screen.getByRole('presentation')).toBeVisible(); expect(setLocationButton).toHaveAttribute('aria-expanded', 'true'); @@ -269,13 +269,13 @@ describe('LocationPicker', () => { renderLocationPicker(); const setLocationButton = screen.getByLabelText('Open the location picker menu to set a value'); - userEvent.click(setLocationButton); + await userEvent.click(setLocationButton); const menuPopover = screen.getByRole('presentation'); expect(menuPopover).toBeVisible(); expect(setLocationButton).toHaveAttribute('aria-expanded', 'true'); - userEvent.click(setLocationButton); + await userEvent.click(setLocationButton); expect(setLocationButton).toHaveAttribute('aria-expanded', 'false'); diff --git a/src/Login/index.test.js b/src/Login/index.test.js index eaf11ff88..b4d6f5d51 100644 --- a/src/Login/index.test.js +++ b/src/Login/index.test.js @@ -62,12 +62,12 @@ describe('Login', () => { const login = async (usernameText = username, passwordText = password) => { const usernameInput = await screen.findByLabelText('Username'); - userEvent.type(usernameInput, usernameText); + await userEvent.type(usernameInput, usernameText); const passwordInput = await screen.findByLabelText('Password'); - userEvent.type(passwordInput, passwordText); + await userEvent.type(passwordInput, passwordText); const formSubmitButton = await screen.findByRole('button'); - userEvent.click(formSubmitButton); + await userEvent.click(formSubmitButton); }; test('navigates to map after a successful login', async () => { diff --git a/src/Map/index.js b/src/Map/index.js index 6892cba83..43f18f963 100644 --- a/src/Map/index.js +++ b/src/Map/index.js @@ -1,4 +1,4 @@ -import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'; +import React, { useCallback, useContext, useEffect, useMemo, useRef, useState } from 'react'; import { useLocation } from 'react-router'; import { useDispatch, useSelector } from 'react-redux'; import uniq from 'lodash/uniq'; @@ -33,7 +33,9 @@ import { updateHeatmapSubjects, updateTrackState } from '../ducks/map-ui'; +import { MapContext } from '../App'; import { updatePatrolTrackState } from '../ducks/patrols'; +import { useMapEventBinding } from '../hooks'; import useNavigate from '../hooks/useNavigate'; import { @@ -42,7 +44,7 @@ import { } from '../constants'; import DelayedUnmount from '../DelayedUnmount'; -import EarthRangerMap, { withMap } from '../EarthRangerMap'; +import EarthRangerMap from '../EarthRangerMap'; import EventsLayer from '../EventsLayer'; import SubjectsLayer from '../SubjectsLayer'; import StaticSensorsLayer from '../StaticSensorsLayer'; @@ -78,7 +80,6 @@ import ReportGeometryDrawer from '../ReportGeometryDrawer'; import MapLocationSelectionOverview from '../MapLocationSelectionOverview'; import './Map.scss'; -import { useMapEventBinding } from '../hooks'; const mapInteractionTracker = trackEventFactory(MAP_INTERACTION_CATEGORY); @@ -101,17 +102,14 @@ const replaceLayoutTextFieldLanguage = (textField, language) => { return textField.map((textField) => replaceLayoutTextFieldLanguage(textField, language)); }; -const Map = ({ - children, - map, - onMapLoad, - socket, -}) => { +const Map = ({ children, onMapLoad, socket }) => { const dispatch = useDispatch(); const { i18n } = useTranslation(); const location = useLocation(); const navigate = useNavigate(); + const map = useContext(MapContext); + const analyzerFeatures = useSelector(analyzerFeaturesSelector); const maps = useSelector(state => state.data.maps); const heatmapSubjectIDs = useSelector(state => state.view.heatmapSubjectIDs); @@ -690,4 +688,4 @@ const Map = ({ }; -export default withMap(Map); +export default Map; diff --git a/src/MapLegend/index.test.js b/src/MapLegend/index.test.js index 8f72b6d42..776d9890d 100644 --- a/src/MapLegend/index.test.js +++ b/src/MapLegend/index.test.js @@ -21,41 +21,41 @@ describe('MapLegend', () => { jest.restoreAllMocks(); }); - test('renders the title from the render prop', () => { + test('renders the title from the render prop', async () => { renderMapLegend({ renderTitle: () =>
    Title
    }); expect(screen.getByTestId('title')).toBeVisible(); }); - test('closes the map legend when clicking the close button', () => { + test('closes the map legend when clicking the close button', async () => { renderMapLegend(); expect(onClose).not.toHaveBeenCalled(); - userEvent.click(screen.getAllByRole('button')[0]); + await userEvent.click(screen.getAllByRole('button')[0]); expect(onClose).toHaveBeenCalledTimes(1); }); - test('shows a settings button if the render settings prop is defined', () => { + test('shows a settings button if the render settings prop is defined', async () => { renderMapLegend(); expect(screen.getAllByRole('button')[1]).toBeVisible(); }); - test('does not show a settings button if the render settings prop is not defined', () => { + test('does not show a settings button if the render settings prop is not defined', async () => { renderMapLegend({ renderSettings: null }); expect(screen.getAllByRole('button')[1]).toBeUndefined(); }); - test('renders the settings from the render prop in a popover', () => { + test('renders the settings from the render prop in a popover', async () => { renderMapLegend({ renderSettings: () =>
    Settings
    }); expect(screen.queryByRole('tooltip')).toBeNull(); expect(screen.queryByTestId('settings')).toBeNull(); - userEvent.click(screen.getAllByRole('button')[1]); + await userEvent.click(screen.getAllByRole('button')[1]); expect(screen.getByRole('tooltip')).toBeVisible(); expect(screen.getByTestId('settings')).toBeVisible(); diff --git a/src/MapLocationSelectionOverview/index.js b/src/MapLocationSelectionOverview/index.js index b095e5022..7b829fe87 100644 --- a/src/MapLocationSelectionOverview/index.js +++ b/src/MapLocationSelectionOverview/index.js @@ -87,9 +87,11 @@ const MapLocationSelectionOverview = ({ : t(`chooseLocationHeader.${patrol ? 'patrol' : 'report'}`)}
    - {onShowInformation && } + {onShowInformation && } - {isOpen ? : } + {isOpen + ? + : }
    diff --git a/src/MapLocationSelectionOverview/index.test.js b/src/MapLocationSelectionOverview/index.test.js index d5c80accb..fbb1ae5db 100644 --- a/src/MapLocationSelectionOverview/index.test.js +++ b/src/MapLocationSelectionOverview/index.test.js @@ -77,8 +77,8 @@ describe('MapLocationSelectionOverview', () => { test('opens the report information modal when clicking the information icon', async () => { expect(onShowInformation).toHaveBeenCalledTimes(0); - const informationIcon = await screen.findByText('information.svg'); - userEvent.click(informationIcon); + const informationIcon = await screen.findByTestId('information-icon'); + await userEvent.click(informationIcon); expect(onShowInformation).toHaveBeenCalledTimes(1); }); @@ -88,13 +88,13 @@ describe('MapLocationSelectionOverview', () => { expect(collapse).toHaveClass('show'); - const arrowUpIcon = await screen.findByText('arrow-up-simple.svg'); - userEvent.click(arrowUpIcon); + const arrowUpIcon = await screen.findByTestId('arrow-up-simple-icon'); + await userEvent.click(arrowUpIcon); expect(collapse).not.toHaveClass('show'); - const arrowDownIcon = await screen.findByText('arrow-down-simple.svg'); - userEvent.click(arrowDownIcon); + const arrowDownIcon = await screen.findByTestId('arrow-down-simple-icon'); + await userEvent.click(arrowDownIcon); await waitFor(() => { expect(collapse).toHaveClass('show'); @@ -158,7 +158,7 @@ describe('MapLocationSelectionOverview', () => { expect(onClickUndo).toHaveBeenCalledTimes(0); const undoButton = await screen.findByText('Undo'); - userEvent.click(undoButton); + await userEvent.click(undoButton); expect(onClickUndo).toHaveBeenCalledTimes(1); }); @@ -184,7 +184,7 @@ describe('MapLocationSelectionOverview', () => { expect((await screen.queryByRole('tooltip'))).toBeNull(); const undoButton = await screen.findByText('Undo'); - userEvent.hover(undoButton); + await userEvent.hover(undoButton); expect((await screen.findByRole('tooltip'))).toHaveTextContent('Reverse your last action'); }); @@ -193,7 +193,7 @@ describe('MapLocationSelectionOverview', () => { expect(onClickDiscard).toHaveBeenCalledTimes(0); const discardButton = await screen.findByText('Discard'); - userEvent.click(discardButton); + await userEvent.click(discardButton); expect(onClickDiscard).toHaveBeenCalledTimes(1); }); @@ -219,7 +219,7 @@ describe('MapLocationSelectionOverview', () => { expect((await screen.queryByRole('tooltip'))).toBeNull(); const discardButton = await screen.findByText('Discard'); - userEvent.hover(discardButton); + await userEvent.hover(discardButton); expect((await screen.findByRole('tooltip'))).toHaveTextContent('Remove all points'); }); diff --git a/src/MapMarkerDropper/index.js b/src/MapMarkerDropper/index.js index 500e1d003..2055cfd28 100644 --- a/src/MapMarkerDropper/index.js +++ b/src/MapMarkerDropper/index.js @@ -1,10 +1,10 @@ -import React, { Fragment, memo, useState, useEffect, useRef } from 'react'; +import React, { memo, useContext, useState, useEffect, useRef } from 'react'; import throttle from 'lodash/throttle'; import { addMapImage } from '../utils/map'; import { MAP_INTERACTION_CATEGORY, trackEventFactory } from '../utils/analytics'; +import { MapContext } from '../App'; import { validateLocation } from '../utils/location'; -import { withMap } from '../EarthRangerMap'; import MouseMarkerLayer from '../MouseMarkerLayer'; import MouseMarkerPopup from '../MouseMarkerPopup'; @@ -16,7 +16,9 @@ import * as styles from './styles.module.scss'; const mapInteractionTracker = trackEventFactory(MAP_INTERACTION_CATEGORY); -const MapMarkerDropper = ({ map, onMarkerDropped = null, showMarkerPopup = true, ...rest }) => { +const MapMarkerDropper = ({ onMarkerDropped = null, showMarkerPopup = true, ...rest }) => { + const map = useContext(MapContext); + const [moving, setMovingState] = useState(false); const [location, setMarkerLocation] = useState({}); const [shouldCleanUpOnNextMapClick, setCleanupState] = useState(false); @@ -100,9 +102,7 @@ const MapMarkerDropper = ({ map, onMarkerDropped = null, showMarkerPopup = true, }, [moving]); // eslint-disable-line - - - return + return <> {showMarkerPopup && moving && } } - ; + ; }; -export default memo(withMap(MapMarkerDropper)); +export default memo(MapMarkerDropper); diff --git a/src/MapRulerControl/index.js b/src/MapRulerControl/index.js index 011ff023f..9d70cc10c 100644 --- a/src/MapRulerControl/index.js +++ b/src/MapRulerControl/index.js @@ -1,29 +1,29 @@ -import React, { memo, useState, useEffect, useCallback } from 'react'; -import { connect } from 'react-redux'; +import React, { memo, useContext, useState, useEffect, useCallback } from 'react'; import Button from 'react-bootstrap/Button'; +import { connect } from 'react-redux'; import isEqual from 'react-fast-compare'; import { useTranslation } from 'react-i18next'; -import { withMap } from '../EarthRangerMap'; import { ReactComponent as RulerIcon } from '../common/images/icons/ruler-icon.svg'; -import { trackEventFactory, MAP_INTERACTION_CATEGORY } from '../utils/analytics'; +import { LAYER_IDS } from '../MapDrawingTools/MapLayers'; +import { MAP_INTERACTION_CATEGORY, trackEventFactory } from '../utils/analytics'; +import { MapContext } from '../App'; import { setIsPickingLocation } from '../ducks/map-ui'; - -import PointPopup from './PointPopup'; - import { useMapEventBinding } from '../hooks'; import MapDrawingTools, { DRAWING_MODES } from '../MapDrawingTools'; -import { LAYER_IDS } from '../MapDrawingTools/MapLayers'; +import PointPopup from './PointPopup'; import * as styles from './styles.module.scss'; const mapInteractionTracker = trackEventFactory(MAP_INTERACTION_CATEGORY); -const MapRulerControl = (props) => { - const { map, setIsPickingLocation } = props; +const MapRulerControl = ({ setIsPickingLocation }) => { const { t } = useTranslation('map-controls', { keyPrefix: 'mapRuler' }); + + const map = useContext(MapContext); + const [active, setActiveState] = useState(false); const [drawing, setDrawingState] = useState(false); const [points, setPoints] = useState([]); @@ -199,6 +199,4 @@ const MapRulerControl = (props) => { ; }; -export default connect(null, { setIsPickingLocation })(memo(withMap(MapRulerControl))); - - +export default connect(null, { setIsPickingLocation })(memo(MapRulerControl)); diff --git a/src/MessageBadgeLayer/index.js b/src/MessageBadgeLayer/index.js index 219629491..31bc31a72 100644 --- a/src/MessageBadgeLayer/index.js +++ b/src/MessageBadgeLayer/index.js @@ -1,21 +1,19 @@ -import React, { useEffect, useContext, useReducer, useRef, memo } from 'react'; -import { connect } from 'react-redux'; +import { useEffect, useContext, useReducer, useRef, memo } from 'react'; import { bboxPolygon, booleanContains, featureCollection } from '@turf/turf'; +import { connect } from 'react-redux'; -import { PERMISSION_KEYS, PERMISSIONS } from '../constants'; +import MessageBadgeIcon from '../common/images/icons/map-message-badge-icon.png'; -import { usePermissions } from '../hooks'; import { addMapImage } from '../utils/map'; +import { extractSubjectFromMessage } from '../utils/messaging'; import { getBboxParamsFromMap } from '../utils/query'; -import { SocketContext } from '../withSocketConnection'; - -import { withMap } from '../EarthRangerMap'; import { getMapSubjectFeatureCollectionWithVirtualPositioning } from '../selectors/subjects'; -import { extractSubjectFromMessage } from '../utils/messaging'; +import { MapContext } from '../App'; +import { PERMISSION_KEYS, PERMISSIONS } from '../constants'; +import { SocketContext } from '../withSocketConnection'; +import { usePermissions } from '../hooks'; import { messageListReducer, removeMessageById, fetchMessagesSuccess, updateMessageFromRealtime, INITIAL_MESSAGE_LIST_STATE, fetchAllMessages } from '../ducks/messaging'; -import MessageBadgeIcon from '../common/images/icons/map-message-badge-icon.png'; - const calcMapMessages = (messages = [], subjectFeatureCollection) => { if (!messages.length || !subjectFeatureCollection?.features?.length) return featureCollection([]); @@ -65,15 +63,13 @@ const messageBadgePaint = { 'text-color': 'white', }; -const MessageBadgeLayer = (props) => { - /* "messages" prop needs to be replaced by a FETCH that retrieves only unread messages and has a huge page size to guarantee full retrieval */ - const { map, onBadgeClick, subjectFeatureCollection } = props; +const MessageBadgeLayer = ({ onBadgeClick, subjectFeatureCollection }) => { + const map = useContext(MapContext); + const socket = useContext(SocketContext); const [state, dispatch] = useReducer(messageListReducer, INITIAL_MESSAGE_LIST_STATE); const canViewMessages = usePermissions(PERMISSION_KEYS.MESSAGING, PERMISSIONS.READ); - const socket = useContext(SocketContext); - const lastRequestedSubjectIdList = useRef(null); useEffect(() => { @@ -195,4 +191,4 @@ const mapStateToProps = (state) => ({ subjectFeatureCollection: getMapSubjectFeatureCollectionWithVirtualPositioning(state), }); -export default connect(mapStateToProps, null)(memo(withMap(MessageBadgeLayer))); +export default connect(mapStateToProps, null)(memo(MessageBadgeLayer)); diff --git a/src/ModalRenderer/index.test.js b/src/ModalRenderer/index.test.js index 061983fd1..881a5413d 100644 --- a/src/ModalRenderer/index.test.js +++ b/src/ModalRenderer/index.test.js @@ -64,7 +64,7 @@ describe('ModalRenderer', () => { test('removes the modal when pressing escape', async () => { expect(removeModal).toHaveBeenCalledTimes(0); - userEvent.keyboard('{Escape}'); + await userEvent.keyboard('{Escape}'); expect(removeModal).toHaveBeenCalledTimes(1); }); @@ -79,7 +79,7 @@ describe('ModalRenderer', () => { ); - userEvent.keyboard('{Escape}'); + await userEvent.keyboard('{Escape}'); expect(removeModal).toHaveBeenCalledTimes(0); }); diff --git a/src/Nav/index.test.js b/src/Nav/index.test.js index bec83f433..ae508cb34 100644 --- a/src/Nav/index.test.js +++ b/src/Nav/index.test.js @@ -2,10 +2,11 @@ import React from 'react'; import { http, HttpResponse } from 'msw'; import { Provider } from 'react-redux'; import { setupServer } from 'msw/node'; +import userEvent from '@testing-library/user-event'; import { createMapMock } from '../__test-helpers/mocks'; import { clearUserProfile, USER_API_URL, CURRENT_USER_API_URL, USER_PROFILES_API_URL } from '../ducks/user'; -import { cleanup, fireEvent, render, screen, waitFor } from '../test-utils'; +import { cleanup, render, screen, waitFor } from '../test-utils'; import { NEWS_API_URL } from '../ducks/news'; import { userWithPin, userWithoutPin, userWithoutEula, userList } from '../__test-helpers/fixtures/users'; @@ -144,11 +145,12 @@ describe('the Nav component', () => { await screen.findByText('Enter Your PIN'); pinInputs = await screen.findAllByRole('input'); - const splitPin = anotherPinProfile.pin.split(''); + const user = userEvent.setup({ delay: null }); - splitPin.forEach((char, index) => { - fireEvent.keyDown(pinInputs[index], { key: char, code: `key${char}` }); - }); + await user.type(pinInputs[0], anotherPinProfile.pin[0]); + await user.type(pinInputs[1], anotherPinProfile.pin[1]); + await user.type(pinInputs[2], anotherPinProfile.pin[2]); + await user.type(pinInputs[3], anotherPinProfile.pin[3]); state = store.getState(); diff --git a/src/NavigationContextProvider/index.test.js b/src/NavigationContextProvider/index.test.js index 575ec86ff..d70c134d9 100644 --- a/src/NavigationContextProvider/index.test.js +++ b/src/NavigationContextProvider/index.test.js @@ -1,6 +1,6 @@ import React, { useContext } from 'react'; -import { renderHook } from '@testing-library/react-hooks'; +import { act, renderHook } from '../test-utils'; import NavigationContextProvider, { BLOCKER_STATES, NavigationContext } from './'; describe('NavigationContextProvider', () => { @@ -12,7 +12,9 @@ describe('NavigationContextProvider', () => { expect(result.current.navigationData).toEqual({}); - result.current.setNavigationData('Navigation data!'); + act(() => { + result.current.setNavigationData('Navigation data!'); + }); expect(result.current.navigationData).toBe('Navigation data!'); }); @@ -23,7 +25,9 @@ describe('NavigationContextProvider', () => { expect(result.current.isNavigationBlocked).toBeFalsy(); - result.current.blockNavigation(blockRequestId); + act(() => { + result.current.blockNavigation(blockRequestId); + }); expect(result.current.isNavigationBlocked).toBeTruthy(); }); @@ -34,11 +38,15 @@ describe('NavigationContextProvider', () => { expect(result.current.isNavigationBlocked).toBeFalsy(); - result.current.blockNavigation(blockRequestId); + act(() => { + result.current.blockNavigation(blockRequestId); + }); expect(result.current.isNavigationBlocked).toBeTruthy(); - result.current.unblockNavigation(blockRequestId); + act(() => { + result.current.unblockNavigation(blockRequestId); + }); expect(result.current.isNavigationBlocked).toBeFalsy(); }); @@ -49,16 +57,22 @@ describe('NavigationContextProvider', () => { expect(result.current.isNavigationBlocked).toBeFalsy(); - result.current.blockNavigation(blockRequestId); + act(() => { + result.current.blockNavigation(blockRequestId); + }); expect(result.current.isNavigationBlocked).toBeTruthy(); expect(result.current.blocker.state).toBe(BLOCKER_STATES.UNBLOCKED); - result.current.onNavigationAttemptBlocked(); + act(() => { + result.current.onNavigationAttemptBlocked(); + }); expect(result.current.blocker.state).toBe(BLOCKER_STATES.BLOCKED); - result.current.blocker.proceed(); + act(() => { + result.current.blocker.proceed(); + }); expect(result.current.blocker.state).toBe(BLOCKER_STATES.PROCEEDING); }); @@ -69,16 +83,22 @@ describe('NavigationContextProvider', () => { expect(result.current.isNavigationBlocked).toBeFalsy(); - result.current.blockNavigation(blockRequestId); + act(() => { + result.current.blockNavigation(blockRequestId); + }); expect(result.current.isNavigationBlocked).toBeTruthy(); expect(result.current.blocker.state).toBe(BLOCKER_STATES.UNBLOCKED); - result.current.onNavigationAttemptBlocked(); + act(() => { + result.current.onNavigationAttemptBlocked(); + }); expect(result.current.blocker.state).toBe(BLOCKER_STATES.BLOCKED); - result.current.blocker.reset(); + act(() => { + result.current.blocker.reset(); + }); expect(result.current.blocker.state).toBe(BLOCKER_STATES.UNBLOCKED); }); @@ -91,16 +111,22 @@ describe('NavigationContextProvider', () => { expect(result.current.isNavigationBlocked).toBeFalsy(); - result.current.blockNavigation(blockRequestId); - result.current.blockNavigation(anotherBlockRequestId); + act(() => { + result.current.blockNavigation(blockRequestId); + result.current.blockNavigation(anotherBlockRequestId); + }); expect(result.current.isNavigationBlocked).toBeTruthy(); - result.current.unblockNavigation(anotherBlockRequestId); + act(() => { + result.current.unblockNavigation(anotherBlockRequestId); + }); expect(result.current.isNavigationBlocked).toBeTruthy(); - result.current.unblockNavigation(blockRequestId); + act(() => { + result.current.unblockNavigation(blockRequestId); + }); expect(result.current.isNavigationBlocked).toBeFalsy(); }); diff --git a/src/NotificationMenu/index.test.js b/src/NotificationMenu/index.test.js index c2cf1b99f..2475eaa97 100644 --- a/src/NotificationMenu/index.test.js +++ b/src/NotificationMenu/index.test.js @@ -51,7 +51,7 @@ describe('listing news items', () => { ); const toggle = await screen.findByTestId('notification-toggle'); - userEvent.click(toggle); + await userEvent.click(toggle); }); afterEach(() => { store = mockStore({ view: { } }); @@ -69,7 +69,7 @@ describe('listing news items', () => { const items = await waitFor(() => screen.getAllByRole('listitem')); const readMoreBtn = items[0].querySelector('button'); - userEvent.click(readMoreBtn); + await userEvent.click(readMoreBtn); expect(global.open).toHaveBeenCalledWith(mockNewsData[0].link, '_blank', 'noopener,noreferrer'); }); @@ -105,7 +105,7 @@ describe('listing news items', () => { ); const toggle = await screen.findByTestId('notification-toggle'); - userEvent.click(toggle); + await userEvent.click(toggle); await waitFor(() => { expect(screen.getAllByRole('listitem')).toHaveLength(4); @@ -126,35 +126,23 @@ describe('listing news items', () => { }); - test('clicking confirm', () => { + test('clicking confirm', async () => { const [, confirmBtn] = userNotificationListItem.querySelectorAll('button'); expect(storeWithUserNotification.view.userNotifications[0].onConfirm).not.toHaveBeenCalled(); - userEvent.click(confirmBtn); + await userEvent.click(confirmBtn); expect(storeWithUserNotification.view.userNotifications[0].onConfirm).toHaveBeenCalled(); }); - test('clicking dismiss', () => { + test('clicking dismiss', async () => { const dismissBtn = userNotificationListItem.querySelector('button'); expect(storeWithUserNotification.view.userNotifications[0].onDismiss).not.toHaveBeenCalled(); - userEvent.click(dismissBtn); + await userEvent.click(dismissBtn); expect(storeWithUserNotification.view.userNotifications[0].onDismiss).toHaveBeenCalled(); }); }); - - - test('marks unread news items as "read" when the menu is closed after being viewed', async () => { - const unreadBadge = await screen.findByTestId('unread-count'); - expect(unreadBadge.textContent).toEqual(`${mockNewsData.filter(n => !n.read).length}`); - - /* menu is open from the `beforeEach setup`, click again to close */ - const toggle = await screen.findByTestId('notification-toggle'); - userEvent.click(toggle); - - await waitForElementToBeRemoved(unreadBadge); - }); }); describe('handling failed news requests', () => { @@ -180,7 +168,7 @@ describe('handling failed news requests', () => { ); const toggle = await screen.findByTestId('notification-toggle'); - userEvent.click(toggle); + await userEvent.click(toggle); }); test('showing an error message', async () => { @@ -189,7 +177,7 @@ describe('handling failed news requests', () => { test('presenting a retry button which attempts to re-fetch news', async () => { const newsFetchRetryBtn = await screen.findByTestId('news-fetch-retry-btn'); - userEvent.click(newsFetchRetryBtn); + await userEvent.click(newsFetchRetryBtn); const items = await waitFor(() => screen.getAllByRole('listitem')); expect(items[0]).toHaveTextContent(mockNewsData[0].description); diff --git a/src/PatrolDetailView/Header/index.test.js b/src/PatrolDetailView/Header/index.test.js index 59194796c..fb9f76d77 100644 --- a/src/PatrolDetailView/Header/index.test.js +++ b/src/PatrolDetailView/Header/index.test.js @@ -104,8 +104,8 @@ describe('Header', () => { renderHeader({ patrol: scheduledPatrol }); const titleTextBox = await screen.findByTestId('patrolDetailView-header-title'); - userEvent.type(titleTextBox, '{del}{del}{del}{del}{del}{del}2'); - userEvent.tab(); + await userEvent.type(titleTextBox, '{del}{del}{del}{del}{del}{del}2'); + await userEvent.tab(); await waitFor(() => { expect(onChangeTitle).toHaveBeenCalledTimes(1); @@ -117,8 +117,8 @@ describe('Header', () => { renderHeader({ patrol: scheduledPatrol }); const titleTextBox = await screen.findByTestId('patrolDetailView-header-title'); - userEvent.type(titleTextBox, '{del}{del}{del}{del}{del}{del}'); - userEvent.tab(); + await userEvent.type(titleTextBox, '{del}{del}{del}{del}{del}{del}'); + await userEvent.tab(); expect(onChangeTitle).toHaveBeenCalledTimes(1); expect(onChangeTitle).toHaveBeenCalledWith('Future'); @@ -131,7 +131,7 @@ describe('Header', () => { expect(setRedirectTo).toHaveBeenCalledTimes(0); const buttons = await screen.findAllByRole('button'); - userEvent.click(buttons[0]); + await userEvent.click(buttons[0]); expect(updatePatrolMock).toHaveBeenCalledTimes(1); expect(updatePatrolMock.mock.calls[0][0].state).toBe('open'); @@ -146,7 +146,7 @@ describe('Header', () => { expect(setRedirectTo).toHaveBeenCalledTimes(0); const restorePatrolButton = await screen.findByText('Restore'); - userEvent.click(restorePatrolButton); + await userEvent.click(restorePatrolButton); expect(updatePatrolMock).toHaveBeenCalledTimes(1); expect(updatePatrolMock.mock.calls[0][0].state).toBe('open'); diff --git a/src/PatrolDetailView/InvalidDatesModal/index.test.js b/src/PatrolDetailView/InvalidDatesModal/index.test.js index af90c5ad0..ac3951a9a 100644 --- a/src/PatrolDetailView/InvalidDatesModal/index.test.js +++ b/src/PatrolDetailView/InvalidDatesModal/index.test.js @@ -19,7 +19,7 @@ describe('InvalidDatesModal', () => { expect(onHide).toHaveBeenCalledTimes(0); const okButton = await screen.findByText('OK'); - userEvent.click(okButton); + await userEvent.click(okButton); expect(onHide).toHaveBeenCalledTimes(1); }); diff --git a/src/PatrolDetailView/PlanSection/index.test.js b/src/PatrolDetailView/PlanSection/index.test.js index 036143544..3443bb7c2 100644 --- a/src/PatrolDetailView/PlanSection/index.test.js +++ b/src/PatrolDetailView/PlanSection/index.test.js @@ -124,12 +124,12 @@ describe('PatrolDetailView - PlanSection', () => { renderPlanSectionWithWrapper(); const selectReportedBy = await screen.getByText('Select Device...'); - userEvent.click(selectReportedBy); + await userEvent.click(selectReportedBy); expect(onPatrolReportedByChange).toHaveBeenCalledTimes(0); const reporterOption = await screen.getByAltText('Radio icon for Alex option'); - userEvent.click(reporterOption); + await userEvent.click(reporterOption); expect(onPatrolReportedByChange).toHaveBeenCalledTimes(1); expect(onPatrolReportedByChange.mock.calls[0][0].id).toBe('dba0e0a6-0083-41be-a0eb-99e956977748'); @@ -147,11 +147,11 @@ describe('PatrolDetailView - PlanSection', () => { renderPlanSectionWithWrapper(); const objectiveInput = await screen.getByTestId('patrolDetailView-objectiveTextArea'); - userEvent.click(objectiveInput); + await userEvent.click(objectiveInput); expect(onPatrolObjectiveChange).toHaveBeenCalledTimes(0); - userEvent.type(objectiveInput, 'Great objective'); + await userEvent.type(objectiveInput, 'Great objective'); expect(onPatrolObjectiveChange).toHaveBeenCalled(); }); @@ -178,9 +178,9 @@ describe('PatrolDetailView - PlanSection', () => { const startDatePicker = await screen.findByTestId('patrolDetailView-planSection-startDatePicker'); const startDatePickerOpenCalendarButton = await within(startDatePicker).findByLabelText('Open calendar'); - userEvent.click(startDatePickerOpenCalendarButton); + await userEvent.click(startDatePickerOpenCalendarButton); const options = await screen.findAllByRole('option'); - userEvent.click(options[25]); + await userEvent.click(options[25]); expect(onPatrolStartDateChange).toHaveBeenCalled(); }); @@ -205,7 +205,7 @@ describe('PatrolDetailView - PlanSection', () => { expect(onPatrolStartDateChange).not.toHaveBeenCalled(); const autoStartInput = await screen.findByTestId('patrol-is-auto-start'); - userEvent.click(autoStartInput); + await userEvent.click(autoStartInput); expect(onPatrolStartDateChange).toHaveBeenCalled(); }); @@ -217,9 +217,9 @@ describe('PatrolDetailView - PlanSection', () => { const endDatePicker = await screen.findByTestId('patrolDetailView-planSection-endDatePicker'); const endDatePickerOpenCalendarButton = await within(endDatePicker).findByLabelText('Open calendar'); - userEvent.click(endDatePickerOpenCalendarButton); + await userEvent.click(endDatePickerOpenCalendarButton); const options = await screen.findAllByRole('option'); - userEvent.click(options[25]); + await userEvent.click(options[25]); expect(onPatrolEndDateChange).toHaveBeenCalled(); }); @@ -244,7 +244,7 @@ describe('PatrolDetailView - PlanSection', () => { expect(onPatrolEndDateChange).not.toHaveBeenCalled(); const autoEndInput = await screen.findByTestId('patrol-is-auto-end'); - userEvent.click(autoEndInput); + await userEvent.click(autoEndInput); expect(onPatrolEndDateChange).toHaveBeenCalled(); }); @@ -267,10 +267,10 @@ describe('PatrolDetailView - PlanSection', () => { renderPlanSectionWithWrapper({ patrolForm: futurePatrol }); const autoStartInput = await screen.findByTestId('patrol-is-auto-start'); - userEvent.click(autoStartInput); + await userEvent.click(autoStartInput); const autoEndInput = await screen.findByTestId('patrol-is-auto-end'); - userEvent.click(autoEndInput); + await userEvent.click(autoEndInput); const [, autoStartAction, autoEndAction] = mockedStore.getActions(); @@ -319,7 +319,7 @@ describe('PatrolDetailView - PlanSection', () => { expect(autoEndInput).not.toBeDisabled(); - userEvent.click(autoEndInput); + await userEvent.click(autoEndInput); const [, autoEndAction] = mockedStore.getActions(); expect(autoEndAction).toStrictEqual({ payload: { autoEndPatrols: true }, type: 'UPDATE_USER_PREFERENCES' }); @@ -344,10 +344,10 @@ describe('PatrolDetailView - PlanSection', () => { renderPlanSectionWithWrapper({ patrolForm: futurePatrol }); const autoStartInput = await screen.findByTestId('patrol-is-auto-start'); - userEvent.click(autoStartInput); + await userEvent.click(autoStartInput); const autoEndInput = await screen.findByTestId('patrol-is-auto-end'); - userEvent.click(autoEndInput); + await userEvent.click(autoEndInput); const [, autoStartAction, autoEndAction] = mockedStore.getActions(); @@ -386,8 +386,8 @@ describe('PatrolDetailView - PlanSection', () => { test('triggers the onPatrolStartLocationChange callback when the user chooses a location in map', async () => { renderPlanSectionWithWrapper(); - userEvent.click(screen.getByLabelText('Start Location')); - userEvent.click(screen.getByLabelText('Pick a location on the map')); + await userEvent.click(screen.getByLabelText('Start Location')); + await userEvent.click(screen.getByLabelText('Pick a location on the map')); expect(onPatrolStartLocationChange).toHaveBeenCalledTimes(0); @@ -400,8 +400,8 @@ describe('PatrolDetailView - PlanSection', () => { test('triggers the onPatrolEndLocationChange callback when the user chooses a location in map', async () => { renderPlanSectionWithWrapper(); - userEvent.click(screen.getByLabelText('End Location')); - userEvent.click(screen.getByLabelText('Pick a location on the map')); + await userEvent.click(screen.getByLabelText('End Location')); + await userEvent.click(screen.getByLabelText('Pick a location on the map')); expect(onPatrolEndLocationChange).toHaveBeenCalledTimes(0); diff --git a/src/PatrolDetailView/index.test.js b/src/PatrolDetailView/index.test.js index c7dd73479..bee2b681c 100644 --- a/src/PatrolDetailView/index.test.js +++ b/src/PatrolDetailView/index.test.js @@ -22,7 +22,7 @@ import { TrackerContext } from '../utils/analytics'; import useNavigate from '../hooks/useNavigate'; import { notes } from '../__test-helpers/fixtures/reports'; import { SidebarScrollProvider } from '../SidebarScrollContext'; -import { render, screen, waitFor, within } from '../test-utils'; +import { act, render, screen, waitFor, within } from '../test-utils'; jest.mock('mapbox-gl', () => ({ ...jest.requireActual('mapbox-gl'), @@ -308,19 +308,19 @@ describe('PatrolDetailView', () => { expect(titleInput).toHaveTextContent('Unknown patrol type'); - userEvent.type(titleInput, '2'); + await userEvent.type(titleInput, '2'); - expect(titleInput).toHaveTextContent('2nknown patrol type'); + expect(titleInput).toHaveTextContent('2'); }); - test('sets the start location when user changes it', () => { + test('sets the start location when user changes it', async () => { renderWithWrapper(); const startLocationPickerButton = screen.getByLabelText('Start Location'); - userEvent.click(startLocationPickerButton); - userEvent.click(screen.getByLabelText('Pick a location on the map')); + await userEvent.click(startLocationPickerButton); + await userEvent.click(screen.getByLabelText('Pick a location on the map')); - map.__test__.fireHandlers('click', { lngLat: { lng: 88, lat: 55 } }); + act(() => map.__test__.fireHandlers('click', { lngLat: { lng: 88, lat: 55 } })); expect(within(startLocationPickerButton).getByRole('textbox')).toHaveValue('55.000000°, 88.000000°'); }); @@ -333,9 +333,9 @@ describe('PatrolDetailView', () => { const startDatePicker = await screen.findByTestId('patrolDetailView-planSection-startDatePicker'); const startDatePickerOpenCalendarButton = await within(startDatePicker).findByLabelText('Open calendar'); - userEvent.click(startDatePickerOpenCalendarButton); + await userEvent.click(startDatePickerOpenCalendarButton); const options = await screen.findAllByRole('option'); - userEvent.click(options[25]); + await userEvent.click(options[25]); expect(await within(startDatePicker).findByTestId('datePicker-input')).toHaveValue('2022-01-20'); }); @@ -348,22 +348,22 @@ describe('PatrolDetailView', () => { const startTimePicker = await screen.findByTestId('patrolDetailView-planSection-startTimePicker'); const startTimePickerOpenOptionsButton = await within(startTimePicker).findByLabelText('Open time options'); - userEvent.click(startTimePickerOpenOptionsButton); + await userEvent.click(startTimePickerOpenOptionsButton); const optionsList = await screen.findByTestId('timePicker-OptionsList'); const timeOptionsListItems = await within(optionsList).findAllByRole('option'); - userEvent.click(timeOptionsListItems[2]); + await userEvent.click(timeOptionsListItems[2]); expect(await within(startTimePicker).findByTestId('timePicker-input')).toHaveValue('00:30'); }); - test('sets the end location when user changes it', () => { + test('sets the end location when user changes it', async () => { renderWithWrapper(); const endLocationPickerButton = screen.getByLabelText('End Location'); - userEvent.click(endLocationPickerButton); - userEvent.click(screen.getByLabelText('Pick a location on the map')); + await userEvent.click(endLocationPickerButton); + await userEvent.click(screen.getByLabelText('Pick a location on the map')); - map.__test__.fireHandlers('click', { lngLat: { lng: 88, lat: 55 } }); + act(() => map.__test__.fireHandlers('click', { lngLat: { lng: 88, lat: 55 } })); expect(within(endLocationPickerButton).getByRole('textbox')).toHaveValue('55.000000°, 88.000000°'); }); @@ -376,9 +376,9 @@ describe('PatrolDetailView', () => { const endDatePicker = await screen.findByTestId('patrolDetailView-planSection-endDatePicker'); const endDatePickerOpenCalendarButton = await within(endDatePicker).findByLabelText('Open calendar'); - userEvent.click(endDatePickerOpenCalendarButton); + await userEvent.click(endDatePickerOpenCalendarButton); const endOptions = await screen.findAllByRole('option'); - userEvent.click(endOptions[25]); + await userEvent.click(endOptions[25]); expect(await within(endDatePicker).findByTestId('datePicker-input')).toHaveValue('2022-01-20'); }); @@ -405,16 +405,16 @@ describe('PatrolDetailView', () => { const endDatePicker = await screen.findByTestId('patrolDetailView-planSection-endDatePicker'); const endDatePickerOpenCalendarButton = await within(endDatePicker).findByLabelText('Open calendar'); - userEvent.click(endDatePickerOpenCalendarButton); + await userEvent.click(endDatePickerOpenCalendarButton); const endOptions = await screen.findAllByRole('option'); - userEvent.click(endOptions[25]); + await userEvent.click(endOptions[25]); const endTimePicker = await screen.findByTestId('patrolDetailView-planSection-endTimePicker'); const endTimePickerOpenOptionsButton = await within(endTimePicker).findByLabelText('Open time options'); - userEvent.click(endTimePickerOpenOptionsButton); + await userEvent.click(endTimePickerOpenOptionsButton); const optionsList = await screen.findByTestId('timePicker-OptionsList'); const timeOptionsListItems = await within(optionsList).findAllByRole('option'); - userEvent.click(timeOptionsListItems[2]); + await userEvent.click(timeOptionsListItems[2]); expect(await within(endTimePicker).findByTestId('timePicker-input')).toHaveValue('00:30'); }); @@ -426,7 +426,7 @@ describe('PatrolDetailView', () => { expect(objectiveInput).not.toHaveTextContent('great objective'); - userEvent.type(objectiveInput, 'great objective'); + await userEvent.type(objectiveInput, 'great objective'); expect(objectiveInput).toHaveTextContent('great objective'); }); @@ -437,7 +437,7 @@ describe('PatrolDetailView', () => { expect(navigate).toHaveBeenCalledTimes(0); const cancelButton = await screen.findByText('Cancel'); - userEvent.click(cancelButton); + await userEvent.click(cancelButton); expect(navigate).toHaveBeenCalledTimes(1); expect(navigate).toHaveBeenCalledWith(`/${TAB_KEYS.PATROLS}`); @@ -446,25 +446,25 @@ describe('PatrolDetailView', () => { test('displays a new note', async () => { renderWithWrapper(); - expect((await screen.findAllByText('note.svg'))).toHaveLength(1); + expect((await screen.queryByTestId('note-icon'))).toBeNull(); const addNoteButton = await screen.findByTestId('addNoteButton'); - userEvent.click(addNoteButton); + await userEvent.click(addNoteButton); - expect((await screen.findAllByText('note.svg'))).toHaveLength(2); + expect((await screen.findAllByTestId('note-icon'))).toHaveLength(1); }); test('deletes a new note', async () => { renderWithWrapper(); - expect((await screen.findAllByText('note.svg'))).toHaveLength(1); + expect((await screen.queryByTestId('note-icon'))).toBeNull(); const addNoteButton = await screen.findByTestId('addNoteButton'); - userEvent.click(addNoteButton); - const deleteNoteButton = await screen.findByText('trash-can.svg'); - userEvent.click(deleteNoteButton); + await userEvent.click(addNoteButton); + const deleteNoteButton = await screen.findByTestId('activitySection-deleteIcon-'); + await userEvent.click(deleteNoteButton); - expect((await screen.findAllByText('note.svg'))).toHaveLength(1); + expect((await screen.queryByTestId('note-icon'))).toBeNull(); }); test('shows invalid dates modal and does not save if dates are invalid', async () => { @@ -477,18 +477,18 @@ describe('PatrolDetailView', () => { const endDatePicker = await screen.findByTestId('patrolDetailView-planSection-endDatePicker'); const endDatePickerOpenCalendarButton = await within(endDatePicker).findByLabelText('Open calendar'); - userEvent.click(endDatePickerOpenCalendarButton); + await userEvent.click(endDatePickerOpenCalendarButton); const endOptions = await screen.findAllByRole('option'); - userEvent.click(endOptions[25]); + await userEvent.click(endOptions[25]); const startDatePicker = await screen.findByTestId('patrolDetailView-planSection-startDatePicker'); const startDatePickerOpenCalendarButton = await within(startDatePicker).findByLabelText('Open calendar'); - userEvent.click(startDatePickerOpenCalendarButton); + await userEvent.click(startDatePickerOpenCalendarButton); const options = await screen.findAllByRole('option'); - userEvent.click(options[26]); + await userEvent.click(options[26]); const saveButton = await screen.findByText('Save'); - userEvent.click(saveButton); + await userEvent.click(saveButton); expect(executeSaveActions).toHaveBeenCalledTimes(0); expect((await screen.findByText('Invalid Patrol Times'))).toBeDefined(); @@ -498,13 +498,13 @@ describe('PatrolDetailView', () => { renderWithWrapper(); const titleInput = (await screen.findAllByRole('textbox'))[0]; - userEvent.type(titleInput, '2'); - userEvent.tab(); + await userEvent.type(titleInput, '2'); + await userEvent.tab(); expect(executeSaveActions).toHaveBeenCalledTimes(0); const saveButton = await screen.findByText('Save'); - userEvent.click(saveButton); + await userEvent.click(saveButton); await waitFor(() => { expect(executeSaveActions).toHaveBeenCalledTimes(1); @@ -513,32 +513,20 @@ describe('PatrolDetailView', () => { }); }); - test('shows the loading overlay while saving', async () => { - renderWithWrapper(); - - const titleInput = (await screen.findAllByRole('textbox'))[0]; - userEvent.type(titleInput, '2'); - userEvent.tab(); - const saveButton = await screen.findByText('Save'); - userEvent.click(saveButton); - - expect(await screen.findByText('Saving...')).toBeDefined(); - }); - test('can not add a second note without saving the first one', async () => { window.alert = jest.fn(); renderWithWrapper(); - expect((await screen.findAllByText('note.svg'))).toHaveLength(1); + expect((await screen.queryByTestId('note-icon'))).toBeNull(); expect(window.alert).toHaveBeenCalledTimes(0); const addNoteButton = await screen.findByTestId('addNoteButton'); - userEvent.click(addNoteButton); - userEvent.click(addNoteButton); + await userEvent.click(addNoteButton); + await userEvent.click(addNoteButton); expect(window.alert).toHaveBeenCalledTimes(1); - expect((await screen.findAllByText('note.svg'))).toHaveLength(2); + expect((await screen.findAllByTestId('note-icon'))).toHaveLength(1); }); test('does not display the activity section nor its anchor if there are no items to show', async () => { @@ -555,7 +543,7 @@ describe('PatrolDetailView', () => { expect((await screen.queryByTestId('quickLinks-anchor-Activity'))).toBeNull(); const addNoteButton = await screen.findByTestId('addNoteButton'); - userEvent.click(addNoteButton); + await userEvent.click(addNoteButton); expect((await screen.findByTestId('detailView-activitySection'))).toBeDefined(); expect((await screen.findByTestId('quickLinks-anchor-Activity'))).toBeDefined(); @@ -584,13 +572,13 @@ describe('PatrolDetailView', () => { renderWithWrapper(); const editNoteIcon = await screen.findByTestId(`activitySection-editIcon-${noteId}`); - userEvent.click(editNoteIcon); + await userEvent.click(editNoteIcon); const noteTextArea = await screen.findByTestId(`activitySection-noteTextArea-${noteId}`); - userEvent.type(noteTextArea, updatedText); + await userEvent.type(noteTextArea, updatedText); const doneNoteButton = await screen.findByTestId(`activitySection-noteDone-${noteId}`); - userEvent.click(doneNoteButton); + await userEvent.click(doneNoteButton); const textArea = await screen.findByTestId(`activitySection-noteTextArea-${noteId}`); return { textArea, doneNoteButton, }; @@ -604,7 +592,7 @@ describe('PatrolDetailView', () => { expect(textArea).toHaveValue(`${note.text}${updatedText}`); const cancelButton = await screen.findByText('Cancel'); - userEvent.click(cancelButton); + await userEvent.click(cancelButton); expect(textArea).toHaveTextContent(note.text); expect( (await screen.queryByText(doneNoteButton)) ).toBeNull(); @@ -643,11 +631,11 @@ describe('PatrolDetailView', () => { renderWithWrapper(); const titleInput = await screen.findByTestId('patrolDetailView-header-title'); - userEvent.type(titleInput, '2'); + await userEvent.type(titleInput, '2'); titleInput.blur(); const cancelButton = await screen.findByText('Cancel'); - userEvent.click(cancelButton); + await userEvent.click(cancelButton); await screen.findByText('Unsaved Changes'); await screen.findByText('There are unsaved changes. Would you like to go back, discard the changes, or save and continue?'); @@ -657,11 +645,11 @@ describe('PatrolDetailView', () => { renderWithWrapper(); const titleTextBox = await screen.findByTestId('patrolDetailView-header-title'); - userEvent.type(titleTextBox, '2'); - userEvent.tab(); + await userEvent.type(titleTextBox, '2'); + await userEvent.tab(); const cancelButton = await screen.findByText('Cancel'); - userEvent.click(cancelButton); + await userEvent.click(cancelButton); expect(executeSaveActions).toHaveBeenCalledTimes(0); expect(navigate).toHaveBeenCalledTimes(0); @@ -680,45 +668,45 @@ describe('PatrolDetailView', () => { test('displays a new attachment', async () => { renderWithWrapper(); - expect((await screen.findAllByText('attachment.svg'))).toHaveLength(1); + expect((await screen.queryByTestId('attachment-icon'))).toBeNull(); const addAttachmentButton = await screen.findByTestId('addAttachmentButton'); const fakeFile = new File(['fake'], 'fake.txt', { type: 'text/plain' }); - userEvent.upload(addAttachmentButton, fakeFile); + await userEvent.upload(addAttachmentButton, fakeFile); - expect((await screen.findAllByText('attachment.svg'))).toHaveLength(2); + expect((await screen.findAllByTestId('attachment-icon'))).toHaveLength(1); }); test('deletes a new attachment', async () => { renderWithWrapper(); - expect((await screen.findAllByText('attachment.svg'))).toHaveLength(1); + expect((await screen.queryByTestId('attachment-icon'))).toBeNull(); const addAttachmentButton = await screen.findByTestId('addAttachmentButton'); const fakeFile = new File(['fake'], 'fake.txt', { type: 'text/plain' }); - userEvent.upload(addAttachmentButton, fakeFile); - const deleteAttachmentButton = await screen.findByText('trash-can.svg'); - userEvent.click(deleteAttachmentButton); + await userEvent.upload(addAttachmentButton, fakeFile); + const deleteAttachmentButton = await screen.findByTestId('activitySection-trashCan-fake.txt'); + await userEvent.click(deleteAttachmentButton); - expect((await screen.findAllByText('attachment.svg'))).toHaveLength(1); + expect((await screen.queryByTestId('attachment-icon'))).toBeNull(); }); test('omits duplicated attachment files', async () => { window.alert = jest.fn(); renderWithWrapper(); - expect((await screen.findAllByText('attachment.svg'))).toHaveLength(1); + expect((await screen.queryByTestId('attachment-icon'))).toBeNull(); const addAttachmentButton = await screen.findByTestId('addAttachmentButton'); const fakeFile = new File(['fake'], 'fake.txt', { type: 'text/plain' }); - userEvent.upload(addAttachmentButton, fakeFile); + await userEvent.upload(addAttachmentButton, fakeFile); - expect((await screen.findAllByText('attachment.svg'))).toHaveLength(2); + expect((await screen.findAllByTestId('attachment-icon'))).toHaveLength(1); const fakeFileAgain = new File(['fake'], 'fake.txt', { type: 'text/plain' }); - userEvent.upload(addAttachmentButton, fakeFileAgain); + await userEvent.upload(addAttachmentButton, fakeFileAgain); - expect((await screen.findAllByText('attachment.svg'))).toHaveLength(2); + expect((await screen.findAllByTestId('attachment-icon'))).toHaveLength(1); }); }); diff --git a/src/PatrolFilter/DateRangePopover/index.test.js b/src/PatrolFilter/DateRangePopover/index.test.js index 7f3c25f9e..e5523bb41 100644 --- a/src/PatrolFilter/DateRangePopover/index.test.js +++ b/src/PatrolFilter/DateRangePopover/index.test.js @@ -30,7 +30,10 @@ describe('DateRangePopover', () => { data: { patrolFilter: { filter: { - date_range: INITIAL_FILTER_STATE.filter.date_range, + date_range: { + lower: INITIAL_FILTER_STATE.filter.date_range.lower, + upper: INITIAL_FILTER_STATE.filter.date_range.upper, + }, }, }, }, @@ -51,9 +54,9 @@ describe('DateRangePopover', () => { expect(resetGlobalDateRange).toHaveBeenCalledTimes(0); const resetButton = await screen.findByText('Reset'); - userEvent.click(resetButton); + await userEvent.click(resetButton); - waitFor(() => { + await waitFor(() => { expect(resetGlobalDateRange).toHaveBeenCalledTimes(1); }); }); @@ -69,13 +72,13 @@ describe('DateRangePopover', () => { // Click the patrol filter settings button const patrolFilterSettings = await screen.getByTestId('settings-gear-icon'); - userEvent.click(patrolFilterSettings); + await userEvent.click(patrolFilterSettings); expect(updatePatrolFilter).toHaveBeenCalledTimes(0); // Click date overlap radio button const dateRangeOverlapRadioButton = (await screen.findAllByRole('radio'))[1]; - userEvent.click(dateRangeOverlapRadioButton); + await userEvent.click(dateRangeOverlapRadioButton); expect(updatePatrolFilter).toHaveBeenCalledTimes(1); expect(updatePatrolFilter).toHaveBeenCalledWith({ filter: { patrols_overlap_daterange: true } }); diff --git a/src/PatrolFilter/FiltersPopover/index.test.js b/src/PatrolFilter/FiltersPopover/index.test.js index 60492bcd6..3cba9a192 100644 --- a/src/PatrolFilter/FiltersPopover/index.test.js +++ b/src/PatrolFilter/FiltersPopover/index.test.js @@ -114,7 +114,7 @@ describe('PatrolFilter', () => { ); const resetFiltersButton = await screen.findByText('Reset All'); - userEvent.click(resetFiltersButton); + await userEvent.click(resetFiltersButton); expect(updatePatrolFilter).toHaveBeenCalledTimes(1); expect(updatePatrolFilter).toHaveBeenCalledWith({ @@ -136,8 +136,8 @@ describe('PatrolFilter', () => { expect(updatePatrolFilter).toHaveBeenCalledTimes(0); const leadersSelect = await screen.findByRole('combobox'); - userEvent.type(leadersSelect, 'Leader 1'); - userEvent.keyboard('{Enter}'); + await userEvent.type(leadersSelect, 'Leader 1'); + await userEvent.keyboard('{Enter}'); expect(updatePatrolFilter).toHaveBeenCalledTimes(1); expect(updatePatrolFilter).toHaveBeenCalledWith({ filter: { tracked_by: ['Leader 1'] } }); @@ -152,8 +152,8 @@ describe('PatrolFilter', () => { ); const leadersSelect = await screen.findByRole('combobox'); - userEvent.type(leadersSelect, 'Leader 2'); - userEvent.keyboard('{Enter}'); + await userEvent.type(leadersSelect, 'Leader 2'); + await userEvent.keyboard('{Enter}'); expect(updatePatrolFilter).toHaveBeenCalledTimes(1); expect(updatePatrolFilter).toHaveBeenCalledWith({ filter: { tracked_by: ['Leader 1', 'Leader 2'] } }); @@ -194,7 +194,7 @@ describe('PatrolFilter', () => { expect(updatePatrolFilter).toHaveBeenCalledTimes(0); const resetLeadersButton = await screen.findByTestId('patrolFilter-reset-leaders-button'); - userEvent.click(resetLeadersButton); + await userEvent.click(resetLeadersButton); expect(updatePatrolFilter).toHaveBeenCalledTimes(1); expect(updatePatrolFilter).toHaveBeenCalledWith({ filter: { tracked_by: INITIAL_FILTER_STATE.filter.tracked_by } }); @@ -211,7 +211,7 @@ describe('PatrolFilter', () => { const statusCheckboxList = await screen.findByTestId('patrolFilter-status-checkbox-list'); const activeStatusCheckbox = (await within(statusCheckboxList).findAllByRole('checkbox'))[1]; - userEvent.click(activeStatusCheckbox); + await userEvent.click(activeStatusCheckbox); expect(updatePatrolFilter).toHaveBeenCalledTimes(1); expect(updatePatrolFilter).toHaveBeenCalledWith({ status: ['active'] }); @@ -229,7 +229,7 @@ describe('PatrolFilter', () => { const statusCheckboxList = await screen.findByTestId('patrolFilter-status-checkbox-list'); const cancelledStatusCheckbox = (await within(statusCheckboxList).findAllByRole('checkbox'))[3]; - userEvent.click(cancelledStatusCheckbox); + await userEvent.click(cancelledStatusCheckbox); expect(updatePatrolFilter).toHaveBeenCalledTimes(1); expect(updatePatrolFilter).toHaveBeenCalledWith({ status: ['active', 'cancelled'] }); @@ -245,7 +245,7 @@ describe('PatrolFilter', () => { const statusCheckboxList = await screen.findByTestId('patrolFilter-status-checkbox-list'); const allStatusCheckbox = (await within(statusCheckboxList).findAllByRole('checkbox'))[0]; - userEvent.click(allStatusCheckbox); + await userEvent.click(allStatusCheckbox); expect(updatePatrolFilter).toHaveBeenCalledTimes(1); expect(updatePatrolFilter).toHaveBeenCalledWith({ status: [] }); @@ -287,7 +287,7 @@ describe('PatrolFilter', () => { expect(updatePatrolFilter).toHaveBeenCalledTimes(0); const resetStatusButton = await screen.findByTestId('patrolFilter-reset-status-button'); - userEvent.click(resetStatusButton); + await userEvent.click(resetStatusButton); expect(updatePatrolFilter).toHaveBeenCalledTimes(1); expect(updatePatrolFilter).toHaveBeenCalledWith({ status: INITIAL_FILTER_STATE.status }); @@ -304,7 +304,7 @@ describe('PatrolFilter', () => { const patrolTypeCheckboxList = await screen.findByTestId('patrolFilter-patrol-type-checkbox-list'); const dogPatrolTypeCheckbox = (await within(patrolTypeCheckboxList).findAllByRole('checkbox'))[1]; - userEvent.click(dogPatrolTypeCheckbox); + await userEvent.click(dogPatrolTypeCheckbox); expect(updatePatrolFilter).toHaveBeenCalledTimes(1); expect(updatePatrolFilter).toHaveBeenCalledWith({ filter: { patrol_type: ['dog_patrol'] } }); @@ -322,7 +322,7 @@ describe('PatrolFilter', () => { const patrolTypeCheckboxList = await screen.findByTestId('patrolFilter-patrol-type-checkbox-list'); const fencePatrolTypeCheckbox = (await within(patrolTypeCheckboxList).findAllByRole('checkbox'))[2]; - userEvent.click(fencePatrolTypeCheckbox); + await userEvent.click(fencePatrolTypeCheckbox); expect(updatePatrolFilter).toHaveBeenCalledTimes(1); expect(updatePatrolFilter).toHaveBeenCalledWith({ filter: { patrol_type: ['dog_patrol', 'fence_patrol'] } }); @@ -340,7 +340,7 @@ describe('PatrolFilter', () => { const patrolTypeCheckboxList = await screen.findByTestId('patrolFilter-patrol-type-checkbox-list'); const allPatrolTypeCheckbox = (await within(patrolTypeCheckboxList).findAllByRole('checkbox'))[0]; - userEvent.click(allPatrolTypeCheckbox); + await userEvent.click(allPatrolTypeCheckbox); expect(updatePatrolFilter).toHaveBeenCalledTimes(1); expect(updatePatrolFilter).toHaveBeenCalledWith({ filter: { patrol_type: [] } }); @@ -381,7 +381,7 @@ describe('PatrolFilter', () => { expect(updatePatrolFilter).toHaveBeenCalledTimes(0); const resetPatrolTypesButton = await screen.findByTestId('patrolFilter-reset-patrol-type-button'); - userEvent.click(resetPatrolTypesButton); + await userEvent.click(resetPatrolTypesButton); expect(updatePatrolFilter).toHaveBeenCalledTimes(1); expect(updatePatrolFilter).toHaveBeenCalledWith({ diff --git a/src/PatrolFilter/index.test.js b/src/PatrolFilter/index.test.js index e64e521ff..f707a5263 100644 --- a/src/PatrolFilter/index.test.js +++ b/src/PatrolFilter/index.test.js @@ -21,7 +21,7 @@ jest.mock('redux-persist', () => { }; }); - describe('PatrolFilter', () => { +describe('PatrolFilter', () => { let store, updatePatrolFilterMock; beforeEach(() => { updatePatrolFilterMock = jest.fn(() => () => {}); @@ -60,7 +60,7 @@ jest.mock('redux-persist', () => { expect(searchBar.value).toBe(''); expect(updatePatrolFilter).toHaveBeenCalledTimes(0); - userEvent.type(searchBar, 'Search'); + await userEvent.type(searchBar, 'Search'); await waitFor(() => { expect(searchBar.value).toBe('Search'); @@ -72,7 +72,7 @@ jest.mock('redux-persist', () => { test('clears the search bar text when the user clicks the clear button', async () => { const searchBar = await screen.findByTestId('search-input'); const clearSearchBarButton = await screen.findByTestId('reset-search-button'); - userEvent.type(searchBar, 'Search'); + await userEvent.type(searchBar, 'Search'); await waitFor(() => { expect(searchBar.value).toBe('Search'); @@ -80,7 +80,7 @@ jest.mock('redux-persist', () => { expect(updatePatrolFilter).toHaveBeenCalledWith({ filter: { text: 'Search' } }); }, { timeout: PATROL_TEXT_FILTER_DEBOUNCE_TIME + 50 }); - userEvent.click(clearSearchBarButton); + await userEvent.click(clearSearchBarButton); await waitFor(() => { expect(searchBar.value).toBe(''); diff --git a/src/PatrolListItem/index.test.js b/src/PatrolListItem/index.test.js index 37f80674a..934d446d3 100644 --- a/src/PatrolListItem/index.test.js +++ b/src/PatrolListItem/index.test.js @@ -67,7 +67,6 @@ beforeEach(() => { updatePatrol.mockImplementation(updatePatrolMock); jest.spyOn(customHooks, 'usePermissions').mockImplementation(() => true); // full permissions for list item read+write access - jest.useFakeTimers('modern'); }); const initialProps = { @@ -173,15 +172,11 @@ describe('the patrol list item', () => { describe('for active patrols', () => { const patrolWithLeader = { ...patrols[1] }; const mockStartDate = new Date('2021-10-09'); - const mockCurrentDate = new Date('2021-10-10'); beforeEach(() => { testPatrol = { ...patrolWithLeader }; testPatrol.patrol_segments[0].time_range.start_time = mockStartDate.toISOString(); - jest.useFakeTimers('modern'); - jest.setSystemTime(mockCurrentDate.getTime()); - jest.spyOn(patrolUtils, 'patrolHasGeoDataToDisplay').mockImplementation(() => true); jest.spyOn(patrolUtils, 'getBoundsForPatrol').mockImplementation(() => { var line = lineString([[-74, 40], [-78, 42], [-82, 35]]); /* some random valid line to create bounding box around */ @@ -200,7 +195,7 @@ describe('for active patrols', () => { test('toggling a patrol track on when clicking the "jump to location button"', async () => { const jumpButton = await screen.findByTestId(`patrol-list-item-jump-btn-${testPatrol.id}`); - userEvent.click(jumpButton); + await userEvent.click(jumpButton); const actions = store.getActions(); @@ -212,7 +207,7 @@ describe('for active patrols', () => { test('toggling a patrol leader\'s track on when clicking the "jump to location button"', async () => { const jumpButton = await screen.findByTestId(`patrol-list-item-jump-btn-${testPatrol.id}`); - userEvent.click(jumpButton); + await userEvent.click(jumpButton); const actions = store.getActions(); @@ -229,12 +224,12 @@ describe('for active patrols', () => { test('canceling the patrol from the kebab menu', async () => { const kebabMenu = await screen.findByTestId(`patrol-list-item-kebab-menu-${testPatrol.id}`); const kebabButton = kebabMenu.querySelector('.dropdown-toggle'); - userEvent.click(kebabButton); + await userEvent.click(kebabButton); expect(updatePatrol).toHaveBeenCalledTimes(0); const cancelBtn = await within(kebabMenu).findByText('Cancel Patrol'); - userEvent.click(cancelBtn); + await userEvent.click(cancelBtn); expect(updatePatrol).toHaveBeenCalledTimes(1); expect(updatePatrol.mock.calls[0][0].state).toBe(PATROL_API_STATES.CANCELLED); @@ -243,16 +238,15 @@ describe('for active patrols', () => { test('ending a patrol from the kebab menu', async () => { const kebabMenu = await screen.findByTestId(`patrol-list-item-kebab-menu-${testPatrol.id}`); const kebabButton = kebabMenu.querySelector('.dropdown-toggle'); - userEvent.click(kebabButton); + await userEvent.click(kebabButton); expect(updatePatrol).toHaveBeenCalledTimes(0); const endBtn = await within(kebabMenu).findByText('End Patrol'); - userEvent.click(endBtn); + await userEvent.click(endBtn); expect(updatePatrol).toHaveBeenCalledTimes(1); expect(updatePatrol.mock.calls[0][0].state).toBe(PATROL_API_STATES.DONE); - expect(updatePatrol.mock.calls[0][0].patrol_segments[0].time_range.end_time).toBe(mockCurrentDate.toISOString()); }); test('theming', async () => { @@ -265,14 +259,11 @@ describe('for active patrols', () => { describe('for scheduled patrols', () => { const mockStartDate = new Date('10-10-2021 11:00'); - const mockCurrentDate = new Date('10-10-2021 9:00'); beforeEach(() => { testPatrol = { ...patrols[0] }; testPatrol.patrol_segments[0].time_range.scheduled_start = mockStartDate.toISOString(); - jest.setSystemTime(mockCurrentDate.getTime()); - jest.spyOn(patrolUtils, 'calcPatrolState').mockImplementation(() => PATROL_UI_STATES.READY_TO_START); renderPatrolListItem({ ...initialProps, patrol: testPatrol }); @@ -282,23 +273,21 @@ describe('for scheduled patrols', () => { expect(updatePatrol).toHaveBeenCalledTimes(0); const startBtn = await screen.findByTestId(`patrol-list-item-start-btn-${testPatrol.id}`); - userEvent.click(startBtn); + await userEvent.click(startBtn); expect(updatePatrol).toHaveBeenCalledTimes(1); expect(updatePatrol.mock.calls[0][0].state).toBe(PATROL_API_STATES.OPEN); - expect(updatePatrol.mock.calls[0][0].patrol_segments[0].time_range.end_time).toBeNull(); - expect(updatePatrol.mock.calls[0][0].patrol_segments[0].time_range.start_time).toBe(mockCurrentDate.toISOString()); }); test('canceling the patrol from the kebab menu', async () => { const kebabMenu = await screen.findByTestId(`patrol-list-item-kebab-menu-${testPatrol.id}`); const kebabButton = kebabMenu.querySelector('.dropdown-toggle'); - userEvent.click(kebabButton); + await userEvent.click(kebabButton); expect(updatePatrol).toHaveBeenCalledTimes(0); const cancelBtn = await within(kebabMenu).findByText('Cancel Patrol'); - userEvent.click(cancelBtn); + await userEvent.click(cancelBtn); expect(updatePatrol).toHaveBeenCalledTimes(1); expect(updatePatrol.mock.calls[0][0].state).toBe(PATROL_API_STATES.CANCELLED); @@ -314,14 +303,11 @@ describe('for scheduled patrols', () => { describe('for overdue patrols', () => { const mockStartDate = new Date('10-10-2021 01:00'); - const mockCurrentDate = new Date('10-10-2021 13:00'); beforeEach(() => { testPatrol = { ...patrols[0] }; testPatrol.patrol_segments[0].time_range.scheduled_start = mockStartDate.toISOString(); - jest.setSystemTime(mockCurrentDate.getTime()); - jest.spyOn(patrolUtils, 'calcPatrolState').mockImplementation(() => PATROL_UI_STATES.START_OVERDUE); renderPatrolListItem({ ...initialProps, patrol: testPatrol }); @@ -342,14 +328,10 @@ describe('for overdue patrols', () => { }); describe('for cancelled patrols', () => { - const mockCurrentDate = new Date('10-10-2021 13:00'); - beforeEach(() => { testPatrol = { ...patrols[0] }; testPatrol.state = PATROL_API_STATES.CANCELLED; - jest.setSystemTime(mockCurrentDate.getTime()); - jest.spyOn(patrolUtils, 'calcPatrolState').mockImplementation(() => PATROL_UI_STATES.CANCELLED); renderPatrolListItem({ ...initialProps, patrol: testPatrol }); @@ -359,7 +341,7 @@ describe('for cancelled patrols', () => { expect(updatePatrol).toHaveBeenCalledTimes(0); const restoreBtn = await screen.findByTestId(`patrol-list-item-restore-btn-${testPatrol.id}`); - userEvent.click(restoreBtn); + await userEvent.click(restoreBtn); expect(updatePatrol).toHaveBeenCalledTimes(1); expect(updatePatrol.mock.calls[0][0].state).toBe(PATROL_API_STATES.OPEN); @@ -369,12 +351,12 @@ describe('for cancelled patrols', () => { test('restoring the patrol from the kebab menu', async () => { const kebabMenu = await screen.findByTestId(`patrol-list-item-kebab-menu-${testPatrol.id}`); const kebabButton = kebabMenu.querySelector('.dropdown-toggle'); - userEvent.click(kebabButton); + await userEvent.click(kebabButton); expect(updatePatrol).toHaveBeenCalledTimes(0); const restoreBtn = await within(kebabMenu).findByText('Restore Patrol'); - userEvent.click(restoreBtn); + await userEvent.click(restoreBtn); expect(updatePatrol).toHaveBeenCalledTimes(1); expect(updatePatrol.mock.calls[0][0].state).toBe(PATROL_API_STATES.OPEN); @@ -389,14 +371,10 @@ describe('for cancelled patrols', () => { }); describe('for completed patrols', () => { - const mockCurrentDate = new Date('10-10-2021 13:00'); - beforeEach(() => { testPatrol = { ...patrols[0] }; testPatrol.state = PATROL_API_STATES.CANCELLED; - jest.setSystemTime(mockCurrentDate.getTime()); - jest.spyOn(patrolUtils, 'calcPatrolState').mockImplementation(() => PATROL_UI_STATES.CANCELLED); renderPatrolListItem({ ...initialProps, patrol: testPatrol }); @@ -405,12 +383,12 @@ describe('for completed patrols', () => { test('restoring the patrol from the kebab menu', async () => { const kebabMenu = await screen.findByTestId(`patrol-list-item-kebab-menu-${testPatrol.id}`); const kebabButton = kebabMenu.querySelector('.dropdown-toggle'); - userEvent.click(kebabButton); + await userEvent.click(kebabButton); expect(updatePatrol).toHaveBeenCalledTimes(0); const restoreBtn = await within(kebabMenu).findByText('Restore Patrol'); - userEvent.click(restoreBtn); + await userEvent.click(restoreBtn); expect(updatePatrol).toHaveBeenCalledTimes(1); expect(updatePatrol.mock.calls[0][0].state).toBe(PATROL_API_STATES.OPEN); diff --git a/src/PatrolMenu/index.js b/src/PatrolMenu/index.js index 3e5c891ff..1d3518286 100644 --- a/src/PatrolMenu/index.js +++ b/src/PatrolMenu/index.js @@ -115,14 +115,14 @@ const PatrolMenu = ({ > { (canEditPatrol && !isPatrolCancelled && !patrolIsDone) && - { canEnd ? : } + { canEnd ? : } {patrolStartStopTitle} } { canEditPatrol && - { isPatrolCancelled || patrolIsDone ? : } + { isPatrolCancelled || patrolIsDone ? : } {patrolCancelRestoreTitle} } @@ -132,7 +132,7 @@ const PatrolMenu = ({ } + icon={} successMessage={t('copyButtonMessage')} permitPropagation /> @@ -140,7 +140,7 @@ const PatrolMenu = ({ { showPatrolPrintOption && - + {t('printPatrolButton')} } diff --git a/src/PatrolMenu/index.test.js b/src/PatrolMenu/index.test.js index 5ddb22668..4cbb201e3 100644 --- a/src/PatrolMenu/index.test.js +++ b/src/PatrolMenu/index.test.js @@ -15,7 +15,7 @@ jest.mock('react-to-print', () => ({ useReactToPrint: jest.fn(), })); -describe('', () => { +describe('PatrolMenu', () => { let useReactToPrintMock = null; const handlePrint = jest.fn(); @@ -66,9 +66,9 @@ describe('', () => { const testMinimumOptionsMenu = () => { expect( screen.getByText('Copy patrol link') ).toBeInTheDocument(); - expect( screen.getByText('link.svg') ).toBeInTheDocument(); + expect( screen.getByTestId('clip-icon') ).toBeInTheDocument(); expect( screen.getByText('Print Patrol') ).toBeInTheDocument(); - expect( screen.getByText('printer-outline.svg') ).toBeInTheDocument(); + expect( screen.getByTestId('printer-icon') ).toBeInTheDocument(); }; beforeEach(() => { @@ -76,50 +76,50 @@ describe('', () => { useReactToPrint.mockImplementation(useReactToPrintMock); }); - test('renders minimum menu options for a patrol', () => { + test('renders minimum menu options for a patrol', async () => { renderPatrolMenu(); - userEvent.click(screen.getByRole('button')); + await userEvent.click(screen.getByRole('button')); testMinimumOptionsMenu(); }); - test('prints the patrol details', () => { + test('prints the patrol details', async () => { renderPatrolMenu(); - userEvent.click(screen.getByRole('button')); + await userEvent.click(screen.getByRole('button')); expect(handlePrint).toHaveBeenCalledTimes(0); - userEvent.click(screen.getByText('Print Patrol')); + await userEvent.click(screen.getByText('Print Patrol')); expect(handlePrint).toHaveBeenCalledTimes(1); }); - test('renders menu options for a patrol with update permissions', () => { + test('renders menu options for a patrol with update permissions', async () => { renderPatrolMenu(undefined, storeWithUpdatePermissions); - userEvent.click(screen.getByRole('button')); + await userEvent.click(screen.getByRole('button')); testMinimumOptionsMenu(); expect( screen.getByText('Cancel Patrol') ).toBeInTheDocument(); - expect( screen.getByText('close-icon.svg') ).toBeInTheDocument(); + expect( screen.getByTestId('close-icon') ).toBeInTheDocument(); expect( screen.getByText('Start Patrol') ).toBeInTheDocument(); - expect( screen.getByText('play-circle.svg') ).toBeInTheDocument(); + expect( screen.getByTestId('play-icon') ).toBeInTheDocument(); }); - test('renders restore menu option for a cancelled patrol', () => { + test('renders restore menu option for a cancelled patrol', async () => { renderMenuWithCancelledPatrol(); - userEvent.click(screen.getByRole('button')); + await userEvent.click(screen.getByRole('button')); testMinimumOptionsMenu(); - expect( screen.getByText('close-icon.svg') ).toBeInTheDocument(); + expect( screen.getByTestId('close-icon') ).toBeInTheDocument(); expect( screen.getByText('Restore Patrol') ).toBeInTheDocument(); }); - test('restores a cancelled patrol using menu option', () => { + test('restores a cancelled patrol using menu option', async () => { const onPatrolChange = jest.fn(); renderMenuWithCancelledPatrol({ onPatrolChange }); - userEvent.click(screen.getByRole('button')); - userEvent.click(screen.getByText('Restore Patrol')); + await userEvent.click(screen.getByRole('button')); + await userEvent.click(screen.getByText('Restore Patrol')); expect(onPatrolChange).toHaveBeenCalledWith({ patrol_segments: [{ time_range: { end_time: null } }], @@ -127,7 +127,7 @@ describe('', () => { }); }); - test('starts a patrol using menu option', () => { + test('starts a patrol using menu option', async () => { const mockedDate = '2024-03-06T17:59:49.837Z'; jest.useFakeTimers('modern'); jest.setSystemTime(new Date(mockedDate)); @@ -135,8 +135,10 @@ describe('', () => { const onPatrolChange = jest.fn(); renderPatrolMenu({ ...initialProps, onPatrolChange }, storeWithUpdatePermissions); - userEvent.click(screen.getByRole('button')); - userEvent.click(screen.getByText('Start Patrol')); + const user = userEvent.setup({ delay: null }); + + await user.click(screen.getByRole('button')); + await user.click(screen.getByText('Start Patrol')); expect(onPatrolChange).toHaveBeenCalledWith({ patrol_segments: [{ time_range: { end_time: null, start_time: mockedDate } }], diff --git a/src/PatrolStartStopLayer/index.js b/src/PatrolStartStopLayer/index.js index 703a2722b..baa0e7555 100644 --- a/src/PatrolStartStopLayer/index.js +++ b/src/PatrolStartStopLayer/index.js @@ -1,28 +1,14 @@ -import React, { Fragment, memo } from 'react'; +import React, { memo } from 'react'; +import { useSelector } from 'react-redux'; -import { connect } from 'react-redux'; - -import { withMap } from '../EarthRangerMap'; import { selectPatrolsWithTracks } from '../selectors/patrols'; import StartStopLayer from './layer'; +const PatrolStartStopLayer = () => { + const patrolsWithTracks = useSelector(selectPatrolsWithTracks); -const PatrolStartStopLayer = ({ patrolsWithTracks }) => { - const onSymbolClick = () => {}; - - return - {patrolsWithTracks - .map((patrol, index) => )} - ; - + return patrolsWithTracks.map((patrol, index) => ); }; -const mapStateToProps = (state) => ({ - patrolsWithTracks: selectPatrolsWithTracks(state), -}); - - -export default connect(mapStateToProps, null)(withMap( - memo(PatrolStartStopLayer), -)); +export default memo(PatrolStartStopLayer); diff --git a/src/PatrolStartStopLayer/layer.js b/src/PatrolStartStopLayer/layer.js index 464c15387..359a42fd7 100644 --- a/src/PatrolStartStopLayer/layer.js +++ b/src/PatrolStartStopLayer/layer.js @@ -1,13 +1,13 @@ -import React, { memo, useEffect, useMemo, useState } from 'react'; +import React, { memo, useContext, useEffect, useMemo, useState } from 'react'; import { connect } from 'react-redux'; import { addMapImage } from '../utils/map'; import { calcImgIdFromUrlForMapImages } from '../utils/img'; import { selectPatrolData } from '../selectors/patrols'; import { DEFAULT_SYMBOL_PAINT, LAYER_IDS } from '../constants'; -import { withMap } from '../EarthRangerMap'; import { uuid } from '../utils/string'; import LabeledPatrolSymbolLayer from '../LabeledPatrolSymbolLayer'; +import { MapContext } from '../App'; import withMapViewConfig from '../WithMapViewConfig'; import useMapSources from '../hooks/useMapSources'; import useMapLayers from '../hooks/useMapLayers'; @@ -46,8 +46,8 @@ const textLayout = { const symbolFilter = ['==', ['geometry-type'], 'Point']; -const StartStopLayer = (props) => { - const { patrolData, map, ...rest } = props; +const StartStopLayer = ({ patrolData, ...rest }) => { + const map = useContext(MapContext); const [instanceId] = useState(uuid()); const layerId = `${PATROL_SYMBOLS}-${instanceId}`; @@ -116,4 +116,4 @@ const makeMapStateToProps = () => { }; -export default connect(makeMapStateToProps, null)(memo(withMap(withMapViewConfig(StartStopLayer)))); +export default connect(makeMapStateToProps, null)(memo(withMapViewConfig(StartStopLayer))); diff --git a/src/PatrolTrackControls/index.test.js b/src/PatrolTrackControls/index.test.js index e3c3dd470..d3b31008f 100644 --- a/src/PatrolTrackControls/index.test.js +++ b/src/PatrolTrackControls/index.test.js @@ -59,7 +59,7 @@ describe('patrols with leader, location and track data', () => { test('toggling a patrol track on when clicking the "jump to location button"', async () => { const jumpButton = await screen.findByTestId(`patrol-list-item-jump-btn-${testPatrol.id}`); - userEvent.click(jumpButton); + await userEvent.click(jumpButton); const actions = store.getActions(); @@ -71,7 +71,7 @@ describe('patrols with leader, location and track data', () => { test('toggling a patrol leader\'s track on when clicking the "jump to location button"', async () => { const jumpButton = await screen.findByTestId(`patrol-list-item-jump-btn-${testPatrol.id}`); - userEvent.click(jumpButton); + await userEvent.click(jumpButton); const actions = store.getActions(); diff --git a/src/PickMapLocationButton/index.js b/src/PickMapLocationButton/index.js index 62ecc1a3f..7fb0ffd15 100644 --- a/src/PickMapLocationButton/index.js +++ b/src/PickMapLocationButton/index.js @@ -83,7 +83,7 @@ const PickMapLocationButton = ({ type="button" {...otherProps} > - {renderContent?.() || } + {renderContent?.() || } {showInstructionsPopup && isPickingMapLocation && { ); - test('configures the button with other props', () => { + test('configures the button with other props', async () => { renderPickMapLocationButton({ className: 'className' }); expect(screen.getByLabelText('Pick a location on the map')).toHaveClass('className'); }); - test('starts the picking location mode when the user clicks the button', () => { + test('starts the picking location mode when the user clicks the button', async () => { const onClick = jest.fn(); renderPickMapLocationButton({ onClick }); @@ -84,7 +84,7 @@ describe('PickMapLocationButton', () => { expect(hideSideBar).not.toHaveBeenCalled(); expect(onClick).not.toHaveBeenCalled(); - userEvent.click(screen.getByLabelText('Pick a location on the map')); + await userEvent.click(screen.getByLabelText('Pick a location on the map')); expect(setIsPickingLocation).toHaveBeenCalledTimes(1); expect(setIsPickingLocation).toHaveBeenCalledWith(true); @@ -94,10 +94,10 @@ describe('PickMapLocationButton', () => { expect(onClick).toHaveBeenCalledTimes(1); }); - test('picks a location by clicking the map', () => { + test('picks a location by clicking the map', async () => { renderPickMapLocationButton(); - userEvent.click(screen.getByLabelText('Pick a location on the map')); + await userEvent.click(screen.getByLabelText('Pick a location on the map')); expect(setIsPickingLocation).toHaveBeenCalledTimes(1); expect(setIsPickingLocation).toHaveBeenCalledWith(true); @@ -117,11 +117,11 @@ describe('PickMapLocationButton', () => { expect(onPick.mock.calls[0][0].lngLat).toEqual({ lng: 10.012657, lat: 11.666666 }); }); - test('cancels the picking operation when the user presses a key', () => { + test('cancels the picking operation when the user presses a key', async () => { const onCancel = jest.fn(); renderPickMapLocationButton({ onCancel }); - userEvent.click(screen.getByLabelText('Pick a location on the map')); + await userEvent.click(screen.getByLabelText('Pick a location on the map')); expect(setIsPickingLocation).toHaveBeenCalledTimes(1); expect(setIsPickingLocation).toHaveBeenCalledWith(true); @@ -130,7 +130,7 @@ describe('PickMapLocationButton', () => { expect(showSideBar).not.toHaveBeenCalled(); expect(onCancel).not.toHaveBeenCalled(); - userEvent.keyboard('{Escape}'); + await userEvent.keyboard('{Escape}'); expect(setIsPickingLocation).toHaveBeenCalledTimes(2); expect(setIsPickingLocation).toHaveBeenCalledWith(false); @@ -141,7 +141,7 @@ describe('PickMapLocationButton', () => { expect(onCancel).toHaveBeenCalledTimes(1); }); - test('renders the button content', () => { + test('renders the button content', async () => { renderPickMapLocationButton({ renderContent: () =>
    }); const button = screen.getByLabelText('Pick a location on the map'); @@ -149,9 +149,9 @@ describe('PickMapLocationButton', () => { expect(within(button).getByTestId('content')).toBeVisible(); }); - test('renders a default button content', () => { + test('renders a default button content', async () => { renderPickMapLocationButton(); - expect(screen.getByLabelText('Pick a location on the map')).toHaveTextContent('marker-feed.svg'); + expect(screen.getByTestId('location-icon')).toBeVisible(); }); }); diff --git a/src/Popup/index.js b/src/Popup/index.js index 79ee6c2da..eb4750a64 100644 --- a/src/Popup/index.js +++ b/src/Popup/index.js @@ -1,13 +1,14 @@ -import React, { Fragment, useEffect, useRef } from 'react'; -import { withMap } from '../EarthRangerMap'; +import React, { useContext, useEffect, useRef } from 'react'; import { createPortal } from 'react-dom'; import mapboxgl from 'mapbox-gl'; - import xor from 'lodash/xor'; -const Popup = ({ className = '', trackPointer = false, offset, coordinates, anchor, children, map }) => { - const classNameRef = useRef(''); +import { MapContext } from '../App'; +const Popup = ({ className = '', trackPointer = false, offset, coordinates, anchor, children }) => { + const map = useContext(MapContext); + + const classNameRef = useRef(''); const popupRef = useRef(null); const popupContainerRef = useRef(document.createElement('div')); @@ -73,9 +74,9 @@ const Popup = ({ className = '', trackPointer = false, offset, coordinates, anch }, []); return createPortal( - {children}, + <>{children}, popupContainerRef.current ); }; -export default withMap(Popup); +export default Popup; diff --git a/src/PrintTitle/index.test.js b/src/PrintTitle/index.test.js index bcff5b869..0ae06f03d 100644 --- a/src/PrintTitle/index.test.js +++ b/src/PrintTitle/index.test.js @@ -1,5 +1,4 @@ import React from 'react'; -import '@testing-library/jest-dom/extend-expect'; import { Provider } from 'react-redux'; import { render, screen } from '@testing-library/react'; import configureStore from 'redux-mock-store'; diff --git a/src/PrioritySelect/index.test.js b/src/PrioritySelect/index.test.js index bfb1fd6ce..6b55ab6fa 100644 --- a/src/PrioritySelect/index.test.js +++ b/src/PrioritySelect/index.test.js @@ -18,38 +18,38 @@ describe('PrioritySelect', () => { render() ); - it('should render all report priority levels', () => { + it('should render all report priority levels', async () => { renderPrioritySelect(); const list = screen.getByText(selectedPriority.display); - userEvent.click(list); + await userEvent.click(list); REPORT_PRIORITIES.forEach(({ key }) => { const currentTestId = `priority-select-${key}`; expect( screen.getByTestId(currentTestId) ).toBeInTheDocument(); }); }); - it('should return selected priority level', () => { + it('should return selected priority level', async () => { const onChangePartialArgs = { action: 'select-option' }; const [ highLevel ] = REPORT_PRIORITIES; const { display } = highLevel; const onChange = jest.fn(); renderPrioritySelect({ ...initialProps, onChange }); const list = screen.getByText(display); - userEvent.click(list); + await userEvent.click(list); expect(onChange).not.toHaveBeenCalled(); const option = screen.getByTestId(testId); - userEvent.click(option); + await userEvent.click(option); expect(onChange).toHaveBeenCalledTimes(1); expect(onChange).toHaveBeenCalledWith(highLevel, onChangePartialArgs); }); - it('closes the menu when pressing escape', () => { + it('closes the menu when pressing escape', async () => { renderPrioritySelect(); const list = screen.getByText(selectedPriority.display); - userEvent.click(list); + await userEvent.click(list); - userEvent.keyboard('{Escape}'); + await userEvent.keyboard('{Escape}'); REPORT_PRIORITIES.forEach(({ key }) => { const currentTestId = `priority-select-${key}`; diff --git a/src/ProfilePINModal/index.js b/src/ProfilePINModal/index.js index 957a5ecbd..3263ca8ea 100644 --- a/src/ProfilePINModal/index.js +++ b/src/ProfilePINModal/index.js @@ -9,7 +9,7 @@ import ConfirmationCheck from '../ConfirmationCheck'; import * as styles from './styles.module.scss'; const PIN_LENGTH = 4; -const PIN_VALIDATION_RULES = /^[0-9]$/; +const PIN_VALIDATION_RULES = '[0-9]'; const ProfilePINModal = ({ onSuccess, profile }) => { const { t } = useTranslation('top-bar', { keyPrefix: 'profilePINModal' }); diff --git a/src/ProfilePINModal/index.test.js b/src/ProfilePINModal/index.test.js index e2c45e907..5a55db9de 100644 --- a/src/ProfilePINModal/index.test.js +++ b/src/ProfilePINModal/index.test.js @@ -1,6 +1,7 @@ import React from 'react'; +import userEvent from '@testing-library/user-event'; -import { fireEvent, render, screen, waitFor } from '../test-utils'; +import { render, screen, waitFor } from '../test-utils'; import ProfilePINModal from './'; describe('ProfilePINModal', () => { @@ -26,13 +27,12 @@ describe('ProfilePINModal', () => { test('entering the correct PIN invokes the onSuccess callback', async () => { const pinInputs = await screen.findAllByRole('input'); - const splitPin = profile.pin.split(''); - expect(onSuccess).not.toHaveBeenCalled(); - splitPin.forEach((char, index) => { - fireEvent.keyDown(pinInputs[index], { key: char, code: `key${char}` }); - }); + await userEvent.type(pinInputs[0], profile.pin[0]); + await userEvent.type(pinInputs[1], profile.pin[1]); + await userEvent.type(pinInputs[2], profile.pin[2]); + await userEvent.type(pinInputs[3], profile.pin[3]); await waitFor(() => { expect(onSuccess).toHaveBeenCalled(); @@ -40,28 +40,25 @@ describe('ProfilePINModal', () => { }); describe('entering the incorrect PIN', () => { - let pinInputs; - - beforeEach(async () => { - pinInputs = await screen.findAllByRole('input'); + test('showing an error message', async () => { + const pinInputs = await screen.findAllByRole('input'); - pinInputs.forEach((input) => { - fireEvent.keyDown(input, { key: '1', code: 'key1' }); - }); + await userEvent.type(pinInputs[0], '1'); + await userEvent.type(pinInputs[1], '1'); + await userEvent.type(pinInputs[2], '1'); + await userEvent.type(pinInputs[3], '1'); - }); - - test('showing an error message', () => { expect(screen.queryByText('Incorrect PIN')).toBeInTheDocument(); }); - test('changing the value after an error clears the error message', () => { - fireEvent.keyDown(pinInputs[1], { - key: 'Backspace', - keyCode: 8, - charCode: 8, - which: 8, - }); + test('changing the value after an error clears the error message', async () => { + const pinInputs = await screen.findAllByRole('input'); + + await userEvent.type(pinInputs[0], '1'); + await userEvent.type(pinInputs[1], '1'); + await userEvent.type(pinInputs[2], '1'); + await userEvent.type(pinInputs[3], '1'); + await userEvent.type(pinInputs[3], '{backspace}'); expect(screen.queryByText('Incorrect PIN')).not.toBeInTheDocument(); }); diff --git a/src/QuickLinks/index.test.js b/src/QuickLinks/index.test.js index ed4273731..4dc3181da 100644 --- a/src/QuickLinks/index.test.js +++ b/src/QuickLinks/index.test.js @@ -68,7 +68,7 @@ describe('ReportManager - QuickLinks', () => { expect(onClick).toHaveBeenCalledTimes(0); const anchor = await screen.queryByTestId('quickLinks-anchor-anchor1'); - userEvent.click(anchor); + await userEvent.click(anchor); expect(onClickAnchor).toHaveBeenCalledTimes(1); expect(onClickAnchor).toHaveBeenCalledWith('anchor1'); diff --git a/src/ReportGeometryDrawer/CancelationConfirmationModal/index.test.js b/src/ReportGeometryDrawer/CancelationConfirmationModal/index.test.js index 86daa83a0..506215a76 100644 --- a/src/ReportGeometryDrawer/CancelationConfirmationModal/index.test.js +++ b/src/ReportGeometryDrawer/CancelationConfirmationModal/index.test.js @@ -42,7 +42,7 @@ describe('CancelationConfirmationModal', () => { expect(setMapDrawingData).toHaveBeenCalledTimes(0); const continueEditingButton = await screen.findByText('Continue Editing'); - userEvent.click(continueEditingButton); + await userEvent.click(continueEditingButton); expect(onHide).toHaveBeenCalledTimes(1); expect(setIsPickingLocation).toHaveBeenCalledTimes(0); @@ -55,7 +55,7 @@ describe('CancelationConfirmationModal', () => { expect(setMapDrawingData).toHaveBeenCalledTimes(0); const discartButton = await screen.findByText('Discard'); - userEvent.click(discartButton); + await userEvent.click(discartButton); expect(onHide).toHaveBeenCalledTimes(1); expect(setIsPickingLocation).toHaveBeenCalledTimes(1); diff --git a/src/ReportGeometryDrawer/Footer/index.test.js b/src/ReportGeometryDrawer/Footer/index.test.js index 1ad7a7156..9eb6dc773 100644 --- a/src/ReportGeometryDrawer/Footer/index.test.js +++ b/src/ReportGeometryDrawer/Footer/index.test.js @@ -19,7 +19,7 @@ describe('Footer', () => { expect(onCancel).toHaveBeenCalledTimes(0); const cancelButton = await screen.findByText('Cancel'); - userEvent.click(cancelButton); + await userEvent.click(cancelButton); expect(onCancel).toHaveBeenCalledTimes(1); }); @@ -28,7 +28,7 @@ describe('Footer', () => { expect(onSave).toHaveBeenCalledTimes(0); const saveButton = await screen.findByText('Save'); - userEvent.click(saveButton); + await userEvent.click(saveButton); expect(onSave).toHaveBeenCalledTimes(1); }); @@ -39,7 +39,7 @@ describe('Footer', () => { expect((await screen.queryByRole('tooltip'))).toBeNull(); const saveButton = await screen.findByText('Save'); - userEvent.hover(saveButton); + await userEvent.hover(saveButton); expect((await screen.findByRole('tooltip'))).toHaveTextContent('Only closed shapes can be saved'); }); @@ -50,7 +50,7 @@ describe('Footer', () => { expect((await screen.queryByRole('tooltip'))).toBeNull(); const saveButton = await screen.findByText('Save'); - userEvent.hover(saveButton); + await userEvent.hover(saveButton); expect((await screen.findByRole('tooltip'))).toHaveTextContent('Segments of the shape cannot intersect'); }); @@ -61,7 +61,7 @@ describe('Footer', () => { expect((await screen.queryByRole('tooltip'))).toBeNull(); const saveButton = await screen.findByText('Save'); - userEvent.hover(saveButton); + await userEvent.hover(saveButton); expect((await screen.queryByRole('tooltip'))).toBeNull(); }); diff --git a/src/ReportGeometryDrawer/index.test.js b/src/ReportGeometryDrawer/index.test.js index 0308f3ab8..9a4a1b078 100644 --- a/src/ReportGeometryDrawer/index.test.js +++ b/src/ReportGeometryDrawer/index.test.js @@ -2,7 +2,7 @@ import React from 'react'; import { Provider } from 'react-redux'; import userEvent from '@testing-library/user-event'; -import { cleanup, render, screen, waitFor } from '../test-utils'; +import { act, cleanup, render, screen, waitFor } from '../test-utils'; import { createMapMock } from '../__test-helpers/mocks'; import { setIsPickingLocation } from '../ducks/map-ui'; import { MapContext } from '../App'; @@ -46,8 +46,6 @@ describe('ReportGeometryDrawer', () => { const setMapDrawingData = jest.fn(); let map, setIsPickingLocationMock, store; beforeEach(() => { - jest.useFakeTimers(); - setIsPickingLocationMock = jest.fn(() => () => {}); setIsPickingLocation.mockImplementation(setIsPickingLocationMock); @@ -77,31 +75,39 @@ describe('ReportGeometryDrawer', () => { test('shows the information modal', async () => { expect((await screen.queryByText('Creating A Report Area'))).toBeNull(); - const informationIcon = await screen.findByText('information.svg'); - userEvent.click(informationIcon); + const informationIcon = await screen.findByTestId('information-icon'); + await userEvent.click(informationIcon); expect((await screen.findByText('Creating An Event Area'))).toBeDefined(); }); test('opens the cancellation confirmation modal when pressing Escape if user made a change', async () => { + jest.useFakeTimers(); + map.__test__.fireHandlers('click', { lngLat: { lng: 87, lat: 54 } }); - jest.runOnlyPendingTimers(); + act(() => jest.runOnlyPendingTimers()); + + jest.useRealTimers(); expect((await screen.queryByText('Discard Changes'))).toBeNull(); - userEvent.keyboard('{Escape}'); + await userEvent.keyboard('{Escape}'); expect((await screen.findByText('Discard Changes'))).toBeDefined(); }); test('opens the cancellation confirmation modal when clicking Cancel if user made a change', async () => { + jest.useFakeTimers(); + map.__test__.fireHandlers('click', { lngLat: { lng: 87, lat: 54 } }); - jest.runOnlyPendingTimers(); + act(() => jest.runOnlyPendingTimers()); + + jest.useRealTimers(); expect((await screen.queryByText('Discard Changes'))).toBeNull(); const cancelButton = await screen.findByText('Cancel'); - userEvent.click(cancelButton); + await userEvent.click(cancelButton); expect((await screen.findByText('Discard Changes'))).toBeDefined(); }); @@ -110,7 +116,7 @@ describe('ReportGeometryDrawer', () => { expect((await screen.queryByText('Discard Changes'))).toBeNull(); expect(setIsPickingLocation).toHaveBeenCalledTimes(0); - userEvent.keyboard('{Escape}'); + await userEvent.keyboard('{Escape}'); expect((await screen.queryByText('Discard Changes'))).toBeNull(); expect(setIsPickingLocation).toHaveBeenCalledTimes(1); @@ -118,12 +124,12 @@ describe('ReportGeometryDrawer', () => { }); test('does not open the cancellation confirmation modal if there is another modal showing', async () => { - const informationIcon = await screen.findByText('information.svg'); - userEvent.click(informationIcon); + const informationIcon = await screen.findByTestId('information-icon'); + await userEvent.click(informationIcon); expect((await screen.queryByText('Discard Changes'))).toBeNull(); - userEvent.keyboard('{Escape}'); + await userEvent.keyboard('{Escape}'); expect((await screen.queryByText('Discard Changes'))).toBeNull(); }); @@ -133,49 +139,59 @@ describe('ReportGeometryDrawer', () => { }); test('enables the save button if user clicks enter after drawing a polygon', async () => { + jest.useFakeTimers(); + map.__test__.fireHandlers('click', { lngLat: { lng: 87, lat: 54 } }); - jest.runOnlyPendingTimers(); + act(() => jest.runOnlyPendingTimers()); map.__test__.fireHandlers('click', { lngLat: { lng: 88, lat: 54 } }); - jest.runOnlyPendingTimers(); + act(() => jest.runOnlyPendingTimers()); map.__test__.fireHandlers('click', { lngLat: { lng: 88, lat: 55 } }); - jest.runOnlyPendingTimers(); + act(() => jest.runOnlyPendingTimers()); + + jest.useRealTimers(); const saveButton = await screen.findByText('Save'); expect(saveButton).toHaveClass('disabled'); - userEvent.keyboard('{Enter}'); + await userEvent.keyboard('{Enter}'); expect(saveButton).not.toHaveClass('disabled'); }); test('enables the save button if user double clicks the map after drawing a polygon', async () => { + jest.useFakeTimers(); + map.__test__.fireHandlers('click', { lngLat: { lng: 87, lat: 54 } }); - jest.runOnlyPendingTimers(); + act(() => jest.runOnlyPendingTimers()); map.__test__.fireHandlers('click', { lngLat: { lng: 88, lat: 54 } }); - jest.runOnlyPendingTimers(); + act(() => jest.runOnlyPendingTimers()); map.__test__.fireHandlers('click', { lngLat: { lng: 88, lat: 55 } }); - jest.runOnlyPendingTimers(); + act(() => jest.runOnlyPendingTimers()); const saveButton = await screen.findByText('Save'); expect(saveButton).toHaveClass('disabled'); map.__test__.fireHandlers('dblclick', { lngLat: { lng: 87, lat: 55 } }); - jest.runOnlyPendingTimers(); + act(() => jest.runOnlyPendingTimers()); await waitFor(() => { expect(saveButton).not.toHaveClass('disabled'); }); + + jest.useRealTimers(); }); test('enables the save button if user clicks the initial point after drawing a polygon', async () => { + jest.useFakeTimers(); + map.__test__.fireHandlers('click', { lngLat: { lng: 87, lat: 54 } }); - jest.runOnlyPendingTimers(); + act(() => jest.runOnlyPendingTimers()); map.__test__.fireHandlers('click', { lngLat: { lng: 88, lat: 54 } }); - jest.runOnlyPendingTimers(); + act(() => jest.runOnlyPendingTimers()); map.__test__.fireHandlers('click', { lngLat: { lng: 88, lat: 55 } }); - jest.runOnlyPendingTimers(); + act(() => jest.runOnlyPendingTimers()); const saveButton = await screen.findByText('Save'); @@ -183,11 +199,13 @@ describe('ReportGeometryDrawer', () => { map.queryRenderedFeatures.mockImplementation(() => [{ properties: { pointIndex: 0 } }]); map.__test__.fireHandlers('click', { lngLat: { lng: 87, lat: 54 } }); - jest.runOnlyPendingTimers(); + act(() => jest.runOnlyPendingTimers()); await waitFor(() => { expect(saveButton).not.toHaveClass('disabled'); }); + + jest.useRealTimers(); }); test('disables the save button if user closes an invalid polygon', async () => { @@ -202,38 +220,46 @@ describe('ReportGeometryDrawer', () => { ); + jest.useFakeTimers(); + map.__test__.fireHandlers('click', { lngLat: { lng: 87, lat: 54 } }); - jest.runOnlyPendingTimers(); + act(() => jest.runOnlyPendingTimers()); map.__test__.fireHandlers('click', { lngLat: { lng: 88, lat: 54 } }); - jest.runOnlyPendingTimers(); + act(() => jest.runOnlyPendingTimers()); map.__test__.fireHandlers('click', { lngLat: { lng: 88, lat: 55 } }); - jest.runOnlyPendingTimers(); + act(() => jest.runOnlyPendingTimers()); map.__test__.fireHandlers('click', { lngLat: { lng: 86, lat: 52 } }); - jest.runOnlyPendingTimers(); + act(() => jest.runOnlyPendingTimers()); + + jest.useRealTimers(); const saveButton = await screen.findByText('Save'); expect(saveButton).toHaveClass('disabled'); - userEvent.keyboard('{Enter}'); + await userEvent.keyboard('{Enter}'); expect(saveButton).toHaveClass('disabled'); }); test('sets to false the pickingLocation flag when saving', async () => { + jest.useFakeTimers(); + map.__test__.fireHandlers('click', { lngLat: { lng: 87, lat: 54 } }); - jest.runOnlyPendingTimers(); + act(() => jest.runOnlyPendingTimers()); map.__test__.fireHandlers('click', { lngLat: { lng: 88, lat: 54 } }); - jest.runOnlyPendingTimers(); + act(() => jest.runOnlyPendingTimers()); map.__test__.fireHandlers('click', { lngLat: { lng: 88, lat: 55 } }); - jest.runOnlyPendingTimers(); + act(() => jest.runOnlyPendingTimers()); + + jest.useRealTimers(); - userEvent.keyboard('{Enter}'); + await userEvent.keyboard('{Enter}'); expect(setIsPickingLocation).toHaveBeenCalledTimes(0); const saveButton = await screen.findByText('Save'); - userEvent.click(saveButton); + await userEvent.click(saveButton); expect(setIsPickingLocation).toHaveBeenCalledTimes(1); expect(setIsPickingLocation).toHaveBeenCalledWith(false); diff --git a/src/ReportManager/DetailsSection/AreaSelectorInput/GeometryPreview/index.test.js b/src/ReportManager/DetailsSection/AreaSelectorInput/GeometryPreview/index.test.js index 69a0fdf87..1db2a90c7 100644 --- a/src/ReportManager/DetailsSection/AreaSelectorInput/GeometryPreview/index.test.js +++ b/src/ReportManager/DetailsSection/AreaSelectorInput/GeometryPreview/index.test.js @@ -62,7 +62,7 @@ describe('GeometryPreview', () => { expect(onAreaSelectStart).toHaveBeenCalledTimes(0); const editAreaButton = await screen.findByTitle('Place geometry on map'); - userEvent.click(editAreaButton); + await userEvent.click(editAreaButton); expect(onAreaSelectStart).toHaveBeenCalledTimes(1); }); @@ -87,7 +87,7 @@ describe('GeometryPreview', () => { expect(onDeleteArea).toHaveBeenCalledTimes(0); const deleteAreaButton = await screen.findByTitle('Delete Area'); - userEvent.click(deleteAreaButton); + await userEvent.click(deleteAreaButton); expect(onDeleteArea).toHaveBeenCalledTimes(1); }); diff --git a/src/ReportManager/DetailsSection/AreaSelectorInput/index.js b/src/ReportManager/DetailsSection/AreaSelectorInput/index.js index e84cbe053..287102efa 100644 --- a/src/ReportManager/DetailsSection/AreaSelectorInput/index.js +++ b/src/ReportManager/DetailsSection/AreaSelectorInput/index.js @@ -151,7 +151,7 @@ const AreaSelectorInput = ({ event, onGeometryChange = null, originalEvent = nul onClick={onClickAreaControl} ref={locationInputAnchorRef} > - + {displayString} diff --git a/src/ReportManager/DetailsSection/AreaSelectorInput/index.test.js b/src/ReportManager/DetailsSection/AreaSelectorInput/index.test.js index cbbafc47a..776ef324e 100644 --- a/src/ReportManager/DetailsSection/AreaSelectorInput/index.test.js +++ b/src/ReportManager/DetailsSection/AreaSelectorInput/index.test.js @@ -114,7 +114,7 @@ describe('The AreaSelector input', () => { expect(setIsPickingLocation).toHaveBeenCalledTimes(0); const setAreaButton = await screen.getByTestId(CONTROL_SELECTOR); - userEvent.click(setAreaButton); + await userEvent.click(setAreaButton); await waitFor(() => { expect(setIsPickingLocation).toHaveBeenCalledTimes(1); @@ -141,7 +141,7 @@ describe('The AreaSelector input', () => { ); expect((await screen.findByText('Set event area'))).toBeDefined(); - expect((await screen.findByText('polygon.svg'))).toBeDefined(); + expect((await screen.findByTestId('polygon-icon'))).toBeDefined(); }); }); @@ -168,12 +168,12 @@ describe('The AreaSelector input', () => { ); const setAreaButton = await screen.getByTestId(CONTROL_SELECTOR); - userEvent.click(setAreaButton); + await userEvent.click(setAreaButton); expect(onGeometryChange).toHaveBeenCalledTimes(0); const deleteAreaButton = await screen.getByTitle('Delete Area'); - userEvent.click(deleteAreaButton); + await userEvent.click(deleteAreaButton); await waitFor(async () => { expect(onGeometryChange).toHaveBeenCalledTimes(1); diff --git a/src/ReportManager/DetailsSection/SchemaForm/fields/ChoiceList/index.test.js b/src/ReportManager/DetailsSection/SchemaForm/fields/ChoiceList/index.test.js index a346817cc..b4b3eae6b 100644 --- a/src/ReportManager/DetailsSection/SchemaForm/fields/ChoiceList/index.test.js +++ b/src/ReportManager/DetailsSection/SchemaForm/fields/ChoiceList/index.test.js @@ -143,9 +143,9 @@ describe('ReportManager - DetailsSection - SchemaForm - fields - ChoiceList', () expect(onFieldChange).toHaveBeenCalledTimes(0); - userEvent.type(screen.getByRole('combobox'), '{arrowdown}'); + await userEvent.type(screen.getByRole('combobox'), '{arrowdown}'); - userEvent.click(screen.getByText('EarthRanger System')); + await userEvent.click(screen.getByText('EarthRanger System')); expect(onFieldChange).toHaveBeenCalledTimes(1); expect(onFieldChange).toHaveBeenCalledWith('a-choice', '0d553bb7-5c4f-43d7-9b82-a561a668ae64'); @@ -162,17 +162,17 @@ describe('ReportManager - DetailsSection - SchemaForm - fields - ChoiceList', () const dropdown = screen.getByRole('combobox'); - userEvent.type(dropdown, '{arrowdown}'); + await userEvent.type(dropdown, '{arrowdown}'); - userEvent.click(screen.getByText('EarthRanger System')); + await userEvent.click(screen.getByText('EarthRanger System')); expect(onFieldChange).toHaveBeenCalledWith('a-choice', [ '0d553bb7-5c4f-43d7-9b82-a561a668ae64' ]); - userEvent.type(dropdown, '{arrowdown}'); + await userEvent.type(dropdown, '{arrowdown}'); - userEvent.click(screen.getByText('frank')); + await userEvent.click(screen.getByText('frank')); expect(onFieldChange).toHaveBeenCalledWith('a-choice', [ '0d9fbeea-5252-4723-ba59-ca696baef2d9' @@ -318,7 +318,7 @@ describe('ReportManager - DetailsSection - SchemaForm - fields - ChoiceList', () expect(onFieldChange).toHaveBeenCalledTimes(0); - userEvent.click(screen.getByText('EarthRanger System')); + await userEvent.click(screen.getByText('EarthRanger System')); expect(onFieldChange).toHaveBeenCalledTimes(1); expect(onFieldChange).toHaveBeenCalledWith('a-choice', '0d553bb7-5c4f-43d7-9b82-a561a668ae64'); @@ -338,13 +338,13 @@ describe('ReportManager - DetailsSection - SchemaForm - fields - ChoiceList', () expect(onFieldChange).toHaveBeenCalledTimes(0); - userEvent.click(screen.getByText('EarthRanger System')); + await userEvent.click(screen.getByText('EarthRanger System')); expect(onFieldChange).toHaveBeenCalledWith('a-choice', [ '0d553bb7-5c4f-43d7-9b82-a561a668ae64' ]); - userEvent.click(screen.getByText('frank')); + await userEvent.click(screen.getByText('frank')); expect(onFieldChange).toHaveBeenCalledWith('a-choice', [ '0d9fbeea-5252-4723-ba59-ca696baef2d9' diff --git a/src/ReportManager/DetailsSection/SchemaForm/fields/Collection/SortableList/Item/FormModal/index.test.js b/src/ReportManager/DetailsSection/SchemaForm/fields/Collection/SortableList/Item/FormModal/index.test.js index 04bf30155..aa308f9c3 100644 --- a/src/ReportManager/DetailsSection/SchemaForm/fields/Collection/SortableList/Item/FormModal/index.test.js +++ b/src/ReportManager/DetailsSection/SchemaForm/fields/Collection/SortableList/Item/FormModal/index.test.js @@ -49,27 +49,27 @@ describe('ReportManager - DetailsSection - SchemaForm - fields - Collection - So ); - test('shows the modal', () => { + test('shows the modal', async () => { renderFormModal({ breadcrumbs: [] }); expect(screen.getByLabelText('Item')).not.toHaveClass('noBackground'); expect(screen.getByLabelText('Item')).not.toHaveClass('hide'); }); - test('does not show the modal background if it is nested', () => { + test('does not show the modal background if it is nested', async () => { renderFormModal(); expect(screen.getByLabelText('Item')).toHaveClass('noBackground'); }); - test('hides the modal if they are disabled by the modals reducer', () => { + test('hides the modal if they are disabled by the modals reducer', async () => { store.view.modals.canShowModals = false; renderFormModal(); expect(screen.getByLabelText('Item')).toHaveClass('hide'); }); - test('shows the breadcrumbs', () => { + test('shows the breadcrumbs', async () => { renderFormModal(); const breadcrumbs = screen.getByLabelText('breadcrumb'); @@ -78,7 +78,7 @@ describe('ReportManager - DetailsSection - SchemaForm - fields - Collection - So expect(breadcrumbs).toHaveTextContent('Item 1Item 2Item 3'); }); - test('shows the left column when it is the only column', () => { + test('shows the left column when it is the only column', async () => { renderFormModal(); const leftColumn = screen.getByTestId('schema-form-collection-form-modal-left-column'); @@ -87,7 +87,7 @@ describe('ReportManager - DetailsSection - SchemaForm - fields - Collection - So expect(leftColumn).toHaveClass('fullWidth'); }); - test('shows the left column when there are two columns', () => { + test('shows the left column when there are two columns', async () => { renderFormModal({ columns: 2 }); const leftColumn = screen.getByTestId('schema-form-collection-form-modal-left-column'); @@ -96,19 +96,19 @@ describe('ReportManager - DetailsSection - SchemaForm - fields - Collection - So expect(leftColumn).toHaveClass('halfWidthLeft'); }); - test('does not show the right column if the section has one column', () => { + test('does not show the right column if the section has one column', async () => { renderFormModal(); expect(screen.queryByTestId('schema-form-collection-form-modal-right-column')).toBeNull(); }); - test('shows the right column if the section has two columns', () => { + test('shows the right column if the section has two columns', async () => { renderFormModal({ columns: 2 }); expect(screen.getByTestId('schema-form-collection-form-modal-right-column')).toBeVisible(); }); - test('renders the children', () => { + test('renders the children', async () => { renderFormModal(); expect(renderField).toHaveBeenCalledTimes(2); @@ -130,32 +130,32 @@ describe('ReportManager - DetailsSection - SchemaForm - fields - Collection - So ); }); - test('deletes the item when user clicks the trash icon', () => { + test('deletes the item when user clicks the trash icon', async () => { renderFormModal(); expect(onDeleteItem).toHaveBeenCalledTimes(0); - userEvent.click(screen.getByLabelText('Delete Item 3')); + await userEvent.click(screen.getByLabelText('Delete Item 3')); expect(onDeleteItem).toHaveBeenCalledTimes(1); }); - test('cancels the edition of the form when user clicks Cancel', () => { + test('cancels the edition of the form when user clicks Cancel', async () => { renderFormModal(); expect(onCancel).toHaveBeenCalledTimes(0); - userEvent.click(screen.getByText('Cancel')); + await userEvent.click(screen.getByText('Cancel')); expect(onCancel).toHaveBeenCalledTimes(1); }); - test('finishes the edition of the form when user clicks Done', () => { + test('finishes the edition of the form when user clicks Done', async () => { renderFormModal(); expect(onDone).toHaveBeenCalledTimes(0); - userEvent.click(screen.getByText('Done')); + await userEvent.click(screen.getByText('Done')); expect(onDone).toHaveBeenCalledTimes(1); }); diff --git a/src/ReportManager/DetailsSection/SchemaForm/fields/Collection/SortableList/Item/FormPreview/index.test.js b/src/ReportManager/DetailsSection/SchemaForm/fields/Collection/SortableList/Item/FormPreview/index.test.js index 19654183e..6a91642ec 100644 --- a/src/ReportManager/DetailsSection/SchemaForm/fields/Collection/SortableList/Item/FormPreview/index.test.js +++ b/src/ReportManager/DetailsSection/SchemaForm/fields/Collection/SortableList/Item/FormPreview/index.test.js @@ -58,31 +58,31 @@ describe('ReportManager - DetailsSection - SchemaForm - fields - Collection - So ); - test('shows the form preview as a drag overlay', () => { + test('shows the form preview as a drag overlay', async () => { renderFormPreview({ isDragOverlay: true }); expect(screen.getByTestId('schema-form-collection-item-form-preview')).toHaveClass('dragOverlay'); }); - test('does not show the form preview as a drag overlay', () => { + test('does not show the form preview as a drag overlay', async () => { renderFormPreview(); expect(screen.getByTestId('schema-form-collection-item-form-preview')).not.toHaveClass('dragOverlay'); }); - test('shows an error state if there are errors', () => { + test('shows an error state if there are errors', async () => { renderFormPreview({ errors: { 'field-1': { message: 'Error' } } }); expect(screen.getByTestId('schema-form-collection-item-form-preview')).toHaveClass('error'); }); - test('does not show an error state if there are no errors', () => { + test('does not show an error state if there are no errors', async () => { renderFormPreview(); expect(screen.getByTestId('schema-form-collection-item-form-preview')).not.toHaveClass('error'); }); - test('shows the preview of each field with its value', () => { + test('shows the preview of each field with its value', async () => { renderFormPreview(); expect(screen.getByText('Field 1')).toBeVisible(); @@ -91,7 +91,7 @@ describe('ReportManager - DetailsSection - SchemaForm - fields - Collection - So expect(screen.getByText('Value 2')).toBeVisible(); }); - test('shows an error state in the preview of erroneous fields', () => { + test('shows an error state in the preview of erroneous fields', async () => { renderFormPreview({ errors: { 'field-1': { message: 'Error' } } }); expect(screen.getByText('Field 1')).toHaveClass('error'); @@ -100,7 +100,7 @@ describe('ReportManager - DetailsSection - SchemaForm - fields - Collection - So expect(screen.getByText('Value 2')).not.toHaveClass('error'); }); - test('shows a jump to location button for location fields with values', () => { + test('shows a jump to location button for location fields with values', async () => { renderFormPreview({ fieldIds: ['field-1', 'field-2'], fields: { @@ -123,13 +123,13 @@ describe('ReportManager - DetailsSection - SchemaForm - fields - Collection - So expect(screen.getByLabelText('Jump to Field 2 location')).toBeVisible(); }); - test('does not show a jump to location button if fields are not of type location', () => { + test('does not show a jump to location button if fields are not of type location', async () => { renderFormPreview(); expect(screen.queryByLabelText('Jump to Field 2 location')).toBeNull(); }); - test('does not show a jump to location button for location fields without values', () => { + test('does not show a jump to location button for location fields without values', async () => { renderFormPreview({ fieldIds: ['field-1', 'field-2'], fields: { @@ -152,7 +152,7 @@ describe('ReportManager - DetailsSection - SchemaForm - fields - Collection - So expect(screen.queryByLabelText('Jump to Field 2 location')).toBeNull(); }); - test('jumps to the location of a location field when clicking the button and focuses its marker', () => { + test('jumps to the location of a location field when clicking the button and focuses its marker', async () => { renderFormPreview({ fieldIds: ['field-1', 'field-2'], fields: { @@ -175,7 +175,7 @@ describe('ReportManager - DetailsSection - SchemaForm - fields - Collection - So expect(jumpToLocationMock).not.toHaveBeenCalled(); expect(focusLocationMarker).not.toHaveBeenCalled(); - userEvent.click(screen.getByLabelText('Jump to Field 2 location')); + await userEvent.click(screen.getByLabelText('Jump to Field 2 location')); expect(jumpToLocationMock).toHaveBeenCalledTimes(1); expect(jumpToLocationMock).toHaveBeenCalledWith([10, 10], 20); @@ -183,7 +183,7 @@ describe('ReportManager - DetailsSection - SchemaForm - fields - Collection - So expect(focusLocationMarker).toHaveBeenCalledWith('field-2'); }); - test('does neither jump to the location of a location field when clicking the button nor focuses its marker if its a drag overlay', () => { + test('does neither jump to the location of a location field when clicking the button nor focuses its marker if its a drag overlay', async () => { renderFormPreview({ fieldIds: ['field-1', 'field-2'], fields: { @@ -204,13 +204,13 @@ describe('ReportManager - DetailsSection - SchemaForm - fields - Collection - So isDragOverlay: true, }); - userEvent.click(screen.getByLabelText('Jump to Field 2 location')); + await userEvent.click(screen.getByLabelText('Jump to Field 2 location')); expect(jumpToLocationMock).not.toHaveBeenCalled(); expect(focusLocationMarker).not.toHaveBeenCalled(); }); - test('blurs the location marker when the jump to location button is blurred', () => { + test('blurs the location marker when the jump to location button is blurred', async () => { renderFormPreview({ fieldIds: ['field-1', 'field-2'], fields: { @@ -230,7 +230,7 @@ describe('ReportManager - DetailsSection - SchemaForm - fields - Collection - So formData: { 'field-1': 'Value 1', 'field-2': { latitude: 10, longitude: 10 } }, }); - userEvent.click(screen.getByLabelText('Jump to Field 2 location')); + await userEvent.click(screen.getByLabelText('Jump to Field 2 location')); expect(blurLocationMarker).not.toHaveBeenCalled(); diff --git a/src/ReportManager/DetailsSection/SchemaForm/fields/Collection/SortableList/Item/index.test.js b/src/ReportManager/DetailsSection/SchemaForm/fields/Collection/SortableList/Item/index.test.js index c4af76f2a..15a354fc1 100644 --- a/src/ReportManager/DetailsSection/SchemaForm/fields/Collection/SortableList/Item/index.test.js +++ b/src/ReportManager/DetailsSection/SchemaForm/fields/Collection/SortableList/Item/index.test.js @@ -80,44 +80,44 @@ describe('ReportManager - DetailsSection - SchemaForm - fields - Collection - So ); - test('shows the item with the form preview open', () => { + test('shows the item with the form preview open', async () => { renderItem({ isFormPreviewOpen: true }); expect(screen.getByTestId('schema-form-collection-item')).toHaveClass('open'); }); - test('shows the item while it is being dragged', () => { + test('shows the item while it is being dragged', async () => { renderItem({ isDragging: true }); expect(screen.getByTestId('schema-form-collection-item')).toHaveClass('isDragging'); expect(document.body.style.cursor).toBe('grabbing'); }); - test('shows the item as a drag overlay', () => { + test('shows the item as a drag overlay', async () => { renderItem({ isDragOverlay: true }); expect(screen.getByTestId('schema-form-collection-item')).toHaveClass('dragOverlay'); - userEvent.click(screen.getByLabelText('Delete Value 1')); + await userEvent.click(screen.getByLabelText('Delete Value 1')); expect(onDelete).not.toHaveBeenCalled(); - userEvent.click(screen.getByLabelText('Edit Value 1')); + await userEvent.click(screen.getByLabelText('Edit Value 1')); expect(setIsFormModalOpen).not.toHaveBeenCalled(); - userEvent.click(screen.getAllByLabelText('Open the Value 1 form preview')[1]); + await userEvent.click(screen.getAllByLabelText('Open the Value 1 form preview')[1]); expect(setIsFormPreviewOpen).not.toHaveBeenCalled(); }); - test('shows an error state in the item if the children have errors', () => { + test('shows an error state in the item if the children have errors', async () => { renderItem({ errors: { 'field-1': { message: 'Error' } } }); expect(screen.getByTestId('schema-form-collection-item')).toHaveClass('error'); }); - test('shows the item normally', () => { + test('shows the item normally', async () => { renderItem(); expect(screen.getByTestId('schema-form-collection-item')).not.toHaveClass('open'); @@ -127,73 +127,73 @@ describe('ReportManager - DetailsSection - SchemaForm - fields - Collection - So expect(document.body.style.cursor).not.toBe('grabbing'); expect(onDelete).not.toHaveBeenCalled(); - userEvent.click(screen.getByLabelText('Delete Value 1')); + await userEvent.click(screen.getByLabelText('Delete Value 1')); expect(onDelete).toHaveBeenCalledTimes(1); expect(setIsFormModalOpen).not.toHaveBeenCalled(); - userEvent.click(screen.getByLabelText('Edit Value 1')); + await userEvent.click(screen.getByLabelText('Edit Value 1')); expect(setIsFormModalOpen).toHaveBeenCalledTimes(1); expect(setIsFormPreviewOpen).not.toHaveBeenCalled(); - userEvent.click(screen.getAllByLabelText('Open the Value 1 form preview')[1]); + await userEvent.click(screen.getAllByLabelText('Open the Value 1 form preview')[1]); expect(setIsFormPreviewOpen).toHaveBeenCalledTimes(1); }); - test('assigns an id to the item based on its position in the form data', () => { + test('assigns an id to the item based on its position in the form data', async () => { renderItem(); expect(screen.getByTestId('schema-form-collection-item')).toHaveAttribute('id', 'collection-1.0'); }); - test('does not assign an id to the item if the position index is not provided', () => { + test('does not assign an id to the item if the position index is not provided', async () => { renderItem({ index: undefined }); expect(screen.getByTestId('schema-form-collection-item')).not.toHaveAttribute('id'); }); - test('opens the form preview when the user clicks the title', () => { + test('opens the form preview when the user clicks the title', async () => { renderItem(); const titleButton = screen.getAllByLabelText('Open the Value 1 form preview')[0]; expect(setIsFormPreviewOpen).not.toHaveBeenCalled(); - userEvent.click(titleButton); + await userEvent.click(titleButton); expect(setIsFormPreviewOpen).toHaveBeenCalledTimes(1); expect(setIsFormPreviewOpen).toHaveBeenCalledWith(true); }); - test('closes the form preview when user clicks the title again', () => { + test('closes the form preview when user clicks the title again', async () => { renderItem({ isFormPreviewOpen: true }); const titleButton = screen.getAllByLabelText('Close the Value 1 form preview')[0]; expect(setIsFormPreviewOpen).not.toHaveBeenCalled(); - userEvent.click(titleButton); + await userEvent.click(titleButton); expect(setIsFormPreviewOpen).toHaveBeenCalledTimes(1); expect(setIsFormPreviewOpen).toHaveBeenCalledWith(false); }); - test('sets a default title with the collection name and its index if there is no identifier', () => { + test('sets a default title with the collection name and its index if there is no identifier', async () => { collectionDetails.itemIdentifier = undefined; renderItem(); expect(screen.getByText('Collection 1 2')).toBeVisible(); }); - test('sets a default title with the collection name and its index if the identifier field does not have a value', () => { + test('sets a default title with the collection name and its index if the identifier field does not have a value', async () => { renderItem({ formData: { 'field-1': '', 'field-2': 'Value 2' } }); expect(screen.getByText('Collection 1 2')).toBeVisible(); }); - test('sets the identifier field value as the title', () => { + test('sets the identifier field value as the title', async () => { renderItem(); const title = screen.getAllByText('Value 1')[0]; @@ -207,50 +207,50 @@ describe('ReportManager - DetailsSection - SchemaForm - fields - Collection - So expect(onDelete).not.toHaveBeenCalled(); - userEvent.click(screen.getByLabelText('Delete Value 1')); + await userEvent.click(screen.getByLabelText('Delete Value 1')); expect(onDelete).toHaveBeenCalledTimes(1); }); - test('opens the form modal when user clicks the edit button', () => { + test('opens the form modal when user clicks the edit button', async () => { renderItem(); expect(setIsFormModalOpen).not.toHaveBeenCalled(); - userEvent.click(screen.getByLabelText('Edit Value 1')); + await userEvent.click(screen.getByLabelText('Edit Value 1')); expect(setIsFormModalOpen).toHaveBeenCalledTimes(1); expect(setIsFormModalOpen).toHaveBeenCalledWith(true); }); - test('opens the form preview when user clicks the chevron', () => { + test('opens the form preview when user clicks the chevron', async () => { renderItem(); const chevronButton = screen.getAllByLabelText('Open the Value 1 form preview')[1]; expect(setIsFormPreviewOpen).not.toHaveBeenCalled(); - userEvent.click(chevronButton); + await userEvent.click(chevronButton); expect(setIsFormPreviewOpen).toHaveBeenCalledTimes(1); expect(setIsFormPreviewOpen).toHaveBeenCalledWith(true); }); - test('closes the form preview when user clicks the chevron again', () => { + test('closes the form preview when user clicks the chevron again', async () => { renderItem({ isFormPreviewOpen: true }); const chevronButton = screen.getAllByLabelText('Close the Value 1 form preview')[1]; expect(setIsFormPreviewOpen).not.toHaveBeenCalled(); - userEvent.click(chevronButton); + await userEvent.click(chevronButton); expect(setIsFormPreviewOpen).toHaveBeenCalledTimes(1); expect(setIsFormPreviewOpen).toHaveBeenCalledWith(false); }); - test('closes the form modal when the user clicks Done', () => { + test('closes the form modal when the user clicks Done', async () => { renderField.mockImplementation((id, value, onChange) => onChange(id, event.target.value)} @@ -260,13 +260,13 @@ describe('ReportManager - DetailsSection - SchemaForm - fields - Collection - So expect(setIsFormModalOpen).not.toHaveBeenCalled(); - userEvent.click(screen.getByText('Done')); + await userEvent.click(screen.getByText('Done')); expect(setIsFormModalOpen).toHaveBeenCalledTimes(1); expect(setIsFormModalOpen).toHaveBeenCalledWith(false); }); - test('changes the content of a child field and clears its error in the form modal', () => { + test('changes the content of a child field and clears its error in the form modal', async () => { renderField.mockImplementation((id, value, onChange) => onChange(id, event.target.value)} @@ -276,7 +276,7 @@ describe('ReportManager - DetailsSection - SchemaForm - fields - Collection - So expect(onChange).not.toHaveBeenCalled(); - userEvent.type(screen.getByTestId('field-1'), 'a'); + await userEvent.type(screen.getByTestId('field-1'), 'a'); expect(onChange).toHaveBeenCalledTimes(1); expect(onChange).toHaveBeenCalledWith( @@ -327,7 +327,7 @@ describe('ReportManager - DetailsSection - SchemaForm - fields - Collection - So expect(onChange).not.toHaveBeenCalled(); expect(setIsFormModalOpen).not.toHaveBeenCalled(); - userEvent.click(screen.getByText('Cancel')); + await userEvent.click(screen.getByText('Cancel')); expect(onChange).toHaveBeenCalledTimes(1); expect(onChange).toHaveBeenCalledWith({ 'field-1': 'Value 1', 'field-2': 'Value 2' }, undefined); @@ -343,7 +343,7 @@ describe('ReportManager - DetailsSection - SchemaForm - fields - Collection - So expect(onDelete).not.toHaveBeenCalled(); expect(setIsFormModalOpen).not.toHaveBeenCalled(); - userEvent.click(within(formModal).getByLabelText('Delete Value 1')); + await userEvent.click(within(formModal).getByLabelText('Delete Value 1')); expect(onDelete).toHaveBeenCalledTimes(1); expect(setIsFormModalOpen).toHaveBeenCalledTimes(1); diff --git a/src/ReportManager/DetailsSection/SchemaForm/fields/Collection/SortableList/SortableItem/index.test.js b/src/ReportManager/DetailsSection/SchemaForm/fields/Collection/SortableList/SortableItem/index.test.js index 31d509f09..f5e8278c2 100644 --- a/src/ReportManager/DetailsSection/SchemaForm/fields/Collection/SortableList/SortableItem/index.test.js +++ b/src/ReportManager/DetailsSection/SchemaForm/fields/Collection/SortableList/SortableItem/index.test.js @@ -83,7 +83,7 @@ describe('ReportManager - DetailsSection - SchemaForm - fields - Collection - So ); - test('registers as a sortable and injects the sortable properties to the item component', () => { + test('registers as a sortable and injects the sortable properties to the item component', async () => { renderSortableItem(); const item = screen.getByTestId('schema-form-collection-item'); @@ -94,12 +94,12 @@ describe('ReportManager - DetailsSection - SchemaForm - fields - Collection - So expect(item).toHaveAttribute('tabindex', '0'); expect(item).toHaveAttribute('style', 'transform: translate3d(0px, 0px, 0); transition: transition 1s, margin 300ms;'); - userEvent.type(item, 'a'); + await userEvent.type(item, 'a'); expect(listeners.onKeyDown).toHaveBeenCalledTimes(1); }); - test('does not inject the listeners if the form modal is open', () => { + test('does not inject the listeners if the form modal is open', async () => { renderSortableItem({ isFormModalOpen: true }); const item = screen.getByTestId('schema-form-collection-item'); @@ -107,7 +107,7 @@ describe('ReportManager - DetailsSection - SchemaForm - fields - Collection - So expect(useSortable).toHaveBeenCalledTimes(1); expect(useSortable).toHaveBeenCalledWith({ id: 1 }); - userEvent.type(item, 'a'); + await userEvent.type(item, 'a'); expect(listeners.onKeyDown).not.toHaveBeenCalled(); }); diff --git a/src/ReportManager/DetailsSection/SchemaForm/fields/Collection/index.test.js b/src/ReportManager/DetailsSection/SchemaForm/fields/Collection/index.test.js index f644951e5..0ef9b48ae 100644 --- a/src/ReportManager/DetailsSection/SchemaForm/fields/Collection/index.test.js +++ b/src/ReportManager/DetailsSection/SchemaForm/fields/Collection/index.test.js @@ -74,7 +74,7 @@ describe('ReportManager - DetailsSection - SchemaForm - fields - Collection', () ); - test('shows a valid collection when there are no errors', () => { + test('shows a valid collection when there are no errors', async () => { renderCollectionField(); const collection = screen.getByTestId('schema-form-collection-collection-1'); @@ -83,7 +83,7 @@ describe('ReportManager - DetailsSection - SchemaForm - fields - Collection', () expect(collection).not.toHaveAccessibleErrorMessage(); }); - test('shows an invalid collection when there are errors', () => { + test('shows an invalid collection when there are errors', async () => { renderCollectionField({ error: { message: 'Error' } }); const collection = screen.getByTestId('schema-form-collection-collection-1'); @@ -95,71 +95,71 @@ describe('ReportManager - DetailsSection - SchemaForm - fields - Collection', () expect(description).toHaveAttribute('aria-live', 'assertive'); }); - test('does not show an error state in the header if the collection and its items are all valid', () => { + test('does not show an error state in the header if the collection and its items are all valid', async () => { renderCollectionField(); expect(screen.getByTestId('schema-form-collection-header-collection-1')).not.toHaveClass('error'); }); - test('shows an error state in the header if the collection is invalid', () => { + test('shows an error state in the header if the collection is invalid', async () => { renderCollectionField({ error: { message: 'Error' } }); expect(screen.getByTestId('schema-form-collection-header-collection-1')).toHaveClass('error'); }); - test('shows an error state in the header if any collection item is invalid', () => { + test('shows an error state in the header if any collection item is invalid', async () => { renderCollectionField({ error: { 0: { 'field-1': 'Error' } } }); expect(screen.getByTestId('schema-form-collection-header-collection-1')).toHaveClass('error'); }); - test('sets the collection label with the number of items it continas', () => { + test('sets the collection label with the number of items it continas', async () => { renderCollectionField({ value: [{}, {}] }); expect(screen.getByLabelText('Collection 1 Label (2)')).toBeVisible(); }); - test('closes the collection list when the user clicks the chevron', () => { + test('closes the collection list when the user clicks the chevron', async () => { renderCollectionField(); const chevronButton = screen.getByLabelText('Close the Collection 1 Label list'); expect(chevronButton).toHaveAttribute('aria-expanded', 'true'); - userEvent.click(chevronButton); + await userEvent.click(chevronButton); expect(chevronButton).toHaveAttribute('aria-expanded', 'false'); }); - test('opens the collection list when the user clicks the chevron again', () => { + test('opens the collection list when the user clicks the chevron again', async () => { renderCollectionField(); const chevronButton = screen.getByLabelText('Close the Collection 1 Label list'); - userEvent.click(chevronButton); + await userEvent.click(chevronButton); expect(chevronButton).toHaveAttribute('aria-expanded', 'false'); - userEvent.click(chevronButton); + await userEvent.click(chevronButton); expect(chevronButton).toHaveAttribute('aria-expanded', 'true'); }); - test('shows an empty state if the collection does not have items', () => { + test('shows an empty state if the collection does not have items', async () => { renderCollectionField(); expect(screen.queryByTestId('schema-form-collection-item')).toBeNull(); expect(screen.getByTestId('schema-form-collection-list-empty-state')).toBeVisible(); }); - test('shows the list of items', () => { + test('shows the list of items', async () => { renderCollectionField({ value: [{}, {}] }); expect(screen.getAllByTestId('schema-form-collection-item')).toHaveLength(2); expect(screen.queryByTestId('schema-form-collection-list-empty-state')).toBeNull(); }); - test('focuses a location marker prefixed with the collection value and the item index', () => { + test('focuses a location marker prefixed with the collection value and the item index', async () => { renderField.mockImplementation((_id, _value, _onChange, _error, focusLocationMarker) => { focusLocationMarker('location-1'); @@ -167,13 +167,13 @@ describe('ReportManager - DetailsSection - SchemaForm - fields - Collection', () }); renderCollectionField({ value: [{}] }); - userEvent.click(screen.getByLabelText('Edit Item 1')); + await userEvent.click(screen.getByLabelText('Edit Item 1')); expect(focusLocationMarker).toHaveBeenCalled(); expect(focusLocationMarker).toHaveBeenCalledWith('collection-1.0.location-1'); }); - test('opens and closes the form preview of an item', () => { + test('opens and closes the form preview of an item', async () => { renderCollectionField({ value: [{}] }); const collectionItem = screen.getByTestId('schema-form-collection-item'); @@ -181,11 +181,11 @@ describe('ReportManager - DetailsSection - SchemaForm - fields - Collection', () expect(collectionItem).not.toHaveClass('open'); - userEvent.click(itemChevronButton); + await userEvent.click(itemChevronButton); expect(collectionItem).toHaveClass('open'); - userEvent.click(itemChevronButton); + await userEvent.click(itemChevronButton); expect(collectionItem).not.toHaveClass('open'); }); @@ -195,16 +195,16 @@ describe('ReportManager - DetailsSection - SchemaForm - fields - Collection', () expect(screen.queryByRole('dialog')).toBeNull(); - userEvent.click(screen.getByLabelText('Edit Item 1')); + await userEvent.click(screen.getByLabelText('Edit Item 1')); expect(screen.getByRole('dialog')).toBeVisible(); - userEvent.click(screen.getByText('Cancel')); + await userEvent.click(screen.getByText('Cancel')); expect(screen.queryByRole('dialog')).toBeNull(); }); - test('changes the collection value when there is a change in an item and updates the error from the item', () => { + test('changes the collection value when there is a change in an item and updates the error from the item', async () => { renderField.mockImplementation((id, value, onChange) => onChange(id, event.target.value)} @@ -215,11 +215,11 @@ describe('ReportManager - DetailsSection - SchemaForm - fields - Collection', () value: [{}, {}], }); - userEvent.click(screen.getByLabelText('Edit Item 1')); + await userEvent.click(screen.getByLabelText('Edit Item 1')); expect(onFieldChange).not.toHaveBeenCalled(); - userEvent.type(screen.getByTestId('field-1'), 'a'); + await userEvent.type(screen.getByTestId('field-1'), 'a'); expect(onFieldChange).toHaveBeenCalledTimes(1); expect(onFieldChange).toHaveBeenCalledWith( @@ -229,65 +229,65 @@ describe('ReportManager - DetailsSection - SchemaForm - fields - Collection', () ); }); - test('changes the collection value when an item is deleted from the item header and removes the collection error message and the errors from the deleted item', () => { + test('changes the collection value when an item is deleted from the item header and removes the collection error message and the errors from the deleted item', async () => { renderCollectionField({ error: { 0: { 'field-1': { message: 'Error' } }, message: 'Error' }, value: [{}, {}] }); expect(onFieldChange).not.toHaveBeenCalled(); - userEvent.click(screen.getByLabelText('Delete Item 1')); + await userEvent.click(screen.getByLabelText('Delete Item 1')); expect(onFieldChange).toHaveBeenCalledTimes(1); expect(onFieldChange).toHaveBeenCalledWith('collection-1', [{}], undefined); }); - test('changes the collection value when an item is deleted from the modal and removes the collection error message and the errors from the deleted item', () => { + test('changes the collection value when an item is deleted from the modal and removes the collection error message and the errors from the deleted item', async () => { renderCollectionField({ error: { 0: { 'field-1': { message: 'Error' } }, message: 'Error' }, value: [{}, {}] }); - userEvent.click(screen.getByLabelText('Edit Item 1')); + await userEvent.click(screen.getByLabelText('Edit Item 1')); const formModal = screen.getByRole('dialog'); expect(onFieldChange).not.toHaveBeenCalled(); - userEvent.click(within(formModal).getByLabelText('Delete Item 1')); + await userEvent.click(within(formModal).getByLabelText('Delete Item 1')); expect(onFieldChange).toHaveBeenCalledTimes(1); expect(onFieldChange).toHaveBeenCalledWith('collection-1', [{}], undefined); }); - test('shows the button text from the schema', () => { + test('shows the button text from the schema', async () => { renderCollectionField(); expect(screen.getByText('Add button text')).toBeVisible(); }); - test('shows a default button text if the schema does not define one', () => { + test('shows a default button text if the schema does not define one', async () => { details.buttonText = ''; renderCollectionField(); expect(screen.getByText('Add')).toBeVisible(); }); - test('disables the add button if there is a max items constraint and it was reached', () => { + test('disables the add button if there is a max items constraint and it was reached', async () => { details.maxItems = 3; renderCollectionField({ value: [{}, {}, {}] }); expect(screen.getByText('Add button text')).toBeDisabled(); }); - test('does not disable the add button if there is a max items constraint and it has not been reached', () => { + test('does not disable the add button if there is a max items constraint and it has not been reached', async () => { details.maxItems = 3; renderCollectionField({ value: [{}, {}] }); expect(screen.getByText('Add button text')).toBeEnabled(); }); - test('opens the form modal and changes the collection value when an item is added and removes its error message', () => { + test('opens the form modal and changes the collection value when an item is added and removes its error message', async () => { const { rerender } = renderCollectionField({ error: { 0: { 'field-1': { message: 'Error' } }, message: 'Error' }, value: [{}, {}] }); expect(onFieldChange).not.toHaveBeenCalled(); expect(screen.queryByRole('dialog')).toBeNull(); - userEvent.click(screen.getByText('Add button text')); + await userEvent.click(screen.getByText('Add button text')); expect(onFieldChange).toHaveBeenCalledTimes(1); expect(onFieldChange).toHaveBeenCalledWith( diff --git a/src/ReportManager/DetailsSection/SchemaForm/fields/DateTime/index.test.js b/src/ReportManager/DetailsSection/SchemaForm/fields/DateTime/index.test.js index 063182fa0..510994e28 100644 --- a/src/ReportManager/DetailsSection/SchemaForm/fields/DateTime/index.test.js +++ b/src/ReportManager/DetailsSection/SchemaForm/fields/DateTime/index.test.js @@ -134,14 +134,14 @@ describe('ReportManager - DetailsSection - SchemaForm - fields - DateTime', () = expect(onFieldChange).toHaveBeenCalledTimes(1); - userEvent.click(screen.getByLabelText('Open calendar')); - userEvent.click(screen.getByLabelText('Choose Monday, January 13th, 2020')); + await userEvent.click(screen.getByLabelText('Open calendar')); + await userEvent.click(screen.getByLabelText('Choose Monday, January 13th, 2020')); expect(onFieldChange).toHaveBeenCalledTimes(2); expect(onFieldChange).toHaveBeenCalledWith('date-time-1', `2020-01-13T06:30:00${getTimezoneOffsetString()}`); - userEvent.click(screen.getByLabelText('Open time options')); - userEvent.click(screen.getByText('08:00 AM')); + await userEvent.click(screen.getByLabelText('Open time options')); + await userEvent.click(screen.getByText('08:00 AM')); expect(onFieldChange).toHaveBeenCalledTimes(3); expect(onFieldChange).toHaveBeenCalledWith('date-time-1', `2020-01-01T08:00:00${getTimezoneOffsetString()}`); diff --git a/src/ReportManager/DetailsSection/SchemaForm/fields/Section/index.test.js b/src/ReportManager/DetailsSection/SchemaForm/fields/Section/index.test.js index ce8919555..c3c314252 100644 --- a/src/ReportManager/DetailsSection/SchemaForm/fields/Section/index.test.js +++ b/src/ReportManager/DetailsSection/SchemaForm/fields/Section/index.test.js @@ -33,20 +33,20 @@ describe('ReportManager - DetailsSection - SchemaForm - fields - Section', () => {...props} />); - test('does not show a header if the label is not defined', () => { + test('does not show a header if the label is not defined', async () => { details.label = ''; renderSectionField(); expect(screen.queryByRole('heading')).toBeNull(); }); - test('shows the header if the labes is defined', () => { + test('shows the header if the labes is defined', async () => { renderSectionField(); expect(screen.getByRole('heading')).toHaveTextContent('Section 1 Label'); }); - test('shows the left column when it is the only column', () => { + test('shows the left column when it is the only column', async () => { details.columns = 1; renderSectionField(); @@ -56,7 +56,7 @@ describe('ReportManager - DetailsSection - SchemaForm - fields - Section', () => expect(leftColumn).toHaveClass('fullWidth'); }); - test('shows the left column when there are two columns', () => { + test('shows the left column when there are two columns', async () => { renderSectionField(); const leftColumn = screen.getByTestId('schema-form-section-section-1-left-column'); @@ -65,20 +65,20 @@ describe('ReportManager - DetailsSection - SchemaForm - fields - Section', () => expect(leftColumn).toHaveClass('halfWidthLeft'); }); - test('does not show the right column if the section has one column', () => { + test('does not show the right column if the section has one column', async () => { details.columns = 1; renderSectionField(); expect(screen.queryByTestId('schema-form-section-section-1-right-column')).toBeNull(); }); - test('shows the right column if the section has two columns', () => { + test('shows the right column if the section has two columns', async () => { renderSectionField(); expect(screen.getByTestId('schema-form-section-section-1-right-column')).toBeVisible(); }); - test('renders the children', () => { + test('renders the children', async () => { renderSectionField(); expect(renderField).toHaveBeenCalledTimes(1); @@ -88,7 +88,7 @@ describe('ReportManager - DetailsSection - SchemaForm - fields - Section', () => expect(renderField.mock.calls[0][4]).toBe(focusLocationMarker); }); - test('applies changes in values and errors from the children', () => { + test('applies changes in values and errors from the children', async () => { renderField.mockImplementation((id, value, onChange) => onChange(id, event.target.value)} @@ -99,7 +99,7 @@ describe('ReportManager - DetailsSection - SchemaForm - fields - Section', () => expect(onFieldChange).not.toHaveBeenCalled(); expect(onFieldErrorsChange).not.toHaveBeenCalled(); - userEvent.type(screen.getByTestId('text-1'), 'a'); + await userEvent.type(screen.getByTestId('text-1'), 'a'); expect(onFieldChange).toHaveBeenCalledTimes(1); expect(onFieldChange).toHaveBeenCalledWith('text-1', 'Value 1a'); diff --git a/src/ReportManager/DetailsSection/SchemaForm/utils/useMapLocationMarkers/index.test.js b/src/ReportManager/DetailsSection/SchemaForm/utils/useMapLocationMarkers/index.test.js index ecdd837b3..4003d36cb 100644 --- a/src/ReportManager/DetailsSection/SchemaForm/utils/useMapLocationMarkers/index.test.js +++ b/src/ReportManager/DetailsSection/SchemaForm/utils/useMapLocationMarkers/index.test.js @@ -1,7 +1,7 @@ import React from 'react'; -import { renderHook } from '@testing-library/react-hooks'; import { waitFor } from '@testing-library/dom'; +import { renderHook } from '../../../../../test-utils'; import { addMapImage } from '../../../../../utils/map'; import { createMapMock } from '../../../../../__test-helpers/mocks'; import { MapContext } from '../../../../../App'; diff --git a/src/ReportManager/DetailsSection/SchemaForm/utils/useSchemaValidations/index.test.js b/src/ReportManager/DetailsSection/SchemaForm/utils/useSchemaValidations/index.test.js index 9f686f25c..13c57dc82 100644 --- a/src/ReportManager/DetailsSection/SchemaForm/utils/useSchemaValidations/index.test.js +++ b/src/ReportManager/DetailsSection/SchemaForm/utils/useSchemaValidations/index.test.js @@ -1,7 +1,7 @@ import React from 'react'; import { I18nextProvider } from 'react-i18next'; -import { renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '../../../../../test-utils'; import i18n from '../../../../../i18nForTests'; import useSchemaValidations from '.'; diff --git a/src/ReportManager/DetailsSection/index.test.js b/src/ReportManager/DetailsSection/index.test.js index 71600e92f..79bcb8199 100644 --- a/src/ReportManager/DetailsSection/index.test.js +++ b/src/ReportManager/DetailsSection/index.test.js @@ -11,7 +11,7 @@ import { MapContext } from '../../App'; import { MapDrawingToolsContext } from '../../MapDrawingTools/ContextProvider'; import { mockStore } from '../../__test-helpers/MockStore'; import patrolTypes from '../../__test-helpers/fixtures/patrol-types'; -import { render, screen, within } from '../../test-utils'; +import { render, screen, waitFor, within } from '../../test-utils'; import { report } from '../../__test-helpers/fixtures/reports'; import { TrackerContext } from '../../utils/analytics'; import { VALID_EVENT_GEOMETRY_TYPES } from '../../constants'; @@ -53,8 +53,6 @@ describe('ReportManager - DetailsSection', () => { let map, store, submitFormButtonRef; beforeEach(() => { - jest.useFakeTimers(); - map = createMapMock(); submitFormButtonRef = { current: {} }; @@ -125,12 +123,12 @@ describe('ReportManager - DetailsSection', () => { expect(screen.queryByTestId('reportManager-detailsSection-stateDropdownMenu')).toBeNull(); const stateDropdownToggleButton = screen.getByText('active'); - userEvent.click(stateDropdownToggleButton); + await userEvent.click(stateDropdownToggleButton); const stateDropdownMenu = screen.getByTestId('reportManager-detailsSection-stateDropdownMenu'); expect(stateDropdownMenu).toHaveClass('show'); - userEvent.click(stateDropdownToggleButton); + await userEvent.click(stateDropdownToggleButton); expect(stateDropdownMenu).not.toHaveClass('show'); }); @@ -139,12 +137,12 @@ describe('ReportManager - DetailsSection', () => { renderDetailsSection(); const stateDropdownToggleButton = screen.getByText('active'); - userEvent.click(stateDropdownToggleButton); + await userEvent.click(stateDropdownToggleButton); const stateDropdownMenu = screen.getByTestId('reportManager-detailsSection-stateDropdownMenu'); expect(stateDropdownMenu).toHaveClass('show'); - userEvent.keyboard('{Escape}'); + await userEvent.keyboard('{Escape}'); expect(stateDropdownMenu).not.toHaveClass('show'); }); @@ -153,7 +151,7 @@ describe('ReportManager - DetailsSection', () => { renderDetailsSection(); const stateDropdownToggleButton = screen.getByText('active'); - userEvent.click(stateDropdownToggleButton); + await userEvent.click(stateDropdownToggleButton); const stateDropdownMenu = screen.getByTestId('reportManager-detailsSection-stateDropdownMenu'); const stateDropdownItems = within(stateDropdownMenu).getAllByRole('button'); @@ -165,13 +163,13 @@ describe('ReportManager - DetailsSection', () => { test('changes the state of the event when selecting an item from the state dropdown', async () => { renderDetailsSection(); - userEvent.click(screen.getByText('active')); + await userEvent.click(screen.getByText('active')); const stateDropdownMenu = screen.getByTestId('reportManager-detailsSection-stateDropdownMenu'); expect(onReportStateChange).toHaveBeenCalledTimes(0); expect(stateDropdownMenu).toHaveClass('show'); - userEvent.click(screen.getByText('resolved')); + await userEvent.click(screen.getByText('resolved')); expect(onReportStateChange).toHaveBeenCalledTimes(1); expect(onReportStateChange.mock.calls[0][0]).toBe('resolved'); @@ -199,11 +197,11 @@ describe('ReportManager - DetailsSection', () => { test('changes the reporter of the event when selecting an item from the reported by select', async () => { renderDetailsSection(); - userEvent.click(screen.getByText('Reported By...')); + await userEvent.click(screen.getByText('Reported By...')); expect(onReportedByChange).toHaveBeenCalledTimes(0); - userEvent.click(screen.getByText('Canek')); + await userEvent.click(screen.getByText('Canek')); expect(onReportedByChange).toHaveBeenCalledTimes(1); expect(onReportedByChange).toHaveBeenCalledWith({ @@ -223,11 +221,11 @@ describe('ReportManager - DetailsSection', () => { test('changes the priority of the event when selecting an item from priority select', async () => { renderDetailsSection(); - userEvent.click(screen.getByText('Red')); + await userEvent.click(screen.getByText('Red')); expect(onPriorityChange).toHaveBeenCalledTimes(0); - userEvent.click(screen.getByText('Green')); + await userEvent.click(screen.getByText('Green')); expect(onPriorityChange).toHaveBeenCalledTimes(1); expect(onPriorityChange).toHaveBeenCalledWith( @@ -283,8 +281,8 @@ describe('ReportManager - DetailsSection', () => { test('changes the location of the event when selecting a location from the location selector input', async () => { renderDetailsSection(); - userEvent.click(screen.getByLabelText('Event Location')); - userEvent.click(screen.getByLabelText('Pick a location on the map')); + await userEvent.click(screen.getByLabelText('Event Location')); + await userEvent.click(screen.getByLabelText('Pick a location on the map')); expect(onReportLocationChange).toHaveBeenCalledTimes(0); @@ -309,15 +307,15 @@ describe('ReportManager - DetailsSection', () => { test('changes the date of the event when selecting an option from the date picker', async () => { renderDetailsSection(); - userEvent.click(screen.getByTestId('datePicker-input')); + await userEvent.click(screen.getByTestId('datePicker-input')); expect(onReportDateChange).not.toHaveBeenCalled(); const datePicker = await screen.findByTestId('reportManager-detailsSection-datePicker'); const datePickerOpenCalendarButton = await within(datePicker).findByLabelText('Open calendar'); - userEvent.click(datePickerOpenCalendarButton); + await userEvent.click(datePickerOpenCalendarButton); const options = await screen.findAllByRole('option'); - userEvent.click(options[16]); + await userEvent.click(options[16]); expect(onReportDateChange).toHaveBeenCalledTimes(1); expect(onReportDateChange.mock.calls[0][0].toISOString()).toMatch(/^2022-04-12/); @@ -342,10 +340,10 @@ describe('ReportManager - DetailsSection', () => { const timePicker = await screen.findByTestId('reportManager-detailsSection-timePicker'); const timePickerOpenOptionsButton = await within(timePicker).findByLabelText('Open time options'); - userEvent.click(timePickerOpenOptionsButton); + await userEvent.click(timePickerOpenOptionsButton); const optionsList = await screen.findByTestId('timePicker-OptionsList'); const timeOptionsListItems = await within(optionsList).findAllByRole('option'); - userEvent.click(timeOptionsListItems[2]); + await userEvent.click(timeOptionsListItems[2]); expect(onReportDateChange).toHaveBeenCalled(); }); @@ -391,7 +389,7 @@ describe('ReportManager - DetailsSection', () => { expect(onLegacyFormChange).toHaveBeenCalledTimes(0); - userEvent.type(screen.getByLabelText('Type of accident'), 'Truck crash'); + await userEvent.type(screen.getByLabelText('Type of accident'), 'Truck crash'); expect(onLegacyFormChange).toHaveBeenCalled(); }); @@ -403,7 +401,9 @@ describe('ReportManager - DetailsSection', () => { submitFormButtonRef.current.click(); - expect(onFormSubmit).toHaveBeenCalledTimes(1); + await waitFor(() => { + expect(onFormSubmit).toHaveBeenCalledTimes(1); + }); }); test('shows a loader while the schema loads', async () => { diff --git a/src/ReportManager/Header/ReportMenu/index.test.js b/src/ReportManager/Header/ReportMenu/index.test.js index 826c245b9..ece4b90d9 100644 --- a/src/ReportManager/Header/ReportMenu/index.test.js +++ b/src/ReportManager/Header/ReportMenu/index.test.js @@ -81,12 +81,12 @@ describe('Menu report options', () => { ); const kebabButton = screen.getByRole('button'); - userEvent.click(kebabButton); + await userEvent.click(kebabButton); expect(writeText).toHaveBeenCalledTimes(0); const copyButton = screen.getByLabelText('Copy to clipboard'); - userEvent.click(copyButton); + await userEvent.click(copyButton); await waitFor(() => { expect(writeText).toHaveBeenCalledTimes(1); @@ -109,17 +109,17 @@ describe('Menu report options', () => { ); const kebabButton = await screen.getByRole('button'); - userEvent.click(kebabButton); + await userEvent.click(kebabButton); expect(handlePrint).toHaveBeenCalledTimes(0); const printReportButton = await screen.getByText('Print Event Details'); - userEvent.click(printReportButton); + await userEvent.click(printReportButton); expect(handlePrint).toHaveBeenCalledTimes(1); }); - test('should not show the incident option if the report is a collection', () => { + test('should not show the incident option if the report is a collection', async () => { const collectionReport = { ...report, ...{ is_collection: true } }; renderWithWrapper( { ); const kebabButton = screen.getByRole('button'); - userEvent.click(kebabButton); + await userEvent.click(kebabButton); expect((screen.queryByText('Add to Incident'))).toBeNull(); expect((screen.queryByText('Add to Parol'))).toBeDefined(); }); - test('should not show the incident option if the report belongs to a collection', () => { + test('should not show the incident option if the report belongs to a collection', async () => { const reportWithCollection = { ...report, ...{ is_contained_in: [{ type: 'contains', ordernum: null, url: 'https://fake.com', related_event: {} }] } }; renderWithWrapper( { ); const kebabButton = screen.getByRole('button'); - userEvent.click(kebabButton); + await userEvent.click(kebabButton); expect((screen.queryByText('Add to Incident'))).toBeNull(); expect((screen.queryByText('Add to Parol'))).toBeDefined(); @@ -169,18 +169,18 @@ describe('Menu report options', () => { ); const kebabButton = await screen.getByRole('button'); - userEvent.click(kebabButton); + await userEvent.click(kebabButton); const addToIncidentButton = await screen.findByText('Add to Incident'); expect(addToIncidentButton).toBeDefined(); - userEvent.click(addToIncidentButton); + await userEvent.click(addToIncidentButton); expect(addModal).toHaveBeenCalledTimes(1); }); - test('should not show the patrol option if the report belongs to a patrol', () => { + test('should not show the patrol option if the report belongs to a patrol', async () => { const patrolReport = { ...report, ...{ patrol_segments: [{}] } }; renderWithWrapper( { ); const kebabButton = screen.getByRole('button'); - userEvent.click(kebabButton); + await userEvent.click(kebabButton); expect((screen.queryByText('Add to Incident'))).toBeDefined(); expect((screen.queryByText('Add to Patrol'))).toBeNull(); @@ -211,13 +211,13 @@ describe('Menu report options', () => { ); const kebabButton = await screen.getByRole('button'); - userEvent.click(kebabButton); + await userEvent.click(kebabButton); const addToPatrolButton = await screen.findByText('Add to Patrol'); expect(addToPatrolButton).toBeDefined(); - userEvent.click(addToPatrolButton); + await userEvent.click(addToPatrolButton); expect(addModal).toHaveBeenCalledTimes(1); }); diff --git a/src/ReportManager/Header/index.test.js b/src/ReportManager/Header/index.test.js index 59276432d..a17135fbe 100644 --- a/src/ReportManager/Header/index.test.js +++ b/src/ReportManager/Header/index.test.js @@ -68,8 +68,8 @@ describe('ReportManager - Header', () => { ); const titleTextBox = await screen.findByTestId('reportManager-header-title'); - userEvent.type(titleTextBox, '{del}{del}{del}{del}{del}2'); - userEvent.tab(); + await userEvent.type(titleTextBox, '{del}{del}{del}{del}{del}2'); + await userEvent.tab(); await waitFor(() => { expect(onChangeTitle).toHaveBeenCalledTimes(1); @@ -84,8 +84,8 @@ describe('ReportManager - Header', () => { ); const titleTextBox = await screen.findByTestId('reportManager-header-title'); - userEvent.type(titleTextBox, '{del}{del}{del}{del}{del}'); - userEvent.tab(); + await userEvent.type(titleTextBox, '{del}{del}{del}{del}{del}'); + await userEvent.tab(); expect(onChangeTitle).toHaveBeenCalledTimes(1); expect(onChangeTitle).toHaveBeenCalledWith('Light'); diff --git a/src/ReportManager/ReportDetailView/index.test.js b/src/ReportManager/ReportDetailView/index.test.js index c551c1937..31ca52119 100644 --- a/src/ReportManager/ReportDetailView/index.test.js +++ b/src/ReportManager/ReportDetailView/index.test.js @@ -245,9 +245,9 @@ describe('ReportManager - ReportDetailView', () => { expect(titleInput).toHaveTextContent('Accident'); - userEvent.type(titleInput, '2'); + await userEvent.type(titleInput, '2'); - expect(titleInput).toHaveTextContent('2ccident'); + expect(titleInput).toHaveTextContent('2'); }); test('sets the location when user changes it', async () => { @@ -260,12 +260,14 @@ describe('ReportManager - ReportDetailView', () => { ); const locationPickerButton = screen.getByLabelText('Event Location'); - userEvent.click(locationPickerButton); - userEvent.click(screen.getByLabelText('Pick a location on the map')); + await userEvent.click(locationPickerButton); + await userEvent.click(screen.getByLabelText('Pick a location on the map')); map.__test__.fireHandlers('click', { lngLat: { lng: 88, lat: 55 } }); - expect(within(locationPickerButton).getByRole('textbox')).toHaveValue('55.000000°, 88.000000°'); + await waitFor(() => { + expect(within(locationPickerButton).getByRole('textbox')).toHaveValue('55.000000°, 88.000000°'); + }); }); test('sets the date when user changes it', async () => { @@ -275,9 +277,9 @@ describe('ReportManager - ReportDetailView', () => { const datePicker = await screen.findByTestId('reportManager-detailsSection-datePicker'); const datePickerOpenCalendarButton = await within(datePicker).findByLabelText('Open calendar'); - userEvent.click(datePickerOpenCalendarButton); + await userEvent.click(datePickerOpenCalendarButton); const options = await screen.findAllByRole('option'); - userEvent.click(options[25]); + await userEvent.click(options[25]); expect(await within(datePicker).findByTestId('datePicker-input')).toHaveValue('2022-12-22'); }); @@ -289,10 +291,10 @@ describe('ReportManager - ReportDetailView', () => { const timePicker = await screen.findByTestId('reportManager-detailsSection-timePicker'); const timePickerOpenOptionsButton = await within(timePicker).findByLabelText('Open time options'); - userEvent.click(timePickerOpenOptionsButton); + await userEvent.click(timePickerOpenOptionsButton); const optionsList = await screen.findByTestId('timePicker-OptionsList'); const timeOptionsListItems = await within(optionsList).findAllByRole('option'); - userEvent.click(timeOptionsListItems[2]); + await userEvent.click(timeOptionsListItems[2]); expect(await within(timePicker).findByTestId('timePicker-input')).toHaveValue('00:30'); }); @@ -307,7 +309,7 @@ describe('ReportManager - ReportDetailView', () => { ); const typeOfAccidentField = await screen.findByLabelText('Type of accident'); - userEvent.type(typeOfAccidentField, 'Truck crash'); + await userEvent.type(typeOfAccidentField, 'Truck crash'); expect((await screen.findByDisplayValue('Truck crash'))).toBeDefined(); }); @@ -324,9 +326,9 @@ describe('ReportManager - ReportDetailView', () => { expect((await screen.queryByRole('button', { name: 'Resolved' }))).toBeNull(); const stateDropdown = await screen.findByText('active'); - userEvent.click(stateDropdown); + await userEvent.click(stateDropdown); const resolvedItem = await screen.findByText('resolved'); - userEvent.click(resolvedItem); + await userEvent.click(resolvedItem); expect(((await screen.findAllByRole('button', { name: 'resolved' })))[0]).toHaveClass('dropdown-toggle'); }); @@ -343,28 +345,24 @@ describe('ReportManager - ReportDetailView', () => { expect(navigate).toHaveBeenCalledTimes(0); const cancelButton = await screen.findByText('Cancel'); - userEvent.click(cancelButton); + await userEvent.click(cancelButton); expect(navigate).toHaveBeenCalledTimes(1); expect(navigate).toHaveBeenCalledWith(`/${TAB_KEYS.EVENTS}`); }); - test('showing the navigation warning prompt when canceling an added report', () => { - - }); - test('displays a new attachment', async () => { renderWithWrapper( ); - expect((await screen.findAllByText('attachment.svg'))).toHaveLength(1); + expect((await screen.queryByTestId('attachment-icon'))).toBeNull(); const addAttachmentButton = await screen.findByTestId('addAttachmentButton'); const fakeFile = new File(['fake'], 'fake.txt', { type: 'text/plain' }); - userEvent.upload(addAttachmentButton, fakeFile); + await userEvent.upload(addAttachmentButton, fakeFile); - expect((await screen.findAllByText('attachment.svg'))).toHaveLength(2); + expect((await screen.findAllByTestId('attachment-icon'))).toHaveLength(1); }); test('deletes a new attachment', async () => { @@ -372,15 +370,16 @@ describe('ReportManager - ReportDetailView', () => { ); - expect((await screen.findAllByText('attachment.svg'))).toHaveLength(1); - const addAttachmentButton = await screen.findByTestId('addAttachmentButton'); const fakeFile = new File(['fake'], 'fake.txt', { type: 'text/plain' }); - userEvent.upload(addAttachmentButton, fakeFile); - const deleteAttachmentButton = await screen.findByText('trash-can.svg'); - userEvent.click(deleteAttachmentButton); + await userEvent.upload(addAttachmentButton, fakeFile); - expect((await screen.findAllByText('attachment.svg'))).toHaveLength(1); + expect((await screen.findAllByTestId('attachment-icon'))).toHaveLength(1); + + const deleteAttachmentButton = await screen.findByTestId('activitySection-trashCan-fake.txt'); + await userEvent.click(deleteAttachmentButton); + + expect((await screen.queryByTestId('attachment-icon'))).toBeNull(); }); test('displays a new note', async () => { @@ -388,12 +387,12 @@ describe('ReportManager - ReportDetailView', () => { ); - expect((await screen.findAllByText('note.svg'))).toHaveLength(notes.length + 1); + expect((await screen.findAllByTestId('note-icon'))).toHaveLength(notes.length); const addNoteButton = await screen.findByTestId('reportDetailView-addNoteButton-original'); - userEvent.click(addNoteButton); + await userEvent.click(addNoteButton); - expect((await screen.findAllByText('note.svg'))).toHaveLength(notes.length + 2); + expect((await screen.findAllByTestId('note-icon'))).toHaveLength(notes.length + 1); }); test('deletes a new note', async () => { @@ -401,14 +400,15 @@ describe('ReportManager - ReportDetailView', () => { ); - expect((await screen.findAllByText('note.svg'))).toHaveLength(1); - const addNoteButton = await screen.findByTestId('reportDetailView-addNoteButton-original'); - userEvent.click(addNoteButton); - const deleteNoteButton = await screen.findByText('trash-can.svg'); - userEvent.click(deleteNoteButton); + await userEvent.click(addNoteButton); - expect((await screen.findAllByText('note.svg'))).toHaveLength(1); + expect((await screen.findAllByTestId('note-icon'))).toHaveLength(1); + + const deleteNoteButton = await screen.findByTestId('activitySection-deleteIcon-'); + await userEvent.click(deleteNoteButton); + + expect((await screen.queryByTestId('note-icon'))).toBeNull(); }); test('if the current report is a collection, adding a new one simply appends it', async () => { @@ -508,13 +508,13 @@ describe('ReportManager - ReportDetailView', () => { ); const titleTextBox = await screen.findByTestId('reportManager-header-title'); - userEvent.type(titleTextBox, '2'); - userEvent.tab(); + await userEvent.type(titleTextBox, '2'); + await userEvent.tab(); expect(onSaveSuccess).toHaveBeenCalledTimes(0); const saveButton = await screen.findByText('Save'); - userEvent.click(saveButton); + await userEvent.click(saveButton); await waitFor(() => { expect(onSaveSuccess).toHaveBeenCalledTimes(1); @@ -530,13 +530,13 @@ describe('ReportManager - ReportDetailView', () => { ); const titleTextBox = await screen.findByTestId('reportManager-header-title'); - userEvent.type(titleTextBox, '2'); - userEvent.tab(); + await userEvent.type(titleTextBox, '2'); + await userEvent.tab(); expect(executeSaveActions).toHaveBeenCalledTimes(0); const saveButton = await screen.findByText('Save'); - userEvent.click(saveButton); + await userEvent.click(saveButton); expect(executeSaveActions).toHaveBeenCalledTimes(1); @@ -554,13 +554,13 @@ describe('ReportManager - ReportDetailView', () => { /> ); const editNoteIcon = await screen.findByTestId(`activitySection-editIcon-${noteId}`); - userEvent.click(editNoteIcon); + await userEvent.click(editNoteIcon); const noteTextArea = await screen.findByTestId(`activitySection-noteTextArea-${noteId}`); - userEvent.type(noteTextArea, updatedText); + await userEvent.type(noteTextArea, updatedText); const doneNoteButton = await screen.findByTestId(`activitySection-noteDone-${noteId}`); - userEvent.click(doneNoteButton); + await userEvent.click(doneNoteButton); const textArea = await screen.findByTestId(`activitySection-noteTextArea-${noteId}`); return { textArea, doneNoteButton }; @@ -575,7 +575,7 @@ describe('ReportManager - ReportDetailView', () => { expect(textArea).toHaveValue(`${note.text}${updatedText}`); const cancelButton = await screen.findByText('Cancel'); - userEvent.click(cancelButton); + await userEvent.click(cancelButton); expect(textArea).toHaveTextContent(note.text); expect((await screen.queryByText(doneNoteButton))).toBeNull(); @@ -598,24 +598,6 @@ describe('ReportManager - ReportDetailView', () => { expect(textArea.value).toBe(`${note.text} with spaces`); }); - test('shows the loading overlay while saving', async () => { - renderWithWrapper( - - ); - - const titleTextBox = await screen.findByTestId('reportManager-header-title'); - userEvent.type(titleTextBox, '2'); - userEvent.tab(); - const saveButton = await screen.findByText('Save'); - userEvent.click(saveButton); - - expect(await screen.findByText('Saving...')).toBeDefined(); - }); - test('triggers the formProps onSaveError callback if there is an error saving', async () => { const onSaveError = jest.fn(); @@ -632,13 +614,13 @@ describe('ReportManager - ReportDetailView', () => { ); const titleTextBox = await screen.findByTestId('reportManager-header-title'); - userEvent.type(titleTextBox, '2'); - userEvent.tab(); + await userEvent.type(titleTextBox, '2'); + await userEvent.tab(); expect(onSaveError).toHaveBeenCalledTimes(0); const saveButton = await screen.findByText('Save'); - userEvent.click(saveButton); + await userEvent.click(saveButton); await waitFor(() => { expect(onSaveError).toHaveBeenCalledTimes(1); @@ -658,10 +640,10 @@ describe('ReportManager - ReportDetailView', () => { ); const titleTextBox = await screen.findByTestId('reportManager-header-title'); - userEvent.type(titleTextBox, '2'); - userEvent.tab(); + await userEvent.type(titleTextBox, '2'); + await userEvent.tab(); const saveButton = await screen.findByText('Save'); - userEvent.click(saveButton); + await userEvent.click(saveButton); expect(await screen.findByText('Error saving event.')).toBeDefined(); }); @@ -673,18 +655,18 @@ describe('ReportManager - ReportDetailView', () => { ); - expect((await screen.findAllByText('attachment.svg'))).toHaveLength(1); + expect((await screen.queryByTestId('attachment-icon'))).toBeNull(); const addAttachmentButton = await screen.findByTestId('addAttachmentButton'); const fakeFile = new File(['fake'], 'fake.txt', { type: 'text/plain' }); - userEvent.upload(addAttachmentButton, fakeFile); + await userEvent.upload(addAttachmentButton, fakeFile); - expect((await screen.findAllByText('attachment.svg'))).toHaveLength(2); + expect((await screen.findAllByTestId('attachment-icon'))).toHaveLength(1); const fakeFileAgain = new File(['fake'], 'fake.txt', { type: 'text/plain' }); - userEvent.upload(addAttachmentButton, fakeFileAgain); + await userEvent.upload(addAttachmentButton, fakeFileAgain); - expect((await screen.findAllByText('attachment.svg'))).toHaveLength(2); + expect((await screen.findAllByTestId('attachment-icon'))).toHaveLength(1); }); test('can not add a second note without saving the first one', async () => { @@ -694,15 +676,15 @@ describe('ReportManager - ReportDetailView', () => { ); - expect((await screen.findAllByText('note.svg'))).toHaveLength(3); + expect((await screen.findAllByTestId('note-icon'))).toHaveLength(2); expect(window.alert).toHaveBeenCalledTimes(0); const addNoteButton = await screen.findByTestId('reportDetailView-addNoteButton-original'); - userEvent.click(addNoteButton); - userEvent.click(addNoteButton); + await userEvent.click(addNoteButton); + await userEvent.click(addNoteButton); expect(window.alert).toHaveBeenCalledTimes(1); - expect((await screen.findAllByText('note.svg'))).toHaveLength(4); + expect((await screen.findAllByTestId('note-icon'))).toHaveLength(3); }); test('does not display the activity section nor its anchor if there are no items to show', async () => { @@ -731,7 +713,7 @@ describe('ReportManager - ReportDetailView', () => { expect((await screen.queryByTestId('quickLinks-anchor-Activity'))).toBeNull(); const addNoteButton = await screen.findByTestId('reportDetailView-addNoteButton-original'); - userEvent.click(addNoteButton); + await userEvent.click(addNoteButton); expect((await screen.findByTestId('detailView-activitySection'))).toBeDefined(); expect((await screen.findByTestId('quickLinks-anchor-Activity'))).toBeDefined(); @@ -818,7 +800,7 @@ describe('ReportManager - ReportDetailView', () => { renderWithWrapper(); const titleInput = await screen.findByTestId('reportManager-header-title'); - userEvent.type(titleInput, '2'); + await userEvent.type(titleInput, '2'); titleInput.blur(); await waitFor(() => { @@ -833,14 +815,14 @@ describe('ReportManager - ReportDetailView', () => { expect(unsetLocallyEditedEvent).toHaveBeenCalledTimes(1); const titleInput = await screen.findByTestId('reportManager-header-title'); - userEvent.type(titleInput, '2'); + await userEvent.type(titleInput, '2'); titleInput.blur(); await waitFor(() => { expect(setLocallyEditedEvent).toHaveBeenCalledTimes(1); }); - userEvent.type(titleInput, 't'); + await userEvent.type(titleInput, 'title'); titleInput.blur(); await waitFor(() => { @@ -861,8 +843,8 @@ describe('ReportManager - ReportDetailView', () => { ); const titleTextBox = await screen.findByTestId('reportManager-header-title'); - userEvent.type(titleTextBox, '2'); - userEvent.tab(); + await userEvent.type(titleTextBox, '2'); + await userEvent.tab(); const saveButtonGroup = (await screen.findAllByRole('group'))[3]; @@ -884,7 +866,7 @@ describe('ReportManager - ReportDetailView', () => { const changes = generateSaveActionsForReportLikeObject.mock.calls[0][0]; expect(changes.state).toBe('resolved'); - expect(changes.title).toBe('2ccident'); + expect(changes.title).toBe('2'); }); }); @@ -911,11 +893,11 @@ describe('ReportManager - ReportDetailView', () => { ); const titleInput = await screen.findByTestId('reportManager-header-title'); - userEvent.type(titleInput, '2'); + await userEvent.type(titleInput, '2'); titleInput.blur(); const cancelButton = await screen.findByText('Cancel'); - userEvent.click(cancelButton); + await userEvent.click(cancelButton); await screen.findByText(modalPromptTitle); await screen.findByText(modalPromptText); @@ -937,7 +919,7 @@ describe('ReportManager - ReportDetailView', () => { expect(onCancelAddedReport).toHaveBeenCalledTimes(0); const cancelButton = await screen.findByText('Cancel'); - userEvent.click(cancelButton); + await userEvent.click(cancelButton); await screen.findByText(modalPromptTitle); await screen.findByText(modalPromptText); @@ -959,7 +941,7 @@ describe('ReportManager - ReportDetailView', () => { expect(onCancelAddedReport).toHaveBeenCalledTimes(0); const cancelButton = await screen.findByText('Cancel'); - userEvent.click(cancelButton); + await userEvent.click(cancelButton); const discardButton = await screen.findByText('Discard'); discardButton.click(); @@ -980,12 +962,12 @@ describe('ReportManager - ReportDetailView', () => { ); const titleTextBox = await screen.findByTestId('reportManager-header-title'); - userEvent.type(titleTextBox, '2'); - userEvent.tab(); + await userEvent.type(titleTextBox, '2'); + await userEvent.tab(); const cancelButton = await screen.findByText('Cancel'); - userEvent.click(cancelButton); + await userEvent.click(cancelButton); expect(onSaveSuccess).not.toHaveBeenCalled(); diff --git a/src/ReportedBySelect/index.test.js b/src/ReportedBySelect/index.test.js index d6cd8e3f0..c7b5dfcd6 100644 --- a/src/ReportedBySelect/index.test.js +++ b/src/ReportedBySelect/index.test.js @@ -44,7 +44,7 @@ describe('ReportedBySelect', () => { expect(screen.getByText('Reported By...')).toBeInTheDocument(); selectControlContainer.focus(); - userEvent.type(selectControlContainer, '{arrowdown}'); + await userEvent.type(selectControlContainer, '{arrowdown}'); await waitFor(() => { expect(screen.getByText('Informant')).toBeInTheDocument(); @@ -60,7 +60,7 @@ describe('ReportedBySelect', () => { const selectControlContainer = container.querySelector('input'); selectControlContainer.focus(); - userEvent.type(selectControlContainer, '{arrowdown}'); + await userEvent.type(selectControlContainer, '{arrowdown}'); const toClick = await screen.findByText('Informant2'); toClick.click(); @@ -71,11 +71,11 @@ describe('ReportedBySelect', () => { it('closes the menu when pressing escape', async () => { const { container } = renderWithWrapper(); - userEvent.click(container.querySelector('input')); + await userEvent.click(container.querySelector('input')); expect(await screen.findByText('Informant2')).toBeVisible(); - userEvent.keyboard('{Escape}'); + await userEvent.keyboard('{Escape}'); expect(await screen.queryByText('Informant2')).toBeNull(); }); diff --git a/src/SchemaFields/index.test.js b/src/SchemaFields/index.test.js index 2bddf28fd..e60c550cf 100644 --- a/src/SchemaFields/index.test.js +++ b/src/SchemaFields/index.test.js @@ -63,9 +63,9 @@ describe('DateTimeWidget', () => { expect(props.onChange).toHaveBeenCalledTimes(0); const datePickerOpenCalendarButton = await screen.findByLabelText('Open calendar'); - userEvent.click(datePickerOpenCalendarButton); + await userEvent.click(datePickerOpenCalendarButton); const options = await screen.findAllByRole('option'); - userEvent.click(options[16]); + await userEvent.click(options[16]); expect(props.onChange).toHaveBeenCalled(); }); @@ -76,10 +76,10 @@ describe('DateTimeWidget', () => { expect(props.onChange).toHaveBeenCalledTimes(0); const timePickerOpenOptionsButton = await screen.findByLabelText('Open time options'); - userEvent.click(timePickerOpenOptionsButton); + await userEvent.click(timePickerOpenOptionsButton); const optionsList = await screen.findByTestId('timePicker-OptionsList'); const timeOptionsListItems = await within(optionsList).findAllByRole('option'); - userEvent.click(timeOptionsListItems[2]); + await userEvent.click(timeOptionsListItems[2]); expect(props.onChange).toHaveBeenCalled(); }); diff --git a/src/SearchBar/index.test.js b/src/SearchBar/index.test.js index 68fe92bf8..1e06fd9dd 100644 --- a/src/SearchBar/index.test.js +++ b/src/SearchBar/index.test.js @@ -7,12 +7,12 @@ import { render, screen } from '../test-utils'; const changeMock = jest.fn(() => {}); const clearMock = jest.fn(); -test('rendering without crashing', () => { +test('rendering without crashing', async () => { render(); }); describe('searching and reset', () => { - beforeEach(async () => { + beforeEach(() => { render(); }); @@ -26,15 +26,15 @@ describe('searching and reset', () => { expect(searchInput).toHaveAttribute('placeholder', 'Search here!'); }); - test('it should call onChange', () => { + test('it should call onChange', async () => { const searchInput = screen.getByTestId('search-input'); - userEvent.type(searchInput, 'ER'); + await userEvent.type(searchInput, 'ER'); expect(changeMock).toHaveBeenCalledTimes(2); }); test('it should clear the search input after clicking the reset button', async () => { const resetButton = await screen.getByTestId('reset-search-button'); - userEvent.click(resetButton); + await userEvent.click(resetButton); expect(clearMock).toHaveBeenCalledTimes(1); }); }); \ No newline at end of file diff --git a/src/SelectListGroup/SelectableItem/index.test.js b/src/SelectListGroup/SelectableItem/index.test.js index 5dbc29954..3a653e6d2 100644 --- a/src/SelectListGroup/SelectableItem/index.test.js +++ b/src/SelectListGroup/SelectableItem/index.test.js @@ -24,7 +24,7 @@ describe('SelectListGroup - SelectableItem', () => { ); - const testSelectableItemHasChangedWithClick = (queryClickableElement, expectedIsChecked, props = {}) => { + const testSelectableItemHasChangedWithClick = async (queryClickableElement, expectedIsChecked, props = {}) => { const onClick = jest.fn(); renderSelectableItem({ @@ -35,13 +35,13 @@ describe('SelectListGroup - SelectableItem', () => { expect(onClick).not.toHaveBeenCalled(); - userEvent.click(queryClickableElement()); + await userEvent.click(queryClickableElement()); expect(onClick).toHaveBeenCalledTimes(1); expect(onClick).toHaveBeenCalledWith(110, expectedIsChecked); }; - const testSelectableItemHasChangedUsingKeyboard = (keyboardKey, expectedIsChecked, props = {}) => { + const testSelectableItemHasChangedUsingKeyboard = async (keyboardKey, expectedIsChecked, props = {}) => { const onClick = jest.fn(); const itemProps = { ...defaultProps, @@ -59,13 +59,13 @@ describe('SelectListGroup - SelectableItem', () => { const input = screen.getByRole(role); input.focus(); - userEvent.keyboard(keyboardKey); + await userEvent.keyboard(keyboardKey); expect(onClick).toHaveBeenCalledTimes(1); expect(onClick).toHaveBeenCalledWith(110, expectedIsChecked); }; - test('shows a proper label', () => { + test('shows a proper label', async () => { renderSelectableItem(); expect( screen.getByText('This is a checkbox') ).toBeVisible(); @@ -73,7 +73,7 @@ describe('SelectListGroup - SelectableItem', () => { describe('Checkbox item', () => { - test('shows a checked checkbox', () => { + test('shows a checked checkbox', async () => { renderSelectableItem(); const checkbox = screen.getByRole('checkbox'); @@ -81,7 +81,7 @@ describe('SelectListGroup - SelectableItem', () => { expect( checkbox ).toBeChecked(); }); - test('shows an unchecked checkbox', () => { + test('shows an unchecked checkbox', async () => { renderSelectableItem({ ...defaultProps, isChecked: false @@ -92,15 +92,15 @@ describe('SelectListGroup - SelectableItem', () => { expect( checkbox ).not.toBeChecked(); }); - test('the checkbox is unchecked when user clicks on label', () => { - testSelectableItemHasChangedWithClick( + test('the checkbox is unchecked when user clicks on label', async () => { + await testSelectableItemHasChangedWithClick( () => screen.getByText('This is a checkbox'), false ); }); - test('the checkbox is checked when user clicks on label', () => { - testSelectableItemHasChangedWithClick( + test('the checkbox is checked when user clicks on label', async () => { + await testSelectableItemHasChangedWithClick( () => screen.getByText('This is a checkbox'), true, { @@ -109,15 +109,15 @@ describe('SelectListGroup - SelectableItem', () => { ); }); - test('the checkbox is unchecked when user focus item and hits space bar', () => { - testSelectableItemHasChangedUsingKeyboard( + test('the checkbox is unchecked when user focus item and hits space bar', async () => { + await testSelectableItemHasChangedUsingKeyboard( '[Space]', false ); }); - test('the checkbox is checked when user focus item and types space bar', () => { - testSelectableItemHasChangedUsingKeyboard( + test('the checkbox is checked when user focus item and types space bar', async () => { + await testSelectableItemHasChangedUsingKeyboard( '[Space]', true, { @@ -126,7 +126,7 @@ describe('SelectListGroup - SelectableItem', () => { ); }); - test('checkbox is disabled', () => { + test('checkbox is disabled', async () => { const onClick = jest.fn(); renderSelectableItem({ ...defaultProps, @@ -138,13 +138,13 @@ describe('SelectListGroup - SelectableItem', () => { const input = screen.getByRole('checkbox'); - userEvent.click(input); + await userEvent.click(input); expect(input).toBeDisabled(); expect(onClick).not.toHaveBeenCalled(); }); - test('checkbox is readOnly', () => { + test('checkbox is readOnly', async () => { const onClick = jest.fn(); renderSelectableItem({ ...defaultProps, @@ -156,7 +156,7 @@ describe('SelectListGroup - SelectableItem', () => { const input = screen.getByRole('checkbox'); - userEvent.click(input); + await userEvent.click(input); expect(input).toHaveProperty('readOnly', true); expect(onClick).not.toHaveBeenCalled(); @@ -165,7 +165,7 @@ describe('SelectListGroup - SelectableItem', () => { describe('Radio item', () => { - test('shows a checked radio', () => { + test('shows a checked radio', async () => { renderSelectableItem({ ...defaultProps, label: 'This is a radio', @@ -177,7 +177,7 @@ describe('SelectListGroup - SelectableItem', () => { expect( radio ).toBeChecked(); }); - test('shows an unchecked radio', () => { + test('shows an unchecked radio', async () => { renderSelectableItem({ ...defaultProps, label: 'This is a radio', @@ -190,7 +190,7 @@ describe('SelectListGroup - SelectableItem', () => { expect( radio ).not.toBeChecked(); }); - test('radio is disabled', () => { + test('radio is disabled', async () => { const onClick = jest.fn(); renderSelectableItem({ ...defaultProps, @@ -203,13 +203,13 @@ describe('SelectListGroup - SelectableItem', () => { const input = screen.getByRole('radio'); - userEvent.click(input); + await userEvent.click(input); expect(input).toBeDisabled(); expect(onClick).not.toHaveBeenCalled(); }); - test('radio is readOnly', () => { + test('radio is readOnly', async () => { const onClick = jest.fn(); renderSelectableItem({ ...defaultProps, @@ -222,7 +222,7 @@ describe('SelectListGroup - SelectableItem', () => { const input = screen.getByRole('radio'); - userEvent.click(input); + await userEvent.click(input); expect(input).toHaveProperty('readOnly', true); expect(onClick).not.toHaveBeenCalled(); diff --git a/src/SelectListGroup/index.test.js b/src/SelectListGroup/index.test.js index 109fc22fc..d77232c88 100644 --- a/src/SelectListGroup/index.test.js +++ b/src/SelectListGroup/index.test.js @@ -38,7 +38,7 @@ describe('SelectListGroup', () => { ); - test('shows a proper list of checkboxes', () => { + test('shows a proper list of checkboxes', async () => { renderSelectListGroup(); options.forEach((option) => { @@ -49,7 +49,7 @@ describe('SelectListGroup', () => { }); }); - test('shows a proper list of radio buttons', () => { + test('shows a proper list of radio buttons', async () => { renderSelectListGroup({ ...initialProps, isMulti: false @@ -63,7 +63,7 @@ describe('SelectListGroup', () => { }); }); - test('allows to select multiple options', () => { + test('allows to select multiple options', async () => { const onChange = jest.fn(); renderSelectListGroup({ @@ -74,13 +74,13 @@ describe('SelectListGroup', () => { expect(onChange).not.toHaveBeenCalled(); - userEvent.click( screen.getByText('The option') ); + await userEvent.click( screen.getByText('The option') ); expect(onChange).toHaveBeenCalledTimes(1); expect(onChange).toHaveBeenCalledWith([124, 32409]); }); - test('allows to select only one option', () => { + test('allows to select only one option', async () => { const onChange = jest.fn(); renderSelectListGroup({ @@ -92,13 +92,13 @@ describe('SelectListGroup', () => { expect(onChange).not.toHaveBeenCalled(); - userEvent.click( screen.getByText('The option') ); + await userEvent.click( screen.getByText('The option') ); expect(onChange).toHaveBeenCalledTimes(1); expect(onChange).toHaveBeenCalledWith(32409); }); - test('shows a proper selectable item with custom option object', () => { + test('shows a proper selectable item with custom option object', async () => { const options = [ { title: 'A custom product', @@ -115,7 +115,7 @@ describe('SelectListGroup', () => { expect( screen.getByText('A custom product') ).toBeVisible(); }); - test('shows a disabled list of checkboxes', () => { + test('shows a disabled list of checkboxes', async () => { renderSelectListGroup({ ...initialProps, disabled: true @@ -132,7 +132,7 @@ describe('SelectListGroup', () => { }); }); - test('shows a disabled list of radios', () => { + test('shows a disabled list of radios', async () => { renderSelectListGroup({ ...initialProps, disabled: true, @@ -150,7 +150,7 @@ describe('SelectListGroup', () => { }); }); - test('shows an invalid list', () => { + test('shows an invalid list', async () => { renderSelectListGroup({ ...initialProps, invalid: true, diff --git a/src/SideBar/PatrolsFeedTab/index.test.js b/src/SideBar/PatrolsFeedTab/index.test.js index 66fc89a84..6fb0dd0db 100644 --- a/src/SideBar/PatrolsFeedTab/index.test.js +++ b/src/SideBar/PatrolsFeedTab/index.test.js @@ -53,7 +53,7 @@ describe('PatrolsFeedTab', () => { expect(navigate).toHaveBeenCalledTimes(0); const patrolItemButton = await screen.findByTestId('patrol-list-item-icon-05113dd3-3f41-49ef-aa7d-fbc6b7379533'); - userEvent.click(patrolItemButton); + await userEvent.click(patrolItemButton); expect(navigate).toHaveBeenCalledTimes(1); }); diff --git a/src/SideBar/SettingsPane/index.test.js b/src/SideBar/SettingsPane/index.test.js index d15055eb0..f0c3dab81 100644 --- a/src/SideBar/SettingsPane/index.test.js +++ b/src/SideBar/SettingsPane/index.test.js @@ -89,7 +89,7 @@ describe('SettingsPane', () => { }); test('toggling the event filter persistence setting when clicked', async () => { const eventFilterPersistToggle = await screen.findByText('Event Filters'); - userEvent.click(eventFilterPersistToggle); + await userEvent.click(eventFilterPersistToggle); expect(global.localStorage.setItem).toHaveBeenCalledWith( 'er-web-restorable:eventFilter', @@ -99,7 +99,7 @@ describe('SettingsPane', () => { test('toggling the patrol filter persistence setting when clicked', async () => { const patrolFilterPersistToggle = await screen.findByText('Patrol Filters'); - userEvent.click(patrolFilterPersistToggle); + await userEvent.click(patrolFilterPersistToggle); expect(global.localStorage.setItem).toHaveBeenCalledWith( 'er-web-restorable:patrolFilter', @@ -111,7 +111,7 @@ describe('SettingsPane', () => { expect(global.localStorage.setItem).not.toHaveBeenCalled(); const mapPositionPersistToggle = await screen.findByText('Map Position & Zoom Level'); - userEvent.click(mapPositionPersistToggle); + await userEvent.click(mapPositionPersistToggle); expect(global.localStorage.setItem).toHaveBeenCalledWith( 'er-web-restorable:mapPosition', @@ -124,7 +124,7 @@ describe('SettingsPane', () => { describe('the "Map" settings tab', () => { it('toggles the showInactiveRadios state when the checkbox is clicked', async () => { const checkbox = await screen.findByText('Show Inactive Radios'); - userEvent.click(checkbox); + await userEvent.click(checkbox); const actions = store.getActions(); expect(actions).toEqual([{ type: 'SHOW_INACTIVE_RADIOS', payload: true }]); @@ -133,7 +133,7 @@ describe('SettingsPane', () => { it('toggles the mapIsLocked state when the checkbox is clicked', async () => { const checkbox = await screen.findByText('Lock Map'); - userEvent.click(checkbox); + await userEvent.click(checkbox); const actions = store.getActions(); expect(actions).toEqual([{ type: 'SET_MAP_LOCK_STATE', payload: true }]); @@ -141,7 +141,7 @@ describe('SettingsPane', () => { it('toggles the enable3D state when the checkbox is clicked', async () => { const checkbox = await screen.findByText('3D Map Terrain'); - userEvent.click(checkbox); + await userEvent.click(checkbox); const actions = store.getActions(); expect(actions).toEqual([{ type: 'UPDATE_USER_PREFERENCES', payload: { enable3D: true } }]); @@ -149,7 +149,7 @@ describe('SettingsPane', () => { it('toggles the simplifyMapDataOnZoom state when the checkbox is clicked', async () => { const checkbox = await screen.findByText('Simplify Map Data on Zoom'); - userEvent.click(checkbox); + await userEvent.click(checkbox); const actions = store.getActions(); expect(actions).toEqual([{ type: 'SET_MAP_DATA_ZOOM_SIMPLIFICATION' }]); @@ -157,7 +157,7 @@ describe('SettingsPane', () => { it('toggles the showTrackTimepoints state when the checkbox is clicked', async () => { const checkbox = await screen.findByText('Show Track Timepoints'); - userEvent.click(checkbox); + await userEvent.click(checkbox); const actions = store.getActions(); expect(actions).toEqual([{ type: 'TOGGLE_TRACK_TIMEPOINTS' }]); @@ -165,7 +165,7 @@ describe('SettingsPane', () => { it('toggles the showInactiveRadios state when the checkbox is clicked', async () => { const checkbox = await screen.findByText('Show Inactive Radios'); - userEvent.click(checkbox); + await userEvent.click(checkbox); const actions = store.getActions(); expect(actions).toEqual([{ type: 'SHOW_INACTIVE_RADIOS', payload: true }]); @@ -173,7 +173,7 @@ describe('SettingsPane', () => { it('toggles the showUserLocation state when the checkbox is clicked', async () => { const checkbox = await screen.findByText('Show My Current Location'); - userEvent.click(checkbox); + await userEvent.click(checkbox); const actions = store.getActions(); expect(actions).toEqual([{ type: 'TOGGLE_DISPLAY_USER_LOCATION' }]); diff --git a/src/SideBar/index.js b/src/SideBar/index.js index 2b7588e9f..445ffa596 100644 --- a/src/SideBar/index.js +++ b/src/SideBar/index.js @@ -151,7 +151,7 @@ const SideBar = () => { // NOTE: This is getting unmaintainable. Is it really a good practice to use escape like a navigation key? useEffect(() => { const onKeydown = (event) => { - const wasEscapePressed = event.keyCode === 27; + const wasEscapePressed = event.key === 'Escape'; const isDetailsViewActive = isReportDetailsViewActive || isPatrolDetailsViewActive; const isSideBarFocused = sideBarRef.current.contains(document.activeElement); if (wasEscapePressed && isDetailsViewActive && isSideBarFocused && !isPickingLocation) { diff --git a/src/SideBar/index.test.js b/src/SideBar/index.test.js index 1efd69224..069f7ed40 100644 --- a/src/SideBar/index.test.js +++ b/src/SideBar/index.test.js @@ -144,20 +144,20 @@ describe('SideBar', () => { expect(await screen.findByText('Patrols')).toBeDefined(); }); - test('does not show the patrols tab if user has not permissions', () => { + test('does not show the patrols tab if user has not permissions', async () => { store.data.user.permissions = {}; renderSideBar(); expect(screen.queryByText('Patrols')).toBeNull(); }); - test('sets the tab title for the Events tab', () => { + test('sets the tab title for the Events tab', async () => { renderSideBar(); expect(screen.getByRole('heading')).toHaveTextContent('Events'); }); - test('sets the tab title for the Patrols tab', () => { + test('sets the tab title for the Patrols tab', async () => { useLocationMock = jest.fn((() => ({ pathname: '/patrols' }))); useLocation.mockImplementation(useLocationMock); renderSideBar(); @@ -165,7 +165,7 @@ describe('SideBar', () => { expect(screen.getAllByRole('heading')[0]).toHaveTextContent('Patrols'); }); - test('sets the tab title for the Map Layers tab', () => { + test('sets the tab title for the Map Layers tab', async () => { useLocationMock = jest.fn((() => ({ pathname: '/layers' }))); useLocation.mockImplementation(useLocationMock); renderSideBar(); @@ -205,7 +205,7 @@ describe('SideBar', () => { await assertBadgeWhenEventSignals(); }); - test('does not show the report badge if sidebar is open in reports tab', () => { + test('does not show the report badge if sidebar is open in reports tab', async () => { renderSideBar(); expect(screen.queryByTestId('badgeIcon')).toBeNull(); @@ -219,13 +219,13 @@ describe('SideBar', () => { expect(screen.queryByTestId('badgeIcon')).toBeNull(); }); - test('shows the Add Report button', () => { + test('shows the Add Report button', async () => { renderSideBar(); expect(screen.getByTestId('sideBar-addReportButton')).not.toHaveClass('hidden'); }); - test('hides the Add Report button in the map layers tab', () => { + test('hides the Add Report button in the map layers tab', async () => { useLocationMock = jest.fn((() => ({ pathname: '/layers' }))); useLocation.mockImplementation(useLocationMock); @@ -240,9 +240,9 @@ describe('SideBar', () => { expect(navigate).toHaveBeenCalledTimes(0); - await waitFor(() => { + await waitFor(async () => { const closeButton = screen.getByTestId('sideBar-closeButton'); - userEvent.click(closeButton); + await userEvent.click(closeButton); expect(navigate).toHaveBeenCalledTimes(1); expect(navigate).toHaveBeenCalledWith('/'); @@ -251,7 +251,7 @@ describe('SideBar', () => { }); - test('shows a back button if the detail view of the current tab is open', () => { + test('shows a back button if the detail view of the current tab is open', async () => { useLocationMock = jest.fn((() => ({ pathname: '/events/new' }))); useLocation.mockImplementation(useLocationMock); renderSideBar(); @@ -259,47 +259,47 @@ describe('SideBar', () => { expect(screen.getByTestId('sideBar-backDetailViewButton')).toBeDefined(); }); - const assertBehaviorOfDetailViewBackButton = (locationMock, expectedInvocationParams) => { + const assertBehaviorOfDetailViewBackButton = async (locationMock, expectedInvocationParams) => { useLocation.mockImplementation(locationMock); renderSideBar(); expect(navigate).toHaveBeenCalledTimes(0); const backDetailViewButton = screen.getByTestId('sideBar-backDetailViewButton'); - userEvent.click(backDetailViewButton); + await userEvent.click(backDetailViewButton); expect(navigate).toHaveBeenCalledTimes(1); expect(navigate).toHaveBeenCalledWith(expectedInvocationParams, {}); }; - test('hides the report detail view if it was opened but user clicked the back button', () => { + test('hides the report detail view if it was opened but user clicked the back button', async () => { useLocationMock = jest.fn((() => ({ pathname: '/events/new' }))); - assertBehaviorOfDetailViewBackButton(useLocationMock, -1); + await assertBehaviorOfDetailViewBackButton(useLocationMock, -1); }); - test('hides the patrol detail view if it was opened but user clicked the back button', () => { + test('hides the patrol detail view if it was opened but user clicked the back button', async () => { useLocationMock = jest.fn((() => ({ pathname: '/patrols/new' }))); - assertBehaviorOfDetailViewBackButton(useLocationMock, -1); + await assertBehaviorOfDetailViewBackButton(useLocationMock, -1); }); - test('return to report feed when user clicked the back button coming from a deep link', () => { + test('return to report feed when user clicked the back button coming from a deep link', async () => { useLocationMock = jest.fn((() => ({ pathname: '/events/123123', key: 'default' }))); - assertBehaviorOfDetailViewBackButton(useLocationMock, '/events'); + await assertBehaviorOfDetailViewBackButton(useLocationMock, '/events'); }); - test('return to patrol feed when user clicked the back button coming from a deep link', () => { + test('return to patrol feed when user clicked the back button coming from a deep link', async () => { useLocationMock = jest.fn((() => ({ pathname: '/patrols/123123', key: 'default' }))); - assertBehaviorOfDetailViewBackButton(useLocationMock, '/patrols'); + await assertBehaviorOfDetailViewBackButton(useLocationMock, '/patrols'); }); - test('return to report feed when user clicked the back button coming from a deep link which required login', () => { + test('return to report feed when user clicked the back button coming from a deep link which required login', async () => { useLocationMock = jest.fn((() => ({ pathname: '/events/123123', key: '2324e2', state: { comesFromLogin: true } }))); - assertBehaviorOfDetailViewBackButton(useLocationMock, '/events'); + await assertBehaviorOfDetailViewBackButton(useLocationMock, '/events'); }); - test('return to report feed when user clicked the back button coming from a deep link with lngLat value', () => { + test('return to report feed when user clicked the back button coming from a deep link with lngLat value', async () => { useLocationMock = jest.fn((() => ({ pathname: '/events/123123', key: '2324e2', state: { comesFromLngLatRedirection: true } }))); - assertBehaviorOfDetailViewBackButton(useLocationMock, '/events'); + await assertBehaviorOfDetailViewBackButton(useLocationMock, '/events'); }); test('redirects to map if a tab is not recognized', async () => { @@ -332,7 +332,7 @@ describe('SideBar', () => { expect(navigate).toHaveBeenCalledTimes(0); - userEvent.keyboard('{Escape}'); + await userEvent.keyboard('{Escape}'); expect(navigate).toHaveBeenCalledTimes(1); expect(navigate).toHaveBeenCalledWith('/events'); @@ -345,7 +345,7 @@ describe('SideBar', () => { expect(navigate).toHaveBeenCalledTimes(0); - userEvent.keyboard('{Escape}'); + await userEvent.keyboard('{Escape}'); expect(navigate).toHaveBeenCalledTimes(1); expect(navigate).toHaveBeenCalledWith('/patrols'); diff --git a/src/SideBar/useFetchPatrolsFeed/index.test.js b/src/SideBar/useFetchPatrolsFeed/index.test.js index 948b3eb34..0f8b2f12e 100644 --- a/src/SideBar/useFetchPatrolsFeed/index.test.js +++ b/src/SideBar/useFetchPatrolsFeed/index.test.js @@ -1,10 +1,9 @@ import React from 'react'; import { http, HttpResponse } from 'msw'; import { Provider } from 'react-redux'; -import { renderHook } from '@testing-library/react-hooks'; import { setupServer } from 'msw/node'; -import { waitFor } from '@testing-library/react'; +import { renderHook, waitFor } from '../../test-utils'; import { INITIAL_FILTER_STATE as INITIAL_PATROL_FILTER_STATE } from '../../ducks/patrol-filter'; import { mockStore } from '../../__test-helpers/MockStore'; import patrols from '../../__test-helpers/fixtures/patrols'; diff --git a/src/SideBar/useReportsFeed/index.test.js b/src/SideBar/useReportsFeed/index.test.js index 7a770595f..1f0630e20 100644 --- a/src/SideBar/useReportsFeed/index.test.js +++ b/src/SideBar/useReportsFeed/index.test.js @@ -1,10 +1,9 @@ import React from 'react'; import { http, HttpResponse } from 'msw'; import { Provider } from 'react-redux'; -import { renderHook } from '@testing-library/react-hooks'; import { setupServer } from 'msw/node'; -import { waitFor } from '@testing-library/react'; +import { renderHook, waitFor } from '../../test-utils'; import { DEFAULT_EVENT_SORT } from '../../constants'; import { events, eventWithPoint } from '../../__test-helpers/fixtures/events'; import { EVENTS_API_URL, EVENT_API_URL } from '../../ducks/events'; diff --git a/src/SidebarScrollContext/index.test.js b/src/SidebarScrollContext/index.test.js index a9d477837..be4cdc5e5 100644 --- a/src/SidebarScrollContext/index.test.js +++ b/src/SidebarScrollContext/index.test.js @@ -1,10 +1,10 @@ import React, { useEffect } from 'react'; -import { SidebarScrollContext, SidebarScrollProvider } from './index'; -import { renderHook } from '@testing-library/react-hooks'; import { useContext } from 'react'; -import { render, screen } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; +import { act, renderHook, render, screen } from '../test-utils'; +import { SidebarScrollContext, SidebarScrollProvider } from './index'; + describe('SidebarScrollContext', () => { it('renders empty scrollPositionValues', () => { @@ -18,7 +18,7 @@ describe('SidebarScrollContext', () => { const wrapper = ({ children }) => {children}; const { result } = renderHook( () => useContext(SidebarScrollContext), { wrapper }); const { current: { setScrollPosition } } = result; - setScrollPosition(tab, scrollPosition); + act(() => setScrollPosition(tab, scrollPosition)); expect(result.current.scrollPositionValues).toEqual({ [tab]: scrollPosition }); }); diff --git a/src/StaticSensorsLayer/index.test.js b/src/StaticSensorsLayer/index.test.js index ef424fe0a..23dedb020 100644 --- a/src/StaticSensorsLayer/index.test.js +++ b/src/StaticSensorsLayer/index.test.js @@ -1,9 +1,8 @@ import React from 'react'; -import { render, waitFor } from '@testing-library/react'; +import { act, render, waitFor } from '@testing-library/react'; import { Provider } from 'react-redux'; import { createMapMock } from '../__test-helpers/mocks'; -import { runAllTimers } from '../__test-helpers/timers.js'; import { mockStore } from '../__test-helpers/MockStore'; import { MapContext } from '../App'; @@ -161,7 +160,7 @@ describe('adding layers to the map', () => { map.queryRenderedFeatures.mockReturnValue([staticSubjectFeature]); map.__test__.fireHandlers('click', { preventDefault() {}, point: { latitude: 66, longitude: 66 } }); - await runAllTimers(); + jest.runAllTimers(); }); test('showing the subject popup', async () => { @@ -173,7 +172,7 @@ describe('adding layers to the map', () => { test('setting the map filter to hide the selected subject\'s marker', async () => { map.__test__.fireHandlers('click', { preventDefault() {}, point: { latitude: 66, longitude: 66 } }); - await runAllTimers(); + act(() => jest.runAllTimers()); expect(map.setFilter).toHaveBeenCalledTimes(4); diff --git a/src/SubjectControls/index.test.js b/src/SubjectControls/index.test.js index ec81f551c..6380b9178 100644 --- a/src/SubjectControls/index.test.js +++ b/src/SubjectControls/index.test.js @@ -69,7 +69,7 @@ describe('SubjectControls', () => { ); const button = await screen.findByTestId(buttonTestId); - userEvent.click(button); + await userEvent.click(button); expect(addModal).toHaveBeenCalledWith(expect.objectContaining({ subjectId: subject.id, subjectIsStatic: subjectIsStatic(subject), title: `Historical Data: ${subject.name}` })); }); diff --git a/src/SubjectGroupList/SubjectListItem.test.js b/src/SubjectGroupList/SubjectListItem.test.js index 877a3313d..79b6e919a 100644 --- a/src/SubjectGroupList/SubjectListItem.test.js +++ b/src/SubjectGroupList/SubjectListItem.test.js @@ -34,7 +34,7 @@ test('rendering without crashing', () => { }); describe('Rendering subject list item', () => { - beforeEach(async () => { + beforeEach(() => { map = createMapMock(); }); diff --git a/src/SubjectHistoricalDataModal/index.js b/src/SubjectHistoricalDataModal/index.js index a257e988b..a001b2936 100644 --- a/src/SubjectHistoricalDataModal/index.js +++ b/src/SubjectHistoricalDataModal/index.js @@ -1,8 +1,8 @@ import React, { memo, useEffect, useState } from 'react'; import flatten from 'lodash/flatten'; import Modal from 'react-bootstrap/Modal'; -import Pagination from 'react-js-pagination'; import startCase from 'lodash/startCase'; +import Pagination from 'react-bootstrap/Pagination'; import Table from 'react-bootstrap/Table'; import unionBy from 'lodash/unionBy'; import { useDispatch, useSelector } from 'react-redux'; @@ -16,7 +16,7 @@ import LoadingOverlay from '../LoadingOverlay'; import * as styles from './styles.module.scss'; -export const DISPLAYED_PAGES_LIMIT = 5; +export const DISPLAYED_PAGE_ITEMS_COUNT = 5; export const ITEMS_PER_PAGE = 10; export const SORT_BY = '-recorded_at'; @@ -26,6 +26,26 @@ export const getObservationUniqProperties = (observations) => { return uniqPropertiesByLabel.map((property) => property.label); }; +const getPageItemNumbers = (pagesCount, activePage) => { + let start = 1; + let end = DISPLAYED_PAGE_ITEMS_COUNT; + if (pagesCount > DISPLAYED_PAGE_ITEMS_COUNT) { + const halfDisplayedPageItemsCount = Math.floor(DISPLAYED_PAGE_ITEMS_COUNT / 2); + start = activePage - halfDisplayedPageItemsCount; + end = activePage + halfDisplayedPageItemsCount; + + if (start < 1) { + start = 1; + end = DISPLAYED_PAGE_ITEMS_COUNT; + } else if (end > pagesCount) { + start = pagesCount - DISPLAYED_PAGE_ITEMS_COUNT + 1; + end = pagesCount; + } + } + + return Array.from({ length: end - start + 1 }, (_, i) => start + i); +}; + const ObservationRow = ({ observation, observationProperties, subjectIsStatic }) => { const { t } = useTranslation('subjects', { keyPrefix: 'subjectHistoricalDataModal.observationRow' }); @@ -82,6 +102,9 @@ const SubjectHistoricalDataModal = ({ subjectId, subjectIsStatic, title }) => { }); }, [activePage, dispatch, subjectId]); + const pagesCount = Math.ceil(observationsCount / ITEMS_PER_PAGE); + const pageItemNumbers = getPageItemNumbers(pagesCount, activePage); + return <> {title} @@ -111,15 +134,23 @@ const SubjectHistoricalDataModal = ({ subjectId, subjectIsStatic, title }) => { - {observationsCount > ITEMS_PER_PAGE && setActivePage(page)} - pageRangeDisplayed={DISPLAYED_PAGES_LIMIT} - totalItemsCount={observationsCount} - />} + {observationsCount > ITEMS_PER_PAGE && + setActivePage(1)} /> + + setActivePage(activePage - 1)} /> + + {pageItemNumbers.map((pageItemNumber) => setActivePage(pageItemNumber)} + > + {pageItemNumber} + )} + + setActivePage(activePage + 1)} /> + + setActivePage(pagesCount)} /> + } ; }; diff --git a/src/SubjectHistoricalDataModal/index.test.js b/src/SubjectHistoricalDataModal/index.test.js index 73d8d62b0..2a50f046f 100644 --- a/src/SubjectHistoricalDataModal/index.test.js +++ b/src/SubjectHistoricalDataModal/index.test.js @@ -70,7 +70,7 @@ describe('SubjectHistoricalDataModal', () => { const table = await screen.getByRole('table'); expect(table).toBeDefined(); - const pagination = await screen.getByRole('list'); + const pagination = await screen.findByRole('list'); expect(pagination).toBeDefined(); }); @@ -104,11 +104,11 @@ describe('SubjectHistoricalDataModal', () => { await waitFor(() => { paginationListItems = screen.getAllByRole('listitem'); - pageLink = within(paginationListItems[3]).getByRole('link'); + pageLink = within(paginationListItems[3]).getByRole('button'); }); expect(pageLink).toHaveTextContent('2'); - userEvent.click(pageLink); + await userEvent.click(pageLink); expect(fetchObservationsForSubject).toHaveBeenCalledWith({ 'page': 2, 'page_size': ITEMS_PER_PAGE, 'subject_id': 'fake-id', sort_by: SORT_BY }); }); diff --git a/src/SubjectHistoricalDataModal/styles.module.scss b/src/SubjectHistoricalDataModal/styles.module.scss index 589a4bc7f..4e2bf521d 100644 --- a/src/SubjectHistoricalDataModal/styles.module.scss +++ b/src/SubjectHistoricalDataModal/styles.module.scss @@ -1,4 +1,4 @@ -@import '../common/styles/vars/colors'; +@use '../common/styles/vars/colors'; .modalBody { display: flex; @@ -9,13 +9,13 @@ table { margin-bottom: 0rem; - color: $dark-gray; + color: colors.$dark-gray; font-size: 0.87rem; thead { font-size: 1rem; - background-color: $medium-light-gray; - color: $off-white; + background-color: colors.$medium-light-gray; + color: colors.$off-white; th { font-weight: 400; @@ -25,7 +25,7 @@ } .noDataLabel { - color:$medium-light-gray; + color: colors.$medium-light-gray; font-size: 0.62rem; font-style: italic; } @@ -37,7 +37,7 @@ ul { margin-top: 1.5rem; font-size: 0.75rem; - color: $off-white; + color: colors.$off-white; } } @@ -46,6 +46,6 @@ font-size: 0.75rem; font-style: normal; font-weight: 500; - color: $dark-gray; + color: colors.$dark-gray; } -} \ No newline at end of file +} diff --git a/src/SubjectPopup/index.test.js b/src/SubjectPopup/index.test.js index 2c700b049..edb973715 100644 --- a/src/SubjectPopup/index.test.js +++ b/src/SubjectPopup/index.test.js @@ -89,7 +89,7 @@ describe('SubjectPopup', () => { test('toggling multiple device properties', async () => { const additionalPropsToggleBtn = await screen.getByTestId('additional-props-toggle-btn'); - userEvent.click(additionalPropsToggleBtn); + await userEvent.click(additionalPropsToggleBtn); const additionalProps = await screen.findByTestId('additional-props'); const deviceStatusProps = subjectFeatureWithMultipleDeviceProps.properties.device_status_properties; @@ -99,7 +99,7 @@ describe('SubjectPopup', () => { if (value.length) expect(additionalProps).toHaveTextContent(value); }); - userEvent.click(additionalPropsToggleBtn); + await userEvent.click(additionalPropsToggleBtn); expect(additionalProps).not.toBeInTheDocument(); }); diff --git a/src/SystemStatus/index.js b/src/SystemStatus/index.js index acb4f9f89..b1e9a9b32 100644 --- a/src/SystemStatus/index.js +++ b/src/SystemStatus/index.js @@ -93,7 +93,9 @@ const SystemStatus = () => { {t(statusSummary || 'UNHEALTHY' )} - {isOpen ? : } + {isOpen + ? + : }
    diff --git a/src/SystemStatus/index.test.js b/src/SystemStatus/index.test.js index df3040672..1be2f8dad 100644 --- a/src/SystemStatus/index.test.js +++ b/src/SystemStatus/index.test.js @@ -83,7 +83,7 @@ describe('SystemStatus', () => { expect((await screen.queryByText('EarthRanger Realtime'))).toBeNull(); const statusIndicatorToggle = await screen.findByRole('button'); - userEvent.click(statusIndicatorToggle); + await userEvent.click(statusIndicatorToggle); expect((await screen.findByText('Network'))).toBeDefined(); expect((await screen.findByText('EarthRanger Server 2.43.1-dev.30033'))).toBeDefined(); @@ -97,15 +97,15 @@ describe('SystemStatus', () => { ); - expect((await screen.findByText('arrow-down-small.svg'))).toBeDefined(); - expect((await screen.queryByText('arrow-up-small.svg'))).toBeNull(); + expect((await screen.findByTestId('arrow-down-small-icon'))).toBeDefined(); + expect((await screen.queryByTestId('arrow-up-small-icon'))).toBeNull(); expect((await screen.findByTestId('systemStatus-indicator'))).not.toHaveClass('open'); const statusIndicatorToggle = await screen.findByRole('button'); - userEvent.click(statusIndicatorToggle); + await userEvent.click(statusIndicatorToggle); - expect((await screen.queryByText('arrow-down-small.svg'))).toBeNull(); - expect((await screen.findByText('arrow-up-small.svg'))).toBeDefined(); + expect((await screen.queryByTestId('arrow-down-small-icon'))).toBeNull(); + expect((await screen.findByTestId('arrow-up-small-icon'))).toBeDefined(); expect((await screen.findByTestId('systemStatus-indicator'))).toHaveClass('open'); }); }); diff --git a/src/TextCopyBtn/index.js b/src/TextCopyBtn/index.js index 27fd39959..b65dd6382 100644 --- a/src/TextCopyBtn/index.js +++ b/src/TextCopyBtn/index.js @@ -11,7 +11,7 @@ const TOAST_AUTOCLOSE_TIME = 2000; const TextCopyBtn = ({ className = '', getText = null, - icon = , + icon = , label = '', permitPropagation = false, successMessage = null, diff --git a/src/TextCopyBtn/index.test.js b/src/TextCopyBtn/index.test.js index 0f0dfcb0b..0066a155a 100644 --- a/src/TextCopyBtn/index.test.js +++ b/src/TextCopyBtn/index.test.js @@ -29,7 +29,7 @@ describe('TextCopyBtn', () => { expect(toast.info).not.toHaveBeenCalled(); - userEvent.click(screen.getByLabelText('Copy to clipboard')); + await userEvent.click(screen.getByLabelText('Copy to clipboard')); expect(window.navigator.clipboard.writeText).toHaveBeenCalledTimes(1); expect(window.navigator.clipboard.writeText).toHaveBeenCalledWith('text'); @@ -50,7 +50,7 @@ describe('TextCopyBtn', () => { expect(toast.info).not.toHaveBeenCalled(); - userEvent.click(screen.getByLabelText('Copy to clipboard')); + await userEvent.click(screen.getByLabelText('Copy to clipboard')); expect(window.navigator.clipboard.writeText).toHaveBeenCalledTimes(1); expect(window.navigator.clipboard.writeText).toHaveBeenCalledWith('text gotten'); @@ -68,7 +68,7 @@ describe('TextCopyBtn', () => { renderTextCopyBtn({ successMessage: 'success message' }); window.navigator.clipboard = { writeText: jest.fn() }; - userEvent.click(screen.getByLabelText('Copy to clipboard')); + await userEvent.click(screen.getByLabelText('Copy to clipboard')); await waitFor(() => { expect(toast.info).toHaveBeenCalledTimes(1); @@ -80,15 +80,15 @@ describe('TextCopyBtn', () => { }); test('shows a custom icon in the button', async () => { - renderTextCopyBtn({ icon: }); + renderTextCopyBtn({ icon: }); - expect(screen.getByLabelText('Copy to clipboard')).toHaveTextContent('link.svg'); + expect(screen.getByTestId('link-icon')).toBeVisible(); }); test('shows a default icon in the button', async () => { renderTextCopyBtn(); - expect(screen.getByLabelText('Copy to clipboard')).toHaveTextContent('clipboard-icon.svg'); + expect(screen.getByTestId('clipboard-icon')).toBeVisible(); }); test('shows text inside the button', async () => { diff --git a/src/TimePicker/OptionsPopover/index.test.js b/src/TimePicker/OptionsPopover/index.test.js index 67be182d5..5e1520a9f 100644 --- a/src/TimePicker/OptionsPopover/index.test.js +++ b/src/TimePicker/OptionsPopover/index.test.js @@ -35,19 +35,19 @@ describe('TimePicker - OptionsPopover', () => { jest.restoreAllMocks(); }); - test('focuses the list automatically', () => { + test('focuses the list automatically', async () => { renderOptionsPopover(); expect(screen.getByRole('listbox')).toHaveFocus(); }); - test('matches the width of the target element', () => { + test('matches the width of the target element', async () => { renderOptionsPopover({ target: { current: { offsetWidth: 48 } } }); expect(screen.getByRole('presentation')).toHaveStyle({ width: '48px' }); }); - test('navigates the options with the arrows', () => { + test('navigates the options with the arrows', async () => { renderOptionsPopover(); const optionsList = screen.getByRole('listbox'); @@ -58,28 +58,28 @@ describe('TimePicker - OptionsPopover', () => { expect(options[1]).toHaveAttribute('aria-selected', 'false'); expect(options[2]).toHaveAttribute('aria-selected', 'false'); - userEvent.keyboard('[ArrowDown]'); + await userEvent.keyboard('[ArrowDown]'); expect(optionsList).toHaveAttribute('aria-activedescendant', '00:30'); expect(options[0]).toHaveAttribute('aria-selected', 'false'); expect(options[1]).toHaveAttribute('aria-selected', 'true'); expect(options[2]).toHaveAttribute('aria-selected', 'false'); - userEvent.keyboard('[ArrowDown]'); + await userEvent.keyboard('[ArrowDown]'); expect(optionsList).toHaveAttribute('aria-activedescendant', '01:00'); expect(options[0]).toHaveAttribute('aria-selected', 'false'); expect(options[1]).toHaveAttribute('aria-selected', 'false'); expect(options[2]).toHaveAttribute('aria-selected', 'true'); - userEvent.keyboard('[ArrowUp]'); + await userEvent.keyboard('[ArrowUp]'); expect(optionsList).toHaveAttribute('aria-activedescendant', '00:30'); expect(options[0]).toHaveAttribute('aria-selected', 'false'); expect(options[1]).toHaveAttribute('aria-selected', 'true'); expect(options[2]).toHaveAttribute('aria-selected', 'false'); - userEvent.keyboard('[ArrowUp]'); + await userEvent.keyboard('[ArrowUp]'); expect(optionsList).toHaveAttribute('aria-activedescendant', '00:00'); expect(options[0]).toHaveAttribute('aria-selected', 'true'); @@ -87,7 +87,7 @@ describe('TimePicker - OptionsPopover', () => { expect(options[2]).toHaveAttribute('aria-selected', 'false'); }); - test('selects the option closest to the current value', () => { + test('selects the option closest to the current value', async () => { renderOptionsPopover({ value: '15:25' }); const options = screen.getAllByRole('option'); @@ -95,15 +95,15 @@ describe('TimePicker - OptionsPopover', () => { expect(options[31]).toHaveAttribute('aria-selected', 'true'); }); - test('changes to the option selected by pressing enter', () => { + test('changes to the option selected by pressing enter', async () => { renderOptionsPopover(); expect(onChange).not.toHaveBeenCalled(); expect(onClose).not.toHaveBeenCalled(); expect(optionsPopoverButtonFocus).not.toHaveBeenCalled(); - userEvent.keyboard('[ArrowDown]'); - userEvent.keyboard('{Enter}'); + await userEvent.keyboard('[ArrowDown]'); + await userEvent.keyboard('{Enter}'); expect(onChange).toHaveBeenCalledTimes(1); expect(onChange).toHaveBeenCalledWith('00:30'); @@ -111,15 +111,15 @@ describe('TimePicker - OptionsPopover', () => { expect(optionsPopoverButtonFocus).toHaveBeenCalledTimes(1); }); - test('changes to the option selected by pressing space', () => { + test('changes to the option selected by pressing space', async () => { renderOptionsPopover(); expect(onChange).not.toHaveBeenCalled(); expect(onClose).not.toHaveBeenCalled(); expect(optionsPopoverButtonFocus).not.toHaveBeenCalled(); - userEvent.keyboard('[ArrowDown]'); - userEvent.keyboard('[Space]'); + await userEvent.keyboard('[ArrowDown]'); + await userEvent.keyboard('[Space]'); expect(onChange).toHaveBeenCalledTimes(1); expect(onChange).toHaveBeenCalledWith('00:30'); @@ -127,14 +127,14 @@ describe('TimePicker - OptionsPopover', () => { expect(optionsPopoverButtonFocus).toHaveBeenCalledTimes(1); }); - test('changes to the option selected by clicking', () => { + test('changes to the option selected by clicking', async () => { renderOptionsPopover(); expect(onChange).not.toHaveBeenCalled(); expect(onClose).not.toHaveBeenCalled(); expect(optionsPopoverButtonFocus).not.toHaveBeenCalled(); - userEvent.click(screen.getByText('12:30 AM')); + await userEvent.click(screen.getByText('12:30 AM')); expect(onChange).toHaveBeenCalledTimes(1); expect(onChange).toHaveBeenCalledWith('00:30'); @@ -142,19 +142,19 @@ describe('TimePicker - OptionsPopover', () => { expect(optionsPopoverButtonFocus).toHaveBeenCalledTimes(1); }); - test('closes the popover when user presses escape and focuses the options popover button', () => { + test('closes the popover when user presses escape and focuses the options popover button', async () => { renderOptionsPopover(); expect(onClose).not.toHaveBeenCalled(); expect(optionsPopoverButtonFocus).not.toHaveBeenCalled(); - userEvent.keyboard('{Escape}'); + await userEvent.keyboard('{Escape}'); expect(onClose).toHaveBeenCalledTimes(1); expect(optionsPopoverButtonFocus).toHaveBeenCalledTimes(1); }); - test('closes the popover when user clicks outside of it', () => { + test('closes the popover when user clicks outside of it', async () => { render( <>
    @@ -178,12 +178,12 @@ describe('TimePicker - OptionsPopover', () => { expect(onClose).not.toHaveBeenCalled(); - userEvent.click(screen.getByTestId('outside')); + await userEvent.click(screen.getByTestId('outside')); expect(onClose).toHaveBeenCalledTimes(1); }); - test('sets a custom interval for the options', () => { + test('sets a custom interval for the options', async () => { renderOptionsPopover({ minutesInterval: 15 }); const options = screen.getAllByRole('option'); @@ -194,7 +194,7 @@ describe('TimePicker - OptionsPopover', () => { expect(options[2]).toHaveTextContent('12:30 AM'); }); - test('shows the duration ellapsed from the min time', () => { + test('shows the duration ellapsed from the min time', async () => { renderOptionsPopover({ min: '12:00', showDurationFromMin: true }); const options = screen.getAllByRole('option'); diff --git a/src/TimePicker/index.test.js b/src/TimePicker/index.test.js index b88312d1b..8ca366076 100644 --- a/src/TimePicker/index.test.js +++ b/src/TimePicker/index.test.js @@ -29,13 +29,13 @@ describe('TimePicker', () => { jest.restoreAllMocks(); }); - test('adds a custom class name', () => { + test('adds a custom class name', async () => { renderTimePicker({ className: 'className' }); expect(screen.getByTestId('timePicker')).toHaveClass('className'); }); - test('does not disable the time picker', () => { + test('does not disable the time picker', async () => { renderTimePicker(); const timePicker = screen.getByTestId('timePicker'); @@ -47,7 +47,7 @@ describe('TimePicker', () => { expect(screen.getByLabelText('Open time options')).not.toBeDisabled(); }); - test('disables the time picker', () => { + test('disables the time picker', async () => { renderTimePicker({ disabled: true }); const timePicker = screen.getByTestId('timePicker'); @@ -59,7 +59,7 @@ describe('TimePicker', () => { expect(screen.getByLabelText('Open time options')).toBeDisabled(); }); - test('sets the name to an input with the time picker value', () => { + test('sets the name to an input with the time picker value', async () => { renderTimePicker({ name: 'time-picker-name', value: '06:30' }); const timePickerInput = screen.getByTestId('timePicker-input'); @@ -68,13 +68,13 @@ describe('TimePicker', () => { expect(timePickerInput).toHaveValue('06:30'); }); - test('blurs the time picker', () => { + test('blurs the time picker', async () => { const onBlur = jest.fn(); renderTimePicker({ onBlur }); const timePicker = screen.getByTestId('timePicker'); - userEvent.click(timePicker); + await userEvent.click(timePicker); expect(onBlur).not.toHaveBeenCalled(); @@ -83,19 +83,19 @@ describe('TimePicker', () => { expect(onBlur).toHaveBeenCalledTimes(1); }); - test('focuses the time picker when focusing one of the inner elements', () => { + test('focuses the time picker when focusing one of the inner elements', async () => { const onFocus = jest.fn(); renderTimePicker({ onFocus }); expect(onFocus).not.toHaveBeenCalled(); - userEvent.click(screen.getByLabelText('Hour')); + await userEvent.click(screen.getByLabelText('Hour')); expect(onFocus).toHaveBeenCalledTimes(1); }); - test('does not set the time picker as read only', () => { + test('does not set the time picker as read only', async () => { renderTimePicker(); expect(screen.getByLabelText('Hour')).not.toHaveAttribute('readonly'); @@ -104,7 +104,7 @@ describe('TimePicker', () => { expect(screen.getByLabelText('Open time options')).not.toBeDisabled(); }); - test('sets the time picker as read only', () => { + test('sets the time picker as read only', async () => { renderTimePicker({ readOnly: true }); const hourInput = screen.getByLabelText('Hour'); @@ -116,38 +116,38 @@ describe('TimePicker', () => { expect(timePeriodInput).toHaveAttribute('readonly'); expect(screen.getByLabelText('Open time options')).toBeDisabled(); - userEvent.click(hourInput); - userEvent.keyboard('[ArrowDown]'); - userEvent.keyboard('[ArrowUp]'); + await userEvent.click(hourInput); + await userEvent.keyboard('[ArrowDown]'); + await userEvent.keyboard('[ArrowUp]'); - userEvent.click(minuteInput); - userEvent.keyboard('[ArrowDown]'); - userEvent.keyboard('[ArrowUp]'); + await userEvent.click(minuteInput); + await userEvent.keyboard('[ArrowDown]'); + await userEvent.keyboard('[ArrowUp]'); - userEvent.click(timePeriodInput); - userEvent.keyboard('[ArrowDown]'); - userEvent.keyboard('[ArrowUp]'); - userEvent.type(timePeriodInput, 'a'); - userEvent.type(timePeriodInput, 'p'); + await userEvent.click(timePeriodInput); + await userEvent.keyboard('[ArrowDown]'); + await userEvent.keyboard('[ArrowUp]'); + await userEvent.type(timePeriodInput, 'a'); + await userEvent.type(timePeriodInput, 'p'); expect(onChange).not.toHaveBeenCalled(); }); - test('does not set the time picker as required', () => { + test('does not set the time picker as required', async () => { renderTimePicker(); expect(screen.getByLabelText('Hour')).not.toBeRequired(); expect(screen.getByLabelText('Minute')).not.toBeRequired(); }); - test('sets the time picker as required', () => { + test('sets the time picker as required', async () => { renderTimePicker({ required: true }); expect(screen.getByLabelText('Hour')).toBeRequired(); expect(screen.getByLabelText('Minute')).toBeRequired(); }); - test('uses a 12 hour format depending on the locale', () => { + test('uses a 12 hour format depending on the locale', async () => { renderTimePicker({ value: '20:00' }); const timePeriodInput = screen.getByLabelText('Time period'); @@ -158,7 +158,7 @@ describe('TimePicker', () => { expect(timePeriodInput).toHaveValue('PM'); }); - test('uses a 24 hour format depending on the locale', () => { + test('uses a 24 hour format depending on the locale', async () => { shouldUse12HourFormat.mockImplementation(() => false); renderTimePicker({ value: '20:00' }); @@ -168,31 +168,31 @@ describe('TimePicker', () => { expect(screen.queryByLabelText('Time period')).toBeNull(); }); - test('autofills the first digit when the user modifies the hour input with a number over 1 for 12 hour format', () => { + test('autofills the first digit when the user modifies the hour input with a number over 1 for 12 hour format', async () => { renderTimePicker(); expect(onChange).not.toHaveBeenCalled(); - userEvent.type(screen.getByLabelText('Hour'), '2'); + await userEvent.type(screen.getByLabelText('Hour'), '2'); expect(onChange).toHaveBeenCalledTimes(1); expect(onChange).toHaveBeenCalledWith('02:'); }); - test('autofills the first digit when the user modifies the hour input with a number over 2 for 24 hour format', () => { + test('autofills the first digit when the user modifies the hour input with a number over 2 for 24 hour format', async () => { shouldUse12HourFormat.mockImplementation(() => false); renderTimePicker(); expect(onChange).not.toHaveBeenCalled(); - userEvent.type(screen.getByLabelText('Hour'), '3'); + await userEvent.type(screen.getByLabelText('Hour'), '3'); expect(onChange).toHaveBeenCalledTimes(1); expect(onChange).toHaveBeenCalledWith('03:'); }); - test('autofills the first digit when the hour input is blurred and it has a digit below 2 for 12 hour format', () => { + test('autofills the first digit when the hour input is blurred and it has a digit below 2 for 12 hour format', async () => { renderTimePicker({ value: '1:' }); expect(onChange).not.toHaveBeenCalled(); @@ -203,7 +203,7 @@ describe('TimePicker', () => { expect(onChange).toHaveBeenCalledWith('01:'); }); - test('does not autofill the first digit when the hour input is blurred and it has a digit below 2 for 12 hour format if the field is readonly', () => { + test('does not autofill the first digit when the hour input is blurred and it has a digit below 2 for 12 hour format if the field is readonly', async () => { renderTimePicker({ readOnly: true, value: '1:' }); fireEvent.blur(screen.getByLabelText('Hour')); @@ -211,7 +211,7 @@ describe('TimePicker', () => { expect(onChange).not.toHaveBeenCalled(); }); - test('autofills the first digit when the hour input is blurred and it has a digit below 3 for 24 hour format', () => { + test('autofills the first digit when the hour input is blurred and it has a digit below 3 for 24 hour format', async () => { shouldUse12HourFormat.mockImplementation(() => false); renderTimePicker({ value: '2:' }); @@ -224,7 +224,7 @@ describe('TimePicker', () => { expect(onChange).toHaveBeenCalledWith('02:'); }); - test('does not autofill the first digit when the hour input is blurred and it has a digit below 3 for 24 hour format if the field is readonly', () => { + test('does not autofill the first digit when the hour input is blurred and it has a digit below 3 for 24 hour format if the field is readonly', async () => { shouldUse12HourFormat.mockImplementation(() => false); renderTimePicker({ readOnly: true, value: '2:' }); @@ -234,309 +234,309 @@ describe('TimePicker', () => { expect(onChange).not.toHaveBeenCalled(); }); - test('changes when the user modifies the hour input with a valid value', () => { + test('changes when the user modifies the hour input with a valid value', async () => { renderTimePicker(); expect(onChange).not.toHaveBeenCalled(); - userEvent.type(screen.getByLabelText('Hour'), '1'); + await userEvent.type(screen.getByLabelText('Hour'), '1'); expect(onChange).toHaveBeenCalledTimes(1); expect(onChange).toHaveBeenCalledWith('1:'); }); - test('changes when the user clears the hour input', () => { + test('changes when the user clears the hour input', async () => { renderTimePicker({ value: '1:' }); expect(onChange).not.toHaveBeenCalled(); - userEvent.type(screen.getByLabelText('Hour'), '{backspace}'); + await userEvent.type(screen.getByLabelText('Hour'), '{backspace}'); expect(onChange).toHaveBeenCalledTimes(1); expect(onChange).toHaveBeenCalledWith(EMPTY_TIME_VALUE); }); - test('does not change when the user modifies the hour input with an invalid value', () => { + test('does not change when the user modifies the hour input with an invalid value', async () => { renderTimePicker(); expect(onChange).not.toHaveBeenCalled(); - userEvent.type(screen.getByLabelText('Hour'), 'a'); + await userEvent.type(screen.getByLabelText('Hour'), 'a'); expect(onChange).not.toHaveBeenCalled(); }); - test('sets the max hour as the new hour value if the new hour is above the max hour for 24 hour format', () => { + test('sets the max hour as the new hour value if the new hour is above the max hour for 24 hour format', async () => { shouldUse12HourFormat.mockImplementation(() => false); const { rerender } = renderTimePicker({ max: '15:00' }); - userEvent.click(screen.getByLabelText('Hour')); + await userEvent.click(screen.getByLabelText('Hour')); rerender(); expect(onChange).not.toHaveBeenCalled(); - userEvent.keyboard('7'); + await userEvent.keyboard('7'); expect(onChange).toHaveBeenCalledTimes(1); expect(onChange).toHaveBeenCalledWith('15:'); }); - test('sets the max minute as the new minute value if the new hour is the max value and the old minute was above the max minute for 24 hour format', () => { + test('sets the max minute as the new minute value if the new hour is the max value and the old minute was above the max minute for 24 hour format', async () => { shouldUse12HourFormat.mockImplementation(() => false); const { rerender } = renderTimePicker({ max: '15:00' }); - userEvent.click(screen.getByLabelText('Hour')); + await userEvent.click(screen.getByLabelText('Hour')); rerender(); expect(onChange).not.toHaveBeenCalled(); - userEvent.keyboard('5'); + await userEvent.keyboard('5'); expect(onChange).toHaveBeenCalledTimes(1); expect(onChange).toHaveBeenCalledWith('15:00'); }); - test('sets the min hour as the new hour value if the new hour is below the min hour for 24 hour format', () => { + test('sets the min hour as the new hour value if the new hour is below the min hour for 24 hour format', async () => { shouldUse12HourFormat.mockImplementation(() => false); const { rerender } = renderTimePicker({ min: '15:00' }); - userEvent.click(screen.getByLabelText('Hour')); + await userEvent.click(screen.getByLabelText('Hour')); rerender(); - userEvent.keyboard('1'); + await userEvent.keyboard('1'); expect(onChange).toHaveBeenCalled(); expect(onChange).toHaveBeenCalledWith('15:'); }); - test('sets the min minute as the new minute value if the new hour is the min value and the old minute was below the min minute for 24 hour format', () => { + test('sets the min minute as the new minute value if the new hour is the min value and the old minute was below the min minute for 24 hour format', async () => { shouldUse12HourFormat.mockImplementation(() => false); const { rerender } = renderTimePicker({ min: '15:30' }); - userEvent.click(screen.getByLabelText('Hour')); + await userEvent.click(screen.getByLabelText('Hour')); rerender(); - userEvent.keyboard('5'); + await userEvent.keyboard('5'); expect(onChange).toHaveBeenCalled(); expect(onChange).toHaveBeenCalledWith('15:30'); }); - test('focuses the minute input if the focus is on the hour input and the user presses the right arrow', () => { + test('focuses the minute input if the focus is on the hour input and the user presses the right arrow', async () => { renderTimePicker(); - userEvent.click(screen.getByLabelText('Hour')); + await userEvent.click(screen.getByLabelText('Hour')); const minuteInput = screen.getByLabelText('Minute'); expect(minuteInput).not.toHaveFocus(); - userEvent.keyboard('[ArrowRight]'); + await userEvent.keyboard('[ArrowRight]'); expect(minuteInput).toHaveFocus(); }); - test('sets the hour to 01 if the input is empty and focused and the user presses the up arrow for 12 hour format', () => { + test('sets the hour to 01 if the input is empty and focused and the user presses the up arrow for 12 hour format', async () => { renderTimePicker(); - userEvent.click(screen.getByLabelText('Hour')); + await userEvent.click(screen.getByLabelText('Hour')); expect(onChange).not.toHaveBeenCalled(); - userEvent.keyboard('[ArrowUp]'); + await userEvent.keyboard('[ArrowUp]'); expect(onChange).toHaveBeenCalledTimes(1); expect(onChange).toHaveBeenCalledWith('01:'); }); - test('sets the hour to 00 if the input is empty and focused and the user presses the up arrow for 24 hour format', () => { + test('sets the hour to 00 if the input is empty and focused and the user presses the up arrow for 24 hour format', async () => { shouldUse12HourFormat.mockImplementation(() => false); renderTimePicker(); - userEvent.click(screen.getByLabelText('Hour')); + await userEvent.click(screen.getByLabelText('Hour')); expect(onChange).not.toHaveBeenCalled(); - userEvent.keyboard('[ArrowUp]'); + await userEvent.keyboard('[ArrowUp]'); expect(onChange).toHaveBeenCalledTimes(1); expect(onChange).toHaveBeenCalledWith('00:'); }); - test('sets the hour to 13: if the input has the value 12 and is focused and the user presses the up arrow for 12 hour format', () => { + test('sets the hour to 13: if the input has the value 12 and is focused and the user presses the up arrow for 12 hour format', async () => { renderTimePicker({ value: '12:' }); - userEvent.click(screen.getByLabelText('Hour')); + await userEvent.click(screen.getByLabelText('Hour')); expect(onChange).not.toHaveBeenCalled(); - userEvent.keyboard('[ArrowUp]'); + await userEvent.keyboard('[ArrowUp]'); expect(onChange).toHaveBeenCalledTimes(1); expect(onChange).toHaveBeenCalledWith('13:'); }); - test('sets the hour to 00 if the input has the value 23 and is focused and the user presses the up arrow for 24 hour format', () => { + test('sets the hour to 00 if the input has the value 23 and is focused and the user presses the up arrow for 24 hour format', async () => { shouldUse12HourFormat.mockImplementation(() => false); renderTimePicker({ value: '23:' }); - userEvent.click(screen.getByLabelText('Hour')); + await userEvent.click(screen.getByLabelText('Hour')); expect(onChange).not.toHaveBeenCalled(); - userEvent.keyboard('[ArrowUp]'); + await userEvent.keyboard('[ArrowUp]'); expect(onChange).toHaveBeenCalledTimes(1); expect(onChange).toHaveBeenCalledWith('00:'); }); - test('increments the hour if the input has a valid value and is focused and the user presses the up arrow for 12 hour format', () => { + test('increments the hour if the input has a valid value and is focused and the user presses the up arrow for 12 hour format', async () => { renderTimePicker({ value: '15:' }); - userEvent.click(screen.getByLabelText('Hour')); + await userEvent.click(screen.getByLabelText('Hour')); expect(onChange).not.toHaveBeenCalled(); - userEvent.keyboard('[ArrowUp]'); + await userEvent.keyboard('[ArrowUp]'); expect(onChange).toHaveBeenCalledTimes(1); expect(onChange).toHaveBeenCalledWith('16:'); }); - test('increments the hour if the input has a valid value and is focused and the user presses the up arrow for 24 hour format', () => { + test('increments the hour if the input has a valid value and is focused and the user presses the up arrow for 24 hour format', async () => { shouldUse12HourFormat.mockImplementation(() => false); renderTimePicker({ value: '15:' }); - userEvent.click(screen.getByLabelText('Hour')); + await userEvent.click(screen.getByLabelText('Hour')); expect(onChange).not.toHaveBeenCalled(); - userEvent.keyboard('[ArrowUp]'); + await userEvent.keyboard('[ArrowUp]'); expect(onChange).toHaveBeenCalledTimes(1); expect(onChange).toHaveBeenCalledWith('16:'); }); - test('sets the hour to 00 if the input is empty and focused and the user presses the down arrow for 12 hour format', () => { + test('sets the hour to 00 if the input is empty and focused and the user presses the down arrow for 12 hour format', async () => { renderTimePicker(); - userEvent.click(screen.getByLabelText('Hour')); + await userEvent.click(screen.getByLabelText('Hour')); expect(onChange).not.toHaveBeenCalled(); - userEvent.keyboard('[ArrowDown]'); + await userEvent.keyboard('[ArrowDown]'); expect(onChange).toHaveBeenCalledTimes(1); expect(onChange).toHaveBeenCalledWith('00:'); }); - test('sets the hour to 23 if the input is empty and focused and the user presses the down arrow for 24 hour format', () => { + test('sets the hour to 23 if the input is empty and focused and the user presses the down arrow for 24 hour format', async () => { shouldUse12HourFormat.mockImplementation(() => false); renderTimePicker(); - userEvent.click(screen.getByLabelText('Hour')); + await userEvent.click(screen.getByLabelText('Hour')); expect(onChange).not.toHaveBeenCalled(); - userEvent.keyboard('[ArrowDown]'); + await userEvent.keyboard('[ArrowDown]'); expect(onChange).toHaveBeenCalledTimes(1); expect(onChange).toHaveBeenCalledWith('23:'); }); - test('sets the hour to 00: if the input has the value 01 and is focused and the user presses the down arrow for 12 hour format', () => { + test('sets the hour to 00: if the input has the value 01 and is focused and the user presses the down arrow for 12 hour format', async () => { renderTimePicker({ value: '01:' }); - userEvent.click(screen.getByLabelText('Hour')); + await userEvent.click(screen.getByLabelText('Hour')); expect(onChange).not.toHaveBeenCalled(); - userEvent.keyboard('[ArrowDown]'); + await userEvent.keyboard('[ArrowDown]'); expect(onChange).toHaveBeenCalledTimes(1); expect(onChange).toHaveBeenCalledWith('00:'); }); - test('sets the hour to 23 if the input has the value 00 and is focused and the user presses the down arrow for 24 hour format', () => { + test('sets the hour to 23 if the input has the value 00 and is focused and the user presses the down arrow for 24 hour format', async () => { shouldUse12HourFormat.mockImplementation(() => false); renderTimePicker({ value: '00:' }); - userEvent.click(screen.getByLabelText('Hour')); + await userEvent.click(screen.getByLabelText('Hour')); expect(onChange).not.toHaveBeenCalled(); - userEvent.keyboard('[ArrowDown]'); + await userEvent.keyboard('[ArrowDown]'); expect(onChange).toHaveBeenCalledTimes(1); expect(onChange).toHaveBeenCalledWith('23:'); }); - test('decrements the hour if the input has a valid value and is focused and the user presses the down arrow for 12 hour format', () => { + test('decrements the hour if the input has a valid value and is focused and the user presses the down arrow for 12 hour format', async () => { renderTimePicker({ value: '15:' }); - userEvent.click(screen.getByLabelText('Hour')); + await userEvent.click(screen.getByLabelText('Hour')); expect(onChange).not.toHaveBeenCalled(); - userEvent.keyboard('[ArrowDown]'); + await userEvent.keyboard('[ArrowDown]'); expect(onChange).toHaveBeenCalledTimes(1); expect(onChange).toHaveBeenCalledWith('14:'); }); - test('decrements the hour if the input has a valid value and is focused and the user presses the down arrow for 24 hour format', () => { + test('decrements the hour if the input has a valid value and is focused and the user presses the down arrow for 24 hour format', async () => { shouldUse12HourFormat.mockImplementation(() => false); renderTimePicker({ value: '15:' }); - userEvent.click(screen.getByLabelText('Hour')); + await userEvent.click(screen.getByLabelText('Hour')); expect(onChange).not.toHaveBeenCalled(); - userEvent.keyboard('[ArrowDown]'); + await userEvent.keyboard('[ArrowDown]'); expect(onChange).toHaveBeenCalledTimes(1); expect(onChange).toHaveBeenCalledWith('14:'); }); - test('focuses the minute input automatically when the user finishes typing a valid hour', () => { + test('focuses the minute input automatically when the user finishes typing a valid hour', async () => { const { rerender } = renderTimePicker(); - userEvent.click(screen.getByLabelText('Hour')); + await userEvent.click(screen.getByLabelText('Hour')); const minuteInput = screen.getByLabelText('Minute'); expect(minuteInput).not.toHaveFocus(); rerender(); - userEvent.keyboard('0'); + await userEvent.keyboard('0'); expect(minuteInput).toHaveFocus(); }); - test('autofills the first digit when the user modifies the minute input with a number over 5', () => { + test('autofills the first digit when the user modifies the minute input with a number over 5', async () => { renderTimePicker(); expect(onChange).not.toHaveBeenCalled(); - userEvent.type(screen.getByLabelText('Minute'), '6'); + await userEvent.type(screen.getByLabelText('Minute'), '6'); expect(onChange).toHaveBeenCalledTimes(1); expect(onChange).toHaveBeenCalledWith(':06'); }); - test('autofills the first digit when the minute input is blurred and it has a digit below 6', () => { + test('autofills the first digit when the minute input is blurred and it has a digit below 6', async () => { renderTimePicker({ value: ':5' }); expect(onChange).not.toHaveBeenCalled(); @@ -547,7 +547,7 @@ describe('TimePicker', () => { expect(onChange).toHaveBeenCalledWith(':05'); }); - test('does not autofill the first digit when the minute input is blurred and it has a digit below 6 if the field is readonly', () => { + test('does not autofill the first digit when the minute input is blurred and it has a digit below 6 if the field is readonly', async () => { renderTimePicker({ readOnly: true, value: ':5' }); fireEvent.blur(screen.getByLabelText('Minute')); @@ -555,191 +555,191 @@ describe('TimePicker', () => { expect(onChange).not.toHaveBeenCalled(); }); - test('changes when the user modifies the minute input with a valid value', () => { + test('changes when the user modifies the minute input with a valid value', async () => { renderTimePicker(); expect(onChange).not.toHaveBeenCalled(); - userEvent.type(screen.getByLabelText('Minute'), '1'); + await userEvent.type(screen.getByLabelText('Minute'), '1'); expect(onChange).toHaveBeenCalledTimes(1); expect(onChange).toHaveBeenCalledWith(':1'); }); - test('changes when the user clears the minute input', () => { + test('changes when the user clears the minute input', async () => { renderTimePicker({ value: ':1' }); expect(onChange).not.toHaveBeenCalled(); - userEvent.type(screen.getByLabelText('Minute'), '{backspace}'); + await userEvent.type(screen.getByLabelText('Minute'), '{backspace}'); expect(onChange).toHaveBeenCalledTimes(1); expect(onChange).toHaveBeenCalledWith(EMPTY_TIME_VALUE); }); - test('does not change when the user modifies the minute input with an invalid value', () => { + test('does not change when the user modifies the minute input with an invalid value', async () => { renderTimePicker(); expect(onChange).not.toHaveBeenCalled(); - userEvent.type(screen.getByLabelText('Minute'), 'a'); + await userEvent.type(screen.getByLabelText('Minute'), 'a'); expect(onChange).not.toHaveBeenCalled(); }); - test('sets the max minute as the new minute value if the hour is the max value and the new minute is above the max minute for 24 hour format', () => { + test('sets the max minute as the new minute value if the hour is the max value and the new minute is above the max minute for 24 hour format', async () => { shouldUse12HourFormat.mockImplementation(() => false); const { rerender } = renderTimePicker({ max: '15:30' }); - userEvent.click(screen.getByLabelText('Minute')); + await userEvent.click(screen.getByLabelText('Minute')); rerender(); expect(onChange).not.toHaveBeenCalled(); - userEvent.keyboard('5'); + await userEvent.keyboard('5'); expect(onChange).toHaveBeenCalledTimes(1); expect(onChange).toHaveBeenCalledWith('15:30'); }); - test('sets the min minute as the new minute value if the hour is the min value and the new minute is below the min minute for 24 hour format', () => { + test('sets the min minute as the new minute value if the hour is the min value and the new minute is below the min minute for 24 hour format', async () => { shouldUse12HourFormat.mockImplementation(() => false); const { rerender } = renderTimePicker({ min: '15:30' }); - userEvent.click(screen.getByLabelText('Minute')); + await userEvent.click(screen.getByLabelText('Minute')); rerender(); expect(onChange).not.toHaveBeenCalled(); - userEvent.keyboard('5'); + await userEvent.keyboard('5'); expect(onChange).toHaveBeenCalledTimes(1); expect(onChange).toHaveBeenCalledWith('15:30'); }); - test('focuses the hour input if the focus is on the minute input and the user presses the left arrow', () => { + test('focuses the hour input if the focus is on the minute input and the user presses the left arrow', async () => { renderTimePicker(); - userEvent.click(screen.getByLabelText('Minute')); + await userEvent.click(screen.getByLabelText('Minute')); const hourInput = screen.getByLabelText('Hour'); expect(hourInput).not.toHaveFocus(); - userEvent.keyboard('[ArrowLeft]'); + await userEvent.keyboard('[ArrowLeft]'); expect(hourInput).toHaveFocus(); }); - test('focuses the time period input if the focus is on the minute input and the user presses the right arrow for 12 hour format', () => { + test('focuses the time period input if the focus is on the minute input and the user presses the right arrow for 12 hour format', async () => { renderTimePicker(); - userEvent.click(screen.getByLabelText('Minute')); + await userEvent.click(screen.getByLabelText('Minute')); const timePeriodInput = screen.getByLabelText('Time period'); expect(timePeriodInput).not.toHaveFocus(); - userEvent.keyboard('[ArrowRight]'); + await userEvent.keyboard('[ArrowRight]'); expect(timePeriodInput).toHaveFocus(); }); - test('focuses the time period input automatically when the user finishes typing a valid minute for 12 hour format', () => { + test('focuses the time period input automatically when the user finishes typing a valid minute for 12 hour format', async () => { const { rerender } = renderTimePicker(); - userEvent.click(screen.getByLabelText('Minute')); + await userEvent.click(screen.getByLabelText('Minute')); const timePeriodInput = screen.getByLabelText('Time period'); expect(timePeriodInput).not.toHaveFocus(); rerender(); - userEvent.keyboard('5'); + await userEvent.keyboard('5'); expect(timePeriodInput).toHaveFocus(); }); - test('sets the minute to 00 if the input is empty and focused and the user presses the up arrow', () => { + test('sets the minute to 00 if the input is empty and focused and the user presses the up arrow', async () => { renderTimePicker(); - userEvent.click(screen.getByLabelText('Minute')); + await userEvent.click(screen.getByLabelText('Minute')); expect(onChange).not.toHaveBeenCalled(); - userEvent.keyboard('[ArrowUp]'); + await userEvent.keyboard('[ArrowUp]'); expect(onChange).toHaveBeenCalledTimes(1); expect(onChange).toHaveBeenCalledWith(':00'); }); - test('sets the minute to 00 if the input has the value 59 and is focused and the user presses the up arrow', () => { + test('sets the minute to 00 if the input has the value 59 and is focused and the user presses the up arrow', async () => { renderTimePicker({ value: ':59' }); - userEvent.click(screen.getByLabelText('Minute')); + await userEvent.click(screen.getByLabelText('Minute')); expect(onChange).not.toHaveBeenCalled(); - userEvent.keyboard('[ArrowUp]'); + await userEvent.keyboard('[ArrowUp]'); expect(onChange).toHaveBeenCalledTimes(1); expect(onChange).toHaveBeenCalledWith(':00'); }); - test('increments the minute if the input has a valid value and is focused and the user presses the up arrow', () => { + test('increments the minute if the input has a valid value and is focused and the user presses the up arrow', async () => { renderTimePicker({ value: ':20' }); - userEvent.click(screen.getByLabelText('Minute')); + await userEvent.click(screen.getByLabelText('Minute')); expect(onChange).not.toHaveBeenCalled(); - userEvent.keyboard('[ArrowUp]'); + await userEvent.keyboard('[ArrowUp]'); expect(onChange).toHaveBeenCalledTimes(1); expect(onChange).toHaveBeenCalledWith(':21'); }); - test('sets the minute to 59 if the input is empty and focused and the user presses the down arrow', () => { + test('sets the minute to 59 if the input is empty and focused and the user presses the down arrow', async () => { renderTimePicker(); - userEvent.click(screen.getByLabelText('Minute')); + await userEvent.click(screen.getByLabelText('Minute')); expect(onChange).not.toHaveBeenCalled(); - userEvent.keyboard('[ArrowDown]'); + await userEvent.keyboard('[ArrowDown]'); expect(onChange).toHaveBeenCalledTimes(1); expect(onChange).toHaveBeenCalledWith(':59'); }); - test('sets the minute to 59 if the input has the value 00 and is focused and the user presses the down arrow', () => { + test('sets the minute to 59 if the input has the value 00 and is focused and the user presses the down arrow', async () => { renderTimePicker({ value: ':00' }); - userEvent.click(screen.getByLabelText('Minute')); + await userEvent.click(screen.getByLabelText('Minute')); expect(onChange).not.toHaveBeenCalled(); - userEvent.keyboard('[ArrowDown]'); + await userEvent.keyboard('[ArrowDown]'); expect(onChange).toHaveBeenCalledTimes(1); expect(onChange).toHaveBeenCalledWith(':59'); }); - test('decrements the minute if the input has a valid value and is focused and the user presses the down arrow', () => { + test('decrements the minute if the input has a valid value and is focused and the user presses the down arrow', async () => { renderTimePicker({ value: ':20' }); - userEvent.click(screen.getByLabelText('Minute')); + await userEvent.click(screen.getByLabelText('Minute')); expect(onChange).not.toHaveBeenCalled(); - userEvent.keyboard('[ArrowDown]'); + await userEvent.keyboard('[ArrowDown]'); expect(onChange).toHaveBeenCalledTimes(1); expect(onChange).toHaveBeenCalledWith(':19'); }); - test('changes when the user presses the first letter of a valid localized time period', () => { + test('changes when the user presses the first letter of a valid localized time period', async () => { const { rerender } = renderTimePicker({ value: '03:00' }); const timePeriodInput = screen.getByLabelText('Time period'); @@ -747,7 +747,7 @@ describe('TimePicker', () => { expect(onChange).not.toHaveBeenCalled(); expect(timePeriodInput).toHaveValue('AM'); - userEvent.type(timePeriodInput, 'p'); + await userEvent.type(timePeriodInput, 'p'); expect(onChange).toHaveBeenCalledTimes(1); expect(onChange).toHaveBeenCalledWith('15:00'); @@ -756,7 +756,7 @@ describe('TimePicker', () => { expect(timePeriodInput).toHaveValue('PM'); - userEvent.type(timePeriodInput, 'a'); + await userEvent.type(timePeriodInput, 'a'); expect(onChange).toHaveBeenCalledTimes(2); expect(onChange).toHaveBeenCalledWith('03:00'); @@ -766,7 +766,7 @@ describe('TimePicker', () => { expect(timePeriodInput).toHaveValue('AM'); }); - test('does not change when the user modifies the time period input with an invalid value', () => { + test('does not change when the user modifies the time period input with an invalid value', async () => { renderTimePicker({ value: '03:00' }); const timePeriodInput = screen.getByLabelText('Time period'); @@ -774,49 +774,49 @@ describe('TimePicker', () => { expect(onChange).not.toHaveBeenCalled(); expect(timePeriodInput).toHaveValue('AM'); - userEvent.type(timePeriodInput, 'x'); + await userEvent.type(timePeriodInput, 'x'); expect(onChange).not.toHaveBeenCalled(); }); - test('focuses the minute input if the focus is on the time period input and the user presses the left arrow', () => { + test('focuses the minute input if the focus is on the time period input and the user presses the left arrow', async () => { renderTimePicker(); - userEvent.click(screen.getByLabelText('Time period')); + await userEvent.click(screen.getByLabelText('Time period')); const minuteInput = screen.getByLabelText('Minute'); expect(minuteInput).not.toHaveFocus(); - userEvent.keyboard('[ArrowLeft]'); + await userEvent.keyboard('[ArrowLeft]'); expect(minuteInput).toHaveFocus(); }); - test('switches between the valid time periods if the user presses up or down arrows', () => { + test('switches between the valid time periods if the user presses up or down arrows', async () => { renderTimePicker(); const timePeriodInput = screen.getByLabelText('Time period'); - userEvent.click(timePeriodInput); + await userEvent.click(timePeriodInput); expect(timePeriodInput).toHaveValue('AM'); - userEvent.keyboard('[ArrowUp]'); + await userEvent.keyboard('[ArrowUp]'); expect(timePeriodInput).toHaveValue('PM'); - userEvent.keyboard('[ArrowDown]'); + await userEvent.keyboard('[ArrowDown]'); expect(timePeriodInput).toHaveValue('AM'); }); - test('opens the time options', () => { + test('opens the time options', async () => { renderTimePicker(); const openTimeOptionsButton = screen.getByLabelText('Open time options'); expect(openTimeOptionsButton).toHaveAttribute('aria-expanded', 'false'); - userEvent.click(openTimeOptionsButton); + await userEvent.click(openTimeOptionsButton); expect(screen.getByRole('presentation')).toBeVisible(); expect(openTimeOptionsButton).toHaveAttribute('aria-expanded', 'true'); @@ -826,13 +826,13 @@ describe('TimePicker', () => { renderTimePicker(); const openTimeOptionsButton = screen.getByLabelText('Open time options'); - userEvent.click(openTimeOptionsButton); + await userEvent.click(openTimeOptionsButton); const timeOptions = screen.getByRole('presentation'); expect(timeOptions).toBeVisible(); expect(openTimeOptionsButton).toHaveAttribute('aria-expanded', 'true'); - userEvent.click(openTimeOptionsButton); + await userEvent.click(openTimeOptionsButton); expect(openTimeOptionsButton).toHaveAttribute('aria-expanded', 'false'); diff --git a/src/TrackLegend/TimeOfDaySettings/TimeZoneSelect/index.test.js b/src/TrackLegend/TimeOfDaySettings/TimeZoneSelect/index.test.js index 728dcbf62..2c2040108 100644 --- a/src/TrackLegend/TimeOfDaySettings/TimeZoneSelect/index.test.js +++ b/src/TrackLegend/TimeOfDaySettings/TimeZoneSelect/index.test.js @@ -34,7 +34,7 @@ describe('TrackLegend - TimeOfDaySettings - TimeZoneSelect', () => { ); - /* test('sets the user time zone as the default value if none has been selected', () => { + /* test('sets the user time zone as the default value if none has been selected', async () => { store.view.trackSettings.timeOfDayTimeZone = null; expect(setTimeOfDayTimeZone).not.toHaveBeenCalled(); @@ -45,10 +45,10 @@ describe('TrackLegend - TimeOfDaySettings - TimeZoneSelect', () => { expect(setTimeOfDayTimeZone).toHaveBeenCalledWith('America/Mexico_City'); }); */ - test('shows an option for each time zone supported sorted by offset', () => { + test('shows an option for each time zone supported sorted by offset', async () => { renderTimeZoneSelect(); - userEvent.click(screen.getByLabelText('Time zone:')); + await userEvent.click(screen.getByLabelText('Time zone:')); const options = screen.getAllByRole('option'); @@ -61,14 +61,14 @@ describe('TrackLegend - TimeOfDaySettings - TimeZoneSelect', () => { }); // @ TODO: Fix this test - // test('selects a new time zone', () => { + // test('selects a new time zone', async () => { // renderTimeZoneSelect(); - // userEvent.click(screen.getByLabelText('Time zone:')); + // await userEvent.click(screen.getByLabelText('Time zone:')); // expect(setTimeOfDayTimeZone).not.toHaveBeenCalled(); - // userEvent.click(screen.getAllByRole('option')[100]); + // await userEvent.click(screen.getAllByRole('option')[100]); // expect(setTimeOfDayTimeZone).toHaveBeenCalledTimes(1); // // This test may break if someday the IANA standard updates. diff --git a/src/TrackLegend/TimeOfDaySettings/index.js b/src/TrackLegend/TimeOfDaySettings/index.js index 954662d86..05464fbea 100644 --- a/src/TrackLegend/TimeOfDaySettings/index.js +++ b/src/TrackLegend/TimeOfDaySettings/index.js @@ -85,8 +85,8 @@ const TimeOfDaySettings = ({ isExpanded, onCollapseTimeOfDaySettings, onExpandTi type="button" > {isExpanded - ? - : } + ? + : }
    diff --git a/src/TrackLegend/TimeOfDaySettings/index.test.js b/src/TrackLegend/TimeOfDaySettings/index.test.js index 67634d342..77feb8716 100644 --- a/src/TrackLegend/TimeOfDaySettings/index.test.js +++ b/src/TrackLegend/TimeOfDaySettings/index.test.js @@ -37,38 +37,38 @@ describe('TrackLegend - TimeOfDaySettings', () => { jest.restoreAllMocks(); }); - test('shows the time of day settings expanded', () => { + test('shows the time of day settings expanded', async () => { renderTimeOfDaySettings(); expect(screen.getByLabelText('Collapse the time of day settings')).toHaveAttribute('aria-expanded', 'true'); - expect(screen.getByText('arrow-up-simple.svg')).toBeVisible(); - expect(screen.queryByText('arrow-down-simple.svg')).toBeNull(); + expect(screen.getByTestId('arrow-up-simple-icon')).toBeVisible(); + expect(screen.queryByTestId('arrow-down-simple-icon')).toBeNull(); }); - test('shows the time of day settings collapsed', () => { + test('shows the time of day settings collapsed', async () => { renderTimeOfDaySettings({ isExpanded: false }); expect(screen.getByLabelText('Expand the time of day settings')).toHaveAttribute('aria-expanded', 'false'); - expect(screen.getByText('arrow-down-simple.svg')).toBeVisible(); - expect(screen.queryByText('arrow-up-simple.svg')).toBeNull(); + expect(screen.getByTestId('arrow-down-simple-icon')).toBeVisible(); + expect(screen.queryByTestId('arrow-up-simple-icon')).toBeNull(); }); - test('collapses the time of day settings', () => { + test('collapses the time of day settings', async () => { renderTimeOfDaySettings(); expect(onCollapseTimeOfDaySettings).not.toHaveBeenCalled(); - userEvent.click(screen.getByLabelText('Collapse the time of day settings')); + await userEvent.click(screen.getByLabelText('Collapse the time of day settings')); expect(onCollapseTimeOfDaySettings).toHaveBeenCalledTimes(1); }); - test('expands the time of day settings', () => { + test('expands the time of day settings', async () => { renderTimeOfDaySettings({ isExpanded: false }); expect(onExpandTimeOfDaySettings).not.toHaveBeenCalled(); - userEvent.click(screen.getByLabelText('Expand the time of day settings')); + await userEvent.click(screen.getByLabelText('Expand the time of day settings')); expect(onExpandTimeOfDaySettings).toHaveBeenCalledTimes(1); }); diff --git a/src/TrackLegend/TrackSettings/index.test.js b/src/TrackLegend/TrackSettings/index.test.js index 5d7ddb5f2..de044742a 100644 --- a/src/TrackLegend/TrackSettings/index.test.js +++ b/src/TrackLegend/TrackSettings/index.test.js @@ -54,40 +54,40 @@ describe('TrackLegend - TrackSettings', () => { jest.restoreAllMocks(); }); - test('closes the track settings', () => { + test('closes the track settings', async () => { renderTrackSettings(); expect(onClose).not.toHaveBeenCalled(); - userEvent.click(screen.getByLabelText('Close the track settings')); + await userEvent.click(screen.getByLabelText('Close the track settings')); expect(onClose).toHaveBeenCalledTimes(1); }); - test('changes the track length origin to the lower event filter date range', () => { + test('changes the track length origin to the lower event filter date range', async () => { renderTrackSettings(); expect(setTrackLengthOrigin).not.toHaveBeenCalled(); - userEvent.click(screen.getAllByRole('radio')[0]); + await userEvent.click(screen.getAllByRole('radio')[0]); expect(setTrackLengthOrigin).toHaveBeenCalledTimes(1); expect(setTrackLengthOrigin).toHaveBeenCalledWith(TRACK_LENGTH_ORIGINS.EVENT_FILTER); }); - test('changes the track length origin to a custom length', () => { + test('changes the track length origin to a custom length', async () => { store.view.trackSettings.origin = TRACK_LENGTH_ORIGINS.EVENT_FILTER; renderTrackSettings(); expect(setTrackLengthOrigin).not.toHaveBeenCalled(); - userEvent.click(screen.getAllByRole('radio')[1]); + await userEvent.click(screen.getAllByRole('radio')[1]); expect(setTrackLengthOrigin).toHaveBeenCalledTimes(1); expect(setTrackLengthOrigin).toHaveBeenCalledWith(TRACK_LENGTH_ORIGINS.CUSTOM_LENGTH); }); - test('disables the track length inputs if the track length origin is the event filter', () => { + test('disables the track length inputs if the track length origin is the event filter', async () => { store.view.trackSettings.origin = TRACK_LENGTH_ORIGINS.EVENT_FILTER; renderTrackSettings(); @@ -95,14 +95,14 @@ describe('TrackLegend - TrackSettings', () => { expect(screen.getAllByLabelText('Track length in days')[1]).toBeDisabled(); }); - test('does not disable the track length inputs if the track length origin is a custom length', () => { + test('does not disable the track length inputs if the track length origin is a custom length', async () => { renderTrackSettings(); expect(screen.getByRole('slider')).toBeEnabled(); expect(screen.getAllByLabelText('Track length in days')[1]).toBeEnabled(); }); - test('changes the track length when the user interacts with the slider', () => { + test('changes the track length when the user interacts with the slider', async () => { renderTrackSettings(); expect(setTrackLength).toHaveBeenCalledTimes(1); @@ -114,19 +114,19 @@ describe('TrackLegend - TrackSettings', () => { expect(setTrackLength).toHaveBeenCalledWith(60); }); - test('changes the track length when the user interacts with the numeric input', () => { + test('changes the track length when the user interacts with the numeric input', async () => { renderTrackSettings(); expect(setTrackLength).toHaveBeenCalledTimes(1); expect(setTrackLength).toHaveBeenCalledWith(21); - userEvent.type(screen.getAllByLabelText('Track length in days')[1], '{backspace}'); + await userEvent.type(screen.getAllByLabelText('Track length in days')[1], '{backspace}'); expect(setTrackLength).toHaveBeenCalledTimes(2); expect(setTrackLength).toHaveBeenCalledWith(2); }); - test('shows an error if the custom length inputs have an invalid value', () => { + test('shows an error if the custom length inputs have an invalid value', async () => { renderTrackSettings(); fireEvent.change(screen.getAllByLabelText('Track length in days')[1], { target: { value: 0 } }); @@ -140,7 +140,7 @@ describe('TrackLegend - TrackSettings', () => { expect(customLenghtNumericInput).toHaveAttribute('aria-errormessage', 'customLengthErrorMessage'); }); - test('does not show an error if the custom length inputs have a valid value', () => { + test('does not show an error if the custom length inputs have a valid value', async () => { renderTrackSettings(); const customLenghtSlider = screen.getByRole('slider'); diff --git a/src/TrackLegend/TracksList/index.test.js b/src/TrackLegend/TracksList/index.test.js index 67bbf47a8..3d5854440 100644 --- a/src/TrackLegend/TracksList/index.test.js +++ b/src/TrackLegend/TracksList/index.test.js @@ -21,17 +21,17 @@ describe('TrackLegend - TracksList', () => { jest.restoreAllMocks(); }); - test('closes the tracks list', () => { + test('closes the tracks list', async () => { renderTracksList(); expect(onClose).not.toHaveBeenCalled(); - userEvent.click(screen.getByLabelText('Close the list of items')); + await userEvent.click(screen.getByLabelText('Close the list of items')); expect(onClose).toHaveBeenCalledTimes(1); }); - test('lists all the items', () => { + test('lists all the items', async () => { renderTracksList({ items: [{ description: 'Item 1 description', @@ -49,7 +49,7 @@ describe('TrackLegend - TracksList', () => { expect(screen.getAllByRole('listitem')).toHaveLength(2); }); - test('shows the item icon', () => { + test('shows the item icon', async () => { renderTracksList({ items: [{ description: 'Item 1 description', @@ -68,7 +68,7 @@ describe('TrackLegend - TracksList', () => { expect(screen.getByAltText('Item 2 icon')).toHaveAttribute('src', 'icon-2'); }); - test('shows the item title', () => { + test('shows the item title', async () => { renderTracksList({ items: [{ description: 'Item 1 description', @@ -87,7 +87,7 @@ describe('TrackLegend - TracksList', () => { expect(screen.getByText('Item 2 title')).toBeVisible(); }); - test('shows the item description', () => { + test('shows the item description', async () => { renderTracksList({ items: [{ description: 'Item 1 description', @@ -106,7 +106,7 @@ describe('TrackLegend - TracksList', () => { expect(screen.getByText('Item 2 description')).toBeVisible(); }); - test('removes an item from the tracks list', () => { + test('removes an item from the tracks list', async () => { renderTracksList({ items: [{ description: 'Item 1 description', @@ -123,7 +123,7 @@ describe('TrackLegend - TracksList', () => { expect(onRemoveItemTracks).not.toHaveBeenCalled(); - userEvent.click(screen.getByLabelText('Remove Item 2 title')); + await userEvent.click(screen.getByLabelText('Remove Item 2 title')); expect(onRemoveItemTracks).toHaveBeenCalledTimes(1); expect(onRemoveItemTracks).toHaveBeenCalledWith('2'); diff --git a/src/TrackLegend/index.js b/src/TrackLegend/index.js index 63cf264f1..1b0886f75 100644 --- a/src/TrackLegend/index.js +++ b/src/TrackLegend/index.js @@ -106,7 +106,7 @@ const TrackLegend = ({

    {items[0].title}

    : <> - +