Skip to content

Commit

Permalink
add tests
Browse files Browse the repository at this point in the history
  • Loading branch information
donavanbecker committed Jan 23, 2025
1 parent 3bec1ac commit d8ec68d
Show file tree
Hide file tree
Showing 7 changed files with 377 additions and 217 deletions.
424 changes: 214 additions & 210 deletions package-lock.json

Large diffs are not rendered by default.

12 changes: 6 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@
],
"main": "dist/index.js",
"engines": {
"homebridge": "^1.8.5 || ^2.0.0 || ^2.0.0-beta.23 || ^2.0.0-alpha.37",
"homebridge": "^1.8.5 || ^2.0.0 || ^2.0.0-beta.26 || ^2.0.0-alpha.37",
"node": "^20 || ^22"
},
"scripts": {
Expand All @@ -71,21 +71,21 @@
"lint-docs": "typedoc --emit none --treatWarningsAsErrors"
},
"dependencies": {
"@homebridge/plugin-ui-utils": "^2.0.0",
"@homebridge/plugin-ui-utils": "^2.0.1",
"axios": "1.7.9",
"rxjs": "^7.8.1"
},
"devDependencies": {
"@antfu/eslint-config": "^3.14.0",
"@antfu/eslint-config": "^3.16.0",
"@types/aes-js": "^3.1.4",
"@types/debug": "^4.1.12",
"@types/fs-extra": "^11.0.4",
"@types/mdast": "^4.0.4",
"@types/node": "^22.10.6",
"@types/node": "^22.10.9",
"@types/semver": "^7.5.8",
"@types/source-map-support": "^0.5.10",
"@typhonjs-typedoc/typedoc-theme-dmt": "^0.3.1",
"@vitest/coverage-v8": "^3.0.1",
"@vitest/coverage-v8": "^3.0.4",
"eslint": "^9.18.0",
"eslint-plugin-format": "^1.0.1",
"homebridge": "^1.8.5",
Expand All @@ -95,6 +95,6 @@
"ts-node": "^10.9.2",
"typedoc": "^0.27.6",
"typescript": "^5.7.3",
"vitest": "^3.0.1"
"vitest": "^3.0.4"
}
}
2 changes: 1 addition & 1 deletion src/homebridge-ui/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ interface CustomRequestResponse {
data?: any
}

class PluginUiServer extends HomebridgePluginUiServer {
export class PluginUiServer extends HomebridgePluginUiServer {
public key!: string
public secret!: string
public hostname!: string
Expand Down
19 changes: 19 additions & 0 deletions src/index.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import type { API } from 'homebridge'

import { describe, expect, it, vi } from 'vitest'

import registerPlatform from './index.js'
import { ResideoPlatform } from './platform.js'
import { PLATFORM_NAME, PLUGIN_NAME } from './settings.js'

describe('index.ts', () => {
it('should register the platform with homebridge', () => {
const apiMock: API = {
registerPlatform: vi.fn(),
} as unknown as API

registerPlatform(apiMock)

expect(apiMock.registerPlatform).toHaveBeenCalledWith(PLUGIN_NAME, PLATFORM_NAME, ResideoPlatform)
})
})
108 changes: 108 additions & 0 deletions src/platform.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
import type { API, Logging } from 'homebridge'
import type { MockedFunction } from 'vitest'

import type { ResideoPlatformConfig } from './settings.js'

import axios from 'axios'
import { beforeEach, describe, expect, it, vi } from 'vitest'

import { ResideoPlatform } from './platform.js'

vi.mock('axios')

describe('resideoPlatform', () => {
let platform: ResideoPlatform
let log: Logging
let config: ResideoPlatformConfig
let api: API

beforeEach(() => {
log = {
info: vi.fn(),
warn: vi.fn(),
error: vi.fn(),
debug: vi.fn(),
} as unknown as Logging

config = {
platform: 'Resideo',
name: 'Test Platform',
credentials: {
accessToken: 'testAccessToken',
consumerKey: 'testConsumerKey',
consumerSecret: 'testConsumerSecret',
refreshToken: 'testRefreshToken',
},
options: {
refreshRate: 120,
pushRate: 0.1,
devices: [],
},
}

api = {
hap: {
uuid: {
generate: vi.fn().mockReturnValue('test-uuid'),
},
},
platformAccessory: vi.fn().mockImplementation((name, uuid) => ({
displayName: name,
UUID: uuid,
context: {},
})),
user: {
configPath: vi.fn().mockReturnValue('/path/to/config.json'),
},
on: vi.fn(),
updatePlatformAccessories: vi.fn(),
} as unknown as API

platform = new ResideoPlatform(log, config, api)
})

it('should initialize platform with given config', () => {
expect(platform.config.name).toBe('Test Platform')
expect(platform.config.credentials?.accessToken).toBe('testAccessToken')
})

it('should verify config correctly', () => {
expect(() => platform.verifyConfig()).not.toThrow()
})

it('should throw error if refresh rate is less than 30', () => {
if (platform.config.options) {
platform.config.options.refreshRate = 20
}
expect(() => platform.verifyConfig()).toThrow('Refresh Rate must be above 30 seconds.')
})

it('should refresh access token', async () => {
(axios.post as MockedFunction<typeof axios.post>).mockResolvedValue({
data: {
access_token: 'newAccessToken',
refresh_token: 'newRefreshToken',
},
})

await platform.refreshAccessToken()

expect(platform.config.credentials?.accessToken).toBe('newAccessToken')
expect(platform.config.credentials?.refreshToken).toBe('newRefreshToken')
})

it('should discover locations', async () => {
const mockLocations = [{ locationID: '1', name: 'Location 1', devices: [] }];
(axios.get as MockedFunction<typeof axios.get>).mockResolvedValue({ data: mockLocations })

const locations = await platform.discoverlocations()

expect(locations).toEqual(mockLocations)
})

it('should handle error during location discovery', async () => {
(axios.get as MockedFunction<typeof axios.get>).mockRejectedValue(new Error('Network Error'))

await expect(platform.discoverlocations()).rejects.toThrow('Network Error')
})
})
9 changes: 9 additions & 0 deletions src/settings.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { describe, expect, it } from 'vitest'

import { PLATFORM_NAME } from './settings.js'

describe('settings', () => {
it('should have the correct PLATFORM_NAME', () => {
expect(PLATFORM_NAME).toBe('Resideo')
})
})
20 changes: 20 additions & 0 deletions src/utils.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { describe, expect, it } from 'vitest'

import { toCelsius } from './utils.js'

describe('toCelsius', () => {
it('should return the same value if the unit is 0 (Celsius)', () => {
expect(toCelsius(25, 0)).toBe(25)
})

it('should convert Fahrenheit to Celsius correctly', () => {
expect(toCelsius(32, 1)).toBe(0) // 32°F is 0°C
expect(toCelsius(68, 1)).toBe(20) // 68°F is 20°C
expect(toCelsius(100, 1)).toBe(37.5) // 100°F is 37.5°C
})

it('should round to the nearest 0.5 degree', () => {
expect(toCelsius(33, 1)).toBe(0.5) // 33°F is 0.5°C
expect(toCelsius(34, 1)).toBe(1) // 34°F is 1°C
})
})

0 comments on commit d8ec68d

Please sign in to comment.