test-runner
test-runner copied to clipboard
[Feature Request] Support stories that override the user agent
I have a component that behaves differently on different browsers / operating systems. I want to test these different behaviours.
I use a decorator that simulates the different environments by overridding the user agent:
export function givenUserAgent (userAgent: string) {
function overrideUserAgent (userAgent: string) {
Object.defineProperty(window.navigator, 'userAgent', {
get: () => userAgent,
configurable: true
})
}
return function SetUserAgent (Story: StoryFn<any>) {
const [isReady, setIsReady] = useReducer(() => true, false)
useEffect(() => {
const initialUserAgent = window.navigator.userAgent
overrideUserAgent(userAgent)
setIsReady()
return function restoreUserAgent () {
overrideUserAgent(initialUserAgent)
}
}, [])
return <>
{isReady && <Story />}
</>
}
}
But test-runner overrides the user agent itself in setup-page.ts
https://github.com/storybookjs/test-runner/blob/428f7db84150abce3f9a0e69e40b98bed1f78f5a/src/setup-page.ts#L230
Because it does so without setting configurable: true when my decorator tries to override the user agent I get an error.
Message:
Cannot redefine property: userAgent
at __throwError (<anonymous>:180:15)
at eval (eval at evaluate (:191:30), <anonymous>:4:19)
at UtilityScript.evaluate (<anonymous>:193:17)
at UtilityScript.<anonymous> (<anonymous>:1:44)
I worked around this by overriding the whole navigator
function overrideUserAgent (userAgent: string) {
const previousNavigator = window.navigator
// storybookjs/test-runner overrides the userAgent and doesn't set `configurable: true`.
// To workaround this I override the whole navigator.
Object.defineProperty(window, 'navigator', {
get: () => Object.create(previousNavigator, {
userAgent: {
get: () => userAgent,
configurable: true
},
// ua-parser-js throws TypeError unless this is overridden too.
userAgentData: {
get: () => undefined,
configurable: true
}
}),
configurable: true
})
}
Hey there @notclive! Could you make a PR to fix this (adding configurable to the property definition)? I'm happy to take a look!
I wasn't sure whether that was a desirable solution. Currently test-runner seems to depend on the user-agent changing (https://github.com/storybookjs/test-runner#storybooktestrunner-user-agent). Though, I'm not sure if any core behaviour depends on it, I haven't seen any issues from overriding.
The test-runner doesn't really depend on the user-agent per se, it just provides it so that users can check against it for various purposes: https://github.com/storybookjs/test-runner#storybooktestrunner-user-agent