tsvesync 1.0.90 → 1.0.92

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.
@@ -0,0 +1,4 @@
1
+ /**
2
+ * Unit tests for VeSyncAir131 air quality data parsing and filter life handling
3
+ */
4
+ export {};
@@ -0,0 +1,365 @@
1
+ "use strict";
2
+ /**
3
+ * Unit tests for VeSyncAir131 air quality data parsing and filter life handling
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const air131_1 = require("../../lib/fans/air131");
7
+ // Mock VeSync manager
8
+ const mockManager = {
9
+ username: 'test@example.com',
10
+ password: 'testpass',
11
+ token: 'testtoken',
12
+ accountID: 'testaccount',
13
+ apiKey: 'testapikey',
14
+ apiBase: 'testbase',
15
+ timezone: 'UTC'
16
+ };
17
+ describe('VeSyncAir131 Air Quality Features', () => {
18
+ let device;
19
+ beforeEach(() => {
20
+ const deviceDetails = {
21
+ deviceName: 'LV-PUR131S Test',
22
+ deviceType: 'LV-PUR131S',
23
+ cid: 'test-cid',
24
+ uuid: 'test-uuid',
25
+ deviceStatus: 'on',
26
+ deviceRegion: 'US',
27
+ configModule: 'VeSyncAir131',
28
+ macId: '00:11:22:33:44:55',
29
+ deviceCategory: 'fan',
30
+ connectionStatus: 'online'
31
+ };
32
+ device = new air131_1.VeSyncAir131(deviceDetails, mockManager);
33
+ });
34
+ describe('Air Quality Data Parsing', () => {
35
+ it('should parse air quality data with PM2.5 values', () => {
36
+ const mockResponse = {
37
+ result: {
38
+ code: 0,
39
+ result: {
40
+ enabled: true,
41
+ mode: 'auto',
42
+ level: 2,
43
+ speed: 2,
44
+ display: true,
45
+ child_lock: false,
46
+ night_light: 'off',
47
+ air_quality: 2,
48
+ air_quality_value: 28,
49
+ filter_life: {
50
+ percent: 68,
51
+ replace_indicator: false
52
+ },
53
+ timer_remain: 0
54
+ }
55
+ }
56
+ };
57
+ device.details = mockResponse.result.result;
58
+ expect(device.airQualityLevel).toBe(2);
59
+ expect(device.airQualityValue).toBe(28);
60
+ expect(device.filterLife).toBe(68);
61
+ });
62
+ it('should handle air quality levels 1-5 mapping', () => {
63
+ const airQualityMappings = [
64
+ { level: 1, pm25: 8, description: 'Excellent' },
65
+ { level: 2, pm25: 22, description: 'Good' },
66
+ { level: 3, pm25: 38, description: 'Fair' },
67
+ { level: 4, pm25: 75, description: 'Poor' },
68
+ { level: 5, pm25: 150, description: 'Very Poor' }
69
+ ];
70
+ airQualityMappings.forEach(mapping => {
71
+ device.details = {
72
+ air_quality: mapping.level,
73
+ air_quality_value: mapping.pm25,
74
+ filter_life: { percent: 50 }
75
+ };
76
+ expect(device.airQualityLevel).toBe(mapping.level);
77
+ expect(device.airQualityValue).toBe(mapping.pm25);
78
+ });
79
+ });
80
+ it('should handle missing air quality data', () => {
81
+ device.details = {
82
+ enabled: true,
83
+ mode: 'manual',
84
+ level: 3,
85
+ speed: 3,
86
+ filter_life: { percent: 45 }
87
+ // air_quality and air_quality_value missing
88
+ };
89
+ expect(device.airQualityLevel).toBe('');
90
+ expect(device.airQualityValue).toBe(0);
91
+ });
92
+ it('should handle zero PM2.5 readings (perfect air)', () => {
93
+ device.details = {
94
+ air_quality: 1,
95
+ air_quality_value: 0,
96
+ filter_life: { percent: 85 }
97
+ };
98
+ expect(device.airQualityLevel).toBe(1);
99
+ expect(device.airQualityValue).toBe(0);
100
+ });
101
+ it('should handle hazardous air quality levels', () => {
102
+ device.details = {
103
+ air_quality: 5,
104
+ air_quality_value: 500,
105
+ filter_life: { percent: 25 }
106
+ };
107
+ expect(device.airQualityLevel).toBe(5);
108
+ expect(device.airQualityValue).toBe(500);
109
+ });
110
+ });
111
+ describe('Filter Life Object Format', () => {
112
+ it('should parse filter life object with percent', () => {
113
+ device.details = {
114
+ filter_life: {
115
+ percent: 72,
116
+ replace_indicator: false
117
+ }
118
+ };
119
+ expect(device.filterLife).toBe(72);
120
+ });
121
+ it('should handle filter replacement indicator', () => {
122
+ device.details = {
123
+ filter_life: {
124
+ percent: 8,
125
+ replace_indicator: true
126
+ }
127
+ };
128
+ expect(device.filterLife).toBe(8);
129
+ });
130
+ it('should handle new filter (100%)', () => {
131
+ device.details = {
132
+ filter_life: {
133
+ percent: 100,
134
+ replace_indicator: false
135
+ }
136
+ };
137
+ expect(device.filterLife).toBe(100);
138
+ });
139
+ it('should handle filter needs replacement (0%)', () => {
140
+ device.details = {
141
+ filter_life: {
142
+ percent: 0,
143
+ replace_indicator: true
144
+ }
145
+ };
146
+ expect(device.filterLife).toBe(0);
147
+ });
148
+ it('should handle missing percent in filter object', () => {
149
+ device.details = {
150
+ filter_life: {
151
+ replace_indicator: true
152
+ // percent missing
153
+ }
154
+ };
155
+ expect(device.filterLife).toBe(0);
156
+ });
157
+ it('should handle null filter life object', () => {
158
+ device.details = {
159
+ filter_life: null
160
+ };
161
+ expect(device.filterLife).toBe(0);
162
+ });
163
+ it('should handle empty filter life object', () => {
164
+ device.details = {
165
+ filter_life: {}
166
+ };
167
+ expect(device.filterLife).toBe(0);
168
+ });
169
+ it('should handle malformed filter life object', () => {
170
+ device.details = {
171
+ filter_life: {
172
+ percent: 'not_a_number',
173
+ replace_indicator: 'not_a_boolean'
174
+ }
175
+ };
176
+ expect(device.filterLife).toBe(0);
177
+ });
178
+ });
179
+ describe('Device Configuration and Features', () => {
180
+ it('should support air quality features for LV-PUR131S', () => {
181
+ expect(device.hasFeature('air_quality')).toBe(true);
182
+ expect(device.hasFeature('display')).toBe(true);
183
+ expect(device.hasFeature('child_lock')).toBe(true);
184
+ expect(device.hasFeature('night_light')).toBe(true);
185
+ expect(device.hasFeature('timer')).toBe(true);
186
+ expect(device.hasFeature('fan_speed')).toBe(true);
187
+ expect(device.hasFeature('auto_mode')).toBe(true);
188
+ });
189
+ it('should return correct maximum speed for LV-PUR131S', () => {
190
+ expect(device.getMaxFanSpeed()).toBe(3); // LV series has 3 speeds
191
+ });
192
+ it('should handle LV-RH131S without air quality', () => {
193
+ const rh131s = new air131_1.VeSyncAir131({
194
+ deviceName: 'LV-RH131S Test',
195
+ deviceType: 'LV-RH131S',
196
+ cid: 'test-cid',
197
+ uuid: 'test-uuid'
198
+ }, mockManager);
199
+ expect(rh131s.hasFeature('air_quality')).toBe(false);
200
+ expect(rh131s.hasFeature('display')).toBe(true);
201
+ });
202
+ });
203
+ describe('Mode-specific Behavior', () => {
204
+ it('should support air quality in auto mode', () => {
205
+ device.details.mode = 'auto';
206
+ expect(device.isFeatureSupportedInCurrentMode('air_quality')).toBe(true);
207
+ });
208
+ it('should support air quality in manual mode', () => {
209
+ device.details.mode = 'manual';
210
+ expect(device.isFeatureSupportedInCurrentMode('air_quality')).toBe(true);
211
+ });
212
+ it('should restrict fan speed control to manual mode', () => {
213
+ device.details.mode = 'manual';
214
+ expect(device.isFeatureSupportedInCurrentMode('fan_speed')).toBe(true);
215
+ device.details.mode = 'auto';
216
+ expect(device.isFeatureSupportedInCurrentMode('fan_speed')).toBe(false);
217
+ });
218
+ it('should disable display and child lock in sleep mode', () => {
219
+ device.details.mode = 'sleep';
220
+ expect(device.isFeatureSupportedInCurrentMode('display')).toBe(false);
221
+ expect(device.isFeatureSupportedInCurrentMode('child_lock')).toBe(false);
222
+ });
223
+ });
224
+ describe('State Tracking and Updates', () => {
225
+ it('should track complete device state', () => {
226
+ device.details = {
227
+ enabled: true,
228
+ mode: 'auto',
229
+ level: 2,
230
+ speed: 2,
231
+ display: true,
232
+ child_lock: false,
233
+ night_light: 'dim',
234
+ air_quality: 2,
235
+ air_quality_value: 32,
236
+ filter_life: {
237
+ percent: 55,
238
+ replace_indicator: false
239
+ },
240
+ timer_remain: 1800
241
+ };
242
+ expect(device.deviceStatus).toBe('on');
243
+ expect(device.mode).toBe('auto');
244
+ expect(device.speed).toBe(2);
245
+ expect(device.screenStatus).toBe('on'); // display: true maps to 'on'
246
+ expect(device.childLock).toBe(false);
247
+ expect(device.airQualityLevel).toBe(2);
248
+ expect(device.airQualityValue).toBe(32);
249
+ expect(device.filterLife).toBe(55);
250
+ });
251
+ it('should handle boolean display values correctly', () => {
252
+ device.details = { display: true };
253
+ expect(device.screenStatus).toBe('on');
254
+ device.details = { display: false };
255
+ expect(device.screenStatus).toBe('off');
256
+ });
257
+ it('should track filter replacement warnings', () => {
258
+ // Filter life getting low
259
+ device.details = {
260
+ filter_life: {
261
+ percent: 15,
262
+ replace_indicator: false
263
+ }
264
+ };
265
+ expect(device.filterLife).toBe(15);
266
+ // Filter replacement needed
267
+ device.details = {
268
+ filter_life: {
269
+ percent: 5,
270
+ replace_indicator: true
271
+ }
272
+ };
273
+ expect(device.filterLife).toBe(5);
274
+ });
275
+ });
276
+ describe('Air Quality History and Trends', () => {
277
+ it('should handle air quality improvements', () => {
278
+ // Poor air quality initially
279
+ device.details = {
280
+ air_quality: 4,
281
+ air_quality_value: 85,
282
+ filter_life: { percent: 40 }
283
+ };
284
+ expect(device.airQualityLevel).toBe(4);
285
+ // Air quality improves
286
+ device.details.air_quality = 2;
287
+ device.details.air_quality_value = 25;
288
+ expect(device.airQualityLevel).toBe(2);
289
+ expect(device.airQualityValue).toBe(25);
290
+ });
291
+ it('should handle air quality deterioration', () => {
292
+ // Good air quality initially
293
+ device.details = {
294
+ air_quality: 2,
295
+ air_quality_value: 20,
296
+ filter_life: { percent: 60 }
297
+ };
298
+ expect(device.airQualityLevel).toBe(2);
299
+ // Air quality worsens
300
+ device.details.air_quality = 4;
301
+ device.details.air_quality_value = 90;
302
+ expect(device.airQualityLevel).toBe(4);
303
+ expect(device.airQualityValue).toBe(90);
304
+ });
305
+ });
306
+ describe('Error Handling and Edge Cases', () => {
307
+ it('should handle completely missing details', () => {
308
+ device.details = undefined;
309
+ expect(device.airQualityLevel).toBe('');
310
+ expect(device.airQualityValue).toBe(0);
311
+ expect(device.filterLife).toBe(0);
312
+ });
313
+ it('should handle partial API responses', () => {
314
+ device.details = {
315
+ mode: 'auto',
316
+ speed: 1
317
+ // All other fields missing
318
+ };
319
+ expect(device.mode).toBe('auto');
320
+ expect(device.speed).toBe(1);
321
+ expect(device.airQualityLevel).toBe('');
322
+ expect(device.airQualityValue).toBe(0);
323
+ expect(device.filterLife).toBe(0);
324
+ });
325
+ it('should handle network errors gracefully', () => {
326
+ // Simulate network error - details remain from last update
327
+ device.details = {
328
+ air_quality: 2,
329
+ air_quality_value: 30,
330
+ filter_life: { percent: 70 }
331
+ };
332
+ // Values preserved from last successful update
333
+ expect(device.airQualityLevel).toBe(2);
334
+ expect(device.airQualityValue).toBe(30);
335
+ expect(device.filterLife).toBe(70);
336
+ });
337
+ it('should handle invalid air quality levels', () => {
338
+ device.details = {
339
+ air_quality: 10, // Invalid level (should be 1-5)
340
+ air_quality_value: 50,
341
+ filter_life: { percent: 50 }
342
+ };
343
+ expect(device.airQualityLevel).toBe(10); // Return raw value for debugging
344
+ expect(device.airQualityValue).toBe(50);
345
+ });
346
+ it('should handle negative filter life percent', () => {
347
+ device.details = {
348
+ filter_life: {
349
+ percent: -10,
350
+ replace_indicator: true
351
+ }
352
+ };
353
+ expect(device.filterLife).toBe(-10); // Allow for error detection
354
+ });
355
+ it('should handle filter life percent over 100', () => {
356
+ device.details = {
357
+ filter_life: {
358
+ percent: 150,
359
+ replace_indicator: false
360
+ }
361
+ };
362
+ expect(device.filterLife).toBe(150); // Allow for error detection
363
+ });
364
+ });
365
+ });
@@ -0,0 +1,4 @@
1
+ /**
2
+ * Unit tests for VeSyncAirBaseV2 air quality data parsing
3
+ */
4
+ export {};
@@ -0,0 +1,283 @@
1
+ "use strict";
2
+ /**
3
+ * Unit tests for VeSyncAirBaseV2 air quality data parsing
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const airBaseV2_1 = require("../../lib/fans/airBaseV2");
7
+ // Mock VeSync manager
8
+ const mockManager = {
9
+ username: 'test@example.com',
10
+ password: 'testpass',
11
+ token: 'testtoken',
12
+ accountID: 'testaccount',
13
+ apiKey: 'testapikey',
14
+ apiBase: 'testbase',
15
+ timezone: 'UTC'
16
+ };
17
+ describe('VeSyncAirBaseV2 Air Quality Features', () => {
18
+ let device;
19
+ beforeEach(() => {
20
+ const deviceDetails = {
21
+ deviceName: 'LAP-V102S Test',
22
+ deviceType: 'LAP-V102S-AASR',
23
+ cid: 'test-cid',
24
+ uuid: 'test-uuid',
25
+ deviceStatus: 'on',
26
+ deviceRegion: 'US',
27
+ configModule: 'VeSyncAirBaseV2',
28
+ macId: '00:11:22:33:44:55',
29
+ deviceCategory: 'fan',
30
+ connectionStatus: 'online'
31
+ };
32
+ device = new airBaseV2_1.VeSyncAirBaseV2(deviceDetails, mockManager);
33
+ });
34
+ describe('Air Quality Data Parsing', () => {
35
+ it('should parse comprehensive air quality data', () => {
36
+ const mockResponse = {
37
+ result: {
38
+ code: 0,
39
+ result: {
40
+ enabled: true,
41
+ mode: 'auto',
42
+ level: 2,
43
+ speed: 2,
44
+ display: 'on',
45
+ child_lock: false,
46
+ night_light: 'off',
47
+ air_quality: 'Good',
48
+ air_quality_value: 18,
49
+ pm1: 12,
50
+ pm10: 22,
51
+ aq_percent: 85,
52
+ filter_life: 78,
53
+ timer_remain: 3600
54
+ }
55
+ }
56
+ };
57
+ device.details = mockResponse.result.result;
58
+ expect(device.airQualityLevel).toBe('Good');
59
+ expect(device.airQualityValue).toBe(18);
60
+ expect(device.pm1).toBe(12);
61
+ expect(device.pm10).toBe(22);
62
+ expect(device.aqPercent).toBe(85);
63
+ expect(device.filterLife).toBe(78);
64
+ });
65
+ it('should handle numeric air quality levels', () => {
66
+ device.details = {
67
+ air_quality: 3,
68
+ air_quality_value: 45,
69
+ pm1: 25,
70
+ pm10: 65,
71
+ filter_life: 45
72
+ };
73
+ expect(device.airQualityLevel).toBe(3);
74
+ expect(device.airQualityValue).toBe(45);
75
+ expect(device.pm1).toBe(25);
76
+ expect(device.pm10).toBe(65);
77
+ });
78
+ it('should handle string air quality levels', () => {
79
+ const qualityLevels = ['Excellent', 'Good', 'Fair', 'Poor', 'Very Poor'];
80
+ qualityLevels.forEach((level, index) => {
81
+ device.details = {
82
+ air_quality: level,
83
+ air_quality_value: (index + 1) * 20
84
+ };
85
+ expect(device.airQualityLevel).toBe(level);
86
+ expect(device.airQualityValue).toBe((index + 1) * 20);
87
+ });
88
+ });
89
+ it('should handle missing PM data gracefully', () => {
90
+ device.details = {
91
+ air_quality: 'Good',
92
+ air_quality_value: 20,
93
+ filter_life: 60
94
+ // pm1 and pm10 missing
95
+ };
96
+ expect(device.airQualityLevel).toBe('Good');
97
+ expect(device.airQualityValue).toBe(20);
98
+ expect(device.pm1).toBe(0);
99
+ expect(device.pm10).toBe(0);
100
+ expect(device.aqPercent).toBe(0);
101
+ });
102
+ it('should handle all PM values at zero', () => {
103
+ device.details = {
104
+ air_quality: 'Excellent',
105
+ air_quality_value: 0,
106
+ pm1: 0,
107
+ pm10: 0,
108
+ aq_percent: 100
109
+ };
110
+ expect(device.airQualityValue).toBe(0);
111
+ expect(device.pm1).toBe(0);
112
+ expect(device.pm10).toBe(0);
113
+ expect(device.aqPercent).toBe(100);
114
+ });
115
+ it('should handle extreme air quality values', () => {
116
+ device.details = {
117
+ air_quality: 'Hazardous',
118
+ air_quality_value: 300,
119
+ pm1: 200,
120
+ pm10: 400,
121
+ aq_percent: 5,
122
+ filter_life: 15
123
+ };
124
+ expect(device.airQualityLevel).toBe('Hazardous');
125
+ expect(device.airQualityValue).toBe(300);
126
+ expect(device.pm1).toBe(200);
127
+ expect(device.pm10).toBe(400);
128
+ expect(device.aqPercent).toBe(5);
129
+ });
130
+ });
131
+ describe('Filter Life Management', () => {
132
+ it('should handle normal filter life values', () => {
133
+ const testValues = [0, 25, 50, 75, 100];
134
+ testValues.forEach(value => {
135
+ device.details = { filter_life: value };
136
+ expect(device.filterLife).toBe(value);
137
+ });
138
+ });
139
+ it('should handle low filter life warning threshold', () => {
140
+ device.details = { filter_life: 5 };
141
+ expect(device.filterLife).toBe(5);
142
+ });
143
+ it('should handle filter replacement needed (0%)', () => {
144
+ device.details = { filter_life: 0 };
145
+ expect(device.filterLife).toBe(0);
146
+ });
147
+ it('should handle new filter (100%)', () => {
148
+ device.details = { filter_life: 100 };
149
+ expect(device.filterLife).toBe(100);
150
+ });
151
+ });
152
+ describe('Device Configuration', () => {
153
+ it('should support air quality features for LAP-V102S', () => {
154
+ expect(device.hasFeature('air_quality')).toBe(true);
155
+ expect(device.hasFeature('display')).toBe(true);
156
+ expect(device.hasFeature('child_lock')).toBe(true);
157
+ expect(device.hasFeature('night_light')).toBe(true);
158
+ expect(device.hasFeature('timer')).toBe(true);
159
+ expect(device.hasFeature('fan_speed')).toBe(true);
160
+ expect(device.hasFeature('auto_mode')).toBe(true);
161
+ });
162
+ it('should return correct maximum speed', () => {
163
+ expect(device.getMaxFanSpeed()).toBe(4); // LAP-V102S has 4 speeds
164
+ });
165
+ it('should support air quality in all modes', () => {
166
+ const modes = ['auto', 'manual', 'sleep', 'turbo'];
167
+ modes.forEach(mode => {
168
+ device.details.mode = mode;
169
+ expect(device.isFeatureSupportedInCurrentMode('air_quality')).toBe(true);
170
+ });
171
+ });
172
+ });
173
+ describe('Real-time Data Updates', () => {
174
+ it('should handle real-time air quality updates', () => {
175
+ // Initial state
176
+ device.details = {
177
+ air_quality: 'Good',
178
+ air_quality_value: 25,
179
+ pm1: 15,
180
+ pm10: 35
181
+ };
182
+ expect(device.airQualityValue).toBe(25);
183
+ // Simulate air quality change
184
+ device.details.air_quality = 'Fair';
185
+ device.details.air_quality_value = 40;
186
+ device.details.pm1 = 28;
187
+ device.details.pm10 = 55;
188
+ expect(device.airQualityLevel).toBe('Fair');
189
+ expect(device.airQualityValue).toBe(40);
190
+ expect(device.pm1).toBe(28);
191
+ expect(device.pm10).toBe(55);
192
+ });
193
+ it('should handle rapid air quality fluctuations', () => {
194
+ const rapidUpdates = [
195
+ { quality: 'Good', value: 20 },
196
+ { quality: 'Fair', value: 35 },
197
+ { quality: 'Good', value: 22 },
198
+ { quality: 'Poor', value: 75 },
199
+ { quality: 'Fair', value: 38 }
200
+ ];
201
+ rapidUpdates.forEach(update => {
202
+ device.details.air_quality = update.quality;
203
+ device.details.air_quality_value = update.value;
204
+ expect(device.airQualityLevel).toBe(update.quality);
205
+ expect(device.airQualityValue).toBe(update.value);
206
+ });
207
+ });
208
+ });
209
+ describe('Device State Synchronization', () => {
210
+ it('should maintain consistent state across updates', () => {
211
+ device.details = {
212
+ enabled: true,
213
+ mode: 'auto',
214
+ level: 3,
215
+ speed: 3,
216
+ display: 'on',
217
+ child_lock: true,
218
+ air_quality: 'Good',
219
+ air_quality_value: 22,
220
+ filter_life: 65
221
+ };
222
+ expect(device.deviceStatus).toBe('on');
223
+ expect(device.mode).toBe('auto');
224
+ expect(device.speed).toBe(3);
225
+ expect(device.screenStatus).toBe('on');
226
+ expect(device.childLock).toBe(true);
227
+ expect(device.airQualityLevel).toBe('Good');
228
+ expect(device.filterLife).toBe(65);
229
+ });
230
+ it('should handle partial state updates', () => {
231
+ // Initial state
232
+ device.details = {
233
+ mode: 'auto',
234
+ speed: 2,
235
+ air_quality_value: 30,
236
+ filter_life: 70
237
+ };
238
+ // Partial update (only some fields changed)
239
+ device.details.air_quality_value = 35;
240
+ device.details.speed = 3;
241
+ expect(device.mode).toBe('auto'); // Unchanged
242
+ expect(device.speed).toBe(3); // Changed
243
+ expect(device.airQualityValue).toBe(35); // Changed
244
+ expect(device.filterLife).toBe(70); // Unchanged
245
+ });
246
+ });
247
+ describe('Error Conditions', () => {
248
+ it('should handle API errors gracefully', () => {
249
+ device.details = undefined;
250
+ expect(device.airQualityValue).toBe(0);
251
+ expect(device.pm1).toBe(0);
252
+ expect(device.pm10).toBe(0);
253
+ expect(device.aqPercent).toBe(0);
254
+ expect(device.filterLife).toBe(0);
255
+ });
256
+ it('should handle corrupted data fields', () => {
257
+ device.details = {
258
+ air_quality: { invalid: 'object' },
259
+ air_quality_value: 'not_a_number',
260
+ pm1: null,
261
+ pm10: undefined,
262
+ filter_life: []
263
+ };
264
+ expect(device.airQualityLevel).toEqual({ invalid: 'object' });
265
+ expect(device.airQualityValue).toBe(0);
266
+ expect(device.pm1).toBe(0);
267
+ expect(device.pm10).toBe(0);
268
+ expect(device.filterLife).toBe(0);
269
+ });
270
+ it('should handle network timeout scenarios', () => {
271
+ // Simulate stale data from last successful update
272
+ device.details = {
273
+ air_quality: 'Good',
274
+ air_quality_value: 25,
275
+ filter_life: 60
276
+ };
277
+ // Values should remain from last update
278
+ expect(device.airQualityLevel).toBe('Good');
279
+ expect(device.airQualityValue).toBe(25);
280
+ expect(device.filterLife).toBe(60);
281
+ });
282
+ });
283
+ });
@@ -0,0 +1,4 @@
1
+ /**
2
+ * Unit tests for VeSyncAirBypass air quality data parsing
3
+ */
4
+ export {};