Skip to content

Commit

Permalink
fix: fix failure to output JSON or YAML history
Browse files Browse the repository at this point in the history
  • Loading branch information
rossiam committed Mar 21, 2023
1 parent f18d75c commit 0b7934b
Show file tree
Hide file tree
Showing 5 changed files with 60 additions and 42 deletions.
5 changes: 5 additions & 0 deletions .changeset/clever-trees-hang.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@smartthings/cli": patch
---

fixed bug when outputting JSON or YAML device or location history
49 changes: 23 additions & 26 deletions packages/cli/src/__tests__/commands/devices/history.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import {
calculateOutputFormat,
chooseDevice,
IOFormat,
jsonFormatter,
writeOutput,
} from '@smartthings/cli-lib'
import { Device, DeviceActivity, DevicesEndpoint, HistoryEndpoint, PaginatedList, SmartThingsClient } from '@smartthings/core-sdk'
Expand All @@ -14,29 +13,14 @@ import { calculateRequestLimit, getHistory, writeDeviceEventsTable } from '../..
jest.mock('../../../lib/commands/history-util')

describe('DeviceHistoryCommand', () => {
const chooseDeviceMock = jest.mocked(chooseDevice).mockResolvedValue('deviceId')
const getDeviceSpy = jest.spyOn(DevicesEndpoint.prototype, 'get').mockImplementation()
const historySpy = jest.spyOn(HistoryEndpoint.prototype, 'devices').mockImplementation()
const deviceSelectionMock = jest.mocked(chooseDevice).mockResolvedValue('deviceId')
const calculateOutputFormatMock = jest.mocked(calculateOutputFormat).mockReturnValue(IOFormat.COMMON)
const writeDeviceEventsTableMock = jest.mocked(writeDeviceEventsTable)
const calculateHistoryRequestLimitMock = jest.mocked(calculateRequestLimit)
const calculateRequestLimitMock = jest.mocked(calculateRequestLimit)
const getHistoryMock = jest.mocked(getHistory)

it('prompts user to select device', async () => {
getDeviceSpy.mockResolvedValueOnce({ locationId: 'locationId' } as Device)
historySpy.mockResolvedValueOnce({
items: [],
hasNext: (): boolean => false,
} as unknown as PaginatedList<DeviceActivity>)
await expect(DeviceHistoryCommand.run(['deviceId'])).resolves.not.toThrow()

expect(deviceSelectionMock).toHaveBeenCalledWith(
expect.any(DeviceHistoryCommand),
'deviceId',
{ allowIndex: true },
)
})

it('queries history and writes event table interactively', async () => {
getDeviceSpy.mockResolvedValueOnce({ locationId: 'locationId' } as Device)
historySpy.mockResolvedValueOnce({
Expand All @@ -46,8 +30,13 @@ describe('DeviceHistoryCommand', () => {

await expect(DeviceHistoryCommand.run(['deviceId'])).resolves.not.toThrow()

expect(calculateRequestLimitMock).toHaveBeenCalledTimes(1)
expect(calculateRequestLimitMock).toHaveBeenCalledWith(20)
expect(chooseDeviceMock).toHaveBeenCalledTimes(1)
expect(chooseDeviceMock).toHaveBeenCalledWith(expect.any(DeviceHistoryCommand), 'deviceId', { allowIndex: true })
expect(getDeviceSpy).toHaveBeenCalledTimes(1)
expect(getDeviceSpy).toHaveBeenCalledWith('deviceId')
expect(calculateOutputFormatMock).toHaveBeenCalledTimes(1)
expect(historySpy).toHaveBeenCalledTimes(1)
expect(historySpy).toHaveBeenCalledWith({
deviceId: 'deviceId',
Expand All @@ -56,23 +45,28 @@ describe('DeviceHistoryCommand', () => {
expect(writeDeviceEventsTableMock).toHaveBeenCalledTimes(1)
})

it('queries history and write event table directly', async () => {
const buildOutputFormatterMock = jest.mocked(buildOutputFormatter)
it('writes non-table output when specified', async () => {
const outputFormatterMock = jest.fn().mockReturnValueOnce('formatted output')
const buildOutputFormatterMock = jest.mocked(buildOutputFormatter<DeviceActivity[]>)
const writeOutputMock = jest.mocked(writeOutput)

calculateHistoryRequestLimitMock.mockReturnValueOnce(20)
const items = [{ deviceId: 'device-1' }] as DeviceActivity[]

calculateRequestLimitMock.mockReturnValueOnce(20)
getDeviceSpy.mockResolvedValueOnce({ locationId: 'locationId' } as Device)
historySpy.mockResolvedValueOnce({
items: [],
hasNext: (): boolean => false,
} as unknown as PaginatedList<DeviceActivity>)
calculateOutputFormatMock.mockReturnValueOnce(IOFormat.JSON)
buildOutputFormatterMock.mockReturnValueOnce(jsonFormatter(4))
buildOutputFormatterMock.mockReturnValueOnce(outputFormatterMock)
getHistoryMock.mockResolvedValueOnce(items)

await expect(DeviceHistoryCommand.run(['deviceId'])).resolves.not.toThrow()

expect(calculateRequestLimitMock).toHaveBeenCalledTimes(1)
expect(calculateRequestLimitMock).toHaveBeenCalledWith(20)
expect(chooseDeviceMock).toHaveBeenCalledTimes(1)
expect(chooseDeviceMock).toHaveBeenCalledWith(expect.any(DeviceHistoryCommand), 'deviceId', { allowIndex: true })
expect(getDeviceSpy).toHaveBeenCalledTimes(1)
expect(getDeviceSpy).toHaveBeenCalledWith('deviceId')
expect(calculateOutputFormatMock).toHaveBeenCalledTimes(1)
expect(getHistoryMock).toHaveBeenCalledTimes(1)
expect(getHistoryMock).toHaveBeenCalledWith(
expect.any(SmartThingsClient),
Expand All @@ -84,7 +78,10 @@ describe('DeviceHistoryCommand', () => {
}),
)
expect(buildOutputFormatterMock).toHaveBeenCalledTimes(1)
expect(outputFormatterMock).toHaveBeenCalledTimes(1)
expect(outputFormatterMock).toHaveBeenCalledWith(items)
expect(writeOutputMock).toHaveBeenCalledTimes(1)
expect(writeOutputMock).toHaveBeenCalledWith('formatted output', undefined)

expect(historySpy).toHaveBeenCalledTimes(0)
expect(writeDeviceEventsTableMock).toHaveBeenCalledTimes(0)
Expand Down
36 changes: 24 additions & 12 deletions packages/cli/src/__tests__/commands/locations/history.test.ts
Original file line number Diff line number Diff line change
@@ -1,25 +1,27 @@
import { DeviceActivity, HistoryEndpoint, PaginatedList, SmartThingsClient } from '@smartthings/core-sdk'

import {
buildOutputFormatter,
calculateOutputFormat,
IOFormat,
jsonFormatter,
writeOutput,
} from '@smartthings/cli-lib'
import { DeviceActivity, HistoryEndpoint, PaginatedList, SmartThingsClient } from '@smartthings/core-sdk'

import LocationHistoryCommand from '../../../commands/locations/history'
import { calculateRequestLimit, getHistory, writeDeviceEventsTable } from '../../../lib/commands/history-util'
import { chooseLocation } from '../../../commands/locations'
import LocationDeviceHistoryCommand from '../../../commands/locations/history'


jest.mock('../../../lib/commands/history-util')
jest.mock('../../../commands/locations')

describe('LocationHistoryCommand', () => {
const mockChooseLocation = jest.mocked(chooseLocation).mockResolvedValue('locationId')
const chooseLocationMock = jest.mocked(chooseLocation).mockResolvedValue('locationId')
const historySpy = jest.spyOn(HistoryEndpoint.prototype, 'devices').mockImplementation()
const calculateOutputFormatMock = jest.mocked(calculateOutputFormat).mockReturnValue(IOFormat.COMMON)
const writeDeviceEventsTableMock = jest.mocked(writeDeviceEventsTable)
const calculateHistoryRequestLimitMock = jest.mocked(calculateRequestLimit)
const calculateRequestLimitMock = jest.mocked(calculateRequestLimit)
const getHistoryMock = jest.mocked(getHistory)

it('queries history and writes event table interactively', async () => {
Expand All @@ -30,7 +32,10 @@ describe('LocationHistoryCommand', () => {

await expect(LocationHistoryCommand.run(['locationId'])).resolves.not.toThrow()

expect(mockChooseLocation).toHaveBeenCalledTimes(1)
expect(calculateRequestLimitMock).toHaveBeenCalledTimes(1)
expect(calculateRequestLimitMock).toHaveBeenCalledWith(20)
expect(chooseLocationMock).toHaveBeenCalledTimes(1)
expect(chooseLocationMock).toHaveBeenCalledWith(expect.any(LocationDeviceHistoryCommand), 'locationId', true, true)
expect(calculateOutputFormatMock).toHaveBeenCalledTimes(1)
expect(historySpy).toHaveBeenCalledTimes(1)
expect(historySpy).toHaveBeenCalledWith({
Expand All @@ -41,18 +46,23 @@ describe('LocationHistoryCommand', () => {
})

it('queries history and write event table directly', async () => {
const buildOutputFormatterMock = jest.mocked(buildOutputFormatter)
const outputFormatterMock = jest.fn().mockReturnValueOnce('formatted output')
const buildOutputFormatterMock = jest.mocked(buildOutputFormatter<DeviceActivity[]>)
const writeOutputMock = jest.mocked(writeOutput)

calculateHistoryRequestLimitMock.mockReturnValueOnce(20)
const items = [{ deviceId: 'device-1' }] as DeviceActivity[]

calculateRequestLimitMock.mockReturnValueOnce(20)
calculateOutputFormatMock.mockReturnValueOnce(IOFormat.JSON)
buildOutputFormatterMock.mockReturnValueOnce(jsonFormatter(4))
buildOutputFormatterMock.mockReturnValueOnce(outputFormatterMock)
getHistoryMock.mockResolvedValueOnce(items)

await expect(LocationHistoryCommand.run(['locationId'])).resolves.not.toThrow()

expect(calculateHistoryRequestLimitMock).toHaveBeenCalledTimes(1)
expect(calculateHistoryRequestLimitMock).toHaveBeenCalledWith(20)
expect(mockChooseLocation).toHaveBeenCalledTimes(1)
expect(calculateRequestLimitMock).toHaveBeenCalledTimes(1)
expect(calculateRequestLimitMock).toHaveBeenCalledWith(20)
expect(chooseLocationMock).toHaveBeenCalledTimes(1)
expect(chooseLocationMock).toHaveBeenCalledWith(expect.any(LocationDeviceHistoryCommand), 'locationId', true, true)
expect(calculateOutputFormatMock).toHaveBeenCalledTimes(1)
expect(getHistoryMock).toHaveBeenCalledTimes(1)
expect(getHistoryMock).toHaveBeenCalledWith(
Expand All @@ -63,9 +73,11 @@ describe('LocationHistoryCommand', () => {
locationId: 'locationId',
}),
)
expect(writeDeviceEventsTableMock).toHaveBeenCalledTimes(0)
expect(buildOutputFormatterMock).toHaveBeenCalledTimes(1)
expect(outputFormatterMock).toHaveBeenCalledTimes(1)
expect(outputFormatterMock).toHaveBeenCalledWith(items)
expect(writeOutputMock).toHaveBeenCalledTimes(1)
expect(writeOutputMock).toHaveBeenCalledWith('formatted output', undefined)

expect(historySpy).toHaveBeenCalledTimes(0)
expect(writeDeviceEventsTableMock).toHaveBeenCalledTimes(0)
Expand Down
6 changes: 4 additions & 2 deletions packages/cli/src/commands/devices/history.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { DeviceActivity } from '@smartthings/core-sdk'

import {
APICommand,
buildOutputFormatter,
Expand Down Expand Up @@ -53,8 +55,8 @@ export default class DeviceHistoryCommand extends APICommand<typeof DeviceHistor
const history = await this.client.history.devices(params)
await writeDeviceEventsTable(this, history, { utcTimeFormat: this.flags.utc })
} else {
const items = getHistory(this.client, limit, perRequestLimit, params)
const outputFormatter = buildOutputFormatter(this)
const items = await getHistory(this.client, limit, perRequestLimit, params)
const outputFormatter = buildOutputFormatter<DeviceActivity[]>(this)
await writeOutput(outputFormatter(items), this.flags.output)
}
}
Expand Down
6 changes: 4 additions & 2 deletions packages/cli/src/commands/locations/history.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { DeviceActivity } from '@smartthings/core-sdk'

import {
APICommand,
buildOutputFormatter,
Expand Down Expand Up @@ -51,8 +53,8 @@ export default class LocationDeviceHistoryCommand extends APICommand<typeof Loca
const history = await this.client.history.devices(params)
await writeDeviceEventsTable(this, history, { includeName: true, utcTimeFormat: this.flags.utc })
} else {
const items = getHistory(this.client, limit, perRequestLimit, params)
const outputFormatter = buildOutputFormatter(this)
const items = await getHistory(this.client, limit, perRequestLimit, params)
const outputFormatter = buildOutputFormatter<DeviceActivity[]>(this)
await writeOutput(outputFormatter(items), this.flags.output)
}
}
Expand Down

0 comments on commit 0b7934b

Please sign in to comment.