From 5c5a3b15f14d80af8c584eedc4fac6a10c922c54 Mon Sep 17 00:00:00 2001 From: Muhammad Ashhub Ali Date: Mon, 13 May 2024 12:34:09 +0500 Subject: [PATCH] Added Two more Test Suites for Hooks and Selenium GUI Testing --- PhotoGallery.side | 125 ++++++++++++++ view_generator_serv/package-lock.json | 158 ++++++------------ view_generator_serv/package.json | 3 +- view_generator_serv/setup.js | 10 +- .../src/components/__test__/Sidebar.test.jsx | 1 - .../src/context/__test__/AuthContext.test.js | 38 +++++ .../src/hooks/__test__/useLogin.test.js | 64 +++++++ 7 files changed, 282 insertions(+), 117 deletions(-) create mode 100644 PhotoGallery.side create mode 100644 view_generator_serv/src/context/__test__/AuthContext.test.js create mode 100644 view_generator_serv/src/hooks/__test__/useLogin.test.js diff --git a/PhotoGallery.side b/PhotoGallery.side new file mode 100644 index 0000000..cd461fb --- /dev/null +++ b/PhotoGallery.side @@ -0,0 +1,125 @@ +{ + "id": "5961be57-55dc-4f00-854f-8c09b6e6875f", + "version": "2.0", + "name": "PhotoGallery", + "url": "http://localhost:3000", + "tests": [{ + "id": "c196feb8-a3a1-4b30-aa00-896b11c5977f", + "name": "Logging in and uploading image", + "commands": [{ + "id": "b4d664ef-2971-4428-90da-822bbd627110", + "comment": "", + "command": "open", + "target": "/login", + "targets": [], + "value": "" + }, { + "id": "df90103a-093c-4981-8b5f-6747e9fdb05b", + "comment": "", + "command": "setWindowSize", + "target": "954x693", + "targets": [], + "value": "" + }, { + "id": "82335a41-e785-4a5d-a3bc-700cd57c70e9", + "comment": "", + "command": "click", + "target": "id=username", + "targets": [ + ["id=username", "id"], + ["css=#username", "css:finder"], + ["xpath=//input[@id='username']", "xpath:attributes"], + ["xpath=//div[@id='root']/div/div/div/div/div/form/div[2]/input", "xpath:idRelative"], + ["xpath=//input", "xpath:position"] + ], + "value": "" + }, { + "id": "cd74eff1-dc9c-48b5-962c-9a5630614d83", + "comment": "", + "command": "type", + "target": "id=username", + "targets": [ + ["id=username", "id"], + ["css=#username", "css:finder"], + ["xpath=//input[@id='username']", "xpath:attributes"], + ["xpath=//div[@id='root']/div/div/div/div/div/form/div[2]/input", "xpath:idRelative"], + ["xpath=//input", "xpath:position"] + ], + "value": "AshIsHere" + }, { + "id": "58118ef3-5918-40fd-9d56-6da599f7ecc2", + "comment": "", + "command": "click", + "target": "id=password", + "targets": [ + ["id=password", "id"], + ["css=#password", "css:finder"], + ["xpath=//input[@id='password']", "xpath:attributes"], + ["xpath=//div[@id='root']/div/div/div/div/div/form/div[3]/input", "xpath:idRelative"], + ["xpath=//div[3]/input", "xpath:position"] + ], + "value": "" + }, { + "id": "1a9597cc-3260-4407-b90a-e27ff5722a1c", + "comment": "", + "command": "type", + "target": "id=password", + "targets": [ + ["id=password", "id"], + ["css=#password", "css:finder"], + ["xpath=//input[@id='password']", "xpath:attributes"], + ["xpath=//div[@id='root']/div/div/div/div/div/form/div[3]/input", "xpath:idRelative"], + ["xpath=//div[3]/input", "xpath:position"] + ], + "value": "Ash@12345" + }, { + "id": "91def1cf-f42a-4738-9fac-e3f513dbdba2", + "comment": "", + "command": "click", + "target": "css=.css-1ikp3wz", + "targets": [ + ["css=.css-1ikp3wz", "css:finder"], + ["xpath=//button[@type='submit']", "xpath:attributes"], + ["xpath=//div[@id='root']/div/div/div/div/div/form/button", "xpath:idRelative"], + ["xpath=//button", "xpath:position"], + ["xpath=//button[contains(.,'Log In')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "77e9dfc5-89d9-47dd-94ca-dbef5ccaa556", + "comment": "", + "command": "click", + "target": "css=.css-6r4ark", + "targets": [ + ["css=.css-6r4ark", "css:finder"], + ["xpath=//div[@id='root']/div/div/div[2]/div/div/div/p", "xpath:idRelative"], + ["xpath=//div[2]/div/div/div/p", "xpath:position"], + ["xpath=//p[contains(.,'View Type:')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "ef3a29f4-4db6-4565-a45c-2fba0960c730", + "comment": "", + "command": "click", + "target": "id=field-:r9:", + "targets": [ + ["id=field-:r9:", "id"], + ["css=#field-\\3Ar9\\3A", "css:finder"], + ["xpath=//input[@id='field-:r9:']", "xpath:attributes"], + ["xpath=//div[@id='root']/div/div/div[2]/div/div/form/div/input", "xpath:idRelative"], + ["xpath=//input", "xpath:position"] + ], + "value": "" + }] + }], + "suites": [{ + "id": "1fb9c823-da16-48d5-8c26-cccc61116a03", + "name": "Default Suite", + "persistSession": false, + "parallel": false, + "timeout": 300, + "tests": ["c196feb8-a3a1-4b30-aa00-896b11c5977f"] + }], + "urls": ["http://localhost:3000/"], + "plugins": [] +} \ No newline at end of file diff --git a/view_generator_serv/package-lock.json b/view_generator_serv/package-lock.json index cb0191b..b3a4370 100644 --- a/view_generator_serv/package-lock.json +++ b/view_generator_serv/package-lock.json @@ -34,6 +34,7 @@ "@babel/core": "^7.24.5", "@babel/preset-env": "^7.24.5", "@faker-js/faker": "^8.4.1", + "@testing-library/react-hooks": "^8.0.1", "jest-mock-axios": "^4.7.3", "react-test-renderer": "^18.3.1" } @@ -5416,104 +5417,6 @@ "url": "https://github.com/sponsors/gregberge" } }, - "node_modules/@testing-library/dom": { - "version": "9.3.3", - "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-9.3.3.tgz", - "integrity": "sha512-fB0R+fa3AUqbLHWyxXa2kGVtf1Fe1ZZFr0Zp6AIbIAzXb2mKbEXl+PCQNUOaq5lbTab5tfctfXRNsWXxa2f7Aw==", - "peer": true, - "dependencies": { - "@babel/code-frame": "^7.10.4", - "@babel/runtime": "^7.12.5", - "@types/aria-query": "^5.0.1", - "aria-query": "5.1.3", - "chalk": "^4.1.0", - "dom-accessibility-api": "^0.5.9", - "lz-string": "^1.5.0", - "pretty-format": "^27.0.2" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/@testing-library/dom/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "peer": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/@testing-library/dom/node_modules/aria-query": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.1.3.tgz", - "integrity": "sha512-R5iJ5lkuHybztUfuOAznmboyjWq8O6sqNqtK7CLOqdydi54VNbORp49mb14KbWgG1QD3JFO9hJdZ+y4KutfdOQ==", - "peer": true, - "dependencies": { - "deep-equal": "^2.0.5" - } - }, - "node_modules/@testing-library/dom/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "peer": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/@testing-library/dom/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "peer": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/@testing-library/dom/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "peer": true - }, - "node_modules/@testing-library/dom/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "peer": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/@testing-library/dom/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "peer": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/@testing-library/jest-dom": { "version": "5.17.0", "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-5.17.0.tgz", @@ -5613,6 +5516,36 @@ "react-dom": "^18.0.0" } }, + "node_modules/@testing-library/react-hooks": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@testing-library/react-hooks/-/react-hooks-8.0.1.tgz", + "integrity": "sha512-Aqhl2IVmLt8IovEVarNDFuJDVWVvhnr9/GCU6UUnrYXwgDFF9h2L2o2P9KBni1AST5sT6riAyoukFLyjQUgD/g==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.12.5", + "react-error-boundary": "^3.1.0" + }, + "engines": { + "node": ">=12" + }, + "peerDependencies": { + "@types/react": "^16.9.0 || ^17.0.0", + "react": "^16.9.0 || ^17.0.0", + "react-dom": "^16.9.0 || ^17.0.0", + "react-test-renderer": "^16.9.0 || ^17.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "react-dom": { + "optional": true + }, + "react-test-renderer": { + "optional": true + } + } + }, "node_modules/@testing-library/react/node_modules/@testing-library/dom": { "version": "8.20.1", "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-8.20.1.tgz", @@ -18947,6 +18880,22 @@ "react": "^18.2.0" } }, + "node_modules/react-error-boundary": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/react-error-boundary/-/react-error-boundary-3.1.4.tgz", + "integrity": "sha512-uM9uPzZJTF6wRQORmSrvOIgt4lJ9MC1sNgEOj2XGsDTRE4kmpWxg7ENK9EWNKJRMAOY9z0MuF4yIfl6gp4sotA==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.12.5" + }, + "engines": { + "node": ">=10", + "npm": ">=6" + }, + "peerDependencies": { + "react": ">=16.13.1" + } + }, "node_modules/react-error-overlay": { "version": "6.0.11", "resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.11.tgz", @@ -21247,19 +21196,6 @@ "is-typedarray": "^1.0.0" } }, - "node_modules/typescript": { - "version": "4.9.5", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", - "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", - "peer": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=4.2.0" - } - }, "node_modules/unbox-primitive": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", diff --git a/view_generator_serv/package.json b/view_generator_serv/package.json index b85fc74..b13660b 100644 --- a/view_generator_serv/package.json +++ b/view_generator_serv/package.json @@ -28,7 +28,7 @@ "scripts": { "start": "react-scripts start", "build": "react-scripts build", - "test": "react-scripts test --transformIgnorePatterns \"node_modules/(?!axios)/\"", + "test": "react-scripts test --watchAll --transformIgnorePatterns \"node_modules/(?!axios)/\"", "testCI": "CI=true react-scripts test --transformIgnorePatterns \"node_modules/(?!axios)/\"", "eject": "react-scripts eject" }, @@ -54,6 +54,7 @@ "@babel/core": "^7.24.5", "@babel/preset-env": "^7.24.5", "@faker-js/faker": "^8.4.1", + "@testing-library/react-hooks": "^8.0.1", "jest-mock-axios": "^4.7.3", "react-test-renderer": "^18.3.1" } diff --git a/view_generator_serv/setup.js b/view_generator_serv/setup.js index 61e7ad9..12ccc18 100644 --- a/view_generator_serv/setup.js +++ b/view_generator_serv/setup.js @@ -1,4 +1,6 @@ -import renderer from 'react-test-renderer'; -import React from 'react'; -import { render, fireEvent, waitFor } from '@testing-library/react'; -import '@testing-library/jest-dom'; \ No newline at end of file +import '@testing-library/jest-dom'; +import '@testing-library/jest-dom/extend-expect'; +import { configure } from '@testing-library/react'; + +// automatically unmount and cleanup DOM after the test is finished. +configure({ autoCleanup: true }); \ No newline at end of file diff --git a/view_generator_serv/src/components/__test__/Sidebar.test.jsx b/view_generator_serv/src/components/__test__/Sidebar.test.jsx index 33e68b4..6d781a7 100644 --- a/view_generator_serv/src/components/__test__/Sidebar.test.jsx +++ b/view_generator_serv/src/components/__test__/Sidebar.test.jsx @@ -1,6 +1,5 @@ import React from 'react'; import { render, fireEvent, waitFor, screen } from '@testing-library/react'; -import userEvent from '@testing-library/user-event'; import '@testing-library/jest-dom'; import { BrowserRouter as Router } from 'react-router-dom'; import { useAuthContext } from '../../hooks/useAuthContext'; diff --git a/view_generator_serv/src/context/__test__/AuthContext.test.js b/view_generator_serv/src/context/__test__/AuthContext.test.js new file mode 100644 index 0000000..3892a96 --- /dev/null +++ b/view_generator_serv/src/context/__test__/AuthContext.test.js @@ -0,0 +1,38 @@ +import { render, screen } from '@testing-library/react'; +import { AuthContextProvider, AuthContext } from '../AuthContext'; +import { useContext } from 'react'; + +const TestingComponent = () => { + const { user } = useContext(AuthContext); + return ( + <> +

{user?.name}

+ + ); +}; + +describe('', () => { + let user; + + beforeAll(() => { + user = { + name: 'John Doe', + }; + }); + + beforeEach(() => { + // Mock localStorage + Storage.prototype.getItem = jest.fn(() => JSON.stringify(user)); + + render( + + + , + ); + }); + + it('provides expected AuthContext to child elements', () => { + const userName = screen.getByTestId('user-name'); + expect(userName.textContent).toEqual(user.name); + }); +}); \ No newline at end of file diff --git a/view_generator_serv/src/hooks/__test__/useLogin.test.js b/view_generator_serv/src/hooks/__test__/useLogin.test.js new file mode 100644 index 0000000..84cf3a6 --- /dev/null +++ b/view_generator_serv/src/hooks/__test__/useLogin.test.js @@ -0,0 +1,64 @@ +import { renderHook, act } from '@testing-library/react-hooks'; +import axios from 'axios'; +import { useLogin } from '../useLogin'; +import React from 'react'; + +jest.mock('axios'); +jest.mock('../useAuthContext', () => ({ + useAuthContext: () => ({ dispatch: jest.fn() }), +})); +// Mock localStorage +// Mock localStorage +const localStorageMock = { + getItem: jest.fn(), + setItem: jest.fn(), + removeItem: jest.fn(), + clear: jest.fn() +}; + +Object.defineProperty(window, 'localStorage', { value: localStorageMock }); + + + + +describe('useLogin', () => { + const dispatchMock = jest.fn(); + const useAuthContextMock = jest.fn().mockReturnValue({ dispatch: dispatchMock }); + + beforeEach(() => { + useAuthContextMock.mockClear(); + dispatchMock.mockClear(); + axios.mockClear(); + }); + + it('should handle login failure', async () => { + const fakeError = { response: { status: 401, data: { message: 'Unauthorized' } } }; + axios.post.mockRejectedValue(fakeError); + + const { result, waitForNextUpdate } = renderHook(() => useLogin(), { + wrapper: ({ children }) => {children}, + }); + + act(() => { + result.current.login('testuser', 'password'); + }); + + expect(result.current.isLoading).toBeTruthy(); + + await waitForNextUpdate(); + + expect(result.current.isLoading).toBeFalsy(); + expect(result.current.error).toBe(fakeError.response.data.message); + }); +}); + +// Mock AuthProvider component for providing the context value +const MockAuthProvider = ({ children }) => { + const contextValue = { dispatch: jest.fn() }; // You might need to mock this as per your context structure + return {children}; +}; + +// Mock AuthContext for testing +const MockAuthContext = React.createContext({ + dispatch: jest.fn(), +});