-
-
Notifications
You must be signed in to change notification settings - Fork 9.4k
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-controls: Copy as URL and load from URL #12291
Comments
To be clear why this is an issue, its not simply about sharing links. During development I want the state of the args to persist between re-renders. For example right now I'm developing the top bar for an app with the current user display. It a photo url that appears in the upper right or an account-circle icon if one is not provided. I don't want to hard-code a photo url in the codebase because it right now just points to my google profile photo over the internet, but its also a real pain in the ass to have to constantly paste the url in every time it re-renders |
@togakangaroo I would strongly encourage you to encode it as a story, if it is useful now, it'll be even more useful later when you have to come back to this component and fix a bug and you can't quite remember how it all works. In any case, it sounds like HMR isn't working for your SB. Or is this a bug in args and HMR? |
I've mentioned that in the #12728 PR, but believe that it should also be stated here (due to some optional workaround suggested above) - the possibility to create a 'deep-link' into the components state with all of the controls set as per user - is quite needed functionality. The proposal of 'flattening' the deep state into a separate stories is inconvenient when component has few dozens of possible state permutations, IMHO. |
To add another use case: My team maintains a component library where the only "frontend" is storybook. We use I know that |
That's the exact same case we preconfigure Storybook for our Nx users. We even automatically give people the option to setup Cypress based e2e tests when we configure Storybook for them. Now not having this deep-linking possibility kinda makes that feature unusable... |
@tmeasday yes, it is part a convenience thing and part a preference thing. First, convenience: The amount of flexibility that comes from injecting variables is hard to replicate, and more importantly maintain, by having many almost-the-same stories built only with slight variations. Most simply this goes against the DRY principle, and reasons why that principle exists fits here. Second, preference: This one may be more important for me actually. If I went ahead and created a bunch of stories to support my test cases, I don't really like what my storybook would end up being; I feel my storybook sidebar would become cluttered and messy. Roughly, I consider my test suite as just another user who might use storybook. Devs creating test cases are merely calling out specific scenarios that I'd expect any real user to try out via the UI controls. That, actually is the beauty of knobs or controls, that the user has full control over component inputs without having to edit the stories themselves. I want my dev and qa teams to continue to have the same flexibility. |
Thanks @jfairley, can I dig a little deeper?
Just to be clear though, in your example you would create a test case in cypress that goes something like:
And the alternative is:
So in a sense we have just moved the
Fair enough. Although this kind of thing feels a little bit like a user preference, like maybe it would be better to somehow tag stories as "testing" stories and have a way to hide such stories from the sidebar? I wonder if other users (e.g. your QA team) would actually prefer those stories to be visible in the sidebar to make debugging their cypress tests easier?
What's a "real user" in this case? Do you mean like a component library consumer?
We agree that control over arg values via URL is super useful of course! Is the role an issue here? Like do the QA team not have the ability to easily write stories? As I ask these questions I'm wondering if there's a bit of a tension here between "stories you want users to see" and "stories that are useful for development/QA" (i.e. edge cases). I wonder if SB needs a semantic distinction between the two somehow when creating docs. |
@shilman That feature request about hiding stories is interesting. I subscribed to see how that one goes. @tmeasday Your clarification of knob args (like I do today) vs a story with baked-in args is clear. We're on the same page with respect to the alternatives. 👍🏼
In my specific case, I am arguing from more of a hypothetical than others might. We don't currently publish our components or stories publicly (though we may in the future), so my users don't extend beyond the engineering team (developers, testers, product owners). But I think a lot of my opinion on this comes from the philosophy of not letting tests drive source code. It's a loose comparison, but in this case I'm trying to treat my stories more as documentation that are defined by the product use cases rather than by tests, which at times might be pressing on uncommon edge cases. Now all that said, my stories certainly aren't perfect. I have plenty of examples where I created new stories to fit test cases (as you're suggesting). I'm just cautious of that being what I have to do.
Here's where things get a little less pleasant. First, yes, the QA team could write stories, but they don't yet. When devs write cypress test cases, they're bundled in the repo and run in CI along site Jest unit tests. Being in the same repo, devs can very easily add or edit stories. The QA team operates on their own though. Their tests live in separate repos and run against a hosted static storybook instance (which doubles as the product owner documentation / demo / playground). So, while the QA team could commit new stories into the main repo, they don't currently, so we would have to change our process a bit.
Yes, it's more about "we don't do it that way" than "we can't do it that way." I do think hidden stories could be an ok middle ground, particularly if exposing controls is difficult on your end. QA adding stories would still be less than ideal, but not the worst thing. |
Actually, your suggested patter IS having lots of repetition, IMHO.
You could say - 'well, you'll need all those permutations anyway, at least somewhere in tests, if to speak that use-case', and you are right. But it's an absolutely different story to make up permutations by URL, dynamically on consumer side, and to actually bake in all those stories. |
@tmeasday Yes and no. We could obviously create different story setups for all the various combinations and then even hide those we don't like in our storybook (as discussed above). Tbh that sounds a bit of a workaround for me. It makes sense to create different story configs that I also want to show on my storybook page as they might highlight the most prominent configurations of a given component. In addition, in Nx we've automated that for the user, to also allow to generate Cypress tests that control those inputs dynamically and test for the behavior of the component. Basically automating the user interaction with the component. And for exactly that interaction we need the possibility to obviously control these component inputs via the URL when we access the iframe that renders the story. To give you a better understanding, here are two vids that demo that:
Obviously, that brings a lot of benefits to the user and motivates them to use the Storybook and Cypress integration together, as they can design and develop the components in isolation with Storybook's capabilities and in addition even test them in isolation (as a user would) with Cypress :) |
It seems like there's an unaddressed issue here. Some of you mentioned you don't like to have separate stories for each of the controls' commonly used settings, because it clutters up the sidebar with a ton of mostly identical stories. Controls is part of a subject we refer to as "combinatorial testing", where one component has many combinations of props (permutations) that need to be tested. We're hashing out various ways to tackle that use case. One of the sub-problems is rendering the various combinations in a sensible way. Having them as separate stories is inconvenient, not only because it clutters the sidebar, but also because it makes snapshot testing more expensive (as typically 1 story = 1 screenshot) and it's often more convenient to view variants side-by-side. That's why I've recently been experimenting with a story wrapper that renders a grid of component instances in various states, as a single story. Something like this example. The trick is to make this work equally for all frameworks. Would this sufficiently alleviate the issue of cluttering the sidebar (besides the option to hide stories)? I'd like to point out that describing all relevant component variants is exactly what Component Story Format is for. Encoding variants in a URL in some unrelated test file instead of in the CSF file undermines the purpose and intent of CSF. You may not currently experience the benefits of doing it that way. That will hopefully change with new addons and tools that build on top of CSF. Being able to share the state of Controls via the URL is a useful feature for the sake of collaboration, so we still want to fix this. |
@gullerya -- I'm not sure I am quite saying what you think I am.
My proposal is just to write stories for whichever combinations of args are referenced (via URL as proposed in this feature) in other places. I'm not suggesting we get rid of the controls feature entirely, which is what enables this combinatorial explosion in the number of arg combinations. If someone is making reference to each of the 6 combinations in 6 different cypress tests (or otherwise), then I guess I am proposing writing 6 stories. But, I suspect if each combination is worth writing a test for, it is probably worth having a story for too.
It's not that it's difficult (and it is something we are going to do!), it's just that some of these use cases feel like anti-patterns to us (we want you to write stories!), so I just want to understand what's stopping people from writing stories and see if we can remove that impediment, rather than just adding a feature that makes it easier to not write them ;).
Why is that? Can you elaborate?
Watching that video I'm not really sure I see how it is required to change the arg (/knob) values via the URL parameters, as opposed to editing a story. I would strongly advocate that your generator did the following when creating a cypress test:
export CypressTestOne = Template.bind({});
CypressTestOne.args = {
label: 'foo',
// ...
}
Apart from the other benefits of having it "storified", I would suggest it is going to be a lot easier and less error prone to alter a line in a CSF file than trying to find and modify a URL query parameter buried in a URL in a test case, especially when you consider things like URL serialization etc. PS it is really cool how your generate generates the CSF file automatically from the components! We want to add a feature like that to Storybook itself via the CLI. If your team is interested in contributing it back to Storybook that would be awesome! |
Put most simply, in the scenario that QA e2e tests exist in a separate repo, it represents them collaborating in two repos instead of one. The lifecycle is much more cumbersome that way. Recall, that QA is coding against a built-and-hosted version of storybook. When simply writing tests against a runtime-parameterized story, the dev cycle is quick:
When adding stories before writing tests, everything above happens, plus:
IMO, this is usually true for happy-path demonstrations. I see stories as "this is how you're supposed to use my component." But good testing often focuses just as much on the sad-path scenario. This is JavaScript after all.
These sad-path scenarios aren't cases that I want enshrined as stories. It's basically saying: "Look, here are 10 examples of how when you disregard the documentation, bad things happen." There's no value in that outside of testing. Not to mention, show the wrong way to use something, and invariably, you're going to find a user/developer who isn't paying enough attention to see that it's a sad-path case, and takes it as instruction, coding it like that in the real app. |
@ghengeveld that's an interesting take, putting multiple variants of a component on the same page. It's a creative way to cut down on sidebar clutter, but I would make cypress (non-snapshot) testing difficult only in that the css selectors need to be made more specific, though that's not a huge deal. I should point out that buttons are one of the smaller components one might want to show off, so as component sizes grow (think a panel or list component), this tactic becomes harder to maintain. But I like the idea! |
I believe my question is related to this issue. |
@sefaltay Looks like this is what @ghengeveld is working on currently |
Ta-da!! I just released https://github.com/storybookjs/storybook/releases/tag/v6.2.0-alpha.29 containing PR #13803 that references this issue. Upgrade today to the
Closing this issue. Please re-open if you think there's still more to do. |
@shilman Awesome! gonna try 🙇 |
now are we able to see changes in "control" in sync with URL ? |
@sefaltay yes, as you update the controls the URL updates in realtime |
Noice! I can't wait to give it a try! |
@shilman awesome works with primitives, but controls with type |
@khats correct. we have a few possible approaches to deal with that and will do our best to address it in a future iteration cc @ghengeveld @amartinez62 |
Same as #11604, but for args/controls.
This is currently possible by the knobs addon:
We should also make sure that the
eject
button works per #12675 at the same timeThe text was updated successfully, but these errors were encountered: