From 16e4e50740ef64e82e2eff6550e4d2a4ba09a548 Mon Sep 17 00:00:00 2001 From: kleinwave Date: Tue, 17 Dec 2024 14:23:02 +0200 Subject: [PATCH] chore: implement requested changes from PR review --- .github/workflows/playwright-tests.yaml | 3 +- frontend/.gitignore | 1 + frontend/tests/README.md | 122 +++++-------------- frontend/tests/e2e/workflow2.test.ts | 155 ------------------------ frontend/tests/e2e/workflow3.test.ts | 12 -- 5 files changed, 29 insertions(+), 264 deletions(-) delete mode 100644 frontend/tests/e2e/workflow2.test.ts delete mode 100644 frontend/tests/e2e/workflow3.test.ts diff --git a/.github/workflows/playwright-tests.yaml b/.github/workflows/playwright-tests.yaml index fe5b2fae..28af0f48 100644 --- a/.github/workflows/playwright-tests.yaml +++ b/.github/workflows/playwright-tests.yaml @@ -81,5 +81,4 @@ jobs: qualibrate start & sleep 5 # Wait for the server to start npx playwright test e2e/workflow1.test.ts - - + \ No newline at end of file diff --git a/frontend/.gitignore b/frontend/.gitignore index c2c5fdef..fef9a63e 100644 --- a/frontend/.gitignore +++ b/frontend/.gitignore @@ -3,6 +3,7 @@ # Edit at https://www.toptal.com/developers/gitignore?templates=react ### react ### +.DS_Store .DS_* *.log logs diff --git a/frontend/tests/README.md b/frontend/tests/README.md index a6297eb6..4fb9306c 100644 --- a/frontend/tests/README.md +++ b/frontend/tests/README.md @@ -18,6 +18,33 @@ qualibrate start ``` Once the server is running, access the application at http://127.0.0.1:8001/. +## Running Tests Locally with `act` + +To simulate GitHub Actions locally and run the tests, you can use the `act` tool. + +### Prerequisites + +1. Install [act](https://github.com/nektos/act) by following the installation instructions on its GitHub page. +2. Ensure Docker is installed and running on your machine. + +### Running Tests + +To execute the Playwright tests locally using act, run the following command from qualibrate-app directory: +```bash +act -j test --container-architecture linux/amd64 -s QUALIBRATION_EXAMPLES_TOKEN= +``` +- -j test: Runs the test job defined in the GitHub Actions workflow file. +- --container-architecture linux/amd64: Ensures compatibility with the workflow container. +- Replace with the actual token value you generated. + - This will allow the GitHub Action to access the qualibrate-examples repository and pull the necessary calibration scripts which are a test-dependency. + - Note: Manually entering your token isn't a requirement for runninng the tests on Github, only locally with `act`. + +This will perform the steps as defined in the CI pipeline, including: +- Installing dependencies. +- Starting the qualibrate server. +- Running the Playwright tests. + + ## Workflow 1: Running a calibration node ### This test validates the end-to-end workflow of running a calibration node in the QUAlibrate application. @@ -49,98 +76,3 @@ Once the server is running, access the application at http://127.0.0.1:8001/. 8. **Check/Update State Values** - Verify the State Updates section displays suggested changes. - Modify values, click the up-arrow to apply changes, and ensure updates are successful. - - -## Workflow 2: Running a Calibration Graph - -### The following workflow tests the functionality of running a calibration graph within the QUAlibrate application. - -1. **Navigate to the Graph Library**: - - Ensure the application is running at http://127.0.0.1:8001/. - - Verify that the main page loads successfully. - - Click on the "Graph Library" tab in the sidebar. - - Confirm make page elements have loaded -2. **Select a Calibration Graph**: - - Identify and click on a specific calibration graph (e.g., `Single Qubit Tuneup`). - - Verify that the graph parameters are displayed. - - You see the calibration nodes populated on the left hands side - - You see the calibration graph populated the right hand side - - Ensure the qubits section is editable to include qubits such as `q0`, `q2`, and `q3`. -3. **Modify Node-Specific Parameters**: - - Navigate to a specific node in the calibration graph and click on the `qubit_spectroscopy` node. - - verify that its parameters are expanded and are now visable - - varify `parameters` qubit parameter has calapsed - - Navigate to the calibration graph and click the middle `Rabi` node - - varify that the `qubit_spectroscopy` parameters have calapsed - - varify that the `Rabi` parameters are visible - - For `Rabi`, update a parameter, such as changing the sampling points from `100` to `1000`. - - Ensure that the updated parameter value is correctly reflected. - - Expand the Ramsey node it too also works correctly -4. **Run the Calibration Graph**: - - Click the "Play" button to start running the graph. - - Verify that the application navigates to the "Graph Status" page. - - Confirm that the graph status shows `running` and that progress (e.g., "1 out of 3 nodes completed") is displayed. -5. **Monitor Graph Execution**: - - Wait for the graph to finish executing. - - Verify that the status updates to `finished` and displays the total runtime (e.g., `12 seconds`). -6. **View Results**: - - Confirm nodes populated in Execution History are expandable and shows the Status, Parameters, and Outcomes sections. - - Check the results section to ensure that data (e.g., qubit spectroscopy) is displayed. - - ~~Confirm that failed nodes or operations are clearly marked, along with the corresponding parameters.~~ - - Confirm the QuAM state window is visible -7. **Inspect Additional Nodes**: - - Navigate through the results of other nodes in the graph (e.g., `Rabi` and `Ramsey`). - - ~~Verify that all available results are displayed, or confirm that no results are present if the node has not generated data.~~ - - -## Workflow 3: Viewing Past Data - -### This workflow ensures users can effectively interact with the "Data" section to review previously recorded measurements, inspect quantum system states, and view saved calibration results. - -1. **Navigate to the Data Section**: - - Open http://127.0.0.1:8001/ in your web browser. - - Click on the "Data" tab in the sidebar. - - Verify that the "Measurement History" heading is visible and that a list of past measurements is displayed. - -2. **Verify Measurements**: - - Check that at least two measurements (e.g., `qubit_spectroscopy`, `Power Rabi`) are present in the measurement list. - - Confirm each measurement has a unique identifier and associated metadata. - -3. **Search Quantum States**: - - Use the search bar to filter measurements (e.g., search for "channel1"). - - Verify that the results update dynamically and only display relevant entries. - -4. **Expand and Collapse Quantum States**: - - Click on a quantum state entry to expand it. - - Verify that the entry shows detailed data, such as channels and their respective values. - - Collapse the entry and ensure it hides the details. - -5. **Validate Qual Updates**: - - Select a measurement with qual updates (e.g., `Power Rabi`). - - Verify that the updates show old and new values for relevant parameters. - - Check that updates correspond accurately to the recorded calibration data. - -6. **Handle Missing Data**: - - Identify a measurement without saved qual states. - - Verify that an appropriate message (e.g., "No qual state saved for this measurement.") is displayed to the user. - - -#### ~~Workflow 4: Typical runtime workflows~~ -- ~~Verify seamless switching between tabs during runtime.~~ -- ~~Validate runtime updates appear dynamically in the "Running Job" container.~~ -- ~~Test runtime responsiveness to changes in parameters mid-execution.~~ -- ~~Verify logs and results update dynamically during node execution.~~ -- ~~Check the correctness of intermediate runtime results (e.g., partial graphs, lo~~gs). -- ~~Test edge cases, such as disconnecting from the server mid-execution.~~ -- ~~Ensure error handling for unexpected runtime failures.~~ - - -#### ~~Workflow 5: Changing project~~ -- ~~Verify navigation to the Project tab.~~ -- ~~Validate project selection from the list.~~ -- ~~Test search functionality for projects (case-insensitive).~~ -- ~~Verify double-click opens a project directly.~~ -- ~~Ensure switching projects reloads associated nodes and graphs.~~ -- ~~Test project state retention (e.g., saving/loading).~~ -- ~~Validate project creation via the "+" button.~~ -- ~~Ensure feedback is provided for invalid or duplicate project names.~~ diff --git a/frontend/tests/e2e/workflow2.test.ts b/frontend/tests/e2e/workflow2.test.ts deleted file mode 100644 index 128ab2f9..00000000 --- a/frontend/tests/e2e/workflow2.test.ts +++ /dev/null @@ -1,155 +0,0 @@ -import { test, expect } from '@playwright/test'; - -// Test for Workflow 1 -// Still in Progress -test('Workflow2', { - annotation: { - type: 'Second User Workflow', - description: 'Running a calibration graph', - }, - }, async ({ page }) => { - - - // 1. Navigate to the Graph Library: - // Ensure the application is running at http://127.0.0.1:8001/. - await page.goto('http://localhost:8001/'); - // Verify that the main page loads successfully. - expect(page.url()).toBe('http://localhost:8001/'); // page loaded successfully - // Click on the "Graph Library" tab in the sidebar. - await page.getByRole('button', { name: 'Graph library' }).click(); - // Confirm make page elements have loaded - await expect(page.getByRole('heading', { name: 'Run calibration graph' })).toBeVisible(); - await expect(page.getByPlaceholder('graph name')).toBeVisible(); - await expect(page.getByRole('button', { name: 'Refresh' })).toBeVisible(); - await expect(page.getByText('Single Qubit TuneupParametersQubits:Qubit_spectroscopyRabiRamsey')).toBeVisible(); - await expect(page.getByText('test_workflowParametersQubits')).toBeVisible(); - - // 2. Select a Calibration Graph: - // Identify and click on a specific calibration graph (e.g., `Single Qubit Tuneup`). - await page.getByText('Single Qubit TuneupParametersQubits:Qubit_spectroscopyRabiRamsey').click(); - // Verify that the graph parameters are displayed. - await expect(page.getByRole('textbox', { name: 'qubits' })).toBeVisible(); - // You see the calibration nodes populated on the left hands side - await expect(page.getByText('ParametersQubits:Qubit_spectroscopyRabiRamsey')).toBeVisible(); - await expect(page.getByText('ParametersQubits:').first()).toBeVisible(); - await expect(page.locator('div').filter({ hasText: /^Qubit_spectroscopy$/ }).first()).toBeVisible(); - await expect(page.locator('div').filter({ hasText: /^Rabi$/ }).first()).toBeVisible(); - await expect(page.locator('div').filter({ hasText: /^Ramsey$/ }).first()).toBeVisible(); - // You see the calibration graph populated the right hand side - await expect(page.locator('canvas').first()).toBeVisible(); - // Ensure the qubits section is editable to include qubits such as q0, q2, and q3. - const qubitsInput = page.getByRole('textbox', { name: 'qubits' }); - await qubitsInput.click(); - await qubitsInput.fill('q0, q2, q3'); - await expect(qubitsInput).toHaveValue('q0, q2, q3'); - - // 3. Modify Node-Specific Parameters: - // Navigate to a specific node in the calibration graph and click on the qubit_spectroscopy node. - await page.locator('canvas').first().click({ - modifiers: ['ControlOrMeta'], - position: { - x: 365, - y: 63 - } - }); - // verify that its parameters are expanded and are now visable - await expect(page.locator('div').filter({ hasText: /^Sampling Points:$/ }).first()).toBeVisible(); - await expect(page.locator('div').filter({ hasText: /^Noise Factor:$/ }).first()).toBeVisible(); - // varify parameters qubit parameter has calapsed - await expect(page.getByRole('textbox', { name: 'qubits' })).toBeHidden(); - // Navigate to the calibration graph and click the middle Rabi node - await page.waitForTimeout(1000); - await page.locator('canvas').first().click({ - position: { - x: 367, - y: 203 - } - }); - // varify that the qubit_spectroscopy parameters have calapsed - await expect(page.getByText('Qubit_spectroscopySampling')).toBeHidden(); - // varify that the Rabi parameters are visible - await expect(page.getByText('RabiSampling Points:Noise')).toBeVisible(); - await expect(page.locator('div').filter({ hasText: /^Sampling Points:$/ }).first()).toBeVisible(); - await expect(page.locator('div').filter({ hasText: /^Noise Factor:$/ }).first()).toBeVisible(); - await expect(page.locator('div').filter({ hasText: /^Test List:$/ }).first()).toBeVisible(); - // For Rabi, update a parameter, such as changing the sampling points from 100 to 1000. - const samplingPointsInput = page.getByPlaceholder('sampling_points'); - await samplingPointsInput.click(); - await samplingPointsInput.fill('1000'); - // Ensure that the updated parameter value is correctly reflected. - await expect(samplingPointsInput).toHaveValue('1000'); - // Expand the Ramsey node it too also works correctly - const parameterTitle5 = page.locator('div:nth-child(5) > [class^="Parameters-module__parameterTitle__"]'); - const arrowIcon5 = parameterTitle5.locator('[class^="Parameters-module__arrowIconWrapper__"]'); - await arrowIcon5.first().click(); - - - // 4. Run the Calibration Graph: - // Click the "Play" button to start running the graph. - await page.locator('[class^="GraphElement-module__iconWrapper__"] > div > svg').first().click(); - // Verify that the application navigates to the "Graph Status" page. - await expect(page.getByText('Calibration Graph Progress')).toBeVisible(); - // Confirm that the graph status shows `Running`. - await expect(page.getByText('Status: Running')).toBeVisible(); - // Confirm progress (e.g., "1 out of 3 nodes completed") is displayed. - await expect(page.getByText('Graph progress: 0/3 node')).toBeVisible(); - await expect(page.getByText('No measurements found')).toBeVisible(); // before any node is measured at all - await expect(page.getByText('Graph progress: 1/3 node')).toBeVisible(); - await expect(page.locator('[class^="MeasurementElement-module__row__"]')).toBeVisible(); // Qubit_spectroscopy populates in execution history - await expect(page.getByText('Graph progress: 2/3 nodes')).toBeVisible(); - await expect(page.locator('[class^="MeasurementElement-module__rowWrapper__"]').first()).toBeVisible(); // Rabi populates in execution history - await expect(page.getByText('Graph progress: 3/3 nodes')).toBeVisible(); - await expect(page.locator('[class^="MeasurementElement-module__rowWrapper__"]').first()).toBeVisible(); // Ramsey populates in execution history - - // 5. Monitor Graph Execution: - // Wait for the graph to finish executing. - await expect(page.getByText('Status: finished')).toBeVisible(); - // Verify total runtime is displayed (e.g., Run duration: 12.176s). - await expect(page.getByText(/Run duration: \d+\.\d{1,3}s/)).toBeVisible(); - - // 6. View Results: - // Confirm nodes populated in Execution History are expandable and shows Status, Parameters, and Outcomes sections. - await page.locator('div:nth-child(3) > [class^="MeasurementElement-module__rowWrapper__"]').click(); - // await expect(page.getByText('#408 Qubit_spectroscopyStatus')).toBeVisible(); - // await expect(page.getByText(/#\d+ Qubit_spectroscopyStatus/)).toBeVisible(); - await expect(page.getByText(/.*Qubit_spectroscopyStatus/)).toBeVisible(); - await expect(page.getByText(/Status:Run start: \d{4}-\d{2}-\d{2}/)).toBeVisible(); - // Status - await expect(page.getByText('Status:', { exact: true })).toBeVisible(); - await expect(page.getByText(/Run start: \d{4}-\d{2}-\d{2} \d{2}:\d{2}:/)).toBeVisible(); - // Parameters - await expect(page.getByText('Parameters')).toBeVisible(); - await expect(page.getByText('qubits: q0q2q3sampling_points')).toBeVisible(); - await expect(page.getByText('qubits: q0q2q3')).toBeVisible(); - await expect(page.getByText('sampling_points:')).toBeVisible(); - await expect(page.getByText('noise_factor:')).toBeVisible(); - // Outcomes - await expect(page.getByText('Outcomes')).toBeVisible(); - // Check the results section to ensure that data (e.g., qubit spectroscopy) is displayed. - await expect(page.getByRole('heading', { name: 'Results' })).toBeVisible(); - await expect(page.getByPlaceholder('Enter a value').first()).toBeVisible(); - await expect(page.getByTestId('data-key-pairfrequency_shift')).toBeVisible(); - await expect(page.getByTestId('data-key-pairfrequency_shift')).toContainText(/"frequency_shift":\d+(\.\d+)?/); // Matches the format of any number - await expect(page.getByText('"./results_fig.png"')).toBeVisible(); - await expect(page.locator('a')).toBeVisible(); // results figure - await expect(page.getByTestId('data-key-pairarr')).toBeVisible(); - // Confirm the QuAM state window is visible - await expect(page.getByRole('heading', { name: 'QuAM' })).toBeVisible(); - await expect(page.getByPlaceholder('Enter a value').nth(1)).toBeVisible(); - await expect(page.locator('div').filter({ hasText: /^\{\}0 Items$/ }).first()).toBeVisible(); - - // 7 Inspect Additional Nodes: - // Navigate through the results of other nodes in the graph (e.g., `Rabi` and `Ramsey`). - await page.locator('canvas').first().click({ // clicking on the Rabi node - position: { - x: 157, - y: 204 - } - }); - await page.locator('canvas').first().click({ // clicking on the Ramsey node - position: { - x: 158, - y: 348 - } - }); - }); \ No newline at end of file diff --git a/frontend/tests/e2e/workflow3.test.ts b/frontend/tests/e2e/workflow3.test.ts deleted file mode 100644 index efd619f6..00000000 --- a/frontend/tests/e2e/workflow3.test.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { test, expect } from '@playwright/test'; - - -test('Workflow_3', { - annotation: { - type: 'Third User Workflow', - description: 'Viewing Past Data', - }, - }, async ({ page }) => { - - // TODO -}); \ No newline at end of file