tsvesync 1.0.89 → 1.0.91
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/README.md +1 -36
- package/dist/__tests__/fans/vesyncAir131.test.d.ts +4 -0
- package/dist/__tests__/fans/vesyncAir131.test.js +365 -0
- package/dist/__tests__/fans/vesyncAirBaseV2.test.d.ts +4 -0
- package/dist/__tests__/fans/vesyncAirBaseV2.test.js +283 -0
- package/dist/__tests__/fans/vesyncAirBypass.test.d.ts +4 -0
- package/dist/__tests__/fans/vesyncAirBypass.test.js +257 -0
- package/dist/__tests__/vesyncFan.test.d.ts +4 -0
- package/dist/__tests__/vesyncFan.test.js +263 -0
- package/dist/lib/fans/air131.js +5 -4
- package/dist/lib/fans/airBypass.js +12 -4
- package/dist/lib/helpers.d.ts +0 -13
- package/dist/lib/helpers.js +4 -158
- package/dist/lib/vesync.d.ts +1 -1
- package/dist/lib/vesync.js +5 -5
- package/dist/lib/vesyncFan.d.ts +30 -4
- package/dist/lib/vesyncFan.js +70 -5
- package/package.json +1 -1
- package/src/lib/fans/air131.ts +5 -4
- package/src/lib/fans/airBypass.ts +10 -4
- package/src/lib/helpers.ts +3 -169
- package/src/lib/vesync.ts +6 -6
- package/src/lib/vesyncFan.ts +79 -7
|
@@ -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,257 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Unit tests for VeSyncAirBypass air quality data parsing
|
|
4
|
+
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const airBypass_1 = require("../../lib/fans/airBypass");
|
|
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('VeSyncAirBypass Air Quality Features', () => {
|
|
18
|
+
let device;
|
|
19
|
+
beforeEach(() => {
|
|
20
|
+
const deviceDetails = {
|
|
21
|
+
deviceName: 'Core300S Test',
|
|
22
|
+
deviceType: 'Core300S',
|
|
23
|
+
cid: 'test-cid',
|
|
24
|
+
uuid: 'test-uuid',
|
|
25
|
+
deviceStatus: 'on',
|
|
26
|
+
deviceRegion: 'US',
|
|
27
|
+
configModule: 'VeSyncAirBypass',
|
|
28
|
+
macId: '00:11:22:33:44:55',
|
|
29
|
+
deviceCategory: 'fan',
|
|
30
|
+
connectionStatus: 'online'
|
|
31
|
+
};
|
|
32
|
+
device = new airBypass_1.VeSyncAirBypass(deviceDetails, mockManager);
|
|
33
|
+
});
|
|
34
|
+
describe('Air Quality Data Parsing', () => {
|
|
35
|
+
it('should parse air quality data from device response', () => {
|
|
36
|
+
const mockResponse = {
|
|
37
|
+
result: {
|
|
38
|
+
code: 0,
|
|
39
|
+
result: {
|
|
40
|
+
enabled: true,
|
|
41
|
+
mode: 'auto',
|
|
42
|
+
level: 3,
|
|
43
|
+
speed: 3,
|
|
44
|
+
display: 'on',
|
|
45
|
+
child_lock: false,
|
|
46
|
+
night_light: 'dim',
|
|
47
|
+
air_quality: 2,
|
|
48
|
+
air_quality_value: 15,
|
|
49
|
+
filter_life: 85,
|
|
50
|
+
timer_remain: 0
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
// Simulate API response parsing
|
|
55
|
+
device.details = mockResponse.result.result;
|
|
56
|
+
expect(device.airQualityLevel).toBe(2);
|
|
57
|
+
expect(device.airQualityValue).toBe(15);
|
|
58
|
+
expect(device.filterLife).toBe(85);
|
|
59
|
+
});
|
|
60
|
+
it('should handle missing air quality data gracefully', () => {
|
|
61
|
+
const mockResponse = {
|
|
62
|
+
result: {
|
|
63
|
+
code: 0,
|
|
64
|
+
result: {
|
|
65
|
+
enabled: true,
|
|
66
|
+
mode: 'auto',
|
|
67
|
+
level: 3,
|
|
68
|
+
speed: 3,
|
|
69
|
+
display: 'on',
|
|
70
|
+
child_lock: false,
|
|
71
|
+
filter_life: 85
|
|
72
|
+
// air_quality and air_quality_value missing
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
device.details = mockResponse.result.result;
|
|
77
|
+
expect(device.airQualityLevel).toBe('');
|
|
78
|
+
expect(device.airQualityValue).toBe(0);
|
|
79
|
+
expect(device.filterLife).toBe(85);
|
|
80
|
+
});
|
|
81
|
+
it('should handle various air quality value ranges', () => {
|
|
82
|
+
const testCases = [
|
|
83
|
+
{ value: 0, level: 1, expected: 'Excellent' },
|
|
84
|
+
{ value: 12, level: 1, expected: 'Good' },
|
|
85
|
+
{ value: 25, level: 2, expected: 'Fair' },
|
|
86
|
+
{ value: 55, level: 3, expected: 'Inferior' },
|
|
87
|
+
{ value: 150, level: 4, expected: 'Poor' },
|
|
88
|
+
{ value: 500, level: 5, expected: 'Poor' }
|
|
89
|
+
];
|
|
90
|
+
testCases.forEach(testCase => {
|
|
91
|
+
device.details = {
|
|
92
|
+
air_quality: testCase.level,
|
|
93
|
+
air_quality_value: testCase.value,
|
|
94
|
+
filter_life: 50
|
|
95
|
+
};
|
|
96
|
+
expect(device.airQualityValue).toBe(testCase.value);
|
|
97
|
+
expect(device.airQualityLevel).toBe(testCase.level);
|
|
98
|
+
});
|
|
99
|
+
});
|
|
100
|
+
it('should handle extended air quality data with PM1 and PM10', () => {
|
|
101
|
+
device.details = {
|
|
102
|
+
air_quality: 2,
|
|
103
|
+
air_quality_value: 20,
|
|
104
|
+
pm1: 15,
|
|
105
|
+
pm10: 35,
|
|
106
|
+
aq_percent: 75,
|
|
107
|
+
filter_life: 60
|
|
108
|
+
};
|
|
109
|
+
expect(device.airQualityValue).toBe(20);
|
|
110
|
+
expect(device.pm1).toBe(15);
|
|
111
|
+
expect(device.pm10).toBe(35);
|
|
112
|
+
expect(device.aqPercent).toBe(75);
|
|
113
|
+
});
|
|
114
|
+
it('should handle zero PM values correctly', () => {
|
|
115
|
+
device.details = {
|
|
116
|
+
air_quality: 1,
|
|
117
|
+
air_quality_value: 0,
|
|
118
|
+
pm1: 0,
|
|
119
|
+
pm10: 0,
|
|
120
|
+
aq_percent: 100,
|
|
121
|
+
filter_life: 100
|
|
122
|
+
};
|
|
123
|
+
expect(device.airQualityValue).toBe(0);
|
|
124
|
+
expect(device.pm1).toBe(0);
|
|
125
|
+
expect(device.pm10).toBe(0);
|
|
126
|
+
expect(device.aqPercent).toBe(100);
|
|
127
|
+
});
|
|
128
|
+
});
|
|
129
|
+
describe('Filter Life Parsing', () => {
|
|
130
|
+
it('should parse filter life as number', () => {
|
|
131
|
+
device.details = { filter_life: 75 };
|
|
132
|
+
expect(device.filterLife).toBe(75);
|
|
133
|
+
});
|
|
134
|
+
it('should handle zero filter life', () => {
|
|
135
|
+
device.details = { filter_life: 0 };
|
|
136
|
+
expect(device.filterLife).toBe(0);
|
|
137
|
+
});
|
|
138
|
+
it('should handle 100% filter life', () => {
|
|
139
|
+
device.details = { filter_life: 100 };
|
|
140
|
+
expect(device.filterLife).toBe(100);
|
|
141
|
+
});
|
|
142
|
+
it('should handle missing filter life data', () => {
|
|
143
|
+
device.details = { mode: 'auto', speed: 3 };
|
|
144
|
+
expect(device.filterLife).toBe(0);
|
|
145
|
+
});
|
|
146
|
+
it('should handle invalid filter life data types', () => {
|
|
147
|
+
device.details = { filter_life: 'invalid' };
|
|
148
|
+
expect(device.filterLife).toBe(0);
|
|
149
|
+
});
|
|
150
|
+
});
|
|
151
|
+
describe('Feature Support', () => {
|
|
152
|
+
it('should support air quality features for Core300S', () => {
|
|
153
|
+
expect(device.hasFeature('air_quality')).toBe(true);
|
|
154
|
+
expect(device.hasFeature('auto_mode')).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
|
+
});
|
|
159
|
+
it('should not support air quality for Core200S', () => {
|
|
160
|
+
const core200s = new airBypass_1.VeSyncAirBypass({
|
|
161
|
+
deviceName: 'Core200S Test',
|
|
162
|
+
deviceType: 'Core200S',
|
|
163
|
+
cid: 'test-cid',
|
|
164
|
+
uuid: 'test-uuid'
|
|
165
|
+
}, mockManager);
|
|
166
|
+
expect(core200s.hasFeature('air_quality')).toBe(false);
|
|
167
|
+
expect(core200s.hasFeature('auto_mode')).toBe(false);
|
|
168
|
+
});
|
|
169
|
+
it('should return correct max speed for different models', () => {
|
|
170
|
+
expect(device.getMaxFanSpeed()).toBe(4); // Core300S has 4 speeds
|
|
171
|
+
const core200s = new airBypass_1.VeSyncAirBypass({
|
|
172
|
+
deviceName: 'Core200S Test',
|
|
173
|
+
deviceType: 'Core200S',
|
|
174
|
+
cid: 'test-cid',
|
|
175
|
+
uuid: 'test-uuid'
|
|
176
|
+
}, mockManager);
|
|
177
|
+
expect(core200s.getMaxFanSpeed()).toBe(3); // Core200S has 3 speeds
|
|
178
|
+
});
|
|
179
|
+
});
|
|
180
|
+
describe('Device State Management', () => {
|
|
181
|
+
it('should track device state correctly', () => {
|
|
182
|
+
device.details = {
|
|
183
|
+
enabled: true,
|
|
184
|
+
mode: 'auto',
|
|
185
|
+
level: 3,
|
|
186
|
+
speed: 3,
|
|
187
|
+
display: 'on',
|
|
188
|
+
child_lock: false,
|
|
189
|
+
air_quality: 2,
|
|
190
|
+
air_quality_value: 25,
|
|
191
|
+
filter_life: 65
|
|
192
|
+
};
|
|
193
|
+
expect(device.deviceStatus).toBe('on');
|
|
194
|
+
expect(device.mode).toBe('auto');
|
|
195
|
+
expect(device.speed).toBe(3);
|
|
196
|
+
expect(device.screenStatus).toBe('on');
|
|
197
|
+
expect(device.childLock).toBe(false);
|
|
198
|
+
});
|
|
199
|
+
it('should handle device off state', () => {
|
|
200
|
+
device.deviceStatus = 'off';
|
|
201
|
+
device.details = {
|
|
202
|
+
enabled: false,
|
|
203
|
+
mode: 'manual',
|
|
204
|
+
level: 0,
|
|
205
|
+
speed: 0,
|
|
206
|
+
air_quality_value: 0
|
|
207
|
+
};
|
|
208
|
+
expect(device.deviceStatus).toBe('off');
|
|
209
|
+
expect(device.speed).toBe(0);
|
|
210
|
+
});
|
|
211
|
+
});
|
|
212
|
+
describe('Error Handling', () => {
|
|
213
|
+
it('should handle malformed API responses', () => {
|
|
214
|
+
device.details = null;
|
|
215
|
+
expect(device.airQualityValue).toBe(0);
|
|
216
|
+
expect(device.filterLife).toBe(0);
|
|
217
|
+
expect(device.mode).toBe('');
|
|
218
|
+
expect(device.speed).toBe(0);
|
|
219
|
+
});
|
|
220
|
+
it('should handle partial API responses', () => {
|
|
221
|
+
device.details = {
|
|
222
|
+
mode: 'auto'
|
|
223
|
+
// Other fields missing
|
|
224
|
+
};
|
|
225
|
+
expect(device.airQualityValue).toBe(0);
|
|
226
|
+
expect(device.filterLife).toBe(0);
|
|
227
|
+
expect(device.mode).toBe('auto');
|
|
228
|
+
expect(device.speed).toBe(0);
|
|
229
|
+
});
|
|
230
|
+
it('should handle negative values gracefully', () => {
|
|
231
|
+
device.details = {
|
|
232
|
+
air_quality_value: -10,
|
|
233
|
+
pm1: -5,
|
|
234
|
+
pm10: -15,
|
|
235
|
+
filter_life: -20
|
|
236
|
+
};
|
|
237
|
+
expect(device.airQualityValue).toBe(-10); // Allow negative for error detection
|
|
238
|
+
expect(device.pm1).toBe(-5);
|
|
239
|
+
expect(device.pm10).toBe(-15);
|
|
240
|
+
expect(device.filterLife).toBe(-20);
|
|
241
|
+
});
|
|
242
|
+
it('should handle extremely high values', () => {
|
|
243
|
+
device.details = {
|
|
244
|
+
air_quality_value: 9999,
|
|
245
|
+
pm1: 5000,
|
|
246
|
+
pm10: 8000,
|
|
247
|
+
filter_life: 200,
|
|
248
|
+
aq_percent: 150
|
|
249
|
+
};
|
|
250
|
+
expect(device.airQualityValue).toBe(9999);
|
|
251
|
+
expect(device.pm1).toBe(5000);
|
|
252
|
+
expect(device.pm10).toBe(8000);
|
|
253
|
+
expect(device.filterLife).toBe(200);
|
|
254
|
+
expect(device.aqPercent).toBe(150);
|
|
255
|
+
});
|
|
256
|
+
});
|
|
257
|
+
});
|