Created
August 19, 2019 22:00
-
-
Save devonChurch/de5efc2701cc63456b4193da151e1590 to your computer and use it in GitHub Desktop.
Get path ID for every Story in sidebar
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Reveals ALL of the Story links in the Storybook Manager Sidebar. From there we | |
// return a list of all of the paths associated to getting each Story to open in | |
// an iFrame. | |
// | |
// The problem here is that Storybook will only inject the Story links associated | |
// under a Story group when it's been triggered by the user. In that regard we | |
// cannot scrape the DOM initially and instead need to programatically open all | |
// Story groups and then take an inventory of their revealed Story links. | |
// The "option" links (not links that trigger a story but links that open up the | |
// hierarchical group with the stories inside). | |
const OPTIONS = "a:not(#explorerstyle):not([href]):not([data-cypress-clicked])"; // prettier-ignore | |
// The links accosted to triggering an individual Story to render in an iFrame. | |
const LINKS = 'a:not(#explorerstyle) ~ div a[href*="/?path=/story/"]'; | |
// NOTE: ☝️ The above selectors are not fetching Stories associated to our CSS | |
// style guide and instead only focus on our component architecture. | |
const getStoryPathIds = () => { | |
const menuNode = document.querySelector("nav.sidebar-container"); | |
// Our recursive function that triggers all unopened Story options. Remember | |
// that new child options can be injected when parent options are triggered, | |
// this is why we must recurse until all options are exhausted. | |
const openAvailableStoryOptions = () => { | |
const optionNodes = menuNode.querySelectorAll(OPTIONS); | |
optionNodes.forEach(optionNode => { | |
const { id, parentNode } = optionNode; | |
// When the content from a triggered option is injected into the DOM, it is | |
// added in as a sibling `<div />` (with no discernible hook). Because | |
// vanilla JS does not have a $.next() we bounce back to the parent node | |
// then back down to the options next sibling and test if it is a `<div />` | |
// (which means it is open with its on injected content). | |
const isOpen = Boolean(parentNode.querySelector(`#${id} ~ div`)); | |
// Regardless if this link was already opened my Storybook (on page load) | |
// or we are able to open it ourselves, we all this open flag to keep track | |
// of every open option (when recursing). | |
optionNode.setAttribute("data-cypress-clicked", "true"); | |
if (!isOpen) { | |
// Open the options then run the recursive function again to investigate | |
// the newly injected content. | |
optionNode.click(); | |
openAvailableStoryOptions(); | |
}; | |
}); | |
}; | |
// Begin recursion... | |
openAvailableStoryOptions(); | |
const linkNodes = menuNode.querySelectorAll(LINKS); | |
// EXAMPLE: for a simple button Story href of [href="/?path=/story/button-primary--colors"] | |
// we extract the path ID of "button-primary--colors" which can be used to target | |
// a dedicated iFrame of "/iframe.html?id=button-primary--colors" | |
return [...linkNodes].map(linkNode => | |
linkNode.getAttribute("href").replace("/?path=/story/", "") | |
); | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment