@storybook/addon-vitest 9.2.0-alpha.2 → 10.0.0-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/README.md +2 -0
  2. package/dist/_browser-chunks/chunk-JK72E6FR.js +6 -0
  3. package/dist/_browser-chunks/chunk-PMYV6BH2.js +76 -0
  4. package/dist/_node-chunks/chunk-2LKDLHP2.js +91 -0
  5. package/dist/_node-chunks/chunk-75PF53UG.js +103 -0
  6. package/dist/_node-chunks/chunk-EZERIZC2.js +481 -0
  7. package/dist/_node-chunks/chunk-FJO43W6J.js +37 -0
  8. package/dist/_node-chunks/chunk-HIDBMPI3.js +247 -0
  9. package/dist/_node-chunks/chunk-MHHQUJAV.js +50 -0
  10. package/dist/_node-chunks/chunk-MJKNSUFZ.js +295 -0
  11. package/dist/_node-chunks/chunk-T7EST64K.js +2264 -0
  12. package/dist/index.js +9 -6
  13. package/dist/manager.js +955 -8
  14. package/dist/node/coverage-reporter.js +1898 -4
  15. package/dist/node/vitest.js +871 -17
  16. package/dist/postinstall.js +2076 -88
  17. package/dist/preset.js +615 -35
  18. package/dist/vitest-plugin/global-setup.js +200 -6
  19. package/dist/vitest-plugin/index.js +3823 -43
  20. package/dist/vitest-plugin/setup-file.js +30 -8
  21. package/dist/vitest-plugin/test-utils.js +102 -8
  22. package/manager.js +1 -1
  23. package/package.json +27 -93
  24. package/preset.js +1 -1
  25. package/dist/chunk-55WZLVGN.mjs +0 -11
  26. package/dist/chunk-JKRQGT2U.mjs +0 -10
  27. package/dist/index.mjs +0 -5
  28. package/dist/node/coverage-reporter.d.ts +0 -184
  29. package/dist/node/coverage-reporter.mjs +0 -12
  30. package/dist/node/vitest.d.ts +0 -2
  31. package/dist/node/vitest.mjs +0 -19
  32. package/dist/vitest-plugin/global-setup.d.ts +0 -6
  33. package/dist/vitest-plugin/global-setup.mjs +0 -13
  34. package/dist/vitest-plugin/index.mjs +0 -28
  35. package/dist/vitest-plugin/setup-file.d.ts +0 -14
  36. package/dist/vitest-plugin/setup-file.mjs +0 -9
  37. package/dist/vitest-plugin/test-utils.d.ts +0 -20
  38. package/dist/vitest-plugin/test-utils.mjs +0 -8
  39. package/manager.mjs +0 -1
  40. package/postinstall.js +0 -1
  41. package/postinstall.mjs +0 -1
  42. package/preset.mjs +0 -1
package/dist/manager.js CHANGED
@@ -1,8 +1,955 @@
1
- import React3, { useState, useContext, useRef, useEffect, useMemo, useCallback } from 'react';
2
- import { Addon_TypesEnum } from 'storybook/internal/types';
3
- import { experimental_UniversalStore, experimental_getStatusStore, experimental_getTestProviderStore, addons, useStorybookApi, experimental_useTestProviderStore, experimental_useUniversalStore, experimental_useStatusStore } from 'storybook/manager-api';
4
- import { Modal, ProgressSpinner, Button, IconButton, WithTooltip, TooltipNote, ListItem, Form, Link } from 'storybook/internal/components';
5
- import { StopAltIcon, SyncIcon, CloseIcon, EyeIcon, PlayHollowIcon, InfoIcon } from '@storybook/icons';
6
- import { styled } from 'storybook/theming';
7
-
8
- var ADDON_ID="storybook/interactions",PANEL_ID=`${ADDON_ID}/panel`;var ADDON_ID2="storybook/a11y",PANEL_ID2=`${ADDON_ID2}/panel`;var ADDON_ID3="storybook/test",TEST_PROVIDER_ID=`${ADDON_ID3}/test-provider`;var DOCUMENTATION_LINK3="writing-tests/integrations/vitest-addon",DOCUMENTATION_FATAL_ERROR_LINK=`${DOCUMENTATION_LINK3}#what-happens-if-vitest-itself-has-an-error`;var storeOptions={id:ADDON_ID3,initialState:{config:{coverage:!1,a11y:!1},watching:!1,cancelling:!1,fatalError:void 0,indexUrl:void 0,previewAnnotations:[],currentRun:{triggeredBy:void 0,config:{coverage:!1,a11y:!1},componentTestCount:{success:0,error:0},a11yCount:{success:0,warning:0,error:0},storyIds:void 0,totalTestCount:void 0,startedAt:void 0,finishedAt:void 0,unhandledErrors:[],coverageSummary:void 0}}},FULL_RUN_TRIGGERS=["global","run-all"];var STATUS_TYPE_ID_COMPONENT_TEST="storybook/component-test",STATUS_TYPE_ID_A11Y="storybook/a11y";var store=experimental_UniversalStore.create({...storeOptions,leader:globalThis.CONFIG_TYPE==="PRODUCTION"}),componentTestStatusStore=experimental_getStatusStore(STATUS_TYPE_ID_COMPONENT_TEST),a11yStatusStore=experimental_getStatusStore(STATUS_TYPE_ID_A11Y),testProviderStore=experimental_getTestProviderStore(ADDON_ID3);var ModalBar=styled.div({display:"flex",justifyContent:"space-between",alignItems:"center",padding:"6px 6px 6px 20px"}),ModalActionBar=styled.div({display:"flex",justifyContent:"space-between",alignItems:"center"}),ModalTitle=styled(Modal.Title)(({theme:{typography}})=>({fontSize:typography.size.s2,fontWeight:typography.weight.bold})),ModalStackTrace=styled.pre(({theme})=>({whiteSpace:"pre-wrap",wordWrap:"break-word",overflow:"auto",maxHeight:"60vh",margin:0,padding:"20px",fontFamily:theme.typography.fonts.mono,fontSize:"12px",borderTop:`1px solid ${theme.appBorderColor}`,borderRadius:0})),TroubleshootLink=styled.a(({theme})=>({color:theme.color.defaultText})),GlobalErrorContext=React3.createContext({isModalOpen:!1,setModalOpen:void 0});function ErrorCause({error}){return error?React3.createElement("div",null,React3.createElement("h4",null,"Caused by: ",error.name||"Error",": ",error.message),error.stack&&React3.createElement("pre",null,error.stack),error.cause&&React3.createElement(ErrorCause,{error:error.cause})):null}function GlobalErrorModal({onRerun,storeState}){let api=useStorybookApi(),{isModalOpen,setModalOpen}=useContext(GlobalErrorContext),handleClose=()=>setModalOpen?.(!1),troubleshootURL=api.getDocsUrl({subpath:DOCUMENTATION_FATAL_ERROR_LINK,versioned:!0,renderer:!0}),{fatalError,currentRun:{unhandledErrors}}=storeState,content=fatalError?React3.createElement(React3.Fragment,null,React3.createElement("p",null,fatalError.error.name||"Error"),fatalError.message&&React3.createElement("p",null,fatalError.message),fatalError.error.message&&React3.createElement("p",null,fatalError.error.message),fatalError.error.stack&&React3.createElement("p",null,fatalError.error.stack),fatalError.error.cause&&React3.createElement(ErrorCause,{error:fatalError.error.cause})):unhandledErrors.length>0?React3.createElement("ol",null,unhandledErrors.map(error=>React3.createElement("li",{key:error.name+error.message},React3.createElement("p",null,error.name,": ",error.message),error.VITEST_TEST_PATH&&React3.createElement("p",null,'This error originated in "',React3.createElement("b",null,error.VITEST_TEST_PATH),`". It doesn't mean the error was thrown inside the file itself, but while it was running.`),error.VITEST_TEST_NAME&&React3.createElement(React3.Fragment,null,React3.createElement("p",null,`The latest test that might've caused the error is "`,React3.createElement("b",null,error.VITEST_TEST_NAME),'". It might mean one of the following:'),React3.createElement("ul",null,React3.createElement("li",null,"The error was thrown, while Vitest was running this test."),React3.createElement("li",null,"If the error occurred after the test had been completed, this was the last documented test before it was thrown."))),error.stacks&&React3.createElement(React3.Fragment,null,React3.createElement("p",null,React3.createElement("b",null,"Stacks:")),React3.createElement("ul",null,error.stacks.map(stack=>React3.createElement("li",{key:stack.file+stack.line+stack.column},stack.file,":",stack.line,":",stack.column," - ",stack.method||"unknown method")))),error.stack&&React3.createElement("p",null,error.stack),error.cause?React3.createElement(ErrorCause,{error:error.cause}):null))):null;return React3.createElement(Modal,{onEscapeKeyDown:handleClose,onInteractOutside:handleClose,open:isModalOpen},React3.createElement(ModalBar,null,React3.createElement(ModalTitle,null,"Storybook Tests error details"),React3.createElement(ModalActionBar,null,React3.createElement(Button,{onClick:onRerun,variant:"ghost"},React3.createElement(SyncIcon,null),"Rerun"),React3.createElement(Button,{variant:"ghost",asChild:!0},React3.createElement("a",{target:"_blank",href:troubleshootURL,rel:"noreferrer"},"Troubleshoot")),React3.createElement(IconButton,{onClick:handleClose,"aria-label":"Close modal"},React3.createElement(CloseIcon,null)))),React3.createElement(ModalStackTrace,null,content,React3.createElement("br",null),React3.createElement("br",null),"Troubleshoot:"," ",React3.createElement(TroubleshootLink,{target:"_blank",href:troubleshootURL},troubleshootURL)))}function noop(){}function getSymbols(object){return Object.getOwnPropertySymbols(object).filter(symbol=>Object.prototype.propertyIsEnumerable.call(object,symbol))}function getTag(value){return value==null?value===void 0?"[object Undefined]":"[object Null]":Object.prototype.toString.call(value)}var regexpTag="[object RegExp]",stringTag="[object String]",numberTag="[object Number]",booleanTag="[object Boolean]",argumentsTag="[object Arguments]",symbolTag="[object Symbol]",dateTag="[object Date]",mapTag="[object Map]",setTag="[object Set]",arrayTag="[object Array]",functionTag="[object Function]",arrayBufferTag="[object ArrayBuffer]",objectTag="[object Object]",errorTag="[object Error]",dataViewTag="[object DataView]",uint8ArrayTag="[object Uint8Array]",uint8ClampedArrayTag="[object Uint8ClampedArray]",uint16ArrayTag="[object Uint16Array]",uint32ArrayTag="[object Uint32Array]",bigUint64ArrayTag="[object BigUint64Array]",int8ArrayTag="[object Int8Array]",int16ArrayTag="[object Int16Array]",int32ArrayTag="[object Int32Array]",bigInt64ArrayTag="[object BigInt64Array]",float32ArrayTag="[object Float32Array]",float64ArrayTag="[object Float64Array]";function isPlainObject(value){if(!value||typeof value!="object")return !1;let proto=Object.getPrototypeOf(value);return proto===null||proto===Object.prototype||Object.getPrototypeOf(proto)===null?Object.prototype.toString.call(value)==="[object Object]":!1}function eq(value,other){return value===other||Number.isNaN(value)&&Number.isNaN(other)}function isEqualWith(a,b,areValuesEqual){return isEqualWithImpl(a,b,void 0,void 0,void 0,void 0,areValuesEqual)}function isEqualWithImpl(a,b,property,aParent,bParent,stack,areValuesEqual){let result=areValuesEqual(a,b,property,aParent,bParent,stack);if(result!==void 0)return result;if(typeof a==typeof b)switch(typeof a){case"bigint":case"string":case"boolean":case"symbol":case"undefined":return a===b;case"number":return a===b||Object.is(a,b);case"function":return a===b;case"object":return areObjectsEqual(a,b,stack,areValuesEqual)}return areObjectsEqual(a,b,stack,areValuesEqual)}function areObjectsEqual(a,b,stack,areValuesEqual){if(Object.is(a,b))return !0;let aTag=getTag(a),bTag=getTag(b);if(aTag===argumentsTag&&(aTag=objectTag),bTag===argumentsTag&&(bTag=objectTag),aTag!==bTag)return !1;switch(aTag){case stringTag:return a.toString()===b.toString();case numberTag:{let x=a.valueOf(),y=b.valueOf();return eq(x,y)}case booleanTag:case dateTag:case symbolTag:return Object.is(a.valueOf(),b.valueOf());case regexpTag:return a.source===b.source&&a.flags===b.flags;case functionTag:return a===b}stack=stack??new Map;let aStack=stack.get(a),bStack=stack.get(b);if(aStack!=null&&bStack!=null)return aStack===b;stack.set(a,b),stack.set(b,a);try{switch(aTag){case mapTag:{if(a.size!==b.size)return !1;for(let[key,value]of a.entries())if(!b.has(key)||!isEqualWithImpl(value,b.get(key),key,a,b,stack,areValuesEqual))return !1;return !0}case setTag:{if(a.size!==b.size)return !1;let aValues=Array.from(a.values()),bValues=Array.from(b.values());for(let i=0;i<aValues.length;i++){let aValue=aValues[i],index=bValues.findIndex(bValue=>isEqualWithImpl(aValue,bValue,void 0,a,b,stack,areValuesEqual));if(index===-1)return !1;bValues.splice(index,1);}return !0}case arrayTag:case uint8ArrayTag:case uint8ClampedArrayTag:case uint16ArrayTag:case uint32ArrayTag:case bigUint64ArrayTag:case int8ArrayTag:case int16ArrayTag:case int32ArrayTag:case bigInt64ArrayTag:case float32ArrayTag:case float64ArrayTag:{if(typeof Buffer<"u"&&Buffer.isBuffer(a)!==Buffer.isBuffer(b)||a.length!==b.length)return !1;for(let i=0;i<a.length;i++)if(!isEqualWithImpl(a[i],b[i],i,a,b,stack,areValuesEqual))return !1;return !0}case arrayBufferTag:return a.byteLength!==b.byteLength?!1:areObjectsEqual(new Uint8Array(a),new Uint8Array(b),stack,areValuesEqual);case dataViewTag:return a.byteLength!==b.byteLength||a.byteOffset!==b.byteOffset?!1:areObjectsEqual(new Uint8Array(a),new Uint8Array(b),stack,areValuesEqual);case errorTag:return a.name===b.name&&a.message===b.message;case objectTag:{if(!(areObjectsEqual(a.constructor,b.constructor,stack,areValuesEqual)||isPlainObject(a)&&isPlainObject(b)))return !1;let aKeys=[...Object.keys(a),...getSymbols(a)],bKeys=[...Object.keys(b),...getSymbols(b)];if(aKeys.length!==bKeys.length)return !1;for(let i=0;i<aKeys.length;i++){let propKey=aKeys[i],aProp=a[propKey];if(!Object.hasOwn(b,propKey))return !1;let bProp=b[propKey];if(!isEqualWithImpl(aProp,bProp,propKey,a,b,stack,areValuesEqual))return !1}return !0}default:return !1}}finally{stack.delete(a),stack.delete(b);}}function isEqual(a,b){return isEqualWith(a,b,noop)}var statusValueToStoryIds=(allStatuses,typeId,storyIds)=>{let statusValueToStoryIdsMap={"status-value:pending":[],"status-value:success":[],"status-value:error":[],"status-value:warning":[],"status-value:unknown":[]};return (storyIds?storyIds.map(storyId=>allStatuses[storyId]).filter(Boolean):Object.values(allStatuses)).forEach(statusByTypeId=>{let status=statusByTypeId[typeId];status&&statusValueToStoryIdsMap[status.value].push(status.storyId);}),statusValueToStoryIdsMap},useTestProvider=(api,entryId)=>{let testProviderState=experimental_useTestProviderStore(s=>s[ADDON_ID3]),[storeState,setStoreState]=experimental_useUniversalStore(store),[isSettingsUpdated,setIsSettingsUpdated]=useState(!1),settingsUpdatedTimeoutRef=useRef();useEffect(()=>{let unsubscribe=store.onStateChange((state,previousState)=>{isEqual(state.config,previousState.config)||(testProviderStore.settingsChanged(),setIsSettingsUpdated(!0),clearTimeout(settingsUpdatedTimeoutRef.current),settingsUpdatedTimeoutRef.current=setTimeout(()=>{setIsSettingsUpdated(!1);},1e3));});return ()=>{unsubscribe(),clearTimeout(settingsUpdatedTimeoutRef.current);}},[]);let storyIds=useMemo(()=>entryId?api.findAllLeafStoryIds(entryId):void 0,[entryId,api]),componentTestStatusSelector=useCallback(allStatuses=>statusValueToStoryIds(allStatuses,STATUS_TYPE_ID_COMPONENT_TEST,storyIds),[storyIds]),componentTestStatusValueToStoryIds=experimental_useStatusStore(componentTestStatusSelector),a11yStatusValueToStoryIdsSelector=useCallback(allStatuses=>statusValueToStoryIds(allStatuses,STATUS_TYPE_ID_A11Y,storyIds),[storyIds]),a11yStatusValueToStoryIds=experimental_useStatusStore(a11yStatusValueToStoryIdsSelector);return {storeState,setStoreState,testProviderState,componentTestStatusValueToStoryIds,a11yStatusValueToStoryIds,isSettingsUpdated}};var RelativeTime=({timestamp})=>{let[timeAgo,setTimeAgo]=useState(null);if(useEffect(()=>{if(timestamp){setTimeAgo(Date.now()-timestamp);let interval=setInterval(()=>setTimeAgo(Date.now()-timestamp),1e4);return ()=>clearInterval(interval)}},[timestamp]),timeAgo===null)return null;let seconds=Math.round(timeAgo/1e3);if(seconds<60)return "just now";let minutes=Math.floor(seconds/60);if(minutes<60)return minutes===1?"a minute ago":`${minutes} minutes ago`;let hours=Math.floor(minutes/60);if(hours<24)return hours===1?"an hour ago":`${hours} hours ago`;let days=Math.floor(hours/24);return days===1?"yesterday":`${days} days ago`};var Wrapper=styled.div(({theme})=>({overflow:"hidden",whiteSpace:"nowrap",textOverflow:"ellipsis",fontSize:theme.typography.size.s1,color:theme.textMutedColor})),PositiveText=styled.span(({theme})=>({color:theme.color.positiveText}));function Description({entryId,storeState,testProviderState,isSettingsUpdated,...props}){let{setModalOpen}=React3.useContext(GlobalErrorContext),{componentTestCount,totalTestCount,unhandledErrors,finishedAt}=storeState.currentRun,finishedTestCount=componentTestCount.success+componentTestCount.error,description="Not run";if(!entryId&&isSettingsUpdated)description=React3.createElement(PositiveText,null,"Settings updated");else if(testProviderState==="test-provider-state:running")description=(finishedTestCount??0)===0?"Starting...":`Testing... ${finishedTestCount}/${totalTestCount}`;else if(!entryId&&testProviderState==="test-provider-state:crashed")description=setModalOpen?React3.createElement(Link,{isButton:!0,onClick:()=>setModalOpen(!0)},"View full error"):"Crashed";else if(!entryId&&unhandledErrors.length>0){let unhandledErrorDescription=`View ${unhandledErrors.length} unhandled error${unhandledErrors?.length>1?"s":""}`;description=setModalOpen?React3.createElement(Link,{isButton:!0,onClick:()=>setModalOpen(!0)},unhandledErrorDescription):unhandledErrorDescription;}else entryId&&totalTestCount?description=`Ran ${totalTestCount} ${totalTestCount===1?"test":"tests"}`:finishedAt?description=React3.createElement(React3.Fragment,null,"Ran ",totalTestCount," ",totalTestCount===1?"test":"tests"," ",React3.createElement(RelativeTime,{timestamp:finishedAt})):storeState.watching&&(description="Watching for file changes");return React3.createElement(Wrapper,{...props},description)}var TestStatusIcon=styled.div(({percentage})=>({width:percentage?12:6,height:percentage?12:6,margin:percentage?1:4,background:percentage?`conic-gradient(var(--status-color) ${percentage}%, var(--status-background) ${percentage+1}%)`:"var(--status-color)",borderRadius:"50%"}),({isRunning,theme})=>isRunning&&{animation:`${theme.animation.glow} 1.5s ease-in-out infinite`},({status,theme})=>status==="positive"&&{"--status-color":theme.color.positive,"--status-background":`${theme.color.positive}66`},({status,theme})=>status==="warning"&&{"--status-color":theme.color.gold,"--status-background":`${theme.color.gold}66`},({status,theme})=>status==="negative"&&{"--status-color":theme.color.negative,"--status-background":`${theme.color.negative}66`},({status,theme})=>status==="critical"&&{"--status-color":theme.color.defaultText,"--status-background":`${theme.color.defaultText}66`},({status,theme})=>status==="unknown"&&{"--status-color":theme.color.mediumdark,"--status-background":`${theme.color.mediumdark}66`});var Container=styled.div({display:"flex",flexDirection:"column"}),Heading=styled.div({display:"flex",justifyContent:"space-between",padding:"8px 0",gap:12}),Info=styled.div({display:"flex",flexDirection:"column",marginLeft:8,minWidth:0}),Title=styled.div(({crashed,theme})=>({fontSize:theme.typography.size.s1,fontWeight:crashed?"bold":"normal",color:crashed?theme.color.negativeText:theme.color.defaultText})),Actions=styled.div({display:"flex",gap:4}),Extras=styled.div({marginBottom:2}),Muted=styled.span(({theme})=>({color:theme.textMutedColor})),Progress=styled(ProgressSpinner)({margin:4}),Row=styled.div({display:"flex",gap:4}),StopIcon=styled(StopAltIcon)({width:10}),openPanel=({api,panelId,entryId})=>{let story=entryId?api.findAllLeafStoryIds(entryId)[0]:void 0;story&&api.selectStory(story),api.setSelectedPanel(panelId),api.togglePanel(!0);},TestProviderRender=({api,entry,testProviderState,storeState,setStoreState,componentTestStatusValueToStoryIds,a11yStatusValueToStoryIds,isSettingsUpdated,...props})=>{let{config,watching,cancelling,currentRun,fatalError}=storeState,finishedTestCount=currentRun.componentTestCount.success+currentRun.componentTestCount.error,hasA11yAddon=addons.experimental_getRegisteredAddons().includes(ADDON_ID2),isRunning=testProviderState==="test-provider-state:running",isStarting=isRunning&&finishedTestCount===0,[componentTestStatusIcon,componentTestStatusLabel]=fatalError?["critical","Component tests crashed"]:componentTestStatusValueToStoryIds["status-value:error"].length>0?["negative","Component tests failed"]:isRunning?["unknown","Testing in progress"]:componentTestStatusValueToStoryIds["status-value:success"].length>0?["positive","Component tests passed"]:["unknown","Run tests to see results"],[a11yStatusIcon,a11yStatusLabel]=fatalError?["critical","Component tests crashed"]:a11yStatusValueToStoryIds["status-value:error"].length>0?["negative","Accessibility tests failed"]:a11yStatusValueToStoryIds["status-value:warning"].length>0?["warning","Accessibility tests failed"]:isRunning?["unknown","Testing in progress"]:a11yStatusValueToStoryIds["status-value:success"].length>0?["positive","Accessibility tests passed"]:["unknown","Run tests to see accessibility results"];return React3.createElement(Container,{...props},React3.createElement(Heading,null,React3.createElement(Info,null,entry?React3.createElement(Title,{id:"testing-module-title"},"Run component tests"):React3.createElement(Title,{id:"testing-module-title",crashed:testProviderState==="test-provider-state:crashed"||fatalError!==void 0||currentRun.unhandledErrors.length>0},currentRun.unhandledErrors.length===1?"Component tests completed with an error":currentRun.unhandledErrors.length>1?"Component tests completed with errors":fatalError?"Component tests didn\u2019t complete":"Run component tests"),React3.createElement(Description,{id:"testing-module-description",storeState,testProviderState,entryId:entry?.id,isSettingsUpdated})),React3.createElement(Actions,null,!entry&&React3.createElement(WithTooltip,{hasChrome:!1,trigger:"hover",tooltip:React3.createElement(TooltipNote,{note:`${watching?"Disable":"Enable"} watch mode`})},React3.createElement(IconButton,{"aria-label":`${watching?"Disable":"Enable"} watch mode`,size:"medium",active:watching,onClick:()=>store.send({type:"TOGGLE_WATCHING",payload:{to:!watching}}),disabled:isRunning},React3.createElement(EyeIcon,null))),isRunning?React3.createElement(WithTooltip,{hasChrome:!1,trigger:"hover",tooltip:React3.createElement(TooltipNote,{note:cancelling?"Stopping...":"Stop test run"})},React3.createElement(IconButton,{"aria-label":cancelling?"Stopping...":"Stop test run",padding:"none",size:"medium",onClick:()=>store.send({type:"CANCEL_RUN"}),disabled:cancelling||isStarting},React3.createElement(Progress,{percentage:finishedTestCount&&storeState.currentRun.totalTestCount?finishedTestCount/storeState.currentRun.totalTestCount*100:void 0},React3.createElement(StopIcon,null)))):React3.createElement(WithTooltip,{hasChrome:!1,trigger:"hover",tooltip:React3.createElement(TooltipNote,{note:"Start test run"})},React3.createElement(IconButton,{"aria-label":"Start test run",size:"medium",onClick:()=>store.send({type:"TRIGGER_RUN",payload:{storyIds:entry?api.findAllLeafStoryIds(entry.id):void 0,triggeredBy:entry?entry.type:"global"}})},React3.createElement(PlayHollowIcon,null))))),React3.createElement(Extras,null,React3.createElement(Row,null,React3.createElement(ListItem,{as:"label",title:"Interactions",icon:entry?null:React3.createElement(Form.Checkbox,{checked:!0,disabled:!0})}),React3.createElement(WithTooltip,{hasChrome:!1,trigger:"hover",tooltip:React3.createElement(TooltipNote,{note:componentTestStatusLabel})},React3.createElement(IconButton,{size:"medium",disabled:componentTestStatusValueToStoryIds["status-value:error"].length===0&&componentTestStatusValueToStoryIds["status-value:warning"].length===0&&componentTestStatusValueToStoryIds["status-value:success"].length===0,onClick:()=>{openPanel({api,panelId:PANEL_ID,entryId:componentTestStatusValueToStoryIds["status-value:error"][0]??componentTestStatusValueToStoryIds["status-value:warning"][0]??componentTestStatusValueToStoryIds["status-value:success"][0]??entry?.id});}},React3.createElement(TestStatusIcon,{status:componentTestStatusIcon,"aria-label":componentTestStatusLabel,isRunning}),componentTestStatusValueToStoryIds["status-value:error"].length+componentTestStatusValueToStoryIds["status-value:warning"].length||null))),!entry&&React3.createElement(Row,null,React3.createElement(ListItem,{as:"label",title:watching?React3.createElement(Muted,null,"Coverage (unavailable)"):"Coverage",icon:React3.createElement(Form.Checkbox,{checked:config.coverage,disabled:isRunning,onChange:()=>setStoreState(s=>({...s,config:{...s.config,coverage:!config.coverage}}))})}),React3.createElement(WithTooltip,{hasChrome:!1,trigger:"hover",tooltip:React3.createElement(TooltipNote,{note:watching?"Unavailable in watch mode":currentRun.triggeredBy&&!FULL_RUN_TRIGGERS.includes(currentRun.triggeredBy)?"Unavailable when running focused tests":isRunning?"Testing in progress":currentRun.coverageSummary?"View coverage report":fatalError?"Component tests crashed":"Run tests to calculate coverage"})},watching||currentRun.triggeredBy&&!FULL_RUN_TRIGGERS.includes(currentRun.triggeredBy)?React3.createElement(IconButton,{size:"medium",disabled:!0},React3.createElement(InfoIcon,{"aria-label":watching?"Coverage is unavailable in watch mode":"Coverage is unavailable when running focused tests"})):currentRun.coverageSummary?React3.createElement(IconButton,{asChild:!0,size:"medium"},React3.createElement("a",{href:"/coverage/index.html",target:"_blank","aria-label":"Open coverage report"},React3.createElement(TestStatusIcon,{isRunning,percentage:currentRun.coverageSummary.percentage,status:currentRun.coverageSummary.status,"aria-label":`Coverage status: ${currentRun.coverageSummary.status}`}),React3.createElement("span",{"aria-label":`${currentRun.coverageSummary.percentage} percent coverage`},currentRun.coverageSummary.percentage,"%"))):React3.createElement(IconButton,{size:"medium",disabled:!0},React3.createElement(TestStatusIcon,{isRunning,status:fatalError?"critical":"unknown","aria-label":"Coverage status: unknown"})))),hasA11yAddon&&React3.createElement(Row,null,React3.createElement(ListItem,{as:"label",title:"Accessibility",icon:entry?null:React3.createElement(Form.Checkbox,{checked:config.a11y,disabled:isRunning,onChange:()=>setStoreState(s=>({...s,config:{...s.config,a11y:!config.a11y}}))})}),React3.createElement(WithTooltip,{hasChrome:!1,trigger:"hover",tooltip:React3.createElement(TooltipNote,{note:a11yStatusLabel})},React3.createElement(IconButton,{size:"medium",disabled:a11yStatusValueToStoryIds["status-value:error"].length===0&&a11yStatusValueToStoryIds["status-value:warning"].length===0&&a11yStatusValueToStoryIds["status-value:success"].length===0,onClick:()=>{openPanel({api,entryId:a11yStatusValueToStoryIds["status-value:error"][0]??a11yStatusValueToStoryIds["status-value:warning"][0]??a11yStatusValueToStoryIds["status-value:success"][0]??entry?.id,panelId:PANEL_ID2});}},React3.createElement(TestStatusIcon,{status:a11yStatusIcon,"aria-label":a11yStatusLabel,isRunning}),a11yStatusValueToStoryIds["status-value:error"].length+a11yStatusValueToStoryIds["status-value:warning"].length||null)))))};var SidebarContextMenu=({context,api})=>{let{testProviderState,componentTestStatusValueToStoryIds,a11yStatusValueToStoryIds,storeState,setStoreState}=useTestProvider(api,context.id);return React3.createElement(TestProviderRender,{api,entry:context,style:{minWidth:240},testProviderState,componentTestStatusValueToStoryIds,a11yStatusValueToStoryIds,storeState,setStoreState,isSettingsUpdated:!1})};addons.register(ADDON_ID3,api=>{if((globalThis.STORYBOOK_BUILDER||"").includes("vite")){let openPanel2=panelId=>{api.setSelectedPanel(panelId),api.togglePanel(!0);};componentTestStatusStore.onSelect(()=>{openPanel2(PANEL_ID);}),a11yStatusStore.onSelect(()=>{openPanel2(PANEL_ID2);}),testProviderStore.onRunAll(()=>{store.send({type:"TRIGGER_RUN",payload:{triggeredBy:"run-all"}});}),store.untilReady().then(()=>{store.setState(state=>({...state,indexUrl:new URL("index.json",window.location.href).toString()}));}),addons.add(TEST_PROVIDER_ID,{type:Addon_TypesEnum.experimental_TEST_PROVIDER,render:()=>{let[isModalOpen,setModalOpen]=useState(!1),{storeState,setStoreState,testProviderState,componentTestStatusValueToStoryIds,a11yStatusValueToStoryIds,isSettingsUpdated}=useTestProvider(api);return React3.createElement(GlobalErrorContext.Provider,{value:{isModalOpen,setModalOpen}},React3.createElement(TestProviderRender,{api,storeState,setStoreState,isSettingsUpdated,testProviderState,componentTestStatusValueToStoryIds,a11yStatusValueToStoryIds}),React3.createElement(GlobalErrorModal,{storeState,onRerun:()=>{setModalOpen(!1),store.send({type:"TRIGGER_RUN",payload:{triggeredBy:"global"}});}}))},sidebarContextMenu:({context})=>context.type==="docs"||context.type==="story"&&!context.tags.includes("test")?null:React3.createElement(SidebarContextMenu,{context,api})});}});
1
+ import {
2
+ ADDON_ID,
3
+ ADDON_ID2,
4
+ DOCUMENTATION_FATAL_ERROR_LINK,
5
+ FULL_RUN_TRIGGERS,
6
+ PANEL_ID,
7
+ PANEL_ID2,
8
+ STATUS_TYPE_ID_A11Y,
9
+ STATUS_TYPE_ID_COMPONENT_TEST,
10
+ TEST_PROVIDER_ID,
11
+ storeOptions
12
+ } from "./_browser-chunks/chunk-PMYV6BH2.js";
13
+ import {
14
+ __name
15
+ } from "./_browser-chunks/chunk-JK72E6FR.js";
16
+
17
+ // src/manager.tsx
18
+ import React5, { useState as useState3 } from "react";
19
+ import { Addon_TypesEnum } from "storybook/internal/types";
20
+
21
+ // src/manager-store.ts
22
+ import {
23
+ experimental_UniversalStore,
24
+ experimental_getStatusStore,
25
+ experimental_getTestProviderStore
26
+ } from "storybook/manager-api";
27
+ var store = experimental_UniversalStore.create({
28
+ ...storeOptions,
29
+ leader: globalThis.CONFIG_TYPE === "PRODUCTION"
30
+ });
31
+ var componentTestStatusStore = experimental_getStatusStore(STATUS_TYPE_ID_COMPONENT_TEST);
32
+ var a11yStatusStore = experimental_getStatusStore(STATUS_TYPE_ID_A11Y);
33
+ var testProviderStore = experimental_getTestProviderStore(ADDON_ID2);
34
+
35
+ // src/manager.tsx
36
+ import { addons as addons2 } from "storybook/manager-api";
37
+
38
+ // src/components/GlobalErrorModal.tsx
39
+ import React, { useContext } from "react";
40
+ import { Button, IconButton, Modal } from "storybook/internal/components";
41
+ import { CloseIcon, SyncIcon } from "@storybook/icons";
42
+ import { useStorybookApi } from "storybook/manager-api";
43
+ import { styled } from "storybook/theming";
44
+ var ModalBar = styled.div({
45
+ display: "flex",
46
+ justifyContent: "space-between",
47
+ alignItems: "center",
48
+ padding: "6px 6px 6px 20px"
49
+ });
50
+ var ModalActionBar = styled.div({
51
+ display: "flex",
52
+ justifyContent: "space-between",
53
+ alignItems: "center"
54
+ });
55
+ var ModalTitle = styled(Modal.Title)(({ theme: { typography } }) => ({
56
+ fontSize: typography.size.s2,
57
+ fontWeight: typography.weight.bold
58
+ }));
59
+ var ModalStackTrace = styled.pre(({ theme }) => ({
60
+ whiteSpace: "pre-wrap",
61
+ wordWrap: "break-word",
62
+ overflow: "auto",
63
+ maxHeight: "60vh",
64
+ margin: 0,
65
+ padding: `20px`,
66
+ fontFamily: theme.typography.fonts.mono,
67
+ fontSize: "12px",
68
+ borderTop: `1px solid ${theme.appBorderColor}`,
69
+ borderRadius: 0
70
+ }));
71
+ var TroubleshootLink = styled.a(({ theme }) => ({
72
+ color: theme.color.defaultText
73
+ }));
74
+ var GlobalErrorContext = React.createContext({
75
+ isModalOpen: false,
76
+ setModalOpen: void 0
77
+ });
78
+ function ErrorCause({ error }) {
79
+ if (!error) {
80
+ return null;
81
+ }
82
+ return React.createElement("div", null, React.createElement("h4", null, "Caused by: ", error.name || "Error", ": ", error.message), error.stack && React.createElement("pre", null, error.stack), error.cause && React.createElement(ErrorCause, { error: error.cause }));
83
+ }
84
+ __name(ErrorCause, "ErrorCause");
85
+ function GlobalErrorModal({ onRerun, storeState }) {
86
+ const api = useStorybookApi();
87
+ const { isModalOpen, setModalOpen } = useContext(GlobalErrorContext);
88
+ const handleClose = /* @__PURE__ */ __name(() => setModalOpen?.(false), "handleClose");
89
+ const troubleshootURL = api.getDocsUrl({
90
+ subpath: DOCUMENTATION_FATAL_ERROR_LINK,
91
+ versioned: true,
92
+ renderer: true
93
+ });
94
+ const {
95
+ fatalError,
96
+ currentRun: { unhandledErrors }
97
+ } = storeState;
98
+ const content = fatalError ? React.createElement(React.Fragment, null, React.createElement("p", null, fatalError.error.name || "Error"), fatalError.message && React.createElement("p", null, fatalError.message), fatalError.error.message && React.createElement("p", null, fatalError.error.message), fatalError.error.stack && React.createElement("p", null, fatalError.error.stack), fatalError.error.cause && React.createElement(ErrorCause, { error: fatalError.error.cause })) : unhandledErrors.length > 0 ? React.createElement("ol", null, unhandledErrors.map((error) => React.createElement("li", { key: error.name + error.message }, React.createElement("p", null, error.name, ": ", error.message), error.VITEST_TEST_PATH && React.createElement("p", null, 'This error originated in "', React.createElement("b", null, error.VITEST_TEST_PATH), `". It doesn't mean the error was thrown inside the file itself, but while it was running.`), error.VITEST_TEST_NAME && React.createElement(React.Fragment, null, React.createElement("p", null, `The latest test that might've caused the error is "`, React.createElement("b", null, error.VITEST_TEST_NAME), '". It might mean one of the following:'), React.createElement("ul", null, React.createElement("li", null, "The error was thrown, while Vitest was running this test."), React.createElement("li", null, "If the error occurred after the test had been completed, this was the last documented test before it was thrown."))), error.stacks && React.createElement(React.Fragment, null, React.createElement("p", null, React.createElement("b", null, "Stacks:")), React.createElement("ul", null, error.stacks.map((stack) => React.createElement("li", { key: stack.file + stack.line + stack.column }, stack.file, ":", stack.line, ":", stack.column, " - ", stack.method || "unknown method")))), error.stack && React.createElement("p", null, error.stack), error.cause ? React.createElement(ErrorCause, { error: error.cause }) : null))) : null;
99
+ return React.createElement(Modal, { onEscapeKeyDown: handleClose, onInteractOutside: handleClose, open: isModalOpen }, React.createElement(ModalBar, null, React.createElement(ModalTitle, null, "Storybook Tests error details"), React.createElement(ModalActionBar, null, React.createElement(Button, { onClick: onRerun, variant: "ghost" }, React.createElement(SyncIcon, null), "Rerun"), React.createElement(Button, { variant: "ghost", asChild: true }, React.createElement("a", { target: "_blank", href: troubleshootURL, rel: "noreferrer" }, "Troubleshoot")), React.createElement(IconButton, { onClick: handleClose, "aria-label": "Close modal" }, React.createElement(CloseIcon, null)))), React.createElement(ModalStackTrace, null, content, React.createElement("br", null), React.createElement("br", null), "Troubleshoot:", " ", React.createElement(TroubleshootLink, { target: "_blank", href: troubleshootURL }, troubleshootURL)));
100
+ }
101
+ __name(GlobalErrorModal, "GlobalErrorModal");
102
+
103
+ // src/components/SidebarContextMenu.tsx
104
+ import React4 from "react";
105
+
106
+ // src/use-test-provider-state.ts
107
+ import { useCallback, useEffect, useMemo, useRef, useState } from "react";
108
+
109
+ // ../../node_modules/es-toolkit/dist/predicate/isPlainObject.mjs
110
+ function isPlainObject(value) {
111
+ if (!value || typeof value !== "object") {
112
+ return false;
113
+ }
114
+ const proto = Object.getPrototypeOf(value);
115
+ const hasObjectPrototype = proto === null || proto === Object.prototype || Object.getPrototypeOf(proto) === null;
116
+ if (!hasObjectPrototype) {
117
+ return false;
118
+ }
119
+ return Object.prototype.toString.call(value) === "[object Object]";
120
+ }
121
+ __name(isPlainObject, "isPlainObject");
122
+
123
+ // ../../node_modules/es-toolkit/dist/compat/_internal/getSymbols.mjs
124
+ function getSymbols(object) {
125
+ return Object.getOwnPropertySymbols(object).filter((symbol) => Object.prototype.propertyIsEnumerable.call(object, symbol));
126
+ }
127
+ __name(getSymbols, "getSymbols");
128
+
129
+ // ../../node_modules/es-toolkit/dist/compat/_internal/getTag.mjs
130
+ function getTag(value) {
131
+ if (value == null) {
132
+ return value === void 0 ? "[object Undefined]" : "[object Null]";
133
+ }
134
+ return Object.prototype.toString.call(value);
135
+ }
136
+ __name(getTag, "getTag");
137
+
138
+ // ../../node_modules/es-toolkit/dist/compat/_internal/tags.mjs
139
+ var regexpTag = "[object RegExp]";
140
+ var stringTag = "[object String]";
141
+ var numberTag = "[object Number]";
142
+ var booleanTag = "[object Boolean]";
143
+ var argumentsTag = "[object Arguments]";
144
+ var symbolTag = "[object Symbol]";
145
+ var dateTag = "[object Date]";
146
+ var mapTag = "[object Map]";
147
+ var setTag = "[object Set]";
148
+ var arrayTag = "[object Array]";
149
+ var functionTag = "[object Function]";
150
+ var arrayBufferTag = "[object ArrayBuffer]";
151
+ var objectTag = "[object Object]";
152
+ var errorTag = "[object Error]";
153
+ var dataViewTag = "[object DataView]";
154
+ var uint8ArrayTag = "[object Uint8Array]";
155
+ var uint8ClampedArrayTag = "[object Uint8ClampedArray]";
156
+ var uint16ArrayTag = "[object Uint16Array]";
157
+ var uint32ArrayTag = "[object Uint32Array]";
158
+ var bigUint64ArrayTag = "[object BigUint64Array]";
159
+ var int8ArrayTag = "[object Int8Array]";
160
+ var int16ArrayTag = "[object Int16Array]";
161
+ var int32ArrayTag = "[object Int32Array]";
162
+ var bigInt64ArrayTag = "[object BigInt64Array]";
163
+ var float32ArrayTag = "[object Float32Array]";
164
+ var float64ArrayTag = "[object Float64Array]";
165
+
166
+ // ../../node_modules/es-toolkit/dist/compat/util/eq.mjs
167
+ function eq(value, other) {
168
+ return value === other || Number.isNaN(value) && Number.isNaN(other);
169
+ }
170
+ __name(eq, "eq");
171
+
172
+ // ../../node_modules/es-toolkit/dist/predicate/isEqualWith.mjs
173
+ function isEqualWith(a, b, areValuesEqual) {
174
+ return isEqualWithImpl(a, b, void 0, void 0, void 0, void 0, areValuesEqual);
175
+ }
176
+ __name(isEqualWith, "isEqualWith");
177
+ function isEqualWithImpl(a, b, property, aParent, bParent, stack, areValuesEqual) {
178
+ const result = areValuesEqual(a, b, property, aParent, bParent, stack);
179
+ if (result !== void 0) {
180
+ return result;
181
+ }
182
+ if (typeof a === typeof b) {
183
+ switch (typeof a) {
184
+ case "bigint":
185
+ case "string":
186
+ case "boolean":
187
+ case "symbol":
188
+ case "undefined": {
189
+ return a === b;
190
+ }
191
+ case "number": {
192
+ return a === b || Object.is(a, b);
193
+ }
194
+ case "function": {
195
+ return a === b;
196
+ }
197
+ case "object": {
198
+ return areObjectsEqual(a, b, stack, areValuesEqual);
199
+ }
200
+ }
201
+ }
202
+ return areObjectsEqual(a, b, stack, areValuesEqual);
203
+ }
204
+ __name(isEqualWithImpl, "isEqualWithImpl");
205
+ function areObjectsEqual(a, b, stack, areValuesEqual) {
206
+ if (Object.is(a, b)) {
207
+ return true;
208
+ }
209
+ let aTag = getTag(a);
210
+ let bTag = getTag(b);
211
+ if (aTag === argumentsTag) {
212
+ aTag = objectTag;
213
+ }
214
+ if (bTag === argumentsTag) {
215
+ bTag = objectTag;
216
+ }
217
+ if (aTag !== bTag) {
218
+ return false;
219
+ }
220
+ switch (aTag) {
221
+ case stringTag:
222
+ return a.toString() === b.toString();
223
+ case numberTag: {
224
+ const x = a.valueOf();
225
+ const y = b.valueOf();
226
+ return eq(x, y);
227
+ }
228
+ case booleanTag:
229
+ case dateTag:
230
+ case symbolTag:
231
+ return Object.is(a.valueOf(), b.valueOf());
232
+ case regexpTag: {
233
+ return a.source === b.source && a.flags === b.flags;
234
+ }
235
+ case functionTag: {
236
+ return a === b;
237
+ }
238
+ }
239
+ stack = stack ?? /* @__PURE__ */ new Map();
240
+ const aStack = stack.get(a);
241
+ const bStack = stack.get(b);
242
+ if (aStack != null && bStack != null) {
243
+ return aStack === b;
244
+ }
245
+ stack.set(a, b);
246
+ stack.set(b, a);
247
+ try {
248
+ switch (aTag) {
249
+ case mapTag: {
250
+ if (a.size !== b.size) {
251
+ return false;
252
+ }
253
+ for (const [key, value] of a.entries()) {
254
+ if (!b.has(key) || !isEqualWithImpl(value, b.get(key), key, a, b, stack, areValuesEqual)) {
255
+ return false;
256
+ }
257
+ }
258
+ return true;
259
+ }
260
+ case setTag: {
261
+ if (a.size !== b.size) {
262
+ return false;
263
+ }
264
+ const aValues = Array.from(a.values());
265
+ const bValues = Array.from(b.values());
266
+ for (let i = 0; i < aValues.length; i++) {
267
+ const aValue = aValues[i];
268
+ const index = bValues.findIndex((bValue) => {
269
+ return isEqualWithImpl(aValue, bValue, void 0, a, b, stack, areValuesEqual);
270
+ });
271
+ if (index === -1) {
272
+ return false;
273
+ }
274
+ bValues.splice(index, 1);
275
+ }
276
+ return true;
277
+ }
278
+ case arrayTag:
279
+ case uint8ArrayTag:
280
+ case uint8ClampedArrayTag:
281
+ case uint16ArrayTag:
282
+ case uint32ArrayTag:
283
+ case bigUint64ArrayTag:
284
+ case int8ArrayTag:
285
+ case int16ArrayTag:
286
+ case int32ArrayTag:
287
+ case bigInt64ArrayTag:
288
+ case float32ArrayTag:
289
+ case float64ArrayTag: {
290
+ if (typeof Buffer !== "undefined" && Buffer.isBuffer(a) !== Buffer.isBuffer(b)) {
291
+ return false;
292
+ }
293
+ if (a.length !== b.length) {
294
+ return false;
295
+ }
296
+ for (let i = 0; i < a.length; i++) {
297
+ if (!isEqualWithImpl(a[i], b[i], i, a, b, stack, areValuesEqual)) {
298
+ return false;
299
+ }
300
+ }
301
+ return true;
302
+ }
303
+ case arrayBufferTag: {
304
+ if (a.byteLength !== b.byteLength) {
305
+ return false;
306
+ }
307
+ return areObjectsEqual(new Uint8Array(a), new Uint8Array(b), stack, areValuesEqual);
308
+ }
309
+ case dataViewTag: {
310
+ if (a.byteLength !== b.byteLength || a.byteOffset !== b.byteOffset) {
311
+ return false;
312
+ }
313
+ return areObjectsEqual(new Uint8Array(a), new Uint8Array(b), stack, areValuesEqual);
314
+ }
315
+ case errorTag: {
316
+ return a.name === b.name && a.message === b.message;
317
+ }
318
+ case objectTag: {
319
+ const areEqualInstances = areObjectsEqual(a.constructor, b.constructor, stack, areValuesEqual) || isPlainObject(a) && isPlainObject(b);
320
+ if (!areEqualInstances) {
321
+ return false;
322
+ }
323
+ const aKeys = [...Object.keys(a), ...getSymbols(a)];
324
+ const bKeys = [...Object.keys(b), ...getSymbols(b)];
325
+ if (aKeys.length !== bKeys.length) {
326
+ return false;
327
+ }
328
+ for (let i = 0; i < aKeys.length; i++) {
329
+ const propKey = aKeys[i];
330
+ const aProp = a[propKey];
331
+ if (!Object.hasOwn(b, propKey)) {
332
+ return false;
333
+ }
334
+ const bProp = b[propKey];
335
+ if (!isEqualWithImpl(aProp, bProp, propKey, a, b, stack, areValuesEqual)) {
336
+ return false;
337
+ }
338
+ }
339
+ return true;
340
+ }
341
+ default: {
342
+ return false;
343
+ }
344
+ }
345
+ } finally {
346
+ stack.delete(a);
347
+ stack.delete(b);
348
+ }
349
+ }
350
+ __name(areObjectsEqual, "areObjectsEqual");
351
+
352
+ // ../../node_modules/es-toolkit/dist/function/noop.mjs
353
+ function noop() {
354
+ }
355
+ __name(noop, "noop");
356
+
357
+ // ../../node_modules/es-toolkit/dist/predicate/isEqual.mjs
358
+ function isEqual(a, b) {
359
+ return isEqualWith(a, b, noop);
360
+ }
361
+ __name(isEqual, "isEqual");
362
+
363
+ // src/use-test-provider-state.ts
364
+ import {
365
+ experimental_useStatusStore,
366
+ experimental_useTestProviderStore,
367
+ experimental_useUniversalStore
368
+ } from "storybook/manager-api";
369
+ var statusValueToStoryIds = /* @__PURE__ */ __name((allStatuses, typeId, storyIds) => {
370
+ const statusValueToStoryIdsMap = {
371
+ "status-value:pending": [],
372
+ "status-value:success": [],
373
+ "status-value:error": [],
374
+ "status-value:warning": [],
375
+ "status-value:unknown": []
376
+ };
377
+ const stories = storyIds ? storyIds.map((storyId) => allStatuses[storyId]).filter(Boolean) : Object.values(allStatuses);
378
+ stories.forEach((statusByTypeId) => {
379
+ const status = statusByTypeId[typeId];
380
+ if (!status) {
381
+ return;
382
+ }
383
+ statusValueToStoryIdsMap[status.value].push(status.storyId);
384
+ });
385
+ return statusValueToStoryIdsMap;
386
+ }, "statusValueToStoryIds");
387
+ var useTestProvider = /* @__PURE__ */ __name((api, entryId) => {
388
+ const testProviderState = experimental_useTestProviderStore((s) => s[ADDON_ID2]);
389
+ const [storeState, setStoreState] = experimental_useUniversalStore(store);
390
+ const [isSettingsUpdated, setIsSettingsUpdated] = useState(false);
391
+ const settingsUpdatedTimeoutRef = useRef();
392
+ useEffect(() => {
393
+ const unsubscribe = store.onStateChange((state, previousState) => {
394
+ if (!isEqual(state.config, previousState.config)) {
395
+ testProviderStore.settingsChanged();
396
+ setIsSettingsUpdated(true);
397
+ clearTimeout(settingsUpdatedTimeoutRef.current);
398
+ settingsUpdatedTimeoutRef.current = setTimeout(() => {
399
+ setIsSettingsUpdated(false);
400
+ }, 1e3);
401
+ }
402
+ });
403
+ return () => {
404
+ unsubscribe();
405
+ clearTimeout(settingsUpdatedTimeoutRef.current);
406
+ };
407
+ }, []);
408
+ const storyIds = useMemo(
409
+ () => entryId ? api.findAllLeafStoryIds(entryId) : void 0,
410
+ [entryId, api]
411
+ );
412
+ const componentTestStatusSelector = useCallback(
413
+ (allStatuses) => statusValueToStoryIds(allStatuses, STATUS_TYPE_ID_COMPONENT_TEST, storyIds),
414
+ [storyIds]
415
+ );
416
+ const componentTestStatusValueToStoryIds = experimental_useStatusStore(
417
+ componentTestStatusSelector
418
+ );
419
+ const a11yStatusValueToStoryIdsSelector = useCallback(
420
+ (allStatuses) => statusValueToStoryIds(allStatuses, STATUS_TYPE_ID_A11Y, storyIds),
421
+ [storyIds]
422
+ );
423
+ const a11yStatusValueToStoryIds = experimental_useStatusStore(a11yStatusValueToStoryIdsSelector);
424
+ return {
425
+ storeState,
426
+ setStoreState,
427
+ testProviderState,
428
+ componentTestStatusValueToStoryIds,
429
+ a11yStatusValueToStoryIds,
430
+ isSettingsUpdated
431
+ };
432
+ }, "useTestProvider");
433
+
434
+ // src/components/TestProviderRender.tsx
435
+ import React3 from "react";
436
+ import {
437
+ Form,
438
+ IconButton as IconButton2,
439
+ ListItem,
440
+ ProgressSpinner,
441
+ TooltipNote,
442
+ WithTooltip
443
+ } from "storybook/internal/components";
444
+ import { EyeIcon, InfoIcon, PlayHollowIcon, StopAltIcon } from "@storybook/icons";
445
+ import { addons } from "storybook/manager-api";
446
+ import { styled as styled4 } from "storybook/theming";
447
+
448
+ // src/components/Description.tsx
449
+ import React2 from "react";
450
+ import { Link as LinkComponent } from "storybook/internal/components";
451
+ import { styled as styled2 } from "storybook/theming";
452
+
453
+ // src/components/RelativeTime.tsx
454
+ import { useEffect as useEffect2, useState as useState2 } from "react";
455
+ var RelativeTime = /* @__PURE__ */ __name(({ timestamp }) => {
456
+ const [timeAgo, setTimeAgo] = useState2(null);
457
+ useEffect2(() => {
458
+ if (timestamp) {
459
+ setTimeAgo(Date.now() - timestamp);
460
+ const interval = setInterval(() => setTimeAgo(Date.now() - timestamp), 1e4);
461
+ return () => clearInterval(interval);
462
+ }
463
+ }, [timestamp]);
464
+ if (timeAgo === null) {
465
+ return null;
466
+ }
467
+ const seconds = Math.round(timeAgo / 1e3);
468
+ if (seconds < 60) {
469
+ return `just now`;
470
+ }
471
+ const minutes = Math.floor(seconds / 60);
472
+ if (minutes < 60) {
473
+ return minutes === 1 ? `a minute ago` : `${minutes} minutes ago`;
474
+ }
475
+ const hours = Math.floor(minutes / 60);
476
+ if (hours < 24) {
477
+ return hours === 1 ? `an hour ago` : `${hours} hours ago`;
478
+ }
479
+ const days = Math.floor(hours / 24);
480
+ return days === 1 ? `yesterday` : `${days} days ago`;
481
+ }, "RelativeTime");
482
+
483
+ // src/components/Description.tsx
484
+ var Wrapper = styled2.div(({ theme }) => ({
485
+ overflow: "hidden",
486
+ whiteSpace: "nowrap",
487
+ textOverflow: "ellipsis",
488
+ fontSize: theme.typography.size.s1,
489
+ color: theme.textMutedColor
490
+ }));
491
+ var PositiveText = styled2.span(({ theme }) => ({
492
+ color: theme.color.positiveText
493
+ }));
494
+ function Description({
495
+ entryId,
496
+ storeState,
497
+ testProviderState,
498
+ isSettingsUpdated,
499
+ ...props
500
+ }) {
501
+ const { setModalOpen } = React2.useContext(GlobalErrorContext);
502
+ const { componentTestCount, totalTestCount, unhandledErrors, finishedAt } = storeState.currentRun;
503
+ const finishedTestCount = componentTestCount.success + componentTestCount.error;
504
+ let description = "Not run";
505
+ if (!entryId && isSettingsUpdated) {
506
+ description = React2.createElement(PositiveText, null, "Settings updated");
507
+ } else if (testProviderState === "test-provider-state:running") {
508
+ description = (finishedTestCount ?? 0) === 0 ? "Starting..." : `Testing... ${finishedTestCount}/${totalTestCount}`;
509
+ } else if (!entryId && testProviderState === "test-provider-state:crashed") {
510
+ description = setModalOpen ? React2.createElement(LinkComponent, { isButton: true, onClick: () => setModalOpen(true) }, "View full error") : "Crashed";
511
+ } else if (!entryId && unhandledErrors.length > 0) {
512
+ const unhandledErrorDescription = `View ${unhandledErrors.length} unhandled error${unhandledErrors?.length > 1 ? "s" : ""}`;
513
+ description = setModalOpen ? React2.createElement(LinkComponent, { isButton: true, onClick: () => setModalOpen(true) }, unhandledErrorDescription) : unhandledErrorDescription;
514
+ } else if (entryId && totalTestCount) {
515
+ description = `Ran ${totalTestCount} ${totalTestCount === 1 ? "test" : "tests"}`;
516
+ } else if (finishedAt) {
517
+ description = React2.createElement(React2.Fragment, null, "Ran ", totalTestCount, " ", totalTestCount === 1 ? "test" : "tests", " ", React2.createElement(RelativeTime, { timestamp: finishedAt }));
518
+ } else if (storeState.watching) {
519
+ description = "Watching for file changes";
520
+ }
521
+ return React2.createElement(Wrapper, { ...props }, description);
522
+ }
523
+ __name(Description, "Description");
524
+
525
+ // src/components/TestStatusIcon.tsx
526
+ import { styled as styled3 } from "storybook/theming";
527
+ var TestStatusIcon = styled3.div(
528
+ ({ percentage }) => ({
529
+ width: percentage ? 12 : 6,
530
+ height: percentage ? 12 : 6,
531
+ margin: percentage ? 1 : 4,
532
+ background: percentage ? `conic-gradient(var(--status-color) ${percentage}%, var(--status-background) ${percentage + 1}%)` : "var(--status-color)",
533
+ borderRadius: "50%"
534
+ }),
535
+ ({ isRunning, theme }) => isRunning && {
536
+ animation: `${theme.animation.glow} 1.5s ease-in-out infinite`
537
+ },
538
+ ({ status, theme }) => status === "positive" && {
539
+ "--status-color": theme.color.positive,
540
+ "--status-background": `${theme.color.positive}66`
541
+ },
542
+ ({ status, theme }) => status === "warning" && {
543
+ "--status-color": theme.color.gold,
544
+ "--status-background": `${theme.color.gold}66`
545
+ },
546
+ ({ status, theme }) => status === "negative" && {
547
+ "--status-color": theme.color.negative,
548
+ "--status-background": `${theme.color.negative}66`
549
+ },
550
+ ({ status, theme }) => status === "critical" && {
551
+ "--status-color": theme.color.defaultText,
552
+ "--status-background": `${theme.color.defaultText}66`
553
+ },
554
+ ({ status, theme }) => status === "unknown" && {
555
+ "--status-color": theme.color.mediumdark,
556
+ "--status-background": `${theme.color.mediumdark}66`
557
+ }
558
+ );
559
+
560
+ // src/components/TestProviderRender.tsx
561
+ var Container = styled4.div({
562
+ display: "flex",
563
+ flexDirection: "column"
564
+ });
565
+ var Heading = styled4.div({
566
+ display: "flex",
567
+ justifyContent: "space-between",
568
+ padding: "8px 0",
569
+ gap: 12
570
+ });
571
+ var Info = styled4.div({
572
+ display: "flex",
573
+ flexDirection: "column",
574
+ marginLeft: 8,
575
+ minWidth: 0
576
+ });
577
+ var Title = styled4.div(({ crashed, theme }) => ({
578
+ fontSize: theme.typography.size.s1,
579
+ fontWeight: crashed ? "bold" : "normal",
580
+ color: crashed ? theme.color.negativeText : theme.color.defaultText
581
+ }));
582
+ var Actions = styled4.div({
583
+ display: "flex",
584
+ gap: 4
585
+ });
586
+ var Extras = styled4.div({
587
+ marginBottom: 2
588
+ });
589
+ var Muted = styled4.span(({ theme }) => ({
590
+ color: theme.textMutedColor
591
+ }));
592
+ var Progress = styled4(ProgressSpinner)({
593
+ margin: 4
594
+ });
595
+ var Row = styled4.div({
596
+ display: "flex",
597
+ gap: 4
598
+ });
599
+ var StopIcon = styled4(StopAltIcon)({
600
+ width: 10
601
+ });
602
+ var openPanel = /* @__PURE__ */ __name(({ api, panelId, entryId }) => {
603
+ const story = entryId ? api.findAllLeafStoryIds(entryId)[0] : void 0;
604
+ if (story) {
605
+ api.selectStory(story);
606
+ }
607
+ api.setSelectedPanel(panelId);
608
+ api.togglePanel(true);
609
+ }, "openPanel");
610
+ var TestProviderRender = /* @__PURE__ */ __name(({
611
+ api,
612
+ entry,
613
+ testProviderState,
614
+ storeState,
615
+ setStoreState,
616
+ componentTestStatusValueToStoryIds,
617
+ a11yStatusValueToStoryIds,
618
+ isSettingsUpdated,
619
+ ...props
620
+ }) => {
621
+ const { config, watching, cancelling, currentRun, fatalError } = storeState;
622
+ const finishedTestCount = currentRun.componentTestCount.success + currentRun.componentTestCount.error;
623
+ const hasA11yAddon = addons.experimental_getRegisteredAddons().includes(ADDON_ID);
624
+ const isRunning = testProviderState === "test-provider-state:running";
625
+ const isStarting = isRunning && finishedTestCount === 0;
626
+ const [componentTestStatusIcon, componentTestStatusLabel] = fatalError ? ["critical", "Component tests crashed"] : componentTestStatusValueToStoryIds["status-value:error"].length > 0 ? ["negative", "Component tests failed"] : isRunning ? ["unknown", "Testing in progress"] : componentTestStatusValueToStoryIds["status-value:success"].length > 0 ? ["positive", "Component tests passed"] : ["unknown", "Run tests to see results"];
627
+ const [a11yStatusIcon, a11yStatusLabel] = fatalError ? ["critical", "Component tests crashed"] : a11yStatusValueToStoryIds["status-value:error"].length > 0 ? ["negative", "Accessibility tests failed"] : a11yStatusValueToStoryIds["status-value:warning"].length > 0 ? ["warning", "Accessibility tests failed"] : isRunning ? ["unknown", "Testing in progress"] : a11yStatusValueToStoryIds["status-value:success"].length > 0 ? ["positive", "Accessibility tests passed"] : ["unknown", "Run tests to see accessibility results"];
628
+ return React3.createElement(Container, { ...props }, React3.createElement(Heading, null, React3.createElement(Info, null, entry ? React3.createElement(Title, { id: "testing-module-title" }, "Run component tests") : React3.createElement(
629
+ Title,
630
+ {
631
+ id: "testing-module-title",
632
+ crashed: testProviderState === "test-provider-state:crashed" || fatalError !== void 0 || currentRun.unhandledErrors.length > 0
633
+ },
634
+ currentRun.unhandledErrors.length === 1 ? "Component tests completed with an error" : currentRun.unhandledErrors.length > 1 ? "Component tests completed with errors" : fatalError ? "Component tests didn\u2019t complete" : "Run component tests"
635
+ ), React3.createElement(
636
+ Description,
637
+ {
638
+ id: "testing-module-description",
639
+ storeState,
640
+ testProviderState,
641
+ entryId: entry?.id,
642
+ isSettingsUpdated
643
+ }
644
+ )), React3.createElement(Actions, null, !entry && React3.createElement(
645
+ WithTooltip,
646
+ {
647
+ hasChrome: false,
648
+ trigger: "hover",
649
+ tooltip: React3.createElement(TooltipNote, { note: `${watching ? "Disable" : "Enable"} watch mode` })
650
+ },
651
+ React3.createElement(
652
+ IconButton2,
653
+ {
654
+ "aria-label": `${watching ? "Disable" : "Enable"} watch mode`,
655
+ size: "medium",
656
+ active: watching,
657
+ onClick: () => store.send({
658
+ type: "TOGGLE_WATCHING",
659
+ payload: {
660
+ to: !watching
661
+ }
662
+ }),
663
+ disabled: isRunning
664
+ },
665
+ React3.createElement(EyeIcon, null)
666
+ )
667
+ ), isRunning ? React3.createElement(
668
+ WithTooltip,
669
+ {
670
+ hasChrome: false,
671
+ trigger: "hover",
672
+ tooltip: React3.createElement(TooltipNote, { note: cancelling ? "Stopping..." : "Stop test run" })
673
+ },
674
+ React3.createElement(
675
+ IconButton2,
676
+ {
677
+ "aria-label": cancelling ? "Stopping..." : "Stop test run",
678
+ padding: "none",
679
+ size: "medium",
680
+ onClick: () => store.send({
681
+ type: "CANCEL_RUN"
682
+ }),
683
+ disabled: cancelling || isStarting
684
+ },
685
+ React3.createElement(
686
+ Progress,
687
+ {
688
+ percentage: finishedTestCount && storeState.currentRun.totalTestCount ? finishedTestCount / storeState.currentRun.totalTestCount * 100 : void 0
689
+ },
690
+ React3.createElement(StopIcon, null)
691
+ )
692
+ )
693
+ ) : React3.createElement(
694
+ WithTooltip,
695
+ {
696
+ hasChrome: false,
697
+ trigger: "hover",
698
+ tooltip: React3.createElement(TooltipNote, { note: "Start test run" })
699
+ },
700
+ React3.createElement(
701
+ IconButton2,
702
+ {
703
+ "aria-label": "Start test run",
704
+ size: "medium",
705
+ onClick: () => store.send({
706
+ type: "TRIGGER_RUN",
707
+ payload: {
708
+ storyIds: entry ? api.findAllLeafStoryIds(entry.id) : void 0,
709
+ triggeredBy: entry ? entry.type : "global"
710
+ }
711
+ })
712
+ },
713
+ React3.createElement(PlayHollowIcon, null)
714
+ )
715
+ ))), React3.createElement(Extras, null, React3.createElement(Row, null, React3.createElement(
716
+ ListItem,
717
+ {
718
+ as: "label",
719
+ title: "Interactions",
720
+ icon: entry ? null : React3.createElement(Form.Checkbox, { checked: true, disabled: true })
721
+ }
722
+ ), React3.createElement(
723
+ WithTooltip,
724
+ {
725
+ hasChrome: false,
726
+ trigger: "hover",
727
+ tooltip: React3.createElement(TooltipNote, { note: componentTestStatusLabel })
728
+ },
729
+ React3.createElement(
730
+ IconButton2,
731
+ {
732
+ size: "medium",
733
+ disabled: componentTestStatusValueToStoryIds["status-value:error"].length === 0 && componentTestStatusValueToStoryIds["status-value:warning"].length === 0 && componentTestStatusValueToStoryIds["status-value:success"].length === 0,
734
+ onClick: () => {
735
+ openPanel({
736
+ api,
737
+ panelId: PANEL_ID,
738
+ entryId: componentTestStatusValueToStoryIds["status-value:error"][0] ?? componentTestStatusValueToStoryIds["status-value:warning"][0] ?? componentTestStatusValueToStoryIds["status-value:success"][0] ?? entry?.id
739
+ });
740
+ }
741
+ },
742
+ React3.createElement(
743
+ TestStatusIcon,
744
+ {
745
+ status: componentTestStatusIcon,
746
+ "aria-label": componentTestStatusLabel,
747
+ isRunning
748
+ }
749
+ ),
750
+ componentTestStatusValueToStoryIds["status-value:error"].length + componentTestStatusValueToStoryIds["status-value:warning"].length || null
751
+ )
752
+ )), !entry && React3.createElement(Row, null, React3.createElement(
753
+ ListItem,
754
+ {
755
+ as: "label",
756
+ title: watching ? React3.createElement(Muted, null, "Coverage (unavailable)") : "Coverage",
757
+ icon: React3.createElement(
758
+ Form.Checkbox,
759
+ {
760
+ checked: config.coverage,
761
+ disabled: isRunning,
762
+ onChange: () => setStoreState((s) => ({
763
+ ...s,
764
+ config: { ...s.config, coverage: !config.coverage }
765
+ }))
766
+ }
767
+ )
768
+ }
769
+ ), React3.createElement(
770
+ WithTooltip,
771
+ {
772
+ hasChrome: false,
773
+ trigger: "hover",
774
+ tooltip: React3.createElement(
775
+ TooltipNote,
776
+ {
777
+ note: watching ? "Unavailable in watch mode" : currentRun.triggeredBy && !FULL_RUN_TRIGGERS.includes(currentRun.triggeredBy) ? "Unavailable when running focused tests" : isRunning ? "Testing in progress" : currentRun.coverageSummary ? "View coverage report" : fatalError ? "Component tests crashed" : "Run tests to calculate coverage"
778
+ }
779
+ )
780
+ },
781
+ watching || currentRun.triggeredBy && !FULL_RUN_TRIGGERS.includes(currentRun.triggeredBy) ? React3.createElement(IconButton2, { size: "medium", disabled: true }, React3.createElement(
782
+ InfoIcon,
783
+ {
784
+ "aria-label": watching ? `Coverage is unavailable in watch mode` : `Coverage is unavailable when running focused tests`
785
+ }
786
+ )) : currentRun.coverageSummary ? React3.createElement(IconButton2, { asChild: true, size: "medium" }, React3.createElement("a", { href: "/coverage/index.html", target: "_blank", "aria-label": "Open coverage report" }, React3.createElement(
787
+ TestStatusIcon,
788
+ {
789
+ isRunning,
790
+ percentage: currentRun.coverageSummary.percentage,
791
+ status: currentRun.coverageSummary.status,
792
+ "aria-label": `Coverage status: ${currentRun.coverageSummary.status}`
793
+ }
794
+ ), React3.createElement("span", { "aria-label": `${currentRun.coverageSummary.percentage} percent coverage` }, currentRun.coverageSummary.percentage, "%"))) : React3.createElement(IconButton2, { size: "medium", disabled: true }, React3.createElement(
795
+ TestStatusIcon,
796
+ {
797
+ isRunning,
798
+ status: fatalError ? "critical" : "unknown",
799
+ "aria-label": "Coverage status: unknown"
800
+ }
801
+ ))
802
+ )), hasA11yAddon && React3.createElement(Row, null, React3.createElement(
803
+ ListItem,
804
+ {
805
+ as: "label",
806
+ title: "Accessibility",
807
+ icon: entry ? null : React3.createElement(
808
+ Form.Checkbox,
809
+ {
810
+ checked: config.a11y,
811
+ disabled: isRunning,
812
+ onChange: () => setStoreState((s) => ({
813
+ ...s,
814
+ config: { ...s.config, a11y: !config.a11y }
815
+ }))
816
+ }
817
+ )
818
+ }
819
+ ), React3.createElement(
820
+ WithTooltip,
821
+ {
822
+ hasChrome: false,
823
+ trigger: "hover",
824
+ tooltip: React3.createElement(TooltipNote, { note: a11yStatusLabel })
825
+ },
826
+ React3.createElement(
827
+ IconButton2,
828
+ {
829
+ size: "medium",
830
+ disabled: a11yStatusValueToStoryIds["status-value:error"].length === 0 && a11yStatusValueToStoryIds["status-value:warning"].length === 0 && a11yStatusValueToStoryIds["status-value:success"].length === 0,
831
+ onClick: () => {
832
+ openPanel({
833
+ api,
834
+ entryId: a11yStatusValueToStoryIds["status-value:error"][0] ?? a11yStatusValueToStoryIds["status-value:warning"][0] ?? a11yStatusValueToStoryIds["status-value:success"][0] ?? entry?.id,
835
+ panelId: PANEL_ID2
836
+ });
837
+ }
838
+ },
839
+ React3.createElement(
840
+ TestStatusIcon,
841
+ {
842
+ status: a11yStatusIcon,
843
+ "aria-label": a11yStatusLabel,
844
+ isRunning
845
+ }
846
+ ),
847
+ a11yStatusValueToStoryIds["status-value:error"].length + a11yStatusValueToStoryIds["status-value:warning"].length || null
848
+ )
849
+ ))));
850
+ }, "TestProviderRender");
851
+
852
+ // src/components/SidebarContextMenu.tsx
853
+ var SidebarContextMenu = /* @__PURE__ */ __name(({ context, api }) => {
854
+ const {
855
+ testProviderState,
856
+ componentTestStatusValueToStoryIds,
857
+ a11yStatusValueToStoryIds,
858
+ storeState,
859
+ setStoreState
860
+ } = useTestProvider(api, context.id);
861
+ return React4.createElement(
862
+ TestProviderRender,
863
+ {
864
+ api,
865
+ entry: context,
866
+ style: { minWidth: 240 },
867
+ testProviderState,
868
+ componentTestStatusValueToStoryIds,
869
+ a11yStatusValueToStoryIds,
870
+ storeState,
871
+ setStoreState,
872
+ isSettingsUpdated: false
873
+ }
874
+ );
875
+ }, "SidebarContextMenu");
876
+
877
+ // src/manager.tsx
878
+ addons2.register(ADDON_ID2, (api) => {
879
+ const storybookBuilder = globalThis.STORYBOOK_BUILDER || "";
880
+ if (storybookBuilder.includes("vite")) {
881
+ const openPanel2 = /* @__PURE__ */ __name((panelId) => {
882
+ api.setSelectedPanel(panelId);
883
+ api.togglePanel(true);
884
+ }, "openPanel");
885
+ componentTestStatusStore.onSelect(() => {
886
+ openPanel2(PANEL_ID);
887
+ });
888
+ a11yStatusStore.onSelect(() => {
889
+ openPanel2(PANEL_ID2);
890
+ });
891
+ testProviderStore.onRunAll(() => {
892
+ store.send({
893
+ type: "TRIGGER_RUN",
894
+ payload: {
895
+ triggeredBy: "run-all"
896
+ }
897
+ });
898
+ });
899
+ store.untilReady().then(() => {
900
+ store.setState((state) => ({
901
+ ...state,
902
+ indexUrl: new URL("index.json", window.location.href).toString()
903
+ }));
904
+ });
905
+ addons2.add(TEST_PROVIDER_ID, {
906
+ type: Addon_TypesEnum.experimental_TEST_PROVIDER,
907
+ render: /* @__PURE__ */ __name(() => {
908
+ const [isModalOpen, setModalOpen] = useState3(false);
909
+ const {
910
+ storeState,
911
+ setStoreState,
912
+ testProviderState,
913
+ componentTestStatusValueToStoryIds,
914
+ a11yStatusValueToStoryIds,
915
+ isSettingsUpdated
916
+ } = useTestProvider(api);
917
+ return React5.createElement(GlobalErrorContext.Provider, { value: { isModalOpen, setModalOpen } }, React5.createElement(
918
+ TestProviderRender,
919
+ {
920
+ api,
921
+ storeState,
922
+ setStoreState,
923
+ isSettingsUpdated,
924
+ testProviderState,
925
+ componentTestStatusValueToStoryIds,
926
+ a11yStatusValueToStoryIds
927
+ }
928
+ ), React5.createElement(
929
+ GlobalErrorModal,
930
+ {
931
+ storeState,
932
+ onRerun: () => {
933
+ setModalOpen(false);
934
+ store.send({
935
+ type: "TRIGGER_RUN",
936
+ payload: {
937
+ triggeredBy: "global"
938
+ }
939
+ });
940
+ }
941
+ }
942
+ ));
943
+ }, "render"),
944
+ sidebarContextMenu: /* @__PURE__ */ __name(({ context }) => {
945
+ if (context.type === "docs") {
946
+ return null;
947
+ }
948
+ if (context.type === "story" && !context.tags.includes("test")) {
949
+ return null;
950
+ }
951
+ return React5.createElement(SidebarContextMenu, { context, api });
952
+ }, "sidebarContextMenu")
953
+ });
954
+ }
955
+ });