Skip to content

Commit a925344

Browse files
committed
AIRAVATA-3680 Basic unit test for loading experiment details by job id
1 parent 405fdbe commit a925344

File tree

6 files changed

+2763
-73
lines changed

6 files changed

+2763
-73
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
module.exports = {
2+
preset: "@vue/cli-plugin-unit-jest",
3+
moduleNameMapper: {
4+
"^@/(.*)$": "<rootDir>/static/django_airavata_admin/src/$1",
5+
// Ignore style imports. From https://jestjs.io/docs/en/webpack#handling-static-assets
6+
"\\.(css|less)$":
7+
"<rootDir>/static/django_airavata_admin/tests/__mocks__/styleMock.js",
8+
},
9+
};

django_airavata/apps/admin/package.json

+24-4
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,17 @@
11
{
22
"name": "admin-airavata",
33
"version": "1.0.0",
4+
"private": true,
45
"description": "A Vue.js project",
56
"author": "Eldho Mathulla <[email protected]>",
6-
"private": true,
77
"scripts": {
88
"serve": "vue-cli-service serve ./static/django_airavata_admin/src/main.js",
99
"build": "vue-cli-service build ./static/django_airavata_admin/src/main.js",
10+
"test": "npm run test:unit",
11+
"test:unit": "vue-cli-service test:unit",
1012
"lint": "vue-cli-service lint ./static/django_airavata_admin/src/",
11-
"lint:visualstudio": "vue-cli-service lint --format visualstudio ./static/django_airavata_admin/src/",
12-
"format": "prettier --write ."
13+
"format": "prettier --write .",
14+
"lint:visualstudio": "vue-cli-service lint --format visualstudio ./static/django_airavata_admin/src/"
1315
},
1416
"dependencies": {
1517
"bootstrap": "^4.3.1",
@@ -34,13 +36,20 @@
3436
"devDependencies": {
3537
"@babel/core": "^7.12.16",
3638
"@babel/eslint-parser": "^7.12.16",
39+
"@testing-library/jest-dom": "^5.16.5",
40+
"@testing-library/vue": "5",
3741
"@vue/cli-plugin-babel": "~5.0.8",
3842
"@vue/cli-plugin-eslint": "~5.0.8",
43+
"@vue/cli-plugin-unit-jest": "~5.0.0",
3944
"@vue/cli-service": "~5.0.8",
4045
"@vue/component-compiler-utils": "^2.3.0",
46+
"@vue/test-utils": "^1.1.3",
47+
"@vue/vue2-jest": "^27.0.0-alpha.2",
4148
"autoprefixer": "^9.3.1",
49+
"babel-jest": "^27.0.6",
4250
"eslint": "^7.32.0",
4351
"eslint-plugin-vue": "^8.0.3",
52+
"jest": "^27.0.5",
4453
"prettier": "^2.1.2",
4554
"vue-loader": "^15.5.1",
4655
"vue-template-compiler": "^2.5.22",
@@ -61,7 +70,18 @@
6170
"parserOptions": {
6271
"parser": "@babel/eslint-parser",
6372
"requireConfigFile": false
64-
}
73+
},
74+
"overrides": [
75+
{
76+
"files": [
77+
"**/__tests__/*.{j,t}s?(x)",
78+
"**/tests/unit/**/*.spec.{j,t}s?(x)"
79+
],
80+
"env": {
81+
"jest": true
82+
}
83+
}
84+
]
6585
},
6686
"postcss": {
6787
"plugins": {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
module.exports = {};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
import { render, fireEvent, within } from "@testing-library/vue";
2+
import "@testing-library/jest-dom";
3+
import ExperimentStatisticsContainer from "@/components/statistics/ExperimentStatisticsContainer.vue";
4+
import Vue from "vue";
5+
import BootstrapVue from "bootstrap-vue";
6+
import VueFlatPickr from "vue-flatpickr-component";
7+
8+
Vue.use(BootstrapVue);
9+
Vue.use(VueFlatPickr);
10+
11+
import { models, services, utils } from "django-airavata-api";
12+
import ExperimentStatus from "django-airavata-api/static/django_airavata_api/js/models/ExperimentStatus";
13+
jest.mock("django-airavata-api", () => {
14+
const originalModule = jest.requireActual("django-airavata-api");
15+
return {
16+
__esModule: true,
17+
...originalModule,
18+
// Mock just the RESTful service calls
19+
services: {
20+
ApplicationInterfaceService: {
21+
list: jest.fn(),
22+
},
23+
ExperimentStatisticsService: {
24+
get: jest.fn(),
25+
},
26+
ComputeResourceService: {
27+
namesList: jest.fn(),
28+
},
29+
ExperimentSearchService: {
30+
list: jest.fn(),
31+
},
32+
ExperimentService: {
33+
retrieve: jest.fn(),
34+
},
35+
FullExperimentService: {
36+
retrieve: jest.fn(),
37+
},
38+
},
39+
};
40+
});
41+
42+
// beforeEach(() => {
43+
// jest.resetAllMocks();
44+
// });
45+
46+
test("load experiment by job id when job id matches unique experiment", async () => {
47+
const spinner = document.createElement("div");
48+
spinner.id = "airavata-spinner";
49+
document.body.appendChild(spinner);
50+
51+
// Service call mocks
52+
services.ApplicationInterfaceService.list.mockResolvedValue([]);
53+
services.ExperimentStatisticsService.get.mockResolvedValue(
54+
new utils.PaginationIterator(
55+
{
56+
count: 0,
57+
next: null,
58+
previous: null,
59+
results: {
60+
allExperimentCount: 0,
61+
completedExperimentCount: 0,
62+
cancelledExperimentCount: 0,
63+
failedExperimentCount: 0,
64+
createdExperimentCount: 0,
65+
runningExperimentCount: 0,
66+
allExperiments: [],
67+
completedExperiments: [],
68+
failedExperiments: [],
69+
cancelledExperiments: [],
70+
createdExperiments: [],
71+
runningExperiments: [],
72+
},
73+
limit: 50,
74+
offset: 0,
75+
},
76+
models.ExperimentStatistics
77+
)
78+
);
79+
services.ComputeResourceService.namesList.mockResolvedValue([]);
80+
services.ExperimentSearchService.list.mockResolvedValue(
81+
new utils.PaginationIterator(
82+
{
83+
count: 1,
84+
next: null,
85+
previous: null,
86+
results: [{ experimentId: "test-experiment-id" }],
87+
},
88+
models.ExperimentSummary
89+
)
90+
);
91+
// Mock just enough of Experiment and FullExperiment to get ExperimentDetailsView to render
92+
const experiment = new models.Experiment({
93+
experimentId: "test-experiment-id",
94+
experimentName: "Test Experiment",
95+
creationTime: Date.now(),
96+
experimentStatus: [
97+
new ExperimentStatus({
98+
timeOfStateChange: Date.now(),
99+
state: models.ExperimentState.COMPLETED,
100+
}),
101+
],
102+
});
103+
services.ExperimentService.retrieve.mockResolvedValue(experiment);
104+
services.FullExperimentService.retrieve.mockResolvedValue(
105+
new models.FullExperiment({
106+
experimentId: "test-experiment-id",
107+
experiment,
108+
})
109+
);
110+
111+
// jsdom doesn't implement scrollIntoView so just provide a stubbed implementation
112+
Element.prototype.scrollIntoView = jest.fn();
113+
114+
// The render method returns a collection of utilities to query your component.
115+
const { findByText, findByPlaceholderText } = render(
116+
ExperimentStatisticsContainer
117+
);
118+
119+
const byJobIDTab = await findByText("By Job ID");
120+
121+
await fireEvent.click(byJobIDTab);
122+
123+
const jobIDInputField = await findByPlaceholderText("Job ID");
124+
125+
await fireEvent.update(jobIDInputField, "12345");
126+
127+
const loadButton = await within(jobIDInputField.parentElement).findByText(
128+
"Load"
129+
);
130+
131+
await fireEvent.click(loadButton);
132+
133+
// The job's tab has the job id instead of the normal experiment name
134+
const jobTab = await findByText("Job 12345");
135+
136+
expect(jobTab).toBeVisible();
137+
138+
// Double check that the experiment services were called to load the experiment
139+
expect(services.ExperimentService.retrieve).toHaveBeenCalledWith({
140+
lookup: experiment.experimentId,
141+
});
142+
expect(services.FullExperimentService.retrieve).toHaveBeenCalledWith({
143+
lookup: experiment.experimentId,
144+
});
145+
});

0 commit comments

Comments
 (0)