111
This commit is contained in:
@@ -28,7 +28,9 @@ const device = (deviceId, name, moduleKey, category, entities = [], extra = {})
|
||||
deviceId, name, moduleKey, category, entities, online: true, manufacturer: '测试品牌', model: '测试型号', areaName: '睡眠空间', ...extra,
|
||||
})
|
||||
const devices = [
|
||||
device('lamp', '演示卧室灯', 'lighting', 'Lighting', [reading('light.room', 'light', 'on', { brightness: 128 })], { primaryControlEntityId: 'light.room' }),
|
||||
device('lamp', '演示卧室灯', 'lighting', 'Lighting', [reading('light.room', 'light', 'on', { brightness: 128,
|
||||
supported_color_modes: ['color_temp'], min_color_temp_kelvin: 2700, max_color_temp_kelvin: 6500,
|
||||
color_temp_kelvin: 3000, supported_features: 4, effect_list: ['阅读', '助眠'], effect: '阅读' })], { primaryControlEntityId: 'light.room' }),
|
||||
device('mattress', '演示智能床垫', 'mattress', 'Sleep'),
|
||||
device('fragrance', '演示香氛机', 'fragrance', 'Fragrance', [reading('switch.fragrance', 'switch', 'off')], { primaryControlEntityId: 'switch.fragrance' }),
|
||||
device('speaker', '演示音箱', 'audio', 'Media', [reading('media_player.room', 'media_player', 'idle', { volume_level: .7 })], { primaryControlEntityId: 'media_player.room' }),
|
||||
@@ -213,6 +215,84 @@ test('outlet overview has a dedicated compact tile and trusted quick power switc
|
||||
for (const text of ['8472528', '充电保护、过载保护', '插座电源状态']) assert.ok(!html.includes(text), text)
|
||||
})
|
||||
|
||||
const standardLight = (mode = 'color_temp', attributes = {}) => device('strip', '新灯带', '', 'Lighting', [reading('light.strip', 'light', 'off', {
|
||||
supported_color_modes: [mode], min_color_temp_kelvin: 2700, max_color_temp_kelvin: 6500, supported_features: 4,
|
||||
brightness: null, color_temp_kelvin: null, effect: null, effect_list: ['阅读模式', '助眠模式'], ...attributes,
|
||||
}), { ...reading('number.packed', 'number', '842138120'), name: '内部保护设置' }], { primaryControlEntityId: 'light.strip' })
|
||||
const lightSnapshot = item => ({ connected: true, devices: [item], summary: { totalDevices: 1, onlineDevices: item.online ? 1 : 0 }, controlParameters: {} })
|
||||
|
||||
test('configured sleep strip preselects its default and displays its own fade without copying wake or massage features', async () => {
|
||||
const item = standardLight(); item.moduleKey = 'sleep-light-strip'; item.defaultLightEffect = '助眠模式'
|
||||
item.entities[0].state = 'on'; item.entities[0].attributes.brightness = 128
|
||||
const transition = { entityId: 'light.room', running: true, brightnessPercent: 11, mode: 'wake', lights: [
|
||||
{ entityId: 'light.room', running: true, brightnessPercent: 11, mode: 'wake' },
|
||||
{ entityId: 'light.strip', running: true, brightnessPercent: 46, mode: 'sleep' },
|
||||
] }
|
||||
const { html } = await render('/device-control/strip', { haStatus: ref(lightSnapshot(item)), lightTransition: ref(transition) })
|
||||
const card = html.match(/<section class="device-card"[\s\S]*?<\/section>/)[0]
|
||||
assert.ok(card.includes('助眠渐暗中 · 46%')); assert.match(card, /<strong class="p-val"[^>]*>46%<\/strong>/)
|
||||
assert.match(card, /<option value="助眠模式"[^>]* selected>/)
|
||||
assert.ok(card.includes('舒睡默认 助眠模式')); assert.ok(card.includes('已加入一键舒睡和关闭'))
|
||||
assert.ok(card.includes('每5秒降低1%')); assert.ok(card.includes('实际模式以顶部回读为准'))
|
||||
for (const text of ['晨起唤醒', '灯灭停止按摩', '11%', '不自动加入舒睡']) assert.ok(!card.includes(text), text)
|
||||
const overview = (await render('/device-control', { haStatus: ref(lightSnapshot(item)), lightTransition: ref(transition) })).html
|
||||
assert.ok(overview.includes('助眠渐暗中')); assert.ok(overview.includes('亮度 46%'))
|
||||
})
|
||||
|
||||
test('both configured light details keep their own runtime brightness when displayed from one shared response', async () => {
|
||||
const strip = standardLight(); strip.moduleKey = 'sleep-light-strip'; strip.defaultLightEffect = '助眠模式'; strip.entities[0].state = 'on'
|
||||
const snapshot = { ...lightSnapshot(strip), devices: [devices[0], strip] }
|
||||
const transition = { entityId: 'light.room', running: true, brightnessPercent: 11, mode: 'sleep', lights: [
|
||||
{ entityId: 'light.room', running: true, brightnessPercent: 11, mode: 'sleep' },
|
||||
{ entityId: 'light.strip', running: true, brightnessPercent: 46, mode: 'sleep' },
|
||||
] }
|
||||
const primary = (await render('/device-control/lamp', { haStatus: ref(snapshot), lightTransition: ref(transition) })).html
|
||||
assert.match(primary, /<strong class="p-val"[^>]*>11%<\/strong>/)
|
||||
const detail = (await render('/device-control/strip', { haStatus: ref(snapshot), lightTransition: ref(transition) })).html
|
||||
assert.match(detail, /<strong class="p-val"[^>]*>46%<\/strong>/)
|
||||
})
|
||||
|
||||
test('unbound new strip has standard brightness temperature and effects without copying scene light controls', async () => {
|
||||
const item = standardLight()
|
||||
const { html } = await render('/device-control/strip', { haStatus: ref(lightSnapshot(item)), lightTransition: ref({ running: true, mode: 'wake', brightnessPercent: 77 }) })
|
||||
const card = html.match(/<section class="device-card"[\s\S]*?<\/section>/)[0]
|
||||
for (const text of ['灯光控制', '新灯带', '灯光亮度', '灯光色温调节', '2700K 暖光', '6500K 冷光', '灯光模式', '阅读模式', '助眠模式', '已熄灭']) assert.ok(html.includes(text), text)
|
||||
for (const text of ['开始助眠渐暗', '晨起唤醒中', '842138120', '内部保护设置', '查看全部能力', '设备能力']) assert.ok(!card.includes(text), text)
|
||||
assert.equal((html.match(/van-slider__bar/g) ?? []).length, 2)
|
||||
assert.match(card, /<strong class="p-val"[^>]*>0%<\/strong>/)
|
||||
assert.doesNotMatch(card, /<strong class="p-val"[^>]*>2700K<\/strong>/)
|
||||
assert.ok(html.includes('目标色温 2700K')); assert.ok(!html.includes('van-slider--disabled'))
|
||||
})
|
||||
|
||||
test('only actually supported controls render for onoff-only brightness-only and alternate-range lamps', async () => {
|
||||
const item = standardLight('onoff', { supported_features: 0, effect_list: [] })
|
||||
let html = (await render('/device-control/strip', { haStatus: ref(lightSnapshot(item)) })).html
|
||||
assert.ok(html.includes('目前仅提供开关')); assert.ok(!html.includes('van-slider')); assert.ok(!html.includes('灯光色温调节')); assert.ok(!html.includes('选择灯光模式'))
|
||||
item.entities[0].attributes.supported_color_modes = ['brightness']
|
||||
html = (await render('/device-control/strip', { haStatus: ref(lightSnapshot(item)) })).html
|
||||
assert.ok(html.includes('灯光亮度')); assert.ok(!html.includes('灯光色温调节')); assert.equal((html.match(/van-slider__bar/g) ?? []).length, 1)
|
||||
item.entities[0].attributes = { supported_color_modes: ['color_temp'], min_color_temp_kelvin: 2000, max_color_temp_kelvin: 4000 }
|
||||
html = (await render('/device-control/strip', { haStatus: ref(lightSnapshot(item)) })).html
|
||||
assert.ok(html.includes('2000K 暖光')); assert.ok(html.includes('4000K 冷光')); assert.ok(!html.includes('6500K'))
|
||||
})
|
||||
|
||||
test('offline main light disables standard controls even when an auxiliary entity remains online', async () => {
|
||||
const item = standardLight(); item.entities[0].available = false; item.entities[0].state = 'unavailable'
|
||||
const { html } = await render('/device-control/strip', { haStatus: ref(lightSnapshot(item)) })
|
||||
assert.ok(html.includes('灯光主控当前不可用')); assert.ok(html.includes('van-slider--disabled'))
|
||||
assert.doesNotMatch(html, /<strong class="p-val"[^>]*>0%<\/strong>/)
|
||||
assert.match(html, /<select[^>]*disabled/)
|
||||
const card = html.match(/<section class="device-card"[\s\S]*?<\/section>/)[0]
|
||||
assert.ok(card.match(/<button[^>]*disabled/)); assert.ok(!card.includes('目标色温 2700K'))
|
||||
})
|
||||
|
||||
test('configured scene light composes shared controls with its own fade and wake extensions', async () => {
|
||||
const { html } = await render('/device-control/lamp')
|
||||
for (const text of ['灯光亮度', '灯光色温调节', '灯光模式', '开始助眠渐暗', '晨起唤醒', '灯灭停止按摩']) assert.ok(html.includes(text), text)
|
||||
assert.equal((html.match(/<section class="device-card"/g) ?? []).length, 1)
|
||||
assert.ok(!html.includes('不自动加入舒睡或唤醒场景'))
|
||||
})
|
||||
|
||||
test('mattress detail retains full controls and never renders other devices or scene-wide actions', async () => {
|
||||
const { html } = await render('/device-control/mattress')
|
||||
assert.equal((html.match(/<section class="device-card"/g) ?? []).length, 1)
|
||||
|
||||
Reference in New Issue
Block a user