@fdm-monster/client-next 2.2.1 → 2.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.yarn/install-state.gz +0 -0
- package/README.md +19 -0
- package/RELEASE_NOTES.MD +22 -0
- package/dist/assets/index-BAB7cJ3l.js +105 -0
- package/dist/assets/index-BAB7cJ3l.js.map +1 -0
- package/dist/assets/index-DfA7W6iO.css +1 -0
- package/dist/index.html +2 -2
- package/package.json +21 -2
- package/screenshots/COVERAGE.md +383 -0
- package/screenshots/README.md +431 -0
- package/screenshots/fixtures/api-mock.ts +699 -0
- package/screenshots/fixtures/data/auth.fixtures.ts +79 -0
- package/screenshots/fixtures/data/cameras.fixtures.ts +48 -0
- package/screenshots/fixtures/data/files.fixtures.ts +56 -0
- package/screenshots/fixtures/data/floors.fixtures.ts +39 -0
- package/screenshots/fixtures/data/jobs.fixtures.ts +172 -0
- package/screenshots/fixtures/data/printers.fixtures.ts +132 -0
- package/screenshots/fixtures/data/settings.fixtures.ts +62 -0
- package/screenshots/fixtures/socketio-mock.ts +76 -0
- package/screenshots/fixtures/test-fixtures.ts +112 -0
- package/screenshots/helpers/dialog.helper.ts +196 -0
- package/screenshots/helpers/form.helper.ts +207 -0
- package/screenshots/helpers/navigation.helper.ts +191 -0
- package/screenshots/playwright.screenshots.config.ts +70 -0
- package/screenshots/suites/00-example.screenshots.spec.ts +29 -0
- package/screenshots/suites/01-auth.screenshots.spec.ts +130 -0
- package/screenshots/suites/02-dashboard.screenshots.spec.ts +106 -0
- package/screenshots/suites/03-printer-grid.screenshots.spec.ts +160 -0
- package/screenshots/suites/04-printer-list.screenshots.spec.ts +184 -0
- package/screenshots/suites/05-camera-grid.screenshots.spec.ts +127 -0
- package/screenshots/suites/06-print-jobs.screenshots.spec.ts +139 -0
- package/screenshots/suites/07-queue.screenshots.spec.ts +86 -0
- package/screenshots/suites/08-files.screenshots.spec.ts +142 -0
- package/screenshots/suites/09-settings.screenshots.spec.ts +130 -0
- package/screenshots/suites/10-panels-dialogs.screenshots.spec.ts +245 -0
- package/screenshots/utils.ts +216 -0
- package/vitest.config.ts +8 -0
- package/dist/assets/index-BaXVMJVZ.js +0 -105
- package/dist/assets/index-BaXVMJVZ.js.map +0 -1
- package/dist/assets/index-CU1IeFlc.css +0 -1
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mock data for authentication-related API endpoints
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
export interface WizardSettingsDto {
|
|
6
|
+
wizardCompleted: boolean;
|
|
7
|
+
wizardVersion: number;
|
|
8
|
+
latestWizardVersion: number;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export interface LoginRequiredResponse {
|
|
12
|
+
loginRequired: boolean;
|
|
13
|
+
registration: boolean;
|
|
14
|
+
wizardState: WizardSettingsDto;
|
|
15
|
+
isDemoMode: boolean;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface LoginResponse {
|
|
19
|
+
token: string;
|
|
20
|
+
refreshToken: string;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export const mockLoginRequired: LoginRequiredResponse = {
|
|
24
|
+
loginRequired: false,
|
|
25
|
+
registration: false,
|
|
26
|
+
wizardState: {
|
|
27
|
+
wizardCompleted: true,
|
|
28
|
+
wizardVersion: 1,
|
|
29
|
+
latestWizardVersion: 1,
|
|
30
|
+
},
|
|
31
|
+
isDemoMode: false,
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
export const mockLoginRequiredTrue: LoginRequiredResponse = {
|
|
35
|
+
loginRequired: true,
|
|
36
|
+
registration: false,
|
|
37
|
+
wizardState: {
|
|
38
|
+
wizardCompleted: true,
|
|
39
|
+
wizardVersion: 1,
|
|
40
|
+
latestWizardVersion: 1,
|
|
41
|
+
},
|
|
42
|
+
isDemoMode: false,
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
export const mockRegistrationEnabled: LoginRequiredResponse = {
|
|
46
|
+
loginRequired: false,
|
|
47
|
+
registration: true,
|
|
48
|
+
wizardState: {
|
|
49
|
+
wizardCompleted: true,
|
|
50
|
+
wizardVersion: 1,
|
|
51
|
+
latestWizardVersion: 1,
|
|
52
|
+
},
|
|
53
|
+
isDemoMode: false,
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
export const mockLoginRequiredWithWizard: LoginRequiredResponse = {
|
|
57
|
+
loginRequired: false,
|
|
58
|
+
registration: false,
|
|
59
|
+
wizardState: {
|
|
60
|
+
wizardCompleted: false,
|
|
61
|
+
wizardVersion: 0,
|
|
62
|
+
latestWizardVersion: 1,
|
|
63
|
+
},
|
|
64
|
+
isDemoMode: false,
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
export const mockLoginResponse: LoginResponse = {
|
|
68
|
+
token: 'mock-jwt-token-eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9',
|
|
69
|
+
refreshToken: 'mock-refresh-token-abcd1234efgh5678ijkl9012',
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
export const mockVerifyResponse = {
|
|
73
|
+
valid: true,
|
|
74
|
+
userId: 1,
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
export const mockRefreshResponse = {
|
|
78
|
+
token: 'mock-new-jwt-token-eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9',
|
|
79
|
+
};
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mock data for camera stream-related API endpoints
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
export interface CameraStream {
|
|
6
|
+
id: number;
|
|
7
|
+
printerId?: number;
|
|
8
|
+
streamURL: string;
|
|
9
|
+
name?: string;
|
|
10
|
+
aspectRatio?: string;
|
|
11
|
+
rotationClockwise?: number;
|
|
12
|
+
flipHorizontal?: boolean;
|
|
13
|
+
flipVertical?: boolean;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export const mockCameras: CameraStream[] = [
|
|
17
|
+
{
|
|
18
|
+
id: 1,
|
|
19
|
+
printerId: 1,
|
|
20
|
+
streamURL: 'http://192.168.1.100/webcam/?action=stream',
|
|
21
|
+
name: 'Prusa i3 MK3S Camera',
|
|
22
|
+
aspectRatio: '16:9',
|
|
23
|
+
rotationClockwise: 0,
|
|
24
|
+
flipHorizontal: false,
|
|
25
|
+
flipVertical: false,
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
id: 2,
|
|
29
|
+
printerId: 2,
|
|
30
|
+
streamURL: 'http://192.168.1.101/webcam/?action=stream',
|
|
31
|
+
name: 'Ender 3 V2 Camera',
|
|
32
|
+
aspectRatio: '16:9',
|
|
33
|
+
rotationClockwise: 0,
|
|
34
|
+
flipHorizontal: false,
|
|
35
|
+
flipVertical: false,
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
id: 3,
|
|
39
|
+
streamURL: 'http://192.168.1.200/stream',
|
|
40
|
+
name: 'Workshop Overview',
|
|
41
|
+
aspectRatio: '16:9',
|
|
42
|
+
rotationClockwise: 0,
|
|
43
|
+
flipHorizontal: false,
|
|
44
|
+
flipVertical: false,
|
|
45
|
+
},
|
|
46
|
+
];
|
|
47
|
+
|
|
48
|
+
export const mockCamerasEmpty: CameraStream[] = [];
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mock data for file-related API endpoints
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
export interface FileDto {
|
|
6
|
+
id: string;
|
|
7
|
+
name: string;
|
|
8
|
+
path: string;
|
|
9
|
+
size: number;
|
|
10
|
+
date: number;
|
|
11
|
+
type?: string;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export const mockFiles: FileDto[] = [
|
|
15
|
+
{
|
|
16
|
+
id: 'file-1',
|
|
17
|
+
name: 'benchy.gcode',
|
|
18
|
+
path: '/files/benchy.gcode',
|
|
19
|
+
size: 5242880, // 5 MB
|
|
20
|
+
date: Date.now() - 86400000,
|
|
21
|
+
type: 'model',
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
id: 'file-2',
|
|
25
|
+
name: 'cube_calibration.gcode',
|
|
26
|
+
path: '/files/cube_calibration.gcode',
|
|
27
|
+
size: 1048576, // 1 MB
|
|
28
|
+
date: Date.now() - 86400000 * 2,
|
|
29
|
+
type: 'model',
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
id: 'file-3',
|
|
33
|
+
name: 'phone_holder.gcode',
|
|
34
|
+
path: '/files/phone_holder.gcode',
|
|
35
|
+
size: 3145728, // 3 MB
|
|
36
|
+
date: Date.now() - 86400000 * 5,
|
|
37
|
+
type: 'model',
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
id: 'file-4',
|
|
41
|
+
name: 'vase_mode_spiral.gcode',
|
|
42
|
+
path: '/files/vase_mode_spiral.gcode',
|
|
43
|
+
size: 2097152, // 2 MB
|
|
44
|
+
date: Date.now() - 86400000 * 7,
|
|
45
|
+
type: 'model',
|
|
46
|
+
},
|
|
47
|
+
];
|
|
48
|
+
|
|
49
|
+
export const mockFilesEmpty: FileDto[] = [];
|
|
50
|
+
|
|
51
|
+
export const mockFileUploadProgress = {
|
|
52
|
+
filename: 'test-model.gcode',
|
|
53
|
+
progress: 45,
|
|
54
|
+
total: 100,
|
|
55
|
+
status: 'uploading',
|
|
56
|
+
};
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mock data for floor-related API endpoints
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
export interface FloorDto {
|
|
6
|
+
id: number;
|
|
7
|
+
name: string;
|
|
8
|
+
order: number;
|
|
9
|
+
printers: PositionDto[];
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface PositionDto {
|
|
13
|
+
x: number;
|
|
14
|
+
y: number;
|
|
15
|
+
printerId: number;
|
|
16
|
+
floorId: number;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export const mockFloors: FloorDto[] = [
|
|
20
|
+
{
|
|
21
|
+
id: 1,
|
|
22
|
+
name: 'Main Workshop',
|
|
23
|
+
order: 1,
|
|
24
|
+
printers: [
|
|
25
|
+
{ x: 0, y: 0, printerId: 1, floorId: 1 },
|
|
26
|
+
{ x: 1, y: 0, printerId: 2, floorId: 1 },
|
|
27
|
+
],
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
id: 2,
|
|
31
|
+
name: 'Test Lab',
|
|
32
|
+
order: 2,
|
|
33
|
+
printers: [
|
|
34
|
+
{ x: 0, y: 0, printerId: 3, floorId: 2 },
|
|
35
|
+
],
|
|
36
|
+
},
|
|
37
|
+
];
|
|
38
|
+
|
|
39
|
+
export const mockFloorsEmpty: FloorDto[] = [];
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mock data for print job-related API endpoints
|
|
3
|
+
* Based on PrintJobDto and GlobalQueueResponse from backend services
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
export interface PrintJobDto {
|
|
7
|
+
id: number;
|
|
8
|
+
printerId: number;
|
|
9
|
+
printerName: string;
|
|
10
|
+
fileName: string;
|
|
11
|
+
filePath: string;
|
|
12
|
+
createdAt: string;
|
|
13
|
+
startedAt?: string;
|
|
14
|
+
endedAt?: string;
|
|
15
|
+
status: 'QUEUED' | 'STARTING' | 'PRINTING' | 'PAUSED' | 'COMPLETED' | 'FAILED' | 'CANCELLED';
|
|
16
|
+
progress?: number;
|
|
17
|
+
statistics?: {
|
|
18
|
+
actualPrintTimeSeconds?: number;
|
|
19
|
+
estimatedPrintTimeSeconds?: number;
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// Mock jobs with various statuses for testing dashboard statistics
|
|
24
|
+
export const mockJobs: PrintJobDto[] = [
|
|
25
|
+
// Active printing job
|
|
26
|
+
{
|
|
27
|
+
id: 1,
|
|
28
|
+
printerId: 1,
|
|
29
|
+
printerName: 'Prusa i3 MK3S',
|
|
30
|
+
fileName: 'benchy.gcode',
|
|
31
|
+
filePath: '/files/benchy.gcode',
|
|
32
|
+
createdAt: new Date(Date.now() - 3600000).toISOString(), // 1 hour ago
|
|
33
|
+
startedAt: new Date(Date.now() - 3600000).toISOString(),
|
|
34
|
+
status: 'PRINTING',
|
|
35
|
+
progress: 45,
|
|
36
|
+
statistics: {
|
|
37
|
+
estimatedPrintTimeSeconds: 7200, // 2 hours
|
|
38
|
+
actualPrintTimeSeconds: 3600, // 1 hour so far
|
|
39
|
+
},
|
|
40
|
+
},
|
|
41
|
+
// Completed job from 1 day ago
|
|
42
|
+
{
|
|
43
|
+
id: 2,
|
|
44
|
+
printerId: 2,
|
|
45
|
+
printerName: 'Ender 3 V2',
|
|
46
|
+
fileName: 'cube_calibration.gcode',
|
|
47
|
+
filePath: '/files/cube_calibration.gcode',
|
|
48
|
+
createdAt: new Date(Date.now() - 86400000).toISOString(), // 1 day ago
|
|
49
|
+
startedAt: new Date(Date.now() - 86400000).toISOString(),
|
|
50
|
+
endedAt: new Date(Date.now() - 86400000 + 1800000).toISOString(), // 30 minutes later
|
|
51
|
+
status: 'COMPLETED',
|
|
52
|
+
progress: 100,
|
|
53
|
+
statistics: {
|
|
54
|
+
actualPrintTimeSeconds: 1800, // 30 minutes
|
|
55
|
+
},
|
|
56
|
+
},
|
|
57
|
+
// Completed job from 2 days ago
|
|
58
|
+
{
|
|
59
|
+
id: 3,
|
|
60
|
+
printerId: 3,
|
|
61
|
+
printerName: 'Artillery Sidewinder X1',
|
|
62
|
+
fileName: 'phone_holder.gcode',
|
|
63
|
+
filePath: '/files/phone_holder.gcode',
|
|
64
|
+
createdAt: new Date(Date.now() - 86400000 * 2).toISOString(), // 2 days ago
|
|
65
|
+
startedAt: new Date(Date.now() - 86400000 * 2).toISOString(),
|
|
66
|
+
endedAt: new Date(Date.now() - 86400000 * 2 + 5400000).toISOString(), // 1.5 hours later
|
|
67
|
+
status: 'COMPLETED',
|
|
68
|
+
progress: 100,
|
|
69
|
+
statistics: {
|
|
70
|
+
actualPrintTimeSeconds: 5400, // 1.5 hours
|
|
71
|
+
},
|
|
72
|
+
},
|
|
73
|
+
// Failed job from 3 days ago
|
|
74
|
+
{
|
|
75
|
+
id: 4,
|
|
76
|
+
printerId: 1,
|
|
77
|
+
printerName: 'Prusa i3 MK3S',
|
|
78
|
+
fileName: 'vase_mode_spiral.gcode',
|
|
79
|
+
filePath: '/files/vase_mode_spiral.gcode',
|
|
80
|
+
createdAt: new Date(Date.now() - 86400000 * 3).toISOString(), // 3 days ago
|
|
81
|
+
startedAt: new Date(Date.now() - 86400000 * 3).toISOString(),
|
|
82
|
+
endedAt: new Date(Date.now() - 86400000 * 3 + 3000000).toISOString(), // 50 minutes later
|
|
83
|
+
status: 'FAILED',
|
|
84
|
+
progress: 75,
|
|
85
|
+
statistics: {
|
|
86
|
+
actualPrintTimeSeconds: 3000, // 50 minutes
|
|
87
|
+
},
|
|
88
|
+
},
|
|
89
|
+
// Completed job from 12 hours ago
|
|
90
|
+
{
|
|
91
|
+
id: 5,
|
|
92
|
+
printerId: 4,
|
|
93
|
+
printerName: 'CR-10 S5',
|
|
94
|
+
fileName: 'large_model.gcode',
|
|
95
|
+
filePath: '/files/large_model.gcode',
|
|
96
|
+
createdAt: new Date(Date.now() - 43200000).toISOString(), // 12 hours ago
|
|
97
|
+
startedAt: new Date(Date.now() - 43200000).toISOString(),
|
|
98
|
+
endedAt: new Date(Date.now() - 43200000 + 14400000).toISOString(), // 4 hours later
|
|
99
|
+
status: 'COMPLETED',
|
|
100
|
+
progress: 100,
|
|
101
|
+
statistics: {
|
|
102
|
+
actualPrintTimeSeconds: 14400, // 4 hours
|
|
103
|
+
},
|
|
104
|
+
},
|
|
105
|
+
];
|
|
106
|
+
|
|
107
|
+
export const mockJobsEmpty: PrintJobDto[] = [];
|
|
108
|
+
|
|
109
|
+
export const mockJobDetails: PrintJobDto = {
|
|
110
|
+
id: 1,
|
|
111
|
+
printerId: 1,
|
|
112
|
+
printerName: 'Prusa i3 MK3S',
|
|
113
|
+
fileName: 'benchy.gcode',
|
|
114
|
+
filePath: '/files/benchy.gcode',
|
|
115
|
+
createdAt: new Date(Date.now() - 3600000).toISOString(),
|
|
116
|
+
startedAt: new Date(Date.now() - 3600000).toISOString(),
|
|
117
|
+
status: 'PRINTING',
|
|
118
|
+
progress: 45,
|
|
119
|
+
statistics: {
|
|
120
|
+
estimatedPrintTimeSeconds: 7200,
|
|
121
|
+
actualPrintTimeSeconds: 3600,
|
|
122
|
+
},
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
// Mock print queue items (GlobalQueueResponse items structure)
|
|
126
|
+
export interface QueueItemDto {
|
|
127
|
+
jobId: number;
|
|
128
|
+
fileName: string;
|
|
129
|
+
printerId: number;
|
|
130
|
+
printerName?: string;
|
|
131
|
+
queuePosition: number;
|
|
132
|
+
status: string;
|
|
133
|
+
createdAt: string;
|
|
134
|
+
estimatedTimeSeconds?: number;
|
|
135
|
+
filamentGrams?: number;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
export const mockQueue: QueueItemDto[] = [
|
|
139
|
+
{
|
|
140
|
+
jobId: 10,
|
|
141
|
+
fileName: 'model_1.gcode',
|
|
142
|
+
printerId: 2,
|
|
143
|
+
printerName: 'Ender 3 V2',
|
|
144
|
+
queuePosition: 1,
|
|
145
|
+
status: 'queued',
|
|
146
|
+
createdAt: new Date().toISOString(),
|
|
147
|
+
estimatedTimeSeconds: 3600,
|
|
148
|
+
filamentGrams: 15.5,
|
|
149
|
+
},
|
|
150
|
+
{
|
|
151
|
+
jobId: 11,
|
|
152
|
+
fileName: 'model_2.gcode',
|
|
153
|
+
printerId: 2,
|
|
154
|
+
printerName: 'Ender 3 V2',
|
|
155
|
+
queuePosition: 2,
|
|
156
|
+
status: 'queued',
|
|
157
|
+
createdAt: new Date().toISOString(),
|
|
158
|
+
estimatedTimeSeconds: 5400,
|
|
159
|
+
filamentGrams: 22.3,
|
|
160
|
+
},
|
|
161
|
+
{
|
|
162
|
+
jobId: 12,
|
|
163
|
+
fileName: 'model_3.gcode',
|
|
164
|
+
printerId: 3,
|
|
165
|
+
printerName: 'Artillery Sidewinder X1',
|
|
166
|
+
queuePosition: 1,
|
|
167
|
+
status: 'queued',
|
|
168
|
+
createdAt: new Date().toISOString(),
|
|
169
|
+
estimatedTimeSeconds: 7200,
|
|
170
|
+
filamentGrams: 30.0,
|
|
171
|
+
},
|
|
172
|
+
];
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mock data for printer-related API endpoints
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
export interface PrinterDto {
|
|
6
|
+
id: number;
|
|
7
|
+
printerType: number;
|
|
8
|
+
correlationToken?: string;
|
|
9
|
+
enabled: boolean;
|
|
10
|
+
dateAdded: number;
|
|
11
|
+
disabledReason: string;
|
|
12
|
+
name: string;
|
|
13
|
+
webSocketURL: string;
|
|
14
|
+
apiKey: string;
|
|
15
|
+
username: string;
|
|
16
|
+
password: string;
|
|
17
|
+
printerURL: string;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export const mockPrinters: PrinterDto[] = [
|
|
21
|
+
{
|
|
22
|
+
id: 1,
|
|
23
|
+
name: 'Prusa i3 MK3S',
|
|
24
|
+
printerType: 0,
|
|
25
|
+
enabled: true,
|
|
26
|
+
dateAdded: Date.now() - 86400000 * 30,
|
|
27
|
+
disabledReason: '',
|
|
28
|
+
printerURL: 'http://192.168.1.100',
|
|
29
|
+
webSocketURL: 'ws://192.168.1.100',
|
|
30
|
+
apiKey: 'mock-api-key-1',
|
|
31
|
+
username: '',
|
|
32
|
+
password: '',
|
|
33
|
+
correlationToken: 'token-1',
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
id: 2,
|
|
37
|
+
name: 'Ender 3 V2',
|
|
38
|
+
printerType: 0,
|
|
39
|
+
enabled: true,
|
|
40
|
+
dateAdded: Date.now() - 86400000 * 15,
|
|
41
|
+
disabledReason: '',
|
|
42
|
+
printerURL: 'http://192.168.1.101',
|
|
43
|
+
webSocketURL: 'ws://192.168.1.101',
|
|
44
|
+
apiKey: 'mock-api-key-2',
|
|
45
|
+
username: '',
|
|
46
|
+
password: '',
|
|
47
|
+
correlationToken: 'token-2',
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
id: 3,
|
|
51
|
+
name: 'Artillery Sidewinder X1',
|
|
52
|
+
printerType: 0,
|
|
53
|
+
enabled: true,
|
|
54
|
+
dateAdded: Date.now() - 86400000 * 7,
|
|
55
|
+
disabledReason: '',
|
|
56
|
+
printerURL: 'http://192.168.1.102',
|
|
57
|
+
webSocketURL: 'ws://192.168.1.102',
|
|
58
|
+
apiKey: 'mock-api-key-3',
|
|
59
|
+
username: '',
|
|
60
|
+
password: '',
|
|
61
|
+
correlationToken: 'token-3',
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
id: 4,
|
|
65
|
+
name: 'Creality CR-10',
|
|
66
|
+
printerType: 0,
|
|
67
|
+
enabled: false,
|
|
68
|
+
dateAdded: Date.now() - 86400000 * 60,
|
|
69
|
+
disabledReason: 'Maintenance required',
|
|
70
|
+
printerURL: 'http://192.168.1.103',
|
|
71
|
+
webSocketURL: 'ws://192.168.1.103',
|
|
72
|
+
apiKey: 'mock-api-key-4',
|
|
73
|
+
username: '',
|
|
74
|
+
password: '',
|
|
75
|
+
correlationToken: 'token-4',
|
|
76
|
+
},
|
|
77
|
+
];
|
|
78
|
+
|
|
79
|
+
export const mockPrinterEmpty: PrinterDto[] = [];
|
|
80
|
+
|
|
81
|
+
export const mockPrinterStates = {
|
|
82
|
+
operational: {
|
|
83
|
+
state: {
|
|
84
|
+
text: 'Operational',
|
|
85
|
+
flags: {
|
|
86
|
+
operational: true,
|
|
87
|
+
printing: false,
|
|
88
|
+
paused: false,
|
|
89
|
+
error: false,
|
|
90
|
+
},
|
|
91
|
+
},
|
|
92
|
+
},
|
|
93
|
+
printing: {
|
|
94
|
+
state: {
|
|
95
|
+
text: 'Printing',
|
|
96
|
+
flags: {
|
|
97
|
+
operational: true,
|
|
98
|
+
printing: true,
|
|
99
|
+
paused: false,
|
|
100
|
+
error: false,
|
|
101
|
+
},
|
|
102
|
+
},
|
|
103
|
+
progress: {
|
|
104
|
+
completion: 45.5,
|
|
105
|
+
filepos: 1234567,
|
|
106
|
+
printTime: 3600,
|
|
107
|
+
printTimeLeft: 4200,
|
|
108
|
+
},
|
|
109
|
+
},
|
|
110
|
+
paused: {
|
|
111
|
+
state: {
|
|
112
|
+
text: 'Paused',
|
|
113
|
+
flags: {
|
|
114
|
+
operational: true,
|
|
115
|
+
printing: true,
|
|
116
|
+
paused: true,
|
|
117
|
+
error: false,
|
|
118
|
+
},
|
|
119
|
+
},
|
|
120
|
+
},
|
|
121
|
+
error: {
|
|
122
|
+
state: {
|
|
123
|
+
text: 'Error: Connection lost',
|
|
124
|
+
flags: {
|
|
125
|
+
operational: false,
|
|
126
|
+
printing: false,
|
|
127
|
+
paused: false,
|
|
128
|
+
error: true,
|
|
129
|
+
},
|
|
130
|
+
},
|
|
131
|
+
},
|
|
132
|
+
};
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mock data for settings-related API endpoints
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
export interface ServerSettings {
|
|
6
|
+
sentryDiagnosticsEnabled: boolean;
|
|
7
|
+
whitelistEnabled: boolean;
|
|
8
|
+
loginRequired: boolean;
|
|
9
|
+
registration: boolean;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface User {
|
|
13
|
+
id: number;
|
|
14
|
+
username: string;
|
|
15
|
+
isRootUser: boolean;
|
|
16
|
+
isVerified: boolean;
|
|
17
|
+
needsPasswordChange: boolean;
|
|
18
|
+
roles: string[];
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export const mockServerSettings: ServerSettings = {
|
|
22
|
+
sentryDiagnosticsEnabled: false,
|
|
23
|
+
whitelistEnabled: false,
|
|
24
|
+
loginRequired: false,
|
|
25
|
+
registration: false,
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
export const mockUsers: User[] = [
|
|
29
|
+
{
|
|
30
|
+
id: 1,
|
|
31
|
+
username: 'admin',
|
|
32
|
+
isRootUser: true,
|
|
33
|
+
isVerified: true,
|
|
34
|
+
needsPasswordChange: false,
|
|
35
|
+
roles: ['admin', 'operator'],
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
id: 2,
|
|
39
|
+
username: 'operator1',
|
|
40
|
+
isRootUser: false,
|
|
41
|
+
isVerified: true,
|
|
42
|
+
needsPasswordChange: false,
|
|
43
|
+
roles: ['operator'],
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
id: 3,
|
|
47
|
+
username: 'viewer1',
|
|
48
|
+
isRootUser: false,
|
|
49
|
+
isVerified: true,
|
|
50
|
+
needsPasswordChange: false,
|
|
51
|
+
roles: ['viewer'],
|
|
52
|
+
},
|
|
53
|
+
];
|
|
54
|
+
|
|
55
|
+
export const mockCurrentUser: User = {
|
|
56
|
+
id: 1,
|
|
57
|
+
username: 'admin',
|
|
58
|
+
isRootUser: true,
|
|
59
|
+
isVerified: true,
|
|
60
|
+
needsPasswordChange: false,
|
|
61
|
+
roles: ['admin', 'operator'],
|
|
62
|
+
};
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { Page } from '@playwright/test';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Mock SocketIO to prevent "server disconnected" messages
|
|
5
|
+
* Sets flags that the app checks to skip Socket.IO setup entirely
|
|
6
|
+
* Also injects Socket.IO update data into stores
|
|
7
|
+
*/
|
|
8
|
+
export async function mockSocketIO(page: Page, data?: any): Promise<void> {
|
|
9
|
+
// Set test mode flags AND inject Socket.IO data BEFORE page loads
|
|
10
|
+
await page.addInitScript((mockData) => {
|
|
11
|
+
(window as any).__DISABLE_SOCKETIO__ = true;
|
|
12
|
+
(window as any).__SCREENSHOT_MODE__ = true;
|
|
13
|
+
|
|
14
|
+
// Store mock data to be consumed by stores
|
|
15
|
+
if (mockData) {
|
|
16
|
+
(window as any).__SOCKETIO_MOCK_DATA__ = mockData;
|
|
17
|
+
}
|
|
18
|
+
}, data);
|
|
19
|
+
|
|
20
|
+
// Block any Socket.IO network requests as a fallback (should not happen now)
|
|
21
|
+
await page.route('**/socket.io/**', (route) => {
|
|
22
|
+
console.warn('[Mock] Unexpected Socket.IO request blocked:', route.request().url());
|
|
23
|
+
route.abort('blockedbyclient');
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
// Hide "Server Disconnected" messages if they somehow appear
|
|
27
|
+
await page.addInitScript(() => {
|
|
28
|
+
const hideDisconnectedMessages = () => {
|
|
29
|
+
const cards = document.querySelectorAll('.v-card');
|
|
30
|
+
cards.forEach((card) => {
|
|
31
|
+
const text = card.textContent || '';
|
|
32
|
+
if (text.includes('Server Disconnected') || text.includes('Cannot connect to FDM Monster')) {
|
|
33
|
+
(card as HTMLElement).style.display = 'none';
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
if (document.readyState === 'loading') {
|
|
39
|
+
document.addEventListener('DOMContentLoaded', hideDisconnectedMessages);
|
|
40
|
+
} else {
|
|
41
|
+
hideDisconnectedMessages();
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const observer = new MutationObserver(hideDisconnectedMessages);
|
|
45
|
+
const startObserving = () => {
|
|
46
|
+
if (document.body) {
|
|
47
|
+
observer.observe(document.body, { childList: true, subtree: true });
|
|
48
|
+
} else {
|
|
49
|
+
setTimeout(startObserving, 10);
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
startObserving();
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Mock SocketIO with simulated data updates
|
|
58
|
+
*/
|
|
59
|
+
export async function mockSocketIOWithData(
|
|
60
|
+
page: Page,
|
|
61
|
+
data?: {
|
|
62
|
+
printers?: any[];
|
|
63
|
+
floors?: any[];
|
|
64
|
+
socketStates?: any;
|
|
65
|
+
printerEvents?: any;
|
|
66
|
+
trackedUploads?: any;
|
|
67
|
+
}
|
|
68
|
+
): Promise<void> {
|
|
69
|
+
await mockSocketIO(page);
|
|
70
|
+
|
|
71
|
+
if (data) {
|
|
72
|
+
await page.addInitScript((mockData) => {
|
|
73
|
+
(window as any).__MOCK_SOCKETIO_DATA__ = mockData;
|
|
74
|
+
}, data);
|
|
75
|
+
}
|
|
76
|
+
}
|