Skip to content

Commit

Permalink
Test: add createToastContext fixture (viamrobotics#550)
Browse files Browse the repository at this point in the history
  • Loading branch information
mcous authored Aug 2, 2024
1 parent 1ef17c0 commit 7337e19
Show file tree
Hide file tree
Showing 4 changed files with 86 additions and 6 deletions.
44 changes: 40 additions & 4 deletions packages/core/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,9 @@ Import the stylesheet. If you are using [SvelteKit][], you can do this in `src/r
import '@viamrobotics/prime-core/prime.css';
```

You can now use the components in your app:
## Usage

Once installed, you can use the components in your app:

```html
<script lang="ts">
Expand All @@ -51,6 +53,40 @@ You can now use the components in your app:
[tailwind]: https://tailwindcss.com/
[sveltekit]: https://kit.svelte.dev/

### Testing components that use Prime

All Prime components have their own test suites, so in your application tests, you generally only need to test that the component itself is rendered rather than try to test that all the behaviors work - we've already written those tests.

#### Testing toasts

The `useToast` hook requires a Svelte context to render. In order to test a component that issues toasts, you can use the `createNoopToastContext` fixture. Before using this fixture, consider if you can re-structure your components to avoid the need for testing a component wired to `useToast` directly.

```ts
import { describe, expect, test, vi } from 'vitest';
import { render } from '@testing-library/svelte';

import { createNoopToastContext } from '@viamrobotics/prime-core/__fixtures__';

import Subject from '../cool-component.svelte';

const toast = vi.fn();

const renderSubject = () => {
const toastContext = createNoopToastContext(toast);
return render(Subject, {
props: { message: 'hello' },
context: new Map([toastContext]),
});
};

describe('<CoolComponent>', () => {
it('toasts `message` on mount', () => {
renderSubject();
expect(toast).toHaveBeenCalledWith({ message: 'hello' });
});
});
```

## Playground

The playground can be used during development but is not used outside of the package.
Expand Down Expand Up @@ -157,9 +193,9 @@ For easier readability, we try to use a standard ordering for component composit

<!-- Your layout -->
<div class="border-black">
<!--
all slots should be named if there are multiple; otherwise a single slot
can be the default `<slot />`
<!--
all slots should be named if there are multiple; otherwise a single slot
can be the default `<slot />`
-->
<slot name="title" />
<slot name="content" />
Expand Down
6 changes: 5 additions & 1 deletion packages/core/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@viamrobotics/prime-core",
"version": "0.0.138",
"version": "0.0.139",
"publishConfig": {
"access": "public"
},
Expand All @@ -24,6 +24,10 @@
"types": "./dist/index.d.ts",
"svelte": "./dist/index.js"
},
"./__fixtures__": {
"types": "./dist/__fixtures__/index.d.ts",
"svelte": "./dist/__fixtures__/index.js"
},
"./prime.css": "./prime.css",
"./plugins": "./plugins.ts",
"./theme": "./theme.ts"
Expand Down
40 changes: 40 additions & 0 deletions packages/core/src/lib/__fixtures__/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/** prime-core test fixtures. */
import { readable, writable } from 'svelte/store';
import { noop } from 'lodash-es';

// NOTE: imported directly from `$lib/toast/context` to avoid
// exporting implementation details in `$lib/toast/index`
import {
ToastContextKey,
type ToastContext,
type Toast,
} from '$lib/toast/context';

/**
* Create a no-op toast context.
*
* @param toast - The `toast` function to return from `useToast` (defaults to `noop`)
*
* @example
* ```ts
* import { vi } from 'vitest';
* import { render } from '@testing-library/svelte';
*
* import { createNoopToastContext } from '@viamrobotics/prime-core/__fixtures__';
*
* import Subject from '../cool-component.svelte';
*
* const toast = vi.fn();
* const renderSubject = () => {
* const toastContext = createNoopToastContext(toast)
* return render(Subject, { props: {}, context: new Map([toastContext]) });
* }
* ```
*/
export const createNoopToastContext = (toast?: Toast): [unknown, unknown] => [
ToastContextKey,
{
state: { toasts: readable([]), pageIsVisible: writable(false) },
toast: toast ?? noop,
} satisfies ToastContext,
];
2 changes: 1 addition & 1 deletion packages/core/src/lib/toast/context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ export interface ToastElement {
dismiss: () => void;
}

const ToastContextKey = Symbol('toast-context');
export const ToastContextKey = Symbol('toast-context');
const ToastDuration = 4000;

/** Create the internal toast state and context object. */
Expand Down

0 comments on commit 7337e19

Please sign in to comment.