From 770e9b3bc4ec1aa2ac02846f56cfb4bdc4e13d7a Mon Sep 17 00:00:00 2001 From: Oleg Vaskevich Date: Fri, 13 Oct 2023 11:23:57 +0300 Subject: [PATCH 1/5] test: fix disabled tests (#2317) --- .../components/EditCv/index.test.tsx | 4 +- .../components/NoConsentView/index.test.tsx | 109 ++++++++++++++---- .../ContactsList/index.test.tsx | 27 ++--- 3 files changed, 98 insertions(+), 42 deletions(-) diff --git a/client/src/modules/Opportunities/components/EditCv/index.test.tsx b/client/src/modules/Opportunities/components/EditCv/index.test.tsx index 701eef1a57..57de760389 100644 --- a/client/src/modules/Opportunities/components/EditCv/index.test.tsx +++ b/client/src/modules/Opportunities/components/EditCv/index.test.tsx @@ -95,7 +95,7 @@ describe('EditCV', () => { expect(mockSwitchView).toHaveBeenCalled(); }); - test.skip('should save data on Save button click and show success notification', async () => { + test('should save data on Save button click and show success notification', async () => { const mockSaveResume = jest .spyOn(OpportunitiesApi.prototype, 'saveResume') .mockResolvedValue({ data: {} } as AxiosResponse); @@ -122,6 +122,6 @@ describe('EditCV', () => { expect(mockOnUpdateResume).toHaveBeenCalled(); }); - expect(screen.getByText(/cv sucessfully updated/i)).toBeInTheDocument(); + expect(await screen.findByText(/cv sucessfully updated/i)).toBeInTheDocument(); }); }); diff --git a/client/src/modules/Opportunities/components/NoConsentView/index.test.tsx b/client/src/modules/Opportunities/components/NoConsentView/index.test.tsx index 0011b875dd..85ff458ad2 100644 --- a/client/src/modules/Opportunities/components/NoConsentView/index.test.tsx +++ b/client/src/modules/Opportunities/components/NoConsentView/index.test.tsx @@ -18,7 +18,7 @@ describe('NoConsentView', () => { expect(createCvButton).toBeInTheDocument(); }); - it('should show confirmation modal correctly', async () => { + it('should show confirmation modal', async () => { render(); const createCvButton = screen.getByRole('button', { name: 'plus Create CV' }); @@ -29,66 +29,125 @@ describe('NoConsentView', () => { const modalTitle = await screen.findByText(confirmationModalInfo.en.header); expect(modal).toBeInTheDocument(); - - // Check that we have all visible texts expect(modalTitle).toBeInTheDocument(); - confirmationModalInfo.en.availableDataList.forEach(text => expect(screen.getByText(text)).toBeInTheDocument()); - // Check that title tooltip works correctly - const titleTooltipIcon = await screen.findByTestId(confirmationModalInfo.ru.header); + // close modal + fireEvent.click(screen.getByRole('button', { name: 'Cancel' })); + + await waitFor(() => { + const modal = screen.queryByRole('dialog'); + expect(modal).not.toBeInTheDocument(); + }); + }); + + it('should render tooltip', async () => { + render(); + + const createCvButton = screen.getByRole('button', { name: 'plus Create CV' }); + + fireEvent.click(createCvButton); + const titleTooltipIcon = await screen.findByTestId(confirmationModalInfo.ru.header); expect(titleTooltipIcon).toBeInTheDocument(); fireEvent.mouseEnter(titleTooltipIcon); const titleTooltipText = await screen.findByText(confirmationModalInfo.ru.header); - expect(titleTooltipText).toBeInTheDocument(); - // Check that list items tooltips works correctly - for (const text of confirmationModalInfo.ru.availableDataList) { - const tooltipIcon = await screen.findByTestId(text); + // close modal + fireEvent.click(screen.getByRole('button', { name: 'Cancel' })); + + await waitFor(() => { + const modal = screen.queryByRole('dialog'); + expect(modal).not.toBeInTheDocument(); + }); + }); + + it.each` + text + ${confirmationModalInfo.en.availableDataList[0]} + ${confirmationModalInfo.en.availableDataList[1]} + ${confirmationModalInfo.en.availableDataList[2]} + ${confirmationModalInfo.en.availableDataList[3]} + `('should render visible text $text', async ({ text }) => { + render(); + + const createCvButton = screen.getByRole('button', { name: 'plus Create CV' }); + + fireEvent.click(createCvButton); + + await waitFor(() => { + expect(screen.getByText(text)).toBeInTheDocument(); + }); + + // close modal + fireEvent.click(screen.getByRole('button', { name: 'Cancel' })); + + await waitFor(() => { + const modal = screen.queryByRole('dialog'); + expect(modal).not.toBeInTheDocument(); + }); + }); + + it.each` + text + ${confirmationModalInfo.ru.availableDataList[0]} + ${confirmationModalInfo.ru.availableDataList[1]} + ${confirmationModalInfo.ru.availableDataList[2]} + ${confirmationModalInfo.ru.availableDataList[3]} + `('should render tooltip $text', async ({ text }) => { + render(); + + const createCvButton = screen.getByRole('button', { name: 'plus Create CV' }); - expect(tooltipIcon).toBeInTheDocument(); + fireEvent.click(createCvButton); - fireEvent.mouseEnter(tooltipIcon); + const tooltipIcon = await screen.findByTestId(text); + expect(tooltipIcon).toBeInTheDocument(); - const tooltipText = await screen.findByText(text); + fireEvent.mouseEnter(tooltipIcon); - expect(tooltipText).toBeInTheDocument(); - } + const tooltipText = await screen.findByText(text); + expect(tooltipText).toBeInTheDocument(); + // close modal fireEvent.click(screen.getByRole('button', { name: 'Cancel' })); + + await waitFor(() => { + const modal = screen.queryByRole('dialog'); + expect(modal).not.toBeInTheDocument(); + }); }); it('should handle cancel correctly', async () => { render(); const createCvButton = screen.getByRole('button', { name: 'plus Create CV' }); + expect(createCvButton).toBeInTheDocument(); fireEvent.click(createCvButton); - expect(screen.getByRole('dialog')).toBeInTheDocument(); - - const cancelButton = screen.getByRole('button', { name: 'Cancel' }); + const cancelButton = await screen.findByRole('button', { name: 'Cancel' }); + expect(cancelButton).toBeInTheDocument(); + // close modal fireEvent.click(cancelButton); - // TODO: disable temporary - // await waitFor(() => { - // expect(screen.queryByRole('dialog')).not.toBeInTheDocument(); - // }); + await waitFor(() => { + const modal = screen.queryByRole('dialog'); + expect(modal).not.toBeInTheDocument(); + }); }); - it.skip('should handle consent correctly', async () => { + it('should handle consent correctly', async () => { const mockGiveConsent = jest.fn(); render(); const createCvButton = screen.getByRole('button', { name: 'plus Create CV' }); - // eslint-disable-next-line testing-library/no-wait-for-side-effects - await waitFor(() => fireEvent.click(createCvButton)); + fireEvent.click(createCvButton); const consentButton = await screen.findByRole('button', { name: 'I consent' }); diff --git a/client/src/modules/Opportunities/components/ViewCv/ContactsSection/ContactsList/index.test.tsx b/client/src/modules/Opportunities/components/ViewCv/ContactsSection/ContactsList/index.test.tsx index 7aedef195f..72ce0fc1db 100644 --- a/client/src/modules/Opportunities/components/ViewCv/ContactsSection/ContactsList/index.test.tsx +++ b/client/src/modules/Opportunities/components/ViewCv/ContactsSection/ContactsList/index.test.tsx @@ -52,23 +52,20 @@ describe('ContactsList', () => { expect(websiteIcon).toBeInTheDocument(); }); - test.skip('should have corresponding links', () => { + test('should have corresponding links', () => { render(); - const emailIcon = screen.getByRole('link', { name: 'E-mail' }); - const githubIcon = screen.getByRole('link', { name: 'Github' }); - const linkedinIcon = screen.getByRole('link', { name: 'LinkedIn' }); - const phoneIcon = screen.getByRole('link', { name: 'Phone' }); - const skypeIcon = screen.getByRole('link', { name: 'Skype' }); - const telegramIcon = screen.getByRole('link', { name: 'Telegram' }); - const websiteIcon = screen.getByRole('link', { name: 'Website' }); + const links = screen.getAllByRole('link'); + expect(links).toHaveLength(7); - expect(emailIcon).toBeInTheDocument(); - expect(githubIcon).toBeInTheDocument(); - expect(linkedinIcon).toBeInTheDocument(); - expect(phoneIcon).toBeInTheDocument(); - expect(skypeIcon).toBeInTheDocument(); - expect(telegramIcon).toBeInTheDocument(); - expect(websiteIcon).toBeInTheDocument(); + const [emailIcon, githubIcon, linkedinIcon, phoneIcon, skypeIcon, telegramIcon, websiteIcon] = links; + + expect(emailIcon).toHaveAttribute('title', 'E-mail'); + expect(githubIcon).toHaveAttribute('title', 'Github'); + expect(linkedinIcon).toHaveAttribute('title', 'LinkedIn'); + expect(phoneIcon).toHaveAttribute('title', 'Phone'); + expect(skypeIcon).toHaveAttribute('title', 'Skype'); + expect(telegramIcon).toHaveAttribute('title', 'Telegram'); + expect(websiteIcon).toHaveAttribute('title', 'Website'); }); }); From 3d2a9140438c6a92e3cb27f7c4f7deadce5d60a5 Mon Sep 17 00:00:00 2001 From: Andrei Date: Mon, 16 Oct 2023 11:32:55 +0300 Subject: [PATCH 2/5] chore(deps): update dependency @nestjs/cli to v10.1.18 (#2298) Co-authored-by: Renovate Bot --- nestjs/package.json | 2 +- package-lock.json | 101 ++++++++++++++++++++++++++------------------ 2 files changed, 62 insertions(+), 41 deletions(-) diff --git a/nestjs/package.json b/nestjs/package.json index f657d2427f..5db7fdc7c9 100644 --- a/nestjs/package.json +++ b/nestjs/package.json @@ -71,7 +71,7 @@ "typeorm": "0.3.17" }, "devDependencies": { - "@nestjs/cli": "10.1.12", + "@nestjs/cli": "10.1.18", "@nestjs/schematics": "10.0.2", "@nestjs/testing": "10.1.3", "@openapitools/openapi-generator-cli": "2.7.0", diff --git a/package-lock.json b/package-lock.json index eb9c8eb8df..1adc9951ed 100644 --- a/package-lock.json +++ b/package-lock.json @@ -146,7 +146,7 @@ "typeorm": "0.3.17" }, "devDependencies": { - "@nestjs/cli": "10.1.12", + "@nestjs/cli": "10.1.18", "@nestjs/schematics": "10.0.2", "@nestjs/testing": "10.1.3", "@openapitools/openapi-generator-cli": "2.7.0", @@ -214,14 +214,15 @@ } }, "node_modules/@angular-devkit/core": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-16.2.0.tgz", - "integrity": "sha512-l1k6Rqm3YM16BEn3CWyQKrk9xfu+2ux7Bw3oS+h1TO4/RoxO2PgHj8LLRh/WNrYVarhaqO7QZ5ePBkXNMkzJ1g==", + "version": "16.2.3", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-16.2.3.tgz", + "integrity": "sha512-oZLdg2XTx7likYAXRj1CU0XmrsCfe5f2grj3iwuI3OB1LXwwpdbHBztruj03y3yHES+TnO+dIbkvRnvMXs7uAA==", "dev": true, "dependencies": { "ajv": "8.12.0", "ajv-formats": "2.1.1", "jsonc-parser": "3.2.0", + "picomatch": "2.3.1", "rxjs": "7.8.1", "source-map": "0.7.4" }, @@ -240,12 +241,12 @@ } }, "node_modules/@angular-devkit/schematics": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-16.2.0.tgz", - "integrity": "sha512-QMDJXPE0+YQJ9Ap3MMzb0v7rx6ZbBEokmHgpdIjN3eILYmbAdsSGE8HTV8NjS9nKmcyE9OGzFCMb7PFrDTlTAw==", + "version": "16.2.3", + "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-16.2.3.tgz", + "integrity": "sha512-+lBiHxi/C9HCfiCbtW25DldwvJDXXXv5oWw+Tg4s18BO/lYZLveGUEaZWu9ZJ5VIJ8GliUi2LohxhDxBkh4Oxg==", "dev": true, "dependencies": { - "@angular-devkit/core": "16.2.0", + "@angular-devkit/core": "16.2.3", "jsonc-parser": "3.2.0", "magic-string": "0.30.1", "ora": "5.4.1", @@ -258,13 +259,13 @@ } }, "node_modules/@angular-devkit/schematics-cli": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/@angular-devkit/schematics-cli/-/schematics-cli-16.2.0.tgz", - "integrity": "sha512-f3HjrDvSrRMvESogLsqsZXsEg//trIBySCHRXCglPrWLVdBbIRctGOhXqZoclRxXimIKUx14zLsOWzDwZG8+HQ==", + "version": "16.2.3", + "resolved": "https://registry.npmjs.org/@angular-devkit/schematics-cli/-/schematics-cli-16.2.3.tgz", + "integrity": "sha512-5YQCbQmY9Kc03a9Io4XHOrxGXjnzcVveUuUO64R1m5x2aA5I+mVR8NVvxuoGRAeoI1FWusAKRe9hH8nRCLrelA==", "dev": true, "dependencies": { - "@angular-devkit/core": "16.2.0", - "@angular-devkit/schematics": "16.2.0", + "@angular-devkit/core": "16.2.3", + "@angular-devkit/schematics": "16.2.3", "ansi-colors": "4.1.3", "inquirer": "8.2.4", "symbol-observable": "4.0.0", @@ -2926,14 +2927,14 @@ } }, "node_modules/@nestjs/cli": { - "version": "10.1.12", - "resolved": "https://registry.npmjs.org/@nestjs/cli/-/cli-10.1.12.tgz", - "integrity": "sha512-L+KZOGBvSQUJACC4/o83FRLn5h3MOD5TrGi+Y2NjiDiZr0WYG5b0FaSaCSCy9WQTk46lMaiQYbvi0d4keHJnrw==", + "version": "10.1.18", + "resolved": "https://registry.npmjs.org/@nestjs/cli/-/cli-10.1.18.tgz", + "integrity": "sha512-jQtG47keLsACt7b4YwJbTBYRm90n82gJpMaiR1HGAyQ9pccbctjSYu592eT4bxqkUWxPgBE3mpNynXj7dWAfrw==", "dev": true, "dependencies": { - "@angular-devkit/core": "16.2.0", - "@angular-devkit/schematics": "16.2.0", - "@angular-devkit/schematics-cli": "16.2.0", + "@angular-devkit/core": "16.2.3", + "@angular-devkit/schematics": "16.2.3", + "@angular-devkit/schematics-cli": "16.2.3", "@nestjs/schematics": "^10.0.1", "chalk": "4.1.2", "chokidar": "3.5.3", @@ -2950,7 +2951,7 @@ "tree-kill": "1.2.2", "tsconfig-paths": "4.2.0", "tsconfig-paths-webpack-plugin": "4.1.0", - "typescript": "5.1.6", + "typescript": "5.2.2", "webpack": "5.88.2", "webpack-node-externals": "3.0.0" }, @@ -3033,6 +3034,19 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/@nestjs/cli/node_modules/typescript": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz", + "integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, "node_modules/@nestjs/common": { "version": "10.1.3", "resolved": "https://registry.npmjs.org/@nestjs/common/-/common-10.1.3.tgz", @@ -23812,25 +23826,26 @@ } }, "@angular-devkit/core": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-16.2.0.tgz", - "integrity": "sha512-l1k6Rqm3YM16BEn3CWyQKrk9xfu+2ux7Bw3oS+h1TO4/RoxO2PgHj8LLRh/WNrYVarhaqO7QZ5ePBkXNMkzJ1g==", + "version": "16.2.3", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-16.2.3.tgz", + "integrity": "sha512-oZLdg2XTx7likYAXRj1CU0XmrsCfe5f2grj3iwuI3OB1LXwwpdbHBztruj03y3yHES+TnO+dIbkvRnvMXs7uAA==", "dev": true, "requires": { "ajv": "8.12.0", "ajv-formats": "2.1.1", "jsonc-parser": "3.2.0", + "picomatch": "2.3.1", "rxjs": "7.8.1", "source-map": "0.7.4" } }, "@angular-devkit/schematics": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-16.2.0.tgz", - "integrity": "sha512-QMDJXPE0+YQJ9Ap3MMzb0v7rx6ZbBEokmHgpdIjN3eILYmbAdsSGE8HTV8NjS9nKmcyE9OGzFCMb7PFrDTlTAw==", + "version": "16.2.3", + "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-16.2.3.tgz", + "integrity": "sha512-+lBiHxi/C9HCfiCbtW25DldwvJDXXXv5oWw+Tg4s18BO/lYZLveGUEaZWu9ZJ5VIJ8GliUi2LohxhDxBkh4Oxg==", "dev": true, "requires": { - "@angular-devkit/core": "16.2.0", + "@angular-devkit/core": "16.2.3", "jsonc-parser": "3.2.0", "magic-string": "0.30.1", "ora": "5.4.1", @@ -23838,13 +23853,13 @@ } }, "@angular-devkit/schematics-cli": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/@angular-devkit/schematics-cli/-/schematics-cli-16.2.0.tgz", - "integrity": "sha512-f3HjrDvSrRMvESogLsqsZXsEg//trIBySCHRXCglPrWLVdBbIRctGOhXqZoclRxXimIKUx14zLsOWzDwZG8+HQ==", + "version": "16.2.3", + "resolved": "https://registry.npmjs.org/@angular-devkit/schematics-cli/-/schematics-cli-16.2.3.tgz", + "integrity": "sha512-5YQCbQmY9Kc03a9Io4XHOrxGXjnzcVveUuUO64R1m5x2aA5I+mVR8NVvxuoGRAeoI1FWusAKRe9hH8nRCLrelA==", "dev": true, "requires": { - "@angular-devkit/core": "16.2.0", - "@angular-devkit/schematics": "16.2.0", + "@angular-devkit/core": "16.2.3", + "@angular-devkit/schematics": "16.2.3", "ansi-colors": "4.1.3", "inquirer": "8.2.4", "symbol-observable": "4.0.0", @@ -26044,14 +26059,14 @@ "requires": {} }, "@nestjs/cli": { - "version": "10.1.12", - "resolved": "https://registry.npmjs.org/@nestjs/cli/-/cli-10.1.12.tgz", - "integrity": "sha512-L+KZOGBvSQUJACC4/o83FRLn5h3MOD5TrGi+Y2NjiDiZr0WYG5b0FaSaCSCy9WQTk46lMaiQYbvi0d4keHJnrw==", + "version": "10.1.18", + "resolved": "https://registry.npmjs.org/@nestjs/cli/-/cli-10.1.18.tgz", + "integrity": "sha512-jQtG47keLsACt7b4YwJbTBYRm90n82gJpMaiR1HGAyQ9pccbctjSYu592eT4bxqkUWxPgBE3mpNynXj7dWAfrw==", "dev": true, "requires": { - "@angular-devkit/core": "16.2.0", - "@angular-devkit/schematics": "16.2.0", - "@angular-devkit/schematics-cli": "16.2.0", + "@angular-devkit/core": "16.2.3", + "@angular-devkit/schematics": "16.2.3", + "@angular-devkit/schematics-cli": "16.2.3", "@nestjs/schematics": "^10.0.1", "chalk": "4.1.2", "chokidar": "3.5.3", @@ -26068,7 +26083,7 @@ "tree-kill": "1.2.2", "tsconfig-paths": "4.2.0", "tsconfig-paths-webpack-plugin": "4.1.0", - "typescript": "5.1.6", + "typescript": "5.2.2", "webpack": "5.88.2", "webpack-node-externals": "3.0.0" }, @@ -26111,6 +26126,12 @@ "requires": { "glob": "^9.2.0" } + }, + "typescript": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz", + "integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==", + "dev": true } } }, @@ -36429,7 +36450,7 @@ "@aws-sdk/client-s3": "3.391.0", "@nestjs/axios": "3.0.0", "@nestjs/cache-manager": "2.1.0", - "@nestjs/cli": "10.1.12", + "@nestjs/cli": "10.1.18", "@nestjs/common": "10.1.3", "@nestjs/config": "3.0.0", "@nestjs/core": "10.1.3", From f1351c05b46506aaf6e7f4e679b81517c84fa299 Mon Sep 17 00:00:00 2001 From: Andrei Date: Mon, 16 Oct 2023 11:33:08 +0300 Subject: [PATCH 3/5] chore(deps): update dependency @types/cache-manager to v4.0.3 (#2299) Co-authored-by: Renovate Bot --- nestjs/package.json | 2 +- package-lock.json | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/nestjs/package.json b/nestjs/package.json index 5db7fdc7c9..359e45e479 100644 --- a/nestjs/package.json +++ b/nestjs/package.json @@ -75,7 +75,7 @@ "@nestjs/schematics": "10.0.2", "@nestjs/testing": "10.1.3", "@openapitools/openapi-generator-cli": "2.7.0", - "@types/cache-manager": "4.0.2", + "@types/cache-manager": "4.0.3", "@types/cookie-parser": "1.4.3", "@types/express": "4.17.17", "@types/jest": "29.5.4", diff --git a/package-lock.json b/package-lock.json index 1adc9951ed..e1c1cf9941 100644 --- a/package-lock.json +++ b/package-lock.json @@ -150,7 +150,7 @@ "@nestjs/schematics": "10.0.2", "@nestjs/testing": "10.1.3", "@openapitools/openapi-generator-cli": "2.7.0", - "@types/cache-manager": "4.0.2", + "@types/cache-manager": "4.0.3", "@types/cookie-parser": "1.4.3", "@types/express": "4.17.17", "@types/jest": "29.5.4", @@ -6019,9 +6019,9 @@ "integrity": "sha512-wJsiX1tosQ+J5+bY5LrSahHxr2wT+uME5UDwdN1kg4frt40euqA+wzECkmq4t5QbveHiJepfdThgQrPw6KiSlg==" }, "node_modules/@types/cache-manager": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@types/cache-manager/-/cache-manager-4.0.2.tgz", - "integrity": "sha512-fT5FMdzsiSX0AbgnS5gDvHl2Nco0h5zYyjwDQy4yPC7Ww6DeGMVKPRqIZtg9HOXDV2kkc18SL1B0N8f0BecrCA==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@types/cache-manager/-/cache-manager-4.0.3.tgz", + "integrity": "sha512-tPo2eUsvPVk/i2AU7BKy2ekSoKFOkST918GF7Qvc4IMNTRHyekEWJtWS9sBdi+DaF/4saiBkgWji5HqH3X7W8g==", "dev": true }, "node_modules/@types/cacheable-request": { @@ -28314,9 +28314,9 @@ "integrity": "sha512-wJsiX1tosQ+J5+bY5LrSahHxr2wT+uME5UDwdN1kg4frt40euqA+wzECkmq4t5QbveHiJepfdThgQrPw6KiSlg==" }, "@types/cache-manager": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@types/cache-manager/-/cache-manager-4.0.2.tgz", - "integrity": "sha512-fT5FMdzsiSX0AbgnS5gDvHl2Nco0h5zYyjwDQy4yPC7Ww6DeGMVKPRqIZtg9HOXDV2kkc18SL1B0N8f0BecrCA==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@types/cache-manager/-/cache-manager-4.0.3.tgz", + "integrity": "sha512-tPo2eUsvPVk/i2AU7BKy2ekSoKFOkST918GF7Qvc4IMNTRHyekEWJtWS9sBdi+DaF/4saiBkgWji5HqH3X7W8g==", "dev": true }, "@types/cacheable-request": { @@ -36466,7 +36466,7 @@ "@sentry/node": "7.68.0", "@swc/cli": "^0.1.62", "@swc/core": "^1.3.77", - "@types/cache-manager": "4.0.2", + "@types/cache-manager": "4.0.3", "@types/cookie-parser": "1.4.3", "@types/express": "4.17.17", "@types/jest": "29.5.4", From 8194714424799713277b65df34a4aa803afb208d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 16 Oct 2023 11:41:38 +0300 Subject: [PATCH 4/5] chore(deps): bump postcss from 8.4.16 to 8.4.31 in /tools/sloths (#2315) Bumps [postcss](https://github.com/postcss/postcss) from 8.4.16 to 8.4.31. - [Release notes](https://github.com/postcss/postcss/releases) - [Changelog](https://github.com/postcss/postcss/blob/main/CHANGELOG.md) - [Commits](https://github.com/postcss/postcss/compare/8.4.16...8.4.31) --- updated-dependencies: - dependency-name: postcss dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- tools/sloths/package-lock.json | 38 +++++++++++++++++++++------------- 1 file changed, 24 insertions(+), 14 deletions(-) diff --git a/tools/sloths/package-lock.json b/tools/sloths/package-lock.json index 8d197bac10..25b5e3bd4f 100644 --- a/tools/sloths/package-lock.json +++ b/tools/sloths/package-lock.json @@ -3933,9 +3933,15 @@ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, "node_modules/nanoid": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz", - "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==", + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", + "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], "bin": { "nanoid": "bin/nanoid.cjs" }, @@ -4526,9 +4532,9 @@ } }, "node_modules/postcss": { - "version": "8.4.16", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.16.tgz", - "integrity": "sha512-ipHE1XBvKzm5xI7hiHCZJCSugxvsdq2mPnsq5+UF+VHCjiBvtDrlxJfMBToWaP9D5XlgNmcFGqoHmUn0EYEaRQ==", + "version": "8.4.31", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", + "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", "funding": [ { "type": "opencollective", @@ -4537,10 +4543,14 @@ { "type": "tidelift", "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" } ], "dependencies": { - "nanoid": "^3.3.4", + "nanoid": "^3.3.6", "picocolors": "^1.0.0", "source-map-js": "^1.0.2" }, @@ -8670,9 +8680,9 @@ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, "nanoid": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz", - "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==" + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", + "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==" }, "natural-compare": { "version": "1.4.0", @@ -9081,11 +9091,11 @@ } }, "postcss": { - "version": "8.4.16", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.16.tgz", - "integrity": "sha512-ipHE1XBvKzm5xI7hiHCZJCSugxvsdq2mPnsq5+UF+VHCjiBvtDrlxJfMBToWaP9D5XlgNmcFGqoHmUn0EYEaRQ==", + "version": "8.4.31", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", + "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", "requires": { - "nanoid": "^3.3.4", + "nanoid": "^3.3.6", "picocolors": "^1.0.0", "source-map-js": "^1.0.2" } From d7be41be3b169ce5a6839c832275aea4409248f3 Mon Sep 17 00:00:00 2001 From: Oleg Vaskevich Date: Mon, 16 Oct 2023 11:43:20 +0300 Subject: [PATCH 5/5] test & refactor: fix tests warnings (#2318) * test: mock use-places-autocomplite hook * refactor: change overlay to menu on Dropdowns * refactor: wrap location.href set into a function, update tests * refactor: extract renderItem function * refactor: migrate MentorStatsModal to React Functional Component * refactor: migrate CoreJsIviewModal to React Functional Component * test: fix async/await issues in tests --- client/src/components/Header.tsx | 69 +++++++----- .../components/Profile/CoreJsIviewsModal.tsx | 93 ++++++++-------- .../components/Profile/MentorStatsModal.tsx | 105 +++++++++--------- .../__test__/CoreJsIviewsCard.test.tsx | 8 +- .../Profile/__test__/MentorStatsCard.test.tsx | 3 + .../components/Coding/Coding.test.tsx | 4 +- .../AddCriteriaForCrossCheck.test.tsx | 10 +- .../__tests__/UploadCriteriaJSON.test.tsx | 9 +- .../MentorDashboard/MentorDashboard.test.tsx | 8 +- .../MentorRegistryTableContainer.tsx | 49 ++++---- .../components/PublicLink/index.test.tsx | 12 +- .../ViewCv/CoursesSection/index.tsx | 99 ++++++++--------- .../Cards/PersonalInfo/PersonalInfo.test.tsx | 14 +++ .../GeneralSection/GeneralSection.test.tsx | 14 +++ .../AdditionalActions.test.tsx | 20 +++- .../AdditionalActions/AdditionalActions.tsx | 12 +- .../components/AdditionalActions/helpers.ts | 4 + .../SettingsPanel/SettingsPanel.test.tsx | 10 +- 18 files changed, 300 insertions(+), 243 deletions(-) diff --git a/client/src/components/Header.tsx b/client/src/components/Header.tsx index 32cef51f16..7f0b6a8277 100644 --- a/client/src/components/Header.tsx +++ b/client/src/components/Header.tsx @@ -1,7 +1,8 @@ import Link from 'next/link'; import { useRouter } from 'next/router'; -import { Fragment, useContext, useMemo } from 'react'; +import { useContext, useMemo } from 'react'; import { Button, Dropdown, Menu, Space } from 'antd'; +import type { MenuProps } from 'antd'; import { EyeOutlined, LogoutOutlined, @@ -14,17 +15,20 @@ import { SolidarityUkraine } from './SolidarityUkraine'; import { SessionContext } from 'modules/Course/contexts'; import { getNavigationItems } from 'modules/Home/data/links'; import { useActiveCourseContext } from 'modules/Course/contexts/ActiveCourseContext'; +import css from 'styled-jsx/css'; type Props = { showCourseName?: boolean; title?: string; }; +type MenuItem = Required['items'][number]; + const MENU_ITEMS = [ { link: '/profile', icon: , - title: 'View', + title: 'Profile', }, { link: '/profile/notifications', @@ -51,26 +55,29 @@ const MENU_ITEMS = [ export function Header({ title, showCourseName }: Props) { const { asPath: currentRoute } = useRouter(); - const menuActiveItemStyle = { backgroundColor: '#e0f2ff' }; const session = useContext(SessionContext); const { course } = useActiveCourseContext(); const courseLinks = useMemo(() => getNavigationItems(session, course ?? null), [course]); - const menu = ( - - {MENU_ITEMS.map(({ link, icon, title, target }, id, arr) => ( - - {id === arr.length - 1 ? : null} - - - - - ))} - - ); + const menuItems = useMemo((): MenuProps['items'] => { + const items = MENU_ITEMS.map(({ title, link, target, icon }) => { + const isActive = currentRoute === link; + + return { + key: title, + label: ( + + ), + }; + }); + + const lastItem = items.pop() as MenuItem; + + return [...items, { type: 'divider' }, lastItem]; + }, [currentRoute]); return (
{session.githubId && ( - + )}
- + ); } + +const styles = css` + :global(li:has(.menu-item-active)) { + background-color: #e0f2ff; + } + + @media all and (max-width: 768px) { + .title { + width: 100%; + order: 3; + text-align: center; + margin-top: 16px; + } + } +`; diff --git a/client/src/components/Profile/CoreJsIviewsModal.tsx b/client/src/components/Profile/CoreJsIviewsModal.tsx index f8c40e8275..ca87339d9a 100644 --- a/client/src/components/Profile/CoreJsIviewsModal.tsx +++ b/client/src/components/Profile/CoreJsIviewsModal.tsx @@ -1,6 +1,6 @@ -import * as React from 'react'; -import { CoreJsInterviewsData } from './CoreJsIviewsCard'; import { Modal, Table, Typography, Tag } from 'antd'; +import { memo } from 'react'; +import { CoreJsInterviewsData } from './CoreJsIviewsCard'; const { Text } = Typography; @@ -11,53 +11,50 @@ type Props = { onHide: () => void; }; -class CoreJsIviewsModal extends React.PureComponent { - render() { - const { stats, isVisible, onHide, interviewIndex } = this.props; - const { courseFullName, interviews } = stats; - const { score, comment, answers, interviewer } = interviews[interviewIndex]; +const CoreJsIviewsModal = ({ stats, isVisible, onHide, interviewIndex }: Props) => { + const { courseFullName, interviews } = stats; + const { score, comment, answers, interviewer } = interviews[interviewIndex]; - return ( - -

- Score: {score} -

+ return ( + +

+ Score: {score} +

+

+ Interviewer: {interviewer.name} +

+ {comment && (

- Interviewer: {interviewer.name} + Comment: + {comment}

- {comment && ( -

- Comment: - {comment} -

- )} - - answer === true ? Yes : answer === false ? No : answer, - }, - ]} - /> - - ); - } -} + )} +
+ answer === true ? Yes : answer === false ? No : answer, + }, + ]} + /> + + ); +}; -export default CoreJsIviewsModal; +export default memo(CoreJsIviewsModal); diff --git a/client/src/components/Profile/MentorStatsModal.tsx b/client/src/components/Profile/MentorStatsModal.tsx index 52b9c3b1f8..4d1dd44cd3 100644 --- a/client/src/components/Profile/MentorStatsModal.tsx +++ b/client/src/components/Profile/MentorStatsModal.tsx @@ -13,61 +13,58 @@ type Props = { onHide: () => void; }; -class MentorStatsModal extends React.Component { - render() { - const { stats, isVisible, onHide } = this.props; - const { courseName, students } = stats; +const MentorStatsModal = ({ stats, isVisible, onHide }: Props) => { + const { courseName, students } = stats; - return ( - - - {students?.map(({ name, githubId, isExpelled, totalScore, repoUrl }) => { - const profile = `/profile?githubId=${githubId}`; - const guithubLink = `https://github.com/${githubId}`; + return ( + + + {students?.map(({ name, githubId, isExpelled, totalScore, repoUrl }) => { + const profile = `/profile?githubId=${githubId}`; + const guithubLink = `https://github.com/${githubId}`; - return ( - - - -
- - - {name} - -
-

- {isExpelled ? expelled : active} -

-

- Score: {totalScore} -

-

- {' '} - - {githubId} - -

-

- {' '} - - {repoUrl?.split('/').pop()} - -

- - - - ); - })} - - - ); - } -} + return ( + + + +
+ + + {name} + +
+

+ {isExpelled ? expelled : active} +

+

+ Score: {totalScore} +

+

+ {' '} + + {githubId} + +

+

+ {' '} + + {repoUrl?.split('/').pop()} + +

+ + + + ); + })} + + + ); +}; export default MentorStatsModal; diff --git a/client/src/components/Profile/__test__/CoreJsIviewsCard.test.tsx b/client/src/components/Profile/__test__/CoreJsIviewsCard.test.tsx index 2742b3d535..dbf67651c7 100644 --- a/client/src/components/Profile/__test__/CoreJsIviewsCard.test.tsx +++ b/client/src/components/Profile/__test__/CoreJsIviewsCard.test.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import { render, screen } from '@testing-library/react'; +import { act, render, screen } from '@testing-library/react'; import CoreJsIviewsCard, { CoreJsInterviewsData } from '../CoreJsIviewsCard'; describe('CoreJSIviewsCard', () => { @@ -43,7 +43,11 @@ describe('CoreJSIviewsCard', () => { render(); const btn = await screen.findByTestId('profile-corejs-iview-button'); - btn.click(); + + act(() => { + btn.click(); + }); + const modal = await screen.findByTestId('profile-corejs-iviews-modal-table'); expect(modal).toBeInTheDocument(); }); diff --git a/client/src/components/Profile/__test__/MentorStatsCard.test.tsx b/client/src/components/Profile/__test__/MentorStatsCard.test.tsx index f78240cbd8..112e6f2c78 100644 --- a/client/src/components/Profile/__test__/MentorStatsCard.test.tsx +++ b/client/src/components/Profile/__test__/MentorStatsCard.test.tsx @@ -1,6 +1,7 @@ import React from 'react'; import { render } from '@testing-library/react'; import { MentorStatsCard } from '../MentorStatsCard'; +import * as reactUse from 'react-use'; describe('MentorStatsCard', () => { const mentorStats = [ @@ -31,6 +32,8 @@ describe('MentorStatsCard', () => { ]; it('should render correctly', () => { + jest.spyOn(reactUse, 'useAsync').mockReturnValue({ value: null, loading: false }); + const { container } = render(); expect(container).toMatchSnapshot(); }); diff --git a/client/src/modules/AutoTest/components/Coding/Coding.test.tsx b/client/src/modules/AutoTest/components/Coding/Coding.test.tsx index 2fd079ce37..f5d2abd010 100644 --- a/client/src/modules/AutoTest/components/Coding/Coding.test.tsx +++ b/client/src/modules/AutoTest/components/Coding/Coding.test.tsx @@ -37,10 +37,10 @@ describe('Coding', () => { ${CourseTaskDetailedDtoTypeEnum.Kotlintask} | ${/https:\/\/github.com\/github-id\/github-repo-name/i} `( 'should render $type task with $text', - ({ type, text }: { type: CourseTaskDetailedDtoTypeEnum; text: RegExp | string }) => { + async ({ type, text }: { type: CourseTaskDetailedDtoTypeEnum; text: RegExp | string }) => { renderCoding(type); - expect(screen.getByText(text)).toBeInTheDocument(); + expect(await screen.findByText(text)).toBeInTheDocument(); }, ); }); diff --git a/client/src/modules/CrossCheck/__tests__/AddCriteriaForCrossCheck.test.tsx b/client/src/modules/CrossCheck/__tests__/AddCriteriaForCrossCheck.test.tsx index 25b1f78f06..9aa3b9c0ca 100644 --- a/client/src/modules/CrossCheck/__tests__/AddCriteriaForCrossCheck.test.tsx +++ b/client/src/modules/CrossCheck/__tests__/AddCriteriaForCrossCheck.test.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import { fireEvent, render, screen } from '@testing-library/react'; +import { fireEvent, render, screen, waitFor } from '@testing-library/react'; import { AddCriteriaForCrossCheck } from '../AddCriteriaForCrossCheck'; import userEvent from '@testing-library/user-event'; @@ -17,7 +17,7 @@ describe('AddCriteriaForCrossCheck', () => { expect(element).toBeInTheDocument(); }); - test('should call addCriteria when "Add new criteria" button was clicked', () => { + test('should call addCriteria when "Add new criteria" button was clicked', async () => { render(); const selectCriteriaType = screen.getByRole('combobox'); fireEvent.mouseDown(selectCriteriaType); @@ -29,7 +29,10 @@ describe('AddCriteriaForCrossCheck', () => { const button = screen.getByRole('button', { name: /Add New Criteria/i }); fireEvent.click(button); - expect(addCriteria).toHaveBeenCalledTimes(1); + + await waitFor(() => { + expect(addCriteria).toHaveBeenCalledTimes(1); + }); }); test('should render textarea', () => { @@ -44,7 +47,6 @@ describe('AddCriteriaForCrossCheck', () => { render(); const textarea = screen.getByPlaceholderText('Add description'); - // eslint-disable-next-line testing-library/no-await-sync-events await userEvent.type(textarea, expectedString); expect(textarea.value).toEqual(expectedString); diff --git a/client/src/modules/CrossCheck/__tests__/UploadCriteriaJSON.test.tsx b/client/src/modules/CrossCheck/__tests__/UploadCriteriaJSON.test.tsx index 16d9989d91..305d812619 100644 --- a/client/src/modules/CrossCheck/__tests__/UploadCriteriaJSON.test.tsx +++ b/client/src/modules/CrossCheck/__tests__/UploadCriteriaJSON.test.tsx @@ -1,6 +1,6 @@ import React from 'react'; import { UploadCriteriaJSON } from '../UploadCriteriaJSON'; -import { fireEvent, render, screen } from '@testing-library/react'; +import { fireEvent, render, screen, waitFor } from '@testing-library/react'; const onLoad = jest.fn(); @@ -11,7 +11,7 @@ describe('UploadCriteriaJSON', () => { expect(element).toBeInTheDocument(); }); - test('upload file', () => { + test('upload file', async () => { render(); global.URL.createObjectURL = jest.fn(); @@ -19,6 +19,9 @@ describe('UploadCriteriaJSON', () => { const input = screen.getByTestId('uploader') as HTMLInputElement; fireEvent.change(input, { target: { files: [file] } }); - expect(input.files).toHaveLength(1); + + await waitFor(() => { + expect(input.files).toHaveLength(1); + }); }); }); diff --git a/client/src/modules/Mentor/components/MentorDashboard/MentorDashboard.test.tsx b/client/src/modules/Mentor/components/MentorDashboard/MentorDashboard.test.tsx index e0b83464b5..26deef8080 100644 --- a/client/src/modules/Mentor/components/MentorDashboard/MentorDashboard.test.tsx +++ b/client/src/modules/Mentor/components/MentorDashboard/MentorDashboard.test.tsx @@ -23,7 +23,7 @@ const PROPS_MOCK: MentorDashboardProps = { }; describe('MentorDashboard', () => { - it('should render instructions when mentor has no students for this course', () => { + it('should render instructions when mentor has no students for this course', async () => { render( { , ); - const instructionsTitle = screen.getByText(INSTRUCTIONS_TEXT.title); + const instructionsTitle = await screen.findByText(INSTRUCTIONS_TEXT.title); expect(instructionsTitle).toBeInTheDocument(); }); - it('should render empty table when mentor has students for this course', () => { + it('should render empty table when mentor has students for this course', async () => { render( { , ); - const emptyTable = screen.getByText(/No Data/i); + const emptyTable = await screen.findByText(/No Data/i); expect(emptyTable).toBeInTheDocument(); }); diff --git a/client/src/modules/MentorRegistry/components/MentorRegistryTableContainer.tsx b/client/src/modules/MentorRegistry/components/MentorRegistryTableContainer.tsx index f2880f1057..c8735ecccd 100644 --- a/client/src/modules/MentorRegistry/components/MentorRegistryTableContainer.tsx +++ b/client/src/modules/MentorRegistry/components/MentorRegistryTableContainer.tsx @@ -7,7 +7,7 @@ import { Course } from 'services/models'; import CopyToClipboardButton from 'components/CopyToClipboardButton'; import { MentorsRegistryColumnKey, MentorsRegistryColumnName, TABS, MentorRegistryTabsMode } from '../constants'; import { FilterValue } from 'antd/lib/table/interface'; -import { Button, Dropdown, Menu, Tooltip, message } from 'antd'; +import { Button, Dropdown, Tooltip, message } from 'antd'; import { MoreOutlined, MessageTwoTone } from '@ant-design/icons'; import { ColumnType } from 'antd/lib/table'; import { DisciplineDto, MentorRegistryDto } from 'api'; @@ -140,31 +140,28 @@ export const MentorRegistryTableContainer = ({ const renderRestActions = (record: MentorRegistryDto) => { return ( handleModalDataChange(ModalDataMode.Resend, record), - disabled: !record.preselectedCourses.length, - } - : null, - { - key: 'delete', - label: 'Delete', - onClick: () => handleModalDataChange(ModalDataMode.Delete, record), - }, - { - key: 'comment', - label: record.comment ? 'Edit comment' : 'Add comment', - onClick: () => handleModalDataChange(ModalDataMode.Comment, record), - }, - ]} - > - } + menu={{ + items: [ + activeTab === MentorRegistryTabsMode.New + ? { + key: 'resend', + label: 'Re-send', + onClick: () => handleModalDataChange(ModalDataMode.Resend, record), + disabled: !record.preselectedCourses.length, + } + : null, + { + key: 'delete', + label: 'Delete', + onClick: () => handleModalDataChange(ModalDataMode.Delete, record), + }, + { + key: 'comment', + label: record.comment ? 'Edit comment' : 'Add comment', + onClick: () => handleModalDataChange(ModalDataMode.Comment, record), + }, + ], + }} > - {title} - - - - - Status: - - - - - Mentor:{' '} - {mentor?.name ? ( - - {mentor.name} - - ) : ( - No mentor - )} - - - - - - - Position: {rank} - - - - - Score: {totalScore} - - - - - - - - ); - }} - /> + ); }; +function renderItem(record: ResumeCourseDto) { + const { fullName, certificateId, completed, totalScore, rank, locationName, mentor } = record; + + const title = `${fullName}${locationName ? ` (${locationName})` : ''}`; + return ( + + + {title} + + + + + Status: + + + + + Mentor:{' '} + {mentor?.name ? ( + + {mentor.name} + + ) : ( + No mentor + )} + + + + + + + Position: {rank} + + + + + Score: {totalScore} + + + + + + + + ); +} + const styles = css` .course-data-key { font-size: 14px; diff --git a/client/src/modules/Registry/components/Cards/PersonalInfo/PersonalInfo.test.tsx b/client/src/modules/Registry/components/Cards/PersonalInfo/PersonalInfo.test.tsx index 666c4f5188..270f908a01 100644 --- a/client/src/modules/Registry/components/Cards/PersonalInfo/PersonalInfo.test.tsx +++ b/client/src/modules/Registry/components/Cards/PersonalInfo/PersonalInfo.test.tsx @@ -2,6 +2,20 @@ import { fireEvent, render, screen } from '@testing-library/react'; import { Form } from 'antd'; import { ERROR_MESSAGES, LABELS, PLACEHOLDERS } from 'modules/Registry/constants'; import { PersonalInfo } from './PersonalInfo'; +import usePlacesAutocomplete from 'use-places-autocomplete'; + +jest.mock('use-places-autocomplete'); + +(usePlacesAutocomplete as jest.Mock).mockImplementation(() => ({ + value: null, + suggestions: { + data: { + map: jest.fn(), + }, + loading: false, + }, + setValue: jest.fn(), +})); const mockValues = { firstName: 'John', diff --git a/client/src/modules/Registry/components/FormSections/GeneralSection/GeneralSection.test.tsx b/client/src/modules/Registry/components/FormSections/GeneralSection/GeneralSection.test.tsx index 29f8f452ca..ea6bfe2c90 100644 --- a/client/src/modules/Registry/components/FormSections/GeneralSection/GeneralSection.test.tsx +++ b/client/src/modules/Registry/components/FormSections/GeneralSection/GeneralSection.test.tsx @@ -3,6 +3,20 @@ import { Form } from 'antd'; import { CourseDto } from 'api'; import { CARD_TITLES } from 'modules/Registry/constants'; import { GeneralSection } from './GeneralSection'; +import usePlacesAutocomplete from 'use-places-autocomplete'; + +jest.mock('use-places-autocomplete'); + +(usePlacesAutocomplete as jest.Mock).mockImplementation(() => ({ + value: null, + suggestions: { + data: { + map: jest.fn(), + }, + loading: false, + }, + setValue: jest.fn(), +})); const renderGeneralSection = (courses?: CourseDto[]) => { render( diff --git a/client/src/modules/Schedule/components/AdditionalActions/AdditionalActions.test.tsx b/client/src/modules/Schedule/components/AdditionalActions/AdditionalActions.test.tsx index f494517043..5fd5527aec 100644 --- a/client/src/modules/Schedule/components/AdditionalActions/AdditionalActions.test.tsx +++ b/client/src/modules/Schedule/components/AdditionalActions/AdditionalActions.test.tsx @@ -1,12 +1,15 @@ -import { fireEvent, render, screen } from '@testing-library/react'; +import { fireEvent, render, screen, waitFor } from '@testing-library/react'; import { AdditionalActions, AdditionalActionsProps, MenuItemType } from '.'; import { SettingsButtons } from '../SettingsPanel'; import { buildMenuItem } from '../SettingsPanel/helpers'; -import { buildExportLink, buildICalendarLink } from './helpers'; +import { buildExportLink, buildICalendarLink, setExportLink } from './helpers'; + +window.prompt = jest.fn(); jest.mock('./helpers', () => ({ buildExportLink: jest.fn(), buildICalendarLink: jest.fn(), + setExportLink: jest.fn(), })); const PROPS_MOCK: AdditionalActionsProps = { @@ -37,7 +40,9 @@ describe('AdditionalActions', () => { const copyBtn = await screen.findByRole('menuitem', { name: new RegExp(SettingsButtons.Copy, 'i') }); fireEvent.click(copyBtn); - expect(PROPS_MOCK.onCopyFromCourse).toHaveBeenCalled(); + await waitFor(() => { + expect(PROPS_MOCK.onCopyFromCourse).toHaveBeenCalled(); + }); }); it('should call onCalendarCopyLink when "Copy iCal Link" action was clicked', async () => { @@ -48,7 +53,13 @@ describe('AdditionalActions', () => { const calendarBtn = await screen.findByRole('menuitem', { name: new RegExp(SettingsButtons.CopyLink, 'i') }); fireEvent.click(calendarBtn); - expect(buildICalendarLink).toHaveBeenCalledWith(PROPS_MOCK.courseId, PROPS_MOCK.calendarToken, PROPS_MOCK.timezone); + await waitFor(() => { + expect(buildICalendarLink).toHaveBeenCalledWith( + PROPS_MOCK.courseId, + PROPS_MOCK.calendarToken, + PROPS_MOCK.timezone, + ); + }); }); it('should call onExport when "Export" action was clicked', async () => { @@ -60,6 +71,7 @@ describe('AdditionalActions', () => { fireEvent.click(exportBtn); expect(buildExportLink).toHaveBeenCalledWith(PROPS_MOCK.courseId, PROPS_MOCK.timezone); + expect(setExportLink).toHaveBeenCalled(); }); }); diff --git a/client/src/modules/Schedule/components/AdditionalActions/AdditionalActions.tsx b/client/src/modules/Schedule/components/AdditionalActions/AdditionalActions.tsx index a395346676..4b434dd1b4 100644 --- a/client/src/modules/Schedule/components/AdditionalActions/AdditionalActions.tsx +++ b/client/src/modules/Schedule/components/AdditionalActions/AdditionalActions.tsx @@ -1,8 +1,8 @@ -import { Button, Dropdown, Menu, message, Space } from 'antd'; +import { Button, Dropdown, message, Space } from 'antd'; import { DownOutlined } from '@ant-design/icons'; import type { MenuProps } from 'antd'; import React from 'react'; -import { buildExportLink, buildICalendarLink } from './helpers'; +import { buildExportLink, buildICalendarLink, setExportLink } from './helpers'; import { SettingsButtons } from '../SettingsPanel'; import { useCopyToClipboard } from 'react-use'; @@ -29,7 +29,7 @@ const AdditionalActions = ({ const [, copyToClipboard] = useCopyToClipboard(); const onExport = () => { - window.location.href = buildExportLink(courseId, timezone); + setExportLink(buildExportLink(courseId, timezone)); }; const onCalendarDownload = () => { @@ -72,11 +72,7 @@ const AdditionalActions = ({ }; return ( - } - trigger={['click']} - placement="bottomRight" - > +