20609: Add unit tests for subprocess progress bar, includes node/dom upgrade to 16...
authorStephen Smith <stephen@curii.com>
Tue, 7 Nov 2023 20:50:37 +0000 (15:50 -0500)
committerStephen Smith <stephen@curii.com>
Tue, 7 Nov 2023 20:50:37 +0000 (15:50 -0500)
Arvados-DCO-1.1-Signed-off-by: Stephen Smith <stephen@curii.com>

cypress/integration/project.spec.js
package.json
src/components/subprocess-progress-bar/subprocess-progress-bar.test.tsx [new file with mode: 0644]
src/store/tree-picker/tree-picker-actions.test.ts
yarn.lock

index a8663d862261bdd51b1be0c353c2ba9ad1a363be..e61138219dcf01558151f2179aec78983c73f6ad 100644 (file)
@@ -564,7 +564,7 @@ describe("Project tests", function () {
         );
     });
 
-    it.only("sorts displayed items correctly", () => {
+    it("sorts displayed items correctly", () => {
         cy.loginAs(activeUser);
 
         cy.get('[data-cy=project-panel] button[title="Select columns"]').click();
index acc2db6ae1b75e05919cbf7573076b98b9b5c3bc..fd9cdf78225ffa58a8a38c3f96b7dcf3f940b6ae 100644 (file)
     "parse-duration": "0.4.4",
     "prop-types": "15.7.2",
     "query-string": "6.9.0",
-    "react": "16.8.6",
+    "react": "16.14.0",
     "react-copy-to-clipboard": "5.0.3",
     "react-dnd": "5.0.0",
     "react-dnd-html5-backend": "5.0.1",
-    "react-dom": "16.8.6",
+    "react-dom": "16.14.0",
     "react-dropzone": "5.1.1",
     "react-highlight-words": "0.14.0",
     "react-idle-timer": "4.3.6",
diff --git a/src/components/subprocess-progress-bar/subprocess-progress-bar.test.tsx b/src/components/subprocess-progress-bar/subprocess-progress-bar.test.tsx
new file mode 100644 (file)
index 0000000..8373717
--- /dev/null
@@ -0,0 +1,153 @@
+// Copyright (C) The Arvados Authors. All rights reserved.
+//
+// SPDX-License-Identifier: AGPL-3.0
+
+import React from "react";
+import { configure, mount } from "enzyme";
+import { ServiceRepository, createServices } from "services/services";
+import { configureStore } from "store/store";
+import { createBrowserHistory } from "history";
+import { mockConfig } from 'common/config';
+import { ApiActions } from "services/api/api-actions";
+import Axios from "axios";
+import MockAdapter from "axios-mock-adapter";
+import { Process } from "store/processes/process";
+import { ContainerState } from "models/container";
+import Adapter from "enzyme-adapter-react-16";
+import { SubprocessProgressBar } from "./subprocess-progress-bar";
+import { Provider } from "react-redux";
+import { FilterBuilder } from 'services/api/filter-builder';
+import { ProcessStatusFilter, buildProcessStatusFilters } from 'store/resource-type-filters/resource-type-filters';
+import {act} from "react-dom/test-utils";
+
+configure({ adapter: new Adapter() });
+
+describe("<SubprocessProgressBar />", () => {
+    const axiosInst = Axios.create({ headers: {} });
+    const axiosMock = new MockAdapter(axiosInst);
+
+    let store;
+    let services: ServiceRepository;
+    const config: any = {};
+    const actions: ApiActions = {
+        progressFn: (id: string, working: boolean) => { },
+        errorFn: (id: string, message: string) => { }
+    };
+    let statusResponse = {
+        [ProcessStatusFilter.COMPLETED]: 0,
+        [ProcessStatusFilter.RUNNING]: 0,
+        [ProcessStatusFilter.FAILED]: 0,
+        [ProcessStatusFilter.QUEUED]: 0,
+    };
+
+    const createMockListFunc = (uuid: string) => jest.fn(async (args) => {
+        const baseFilter = new FilterBuilder().addEqual('requesting_container_uuid', uuid).getFilters();
+
+        const filterResponses = Object.keys(statusResponse)
+            .map(status => ({filters: buildProcessStatusFilters(new FilterBuilder(baseFilter), status).getFilters(), value: statusResponse[status]}));
+
+        const matchedFilter = filterResponses.find(response => response.filters === args.filters);
+        if (matchedFilter) {
+            return { itemsAvailable: matchedFilter.value };
+        } else {
+            return { itemsAvailable: 0 };
+        }
+    });
+
+    beforeEach(() => {
+        services = createServices(mockConfig({}), actions, axiosInst);
+        store = configureStore(createBrowserHistory(), services, config);
+    });
+
+    it("requests subprocess progress stats for stopped processes and displays progress", async () => {
+        // when
+        const process = {
+            container: {
+                state: ContainerState.COMPLETE,
+            },
+            containerRequest: {
+                containerUuid: 'zzzzz-dz642-000000000000000',
+            },
+        } as Process;
+
+        statusResponse = {
+            [ProcessStatusFilter.COMPLETED]: 100,
+            [ProcessStatusFilter.RUNNING]: 200,
+            [ProcessStatusFilter.FAILED]: 300,
+            [ProcessStatusFilter.QUEUED]: 400,
+        };
+
+        services.containerRequestService.list = createMockListFunc(process.containerRequest.containerUuid);
+
+        let progressBar;
+        await act(async () => {
+            progressBar = mount(
+                <Provider store={store}>
+                    <SubprocessProgressBar process={process} />
+                </Provider>);
+        });
+        await progressBar.update();
+
+        // expects 4 subprocess status list requests
+        const expectedFilters = [
+            ProcessStatusFilter.COMPLETED,
+            ProcessStatusFilter.RUNNING,
+            ProcessStatusFilter.FAILED,
+            ProcessStatusFilter.QUEUED,
+        ].map((state) =>
+            buildProcessStatusFilters(
+                new FilterBuilder().addEqual(
+                    "requesting_container_uuid",
+                    process.containerRequest.containerUuid
+                ),
+                state
+            ).getFilters()
+        );
+
+        expectedFilters.forEach((filter) => {
+            expect(services.containerRequestService.list).toHaveBeenCalledWith({limit: 0, offset: 0, filters: filter});
+        });
+
+        // Verify progress bar with correct degment widths
+        ['10%', '20%', '30%', '40%'].forEach((value, i) => {
+            const styles = progressBar.find('.progress').at(i).props().style;
+            expect(styles).toHaveProperty('width', value);
+        });
+    });
+
+    it("dislays correct progress bar widths with different values", async () => {
+        const process = {
+            container: {
+                state: ContainerState.COMPLETE,
+            },
+            containerRequest: {
+                containerUuid: 'zzzzz-dz642-000000000000001',
+            },
+        } as Process;
+
+        statusResponse = {
+            [ProcessStatusFilter.COMPLETED]: 50,
+            [ProcessStatusFilter.RUNNING]: 55,
+            [ProcessStatusFilter.FAILED]: 60,
+            [ProcessStatusFilter.QUEUED]: 335,
+        };
+
+        services.containerRequestService.list = createMockListFunc(process.containerRequest.containerUuid);
+
+        let progressBar;
+        await act(async () => {
+            progressBar = mount(
+                <Provider store={store}>
+                    <SubprocessProgressBar process={process} />
+                </Provider>);
+        });
+        await progressBar.update();
+
+        // Verify progress bar with correct degment widths
+        ['10%', '11%', '12%', '67%'].forEach((value, i) => {
+            const styles = progressBar.find('.progress').at(i).props().style;
+            expect(styles).toHaveProperty('width', value);
+        });
+    });
+
+});
index 9622282c4fcb02414401006eb3e357b9b2569d22..7a55503e20f7b2968ea05b3678591a58e262f1bd 100644 (file)
@@ -23,10 +23,7 @@ describe('tree-picker-actions', () => {
 
     let store: RootStore;
     let services: ServiceRepository;
-    const config: any = {
-
-
-    };
+    const config: any = {};
     const actions: ApiActions = {
         progressFn: (id: string, working: boolean) => { },
         errorFn: (id: string, message: string) => { }
index 142694c883e667d2332e216dc57b07a248e8ea21..7b837aab6048c16dbbda5c1cc3f0906b36f5d4c4 100644 (file)
--- a/yarn.lock
+++ b/yarn.lock
@@ -3894,11 +3894,11 @@ __metadata:
     parse-duration: 0.4.4
     prop-types: 15.7.2
     query-string: 6.9.0
-    react: 16.8.6
+    react: 16.14.0
     react-copy-to-clipboard: 5.0.3
     react-dnd: 5.0.0
     react-dnd-html5-backend: 5.0.1
-    react-dom: 16.8.6
+    react-dom: 16.14.0
     react-dropzone: 5.1.1
     react-highlight-words: 0.14.0
     react-idle-timer: 4.3.6
@@ -15349,17 +15349,17 @@ __metadata:
   languageName: node
   linkType: hard
 
-"react-dom@npm:16.8.6":
-  version: 16.8.6
-  resolution: "react-dom@npm:16.8.6"
+"react-dom@npm:16.14.0":
+  version: 16.14.0
+  resolution: "react-dom@npm:16.14.0"
   dependencies:
     loose-envify: ^1.1.0
     object-assign: ^4.1.1
     prop-types: ^15.6.2
-    scheduler: ^0.13.6
+    scheduler: ^0.19.1
   peerDependencies:
-    react: ^16.0.0
-  checksum: 7f8ebd8523eb4a14a1439efa009d020abc0529da25d0de251a4f3d5b3781061f6b30d72425f5fe944317850997efc6c1d667e99b1fd70172f30a976a00008bf6
+    react: ^16.14.0
+  checksum: 5a5c49da0f106b2655a69f96c622c347febcd10532db391c262b26aec225b235357d9da1834103457683482ab1b229af7a50f6927a6b70e53150275e31785544
   languageName: node
   linkType: hard
 
@@ -15683,15 +15683,14 @@ __metadata:
   languageName: node
   linkType: hard
 
-"react@npm:16.8.6":
-  version: 16.8.6
-  resolution: "react@npm:16.8.6"
+"react@npm:16.14.0":
+  version: 16.14.0
+  resolution: "react@npm:16.14.0"
   dependencies:
     loose-envify: ^1.1.0
     object-assign: ^4.1.1
     prop-types: ^15.6.2
-    scheduler: ^0.13.6
-  checksum: 8dfdbec9af6999c2cfb33a9389995c6401daba732e1ee7e0a4920d28fd2e8e6b0fde99dfe4b8e2f81efc4a962c92656e3e79e221323449e55850232163f15ff4
+  checksum: 8484f3ecb13414526f2a7412190575fc134da785c02695eb92bb6028c930bfe1c238d7be2a125088fec663cc7cda0a3623373c46807cf2c281f49c34b79881ac
   languageName: node
   linkType: hard
 
@@ -16696,16 +16695,6 @@ __metadata:
   languageName: node
   linkType: hard
 
-"scheduler@npm:^0.13.6":
-  version: 0.13.6
-  resolution: "scheduler@npm:0.13.6"
-  dependencies:
-    loose-envify: ^1.1.0
-    object-assign: ^4.1.1
-  checksum: c82c705f6d0d6df87b26bf2cca33f427e91889438c0435ade3ee7f41860eda4dd7f3171ca2d93e8fe9431f3bd831ca0e267a401a0296e4b14de05e389f82d320
-  languageName: node
-  linkType: hard
-
 "scheduler@npm:^0.19.1":
   version: 0.19.1
   resolution: "scheduler@npm:0.19.1"