Skip to content
Merged
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
36 changes: 0 additions & 36 deletions packages/edge/src/__tests__/commands/edge/channels/delete.test.ts

This file was deleted.

52 changes: 0 additions & 52 deletions packages/edge/src/commands/edge/channels/create.ts

This file was deleted.

24 changes: 0 additions & 24 deletions packages/edge/src/commands/edge/channels/delete.ts

This file was deleted.

86 changes: 86 additions & 0 deletions src/__tests__/commands/edge/channels/delete.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import { jest } from '@jest/globals'

import type { ArgumentsCamelCase, Argv } from 'yargs'

import { ChannelsEndpoint } from '@smartthings/core-sdk'

import type { CommandArgs } from '../../../../commands/edge/channels/delete.js'
import type { APICommand, APICommandFlags } from '../../../../lib/command/api-command.js'
import type { CLIConfig, resetManagedConfigKey } from '../../../../lib/cli-config.js'
import type { chooseChannel } from '../../../../lib/command/util/edge/channels-choose.js'
import { apiCommandMocks } from '../../../test-lib/api-command-mock.js'
import { buildArgvMock } from '../../../test-lib/builder-mock.js'


const resetManagedConfigKeyMock = jest.fn<typeof resetManagedConfigKey>()
jest.unstable_mockModule('../../../../lib/cli-config.js', () => ({
resetManagedConfigKey: resetManagedConfigKeyMock,
}))

const { apiCommandMock, apiCommandBuilderMock, apiDocsURLMock } = apiCommandMocks('../../../..')

const chooseChannelMock = jest.fn<typeof chooseChannel>().mockResolvedValue('chosen-channel-id')
jest.unstable_mockModule('../../../../lib/command/util/edge/channels-choose.js', () => ({
chooseChannel: chooseChannelMock,
}))

const consoleLogSpy = jest.spyOn(console, 'log').mockImplementation(() => { /* do nothing */ })


const { default: cmd } = await import('../../../../commands/edge/channels/delete.js')


test('builder', () => {
const {
yargsMock,
positionalMock,
optionMock,
exampleMock,
epilogMock,
argvMock,
} = buildArgvMock<APICommandFlags, CommandArgs>()

apiCommandBuilderMock.mockReturnValue(argvMock)

const builder = cmd.builder as (yargs: Argv<object>) => Argv<CommandArgs>
expect(builder(yargsMock)).toBe(argvMock)

expect(apiCommandBuilderMock).toHaveBeenCalledExactlyOnceWith(yargsMock)

expect(positionalMock).toHaveBeenCalledTimes(1)
expect(optionMock).toHaveBeenCalledTimes(0)
expect(exampleMock).toHaveBeenCalledTimes(1)
expect(apiDocsURLMock).toHaveBeenCalledTimes(1)
expect(epilogMock).toHaveBeenCalledTimes(1)
})

test('handler', async () => {
const cliConfig = { profile: {} } as CLIConfig
const inputArgv = {
profile: 'default',
id: 'cmd-line-id',
} as ArgumentsCamelCase<CommandArgs>
const apiChannelsDeleteMock = jest.fn<typeof ChannelsEndpoint.prototype.delete>()
const command = {
client: {
channels: {
delete: apiChannelsDeleteMock,
},
},
cliConfig,
} as unknown as APICommand
apiCommandMock.mockResolvedValueOnce(command)

await expect(cmd.handler(inputArgv)).resolves.not.toThrow()

expect(apiCommandMock).toHaveBeenCalledExactlyOnceWith(inputArgv)
expect(chooseChannelMock).toHaveBeenCalledExactlyOnceWith(command, 'Choose a channel to delete.', 'cmd-line-id')
expect(apiChannelsDeleteMock).toHaveBeenCalledExactlyOnceWith('chosen-channel-id')
expect(resetManagedConfigKeyMock).toHaveBeenCalledExactlyOnceWith(cliConfig, 'defaultChannel', expect.any(Function))
expect(consoleLogSpy).toHaveBeenCalledWith('Channel chosen-channel-id deleted.')

const resetPredicate = resetManagedConfigKeyMock.mock.calls[0][2]

expect(resetPredicate?.('chosen-channel-id')).toBe(true)
expect(resetPredicate?.('different-channel-id')).toBe(false)
})
78 changes: 78 additions & 0 deletions src/commands/edge/channels/create.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import inquirer from 'inquirer'
import { type ArgumentsCamelCase, type Argv, type CommandModule } from 'yargs'

import { type Channel, type ChannelCreate } from '@smartthings/core-sdk'

import { apiCommand, apiCommandBuilder, type APICommandFlags, apiDocsURL } from '../../../lib/command/api-command.js'
import {
inputAndOutputItem,
inputAndOutputItemBuilder,
type InputAndOutputItemFlags,
} from '../../../lib/command/input-and-output-item.js'
import { type TableFieldDefinition } from '../../../lib/table-generator.js'
import { userInputProcessor } from '../../../lib/command/input-processor.js'


export type CommandArgs =
& APICommandFlags
& InputAndOutputItemFlags

const command = 'edge:channels:create'

const describe = 'create a channel'

const tableFieldDefinitions: TableFieldDefinition<Channel>[] = ['channelId', 'name', 'description',
'type', 'termsOfServiceUrl', 'createdDate', 'lastModifiedDate']

const builder = (yargs: Argv): Argv<CommandArgs> =>
inputAndOutputItemBuilder(apiCommandBuilder(yargs))
.example([
[
'$0 edge:channels:create',
'create a channel from prompted input',
],
[
'$0 edge:channels:create --input channel.json',
'create a channel as defined in channel.json',
],
])
.epilog(apiDocsURL('createChannel'))

const handler = async (argv: ArgumentsCamelCase<CommandArgs>): Promise<void> => {
const command = await apiCommand(argv)

const getInputFromUser = async (): Promise<ChannelCreate> => {
const name = (await inquirer.prompt({
type: 'input',
name: 'name',
message: 'Channel name:',
validate: input => input ? true : 'name is required',
})).name as string

const description = (await inquirer.prompt({
type: 'input',
name: 'description',
message: 'Channel description:',
validate: input => input ? true : 'description is required',
})).description as string

const termsOfServiceUrl = (await inquirer.prompt({
type: 'input',
name: 'termsOfServiceUrl',
message: 'Channel terms of service URL:',
validate: input => input ? true : 'termsOfServiceUrl is required',
})).termsOfServiceUrl as string

return { name, description, termsOfServiceUrl, type: 'DRIVER' }
}

await inputAndOutputItem<ChannelCreate, Channel>(
command,
{ tableFieldDefinitions },
(_, input: ChannelCreate) => command.client.channels.create(input),
userInputProcessor(() => getInputFromUser()),
)
}

const cmd: CommandModule<object, CommandArgs> = { command, describe, builder, handler }
export default cmd
42 changes: 42 additions & 0 deletions src/commands/edge/channels/delete.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { type ArgumentsCamelCase, type Argv, type CommandModule } from 'yargs'

import { resetManagedConfigKey } from '../../../lib/cli-config.js'
import { apiCommand, apiCommandBuilder, apiDocsURL, type APICommandFlags } from '../../../lib/command/api-command.js'
import { chooseChannel } from '../../../lib/command/util/edge/channels-choose.js'


export type CommandArgs =
& APICommandFlags
& {
id?: string
}

const command = 'edge:channels:delete [id]'

const describe = 'delete a channel'

const builder = (yargs: Argv): Argv<CommandArgs> =>
apiCommandBuilder(yargs)
.positional('id', { describe: 'channel id', type: 'string' })
.example([
['$0 edge:channels:delete', 'choose the channel to delete from a list'],
[
'$0 edge:channels:delete 636169e4-8b9f-4438-a941-953b0d617231',
'delete the channel with the specified id',
],
])
.epilog(apiDocsURL('deleteChannel'))


const handler = async (argv: ArgumentsCamelCase<CommandArgs>): Promise<void> => {
const command = await apiCommand(argv)

const id = await chooseChannel(command, 'Choose a channel to delete.', argv.id)
await command.client.channels.delete(id)
console.log(`command.cliConfig = ${JSON.stringify(command.cliConfig)}`)
await resetManagedConfigKey(command.cliConfig, 'defaultChannel', value => value === id)
console.log(`Channel ${id} deleted.`)
}

const cmd: CommandModule<object, CommandArgs> = { command, describe, builder, handler }
export default cmd
4 changes: 4 additions & 0 deletions src/commands/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ import devicesHistoryCommand from './devices/history.js'
import devicesPreferencesCommand from './devices/preferences.js'
import devicesUpdateCommand from './devices/update.js'
import edgeChannelsCommand from './edge/channels.js'
import edgeChannelsCreateCommand from './edge/channels/create.js'
import edgeChannelsDeleteCommand from './edge/channels/delete.js'
import edgeChannelsInvitesCommand from './edge/channels/invites.js'
import edgeDriversCommand from './edge/drivers.js'
import edgeDriversDefaultCommand from './edge/drivers/default.js'
Expand Down Expand Up @@ -136,6 +138,8 @@ export const commands: CommandModule<object, any>[] = [
devicesPreferencesCommand,
devicesUpdateCommand,
edgeChannelsCommand,
edgeChannelsCreateCommand,
edgeChannelsDeleteCommand,
edgeChannelsInvitesCommand,
edgeDriversCommand,
edgeDriversDefaultCommand,
Expand Down
1 change: 0 additions & 1 deletion src/commands/locations/modes/create.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ const builder = (yargs: Argv): Argv<CommandArgs> =>
])
.epilog(apiDocsURL('createMode'))


const handler = async (argv: ArgumentsCamelCase<CommandArgs>): Promise<void> => {
const command = await apiCommand(argv)

Expand Down