Skip to content
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

Node: Safe use of document for preview #24248

Merged
merged 5 commits into from
Mar 26, 2024

Conversation

DylanPiercey
Copy link
Contributor

What I did

Avoid referencing document.location when it's possible for it not to be there.

I am currently using the following apis in order to reimplement the testing portion for Marko Storybook which I am upgrading to support storybook 7.

import {
  composeStories,
  composeStory,
  setProjectAnnotations,
} from "@storybook/preview-api";

These defer the implementation of the story composition for testing which is great!

The issue I ran into is that the @storybook/preview-api uses a browser api which does not exist in server environments and for Marko apps (likely Svelte, Solid and anything else with a different ssr compilation) it is nice to also test these fixtures in a server context.

With the simple change in this PR it seems this API works fine in a bare node environment and there is already precedent in the storybook codebase for checking if the document.location exists.

Checklist for Contributors

Testing

I'm not exactly sure how best to add tests for this but am open to ideas.

The changes in this PR are covered in the following automated tests:

  • stories
  • unit tests
  • integration tests
  • end-to-end tests

Manual testing

  1. Use any storybook project where the stories could be rendered on the server.
  2. Import the stories, and the composeStory api in a node script.
  3. Try and render the story using the composeStory api.

-->

Documentation

  • Add or update documentation reflecting your changes
  • If you are deprecating/removing a feature, make sure to update
    MIGRATION.MD

Checklist for Maintainers

  • When this PR is ready for testing, make sure to add ci:normal, ci:merged or ci:daily GH label to it to run a specific set of sandboxes. The particular set of sandboxes can be found in code/lib/cli/src/sandbox-templates.ts

  • Make sure this PR contains one of the labels below:

    Available labels
    • bug: Internal changes that fixes incorrect behavior.
    • maintenance: User-facing maintenance tasks.
    • dependencies: Upgrading (sometimes downgrading) dependencies.
    • build: Internal-facing build tooling & test updates. Will not show up in release changelog.
    • cleanup: Minor cleanup style change. Will not show up in release changelog.
    • documentation: Documentation only changes. Will not show up in release changelog.
    • feature request: Introducing a new feature.
    • BREAKING CHANGE: Changes that break compatibility in some way with current major version.
    • other: Changes that don't fit in the above categories.

🦋 Canary release

This PR does not have a canary release associated. You can request a canary release of this pull request by mentioning the @storybookjs/core team here.

core team members can create a canary release here or locally with gh workflow run --repo storybookjs/storybook canary-release-pr.yml --field pr=<PR_NUMBER>

@DylanPiercey
Copy link
Contributor Author

I found the main issue is calling @storybook/preview-api#start. So another work around for me is to just avoid that in the testing setups.

I'm happy with that work around, but I'll leave up the PR if you all wish to discuss.

@@ -22,7 +22,7 @@ const getQueryString = ({
selection?: Selection;
extraParams?: qs.ParsedQs;
}) => {
const { search = '' } = document.location;
const search = (document && document.location && document.location.search) || '';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm ok with this defensive programming, just to be on the safe side.

Minor nit pick: could you use optional chaining here to keep the code concise?

@shilman WDYT?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Happy to use optional chaining, I only avoided it to stick with the pattern used here: https://github.com/storybookjs/storybook/blob/next/code/lib/preview-api/src/modules/client-api/queryparams.ts#L7

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should start using optional chaining there too 😅

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ndelangen do you think it's worth changing this? Or create a separate issue for switching stuff to optional chaining more broadly?

@ndelangen
Copy link
Member

I am currently using the following apis in order to reimplement the testing portion for Marko Storybook which I am upgrading to support storybook 7.

OW! that's awesome! Please reach out to me, if you need assistance!

@tmeasday
Copy link
Member

@DylanPiercey I'm confused as to why that code is executing if you are only using the listed APIs?

@yannbf
Copy link
Member

yannbf commented Sep 22, 2023

@DylanPiercey I'm confused as to why that code is executing if you are only using the listed APIs?

This happens when APIs like composeStories are called in node, in non JSDOM environments. We had a similar issue when trying composeStories with Playwright CT. This PR seems like it would fix those problems!

@ndelangen ndelangen changed the title fix: avoid relying on document for preview file used in the compose/t… Node: Safe use of document for preview Sep 22, 2023
@ndelangen ndelangen self-assigned this Sep 22, 2023
@tmeasday
Copy link
Member

This happens when APIs like composeStories are called in node, in non JSDOM environments. We had a similar issue when trying composeStories with Playwright CT.

What does composeStories call that ends up calling these lines?

This PR seems like it would fix those problems!

Agree, but it seems like maybe a bandaid. I don't think a preview should be getting initiated if there is no "preview", at least naively (maybe there's a good reason it needs to). Can we figure out if it absolutely necessary for these lines to execute?

@DylanPiercey
Copy link
Contributor Author

@tmeasday to be clear calling composeStory or composeStories does not cause these lines to execute. What does is calling the start api from preview. Since in my case start was called unconditionally and the test apis were exposed through the same module this is more of a side effect.

I changed it to lazily call start so that it doesn't happen in testing, which is a good enough work around for me, but maybe this change is still worth while?

@tmeasday
Copy link
Member

What does is calling the start api from preview. Since in my case start was called unconditionally and the test apis were exposed through the same module this is more of a side effect.

There's no reason to call start outside of story store v6 which is definitely not relevant in this scenario. We'll be removing that code in SB8.0 in any case.

I changed it to lazily call start so that it doesn't happen in testing, which is a good enough work around for me, but maybe this change is still worth while?

Can you explain this to me / link me to this code?

@ndelangen ndelangen removed their assignment Nov 27, 2023
@tmeasday
Copy link
Member

@ndelangen although this PR isn't causing any harm, I'm still unsure why it's necessary. Plus I wonder if we need to check typeof document !== 'undefined' rather than just !!document, TBH.

@ndelangen
Copy link
Member

I agree @tmeasday

@ndelangen
Copy link
Member

@yannbf considering you've worked a lot on composable stories.. Do you think this PR should still be merged?

@ndelangen ndelangen removed their assignment Mar 26, 2024
@yannbf
Copy link
Member

yannbf commented Mar 26, 2024

@yannbf considering you've worked a lot on composable stories.. Do you think this PR should still be merged?

I don't think these changes are much needed anymore because we don't instantiate PreviewWeb like we used to in Storybook 7, which was part of exporting clientApi. However I think it's fine to merge them, so I'd say let's do it! But would be nice to change the assertions to use optional chaining if possible

Copy link

nx-cloud bot commented Mar 26, 2024

☁️ Nx Cloud Report

CI is running/has finished running commands for commit 779117c. As they complete they will appear below. Click to see the status, the terminal output, and the build insights.

📂 See all runs for this CI Pipeline Execution


✅ Successfully ran 1 target

Sent with 💌 from NxCloud.

@ndelangen ndelangen merged commit 11534e4 into storybookjs:next Mar 26, 2024
51 checks passed
@github-actions github-actions bot mentioned this pull request Mar 26, 2024
22 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants