-
-
Notifications
You must be signed in to change notification settings - Fork 9.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Addon-interactions: Low level instrumentation API #16667
Comments
I think the Jest lifecycle is a familiar and solid pattern to look at. https://noriste.github.io/reactjsday-2019-testing-course/book/jest-101/jest-lifecycle.html |
Honestly feel like play functions should be interchangeable with Jest tests but thats just me. |
@andrewluetgers Are you imagining something similar but using the import { beforeEach } from '@storybook/instrumentation';
beforeEach(async (act: ActionFn, signal: AbortSignal) => {
// setup integration here.
}); |
If we can agree on a general direction to take with the API, we'd be happy to take a shot at spiking an implementation. |
@cowboyd yeah but now that I think of it there is no concept of a suite of play functions equivalent to a jest suite. I suppose beforeEach makes sense for a global rule but the convention for storybook to apply global rules like that in the preview.js. |
I think maybe it should not be as a part of instrument API, but instead create new API that allows to define custom steps by passing there special structure which describes js statement in ast-like format. |
@wKich Sounds coo, although I'm not sure what it would look like in practice. Can you post an example of what you're thinking? |
The steps API could look like this: // Menu('Actions', { disabled: or(true, false) }).find(Item('First')).click()
defineStep(
fn,
object(
call('Menu', ['Actions', { disabled: call('or', [true, false]) }]),
call('find', [
call('Item', ['First'])
]),
call('click')
)
) |
How would the full integration work though? I'm not quite seeing it. Can you show what the full integration between interaction and storybook would look like? |
To clarify, one of the things that we're realizing is that when we define a step in storybook, we'll need some way of integrating with the highlighter. I think that's what @wKich as getting at by effectively defining an AST of some sort that the debugger could use to render appropriately. Rather than require some one-size-fits all syntax tree, what if we just passed the highlighter to the steps? import { onPlay } from '@storybook/interactions';
onPlay(async (step: StepFn, signal: AbortSignal, h: Highlighter) => {
// highlight with bundled js highlighter
step(h("Do(some(thing()))"), async () => { /* do the thing */ });
// highlight with bundled text highlighter
step(h("do something else", type: 'text/plain' }), async => { /* do the thing */ });
// use a custom highlighter function
step(h("(use (some (lispy thing)))", type: txt => coderay(text, { type: 'clojurescript' }))
}); |
Can you clarify what this highlighter does? Regarding the Jest API suggestion (e.g. beforeEach), we did talk about this but concluded that the Jest scoping patterns (describe, it) simply map onto Storybook's existing story hierarchy, where a story is basically a What we do have in mind (and will add in 6.5) is a play: async () => {
await step("Select product and quantity", async () => {
await userEvent.select(...)
await userEvent.type(...)
})
await step("Select shipping method", () => userEvent.click(...))
await step("Checkout", async () => {
await userEvent.type(...)
await userEvent.type(...)
await userEvent.click(...)
})
} Effectively these are just "labeled groups". They don't really do anything special beyond making the interaction log more descriptive. |
@ghengeveld the highlighter is the same highlighter that is used in Storybook to highlight step's code. I like your Does |
Hey @cowboyd @wKich sorry for the late notice, but the export const MyStory = {
play: async (context) => {
await step("Select product and quantity", async () => {
await userEvent.select(...)
await userEvent.type(...)
})
// you can reuse other story's play function as a step, the story context will be passed down to that callback
await step("Select shipping method", SelectShipping.play)
await step("Checkout", async () => {
await userEvent.type(...)
await userEvent.type(...)
await userEvent.click(...)
})
}
} The step can be augmented by addons which expose a This is a code example of actual usage: This is where the step runners are composed: I'll be closing this issue, but feel free to experiment and check if this is good for your scenario, and open the issue again it shouldn't have been closed. |
Is your feature request related to a problem? Please describe
We're attempting an integration of interactors with storybook. The good news is that we were up and running in just a few minutes. You can see the results here thefrontside/interactors#126
However, we were only able to get this working by getting a reference to the internal instrumentation's
track()
method and invoking it manually.storybook/lib/instrumenter/src/instrumenter.ts
Lines 321 to 332 in 1d1a59d
This was necessary because unlike testing library, interactors are page objects for components, and their actions live on the objects themselves which are created at runtime, rather than available as static module methods.
The good news is that it actually made the integration less work in the sense that interactors already have a native instrumentation mechanism, and so all we needed to do was to integrate it with the underlying storybook instrumentation method.
Describe the solution you'd like
Would love to see an officially supported instrumentation API that sits underneath, and is used by, the
instrumenter()
API. Not only would it allow non-static libraries like interactors to hook directly into the interaction api, but it would also mean that any other libraryx
that made use of this API could be imported directly into story book rather than having to publish a separatestorybook-instrumented-x
for its users.This API would need to:
Maybe something like this?
Where
ActionFn
is maybe so:Are you able to assist to bring the feature to reality?
Definitely!
Additional context
Interactors, page objects for components.
The text was updated successfully, but these errors were encountered: