Repository: microsoft/griffel
Pull request #397 (2023-07-18 13:04:50)

chore: use modern APIs in tests
This modifies tests to use non-deprecated APIs from React 18. Also adds some new assertions to existing tests.

github-actions[bot]: ## 📊 Bundle size report

<details>
<summary>Unchanged fixtures</summary>

| Package & Exports                                                                                                          |        Size (minified/GZIP) |
| -------------------------------------------------------------------------------------------------------------------------- | --------------------------: |
| <samp>react</samp> <br /> <abbr title='bundle-size/__css.fixture.js'>\_\_css</abbr>                                        |     `1.645 kB`<br />`767 B` |
| <samp>react</samp> <br /> <abbr title='bundle-size/__styles.fixture.js'>\_\_styles</abbr>                                  |  `3.463 kB`<br />`1.578 kB` |
| <samp>react</samp> <br /> <abbr title='bundle-size/makeResetStyles.fixture.js'>makeResetStyles (runtime)</abbr>            | `18.776 kB`<br />`7.223 kB` |
| <samp>react</samp> <br /> <abbr title='bundle-size/makeStaticStyles.fixture.js'>makeStaticStyles (runtime)</abbr>          |  `8.753 kB`<br />`3.868 kB` |
| <samp>react</samp> <br /> <abbr title='bundle-size/makeStyles.fixture.js'>makeStyles (runtime)</abbr>                      | `23.129 kB`<br />`8.791 kB` |
| <samp>shadow-dom</samp> <br /> <abbr title='bundle-size/createShadowDOMRenderer.fixture.js'>createShadowDOMRenderer</abbr> |  `3.232 kB`<br />`1.405 kB` |

</details>
<sub>🤖 This report was generated against <a href='https://github.com/microsoft/griffel/commit/c7fd5334a5486a305f19b3fbf81d9d13260ad51d'>c7fd5334a5486a305f19b3fbf81d9d13260ad51d</a></sub>

<!-- Sticky Pull Request Comment -->

Patch:
diff --git a/change/@griffel-react-43329235-82d9-463b-aebe-f0609c2617bc.json b/change/@griffel-react-43329235-82d9-463b-aebe-f0609c2617bc.json
new file mode 100644
index 0000000..697c06b
--- /dev/null
+++ b/change/@griffel-react-43329235-82d9-463b-aebe-f0609c2617bc.json
@@ -0,0 +1,7 @@
+{
+  "type": "none",
+  "comment": "chore: use modern APIs in tests",
+  "packageName": "@griffel/react",
+  "email": "olfedias@microsoft.com",
+  "dependentChangeType": "none"
+}
diff --git a/packages/react/jest.config.ts b/packages/react/jest.config.ts
index b7b517e..0a5d03f 100644
--- a/packages/react/jest.config.ts
+++ b/packages/react/jest.config.ts
@@ -5,6 +5,9 @@ export default {
   transform: {
     '^.+\\.[tj]sx?$': ['babel-jest', { presets: ['@nrwl/react/babel'] }],
   },
+  globals: {
+    IS_REACT_ACT_ENVIRONMENT: true,
+  },
   moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx'],
   coverageDirectory: '../../coverage/packages/react',
 };


Test patch:
diff --git a/packages/react/src/createDOMRenderer.test.tsx b/packages/react/src/createDOMRenderer.test.tsx
index 670e29e..89b6fa0 100644
--- a/packages/react/src/createDOMRenderer.test.tsx
+++ b/packages/react/src/createDOMRenderer.test.tsx
@@ -1,7 +1,8 @@
 import { createDOMRenderer, mergeClasses } from '@griffel/core';
 import * as React from 'react';
-import { hydrate } from 'react-dom';
+import { hydrateRoot } from 'react-dom/client';
 import { renderToStaticMarkup } from 'react-dom/server';
+import { act } from 'react-dom/test-utils';
 
 import { makeStyles } from './makeStyles';
 import { makeResetStyles } from './makeResetStyles';
@@ -52,6 +53,17 @@ describe('createDOMRenderer', () => {
     );
     const stylesHTML = renderToStaticMarkup(<>{renderToStyleElements(serverRenderer)}</>);
 
+    // Ensure that all styles are inserted into the cache
+    expect(serverRenderer.insertionCache).toMatchInlineSnapshot(`
+      Object {
+        ".f1p9cr64{animation-name:f1kgwxhb;}": "d",
+        ".fe3e8s9{color:red;}": "d",
+        ".rp2atum:hover{color:blue;}": "r",
+        ".rp2atum{color:red;}": "r",
+        "@keyframes f1kgwxhb{from{height:10px;}to{height:20px;}}": "k",
+        "@media screen and (max-width: 992px){.fnao3vb:hover{color:blue;}}": "m",
+      }
+    `);
     // There is no DOM on a server, style nodes should not be present
     expect(document.querySelector('style')).toBe(null);
 
@@ -61,6 +73,7 @@ describe('createDOMRenderer', () => {
     //
 
     const container = document.createElement('div');
+
     document.body.appendChild(container);
 
     container.innerHTML = componentHTML;
@@ -73,13 +86,15 @@ describe('createDOMRenderer', () => {
       jest.spyOn(styleEl.sheet!, 'insertRule'),
     );
 
-    hydrate(
-      // "RendererProvider" is not required there, we need it only for Jest spies
-      <RendererProvider renderer={clientRenderer}>
-        <ExampleComponent />
-      </RendererProvider>,
-      container,
-    );
+    act(() => {
+      hydrateRoot(
+        container,
+        // "RendererProvider" is not required there, we need it only for Jest spies
+        <RendererProvider renderer={clientRenderer}>
+          <ExampleComponent />
+        </RendererProvider>,
+      );
+    });
 
     const styleElementsAfterHydration = document.querySelectorAll<HTMLStyleElement>('style');
 
diff --git a/packages/react/src/makeResetStyles.test.tsx b/packages/react/src/makeResetStyles.test.tsx
new file mode 100644
index 0000000..b8dde10
--- /dev/null
+++ b/packages/react/src/makeResetStyles.test.tsx
@@ -0,0 +1,27 @@
+import * as React from 'react';
+import { createRoot } from 'react-dom/client';
+import { act } from 'react-dom/test-utils';
+
+import { makeResetStyles } from './makeResetStyles';
+
+describe('makeResetStyles', () => {
+  it('works outside of React components', () => {
+    expect(() => makeResetStyles({ root: { color: 'red' } })).not.toThrow();
+  });
+
+  it('throws inside React components', () => {
+    // eslint-disable-next-line @typescript-eslint/no-empty-function
+    jest.spyOn(console, 'error').mockImplementation(() => {});
+
+    const Example: React.FC = () => {
+      makeResetStyles({ color: 'red' });
+      return null;
+    };
+    const root = createRoot(document.createElement('div'));
+
+    expect(() => act(() => root.render(<Example />))).toThrow(/All makeResetStyles\(\) calls should be top level/);
+
+    // Should not throw outside React components after rendering
+    expect(() => makeResetStyles({ color: 'red' })).not.toThrow();
+  });
+});
diff --git a/packages/react/src/makeStyles.test.tsx b/packages/react/src/makeStyles.test.tsx
index fa9e4bb..dfa40ef 100644
--- a/packages/react/src/makeStyles.test.tsx
+++ b/packages/react/src/makeStyles.test.tsx
@@ -1,5 +1,6 @@
 import * as React from 'react';
-import * as ReactDOM from 'react-dom';
+import { createRoot } from 'react-dom/client';
+import { act } from 'react-dom/test-utils';
 
 import { makeStyles } from './makeStyles';
 
@@ -16,9 +17,9 @@ describe('makeStyles', () => {
       makeStyles({ root: { color: 'red' } });
       return null;
     };
-    const container = document.createElement('div');
+    const root = createRoot(document.createElement('div'));
 
-    expect(() => ReactDOM.render(<Example />, container)).toThrow(/All makeStyles\(\) calls should be top level/);
+    expect(() => act(() => root.render(<Example />))).toThrow(/All makeStyles\(\) calls should be top level/);
 
     // Should not throw outside React components after rendering
     expect(() => makeStyles({ root: { color: 'red' } })).not.toThrow();
diff --git a/packages/react/src/renderToStyleElements.test.tsx b/packages/react/src/renderToStyleElements.test.tsx
index 82572a6..42aff05 100644
--- a/packages/react/src/renderToStyleElements.test.tsx
+++ b/packages/react/src/renderToStyleElements.test.tsx
@@ -1,7 +1,9 @@
 import { createDOMRenderer, GriffelRenderer } from '@griffel/core';
 import * as prettier from 'prettier';
 import * as React from 'react';
-import * as ReactDOM from 'react-dom/server';
+import { createRoot } from 'react-dom/client';
+import { renderToStaticMarkup } from 'react-dom/server';
+import { act } from 'react-dom/test-utils';
 
 import { makeStyles } from './makeStyles';
 import { makeResetStyles } from './makeResetStyles';
@@ -43,14 +45,17 @@ describe('renderToStyleElements (DOM)', () => {
 
       return <div className={classes.root} />;
     };
+    const root = createRoot(document.createElement('div'));
 
-    ReactDOM.renderToStaticMarkup(
-      <RendererProvider renderer={renderer}>
-        <ExampleComponent />
-      </RendererProvider>,
-    );
+    act(() => {
+      root.render(
+        <RendererProvider renderer={renderer}>
+          <ExampleComponent />
+        </RendererProvider>,
+      );
+    });
 
-    expect(ReactDOM.renderToStaticMarkup(<>{renderToStyleElements(renderer)}</>)).toMatchInlineSnapshot(`
+    expect(renderToStaticMarkup(<>{renderToStyleElements(renderer)}</>)).toMatchInlineSnapshot(`
       <style data-make-styles-bucket="d" data-make-styles-rehydration="true">
         .fe3e8s9 {
           color: red;
@@ -71,14 +76,17 @@ describe('renderToStyleElements (DOM)', () => {
     const ExampleComponent: React.FC = () => {
       return <div className={useClassName()} />;
     };
+    const root = createRoot(document.createElement('div'));
 
-    ReactDOM.renderToStaticMarkup(
-      <RendererProvider renderer={renderer}>
-        <ExampleComponent />
-      </RendererProvider>,
-    );
+    act(() => {
+      root.render(
+        <RendererProvider renderer={renderer}>
+          <ExampleComponent />
+        </RendererProvider>,
+      );
+    });
 
-    expect(ReactDOM.renderToStaticMarkup(<>{renderToStyleElements(renderer)}</>)).toMatchInlineSnapshot(`
+    expect(renderToStaticMarkup(<>{renderToStyleElements(renderer)}</>)).toMatchInlineSnapshot(`
         <style data-make-styles-bucket="r" data-make-styles-rehydration="true">
           .r1tsu58y {
             color: red;