[Fiber] Fix false-positive hydration mismatch on nonce attributes (โฆ
[Fiber] Fix false-positive hydration mismatch on nonce attributes (#37030)
Co-authored-by: Suneil Nyamathi snyamathi@gmail.com
Changes to test setup
Added jest.restoreAllMocks() in the afterEach block to ensure mock cleanup between tests:
afterEach ( ( ) => {
jest . restoreAllMocks ( ) ;
window . removeEventListener ( 'error' , errorHandler ) ;
document . body . removeChild ( container ) ;
console . error = realConsoleError ;
} ) ;
New test suite for nonce attribute hydration
The following test suite was added to cover hydration behavior with nonce attributes, which exist on HTMLOrSVGElement. The tests cover multiple host tags that hydrate attributes through getValueForAttribute:
describe ( 'nonce' , ( ) => {
function App ( ) {
return (
<html>
<head>
<meta charSet="utf-8" />
<style nonce="r4nd0m">
{ `body { background-color: red; }` }
</style>
</head>
<body>
<script nonce="r4nd0m" />
<link nonce="r4nd0m" rel="stylesheet" href="style.css" />
</body>
</html>
) ;
}
Test: No warning when nonce matches and CSP hides getAttribute
When Content Security Policy (CSP) is enabled, browsers hide the nonce content attribute - getAttribute("nonce") returns "" while .nonce remains readable. JSDOM does not implement this behavior, so it is mocked for this test case.
// @gate __DEV__
it ( 'does not warn when nonce matches and CSP hides getAttribute' , ( ) => {
const originalGetAttribute = window . Element . prototype . getAttribute ;
spyOnDevAndProd (
window . Element . prototype ,
'getAttribute' ,
) . mockImplementation ( function ( name ) {
if ( typeof name === 'string' && name . toLowerCase ( ) === 'nonce' ) {
return '' ;
}
return originalGetAttribute . call ( this , name ) ;
} ) ;
const htmlString = ReactDOMServer . renderToString ( <App /> ) ;
container . innerHTML = htmlString ;
// validate that the nonce attribute is hidden by getAttribute
// mimicking the behavior of browsers when CSP is enabled
const script = container . querySelector ( 'script' ) ;
expect ( script . getAttribute ( 'nonce' ) ) . toBe ( '' ) ;
expect ( script . nonce ) . toBe ( 'r4nd0m' ) ;
expect ( testMismatch ( App ) ) . toEqual ( [ ] ) ;
} ) ;
Test: No warning when nonce matches without CSP hiding
When CSP is disabled, getAttribute("nonce") returns the actual value and matches .nonce.
// @gate __DEV__
it ( 'does not warn when nonce matches without CSP hiding' , ( ) => {
const htmlString = ReactDOMServer . renderToString ( <App /> ) ;
container . innerHTML = htmlString ;
// validate that the nonce attribute is visible via getAttribute
// when CSP is disabled
const script = container . querySelector ( 'script' ) ;
expect ( script . getAttribute ( 'nonce' ) ) . toBe ( 'r4nd0m' ) ;
expect ( script . nonce ) . toBe ( 'r4nd0m' ) ;
expect ( testMismatch ( App ) ) . toEqual ( [ ] ) ;
} ) ;
Comments
No comments yet. Start the discussion.