Open shilman opened 3 years ago
Question: How would the following code work in a docs page?
const HelloStory = {
play: async () => {
userEvent.type(screen.getByRole('textbox'), 'Hello, World!')
}
}
const GoodbyeStory = {
play: async () => {
userEvent.type(screen.getByRole('textbox'), 'Goodbye, World!')
}
}
I think getByRole
might return an error like: TestingLibraryElementError: Found multiple elements with the role "textbox"
because the stories are inline, thus the selectors are duplicated.
@yannbf If the expectation is role='textbox'
occurs only once on a screen, then there's no way to work if it appears multiple time.
I only see 2 ways of dealing with this:
screen
implementation as-isscreen
to select within the "targetContainer"modify screen to select within the "targetContainer"
Can't we do something similar to the renderResult
you get back when Testing Lib takes care of the render
ing? It creates some preconfigured queries which are limited to the "targetContainer". Something like that could be passed to the play
function?
// how it can be done inside a unit test
import { render } from '@testing-library/react';
const result = render(<GoodbyeStory />);
// in your story (`result` being something similar to what we would get from `render`)
const GoodbyeStory = {
play: async ({ result }) => {
userEvent.type(result.getByRole('textbox'), 'Goodbye, World!')
}
}
Or if you want less coupling to Testing Lib this would be an alternative with a bit more typing:
import { within } from '@testing-library/react';
const GoodbyeStory = {
play: async ({ container }) => {
const queries = within(container); // container is just the DOM element with our rendered story
userEvent.type(queries.getByRole('textbox'), 'Goodbye, World!')
}
}
const queries = within(container)
❤️
@ghengeveld We talked about this a lot last week, should this ticket be assigned to you or us both perhaps?
@ghengeveld Want to talk about this later this week?
Pitty that this is not in 6.4 already, but given that chromatic does not look at the docs page it’s not that bad.
Having play UI on each story with a play function in the docs page sounds great functionally, but is probably not easy to make look good, especially when the story is not wrapped in a Canvas.
Good job with the docs promoting const canvas = within(canvasElement)
as standard practice. :-)
Due to the way the interactive step-by-step debugger works, each play function instruction already has to be written in a way that is independant from the current state of focus. Is this something you want to tackle there as well?
Hi everyone! Seems like there hasn't been much going on in this issue lately. If there are still questions, comments, or bugs, please feel free to continue the discussion. Unfortunately, we don't have time to get to every issue. We are always open to contributions so please send us a pull request if you would like to help. Inactive issues will be closed after 30 days. Thanks!
I feel like issue, where someone is assigned, shouldn't be closed automatically.
Is this included in version 6.5?
@bodograumann nope, unfortunately not. 7.0 🤞
Is this included in 7.0?
Is this included in 7.0?
Great question! Yes, the play function works in MDX, however does not run by defualt. You can try it out with the Story
block by passing the autoplay
property to it, and then it will:
import { Meta, Story } from '@storybook/blocks'
import * as ButtonStories from './Button.stories'
# Button
<Meta of={ButtonStories} />
<Story of={ButtonStories.Primary} autoplay />
Is there a way to run it on the default template @yannbf ?
Is there a way to run it on the default template @yannbf ?
Good question! I don't think so? @JReinhold @tmeasday could answer this one.
I was going to suggest to write a custom default autodocs template but you'd end up using the <Stories />
block and not the <Story />
one. The Stories block does not (currently) have an autoplay prop that would be passed down to all stories.
Is there a way to run it on the default template @yannbf ?
There is! All props on doc blocks can also be set via parameters on stories/component/project. So you can set parameters.docs.story.autoplay = true
, documented here: https://storybook.js.org/docs/react/api/doc-block-story#autoplay
@ignaciolarranaga we have documentation on this. If you check this, you'll see all the available props and what is available with that Doc Block. Heads up, @JReinhold, check your link. You referenced something unrelated to the conversation. Might I suggest that you remove it?
After searching far and wide and finally finding this thread, it's worth pointing out that previous versions' documentation does not indicate that play
functions will not be ran on DocsPages: https://storybook.js.org/docs/6.5/react/writing-stories/play-function#writing-stories-with-the-play-function
The inclusion of MDX files on this v6.5 documentation even may make it seem that it's allowed, as does this generic language:
Play
functions are small snippets of code executed after the story renders
cc @jonniebigodes ☝️
Is it possible to run play
functions in the docs page with some workaround today? I tried setting parameters.docs.story.autoplay = true
in my preview.tsx
, but it doesn't seem to have an effect.
Is it possible to run
play
functions in the docs page with some workaround today? I tried settingparameters.docs.story.autoplay = true
in mypreview.tsx
, but it doesn't seem to have an effect.
@donaldpipowitch that should be the current workaround, so if that doesn't work, that's a bug. Can you open a separate bug report with a minimal reproduction?
Storybook CSF3 adds a
play
function for scripted interaction with components after a story has rendered. This currently does not work in the docs tab. We need to make it work:There are a few different issues to deal with around dueling
play
functions and dueling focus.Dueling play functions
Two
play
functions can't run at the same time: their events will clobber one another, especially if they require focus, e.g. keyboard events.One way to deal with this is to run play functions sequentially. This can be problematic for long-running play functions.
Another way to deal with it is to not run
play
functions on the Docs page at all, and have UI by which the user can run aplay
function.Dueling focus
A related issue is dueling Focus. Even if a
play
function finishes instantaneously, if storyA
shows elementA
focused, and storyB
shows elementB
focused, then at most one of those stories can show correctly on the Docs page.The sequential approach above won't fix this. Only the
play
function UI, would work for this.Proposal
Since the
play
function UI works for all cases, that's a relatively simple solution.Alternative
A more complex solution would be to make it configurable with a parameter, e.g.
And then sequentially play all stories with
playFunction
true. This way the CSF author has control and can setplayFunction
to false for long-running stories.┆Issue is synchronized with this Asana task by Unito