-
Notifications
You must be signed in to change notification settings - Fork 110
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
refactor: move devicepreferences:translations:create command to yargs
- Loading branch information
Showing
10 changed files
with
295 additions
and
92 deletions.
There are no files selected for viewing
33 changes: 0 additions & 33 deletions
33
packages/cli/src/commands/devicepreferences/translations/create.ts
This file was deleted.
Oops, something went wrong.
21 changes: 0 additions & 21 deletions
21
packages/cli/src/lib/commands/devicepreferences/translations-util.ts
This file was deleted.
Oops, something went wrong.
118 changes: 118 additions & 0 deletions
118
src/__tests__/commands/devicepreferences/translations/create.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,118 @@ | ||
import { jest } from '@jest/globals' | ||
|
||
import type { ArgumentsCamelCase, Argv } from 'yargs' | ||
|
||
import type { | ||
DevicePreferencesEndpoint, | ||
PreferenceLocalization, | ||
SmartThingsClient, | ||
} from '@smartthings/core-sdk' | ||
|
||
import type { CommandArgs } from '../../../../commands/devicepreferences/translations/create.js' | ||
import type { | ||
APIOrganizationCommand, | ||
APIOrganizationCommandFlags, | ||
apiOrganizationCommand, | ||
apiOrganizationCommandBuilder, | ||
} from '../../../../lib/command/api-organization-command.js' | ||
import type { | ||
inputAndOutputItem, | ||
inputAndOutputItemBuilder, | ||
} from '../../../../lib/command/basic-io.js' | ||
import type { chooseDevicePreference } from '../../../../lib/command/util/devicepreferences-util.js' | ||
import { | ||
tableFieldDefinitions, | ||
} from '../../../../lib/command/util/devicepreferences/translations-util.js' | ||
import { buildArgvMock, buildArgvMockStub } from '../../../test-lib/builder-mock.js' | ||
|
||
|
||
const apiOrganizationCommandMock = jest.fn<typeof apiOrganizationCommand>() | ||
const apiOrganizationCommandBuilderMock = jest.fn<typeof apiOrganizationCommandBuilder>() | ||
jest.unstable_mockModule('../../../../lib/command/api-organization-command.js', () => ({ | ||
apiOrganizationCommand: apiOrganizationCommandMock, | ||
apiOrganizationCommandBuilder: apiOrganizationCommandBuilderMock, | ||
})) | ||
|
||
const inputAndOutputItemMock = jest.fn<typeof inputAndOutputItem>() | ||
const inputAndOutputItemBuilderMock = jest.fn<typeof inputAndOutputItemBuilder>() | ||
jest.unstable_mockModule('../../../../lib/command/basic-io.js', () => ({ | ||
inputAndOutputItem: inputAndOutputItemMock, | ||
inputAndOutputItemBuilder: inputAndOutputItemBuilderMock, | ||
})) | ||
|
||
const chooseDevicePreferenceMock = jest.fn<typeof chooseDevicePreference>() | ||
jest.unstable_mockModule('../../../../lib/command/util/devicepreferences-util.js', () => ({ | ||
chooseDevicePreference: chooseDevicePreferenceMock, | ||
})) | ||
|
||
|
||
const { | ||
default: cmd, | ||
} = await import('../../../../commands/devicepreferences/translations/create.js') | ||
|
||
|
||
test('builder', () => { | ||
const yargsMock = buildArgvMockStub<object>() | ||
const { | ||
yargsMock: apiOrganizationCommandBuilderArgvMock, | ||
positionalMock, | ||
exampleMock, | ||
argvMock, | ||
} = buildArgvMock<APIOrganizationCommandFlags, CommandArgs>() | ||
|
||
apiOrganizationCommandBuilderMock.mockReturnValueOnce(apiOrganizationCommandBuilderArgvMock) | ||
inputAndOutputItemBuilderMock.mockReturnValueOnce(argvMock) | ||
|
||
const builder = cmd.builder as (yargs: Argv<object>) => Argv<CommandArgs> | ||
|
||
expect(builder(yargsMock)).toBe(argvMock) | ||
|
||
expect(apiOrganizationCommandBuilderMock).toHaveBeenCalledExactlyOnceWith(yargsMock) | ||
expect(inputAndOutputItemBuilderMock) | ||
.toHaveBeenCalledExactlyOnceWith(apiOrganizationCommandBuilderArgvMock) | ||
|
||
expect(exampleMock).toHaveBeenCalledTimes(1) | ||
expect(positionalMock).toHaveBeenCalledTimes(1) | ||
}) | ||
|
||
test('handler', async () => { | ||
const apiDevicePreferencesCreateTranslationsMock = | ||
jest.fn<typeof DevicePreferencesEndpoint.prototype['createTranslations']>() | ||
|
||
const clientMock = { | ||
devicePreferences: { | ||
createTranslations: apiDevicePreferencesCreateTranslationsMock, | ||
}, | ||
} as unknown as SmartThingsClient | ||
const command = { | ||
client: clientMock, | ||
} as APIOrganizationCommand<CommandArgs> | ||
apiOrganizationCommandMock.mockResolvedValueOnce(command) | ||
chooseDevicePreferenceMock.mockResolvedValueOnce('chosen-id') | ||
|
||
const inputArgv = { | ||
profile: 'default', | ||
devicePreferenceId: 'argv-id', | ||
} as unknown as ArgumentsCamelCase<CommandArgs> | ||
await expect(cmd.handler(inputArgv)).resolves.not.toThrow() | ||
|
||
expect(apiOrganizationCommandMock).toHaveBeenCalledExactlyOnceWith(inputArgv) | ||
expect(chooseDevicePreferenceMock).toHaveBeenCalledExactlyOnceWith(command, 'argv-id') | ||
expect(inputAndOutputItemMock).toHaveBeenCalledExactlyOnceWith( | ||
command, | ||
{ tableFieldDefinitions }, | ||
expect.any(Function), | ||
) | ||
|
||
const create = inputAndOutputItemMock.mock.calls[0][2] | ||
|
||
const translationCreate = { description: 'Translation To Create' } as PreferenceLocalization | ||
const createdTranslation = { description: 'Created Translation' } as PreferenceLocalization | ||
|
||
apiDevicePreferencesCreateTranslationsMock.mockResolvedValueOnce(createdTranslation) | ||
|
||
expect(await create(undefined, translationCreate)).toBe(createdTranslation) | ||
|
||
expect(apiDevicePreferencesCreateTranslationsMock) | ||
.toHaveBeenCalledExactlyOnceWith('chosen-id', translationCreate) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
53 changes: 53 additions & 0 deletions
53
src/__tests__/lib/command/util/devicepreferences/translations-util.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
import type { PreferenceLocalization } from '@smartthings/core-sdk' | ||
|
||
import { ValueTableFieldDefinition } from '../../../../../lib/table-generator.js' | ||
import { | ||
tableFieldDefinitions, | ||
} from '../../../../../lib/command/util/devicepreferences/translations-util.js' | ||
|
||
|
||
const unpopulatedOptions: (Record<string, { label: string }> | null | undefined)[] = [ | ||
null, | ||
undefined, | ||
{}, | ||
] | ||
|
||
const populatedOptions: ({ | ||
options: Record<string, { label: string }> | ||
expected: string | ||
})[] = [ | ||
{ options: { key: { label: 'Translation' } }, expected: 'key: Translation' }, | ||
{ | ||
options: { key1: { label: 'Translation 1' }, key2: { label: 'Translation 2' } }, | ||
expected: 'key1: Translation 1\nkey2: Translation 2', | ||
}, | ||
] | ||
|
||
const definition = (tableFieldDefinitions[3] as ValueTableFieldDefinition<PreferenceLocalization>) | ||
|
||
describe('options include function', () => { | ||
const include = definition.include | ||
|
||
it.each(unpopulatedOptions)('returns false for unpopulated options', (options) => { | ||
expect(include?.({ options } as PreferenceLocalization)).toBeFalse() | ||
}) | ||
|
||
it.each(populatedOptions)('returns true for populated options', ({ options }) => { | ||
expect(include?.({ options } as PreferenceLocalization)).toBeTrue() | ||
}) | ||
}) | ||
|
||
describe('options value function', () => { | ||
const value = definition.value | ||
|
||
it.each(unpopulatedOptions)('returns falsy for unpopulated options', (options) => { | ||
expect(value?.({ options } as PreferenceLocalization)).toBeFalsy() | ||
}) | ||
|
||
it.each(populatedOptions)( | ||
'returns string representation for populated options', | ||
({ options, expected }) => { | ||
expect(value?.({ options } as PreferenceLocalization)).toBe(expected) | ||
}, | ||
) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
import { ArgumentsCamelCase, Argv, CommandModule } from 'yargs' | ||
|
||
import { PreferenceLocalization } from '@smartthings/core-sdk' | ||
|
||
import { | ||
apiOrganizationCommand, | ||
apiOrganizationCommandBuilder, | ||
type APIOrganizationCommandFlags, | ||
} from '../../../lib/command/api-organization-command.js' | ||
import { | ||
inputAndOutputItem, | ||
inputAndOutputItemBuilder, | ||
InputAndOutputItemFlags, | ||
} from '../../../lib/command/basic-io.js' | ||
import { chooseDevicePreference } from '../../../lib/command/util/devicepreferences-util.js' | ||
import { | ||
tableFieldDefinitions, | ||
} from '../../../lib/command/util/devicepreferences/translations-util.js' | ||
|
||
|
||
export type CommandArgs = | ||
& APIOrganizationCommandFlags | ||
& InputAndOutputItemFlags | ||
& { | ||
devicePreferenceId?: string | ||
} | ||
|
||
const command = 'devicepreferences:translations:create [device-preference-id]' | ||
|
||
const describe = 'create a translation for a device preference' | ||
|
||
const builder = (yargs: Argv): Argv<CommandArgs> => | ||
inputAndOutputItemBuilder(apiOrganizationCommandBuilder(yargs)) | ||
.positional('device-preference-id', { describe: 'device preference id', type: 'string' }) | ||
.example([ | ||
[ | ||
'$0 devicepreferences:translations:create -i preferenceTranslation.json', | ||
'create a translation as defined in preferenceTranslation.json', | ||
], | ||
]) | ||
|
||
const handler = async (argv: ArgumentsCamelCase<CommandArgs>): Promise<void> => { | ||
const command = await apiOrganizationCommand(argv) | ||
|
||
const preferenceId = await chooseDevicePreference(command, argv.devicePreferenceId) | ||
|
||
await inputAndOutputItem<PreferenceLocalization, PreferenceLocalization>( | ||
command, | ||
{ tableFieldDefinitions }, | ||
(_, translation) => | ||
command.client.devicePreferences.createTranslations(preferenceId, translation), | ||
) | ||
} | ||
|
||
const cmd: CommandModule<object, CommandArgs> = { command, describe, builder, handler } | ||
export default cmd |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.