diff --git a/.changeset/bumpy-sheep-sneeze.md b/.changeset/bumpy-sheep-sneeze.md new file mode 100644 index 0000000..0de4f5b --- /dev/null +++ b/.changeset/bumpy-sheep-sneeze.md @@ -0,0 +1,5 @@ +--- +'@viamrobotics/test-widgets': patch +--- + +Fix circular imports diff --git a/.changeset/violet-pets-sleep.md b/.changeset/violet-pets-sleep.md new file mode 100644 index 0000000..ec7e1f5 --- /dev/null +++ b/.changeset/violet-pets-sleep.md @@ -0,0 +1,5 @@ +--- +'@viamrobotics/test-widgets': minor +--- + +Add `IsHoldingSomething` widget diff --git a/src/lib/client-map.ts b/src/lib/client-map.ts index e8c0f57..770be08 100644 --- a/src/lib/client-map.ts +++ b/src/lib/client-map.ts @@ -31,7 +31,7 @@ import { WorldStateStoreClient, } from '@viamrobotics/sdk' -import { getResourceAPI } from './resource.ts' +import { getResourceAPI } from './get-resource-api.ts' export const clientMap = { 'rdk:component:arm': ArmClient, diff --git a/src/lib/components/widgets/do-command/do-command.svelte b/src/lib/components/widgets/do-command/do-command.svelte index e9f1ddc..91840b6 100644 --- a/src/lib/components/widgets/do-command/do-command.svelte +++ b/src/lib/components/widgets/do-command/do-command.svelte @@ -6,7 +6,8 @@ import { PersistedState } from 'runed' import { supportsDoCommand } from '$lib/client-map' - import { getResourceAPI, getResourceKey } from '$lib/resource' + import { getResourceAPI } from '$lib/get-resource-api' + import { getResourceKey } from '$lib/get-resource-key' import ErrorDisplay from '../../error.svelte' import { createDoCommandClient } from './create-do-command-client.svelte' diff --git a/src/lib/components/widgets/gripper/__tests__/is-holding-something.svelte.spec.ts b/src/lib/components/widgets/gripper/__tests__/is-holding-something.svelte.spec.ts new file mode 100644 index 0000000..ea812b4 --- /dev/null +++ b/src/lib/components/widgets/gripper/__tests__/is-holding-something.svelte.spec.ts @@ -0,0 +1,68 @@ +import { render, screen } from '@testing-library/svelte' +import { createResourceQuery } from '@viamrobotics/svelte-sdk' +import { describe, expect, it, vi } from 'vitest' + +import Subject from '../is-holding-something.svelte' + +vi.mock('@viamrobotics/sdk', () => ({ + GripperClient: class {}, +})) + +vi.mock('@viamrobotics/svelte-sdk', () => ({ + createResourceClient: vi.fn(() => ({ current: {} })), + createResourceQuery: vi.fn(() => ({ + data: undefined, + isLoading: true, + isError: false, + error: null, + })), +})) + +describe('Gripper IsHoldingSomething', () => { + it('renders with "Empty" status when not holding', () => { + vi.mocked(createResourceQuery).mockReturnValue({ + data: false, + isLoading: false, + isError: false, + error: null, + } as ReturnType) + + render(Subject, { + props: { partID: 'test-part', resourceName: 'test-gripper' }, + }) + + expect(screen.getByText('Empty')).toBeInTheDocument() + }) + + it('renders with "Holding" status when holding something', () => { + vi.mocked(createResourceQuery).mockReturnValue({ + data: true, + isLoading: false, + isError: false, + error: null, + } as ReturnType) + + render(Subject, { + props: { partID: 'test-part', resourceName: 'test-gripper' }, + }) + + expect(screen.getByText('Holding')).toBeInTheDocument() + }) + + it('creates a resource query for isHoldingSomething with polling', () => { + vi.mocked(createResourceQuery).mockReturnValue({ + data: false, + isLoading: false, + isError: false, + error: null, + } as never) + + render(Subject, { + props: { partID: 'test-part', resourceName: 'test-gripper' }, + }) + + expect(createResourceQuery).toHaveBeenCalledWith(expect.anything(), 'isHoldingSomething', { + refetchInterval: 500, + }) + }) +}) diff --git a/src/lib/components/widgets/gripper/gripper.svelte b/src/lib/components/widgets/gripper/gripper.svelte index 876a4f0..33c7909 100644 --- a/src/lib/components/widgets/gripper/gripper.svelte +++ b/src/lib/components/widgets/gripper/gripper.svelte @@ -8,6 +8,7 @@ import StopButton from '$lib/components/stop-button.svelte' import Grab from './grab.svelte' + import IsHoldingSomething from './is-holding-something.svelte' import Open from './open.svelte' interface Props { @@ -63,6 +64,10 @@ {partID} {resourceName} /> + {/snippet} diff --git a/src/lib/components/widgets/gripper/is-holding-something.svelte b/src/lib/components/widgets/gripper/is-holding-something.svelte new file mode 100644 index 0000000..599c07a --- /dev/null +++ b/src/lib/components/widgets/gripper/is-holding-something.svelte @@ -0,0 +1,57 @@ + + + + +
+ {#if query.data !== undefined} + {#if query.data} + + {:else} + + {/if} + + {:else} + + {/if} +
+
+
diff --git a/src/lib/get-resource-api.ts b/src/lib/get-resource-api.ts new file mode 100644 index 0000000..0bf0547 --- /dev/null +++ b/src/lib/get-resource-api.ts @@ -0,0 +1,4 @@ +import type { ResourceName } from '@viamrobotics/sdk' + +export const getResourceAPI = ({ namespace, type, subtype }: ResourceName) => + `${namespace}:${type}:${subtype}` diff --git a/src/lib/get-resource-key.ts b/src/lib/get-resource-key.ts new file mode 100644 index 0000000..8d221a9 --- /dev/null +++ b/src/lib/get-resource-key.ts @@ -0,0 +1,5 @@ +import type { ResourceName } from '@viamrobotics/sdk' + +import { getResourceAPI } from './get-resource-api.ts' + +export const getResourceKey = (name: ResourceName) => `${getResourceAPI(name)}/${name.name}` diff --git a/src/lib/index.ts b/src/lib/index.ts index b364307..68f40e3 100644 --- a/src/lib/index.ts +++ b/src/lib/index.ts @@ -6,6 +6,7 @@ export { export { clientForResource } from './client-map' export * from './components' +export { getResourceAPI } from './get-resource-api' export { providePip, usePip } from './pip/context.svelte' -export { getResourceAPI, hasWidget, showResourceWidget, widgetForResource } from './resource' +export { hasWidget, showResourceWidget, widgetForResource } from './resource' diff --git a/src/lib/resource.ts b/src/lib/resource.ts index 3839b42..7c9ef68 100644 --- a/src/lib/resource.ts +++ b/src/lib/resource.ts @@ -28,6 +28,7 @@ import { SwitchWidget, VisionServiceWidget, } from './components' +import { getResourceAPI } from './get-resource-api.ts' export type NamedResourceStatus = ResourceStatus & { name: ResourceName @@ -102,11 +103,6 @@ const resourceMap = 'rdk:service:video': [clientMap['rdk:service:video'], undefined, true], } as const -export const getResourceAPI = ({ namespace, type, subtype }: ResourceName) => - `${namespace}:${type}:${subtype}` - -export const getResourceKey = (name: ResourceName) => `${getResourceAPI(name)}/${name.name}` - // sorts resource names by local/remote -> type -> name (alphabetical) to produce a list like // component a // component z diff --git a/src/routes/widgets/card-list-item.svelte b/src/routes/widgets/card-list-item.svelte index 4fd57a1..e868455 100644 --- a/src/routes/widgets/card-list-item.svelte +++ b/src/routes/widgets/card-list-item.svelte @@ -35,13 +35,9 @@ import ResourceIcon from '$lib/components/resource-icon.svelte' import SectionGroup from '$lib/components/section-group.svelte' import DoCommandWidget from '$lib/components/widgets/do-command/do-command.svelte' - import { - getResourceAPI, - getResourceKey, - type NamedResourceStatus, - ResourceStatusText, - widgetForResource, - } from '$lib/resource' + import { getResourceAPI } from '$lib/get-resource-api' + import { getResourceKey } from '$lib/get-resource-key' + import { type NamedResourceStatus, ResourceStatusText, widgetForResource } from '$lib/resource' import { scrollIntoView } from '$lib/scroll-into-view' import ResourceStatus from './resource-status.svelte' diff --git a/src/routes/widgets/card-list.svelte b/src/routes/widgets/card-list.svelte index e47374e..c0deb03 100644 --- a/src/routes/widgets/card-list.svelte +++ b/src/routes/widgets/card-list.svelte @@ -1,6 +1,7 @@