From c624c9c10b245affaf0d44fc3ae97e0497576653 Mon Sep 17 00:00:00 2001 From: Yousef Moazzam Date: Mon, 10 Aug 2026 09:35:45 +0100 Subject: [PATCH 1/2] Add testing package dependency for more matchers --- frontend/package-lock.json | 94 +++++++++++++++++++++++++++++++++++++- frontend/package.json | 1 + 2 files changed, 94 insertions(+), 1 deletion(-) diff --git a/frontend/package-lock.json b/frontend/package-lock.json index ea1cf38..ab3379d 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -6,7 +6,7 @@ "packages": { "": { "name": "imaginghub", - "version": "0.8.1", + "version": "0.9.3", "dependencies": { "@apollo/client": "^4.2.9", "@diamondlightsource/davidia": "1.0.3", @@ -39,6 +39,7 @@ "@graphql-codegen/near-operation-file-preset": "^5.2.1", "@graphql-codegen/typescript-operations": "^6.1.5", "@testing-library/dom": "^10.4.1", + "@testing-library/jest-dom": "^7.0.0", "@testing-library/react": "^16.3.2", "@testing-library/user-event": "^14.6.1", "@types/js-yaml": "^4.0.9", @@ -63,6 +64,13 @@ "vitest": "^4.1.10" } }, + "node_modules/@adobe/css-tools": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.5.0.tgz", + "integrity": "sha512-6OzddxPio9UiWTCemp4N8cYLV2ZN1ncRnV1cVGtve7dhPOtRkleRyx32GQCYSwDYgaHU3USMm84tNsvKzRCa1Q==", + "dev": true, + "license": "MIT" + }, "node_modules/@apollo/client": { "version": "4.2.9", "resolved": "https://registry.npmjs.org/@apollo/client/-/client-4.2.9.tgz", @@ -4335,6 +4343,36 @@ "node": ">=18" } }, + "node_modules/@testing-library/jest-dom": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-7.0.0.tgz", + "integrity": "sha512-HKAH9C6mBo5yBG6yRO5i43L2iisencAo5z+o5P/saHUoY+miC5ivXRxHBJcFyB5ypPNxHJdK3BoF/3O4DIptMg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@adobe/css-tools": "^4.4.0", + "aria-query": "^5.0.0", + "css.escape": "^1.5.1", + "dom-accessibility-api": "^0.6.3", + "picocolors": "^1.1.1", + "redent": "^3.0.0" + }, + "engines": { + "node": ">=22", + "npm": ">=6", + "yarn": ">=1" + }, + "peerDependencies": { + "@testing-library/dom": ">=10 <11" + } + }, + "node_modules/@testing-library/jest-dom/node_modules/dom-accessibility-api": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.6.3.tgz", + "integrity": "sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w==", + "dev": true, + "license": "MIT" + }, "node_modules/@testing-library/react": { "version": "16.3.2", "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-16.3.2.tgz", @@ -6496,6 +6534,13 @@ "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0" } }, + "node_modules/css.escape": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/css.escape/-/css.escape-1.5.1.tgz", + "integrity": "sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==", + "dev": true, + "license": "MIT" + }, "node_modules/csstype": { "version": "3.2.3", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", @@ -8863,6 +8908,16 @@ "node": ">=0.8.19" } }, + "node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", @@ -10156,6 +10211,16 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/min-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", + "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/minimatch": { "version": "3.1.5", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", @@ -11321,6 +11386,20 @@ "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==", "license": "MIT" }, + "node_modules/redent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", + "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", + "dev": true, + "license": "MIT", + "dependencies": { + "indent-string": "^4.0.0", + "strip-indent": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/reduce-css-calc": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/reduce-css-calc/-/reduce-css-calc-1.3.0.tgz", @@ -12251,6 +12330,19 @@ "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, + "node_modules/strip-indent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", + "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "min-indent": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/strip-json-comments": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", diff --git a/frontend/package.json b/frontend/package.json index d098e11..50e4856 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -47,6 +47,7 @@ "@graphql-codegen/near-operation-file-preset": "^5.2.1", "@graphql-codegen/typescript-operations": "^6.1.5", "@testing-library/dom": "^10.4.1", + "@testing-library/jest-dom": "^7.0.0", "@testing-library/react": "^16.3.2", "@testing-library/user-event": "^14.6.1", "@types/js-yaml": "^4.0.9", From cfb865cdeb7bb6c88e79d4e5f94f2ea3c6971679 Mon Sep 17 00:00:00 2001 From: Yousef Moazzam Date: Mon, 10 Aug 2026 09:51:18 +0100 Subject: [PATCH 2/2] Add session selector test for displaying latest session --- .../src/components/SessionSelector.tsx | 23 +++++-- .../unified/tests/SessionSelector.test.tsx | 62 +++++++++++++++++++ 2 files changed, 79 insertions(+), 6 deletions(-) create mode 100644 frontend/unified/tests/SessionSelector.test.tsx diff --git a/frontend/unified/src/components/SessionSelector.tsx b/frontend/unified/src/components/SessionSelector.tsx index c233498..c885343 100644 --- a/frontend/unified/src/components/SessionSelector.tsx +++ b/frontend/unified/src/components/SessionSelector.tsx @@ -1,3 +1,4 @@ +import React from "react"; import { Chip, TextField, @@ -13,7 +14,7 @@ import { SessionQueryQueryVariables, } from "./__generated__/SessionSelector.generated"; -const SESSION_QUERY: TypedDocumentNode< +export const SESSION_QUERY: TypedDocumentNode< SessionQueryQuery, SessionQueryQueryVariables > = gql` @@ -41,15 +42,24 @@ enum SessionSelectionMode { } export const SessionSelector: React.FC = () => { - // TODO: initial value based on fetching latest session associated with logged-in user - const [session] = useState("latest-session"); // TODO: initial value based on the initial session const [beamline] = useState("Beamline: depends-on-session"); const [sessionSelectionMode, setSessionSelectionMode] = useState(SessionSelectionMode.Latest); const [textInputValue, setTextInputValue] = useState(""); - const sessions = useQuery(SESSION_QUERY, {}); - console.log("sessions: ", sessions); + const { loading, error, data } = useQuery(SESSION_QUERY, { variables: {} }); + + if (loading) return

Loading...

; + if (error) return

Error : {error.message}

; + if (data === undefined) { + return

Data undefined

; + } + + const proposal = data.account?.proposalRoles[0].proposal; + const latestSessionNumber = + proposal?.instrumentSessions[proposal?.instrumentSessions.length - 1] + .instrumentSessionNumber; + const latestSession = `${proposal?.proposalCategory?.toLowerCase()}${proposal?.proposalNumber}-${latestSessionNumber}`; return ( @@ -78,12 +88,13 @@ export const SessionSelector: React.FC = () => { ) => { diff --git a/frontend/unified/tests/SessionSelector.test.tsx b/frontend/unified/tests/SessionSelector.test.tsx new file mode 100644 index 0000000..4057678 --- /dev/null +++ b/frontend/unified/tests/SessionSelector.test.tsx @@ -0,0 +1,62 @@ +import React from "react"; +import "@testing-library/jest-dom"; +import { expect, test, vi, afterEach } from "vitest"; +import { render, screen } from "@testing-library/react"; +import { MockedProvider } from "@apollo/client/testing/react"; +import { + SessionSelector, + SESSION_QUERY, +} from "../src/components/SessionSelector"; + +afterEach(() => { + vi.clearAllMocks(); +}); + +const mocks = [ + { + request: { + query: SESSION_QUERY, + variables: {}, + }, + result: { + data: { + account: { + proposalRoles: [ + { + proposal: { + proposalNumber: 12345, + proposalCategory: "MG", + title: "test proposal title", + instrumentSessions: [ + { + startTime: "2024-03-12T09:00:00", + endTime: "2024-03-15T09:00:00", + instrumentSessionNumber: 1, + }, + { + startTime: "2024-01-23T09:00:00", + endTime: "2024-01-24T01:00:00", + instrumentSessionNumber: 2, + }, + ], + }, + }, + ], + }, + }, + }, + }, +]; + +test("session selector input field renders latest session from query", async () => { + render( + + + + ); + const sessionSelectorInput = await screen.findByTestId( + "session-selector-input" + ); + const input = sessionSelectorInput.querySelector("input"); + expect(input).toHaveValue("mg12345-2"); +});