Skip to content

Commit 8737db2

Browse files
yehudit1987Yehudit Kerido
and
Yehudit Kerido
authored
test(ws): Add workspaces tests (#188)
feat(ws): Notebooks 2.0 // Frontend // Fetch workspaces feat(ws): Notebooks 2.0 // Frontend // Fetch workspaces feat(ws): Notebooks 2.0 // Frontend // Fetch workspaces feat(ws): Notebooks 2.0 // Frontend // Fetch workspaces feat(ws): Notebooks 2.0 // Frontend // Fetch workspaces feat(ws): Notebooks 2.0 // Frontend // Fetch workspaces feat(ws): Notebooks 2.0 // Frontend // Fetch workspaces feat(ws): Notebooks 2.0 // Frontend // Fetch workspaces feat(ws): Notebooks 2.0 // Frontend // Fetch workspaces feat(ws): Notebooks 2.0 // Frontend // Fetch workspaces fix cypress tests Signed-off-by: Yehudit Kerido <[email protected]> Co-authored-by: Yehudit Kerido <[email protected]>
1 parent 2c3e75e commit 8737db2

File tree

6 files changed

+376
-88
lines changed

6 files changed

+376
-88
lines changed

workspaces/frontend/src/__tests__/cypress/cypress/tests/e2e/WorkspaceDetails/WorkspaceDetailsActivity.cy.ts

Lines changed: 0 additions & 18 deletions
This file was deleted.

workspaces/frontend/src/__tests__/cypress/cypress/tests/e2e/Workspaces.cy.ts

Lines changed: 0 additions & 65 deletions
This file was deleted.
Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
import { WorkspaceState } from '~/shared/api/backendApiTypes';
2+
import type { Workspace, WorkspaceKindInfo } from '~/shared/api/backendApiTypes';
3+
4+
const generateMockWorkspace = (
5+
name: string,
6+
namespace: string,
7+
state: WorkspaceState,
8+
paused: boolean,
9+
imageConfigId: string,
10+
imageConfigDisplayName: string,
11+
podConfigId: string,
12+
podConfigDisplayName: string,
13+
pvcName: string,
14+
): Workspace => {
15+
const currentTime = Date.now();
16+
const lastActivityTime = currentTime - Math.floor(Math.random() * 1000000);
17+
const lastUpdateTime = currentTime - Math.floor(Math.random() * 100000);
18+
19+
return {
20+
name,
21+
namespace,
22+
workspaceKind: { name: 'jupyterlab' } as WorkspaceKindInfo,
23+
deferUpdates: paused,
24+
paused,
25+
pausedTime: paused ? currentTime - Math.floor(Math.random() * 1000000) : 0,
26+
pendingRestart: Math.random() < 0.5, //to generate randomly True/False value
27+
state,
28+
stateMessage:
29+
state === WorkspaceState.WorkspaceStateRunning
30+
? 'Workspace is running smoothly.'
31+
: state === WorkspaceState.WorkspaceStatePaused
32+
? 'Workspace is paused.'
33+
: 'Workspace is operational.',
34+
podTemplate: {
35+
podMetadata: {
36+
labels: {},
37+
annotations: {},
38+
},
39+
volumes: {
40+
home: {
41+
pvcName: `${pvcName}-home`,
42+
mountPath: '/home/jovyan',
43+
readOnly: false,
44+
},
45+
data: [
46+
{
47+
pvcName,
48+
mountPath: '/data/my-data',
49+
readOnly: paused,
50+
},
51+
],
52+
},
53+
options: {
54+
imageConfig: {
55+
current: {
56+
id: imageConfigId,
57+
displayName: imageConfigDisplayName,
58+
description: 'JupyterLab environment',
59+
labels: [{ key: 'python_version', value: '3.11' }],
60+
},
61+
},
62+
podConfig: {
63+
current: {
64+
id: podConfigId,
65+
displayName: podConfigDisplayName,
66+
description: 'Pod configuration with resource limits',
67+
labels: [
68+
{ key: 'cpu', value: '100m' },
69+
{ key: 'memory', value: '128Mi' },
70+
],
71+
},
72+
},
73+
},
74+
},
75+
activity: {
76+
lastActivity: lastActivityTime,
77+
lastUpdate: lastUpdateTime,
78+
},
79+
services: [
80+
{
81+
httpService: {
82+
displayName: 'Jupyter-lab',
83+
httpPath: `/workspace/${namespace}/${name}/Jupyter-lab/`,
84+
},
85+
},
86+
],
87+
};
88+
};
89+
90+
const generateMockWorkspaces = (numWorkspaces: number, byNamespace = false) => {
91+
const mockWorkspaces = [];
92+
const podConfigs = [
93+
{ id: 'small-cpu', displayName: 'Small CPU' },
94+
{ id: 'medium-cpu', displayName: 'Medium CPU' },
95+
{ id: 'large-cpu', displayName: 'Large CPU' },
96+
];
97+
const imageConfigs = [
98+
{ id: 'jupyterlab_scipy_180', displayName: 'JupyterLab SciPy 1.8.0' },
99+
{ id: 'jupyterlab_tensorflow_230', displayName: 'JupyterLab TensorFlow 2.3.0' },
100+
{ id: 'jupyterlab_pytorch_120', displayName: 'JupyterLab PyTorch 1.2.0' },
101+
];
102+
const namespaces = byNamespace ? ['kubeflow'] : ['kubeflow', 'system', 'user-example', 'default'];
103+
104+
for (let i = 1; i <= numWorkspaces; i++) {
105+
const state =
106+
i % 3 === 0
107+
? WorkspaceState.WorkspaceStateError
108+
: i % 2 === 0
109+
? WorkspaceState.WorkspaceStatePaused
110+
: WorkspaceState.WorkspaceStateRunning;
111+
const paused = state === WorkspaceState.WorkspaceStatePaused;
112+
const name = `workspace-${i}`;
113+
const namespace = namespaces[i % namespaces.length];
114+
const pvcName = `data-pvc-${i}`;
115+
116+
const imageConfig = imageConfigs[i % imageConfigs.length];
117+
const podConfig = podConfigs[i % podConfigs.length];
118+
119+
mockWorkspaces.push(
120+
generateMockWorkspace(
121+
name,
122+
namespace,
123+
state,
124+
paused,
125+
imageConfig.id,
126+
imageConfig.displayName,
127+
podConfig.id,
128+
podConfig.displayName,
129+
pvcName,
130+
),
131+
);
132+
}
133+
134+
return mockWorkspaces;
135+
};
136+
137+
// Example usage
138+
export const mockWorkspaces = generateMockWorkspaces(5);
139+
export const mockWorkspacesByNS = generateMockWorkspaces(10, true);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import { mockBFFResponse } from '~/__mocks__/utils';
2+
import { mockWorkspaces } from '~/__tests__/cypress/cypress/tests/mocked/workspace.mock';
3+
import { formatTimestamp } from '~/shared/utilities/WorkspaceUtils';
4+
5+
describe('WorkspaceDetailsActivity Component', () => {
6+
beforeEach(() => {
7+
cy.intercept('GET', 'api/v1/workspaces', {
8+
body: mockBFFResponse(mockWorkspaces),
9+
}).as('getWorkspaces');
10+
cy.visit('/');
11+
});
12+
13+
// This tests depends on the mocked workspaces data at home page, needs revisit once workspace data fetched from BE
14+
it('open workspace details, open activity tab, check all fields match', () => {
15+
cy.findAllByTestId('table-body').first().findByTestId('action-column').click();
16+
// Extract first workspace from mock data
17+
cy.wait('@getWorkspaces').then((interception) => {
18+
if (!interception.response || !interception.response.body) {
19+
throw new Error('Intercepted response is undefined or empty');
20+
}
21+
const workspace = interception.response.body.data[0];
22+
cy.findByTestId('action-view-details').click();
23+
cy.findByTestId('activityTab').click();
24+
cy.findByTestId('lastActivity')
25+
.invoke('text')
26+
.then((text) => {
27+
console.log('Rendered lastActivity:', text);
28+
});
29+
cy.findByTestId('lastActivity').should(
30+
'have.text',
31+
formatTimestamp(workspace.activity.lastActivity),
32+
);
33+
cy.findByTestId('lastUpdate').should(
34+
'have.text',
35+
formatTimestamp(workspace.activity.lastUpdate),
36+
);
37+
cy.findByTestId('pauseTime').should('have.text', formatTimestamp(workspace.pausedTime));
38+
cy.findByTestId('pendingRestart').should(
39+
'have.text',
40+
workspace.pendingRestart ? 'Yes' : 'No',
41+
);
42+
});
43+
});
44+
});

0 commit comments

Comments
 (0)