Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 2 additions & 5 deletions api/lib/ZwaveClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3262,12 +3262,9 @@ class ZwaveClient extends TypedEventEmitter<ZwaveClientEventCallbacks> {
// Determine which properties need updating
const propsToUpdate: Array<
'powerlevel' | 'RFRegion' | 'maxLongRangePowerlevel'
> = ['RFRegion']
> = ['RFRegion', 'powerlevel']

// If powerlevels are in auto mode, refresh them after region change
if (this.cfg.rf?.txPower?.powerlevel === 'auto') {
propsToUpdate.push('powerlevel')
}
// If LR powerlevel is in auto mode, refresh it after region change
if (this.cfg.rf?.maxLongRangePowerlevel === 'auto') {
propsToUpdate.push('maxLongRangePowerlevel')
}
Expand Down
114 changes: 114 additions & 0 deletions test/lib/ZwaveClient.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
import chai, { expect } from 'chai'
import sinon from 'sinon'
import sinonChai from 'sinon-chai'
import { RFRegion } from '@zwave-js/core'

chai.use(sinonChai)

// Mock ZwaveClient with minimal implementation for testing
class MockZwaveClient {
private _driver: any
private cfg: any
public driverReady: boolean = true
public updateControllerNodeProps: sinon.SinonStub

constructor() {
this._driver = {
controller: {
setRFRegion: sinon.stub().resolves(true),
},
}
this.cfg = {
rf: {
txPower: { powerlevel: 5.0 },
maxLongRangePowerlevel: 14,
},
}
this.updateControllerNodeProps = sinon.stub().resolves()
}

async setRFRegion(region: RFRegion): Promise<boolean> {
if (this.driverReady) {
const result = await this._driver.controller.setRFRegion(region)

// Determine which properties need updating
const propsToUpdate: Array<
'powerlevel' | 'RFRegion' | 'maxLongRangePowerlevel'
> = ['RFRegion', 'powerlevel']

// If LR powerlevel is in auto mode, refresh it after region change
if (this.cfg.rf?.maxLongRangePowerlevel === 'auto') {
propsToUpdate.push('maxLongRangePowerlevel')
}

await this.updateControllerNodeProps(null, propsToUpdate)
return result
}

throw new Error('Driver not ready')
}
}

describe('#ZwaveClient', () => {
describe('#setRFRegion()', () => {
let client: MockZwaveClient

beforeEach(() => {
client = new MockZwaveClient()
})

afterEach(() => {
sinon.restore()
})

it('should always update normal powerlevel when region changes', async () => {
// Set powerlevel to a specific value (not auto)
client.cfg.rf.txPower.powerlevel = 5.0

await client.setRFRegion(RFRegion.Europe)

// Verify that updateControllerNodeProps was called with both RFRegion and powerlevel
expect(client.updateControllerNodeProps).to.have.been.calledWith(
null,
['RFRegion', 'powerlevel'],
)
})

it('should update LR powerlevel only when in auto mode', async () => {
// Set LR powerlevel to auto mode
client.cfg.rf.maxLongRangePowerlevel = 'auto'

await client.setRFRegion(RFRegion.USA)

// Verify that updateControllerNodeProps was called with all three properties
expect(client.updateControllerNodeProps).to.have.been.calledWith(
null,
['RFRegion', 'powerlevel', 'maxLongRangePowerlevel'],
)
})

it('should not update LR powerlevel when not in auto mode', async () => {
// Set LR powerlevel to specific value (not auto)
client.cfg.rf.maxLongRangePowerlevel = 14

await client.setRFRegion(RFRegion.Europe)

// Verify that updateControllerNodeProps was called with only RFRegion and powerlevel
expect(client.updateControllerNodeProps).to.have.been.calledWith(
null,
['RFRegion', 'powerlevel'],
)
})

it('should throw error when driver is not ready', async () => {
client.driverReady = false

try {
await client.setRFRegion(RFRegion.Europe)
expect.fail('Should have thrown an error')
} catch (error) {
expect(error.message).to.equal('Driver not ready')
}
})
})
})
Loading