1- import { captureWebviewThemeFixture } from "../useThemeFixtureProbe"
1+ import { act , renderHook } from "@testing-library/react"
2+
3+ import { vscode } from "../vscode"
4+ import { captureWebviewThemeFixture , useThemeFixtureProbe } from "../useThemeFixtureProbe"
25
36describe ( "captureWebviewThemeFixture" , ( ) => {
7+ afterEach ( ( ) => {
8+ document . documentElement . removeAttribute ( "style" )
9+ document . body . removeAttribute ( "style" )
10+ document . body . removeAttribute ( "class" )
11+ delete document . body . dataset . vscodeThemeId
12+ vi . unstubAllGlobals ( )
13+ vi . restoreAllMocks ( )
14+ } )
15+
416 it ( "captures only resolved VS Code custom properties" , ( ) => {
17+ document . documentElement . style . setProperty ( "--vscode-root" , "#ffffff" )
518 document . body . className = "vscode-dark extra-class"
619 document . body . dataset . vscodeThemeId = "Default Dark Modern"
720 document . body . style . colorScheme = "dark"
@@ -13,9 +26,76 @@ describe("captureWebviewThemeFixture", () => {
1326 themeId : "Default Dark Modern" ,
1427 bodyClass : "vscode-dark extra-class" ,
1528 variables : {
29+ "--vscode-root" : "" ,
1630 "--vscode-z-last" : "rgb(2, 2, 2)" ,
1731 "--vscode-a-first" : "#010101" ,
1832 } ,
1933 } )
2034 } )
35+
36+ it ( "responds after two animation frames" , ( ) => {
37+ const callbacks = new Map < number , FrameRequestCallback > ( )
38+ let nextFrame = 0
39+ vi . stubGlobal (
40+ "requestAnimationFrame" ,
41+ vi . fn ( ( callback : FrameRequestCallback ) => {
42+ const id = ++ nextFrame
43+ callbacks . set ( id , callback )
44+ return id
45+ } ) ,
46+ )
47+ vi . stubGlobal (
48+ "cancelAnimationFrame" ,
49+ vi . fn ( ( id : number ) => callbacks . delete ( id ) ) ,
50+ )
51+ const postMessage = vi . spyOn ( vscode , "postMessage" ) . mockImplementation ( ( ) => undefined )
52+ const { unmount } = renderHook ( ( ) => useThemeFixtureProbe ( ) )
53+
54+ act ( ( ) => {
55+ window . dispatchEvent (
56+ new MessageEvent ( "message" , { data : { type : "themeFixtureProbeRequest" , requestId : "request-1" } } ) ,
57+ )
58+ } )
59+ expect ( postMessage ) . not . toHaveBeenCalled ( )
60+
61+ act ( ( ) => {
62+ callbacks . get ( 1 ) ?.( 0 )
63+ } )
64+ expect ( postMessage ) . not . toHaveBeenCalled ( )
65+
66+ act ( ( ) => {
67+ callbacks . get ( 2 ) ?.( 0 )
68+ } )
69+
70+ expect ( postMessage ) . toHaveBeenCalledWith (
71+ expect . objectContaining ( { type : "themeFixtureProbeResponse" , requestId : "request-1" } ) ,
72+ )
73+ unmount ( )
74+ } )
75+
76+ it ( "ignores incomplete requests and cancels pending frames on unmount" , ( ) => {
77+ const callbacks = new Map < number , FrameRequestCallback > ( )
78+ vi . stubGlobal (
79+ "requestAnimationFrame" ,
80+ vi . fn ( ( callback : FrameRequestCallback ) => {
81+ callbacks . set ( 1 , callback )
82+ return 1
83+ } ) ,
84+ )
85+ const cancelAnimationFrame = vi . fn ( ( id : number ) => callbacks . delete ( id ) )
86+ vi . stubGlobal ( "cancelAnimationFrame" , cancelAnimationFrame )
87+ const postMessage = vi . spyOn ( vscode , "postMessage" ) . mockImplementation ( ( ) => undefined )
88+ const { unmount } = renderHook ( ( ) => useThemeFixtureProbe ( ) )
89+
90+ act ( ( ) => {
91+ window . dispatchEvent ( new MessageEvent ( "message" , { data : { type : "themeFixtureProbeRequest" } } ) )
92+ window . dispatchEvent (
93+ new MessageEvent ( "message" , { data : { type : "themeFixtureProbeRequest" , requestId : "pending" } } ) ,
94+ )
95+ } )
96+ unmount ( )
97+
98+ expect ( postMessage ) . not . toHaveBeenCalled ( )
99+ expect ( cancelAnimationFrame ) . toHaveBeenCalledWith ( 1 )
100+ } )
21101} )
0 commit comments