From 319b3f5e5902c71e21dd1a1b3c9b7a7d2d8d09c9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= <mateuszburzynski@gmail.com>
Date: Sun, 15 Dec 2024 12:01:51 +0100
Subject: [PATCH] Use React 19 (#3291)

* Use React 19

* Specify TS 5.0 as min TS version in most dtslint tests

* try patching dtslint

* update lockfile

* fixed TS error

* dedupe `@types/react`

* update react testing library

* add `@testing-library/dom`

* migrate tests

* migrate more

* moar

* moar

* fix

* more

* more

* more

* more

* more

* more

* more

* more

* fix

* migrate more tests

* moar

* moar

* moar

* moar

* moar

* more

* more

* more

* tweak

* more converted tests

* fix thing

* fix

* tweak

* fixed test

* tweaks

* unskip 2 tests

* unskip again

* stuff

* fix streams

* skip some tests

* tweak

* fix things

* fix snap

* fixed snapshot indent

* fixed extra snapshot issue

* strip-ansi

* Require TS 5.1

* `useInsertionEffect` directly in `Global`

* keep old peer dep range in `use-insertion-effect-with-fallbacks`

* add changeset

* fixed lockfile
---
 .changeset/amaranth-owls-dream.md             |   6 +
 .github/workflows/main.yml                    |  10 -
 ...ript-versions-npm-0.0.112-f668f50e03.patch |  16 +
 docs/testing.mdx                              |   8 +-
 jest-react18.config.js                        |   9 -
 package.json                                  |  19 +-
 .../component-selector.test.js.snap           |   4 +-
 .../css/test/__snapshots__/css.test.js.snap   | 111 ++--
 .../css/test/__snapshots__/cx.test.js.snap    |  10 +-
 .../test/__snapshots__/keyframes.test.js.snap |   4 +-
 .../__snapshots__/label-pattern.test.js.snap  |   2 +-
 .../test/__snapshots__/warnings.test.js.snap  |   2 +-
 packages/css/test/component-selector.test.js  |  17 +-
 packages/css/test/css.test.js                 | 170 +++---
 packages/css/test/cx.test.js                  |  59 +-
 .../instance/__snapshots__/css.test.js.snap   | 100 ++--
 packages/css/test/instance/css.test.js        | 157 +++---
 packages/css/test/instance/inline.test.js     |  15 +-
 packages/css/test/instance/stream.test.js     |  20 +-
 packages/css/test/keyframes.test.js           |  60 +-
 packages/css/test/label-pattern.test.js       |  18 +-
 .../no-babel/__snapshots__/index.test.js.snap |  36 +-
 packages/css/test/no-babel/index.test.js      | 101 ++--
 packages/css/test/warnings.test.js            |   8 +-
 packages/jest/README.md                       |  50 +-
 packages/jest/package.json                    |   5 +-
 .../test/__snapshots__/matchers.test.js.snap  |   8 +-
 .../test/__snapshots__/printer.test.js.snap   |   4 +-
 packages/jest/test/matchers.test.js           | 256 +++++----
 packages/jest/test/printer.test.js            | 107 ++--
 packages/jest/test/prod.test.js               |  40 +-
 packages/jest/types/index.d.ts                |   2 +-
 packages/native/package.json                  |   2 +-
 packages/native/test/native-styled.test.js    | 129 +++--
 packages/native/types/base.d.ts               |   2 +-
 packages/native/types/index.d.ts              |   2 +-
 packages/primitives-core/package.json         |   4 +-
 packages/primitives/package.json              |   4 +-
 .../emotion-primitives.test.js.snap           |  64 +--
 .../test/emotion-primitives.test.js           | 108 ++--
 .../no-babel/__snapshots__/basic.test.js.snap |   8 +-
 .../primitives/test/no-babel/basic.test.js    |  21 +-
 .../__tests__/__snapshots__/at-import.js.snap |   8 +-
 .../__snapshots__/class-names.js.snap         |   6 +-
 .../__snapshots__/css-cache-hash.js.snap      |   2 +-
 .../react/__tests__/__snapshots__/css.js.snap |  50 +-
 .../__tests__/__snapshots__/keyframes.js.snap |  18 +-
 .../__snapshots__/legacy-class-name.js.snap   |   4 +-
 .../__tests__/__snapshots__/prod.js.snap      |  10 +
 .../__snapshots__/theme-provider.js.snap      |   4 +-
 .../__tests__/__snapshots__/use-theme.js.snap |   6 +-
 .../__tests__/__snapshots__/warnings.js.snap  |  78 ++-
 .../__snapshots__/with-theme.js.snap          |   2 +-
 packages/react/__tests__/at-import.js         |  13 +-
 .../__tests__/babel/__snapshots__/css.js.snap |   4 +-
 packages/react/__tests__/babel/css.js         |  11 +-
 packages/react/__tests__/class-names.js       |  18 +-
 packages/react/__tests__/css-cache-hash.js    |   6 +-
 packages/react/__tests__/css.js               |  85 +--
 packages/react/__tests__/custom-cache.js      |  10 +-
 packages/react/__tests__/import-prod.js       |  23 +-
 packages/react/__tests__/keyframes.js         |   7 +-
 packages/react/__tests__/legacy-class-name.js |  42 +-
 packages/react/__tests__/prod.js              |   6 +-
 packages/react/__tests__/ref.js               |   2 +-
 packages/react/__tests__/rehydration.js       |   3 +-
 packages/react/__tests__/theme-provider.js    |  74 ++-
 packages/react/__tests__/use-theme.js         |  28 +-
 packages/react/__tests__/warnings.js          | 333 +++++------
 packages/react/__tests__/with-theme.js        |  20 +-
 packages/react/package.json                   |   4 +-
 packages/react/src/global.tsx                 |   9 +-
 packages/react/src/jsx-namespace.ts           |  94 +---
 packages/react/types/index.d.ts               |   2 +-
 packages/react/types/tests-theming.tsx        |   2 +-
 packages/react/types/tests.tsx                |  24 -
 packages/server/test/inline.test.js           |  18 +-
 packages/server/test/stream.test.js           |  20 +-
 packages/server/test/util.js                  |  18 +-
 packages/server/types/create-instance.d.ts    |   2 +-
 packages/server/types/index.d.ts              |   2 +-
 .../__snapshots__/edge-cases.js.snap          |   4 +-
 .../__tests__/__snapshots__/styled.js.snap    | 142 +++--
 packages/styled/__tests__/edge-cases.js       |  12 +-
 packages/styled/__tests__/styled-dom.js       |   2 +-
 packages/styled/__tests__/styled.js           | 529 ++++++++----------
 packages/styled/package.json                  |   4 +-
 packages/styled/src/index.ts                  |   6 +-
 packages/styled/src/jsx-namespace.ts          |  12 -
 packages/styled/src/types.ts                  |  22 +-
 .../__snapshots__/babel-plugin.test.js.snap   |  11 +
 .../component-selector.test.js.snap           |  24 +-
 .../__snapshots__/composition.test.js.snap    |  20 +-
 .../test/__snapshots__/index.test.js.snap     |  66 ++-
 .../__snapshots__/prop-filtering.test.js.snap | 100 ++--
 .../__snapshots__/source-map.test.js.snap     |  36 +-
 .../test/__snapshots__/theming.test.js.snap   |   8 +-
 packages/styled/test/babel-plugin.test.js     |   7 +-
 .../styled/test/component-selector.test.js    |  58 +-
 packages/styled/test/composition.test.js      |  96 ++--
 packages/styled/test/index.test.js            | 180 +++---
 packages/styled/test/prop-filtering.test.js   | 255 +++++----
 packages/styled/test/source-map.test.js       |   8 +-
 packages/styled/test/theming.test.js          |  41 +-
 packages/styled/types/base.d.ts               |   2 +-
 packages/styled/types/index.d.ts              |   2 +-
 .../package.json                              |   2 +-
 playgrounds/cra/package.json                  |   4 +-
 playgrounds/nextjs/package.json               |   4 +-
 scripts/benchmarks/package.json               |   4 +-
 scripts/ssr-benchmarks/package.json           |   4 +-
 scripts/test-utils/src/index.js               |   7 +-
 site/package.json                             |   6 +-
 yarn.lock                                     | 342 +++++------
 114 files changed, 2297 insertions(+), 2569 deletions(-)
 create mode 100644 .changeset/amaranth-owls-dream.md
 create mode 100644 .yarn/patches/@definitelytyped-typescript-versions-npm-0.0.112-f668f50e03.patch
 delete mode 100644 jest-react18.config.js
 create mode 100644 packages/react/__tests__/__snapshots__/prod.js.snap
 delete mode 100644 packages/styled/src/jsx-namespace.ts
 create mode 100644 packages/styled/test/__snapshots__/babel-plugin.test.js.snap

diff --git a/.changeset/amaranth-owls-dream.md b/.changeset/amaranth-owls-dream.md
new file mode 100644
index 0000000000..38b5f13f77
--- /dev/null
+++ b/.changeset/amaranth-owls-dream.md
@@ -0,0 +1,6 @@
+---
+'@emotion/styled': major
+'@emotion/react': major
+---
+
+Dropped support for older React versions. React 19 becomes the only compatible version with this package.
diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index f6933c340e..71d76eb687 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -41,16 +41,6 @@ jobs:
       - name: Check Types
         run: yarn tsc:all
 
-  test_react18:
-    name: Test React 18
-    runs-on: ubuntu-latest
-    steps:
-      - uses: actions/checkout@v3
-      - uses: ./.github/actions/ci-setup
-
-      - name: Run Tests with React 18
-        run: yarn test:react18:ci
-
   test_prod:
     name: Test Prod
     runs-on: ubuntu-latest
diff --git a/.yarn/patches/@definitelytyped-typescript-versions-npm-0.0.112-f668f50e03.patch b/.yarn/patches/@definitelytyped-typescript-versions-npm-0.0.112-f668f50e03.patch
new file mode 100644
index 0000000000..4e828d0aa5
--- /dev/null
+++ b/.yarn/patches/@definitelytyped-typescript-versions-npm-0.0.112-f668f50e03.patch
@@ -0,0 +1,16 @@
+diff --git a/dist/index.js b/dist/index.js
+index 0a9abde5fbe918397794db0c0962129cf6bec3fa..26fe2b048b7fa898282d2d9d0dbd1719384b1f60 100644
+--- a/dist/index.js
++++ b/dist/index.js
+@@ -8,9 +8,9 @@ const assert_1 = __importDefault(require("assert"));
+ var TypeScriptVersion;
+ (function (TypeScriptVersion) {
+     /** Add to this list when a version actually ships.  */
+-    TypeScriptVersion.shipped = ["3.9", "4.0", "4.1", "4.2", "4.3", "4.4", "4.5", "4.6"];
++    TypeScriptVersion.shipped = ["3.9", "4.0", "4.1", "4.2", "4.3", "4.4", "4.5", "4.6", "4.7", "4.8", "4.9", "5.0", "5.1", "5.2", "5.3", "5.4", "5.5", "5.6", "5.7"];
+     /** Add to this list when a version is available as typescript@next */
+-    TypeScriptVersion.supported = [...TypeScriptVersion.shipped, "4.7"];
++    TypeScriptVersion.supported = [...TypeScriptVersion.shipped, "5.8"];
+     /** Add to this list when it will no longer be supported on Definitely Typed */
+     TypeScriptVersion.unsupported = [
+         "2.0",
diff --git a/docs/testing.mdx b/docs/testing.mdx
index cd4b92ad1a..447265df72 100644
--- a/docs/testing.mdx
+++ b/docs/testing.mdx
@@ -34,11 +34,11 @@ expect.addSnapshotSerializer(createSerializer())
 
 ### Writing a test
 
-Writing a test with `@emotion/jest` involves creating a snapshot from the `react-test-renderer`'s resulting JSON.
+Writing a test with `@emotion/jest` involves creating a snapshot from the `@testing-library/react`'s result.
 
 ```jsx
 import React from 'react'
-import renderer from 'react-test-renderer'
+import { render } from '@testing-library/react'
 
 const Button = props => (
   <button
@@ -51,7 +51,7 @@ const Button = props => (
 
 test('Button renders correctly', () => {
   expect(
-    renderer.create(<Button>This is hotpink.</Button>).toJSON()
+    render(<Button>This is hotpink.</Button>).container
   ).toMatchSnapshot()
 })
 ```
@@ -67,7 +67,7 @@ exports[`Button renders correctly 1`] = `
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 >
   This is hotpink.
 </div>
diff --git a/jest-react18.config.js b/jest-react18.config.js
deleted file mode 100644
index 119490a9b6..0000000000
--- a/jest-react18.config.js
+++ /dev/null
@@ -1,9 +0,0 @@
-const baseConfig = require('./jest.config.js')
-
-module.exports = Object.assign({}, baseConfig, {
-  moduleNameMapper: {
-    '^react($|\\/.+)': 'react18$1',
-    '^react-dom($|\\/.+)': 'react18-dom$1',
-    '^react-test-renderer($|\\/.+)': 'react18-test-renderer$1'
-  }
-})
diff --git a/package.json b/package.json
index fba49a4d31..0dc1dae885 100644
--- a/package.json
+++ b/package.json
@@ -9,10 +9,8 @@
     "test:size": "npm-run-all build size",
     "test:debug": "node --inspect-brk ./node_modules/jest/bin/jest.js --runInBand --watch",
     "test": "jest",
-    "test:react18": "jest -c jest-react18.config.js",
     "test:typescript": "yarn workspaces foreach --verbose --exclude emotion-monorepo run test:typescript",
     "test:ci": "jest --coverage --no-cache --ci --runInBand",
-    "test:react18:ci": "yarn test:react18 --coverage --no-cache --ci --runInBand",
     "test:dist": "yarn build && jest -c jest.dist.js --no-cache --ci --runInBand",
     "test:prod": "jest -c jest.prod.js --no-cache --ci --runInBand",
     "lint:check": "eslint .",
@@ -185,10 +183,11 @@
     "@changesets/cli": "^2.27.7",
     "@manypkg/cli": "^0.19.1",
     "@preconstruct/cli": "^2.8.8",
-    "@testing-library/react": "13.0.0-alpha.5",
+    "@testing-library/dom": "^10.4.0",
+    "@testing-library/react": "^16.1.0",
     "@types/jest": "^29.5.12",
     "@types/node": "^12.20.37",
-    "@types/react": "18.3.12",
+    "@types/react": "19.0.1",
     "@typescript-eslint/eslint-plugin": "^7.13.0",
     "@typescript-eslint/parser": "^7.13.0",
     "babel-check-duplicated-nodes": "^1.0.0",
@@ -226,14 +225,11 @@
     "polished": "^1.2.1",
     "prettier": "^3.3.2",
     "raf": "^3.4.0",
-    "react": "16.14.0",
-    "react-dom": "16.14.0",
+    "react": "19.0.0",
+    "react-dom": "19.0.0",
     "react-native": "^0.63.2",
     "react-primitives": "^0.8.1",
-    "react-test-renderer": "16.8.6",
-    "react18": "npm:react@18.0.0-rc.0-next-aa8f2bdbc-20211215",
-    "react18-dom": "npm:react-dom@18.0.0-rc.0-next-aa8f2bdbc-20211215",
-    "react18-test-renderer": "npm:react-test-renderer@18.0.0-rc.0-next-aa8f2bdbc-20211215",
+    "react-test-renderer": "19.0.0",
     "svg-tag-names": "^1.1.1",
     "through": "^2.3.8",
     "typescript": "^5.4.5",
@@ -242,6 +238,7 @@
   },
   "packageManager": "yarn@3.2.3",
   "resolutions": {
-    "@definitelytyped/dtslint@0.0.112": "patch:@definitelytyped/dtslint@npm%3A0.0.112#./.yarn/patches/@definitelytyped-dtslint-npm-0.0.112-1e6b842976.patch"
+    "@definitelytyped/dtslint@0.0.112": "patch:@definitelytyped/dtslint@npm%3A0.0.112#./.yarn/patches/@definitelytyped-dtslint-npm-0.0.112-1e6b842976.patch",
+    "@definitelytyped/typescript-versions@^0.0.112": "patch:@definitelytyped/typescript-versions@npm%3A0.0.112#./.yarn/patches/@definitelytyped-typescript-versions-npm-0.0.112-f668f50e03.patch"
   }
 }
diff --git a/packages/css/test/__snapshots__/component-selector.test.js.snap b/packages/css/test/__snapshots__/component-selector.test.js.snap
index 0831e50cb4..f5816e1d25 100644
--- a/packages/css/test/__snapshots__/component-selector.test.js.snap
+++ b/packages/css/test/__snapshots__/component-selector.test.js.snap
@@ -10,10 +10,10 @@ exports[`component selector should be converted to use the emotion target classN
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 >
   <div
-    className="emotion-1 emotion-2"
+    class="emotion-1 emotion-2"
   />
 </div>
 `;
diff --git a/packages/css/test/__snapshots__/css.test.js.snap b/packages/css/test/__snapshots__/css.test.js.snap
index fcf9de1124..c4b2a1a926 100644
--- a/packages/css/test/__snapshots__/css.test.js.snap
+++ b/packages/css/test/__snapshots__/css.test.js.snap
@@ -8,7 +8,7 @@ exports[`css @supports 1`] = `
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 />
 `;
 
@@ -19,7 +19,7 @@ exports[`css array fallback 1`] = `
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 />
 `;
 
@@ -32,7 +32,7 @@ exports[`css array with explicit false 1`] = `
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 />
 `;
 
@@ -45,7 +45,7 @@ exports[`css array with explicit true 1`] = `
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 />
 `;
 
@@ -63,7 +63,7 @@ exports[`css auto px 1`] = `
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 />
 `;
 
@@ -76,7 +76,7 @@ exports[`css boolean as value 1`] = `
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 />
 `;
 
@@ -89,7 +89,7 @@ exports[`css composition stuff 1`] = `
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 />
 `;
 
@@ -102,7 +102,7 @@ exports[`css composition stuff 2`] = `
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 />
 `;
 
@@ -136,7 +136,7 @@ exports[`css composition with objects 1`] = `
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 />
 `;
 
@@ -147,7 +147,7 @@ exports[`css computed key is only dynamic 1`] = `
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 />
 `;
 
@@ -158,7 +158,7 @@ exports[`css css variables 1`] = `
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 />
 `;
 
@@ -171,7 +171,7 @@ exports[`css explicit & 1`] = `
 }
 
 <div
-  className="emotion-0 another-class"
+  class="emotion-0 another-class"
 />
 `;
 
@@ -186,7 +186,7 @@ exports[`css explicit & 2`] = `
 
 exports[`css explicit false 1`] = `
 <div
-  className="emotion-0"
+  class="emotion-0"
 />
 `;
 
@@ -199,7 +199,7 @@ exports[`css falsy property value in object 1`] = `
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 />
 `;
 
@@ -209,7 +209,7 @@ exports[`css falsy value in nested selector on object 1`] = `
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 />
 `;
 
@@ -219,7 +219,7 @@ exports[`css float property 1`] = `
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 />
 `;
 
@@ -232,13 +232,13 @@ exports[`css flushes correctly 1`] = `
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 />
 `;
 
 exports[`css flushes correctly 2`] = `
 <div
-  className="css-15gpprc-cls1"
+  class="css-15gpprc-cls1"
 />
 `;
 
@@ -249,7 +249,7 @@ exports[`css handles array of objects 1`] = `
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 />
 `;
 
@@ -270,7 +270,7 @@ exports[`css handles more than 10 dynamic properties 1`] = `
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 />
 `;
 
@@ -288,7 +288,7 @@ exports[`css handles objects 1`] = `
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 />
 `;
 
@@ -298,7 +298,7 @@ exports[`css manually use label property 1`] = `
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 />
 `;
 
@@ -338,7 +338,7 @@ exports[`css media query specificity 2`] = `
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 />
 `;
 
@@ -349,7 +349,7 @@ exports[`css multiline declaration 1`] = `
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 />
 `;
 
@@ -359,7 +359,7 @@ exports[`css multiline selector 1`] = `
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 />
 `;
 
@@ -386,13 +386,13 @@ exports[`css nested 1`] = `
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 >
   <div
-    className="some-class"
+    class="some-class"
   >
     <div
-      className="some-other-class"
+      class="some-other-class"
     />
   </div>
 </div>
@@ -417,7 +417,7 @@ exports[`css nested array 1`] = `
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 />
 `;
 
@@ -435,19 +435,52 @@ exports[`css nested at rule 1`] = `
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
+/>
+`;
+
+exports[`css nested at rules 1`] = `
+@supports (display: grid) {
+  .emotion-0 {
+    display: grid;
+  }
+
+  @supports (display: flex) {
+    .emotion-0 {
+      display: -webkit-box;
+      display: -webkit-flex;
+      display: -ms-flexbox;
+      display: flex;
+    }
+  }
+}
+
+@media (min-width: 420px) {
+  .emotion-0 {
+    color: pink;
+  }
+
+  @media (max-width: 500px) {
+    .emotion-0 {
+      color: hotpink;
+    }
+  }
+}
+
+<div
+  class="emotion-0"
 />
 `;
 
 exports[`css null rule 1`] = `
 <div
-  className="emotion-0"
+  class="emotion-0"
 />
 `;
 
 exports[`css null value 1`] = `
 <div
-  className="emotion-0"
+  class="emotion-0"
 />
 `;
 
@@ -467,7 +500,7 @@ exports[`css random expression 1`] = `
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 />
 `;
 
@@ -480,7 +513,7 @@ exports[`css random interpolation with undefined values 1`] = `
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 />
 `;
 
@@ -494,7 +527,7 @@ exports[`css registered styles as nested selector value in object 1`] = `
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 />
 `;
 
@@ -510,7 +543,7 @@ exports[`css rule after media query 1`] = `
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 />
 `;
 
@@ -531,7 +564,7 @@ exports[`css simple composition 1`] = `
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 />
 `;
 
@@ -544,7 +577,7 @@ exports[`css weakmap 1`] = `
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 />
 `;
 
@@ -557,6 +590,6 @@ exports[`css weakmap 2`] = `
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 />
 `;
diff --git a/packages/css/test/__snapshots__/cx.test.js.snap b/packages/css/test/__snapshots__/cx.test.js.snap
index 4c80ffe3ed..5fae78ea10 100644
--- a/packages/css/test/__snapshots__/cx.test.js.snap
+++ b/packages/css/test/__snapshots__/cx.test.js.snap
@@ -11,7 +11,7 @@ exports[`cx all types 1`] = `
 }
 
 <div
-  className="modal profile emotion-0"
+  class="modal profile emotion-0"
 />
 `;
 
@@ -26,7 +26,7 @@ exports[`cx fun fun functions 1`] = `
 }
 
 <div
-  className="modal profile emotion-0"
+  class="modal profile emotion-0"
 />
 `;
 
@@ -37,7 +37,7 @@ exports[`cx merge 2 1`] = `
 }
 
 <div
-  className="emotion-0 modal"
+  class="emotion-0 modal"
 />
 `;
 
@@ -50,7 +50,7 @@ exports[`cx merge 3 1`] = `
 }
 
 <div
-  className="modal emotion-0"
+  class="modal emotion-0"
 />
 `;
 
@@ -63,7 +63,7 @@ exports[`cx merge 4 1`] = `
 }
 
 <div
-  className="modal profile emotion-0"
+  class="modal profile emotion-0"
 />
 `;
 
diff --git a/packages/css/test/__snapshots__/keyframes.test.js.snap b/packages/css/test/__snapshots__/keyframes.test.js.snap
index f0012fdc76..190c314456 100644
--- a/packages/css/test/__snapshots__/keyframes.test.js.snap
+++ b/packages/css/test/__snapshots__/keyframes.test.js.snap
@@ -23,7 +23,7 @@ exports[`keyframes keyframes with interpolation 1`] = `
 }
 
 <h1
-  className="emotion-0"
+  class="emotion-0"
 >
   hello world
 </h1>
@@ -72,7 +72,7 @@ exports[`keyframes renders 1`] = `
 }
 
 <h1
-  className="emotion-0"
+  class="emotion-0"
 >
   hello world
 </h1>
diff --git a/packages/css/test/__snapshots__/label-pattern.test.js.snap b/packages/css/test/__snapshots__/label-pattern.test.js.snap
index be38536610..7d06aae22f 100644
--- a/packages/css/test/__snapshots__/label-pattern.test.js.snap
+++ b/packages/css/test/__snapshots__/label-pattern.test.js.snap
@@ -8,7 +8,7 @@ exports[`label pattern input + label styled 1`] = `
 
 <div>
   <input
-    className="emotion-0 emotion-1"
+    class="emotion-0 emotion-1"
   />
   <label>
     Label
diff --git a/packages/css/test/__snapshots__/warnings.test.js.snap b/packages/css/test/__snapshots__/warnings.test.js.snap
index cb3ceae100..8aa3245bc9 100644
--- a/packages/css/test/__snapshots__/warnings.test.js.snap
+++ b/packages/css/test/__snapshots__/warnings.test.js.snap
@@ -26,6 +26,6 @@ exports[`does not warn when valid values are passed for the content property 1`]
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 />
 `;
diff --git a/packages/css/test/component-selector.test.js b/packages/css/test/component-selector.test.js
index a7eab145e1..47adaba295 100644
--- a/packages/css/test/component-selector.test.js
+++ b/packages/css/test/component-selector.test.js
@@ -1,7 +1,8 @@
 import 'test-utils/setup-env'
 import React from 'react'
+import { act } from 'react'
 import styled from '@emotion/styled'
-import renderer from 'react-test-renderer'
+import { render } from '@testing-library/react'
 import { css } from '@emotion/css'
 
 describe('component selector', () => {
@@ -15,13 +16,11 @@ describe('component selector', () => {
         color: red;
       }
     `
-    const tree = renderer
-      .create(
-        <div className={cls2}>
-          <FakeComponent />
-        </div>
-      )
-      .toJSON()
-    expect(tree).toMatchSnapshot()
+    const { container } = render(
+      <div className={cls2}>
+        <FakeComponent />
+      </div>
+    )
+    expect(container.firstChild).toMatchSnapshot()
   })
 })
diff --git a/packages/css/test/css.test.js b/packages/css/test/css.test.js
index df86dd5722..a7264ef135 100644
--- a/packages/css/test/css.test.js
+++ b/packages/css/test/css.test.js
@@ -1,6 +1,6 @@
 import 'test-utils/setup-env'
 import React from 'react'
-import renderer from 'react-test-renderer'
+import { render } from '@testing-library/react'
 import { css, flush, sheet } from '@emotion/css'
 
 describe('css', () => {
@@ -9,8 +9,8 @@ describe('css', () => {
       float: left;
     `
 
-    const tree = renderer.create(<div className={cls1} />).toJSON()
-    expect(tree).toMatchSnapshot()
+    const { container } = render(<div className={cls1} />)
+    expect(container.firstChild).toMatchSnapshot()
   })
 
   test('handles more than 10 dynamic properties', () => {
@@ -28,24 +28,24 @@ describe('css', () => {
       text-align: ${'center'};
     `
 
-    const tree = renderer.create(<div className={cls1} />).toJSON()
-    expect(tree).toMatchSnapshot()
+    const { container } = render(<div className={cls1} />)
+    expect(container.firstChild).toMatchSnapshot()
   })
 
   test('falsy value in nested selector on object', () => {
     const cls1 = css({ ':hover': { display: null, color: 'hotpink' } })
-    const tree = renderer.create(<div className={cls1} />).toJSON()
-    expect(tree).toMatchSnapshot()
+    const { container } = render(<div className={cls1} />)
+    expect(container.firstChild).toMatchSnapshot()
   })
   test('boolean as value', () => {
     const cls1 = css({ display: 'flex', color: false, backgroundColor: true })
-    const tree = renderer.create(<div className={cls1} />).toJSON()
-    expect(tree).toMatchSnapshot()
+    const { container } = render(<div className={cls1} />)
+    expect(container.firstChild).toMatchSnapshot()
   })
   test('auto px', () => {
     const cls1 = css({ display: 'flex', flex: 1, fontSize: 10, '--custom': 5 })
-    const tree = renderer.create(<div className={cls1} />).toJSON()
-    expect(tree).toMatchSnapshot()
+    const { container } = render(<div className={cls1} />)
+    expect(container.firstChild).toMatchSnapshot()
   })
 
   test('random interpolation with undefined values', () => {
@@ -53,8 +53,8 @@ describe('css', () => {
       ${undefined};
       justify-content: center;
     `
-    const tree = renderer.create(<div className={cls2} />).toJSON()
-    expect(tree).toMatchSnapshot()
+    const { container } = render(<div className={cls2} />)
+    expect(container.firstChild).toMatchSnapshot()
   })
 
   test('random expression', () => {
@@ -70,8 +70,8 @@ describe('css', () => {
       }
       background: green;
     `
-    const tree = renderer.create(<div className={cls2} />).toJSON()
-    expect(tree).toMatchSnapshot()
+    const { container } = render(<div className={cls2} />)
+    expect(container.firstChild).toMatchSnapshot()
   })
 
   test('simple composition', () => {
@@ -85,8 +85,8 @@ describe('css', () => {
       ${cls1};
       justify-content: center;
     `
-    const tree = renderer.create(<div className={cls2} />).toJSON()
-    expect(tree).toMatchSnapshot()
+    const { container } = render(<div className={cls2} />)
+    expect(container.firstChild).toMatchSnapshot()
   })
 
   test('handles objects', () => {
@@ -98,20 +98,20 @@ describe('css', () => {
       height: 50,
       width: 20
     })
-    const tree = renderer.create(<div className={cls1} />).toJSON()
-    expect(tree).toMatchSnapshot()
+    const { container } = render(<div className={cls1} />)
+    expect(container.firstChild).toMatchSnapshot()
   })
 
   test('handles array of objects', () => {
     const cls1 = css([{ height: 50, width: 20 }, null])
-    const tree = renderer.create(<div className={cls1} />).toJSON()
-    expect(tree).toMatchSnapshot()
+    const { container } = render(<div className={cls1} />)
+    expect(container.firstChild).toMatchSnapshot()
   })
 
   test('computed key is only dynamic', () => {
     const cls1 = css({ fontSize: 10, [`w${'idth'}`]: 20 })
-    const tree = renderer.create(<div className={cls1} />).toJSON()
-    expect(tree).toMatchSnapshot()
+    const { container } = render(<div className={cls1} />)
+    expect(container.firstChild).toMatchSnapshot()
   })
 
   test('composition with objects', () => {
@@ -133,8 +133,8 @@ describe('css', () => {
       justify-content: center;
     `
 
-    const tree = renderer.create(<div className={cls2} />).toJSON()
-    expect(tree).toMatchSnapshot()
+    const { container } = render(<div className={cls2} />)
+    expect(container.firstChild).toMatchSnapshot()
   })
   test('@supports', () => {
     const cls1 = css`
@@ -142,10 +142,10 @@ describe('css', () => {
         display: grid;
       }
     `
-    const tree = renderer.create(<div className={cls1} />).toJSON()
-    expect(tree).toMatchSnapshot()
+    const { container } = render(<div className={cls1} />)
+    expect(container.firstChild).toMatchSnapshot()
   })
-  test.skip('nested at rules', () => {
+  test('nested at rules', () => {
     const cls1 = css`
       @supports (display: grid) {
         display: grid;
@@ -160,8 +160,8 @@ describe('css', () => {
         }
       }
     `
-    const tree = renderer.create(<div className={cls1} />).toJSON()
-    expect(tree).toMatchSnapshot()
+    const { container } = render(<div className={cls1} />)
+    expect(container.firstChild).toMatchSnapshot()
   })
   test('nested array', () => {
     const cls1 = css([
@@ -184,26 +184,26 @@ describe('css', () => {
         ]
       ]
     ])
-    const tree = renderer.create(<div className={cls1} />).toJSON()
-    expect(tree).toMatchSnapshot()
+    const { container } = render(<div className={cls1} />)
+    expect(container.firstChild).toMatchSnapshot()
   })
 
   test('explicit false', () => {
     const cls1 = css(false)
-    const tree = renderer.create(<div className={cls1} />).toJSON()
-    expect(tree).toMatchSnapshot()
+    const { container } = render(<div className={cls1} />)
+    expect(container.firstChild).toMatchSnapshot()
   })
 
   test('array with explicit false', () => {
     const cls1 = css([[{ display: 'flex' }], false])
-    const tree = renderer.create(<div className={cls1} />).toJSON()
-    expect(tree).toMatchSnapshot()
+    const { container } = render(<div className={cls1} />)
+    expect(container.firstChild).toMatchSnapshot()
   })
 
   test('array with explicit true', () => {
     const cls1 = css([[{ display: 'flex' }], true])
-    const tree = renderer.create(<div className={cls1} />).toJSON()
-    expect(tree).toMatchSnapshot()
+    const { container } = render(<div className={cls1} />)
+    expect(container.firstChild).toMatchSnapshot()
   })
 
   test('nested', () => {
@@ -219,16 +219,14 @@ describe('css', () => {
         }
       }
     `
-    const tree = renderer
-      .create(
-        <div className={cls1}>
-          <div className="some-class">
-            <div className="some-other-class" />
-          </div>
+    const { container } = render(
+      <div className={cls1}>
+        <div className="some-class">
+          <div className="some-other-class" />
         </div>
-      )
-      .toJSON()
-    expect(tree).toMatchSnapshot()
+      </div>
+    )
+    expect(container.firstChild).toMatchSnapshot()
   })
   test('explicit &', () => {
     flush()
@@ -237,62 +235,62 @@ describe('css', () => {
         display: flex;
       }
     `
-    const tree = renderer
-      .create(<div className={`${cls1} another-class`} />)
-      .toJSON()
-    expect(tree).toMatchSnapshot()
+    const { container } = render(<div className={`${cls1} another-class`} />)
+    expect(container.firstChild).toMatchSnapshot()
     expect(sheet).toMatchSnapshot()
     flush()
   })
   test('falsy property value in object', () => {
     const cls = css({ display: 'flex', backgroundColor: undefined })
-    const tree = renderer.create(<div className={cls} />).toJSON()
-    expect(tree).toMatchSnapshot()
+    const { container } = render(<div className={cls} />)
+    expect(container.firstChild).toMatchSnapshot()
   })
   test('registered styles as nested selector value in object', () => {
     const cls = css({ display: 'flex', backgroundColor: 'hotpink' })
     const cls1 = css({ ':hover': cls })
-    const tree = renderer.create(<div className={cls1} />).toJSON()
-    expect(tree).toMatchSnapshot()
+    const { container } = render(<div className={cls1} />)
+    expect(container.firstChild).toMatchSnapshot()
   })
   test('composition stuff', () => {
     const cls1 = css({ justifyContent: 'center' })
     const cls2 = css([cls1])
-    const tree = renderer.create(<div className={cls1} />).toJSON()
-    expect(tree).toMatchSnapshot()
-    const tree2 = renderer.create(<div className={cls2} />).toJSON()
-    expect(tree2).toMatchSnapshot()
+    const { container: container1 } = render(<div className={cls1} />)
+    expect(container1.firstChild).toMatchSnapshot()
+    const { container: container2 } = render(<div className={cls2} />)
+    expect(container2.firstChild).toMatchSnapshot()
   })
   test('null rule', () => {
     const cls1 = css()
 
-    const tree = renderer.create(<div className={cls1} />).toJSON()
-    expect(tree).toMatchSnapshot()
+    const { container } = render(<div className={cls1} />)
+    expect(container.firstChild).toMatchSnapshot()
   })
   test('css variables', () => {
     const cls1 = css`
       --some-var: 1px;
       width: var(--some-var);
     `
-    const tree = renderer.create(<div className={cls1} />).toJSON()
-    expect(tree).toMatchSnapshot()
+    const { container } = render(<div className={cls1} />)
+    expect(container.firstChild).toMatchSnapshot()
   })
 
   test('null value', () => {
     const cls1 = css(null)
 
-    expect(renderer.create(<div className={cls1} />).toJSON()).toMatchSnapshot()
+    expect(
+      render(<div className={cls1} />).container.firstChild
+    ).toMatchSnapshot()
   })
 
   test('flushes correctly', () => {
     const cls1 = css`
       display: flex;
     `
-    const tree = renderer.create(<div className={cls1} />).toJSON()
-    expect(tree).toMatchSnapshot()
+    const { container: container1 } = render(<div className={cls1} />)
+    expect(container1.firstChild).toMatchSnapshot()
     flush()
-    const tree2 = renderer.create(<div className={cls1} />).toJSON()
-    expect(tree2).toMatchSnapshot()
+    const { container: container2 } = render(<div className={cls1} />)
+    expect(container2.firstChild).toMatchSnapshot()
   })
   test('media query specificity', () => {
     flush()
@@ -307,19 +305,19 @@ describe('css', () => {
       }
     `
 
-    const tree = renderer.create(<div className={cls} />).toJSON()
+    const { container } = render(<div className={cls} />)
     expect(sheet).toMatchSnapshot()
-    expect(tree).toMatchSnapshot()
+    expect(container.firstChild).toMatchSnapshot()
     flush()
   })
   test('weakmap', () => {
     const styles = { display: 'flex' }
     const cls1 = css(styles)
     const cls2 = css(styles)
-    const tree1 = renderer.create(<div className={cls1} />).toJSON()
-    expect(tree1).toMatchSnapshot()
-    const tree2 = renderer.create(<div className={cls2} />).toJSON()
-    expect(tree2).toMatchSnapshot()
+    const { container: container1 } = render(<div className={cls1} />)
+    expect(container1.firstChild).toMatchSnapshot()
+    const { container: container2 } = render(<div className={cls2} />)
+    expect(container2.firstChild).toMatchSnapshot()
   })
 
   test('manually use label property', () => {
@@ -328,8 +326,8 @@ describe('css', () => {
       color: hotpink;
       label: wow;
     `
-    const tree = renderer.create(<div className={cls1} />).toJSON()
-    expect(tree).toMatchSnapshot()
+    const { container } = render(<div className={cls1} />)
+    expect(container.firstChild).toMatchSnapshot()
     expect(sheet).toMatchSnapshot()
   })
   test('multiline declaration', () => {
@@ -343,8 +341,8 @@ describe('css', () => {
     `
     /* eslint-enable prettier/prettier */
 
-    const tree = renderer.create(<div className={cls1} />).toJSON()
-    expect(tree).toMatchSnapshot()
+    const { container } = render(<div className={cls1} />)
+    expect(container.firstChild).toMatchSnapshot()
   })
   test('multiline selector', () => {
     /* eslint-disable prettier/prettier */
@@ -355,8 +353,8 @@ describe('css', () => {
     `
     /* eslint-enable prettier/prettier */
 
-    const tree = renderer.create(<div className={cls1} />).toJSON()
-    expect(tree).toMatchSnapshot()
+    const { container } = render(<div className={cls1} />)
+    expect(container.firstChild).toMatchSnapshot()
   })
   test('rule after media query', () => {
     const cls1 = css`
@@ -367,8 +365,8 @@ describe('css', () => {
         color: hotpink;
       }
     `
-    const tree = renderer.create(<div className={cls1} />).toJSON()
-    expect(tree).toMatchSnapshot()
+    const { container } = render(<div className={cls1} />)
+    expect(container.firstChild).toMatchSnapshot()
   })
   test('nested at rule', () => {
     const cls = css({
@@ -380,14 +378,14 @@ describe('css', () => {
       }
     })
     // this works correctly but `css` doesn't print it correctly so the snapshot doesn't look correct
-    const tree = renderer.create(<div className={cls} />).toJSON()
-    expect(tree).toMatchSnapshot()
+    const { container } = render(<div className={cls} />)
+    expect(container.firstChild).toMatchSnapshot()
   })
   test('array fallback', () => {
     const cls = css({
       color: ['yellow', 'hotpink']
     })
-    const tree = renderer.create(<div className={cls} />).toJSON()
-    expect(tree).toMatchSnapshot()
+    const { container } = render(<div className={cls} />)
+    expect(container.firstChild).toMatchSnapshot()
   })
 })
diff --git a/packages/css/test/cx.test.js b/packages/css/test/cx.test.js
index a05b72002f..1c75d35403 100644
--- a/packages/css/test/cx.test.js
+++ b/packages/css/test/cx.test.js
@@ -1,6 +1,6 @@
 import 'test-utils/setup-env'
 import React from 'react'
-import renderer from 'react-test-renderer'
+import { render } from '@testing-library/react'
 import { css, cx } from '@emotion/css'
 
 describe('cx', () => {
@@ -10,8 +10,8 @@ describe('cx', () => {
       background: green;
     `
 
-    const tree = renderer.create(<div className={cx(cls1, 'modal')} />).toJSON()
-    expect(tree).toMatchSnapshot()
+    const { container } = render(<div className={cx(cls1, 'modal')} />)
+    expect(container.firstChild).toMatchSnapshot()
   })
 
   test('merge 3', () => {
@@ -24,10 +24,8 @@ describe('cx', () => {
       background: blue;
     `
 
-    const tree = renderer
-      .create(<div className={cx(cls1, cls2, 'modal')} />)
-      .toJSON()
-    expect(tree).toMatchSnapshot()
+    const { container } = render(<div className={cx(cls1, cls2, 'modal')} />)
+    expect(container.firstChild).toMatchSnapshot()
   })
 
   test('merge 4', () => {
@@ -40,10 +38,11 @@ describe('cx', () => {
       background: blue;
     `
 
-    const tree = renderer
-      .create(<div className={cx(cls1, cls2, 'modal', 'profile')} />)
-      .toJSON()
-    expect(tree).toMatchSnapshot()
+    const { container } = render(
+      <div className={cx(cls1, cls2, 'modal', 'profile')} />
+    )
+
+    expect(container.firstChild).toMatchSnapshot()
   })
 
   test('all types', () => {
@@ -69,16 +68,14 @@ describe('cx', () => {
     const foo = true
     const bar = false
 
-    const tree = renderer
-      .create(
-        <div
-          className={cx({ [cls1]: foo }, 'modal', { [cls2]: bar }, 'profile', [
-            [cls3, [cls4]]
-          ])}
-        />
-      )
-      .toJSON()
-    expect(tree).toMatchSnapshot()
+    const { container } = render(
+      <div
+        className={cx({ [cls1]: foo }, 'modal', { [cls2]: bar }, 'profile', [
+          [cls3, [cls4]]
+        ])}
+      />
+    )
+    expect(container.firstChild).toMatchSnapshot()
   })
 
   test('fun fun functions', () => {
@@ -101,17 +98,15 @@ describe('cx', () => {
       background: darkgreen;
     `
 
-    const tree = renderer
-      .create(
-        <div
-          className={cx([
-            [cls1, false && cls2, 'modal'],
-            [cls3, { [cls4]: true }, 'profile']
-          ])}
-        />
-      )
-      .toJSON()
-    expect(tree).toMatchSnapshot()
+    const { container } = render(
+      <div
+        className={cx([
+          [cls1, false && cls2, 'modal'],
+          [cls3, { [cls4]: true }, 'profile']
+        ])}
+      />
+    )
+    expect(container.firstChild).toMatchSnapshot()
   })
   test('no extra whitespace', () => {
     expect(cx('blockquote', '', 'news')).toMatchSnapshot()
diff --git a/packages/css/test/instance/__snapshots__/css.test.js.snap b/packages/css/test/instance/__snapshots__/css.test.js.snap
index ec57cd312b..1c4228cbfc 100644
--- a/packages/css/test/instance/__snapshots__/css.test.js.snap
+++ b/packages/css/test/instance/__snapshots__/css.test.js.snap
@@ -8,7 +8,7 @@ exports[`css @supports 1`] = `
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 />
 `;
 
@@ -18,7 +18,7 @@ exports[`css array with explicit false 1`] = `
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 />
 `;
 
@@ -28,7 +28,7 @@ exports[`css array with explicit true 1`] = `
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 />
 `;
 
@@ -40,7 +40,7 @@ exports[`css auto px 1`] = `
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 />
 `;
 
@@ -50,7 +50,7 @@ exports[`css boolean as value 1`] = `
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 />
 `;
 
@@ -60,7 +60,7 @@ exports[`css composition stuff 1`] = `
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 />
 `;
 
@@ -70,7 +70,7 @@ exports[`css composition stuff 2`] = `
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 />
 `;
 
@@ -98,7 +98,7 @@ exports[`css composition with objects 1`] = `
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 />
 `;
 
@@ -109,7 +109,7 @@ exports[`css computed key is only dynamic 1`] = `
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 />
 `;
 
@@ -120,7 +120,7 @@ exports[`css css variables 1`] = `
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 />
 `;
 
@@ -130,7 +130,7 @@ exports[`css explicit & 1`] = `
 }
 
 <div
-  className="emotion-0 another-class"
+  class="emotion-0 another-class"
 />
 `;
 
@@ -142,7 +142,7 @@ exports[`css explicit & 2`] = `
 
 exports[`css explicit false 1`] = `
 <div
-  className="emotion-0"
+  class="emotion-0"
 />
 `;
 
@@ -152,7 +152,7 @@ exports[`css falsy property value in object 1`] = `
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 />
 `;
 
@@ -162,7 +162,7 @@ exports[`css falsy value in nested selector on object 1`] = `
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 />
 `;
 
@@ -172,7 +172,7 @@ exports[`css float property 1`] = `
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 />
 `;
 
@@ -182,13 +182,13 @@ exports[`css flushes correctly 1`] = `
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 />
 `;
 
 exports[`css flushes correctly 2`] = `
 <div
-  className="some-key-vyoujf"
+  class="some-key-vyoujf"
 />
 `;
 
@@ -199,7 +199,7 @@ exports[`css handles array of objects 1`] = `
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 />
 `;
 
@@ -219,7 +219,7 @@ exports[`css handles more than 10 dynamic properties 1`] = `
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 />
 `;
 
@@ -234,7 +234,7 @@ exports[`css handles objects 1`] = `
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 />
 `;
 
@@ -244,7 +244,7 @@ exports[`css manually use label property 1`] = `
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 />
 `;
 
@@ -284,7 +284,7 @@ exports[`css media query specificity 2`] = `
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 />
 `;
 
@@ -308,13 +308,13 @@ exports[`css nested 1`] = `
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 >
   <div
-    className="some-class"
+    class="some-class"
   >
     <div
-      className="some-other-class"
+      class="some-other-class"
     />
   </div>
 </div>
@@ -336,25 +336,55 @@ exports[`css nested array 1`] = `
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
+/>
+`;
+
+exports[`css nested at rules 1`] = `
+@supports (display: grid) {
+  .emotion-0 {
+    display: grid;
+  }
+
+  @supports (display: flex) {
+    .emotion-0 {
+      display: flex;
+    }
+  }
+}
+
+@media (min-width: 420px) {
+  .emotion-0 {
+    color: hotpink;
+  }
+
+  @media (max-width: 500px) {
+    .emotion-0 {
+      color: hotpink;
+    }
+  }
+}
+
+<div
+  class="emotion-0"
 />
 `;
 
 exports[`css null rule 1`] = `
 <div
-  className="emotion-0"
+  class="emotion-0"
 />
 `;
 
 exports[`css null value 1`] = `
 <div
-  className="emotion-0"
+  class="emotion-0"
 />
 `;
 
 exports[`css null value 2`] = `
 <div
-  className="emotion-0"
+  class="emotion-0"
 />
 `;
 
@@ -374,7 +404,7 @@ exports[`css random expression 1`] = `
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 />
 `;
 
@@ -384,7 +414,7 @@ exports[`css random interpolation with undefined values 1`] = `
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 />
 `;
 
@@ -395,7 +425,7 @@ exports[`css registered styles as nested selector value in object 1`] = `
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 />
 `;
 
@@ -410,7 +440,7 @@ exports[`css simple composition 1`] = `
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 />
 `;
 
@@ -420,7 +450,7 @@ exports[`css weakmap 1`] = `
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 />
 `;
 
@@ -430,6 +460,6 @@ exports[`css weakmap 2`] = `
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 />
 `;
diff --git a/packages/css/test/instance/css.test.js b/packages/css/test/instance/css.test.js
index cce9704274..600cbdc38e 100644
--- a/packages/css/test/instance/css.test.js
+++ b/packages/css/test/instance/css.test.js
@@ -1,6 +1,7 @@
 import 'test-utils/setup-env'
 import React from 'react'
-import renderer from 'react-test-renderer'
+import { act } from 'react'
+import { render } from '@testing-library/react'
 import { css as differentCss, flush, sheet } from './emotion-instance'
 
 describe('css', () => {
@@ -9,8 +10,8 @@ describe('css', () => {
       float: left;
     `
 
-    const tree = renderer.create(<div className={cls1} />).toJSON()
-    expect(tree).toMatchSnapshot()
+    const { container } = render(<div className={cls1} />)
+    expect(container.firstChild).toMatchSnapshot()
   })
 
   test('handles more than 10 dynamic properties', () => {
@@ -28,14 +29,14 @@ describe('css', () => {
       text-align: ${'center'};
     `
 
-    const tree = renderer.create(<div className={cls1} />).toJSON()
-    expect(tree).toMatchSnapshot()
+    const { container } = render(<div className={cls1} />)
+    expect(container.firstChild).toMatchSnapshot()
   })
 
   test('falsy value in nested selector on object', () => {
     const cls1 = differentCss({ ':hover': { display: null, color: 'hotpink' } })
-    const tree = renderer.create(<div className={cls1} />).toJSON()
-    expect(tree).toMatchSnapshot()
+    const { container } = render(<div className={cls1} />)
+    expect(container.firstChild).toMatchSnapshot()
   })
   test('boolean as value', () => {
     const cls1 = differentCss({
@@ -43,13 +44,13 @@ describe('css', () => {
       color: false,
       backgroundColor: true
     })
-    const tree = renderer.create(<div className={cls1} />).toJSON()
-    expect(tree).toMatchSnapshot()
+    const { container } = render(<div className={cls1} />)
+    expect(container.firstChild).toMatchSnapshot()
   })
   test('auto px', () => {
     const cls1 = differentCss({ display: 'flex', flex: 1, fontSize: 10 })
-    const tree = renderer.create(<div className={cls1} />).toJSON()
-    expect(tree).toMatchSnapshot()
+    const { container } = render(<div className={cls1} />)
+    expect(container.firstChild).toMatchSnapshot()
   })
 
   test('random interpolation with undefined values', () => {
@@ -57,8 +58,8 @@ describe('css', () => {
       ${undefined};
       justify-content: center;
     `
-    const tree = renderer.create(<div className={cls2} />).toJSON()
-    expect(tree).toMatchSnapshot()
+    const { container } = render(<div className={cls2} />)
+    expect(container.firstChild).toMatchSnapshot()
   })
 
   test('random expression', () => {
@@ -74,8 +75,8 @@ describe('css', () => {
       }
       background: green;
     `
-    const tree = renderer.create(<div className={cls2} />).toJSON()
-    expect(tree).toMatchSnapshot()
+    const { container } = render(<div className={cls2} />)
+    expect(container.firstChild).toMatchSnapshot()
   })
 
   test('simple composition', () => {
@@ -89,8 +90,8 @@ describe('css', () => {
       ${cls1};
       justify-content: center;
     `
-    const tree = renderer.create(<div className={cls2} />).toJSON()
-    expect(tree).toMatchSnapshot()
+    const { container } = render(<div className={cls2} />)
+    expect(container.firstChild).toMatchSnapshot()
   })
 
   test('handles objects', () => {
@@ -102,20 +103,20 @@ describe('css', () => {
       height: 50,
       width: 20
     })
-    const tree = renderer.create(<div className={cls1} />).toJSON()
-    expect(tree).toMatchSnapshot()
+    const { container } = render(<div className={cls1} />)
+    expect(container.firstChild).toMatchSnapshot()
   })
 
   test('handles array of objects', () => {
     const cls1 = differentCss([{ height: 50, width: 20 }, null])
-    const tree = renderer.create(<div className={cls1} />).toJSON()
-    expect(tree).toMatchSnapshot()
+    const { container } = render(<div className={cls1} />)
+    expect(container.firstChild).toMatchSnapshot()
   })
 
   test('computed key is only dynamic', () => {
     const cls1 = differentCss({ fontSize: 10, [`w${'idth'}`]: 20 })
-    const tree = renderer.create(<div className={cls1} />).toJSON()
-    expect(tree).toMatchSnapshot()
+    const { container } = render(<div className={cls1} />)
+    expect(container.firstChild).toMatchSnapshot()
   })
 
   test('composition with objects', () => {
@@ -137,8 +138,8 @@ describe('css', () => {
       justify-content: center;
     `
 
-    const tree = renderer.create(<div className={cls2} />).toJSON()
-    expect(tree).toMatchSnapshot()
+    const { container } = render(<div className={cls2} />)
+    expect(container.firstChild).toMatchSnapshot()
   })
   test('@supports', () => {
     const cls1 = differentCss`
@@ -146,10 +147,10 @@ describe('css', () => {
         display: grid;
       }
     `
-    const tree = renderer.create(<div className={cls1} />).toJSON()
-    expect(tree).toMatchSnapshot()
+    const { container } = render(<div className={cls1} />)
+    expect(container.firstChild).toMatchSnapshot()
   })
-  test.skip('nested at rules', () => {
+  test('nested at rules', () => {
     const cls1 = differentCss`
       @supports (display: grid) {
         display: grid;
@@ -164,8 +165,8 @@ describe('css', () => {
         }
       }
     `
-    const tree = renderer.create(<div className={cls1} />).toJSON()
-    expect(tree).toMatchSnapshot()
+    const { container } = render(<div className={cls1} />)
+    expect(container.firstChild).toMatchSnapshot()
   })
   test('nested array', () => {
     const cls1 = differentCss([
@@ -188,26 +189,26 @@ describe('css', () => {
         ]
       ]
     ])
-    const tree = renderer.create(<div className={cls1} />).toJSON()
-    expect(tree).toMatchSnapshot()
+    const { container } = render(<div className={cls1} />)
+    expect(container.firstChild).toMatchSnapshot()
   })
 
   test('explicit false', () => {
     const cls1 = differentCss(false)
-    const tree = renderer.create(<div className={cls1} />).toJSON()
-    expect(tree).toMatchSnapshot()
+    const { container } = render(<div className={cls1} />)
+    expect(container.firstChild).toMatchSnapshot()
   })
 
   test('array with explicit false', () => {
     const cls1 = differentCss([[{ display: 'flex' }], false])
-    const tree = renderer.create(<div className={cls1} />).toJSON()
-    expect(tree).toMatchSnapshot()
+    const { container } = render(<div className={cls1} />)
+    expect(container.firstChild).toMatchSnapshot()
   })
 
   test('array with explicit true', () => {
     const cls1 = differentCss([[{ display: 'flex' }], true])
-    const tree = renderer.create(<div className={cls1} />).toJSON()
-    expect(tree).toMatchSnapshot()
+    const { container } = render(<div className={cls1} />)
+    expect(container.firstChild).toMatchSnapshot()
   })
 
   test('nested', () => {
@@ -223,16 +224,15 @@ describe('css', () => {
         }
       }
     `
-    const tree = renderer
-      .create(
-        <div className={cls1}>
-          <div className="some-class">
-            <div className="some-other-class" />
-          </div>
+    const { container } = render(
+      <div className={cls1}>
+        <div className="some-class">
+          <div className="some-other-class" />
         </div>
-      )
-      .toJSON()
-    expect(tree).toMatchSnapshot()
+      </div>
+    )
+
+    expect(container.firstChild).toMatchSnapshot()
   })
   test('explicit &', () => {
     flush()
@@ -241,45 +241,44 @@ describe('css', () => {
         display: flex;
       }
     `
-    const tree = renderer
-      .create(<div className={`${cls1} another-class`} />)
-      .toJSON()
-    expect(tree).toMatchSnapshot()
+    const { container } = render(<div className={`${cls1} another-class`} />)
+
+    expect(container.firstChild).toMatchSnapshot()
     expect(sheet).toMatchSnapshot()
     flush()
   })
   test('falsy property value in object', () => {
     const cls = differentCss({ display: 'flex', backgroundColor: undefined })
-    const tree = renderer.create(<div className={cls} />).toJSON()
-    expect(tree).toMatchSnapshot()
+    const { container } = render(<div className={cls} />)
+    expect(container.firstChild).toMatchSnapshot()
   })
   test('registered styles as nested selector value in object', () => {
     const cls = differentCss({ display: 'flex', backgroundColor: 'hotpink' })
     const cls1 = differentCss({ ':hover': cls })
-    const tree = renderer.create(<div className={cls1} />).toJSON()
-    expect(tree).toMatchSnapshot()
+    const { container } = render(<div className={cls1} />)
+    expect(container.firstChild).toMatchSnapshot()
   })
   test('composition stuff', () => {
     const cls1 = differentCss({ justifyContent: 'center' })
     const cls2 = differentCss([cls1])
-    const tree = renderer.create(<div className={cls1} />).toJSON()
-    expect(tree).toMatchSnapshot()
-    const tree2 = renderer.create(<div className={cls2} />).toJSON()
-    expect(tree2).toMatchSnapshot()
+    const { container: container1 } = render(<div className={cls1} />)
+    expect(container1.firstChild).toMatchSnapshot()
+    const { container: container2 } = render(<div className={cls2} />)
+    expect(container2.firstChild).toMatchSnapshot()
   })
   test('null rule', () => {
     const cls1 = differentCss()
 
-    const tree = renderer.create(<div className={cls1} />).toJSON()
-    expect(tree).toMatchSnapshot()
+    const { container } = render(<div className={cls1} />)
+    expect(container.firstChild).toMatchSnapshot()
   })
   test('css variables', () => {
     const cls1 = differentCss`
       --some-var: 1px;
       width: var(--some-var);
     `
-    const tree = renderer.create(<div className={cls1} />).toJSON()
-    expect(tree).toMatchSnapshot()
+    const { container } = render(<div className={cls1} />)
+    expect(container.firstChild).toMatchSnapshot()
   })
 
   test('null value', () => {
@@ -287,19 +286,23 @@ describe('css', () => {
     const cls2 = differentCss`
       ${null};
     `
-    expect(renderer.create(<div className={cls1} />).toJSON()).toMatchSnapshot()
-    expect(renderer.create(<div className={cls2} />).toJSON()).toMatchSnapshot()
+    expect(
+      render(<div className={cls1} />).container.firstChild
+    ).toMatchSnapshot()
+    expect(
+      render(<div className={cls2} />).container.firstChild
+    ).toMatchSnapshot()
   })
 
   test('flushes correctly', () => {
     const cls1 = differentCss`
       display: flex;
     `
-    const tree = renderer.create(<div className={cls1} />).toJSON()
-    expect(tree).toMatchSnapshot()
+    const { container: container1 } = render(<div className={cls1} />)
+    expect(container1.firstChild).toMatchSnapshot()
     flush()
-    const tree2 = renderer.create(<div className={cls1} />).toJSON()
-    expect(tree2).toMatchSnapshot()
+    const { container: container2 } = render(<div className={cls1} />)
+    expect(container2.firstChild).toMatchSnapshot()
   })
   test('media query specificity', () => {
     flush()
@@ -314,19 +317,19 @@ describe('css', () => {
       }
     `
 
-    const tree = renderer.create(<div className={cls} />).toJSON()
+    const { container } = render(<div className={cls} />)
     expect(sheet).toMatchSnapshot()
-    expect(tree).toMatchSnapshot()
+    expect(container.firstChild).toMatchSnapshot()
     flush()
   })
   test('weakmap', () => {
     const styles = { display: 'flex' }
     const cls1 = differentCss(styles)
     const cls2 = differentCss(styles)
-    const tree1 = renderer.create(<div className={cls1} />).toJSON()
-    expect(tree1).toMatchSnapshot()
-    const tree2 = renderer.create(<div className={cls2} />).toJSON()
-    expect(tree2).toMatchSnapshot()
+    const { container: container1 } = render(<div className={cls1} />)
+    expect(container1.firstChild).toMatchSnapshot()
+    const { container: container2 } = render(<div className={cls2} />)
+    expect(container2.firstChild).toMatchSnapshot()
   })
 
   test('manually use label property', () => {
@@ -335,8 +338,8 @@ describe('css', () => {
       color: hotpink;
       label: wow;
     `
-    const tree = renderer.create(<div className={cls1} />).toJSON()
-    expect(tree).toMatchSnapshot()
+    const { container } = render(<div className={cls1} />)
+    expect(container.firstChild).toMatchSnapshot()
     expect(sheet).toMatchSnapshot()
   })
   test('sets correct nonce value', () => {
diff --git a/packages/css/test/instance/inline.test.js b/packages/css/test/instance/inline.test.js
index dd3be901ad..6d65cdd6fb 100644
--- a/packages/css/test/instance/inline.test.js
+++ b/packages/css/test/instance/inline.test.js
@@ -1,8 +1,4 @@
-import {
-  stripDataReactRoot,
-  disableBrowserEnvTemporarily,
-  safeQuerySelector
-} from 'test-utils'
+import { disableBrowserEnvTemporarily, safeQuerySelector } from 'test-utils'
 import {
   getComponents,
   getInjectedRules,
@@ -41,15 +37,14 @@ describe('renderStylesToString', () => {
       ).toMatchSnapshot()
     })
   })
-  test('renders large recursive component', async () => {
+  // blocked on https://github.com/facebook/react/issues/31754
+  test.skip('renders large recursive component', async () => {
     await disableBrowserEnvTemporarily(() => {
       resetAllModules()
       const BigComponent = createBigComponent(emotion)
       expect(
-        stripDataReactRoot(
-          emotionServer.renderStylesToString(
-            renderToString(<BigComponent count={200} />)
-          )
+        emotionServer.renderStylesToString(
+          renderToString(<BigComponent count={200} />)
         )
       ).toMatchSnapshot()
     })
diff --git a/packages/css/test/instance/stream.test.js b/packages/css/test/instance/stream.test.js
index c73e696c8a..3324194297 100644
--- a/packages/css/test/instance/stream.test.js
+++ b/packages/css/test/instance/stream.test.js
@@ -1,8 +1,6 @@
-import {
-  stripDataReactRoot,
-  disableBrowserEnvTemporarily,
-  safeQuerySelector
-} from 'test-utils'
+import { disableBrowserEnvTemporarily, safeQuerySelector } from 'test-utils'
+
+globalThis.setImmediate ??= cb => setTimeout(cb, 0)
 
 let React
 let renderToString
@@ -36,16 +34,16 @@ describe('renderStylesToNodeStream', () => {
       ).toMatchSnapshot()
     })
   })
-  test('renders large recursive component', async () => {
+
+  // blocked on https://github.com/facebook/react/issues/31754
+  test.skip('renders large recursive component', async () => {
     await disableBrowserEnvTemporarily(async () => {
       resetAllModules()
       const BigComponent = util.createBigComponent(emotion)
       expect(
-        stripDataReactRoot(
-          await util.renderToStringWithStream(
-            <BigComponent count={200} />,
-            emotionServer
-          )
+        await util.renderToStringWithStream(
+          <BigComponent count={200} />,
+          emotionServer
         )
       ).toMatchSnapshot()
     })
diff --git a/packages/css/test/keyframes.test.js b/packages/css/test/keyframes.test.js
index 863a6ab4ad..24fb200954 100644
--- a/packages/css/test/keyframes.test.js
+++ b/packages/css/test/keyframes.test.js
@@ -1,6 +1,6 @@
 import 'test-utils/setup-env'
 import React from 'react'
-import renderer from 'react-test-renderer'
+import { render } from '@testing-library/react'
 import { keyframes, flush, css } from '@emotion/css'
 
 describe('keyframes', () => {
@@ -29,43 +29,39 @@ describe('keyframes', () => {
       }
     `
 
-    const tree = renderer
-      .create(
-        <h1
-          className={css`
-            animation: ${bounce} 2s linear infinite;
-          `}
-        >
-          hello world
-        </h1>
-      )
-      .toJSON()
+    const { container } = render(
+      <h1
+        className={css`
+          animation: ${bounce} 2s linear infinite;
+        `}
+      >
+        hello world
+      </h1>
+    )
 
-    expect(tree).toMatchSnapshot()
+    expect(container.firstChild).toMatchSnapshot()
   })
   test('keyframes with interpolation', () => {
     const endingRotation = '360deg'
 
-    const tree = renderer
-      .create(
-        <h1
-          className={css`
-            animation: ${keyframes`
-    from {
-      transform: rotate(0deg);
-    }
+    const { container } = render(
+      <h1
+        className={css`
+          animation: ${keyframes`
+            from {
+              transform: rotate(0deg);
+            }
 
-    to {
-      transform: rotate(${endingRotation});
-    }
-  `} 2s linear infinite;
-          `}
-        >
-          hello world
-        </h1>
-      )
-      .toJSON()
+            to {
+              transform: rotate(${endingRotation});
+            }
+          `} 2s linear infinite;
+        `}
+      >
+        hello world
+      </h1>
+    )
 
-    expect(tree).toMatchSnapshot()
+    expect(container.firstChild).toMatchSnapshot()
   })
 })
diff --git a/packages/css/test/label-pattern.test.js b/packages/css/test/label-pattern.test.js
index 94e54bc440..428c7bdfa8 100644
--- a/packages/css/test/label-pattern.test.js
+++ b/packages/css/test/label-pattern.test.js
@@ -1,7 +1,7 @@
 import 'test-utils/setup-env'
 import React from 'react'
+import { render } from '@testing-library/react'
 import styled from '@emotion/styled'
-import renderer from 'react-test-renderer'
 import { flush } from '@emotion/css'
 
 describe('label pattern', () => {
@@ -15,15 +15,13 @@ describe('label pattern', () => {
       }
     `
 
-    const tree = renderer
-      .create(
-        <div>
-          <Input />
-          <label>Label</label>
-        </div>
-      )
-      .toJSON()
+    const { container } = render(
+      <div>
+        <Input />
+        <label>Label</label>
+      </div>
+    )
 
-    expect(tree).toMatchSnapshot()
+    expect(container.firstChild).toMatchSnapshot()
   })
 })
diff --git a/packages/css/test/no-babel/__snapshots__/index.test.js.snap b/packages/css/test/no-babel/__snapshots__/index.test.js.snap
index 46b809fff8..ab9d62bb38 100644
--- a/packages/css/test/no-babel/__snapshots__/index.test.js.snap
+++ b/packages/css/test/no-babel/__snapshots__/index.test.js.snap
@@ -8,14 +8,12 @@ exports[`css @supports 1`] = `
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 />
 `;
 
 exports[`css component as selectors (object syntax) 1`] = `"Component selectors can only be used in conjunction with @emotion/babel-plugin, the swc Emotion plugin, or another Emotion-aware compiler transform."`;
 
-exports[`css component as selectors (object syntax) 2`] = `"The above error occurred in the <Styled(div)> component:"`;
-
 exports[`css component selectors without target 1`] = `"Component selectors can only be used in conjunction with @emotion/babel-plugin, the swc Emotion plugin, or another Emotion-aware compiler transform."`;
 
 exports[`css composition 1`] = `
@@ -35,7 +33,7 @@ exports[`css composition 1`] = `
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 />
 `;
 
@@ -48,7 +46,7 @@ exports[`css composition stuff 1`] = `
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 />
 `;
 
@@ -61,7 +59,7 @@ exports[`css composition stuff 2`] = `
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 />
 `;
 
@@ -95,7 +93,7 @@ exports[`css composition with objects 1`] = `
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 />
 `;
 
@@ -106,8 +104,8 @@ exports[`css function in expression 1`] = `
 }
 
 <h1
-  className="legacy__class emotion-0"
-  scale={2}
+  class="legacy__class emotion-0"
+  scale="2"
 >
   hello world
 </h1>
@@ -126,8 +124,8 @@ exports[`css glamorous style api & composition 1`] = `
 }
 
 <h1
-  className="emotion-0"
-  fontSize={20}
+  class="emotion-0"
+  font-size="20"
 >
   hello world
 </h1>
@@ -147,7 +145,7 @@ exports[`css handles objects 1`] = `
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 />
 `;
 
@@ -160,7 +158,7 @@ exports[`css nested array 1`] = `
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 />
 `;
 
@@ -170,7 +168,7 @@ exports[`css no dynamic 1`] = `
 }
 
 <h1
-  className="emotion-0"
+  class="emotion-0"
 >
   hello world
 </h1>
@@ -178,7 +176,7 @@ exports[`css no dynamic 1`] = `
 
 exports[`css null rule 1`] = `
 <div
-  className="emotion-0"
+  class="emotion-0"
 />
 `;
 
@@ -195,8 +193,8 @@ exports[`css object as style 1`] = `
 }
 
 <h1
-  className="emotion-0"
-  fontSize={20}
+  class="emotion-0"
+  font-size="20"
 >
   hello world
 </h1>
@@ -218,7 +216,7 @@ exports[`css random expression 1`] = `
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 />
 `;
 
@@ -228,7 +226,7 @@ exports[`css random expressions undefined return 1`] = `
 }
 
 <h1
-  className="legacy__class emotion-0"
+  class="legacy__class emotion-0"
 >
   hello world
 </h1>
diff --git a/packages/css/test/no-babel/index.test.js b/packages/css/test/no-babel/index.test.js
index da31f40cf4..b5b658fd3a 100644
--- a/packages/css/test/no-babel/index.test.js
+++ b/packages/css/test/no-babel/index.test.js
@@ -1,6 +1,7 @@
 import 'test-utils/setup-env'
 import React from 'react'
-import renderer from 'react-test-renderer'
+import { act } from 'react'
+import { render } from '@testing-library/react'
 import { css } from '@emotion/css'
 import styled from '@emotion/styled'
 
@@ -24,8 +25,8 @@ describe('css', () => {
       }
       background: green;
     `
-    const tree = renderer.create(<div className={cls2} />).toJSON()
-    expect(tree).toMatchSnapshot()
+    const { container } = render(<div className={cls2} />)
+    expect(container.firstChild).toMatchSnapshot()
   })
 
   test('composition', () => {
@@ -39,8 +40,8 @@ describe('css', () => {
       ${cls1};
       justify-content: center;
     `
-    const tree = renderer.create(<div className={cls2} />).toJSON()
-    expect(tree).toMatchSnapshot()
+    const { container } = render(<div className={cls2} />)
+    expect(container.firstChild).toMatchSnapshot()
   })
 
   test('handles objects', () => {
@@ -52,8 +53,8 @@ describe('css', () => {
       height: 50,
       width: 20
     })
-    const tree = renderer.create(<div className={cls1} />).toJSON()
-    expect(tree).toMatchSnapshot()
+    const { container } = render(<div className={cls1} />)
+    expect(container.firstChild).toMatchSnapshot()
   })
 
   test('composition with objects', () => {
@@ -75,8 +76,8 @@ describe('css', () => {
       justify-content: center;
     `
 
-    const tree = renderer.create(<div className={cls2} />).toJSON()
-    expect(tree).toMatchSnapshot()
+    const { container } = render(<div className={cls2} />)
+    expect(container.firstChild).toMatchSnapshot()
   })
   test('@supports', () => {
     const cls1 = css`
@@ -84,36 +85,36 @@ describe('css', () => {
         display: grid;
       }
     `
-    const tree = renderer.create(<div className={cls1} />).toJSON()
-    expect(tree).toMatchSnapshot()
+    const { container } = render(<div className={cls1} />)
+    expect(container.firstChild).toMatchSnapshot()
   })
   test('nested array', () => {
     const cls1 = css([[{ display: 'flex' }]])
-    const tree = renderer.create(<div className={cls1} />).toJSON()
-    expect(tree).toMatchSnapshot()
+    const { container } = render(<div className={cls1} />)
+    expect(container.firstChild).toMatchSnapshot()
   })
   test('composition stuff', () => {
     const cls1 = css({ justifyContent: 'center' })
     const cls2 = css([cls1])
-    const tree = renderer.create(<div className={cls1} />).toJSON()
-    expect(tree).toMatchSnapshot()
-    const tree2 = renderer.create(<div className={cls2} />).toJSON()
-    expect(tree2).toMatchSnapshot()
+    const { container: container1 } = render(<div className={cls1} />)
+    expect(container1.firstChild).toMatchSnapshot()
+    const { container: container2 } = render(<div className={cls2} />)
+    expect(container2.firstChild).toMatchSnapshot()
   })
   test('null rule', () => {
     const cls1 = css()
 
-    const tree = renderer.create(<div className={cls1} />).toJSON()
-    expect(tree).toMatchSnapshot()
+    const { container } = render(<div className={cls1} />)
+    expect(container.firstChild).toMatchSnapshot()
   })
   test('no dynamic', () => {
     const H1 = styled('h1')`
       float: left;
     `
 
-    const tree = renderer.create(<H1>hello world</H1>).toJSON()
+    const { container } = render(<H1>hello world</H1>)
 
-    expect(tree).toMatchSnapshot()
+    expect(container.firstChild).toMatchSnapshot()
   })
   test('object as style', () => {
     const H1 = styled('h1')(
@@ -124,15 +125,13 @@ describe('css', () => {
       { display: 'flex' }
     )
 
-    const tree = renderer
-      .create(
-        <H1 fontSize={20} flex={1}>
-          hello world
-        </H1>
-      )
-      .toJSON()
+    const { container } = render(
+      <H1 fontSize={20} flex={1}>
+        hello world
+      </H1>
+    )
 
-    expect(tree).toMatchSnapshot()
+    expect(container.firstChild).toMatchSnapshot()
   })
   test('component as selectors (object syntax)', () => {
     const fontSize = '20px'
@@ -144,19 +143,13 @@ describe('css', () => {
       }
     })
 
-    const spy = jest.fn()
-    console.error = spy
-
     expect(() =>
-      renderer.create(
+      render(
         <Thing>
           hello <H1>This will be green</H1> world
         </Thing>
       )
     ).toThrowErrorMatchingSnapshot()
-
-    expect(spy.mock.calls.length).toBe(1)
-    expect(spy.mock.calls[0][0].split('\n')[0]).toMatchSnapshot()
   })
   test('component selectors without target', () => {
     const SomeComponent = styled('div')`
@@ -177,15 +170,13 @@ describe('css', () => {
       display: 'flex'
     })
 
-    const tree = renderer
-      .create(
-        <H2 fontSize={20} flex={1}>
-          hello world
-        </H2>
-      )
-      .toJSON()
+    const { container } = render(
+      <H2 fontSize={20} flex={1}>
+        hello world
+      </H2>
+    )
 
-    expect(tree).toMatchSnapshot()
+    expect(container.firstChild).toMatchSnapshot()
   })
   test('random expressions undefined return', () => {
     const H1 = styled('h1')`
@@ -197,11 +188,11 @@ describe('css', () => {
       color: green;
     `
 
-    const tree = renderer
-      .create(<H1 className={'legacy__class'}>hello world</H1>)
-      .toJSON()
+    const { container } = render(
+      <H1 className={'legacy__class'}>hello world</H1>
+    )
 
-    expect(tree).toMatchSnapshot()
+    expect(container.firstChild).toMatchSnapshot()
   })
 
   test('function in expression', () => {
@@ -214,15 +205,13 @@ describe('css', () => {
       font-size: ${({ scale }) => fontSize * scale + 'px'};
     `
 
-    const tree = renderer
-      .create(
-        <H2 scale={2} className={'legacy__class'}>
-          hello world
-        </H2>
-      )
-      .toJSON()
+    const { container } = render(
+      <H2 scale={2} className={'legacy__class'}>
+        hello world
+      </H2>
+    )
 
-    expect(tree).toMatchSnapshot()
+    expect(container.firstChild).toMatchSnapshot()
   })
   test('name with class component', () => {
     class SomeComponent extends React.Component /* <{ className: string }> */ {
diff --git a/packages/css/test/warnings.test.js b/packages/css/test/warnings.test.js
index 5769bdd238..b8e6f7808f 100644
--- a/packages/css/test/warnings.test.js
+++ b/packages/css/test/warnings.test.js
@@ -1,8 +1,8 @@
 import 'test-utils/setup-env'
 import { css } from '@emotion/css'
 import createCss from '@emotion/css/create-instance'
-import * as React from 'react'
-import renderer from 'react-test-renderer'
+import React from 'react'
+import { render } from '@testing-library/react'
 
 console.error = jest.fn()
 
@@ -37,7 +37,7 @@ afterEach(() => {
 test('does not warn when valid values are passed for the content property', () => {
   const cls = css(validValues.map(value => ({ content: value })))
   expect(console.error).not.toBeCalled()
-  expect(renderer.create(<div className={cls} />).toJSON()).toMatchSnapshot()
+  expect(render(<div className={cls} />).container.firstChild).toMatchSnapshot()
 })
 
 const invalidValues = ['this is not valid', '']
@@ -45,7 +45,7 @@ const invalidValues = ['this is not valid', '']
 test('does warn when invalid values are passed for the content property', () => {
   invalidValues.forEach(value => {
     expect(() =>
-      renderer.create(<div className={css({ content: value })} />)
+      render(<div className={css({ content: value })} />)
     ).toThrowError(
       `You seem to be using a value for 'content' without quotes, try replacing it with \`content: '"${value}"'\``
     )
diff --git a/packages/jest/README.md b/packages/jest/README.md
index b7c28917e8..675acceaf4 100644
--- a/packages/jest/README.md
+++ b/packages/jest/README.md
@@ -26,7 +26,7 @@ Or you can add the serializer via the `expect.addSnapshotSerializer` method like
 
 ```jsx
 import React from 'react'
-import renderer from 'react-test-renderer'
+import { render } from '@testing-library/react'
 import { createSerializer } from '@emotion/jest'
 import styled from '@emotion/styled'
 
@@ -37,9 +37,9 @@ test('renders with correct styles', () => {
     float: left;
   `
 
-  const tree = renderer.create(<H1>hello world</H1>).toJSON()
+  const { container } = render(<H1>hello world</H1>)
 
-  expect(tree).toMatchSnapshot()
+  expect(container).toMatchSnapshot()
 })
 ```
 
@@ -99,7 +99,7 @@ To make more explicit assertions when testing your styled components you can use
 
 ```jsx
 import React from 'react'
-import renderer from 'react-test-renderer'
+import { render } from '@testing-library/react'
 import { matchers } from '@emotion/jest'
 import styled from '@emotion/styled'
 
@@ -128,17 +128,15 @@ test('renders with correct styles', () => {
     }
   `
 
-  const tree = renderer
-    .create(
-      <Div>
-        <Svg />
-        <span>Test</span>
-      </Div>
-    )
-    .toJSON()
-
-  expect(tree).toHaveStyleRule('float', 'left')
-  expect(tree).not.toHaveStyleRule('height', '100%')
+  const { container } = render(
+    <Div>
+      <Svg />
+      <span>Test</span>
+    </Div>
+  )
+
+  expect(container.firstChild).toHaveStyleRule('float', 'left')
+  expect(container.firstChild).not.toHaveStyleRule('height', '100%')
 })
 ```
 
@@ -147,22 +145,22 @@ You can provide additional options for `toHaveStyleRule` matcher.
 where style rule should be found.
 
 ```js
-expect(tree).toHaveStyleRule('width', '50px', { target: ':hover' })
+expect(element).toHaveStyleRule('width', '50px', { target: ':hover' })
 ```
 
 ```js
-expect(tree).toHaveStyleRule('color', 'yellow', { target: 'span' })
+expect(element).toHaveStyleRule('color', 'yellow', { target: 'span' })
 ```
 
 ```js
-expect(tree).toHaveStyleRule('fill', 'green', { target: `${Svg}` })
+expect(element).toHaveStyleRule('fill', 'green', { target: `${Svg}` })
 ```
 
 `media` - specifies the media rule where the matcher
 should look for the style property.
 
 ```js
-expect(tree).toHaveStyleRule('font-size', '14px', {
+expect(element).toHaveStyleRule('font-size', '14px', {
   media: 'screen and (max-width: 1200px)'
 })
 ```
@@ -171,7 +169,7 @@ Use `media` and `target` options to assert on rules within media queries and to
 
 ```jsx
 import React from 'react'
-import renderer from 'react-test-renderer'
+import { render } from '@testing-library/react'
 import { matchers } from '@emotion/jest'
 import styled from '@emotion/styled'
 
@@ -195,11 +193,15 @@ test('renders with correct link styles', () => {
     }
   `
 
-  const tree = renderer.create(<Container>hello world</Container>).toJSON()
+  const { container } = render(<Container>hello world</Container>)
 
-  expect(tree).toHaveStyleRule('color', 'yellow', { target: /a$/ })
-  expect(tree).toHaveStyleRule('color', 'black', { target: 'a:hover' })
-  expect(tree).toHaveStyleRule('font-size', '16px', {
+  expect(container.firstChild).toHaveStyleRule('color', 'yellow', {
+    target: /a$/
+  })
+  expect(container.firstChild).toHaveStyleRule('color', 'black', {
+    target: 'a:hover'
+  })
+  expect(container.firstChild).toHaveStyleRule('font-size', '16px', {
     media: '(min-width: 768px)'
   })
 })
diff --git a/packages/jest/package.json b/packages/jest/package.json
index f017a682c8..2e335f32d3 100644
--- a/packages/jest/package.json
+++ b/packages/jest/package.json
@@ -63,8 +63,9 @@
     "@types/jest": "^29.5.12",
     "enzyme-to-json": "^3.6.1",
     "pretty-format": "^22.4.3",
-    "react": "16.14.0",
-    "react-dom": "16.14.0",
+    "react": "19.0.0",
+    "react-dom": "19.0.0",
+    "strip-ansi": "^6.0.1",
     "typescript": "^5.4.5"
   },
   "author": "Kye Hohenberger",
diff --git a/packages/jest/test/__snapshots__/matchers.test.js.snap b/packages/jest/test/__snapshots__/matchers.test.js.snap
index e8e0942745..d792336b5f 100644
--- a/packages/jest/test/__snapshots__/matchers.test.js.snap
+++ b/packages/jest/test/__snapshots__/matchers.test.js.snap
@@ -2,14 +2,14 @@
 
 exports[`toHaveStyleRule returns a message explaining the failure 1`] = `
 "Expected color to match:
-  blue
+  blue
 Received:
-  red"
+  red"
 `;
 
 exports[`toHaveStyleRule returns a message explaining the failure 2`] = `
 "Expected color not to match:
-  red
+  red
 Received:
-  red"
+  red"
 `;
diff --git a/packages/jest/test/__snapshots__/printer.test.js.snap b/packages/jest/test/__snapshots__/printer.test.js.snap
index 0fd0f49acf..0c53bd88af 100644
--- a/packages/jest/test/__snapshots__/printer.test.js.snap
+++ b/packages/jest/test/__snapshots__/printer.test.js.snap
@@ -16,7 +16,7 @@ exports[`does not replace class names that are not from emotion 1`] = `
 }
 
 <div
-  className="net-42 net emotion-0"
+  class="net-42 net emotion-0"
 />"
 `;
 
@@ -90,6 +90,6 @@ exports[`prints speedy styles 1`] = `
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 />"
 `;
diff --git a/packages/jest/test/matchers.test.js b/packages/jest/test/matchers.test.js
index 6eb9a75adc..a92b7d43b1 100644
--- a/packages/jest/test/matchers.test.js
+++ b/packages/jest/test/matchers.test.js
@@ -1,12 +1,13 @@
-import 'test-utils/setup-env'
-import renderer from 'react-test-renderer'
 /** @jsx jsx */
-import * as React from 'react'
+import 'test-utils/setup-env'
+import React from 'react'
+import { act } from 'react'
+import { render } from '@testing-library/react'
+import testRenderer from 'react-test-renderer'
 import { css, jsx } from '@emotion/react'
 import styled from '@emotion/styled'
 import { matchers } from '@emotion/jest'
-
-const isReact16 = React.version.split('.')[0] === '16'
+import stripAnsi from 'strip-ansi'
 
 const { toHaveStyleRule } = matchers
 
@@ -22,62 +23,61 @@ describe('toHaveStyleRule', () => {
   `
 
   test('matches styles on the top-most node passed in', () => {
-    const tree = renderer
-      .create(
-        <div css={divStyle}>
-          <svg css={svgStyle} />
-        </div>
-      )
-      .toJSON()
+    const { container } = render(
+      <div css={divStyle}>
+        <svg css={svgStyle} />
+      </div>
+    )
 
-    expect(tree).toHaveStyleRule('color', 'red')
-    expect(tree).not.toHaveStyleRule('width', '100%')
+    expect(container.firstChild).toHaveStyleRule('color', 'red')
+    expect(container.firstChild).not.toHaveStyleRule('width', '100%')
 
-    const svgNode = tree.children[0]
+    const svgNode = container.firstChild?.firstChild
 
     expect(svgNode).toHaveStyleRule('width', '100%')
     expect(svgNode).not.toHaveStyleRule('color', 'red')
   })
 
   test('supports asymmetric matchers', () => {
-    const tree = renderer
-      .create(
-        <div css={divStyle}>
-          <svg css={svgStyle} />
-        </div>
-      )
-      .toJSON()
+    const { container } = render(
+      <div css={divStyle}>
+        <svg css={svgStyle} />
+      </div>
+    )
 
-    expect(tree).toHaveStyleRule('color', expect.anything())
-    expect(tree).not.toHaveStyleRule('padding', expect.anything())
+    expect(container.firstChild).toHaveStyleRule('color', expect.anything())
+    expect(container.firstChild).not.toHaveStyleRule(
+      'padding',
+      expect.anything()
+    )
 
-    const svgNode = tree.children[0]
+    const svgNode = container.firstChild?.firstChild
 
     expect(svgNode).toHaveStyleRule('width', expect.stringMatching(/.*%$/))
   })
 
   test('fails if no styles are found', () => {
-    const tree = renderer.create(<div />).toJSON()
-    const result = toHaveStyleRule(tree, 'color', 'red')
+    const { container } = render(<div />)
+    const result = toHaveStyleRule(container.firstChild, 'color', 'red')
     expect(result.pass).toBe(false)
     expect(result.message()).toBe('Property not found: color')
   })
 
   test('supports regex values', () => {
-    const tree = renderer.create(<div css={divStyle} />).toJSON()
-    expect(tree).toHaveStyleRule('color', /red/)
+    const { container } = render(<div css={divStyle} />)
+    expect(container.firstChild).toHaveStyleRule('color', /red/)
   })
 
-  it.skip('returns a message explaining the failure', () => {
-    const tree = renderer.create(<div css={divStyle} />).toJSON()
+  it('returns a message explaining the failure', () => {
+    const { container } = render(<div css={divStyle} />)
 
-    // When expect(tree).toHaveStyleRule('color', 'blue') fails
-    const resultFail = toHaveStyleRule(tree, 'color', 'blue')
-    expect(resultFail.message()).toMatchSnapshot()
+    // When expect(container.firstChild).toHaveStyleRule('color', 'blue') fails
+    const resultFail = toHaveStyleRule(container.firstChild, 'color', 'blue')
+    expect(stripAnsi(resultFail.message())).toMatchSnapshot()
 
-    // When expect(tree).not.toHaveStyleRule('color', 'red')
-    const resultPass = toHaveStyleRule(tree, 'color', 'red')
-    expect(resultPass.message()).toMatchSnapshot()
+    // When expect(container.firstChild).not.toHaveStyleRule('color', 'red')
+    const resultPass = toHaveStyleRule(container.firstChild, 'color', 'red')
+    expect(stripAnsi(resultPass.message())).toMatchSnapshot()
   })
 
   test('matches styles on the focus, hover targets', () => {
@@ -90,17 +90,19 @@ describe('toHaveStyleRule', () => {
         color: black;
       }
     `
-    const tree = renderer
-      .create(
-        <div css={localDivStyle}>
-          <svg css={svgStyle} />
-        </div>
-      )
-      .toJSON()
+    const { container } = render(
+      <div css={localDivStyle}>
+        <svg css={svgStyle} />
+      </div>
+    )
 
-    expect(tree).toHaveStyleRule('color', 'yellow', { target: ':hover' })
-    expect(tree).toHaveStyleRule('color', 'black', { target: ':focus' })
-    expect(tree).toHaveStyleRule('color', 'white')
+    expect(container.firstChild).toHaveStyleRule('color', 'yellow', {
+      target: ':hover'
+    })
+    expect(container.firstChild).toHaveStyleRule('color', 'black', {
+      target: ':focus'
+    })
+    expect(container.firstChild).toHaveStyleRule('color', 'white')
   })
 
   test('matches styles on the nested component or html element', () => {
@@ -118,19 +120,21 @@ describe('toHaveStyleRule', () => {
       }
     `
 
-    const tree = renderer
-      .create(
-        <Div>
-          <Svg />
-          <span>Test</span>
-        </Div>
-      )
-      .toJSON()
+    const { container } = render(
+      <Div>
+        <Svg />
+        <span>Test</span>
+      </Div>
+    )
 
-    expect(tree).toHaveStyleRule('color', 'yellow', { target: 'span' })
-    expect(tree).toHaveStyleRule('color', 'red')
+    expect(container.firstChild).toHaveStyleRule('color', 'yellow', {
+      target: 'span'
+    })
+    expect(container.firstChild).toHaveStyleRule('color', 'red')
 
-    expect(tree).toHaveStyleRule('fill', 'green', { target: `${Svg}` })
+    expect(container.firstChild).toHaveStyleRule('fill', 'green', {
+      target: `${Svg}`
+    })
   })
 
   test('matches target styles by regex', () => {
@@ -142,30 +146,28 @@ describe('toHaveStyleRule', () => {
         color: black;
       }
     `
-    const tree = renderer
-      .create(
-        <div css={localDivStyle}>
-          <svg css={svgStyle} />
-        </div>
-      )
-      .toJSON()
+    const { container } = render(
+      <div css={localDivStyle}>
+        <svg css={svgStyle} />
+      </div>
+    )
 
-    expect(tree).toHaveStyleRule('color', 'yellow', { target: /a$/ })
+    expect(container.firstChild).toHaveStyleRule('color', 'yellow', {
+      target: /a$/
+    })
   })
 
   test('matches proper style for css', () => {
-    const tree = renderer
-      .create(
-        <div
-          css={css`
-            color: green;
-            color: hotpink;
-          `}
-        />
-      )
-      .toJSON()
-    expect(tree).not.toHaveStyleRule('color', 'green')
-    expect(tree).toHaveStyleRule('color', 'hotpink')
+    const { container } = render(
+      <div
+        css={css`
+          color: green;
+          color: hotpink;
+        `}
+      />
+    )
+    expect(container.firstChild).not.toHaveStyleRule('color', 'green')
+    expect(container.firstChild).toHaveStyleRule('color', 'hotpink')
   })
 
   test('matches style of the media', () => {
@@ -188,25 +190,23 @@ describe('toHaveStyleRule', () => {
       }
     `
 
-    const tree = renderer
-      .create(
-        <Div>
-          <Svg />
-        </Div>
-      )
-      .toJSON()
+    const { container } = render(
+      <Div>
+        <Svg />
+      </Div>
+    )
 
-    expect(tree).toHaveStyleRule('font-size', '30px')
-    expect(tree).toHaveStyleRule('font-size', '50px', {
+    expect(container.firstChild).toHaveStyleRule('font-size', '30px')
+    expect(container.firstChild).toHaveStyleRule('font-size', '50px', {
       media: '(min-width: 420px)'
     })
-    expect(tree).toHaveStyleRule('font-size', '70px', {
+    expect(container.firstChild).toHaveStyleRule('font-size', '70px', {
       media: '(min-width: 920px) and (max-width: 1200px)'
     })
-    expect(tree).toHaveStyleRule('font-size', '80px', {
+    expect(container.firstChild).toHaveStyleRule('font-size', '80px', {
       media: 'screen and (max-width: 1200px)'
     })
-    expect(tree).toHaveStyleRule('font-size', '90px', {
+    expect(container.firstChild).toHaveStyleRule('font-size', '90px', {
       media: 'not all and (monochrome)'
     })
   })
@@ -221,22 +221,20 @@ describe('toHaveStyleRule', () => {
         }
       }
     `
-    const tree = renderer
-      .create(
-        <div css={localDivStyle}>
-          <span>Test</span>
-        </div>
-      )
-      .toJSON()
+    const { container } = render(
+      <div css={localDivStyle}>
+        <span>Test</span>
+      </div>
+    )
 
-    expect(tree).toHaveStyleRule('color', 'yellow', {
+    expect(container.firstChild).toHaveStyleRule('color', 'yellow', {
       target: ':hover',
       media: '(min-width: 420px)'
     })
-    expect(tree).toHaveStyleRule('color', 'green', {
+    expect(container.firstChild).toHaveStyleRule('color', 'green', {
       media: '(min-width: 420px)'
     })
-    expect(tree).toHaveStyleRule('color', 'white')
+    expect(container.firstChild).toHaveStyleRule('color', 'white')
   })
 
   test('fails if option media invalid', () => {
@@ -247,9 +245,9 @@ describe('toHaveStyleRule', () => {
       }
     `
 
-    const tree = renderer.create(<Div />).toJSON()
+    const { container } = render(<Div />)
 
-    const result = toHaveStyleRule(tree, 'font-size', '50px', {
+    const result = toHaveStyleRule(container.firstChild, 'font-size', '50px', {
       media: '(min-width-'
     })
     expect(result.pass).toBe(false)
@@ -266,15 +264,13 @@ describe('toHaveStyleRule', () => {
         color: hotpink;
       }
     `
-    const tree = renderer
-      .create(
-        <Foo>
-          <Bar />
-        </Foo>
-      )
-      .toJSON()
+    const { container } = render(
+      <Foo>
+        <Bar />
+      </Foo>
+    )
 
-    expect(tree.children[0]).toHaveStyleRule('color', 'hotpink')
+    expect(container.firstChild?.firstChild).toHaveStyleRule('color', 'hotpink')
   })
 
   test('takes specificity into account when matching styles (basic)', () => {
@@ -290,30 +286,30 @@ describe('toHaveStyleRule', () => {
       }
     `
 
-    const tree = renderer
-      .create(
-        <Foo>
-          <Bar />
-        </Foo>
-      )
-      .toJSON()
+    const { container } = render(
+      <Foo>
+        <Bar />
+      </Foo>
+    )
 
-    expect(tree.children[0]).toHaveStyleRule('color', 'hotpink')
+    expect(container.firstChild.firstChild).toHaveStyleRule('color', 'hotpink')
   })
 
-  test('should throw a friendly error when it receives an array', () => {
-    const tree = renderer
-      .create(
-        <>
-          <div
-            css={css`
-              color: hotpink;
-            `}
-          />
-          {'Some text'}
-        </>
+  test('should throw a friendly error when it receives an array', async () => {
+    const tree = (
+      await act(() =>
+        testRenderer.create(
+          <>
+            <div
+              css={css`
+                color: hotpink;
+              `}
+            />
+            {'Some text'}
+          </>
+        )
       )
-      .toJSON()
+    ).toJSON()
 
     expect(() =>
       expect(tree).toHaveStyleRule('color', 'hotpink')
diff --git a/packages/jest/test/printer.test.js b/packages/jest/test/printer.test.js
index 2c22b2c186..31161eda09 100644
--- a/packages/jest/test/printer.test.js
+++ b/packages/jest/test/printer.test.js
@@ -1,12 +1,13 @@
-import React from 'react'
+/** @jsx jsx */
 import 'test-utils/setup-env'
-import renderer from 'react-test-renderer'
+import React from 'react'
+import { act } from 'react'
 import prettyFormat from 'pretty-format'
-/** @jsx jsx */
 import { css, jsx, CacheProvider } from '@emotion/react'
 import createCache from '@emotion/cache'
 import { createSerializer } from '@emotion/jest'
 import { render } from '@testing-library/react'
+import testRenderer from 'react-test-renderer'
 import { ignoreConsoleErrors } from 'test-utils'
 
 let emotionPlugin = createSerializer()
@@ -22,14 +23,16 @@ describe('jest-emotion with dom elements', () => {
     width: 100%;
   `
 
-  test('replaces class names and inserts styles into React test component snapshots', () => {
-    const tree = renderer
-      .create(
-        <div css={divStyle}>
-          <svg css={svgStyle} />
-        </div>
+  test('replaces class names and inserts styles into React test component snapshots', async () => {
+    const tree = (
+      await act(() =>
+        testRenderer.create(
+          <div css={divStyle}>
+            <svg css={svgStyle} />
+          </div>
+        )
       )
-      .toJSON()
+    ).toJSON()
 
     const output = prettyFormat(tree, {
       plugins: [emotionPlugin, ReactElement, ReactTestComponent, DOMElement]
@@ -38,7 +41,7 @@ describe('jest-emotion with dom elements', () => {
     expect(output).toMatchSnapshot()
   })
 
-  test.skip('replaces class names and inserts styles into DOM element snapshots', () => {
+  test('replaces class names and inserts styles into DOM element snapshots', () => {
     const divRef = React.createRef()
     render(
       <div css={divStyle} ref={divRef}>
@@ -65,23 +68,23 @@ describe('jest-emotion with DOM elements disabled', () => {
     width: 100%;
   `
 
-  test('replaces class names and inserts styles into React test component snapshots', () => {
-    const tree = renderer
-      .create(
+  test('replaces class names and inserts styles into React test component snapshots', async () => {
+    const tree = await act(() =>
+      testRenderer.create(
         <div css={divStyle}>
           <svg css={svgStyle} />
         </div>
       )
-      .toJSON()
+    )
 
-    const output = prettyFormat(tree, {
+    const output = prettyFormat(tree.toJSON(), {
       plugins: [emotionPlugin, ReactElement, ReactTestComponent, DOMElement]
     })
 
     expect(output).toMatchSnapshot()
   })
 
-  test.skip('does not replace class names or insert styles into DOM element snapshots', () => {
+  test('does not replace class names or insert styles into DOM element snapshots', async () => {
     const divRef = React.createRef()
     render(
       <div css={divStyle} ref={divRef}>
@@ -97,7 +100,7 @@ describe('jest-emotion with DOM elements disabled', () => {
   })
 })
 
-test.skip('allows to opt-out from styles printing', () => {
+test('allows to opt-out from styles printing', () => {
   const emotionPlugin = createSerializer({ includeStyles: false })
 
   const divStyle = css`
@@ -123,18 +126,16 @@ test.skip('allows to opt-out from styles printing', () => {
 })
 
 test('does not replace class names that are not from emotion', () => {
-  let tree = renderer
-    .create(
-      <div
-        className="net-42 net"
-        css={css`
-          color: darkorchid;
-        `}
-      />
-    )
-    .toJSON()
+  let { container } = render(
+    <div
+      className="net-42 net"
+      css={css`
+        color: darkorchid;
+      `}
+    />
+  )
 
-  const output = prettyFormat(tree, {
+  const output = prettyFormat(container.firstChild, {
     plugins: [emotionPlugin, ReactElement, ReactTestComponent, DOMElement]
   })
 
@@ -150,8 +151,10 @@ describe('jest-emotion with nested selectors', () => {
     }
   `
 
-  test('replaces class names and inserts styles into React test component snapshots', () => {
-    const tree = renderer.create(<div css={divStyle} />).toJSON()
+  test('replaces class names and inserts styles into React test component snapshots', async () => {
+    const tree = (
+      await act(() => testRenderer.create(<div css={divStyle} />))
+    ).toJSON()
 
     const output = prettyFormat(tree, {
       plugins: [emotionPlugin, ReactElement, ReactTestComponent, DOMElement]
@@ -167,6 +170,26 @@ header .emotion-0 {
 
 <div
   className="emotion-0"
+/>`)
+  })
+
+  test('replaces class names and inserts styles into DOM element snapshots', () => {
+    const { container } = render(<div css={divStyle} />)
+
+    const output = prettyFormat(container.firstChild, {
+      plugins: [emotionPlugin, ReactElement, ReactTestComponent, DOMElement]
+    })
+
+    expect(output).toBe(`.emotion-0 {
+  color: blue;
+}
+
+header .emotion-0 {
+  color: red;
+}
+
+<div
+  class="emotion-0"
 />`)
   })
 })
@@ -176,20 +199,18 @@ test('prints speedy styles', () => {
     key: 'speedy-key',
     speedy: true
   })
-  const tree = renderer
-    .create(
-      <CacheProvider value={speedyCache}>
-        <div
-          css={css`
-            color: hotpink;
-          `}
-        />
-      </CacheProvider>
-    )
-    .toJSON()
+  const { container } = render(
+    <CacheProvider value={speedyCache}>
+      <div
+        css={css`
+          color: hotpink;
+        `}
+      />
+    </CacheProvider>
+  )
 
   expect(
-    prettyFormat(tree, {
+    prettyFormat(container.firstChild, {
       plugins: [emotionPlugin, ReactElement, ReactTestComponent, DOMElement]
     })
   ).toMatchSnapshot()
diff --git a/packages/jest/test/prod.test.js b/packages/jest/test/prod.test.js
index 0e691ec7a0..69b0b3b7a6 100644
--- a/packages/jest/test/prod.test.js
+++ b/packages/jest/test/prod.test.js
@@ -1,6 +1,6 @@
-import 'test-utils/setup-env'
-import renderer from 'react-test-renderer'
 /** @jsx jsx */
+import 'test-utils/setup-env'
+import { render } from '@testing-library/react'
 import * as React from 'react'
 import { css, jsx } from '@emotion/react'
 import { matchers } from '@emotion/jest'
@@ -9,15 +9,13 @@ expect.extend(matchers)
 
 gate({ development: false }, ({ test }) => {
   test('it prints fallback values', () => {
-    const tree = renderer
-      .create(
-        <div css={[{ backgroundColor: '#000' }, { backgroundColor: '#fff' }]}>
-          <span css={{ color: 'hotpink' }}>{'emotion'}</span>
-        </div>
-      )
-      .toJSON()
+    const { container } = render(
+      <div css={[{ backgroundColor: '#000' }, { backgroundColor: '#fff' }]}>
+        <span css={{ color: 'hotpink' }}>{'emotion'}</span>
+      </div>
+    )
 
-    expect(tree).toMatchInlineSnapshot(`
+    expect(container.firstChild).toMatchInlineSnapshot(`
 .emotion-0 {
   background-color: #000;
   background-color: #fff;
@@ -28,10 +26,10 @@ gate({ development: false }, ({ test }) => {
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 >
   <span
-    className="emotion-1"
+    class="emotion-1"
   >
     emotion
   </span>
@@ -40,15 +38,13 @@ gate({ development: false }, ({ test }) => {
   })
 
   test('it prints invalid declarations', () => {
-    const tree = renderer
-      .create(
-        <div css={{ bazinga: 'joke' }}>
-          <span css={{ color: 'hotpink' }}>{'emotion'}</span>
-        </div>
-      )
-      .toJSON()
+    const { container } = render(
+      <div css={{ bazinga: 'joke' }}>
+        <span css={{ color: 'hotpink' }}>{'emotion'}</span>
+      </div>
+    )
 
-    expect(tree).toMatchInlineSnapshot(`
+    expect(container.firstChild).toMatchInlineSnapshot(`
 .emotion-0 {
   bazinga: joke;
 }
@@ -58,10 +54,10 @@ gate({ development: false }, ({ test }) => {
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 >
   <span
-    className="emotion-1"
+    class="emotion-1"
   >
     emotion
   </span>
diff --git a/packages/jest/types/index.d.ts b/packages/jest/types/index.d.ts
index 758379af72..86b71005ea 100644
--- a/packages/jest/types/index.d.ts
+++ b/packages/jest/types/index.d.ts
@@ -1,5 +1,5 @@
 // Definitions by: Junyoung Clare Jang <https://github.com/Ailrun>
-// TypeScript Version: 4.3
+// TypeScript Version: 5.0
 
 /// <reference types="jest" />
 
diff --git a/packages/native/package.json b/packages/native/package.json
index 3021231b82..d87fdb2fec 100644
--- a/packages/native/package.json
+++ b/packages/native/package.json
@@ -36,7 +36,7 @@
   "devDependencies": {
     "@definitelytyped/dtslint": "0.0.112",
     "@types/react-native": "^0.63.2",
-    "react": "16.14.0",
+    "react": "19.0.0",
     "react-native": "^0.63.2",
     "typescript": "^5.4.5"
   },
diff --git a/packages/native/test/native-styled.test.js b/packages/native/test/native-styled.test.js
index b5538963dd..4538a3b038 100644
--- a/packages/native/test/native-styled.test.js
+++ b/packages/native/test/native-styled.test.js
@@ -1,5 +1,6 @@
-import * as React from 'react'
-import renderer from 'react-test-renderer'
+import React from 'react'
+import { act } from 'react'
+import testRenderer from 'react-test-renderer'
 import { ThemeProvider } from '@emotion/react'
 import styled, { css } from '@emotion/native'
 import reactNative from 'react-native'
@@ -21,79 +22,93 @@ describe('Emotion native styled', () => {
     expect(() => styled.TEXT({})).toThrow()
   })
 
-  test('should render the primitive when styles applied using object style notation', () => {
+  test('should render the primitive when styles applied using object style notation', async () => {
     const Text = styled.Text`
       color: red;
       font-size: 20px;
       background-color: ${props => props.back};
     `
-    const tree = renderer
-      .create(
-        <Text style={{ fontSize: 40 }} back="red">
-          Emotion Primitives
-        </Text>
+    const tree = (
+      await act(() =>
+        testRenderer.create(
+          <Text style={{ fontSize: 40 }} back="red">
+            Emotion Primitives
+          </Text>
+        )
       )
-      .toJSON()
+    ).toJSON()
     expect(tree).toMatchSnapshot()
   })
 
-  test('should work with theming from @emotion/react', () => {
+  test('should work with theming from @emotion/react', async () => {
     const Text = styled.Text`
       color: ${props => props.theme.backgroundColor};
     `
 
-    const tree = renderer
-      .create(
-        <ThemeProvider theme={theme}>
-          <Text>Hello World</Text>
-        </ThemeProvider>
+    const tree = (
+      await act(() =>
+        testRenderer.create(
+          <ThemeProvider theme={theme}>
+            <Text>Hello World</Text>
+          </ThemeProvider>
+        )
       )
-      .toJSON()
+    ).toJSON()
 
     expect(tree).toMatchSnapshot()
   })
 
-  test('should render the primitive on changing the props', () => {
+  test('should render the primitive on changing the props', async () => {
     const Text = styled.Text({ padding: '20px' }, props => ({
       color: props.decor
     }))
-    const tree = renderer
-      .create(<Text decor="hotpink">Emotion Primitives</Text>)
-      .toJSON()
+    const tree = (
+      await act(() =>
+        testRenderer.create(<Text decor="hotpink">Emotion Primitives</Text>)
+      )
+    ).toJSON()
     expect(tree).toMatchSnapshot()
   })
 
-  test('should render primitive with style prop', () => {
+  test('should render primitive with style prop', async () => {
     const Title = styled.Text`
       color: hotpink;
     `
-    const tree = renderer
-      .create(<Title style={{ padding: 10 }}>Emotion primitives</Title>)
-      .toJSON()
+    const tree = (
+      await act(() =>
+        testRenderer.create(
+          <Title style={{ padding: 10 }}>Emotion primitives</Title>
+        )
+      )
+    ).toJSON()
     expect(tree).toMatchSnapshot()
   })
 
-  test('should work with StyleSheet.create API', () => {
+  test('should work with StyleSheet.create API', async () => {
     const styles = StyleSheet.create({ foo: { color: 'red' } })
     const Text = styled.Text`
       font-size: 10px;
     `
-    const tree = renderer
-      .create(<Text style={styles.foo}>Emotion primitives</Text>)
-      .toJSON()
+    const tree = (
+      await act(() =>
+        testRenderer.create(<Text style={styles.foo}>Emotion primitives</Text>)
+      )
+    ).toJSON()
     expect(tree).toMatchSnapshot()
   })
 
-  test('primitive should work with `withComponent`', () => {
+  test('primitive should work with `withComponent`', async () => {
     const Text = styled.Text`
       color: ${props => props.decor};
     `
     const Name = Text.withComponent(reactNative.Text)
-    const tree = renderer.create(<Name decor="hotpink">Mike</Name>).toJSON()
+    const tree = (
+      await act(() => testRenderer.create(<Name decor="hotpink">Mike</Name>))
+    ).toJSON()
     expect(tree).toMatchSnapshot()
   })
 
-  test('should style any other component', () => {
+  test('should style any other component', async () => {
     const Text = styled.Text`
       color: hotpink;
     `
@@ -102,55 +117,63 @@ describe('Emotion native styled', () => {
       font-size: 20px;
       font-style: ${props => props.sty};
     `
-    const tree = renderer.create(<StyledTitle sty="italic" />).toJSON()
+    const tree = (
+      await act(() => testRenderer.create(<StyledTitle sty="italic" />))
+    ).toJSON()
     expect(tree).toMatchSnapshot()
   })
 
-  test('should pass props in withComponent', () => {
+  test('should pass props in withComponent', async () => {
     const ViewOne = styled.View`
       background-color: ${props => props.color};
     `
-    const treeOne = renderer.create(<ViewOne color="green" />)
+    const treeOne = await act(() =>
+      testRenderer.create(<ViewOne color="green" />)
+    )
     const ViewTwo = ViewOne.withComponent(reactNative.Text)
-    const treeTwo = renderer.create(<ViewTwo color="hotpink" />)
+    const treeTwo = await act(() =>
+      testRenderer.create(<ViewTwo color="hotpink" />)
+    )
 
     expect(treeOne).toMatchSnapshot()
     expect(treeTwo).toMatchSnapshot()
   })
 
-  test('should render <Image />', () => {
+  test('should render <Image />', async () => {
     const Image = styled.Image`
       border-radius: 2px;
     `
-    const tree = renderer
-      .create(
-        <Image
-          source={{
-            uri: 'https://camo.githubusercontent.com/209bdea972b9b6ef90220c59ecbe66d35ffefa8a/68747470733a2f2f63646e2e7261776769742e636f6d2f746b6834342f656d6f74696f6e2f6d61737465722f656d6f74696f6e2e706e67',
-            height: 150,
-            width: 150
-          }}
-        />
+    const tree = (
+      await act(() =>
+        testRenderer.create(
+          <Image
+            source={{
+              uri: 'https://camo.githubusercontent.com/209bdea972b9b6ef90220c59ecbe66d35ffefa8a/68747470733a2f2f63646e2e7261776769742e636f6d2f746b6834342f656d6f74696f6e2f6d61737465722f656d6f74696f6e2e706e67',
+              height: 150,
+              width: 150
+            }}
+          />
+        )
       )
-      .toJSON()
+    ).toJSON()
 
     expect(tree).toMatchSnapshot()
   })
 
-  test('Log error message if units are not specified when using shorthand properties', () => {
+  test('Log error message if units are not specified when using shorthand properties', async () => {
     const Text = styled.Text`
       margin: 20px;
       padding: 20;
     `
 
-    renderer.create(<Text>Hello World</Text>)
+    await act(() => testRenderer.create(<Text>Hello World</Text>))
 
     expect(console.error).toBeCalledWith(
       "'padding' shorthand property requires units for example - padding: 20px or padding: 10px 20px 40px 50px"
     )
   })
 
-  test('should render styles correctly from all nested style factories', () => {
+  test('should render styles correctly from all nested style factories', async () => {
     const bgColor = color => css`
       background-color: ${color};
     `
@@ -160,9 +183,11 @@ describe('Emotion native styled', () => {
       ${({ backgroundColor }) => bgColor(backgroundColor)};
     `
 
-    const tree = renderer
-      .create(<Text backgroundColor="blue">Hello World</Text>)
-      .toJSON()
+    const tree = (
+      await act(() =>
+        testRenderer.create(<Text backgroundColor="blue">Hello World</Text>)
+      )
+    ).toJSON()
 
     expect(tree).toMatchSnapshot()
   })
diff --git a/packages/native/types/base.d.ts b/packages/native/types/base.d.ts
index a14f22bada..b0b8df9c66 100644
--- a/packages/native/types/base.d.ts
+++ b/packages/native/types/base.d.ts
@@ -1,5 +1,5 @@
 // Definitions by: Pat Sissons <https://github.com/patsissons>
-// TypeScript Version: 3.4
+// TypeScript Version: 5.0
 
 import { Theme } from '@emotion/react'
 import * as RN from 'react-native'
diff --git a/packages/native/types/index.d.ts b/packages/native/types/index.d.ts
index e7c6036366..49f86bc73b 100644
--- a/packages/native/types/index.d.ts
+++ b/packages/native/types/index.d.ts
@@ -1,5 +1,5 @@
 // Definitions by: Pat Sissons <https://github.com/patsissons>
-// TypeScript Version: 4.1
+// TypeScript Version: 5.0
 
 import * as RN from 'react-native'
 import { Theme } from '@emotion/react'
diff --git a/packages/primitives-core/package.json b/packages/primitives-core/package.json
index 4e4b84408a..4581535aee 100644
--- a/packages/primitives-core/package.json
+++ b/packages/primitives-core/package.json
@@ -15,12 +15,12 @@
   },
   "peerDependencies": {
     "@emotion/react": "^11.0.0-rc.0",
-    "react": ">=16.8.0"
+    "react": "^19.0.0"
   },
   "devDependencies": {
     "@emotion/react": "11.14.0",
     "@types/css-to-react-native": "^3.0.0",
-    "react": "16.14.0"
+    "react": "19.0.0"
   },
   "homepage": "https://emotion.sh",
   "repository": "https://github.com/emotion-js/emotion/tree/main/packages/primitives-core",
diff --git a/packages/primitives/package.json b/packages/primitives/package.json
index 0126f1f8e1..1015117cc3 100644
--- a/packages/primitives/package.json
+++ b/packages/primitives/package.json
@@ -14,11 +14,11 @@
     "@emotion/primitives-core": "^11.13.0"
   },
   "peerDependencies": {
-    "react": ">=16.8.0",
+    "react": "^19.0.0",
     "react-primitives": "^0.8.1"
   },
   "devDependencies": {
-    "react": "16.14.0",
+    "react": "19.0.0",
     "react-primitives": "^0.8.1"
   },
   "homepage": "https://emotion.sh",
diff --git a/packages/primitives/test/__snapshots__/emotion-primitives.test.js.snap b/packages/primitives/test/__snapshots__/emotion-primitives.test.js.snap
index 6cf28bd136..9ae2a0559f 100644
--- a/packages/primitives/test/__snapshots__/emotion-primitives.test.js.snap
+++ b/packages/primitives/test/__snapshots__/emotion-primitives.test.js.snap
@@ -2,7 +2,7 @@
 
 exports[`Emotion primitives custom shouldForwardProp works 1`] = `
 <div
-  className="css-text-901oao r-color-185hjl9"
+  class="css-text-901oao r-color-185hjl9"
   dir="auto"
 >
   Emotion
@@ -11,7 +11,7 @@ exports[`Emotion primitives custom shouldForwardProp works 1`] = `
 
 exports[`Emotion primitives primitive should work with \`withComponent\` 1`] = `
 <div
-  className="css-text-901oao r-color-185hjl9"
+  class="css-text-901oao r-color-185hjl9"
   dir="auto"
 >
   Mike
@@ -20,56 +20,40 @@ exports[`Emotion primitives primitive should work with \`withComponent\` 1`] = `
 
 exports[`Emotion primitives should pass props in withComponent 1`] = `
 <div
-  className="css-view-1dbjc4n r-backgroundColor-1542mo4"
+  class="css-view-1dbjc4n r-backgroundColor-1542mo4"
 />
 `;
 
 exports[`Emotion primitives should pass props in withComponent 2`] = `
 <div
-  className="css-text-901oao r-backgroundColor-173gl9r"
+  class="css-text-901oao r-backgroundColor-173gl9r"
   dir="auto"
 />
 `;
 
 exports[`Emotion primitives should render <Image /> 1`] = `
 <div
-  className="css-view-1dbjc4n r-flexBasis-1mlwlqe r-overflow-1udh08x r-zIndex-417010"
-  style={
-    {
-      "borderBottomColor": "rgba(255,105,180,1.00)",
-      "borderBottomStyle": "solid",
-      "borderBottomWidth": "2px",
-      "borderLeftColor": "rgba(255,105,180,1.00)",
-      "borderLeftStyle": "solid",
-      "borderLeftWidth": "2px",
-      "borderRightColor": "rgba(255,105,180,1.00)",
-      "borderRightStyle": "solid",
-      "borderRightWidth": "2px",
-      "borderTopColor": "rgba(255,105,180,1.00)",
-      "borderTopStyle": "solid",
-      "borderTopWidth": "2px",
-    }
-  }
+  class="css-view-1dbjc4n r-flexBasis-1mlwlqe r-overflow-1udh08x r-zIndex-417010"
+  style="border-top-color: rgba(255,105,180,1.00); border-right-color: rgba(255,105,180,1.00); border-bottom-color: rgba(255,105,180,1.00); border-left-color: rgba(255,105,180,1.00); border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-width: 2px; border-right-width: 2px; border-bottom-width: 2px; border-left-width: 2px; height: 150px; width: 150px;"
 >
   <div
-    className="css-view-1dbjc4n r-backgroundColor-1niwhzg r-backgroundPosition-vvn4in r-backgroundRepeat-u6sd8q r-backgroundSize-4gszlv r-bottom-1p0dtai r-height-1pi2tsx r-left-1d2f490 r-position-u8s1d r-right-zchlnj r-top-ipm5af r-width-13qz1uu r-zIndex-1wyyakw"
-    suppressHydrationWarning={true}
+    class="css-view-1dbjc4n r-backgroundColor-1niwhzg r-backgroundPosition-vvn4in r-backgroundRepeat-u6sd8q r-backgroundSize-4gszlv r-bottom-1p0dtai r-height-1pi2tsx r-left-1d2f490 r-position-u8s1d r-right-zchlnj r-top-ipm5af r-width-13qz1uu r-zIndex-1wyyakw"
+    style="background-image: url(https://camo.githubusercontent.com/209bdea972b9b6ef90220c59ecbe66d35ffefa8a/68747470733a2f2f63646e2e7261776769742e636f6d2f746b6834342f656d6f74696f6e2f6d61737465722f656d6f74696f6e2e706e67);"
+  />
+  <img
+    alt=""
+    class="css-accessibilityImage-9pa8cd"
+    draggable="false"
+    src="https://camo.githubusercontent.com/209bdea972b9b6ef90220c59ecbe66d35ffefa8a/68747470733a2f2f63646e2e7261776769742e636f6d2f746b6834342f656d6f74696f6e2f6d61737465722f656d6f74696f6e2e706e67"
   />
 </div>
 `;
 
 exports[`Emotion primitives should render primitive with style prop 1`] = `
 <div
-  className="css-text-901oao r-color-185hjl9"
+  class="css-text-901oao r-color-185hjl9"
   dir="auto"
-  style={
-    {
-      "paddingBottom": "10px",
-      "paddingLeft": "10px",
-      "paddingRight": "10px",
-      "paddingTop": "10px",
-    }
-  }
+  style="padding: 10px 10px 10px 10px;"
 >
   Emotion primitives
 </div>
@@ -77,7 +61,7 @@ exports[`Emotion primitives should render primitive with style prop 1`] = `
 
 exports[`Emotion primitives should render the primitive on changing the props 1`] = `
 <div
-  className="css-text-901oao r-color-185hjl9 r-paddingBottom-k8qxaj r-paddingLeft-b5h31w r-paddingRight-1ah4tor r-paddingTop-1knelpx"
+  class="css-text-901oao r-color-185hjl9 r-paddingBottom-k8qxaj r-paddingLeft-b5h31w r-paddingRight-1ah4tor r-paddingTop-1knelpx"
   dir="auto"
 >
   Emotion Primitives
@@ -86,13 +70,9 @@ exports[`Emotion primitives should render the primitive on changing the props 1`
 
 exports[`Emotion primitives should render the primitive when styles applied using object style notation 1`] = `
 <div
-  className="css-text-901oao r-backgroundColor-1g6456j r-color-howw7u"
+  class="css-text-901oao r-backgroundColor-1g6456j r-color-howw7u"
   dir="auto"
-  style={
-    {
-      "fontSize": "40px",
-    }
-  }
+  style="font-size: 40px;"
 >
   Emotion Primitives
 </div>
@@ -100,7 +80,7 @@ exports[`Emotion primitives should render the primitive when styles applied usin
 
 exports[`Emotion primitives should style any other component 1`] = `
 <div
-  className="css-text-901oao r-color-185hjl9"
+  class="css-text-901oao r-color-185hjl9"
   dir="auto"
 >
   Hello World
@@ -121,7 +101,7 @@ exports[`Emotion primitives should unmount with theming 1`] = `
 
 exports[`Emotion primitives should work with StyleSheet.create API 1`] = `
 <div
-  className="css-text-901oao r-color-howw7u r-fontSize-10x49cs"
+  class="css-text-901oao r-color-howw7u r-fontSize-10x49cs"
   dir="auto"
 >
   Emotion Primitives
@@ -130,7 +110,7 @@ exports[`Emotion primitives should work with StyleSheet.create API 1`] = `
 
 exports[`Emotion primitives should work with theming from @emotion/react 1`] = `
 <div
-  className="css-text-901oao r-color-1hxtt4r"
+  class="css-text-901oao r-color-1hxtt4r"
   dir="auto"
 >
   Hello World
diff --git a/packages/primitives/test/emotion-primitives.test.js b/packages/primitives/test/emotion-primitives.test.js
index 17993dd812..d8415faf9a 100644
--- a/packages/primitives/test/emotion-primitives.test.js
+++ b/packages/primitives/test/emotion-primitives.test.js
@@ -1,5 +1,4 @@
 import * as React from 'react'
-import renderer from 'react-test-renderer'
 import { Text, StyleSheet } from 'react-primitives'
 import { ThemeProvider } from '@emotion/react'
 import { render } from '@testing-library/react'
@@ -25,14 +24,13 @@ describe('Emotion primitives', () => {
       font-size: 20px;
       background-color: ${props => props.back};
     `
-    const tree = renderer
-      .create(
-        <Text style={{ fontSize: 40 }} back="red">
-          Emotion Primitives
-        </Text>
-      )
-      .toJSON()
-    expect(tree).toMatchSnapshot()
+    const { container } = render(
+      <Text style={{ fontSize: 40 }} back="red">
+        Emotion Primitives
+      </Text>
+    )
+
+    expect(container.firstChild).toMatchSnapshot()
   })
 
   test('should work with theming from @emotion/react', () => {
@@ -40,15 +38,13 @@ describe('Emotion primitives', () => {
       color: ${props => props.theme.backgroundColor};
     `
 
-    const tree = renderer
-      .create(
-        <ThemeProvider theme={theme}>
-          <Text>Hello World</Text>
-        </ThemeProvider>
-      )
-      .toJSON()
+    const { container } = render(
+      <ThemeProvider theme={theme}>
+        <Text>Hello World</Text>
+      </ThemeProvider>
+    )
 
-    expect(tree).toMatchSnapshot()
+    expect(container.firstChild).toMatchSnapshot()
   })
 
   test('should unmount with theming', () => {
@@ -72,20 +68,22 @@ describe('Emotion primitives', () => {
     const Text = styled.Text({ padding: '20px' }, props => ({
       color: props.decor
     }))
-    const tree = renderer
-      .create(<Text decor="hotpink">Emotion Primitives</Text>)
-      .toJSON()
-    expect(tree).toMatchSnapshot()
+    const { container } = render(
+      <Text decor="hotpink">Emotion Primitives</Text>
+    )
+
+    expect(container.firstChild).toMatchSnapshot()
   })
 
   test('should render primitive with style prop', () => {
     const Title = styled.Text`
       color: hotpink;
     `
-    const tree = renderer
-      .create(<Title style={{ padding: 10 }}>Emotion primitives</Title>)
-      .toJSON()
-    expect(tree).toMatchSnapshot()
+    const { container } = render(
+      <Title style={{ padding: 10 }}>Emotion primitives</Title>
+    )
+
+    expect(container.firstChild).toMatchSnapshot()
   })
 
   test('should work with StyleSheet.create API', () => {
@@ -94,10 +92,11 @@ describe('Emotion primitives', () => {
       font-size: 10px;
     `
 
-    const tree = renderer
-      .create(<Text style={styles.foo}>Emotion Primitives</Text>)
-      .toJSON()
-    expect(tree).toMatchSnapshot()
+    const { container } = render(
+      <Text style={styles.foo}>Emotion Primitives</Text>
+    )
+
+    expect(container.firstChild).toMatchSnapshot()
   })
 
   test('primitive should work with `withComponent`', () => {
@@ -105,8 +104,8 @@ describe('Emotion primitives', () => {
       color: ${props => props.decor};
     `
     const Name = StyledText.withComponent(Text)
-    const tree = renderer.create(<Name decor="hotpink">Mike</Name>).toJSON()
-    expect(tree).toMatchSnapshot()
+    const { container } = render(<Name decor="hotpink">Mike</Name>)
+    expect(container.firstChild).toMatchSnapshot()
   })
 
   test('should style any other component', () => {
@@ -118,11 +117,11 @@ describe('Emotion primitives', () => {
       font-size: 20px;
       font-style: ${props => props.sty};
     `
-    const tree = renderer.create(<StyledTitle sty="italic" />).toJSON()
-    expect(tree).toMatchSnapshot()
+    const { container } = render(<StyledTitle sty="italic" />)
+    expect(container.firstChild).toMatchSnapshot()
   })
 
-  test.skip('ref', () => {
+  test('ref', () => {
     const StyledText = styled.Text`
       color: hotpink;
     `
@@ -138,31 +137,29 @@ describe('Emotion primitives', () => {
     const ViewOne = styled.View`
       background-color: ${props => props.color};
     `
-    const treeOne = renderer.create(<ViewOne color="green" />)
+    const { container: container1 } = render(<ViewOne color="green" />)
     const ViewTwo = ViewOne.withComponent(Text)
-    const treeTwo = renderer.create(<ViewTwo color="hotpink" />)
+    const { container: container2 } = render(<ViewTwo color="hotpink" />)
 
-    expect(treeOne).toMatchSnapshot()
-    expect(treeTwo).toMatchSnapshot()
+    expect(container1.firstChild).toMatchSnapshot()
+    expect(container2.firstChild).toMatchSnapshot()
   })
 
   test('should render <Image />', () => {
     const Image = styled.Image`
       border: 2px solid hotpink;
     `
-    const tree = renderer
-      .create(
-        <Image
-          source={{
-            uri: 'https://camo.githubusercontent.com/209bdea972b9b6ef90220c59ecbe66d35ffefa8a/68747470733a2f2f63646e2e7261776769742e636f6d2f746b6834342f656d6f74696f6e2f6d61737465722f656d6f74696f6e2e706e67',
-            height: 150,
-            width: 150
-          }}
-        />
-      )
-      .toJSON()
-
-    expect(tree).toMatchSnapshot()
+    const { container } = render(
+      <Image
+        source={{
+          uri: 'https://camo.githubusercontent.com/209bdea972b9b6ef90220c59ecbe66d35ffefa8a/68747470733a2f2f63646e2e7261776769742e636f6d2f746b6834342f656d6f74696f6e2f6d61737465722f656d6f74696f6e2e706e67',
+          height: 150,
+          width: 150
+        }}
+      />
+    )
+
+    expect(container.firstChild).toMatchSnapshot()
   })
 
   test('custom shouldForwardProp works', () => {
@@ -174,9 +171,10 @@ describe('Emotion primitives', () => {
       color: ${props => props.color};
     `
 
-    const tree = renderer
-      .create(<StyledTitle color="hotpink">{'Emotion'}</StyledTitle>)
-      .toJSON()
-    expect(tree).toMatchSnapshot()
+    const { container } = render(
+      <StyledTitle color="hotpink">{'Emotion'}</StyledTitle>
+    )
+
+    expect(container.firstChild).toMatchSnapshot()
   })
 })
diff --git a/packages/primitives/test/no-babel/__snapshots__/basic.test.js.snap b/packages/primitives/test/no-babel/__snapshots__/basic.test.js.snap
index 4c13c5691f..d3a94d1e39 100644
--- a/packages/primitives/test/no-babel/__snapshots__/basic.test.js.snap
+++ b/packages/primitives/test/no-babel/__snapshots__/basic.test.js.snap
@@ -2,13 +2,9 @@
 
 exports[`should render the primitive when styles applied using object style notation 1`] = `
 <div
-  className="css-text-901oao r-backgroundColor-1g6456j r-color-howw7u"
+  class="css-text-901oao r-backgroundColor-1g6456j r-color-howw7u"
   dir="auto"
-  style={
-    {
-      "fontSize": "40px",
-    }
-  }
+  style="font-size: 40px;"
 >
   Emotion Primitives
 </div>
diff --git a/packages/primitives/test/no-babel/basic.test.js b/packages/primitives/test/no-babel/basic.test.js
index 7697ac1256..2604d1ddaf 100644
--- a/packages/primitives/test/no-babel/basic.test.js
+++ b/packages/primitives/test/no-babel/basic.test.js
@@ -1,6 +1,6 @@
 import * as React from 'react'
 import styled, { css } from '@emotion/primitives'
-import renderer from 'react-test-renderer'
+import { render } from '@testing-library/react'
 import { StyleSheet } from 'react-native'
 
 jest.mock('react-primitives')
@@ -45,21 +45,20 @@ test('should render the primitive when styles applied using object style notatio
     font-size: 20px;
     background-color: ${props => props.back};
   `
-  const tree = renderer
-    .create(
-      <Text style={{ fontSize: 40 }} back="red">
-        Emotion Primitives
-      </Text>
-    )
-    .toJSON()
-  expect(tree).toMatchSnapshot()
+  const { container } = render(
+    <Text style={{ fontSize: 40 }} back="red">
+      Emotion Primitives
+    </Text>
+  )
+
+  expect(container.firstChild).toMatchSnapshot()
 })
 
 // this needs to be here since the babel plugin will remove the whitespace
 test('empty string', () => {
   // prettier-ignore
-  let style = css`    
-      
+  let style = css`
+
   `
   expect(StyleSheet.flatten(style)).toEqual({})
 })
diff --git a/packages/react/__tests__/__snapshots__/at-import.js.snap b/packages/react/__tests__/__snapshots__/at-import.js.snap
index 4cd8402130..ab9443d07e 100644
--- a/packages/react/__tests__/__snapshots__/at-import.js.snap
+++ b/packages/react/__tests__/__snapshots__/at-import.js.snap
@@ -19,9 +19,7 @@ exports[`basic 1`] = `
 
 exports[`basic 2`] = `
 <body>
-  <div
-    id="root"
-  >
+  <div>
     <div
       class="css-1lrxbo5"
     />
@@ -42,8 +40,6 @@ exports[`basic 4`] = `
 
 exports[`basic 5`] = `
 <body>
-  <div
-    id="root"
-  />
+  <div />
 </body>
 `;
diff --git a/packages/react/__tests__/__snapshots__/class-names.js.snap b/packages/react/__tests__/__snapshots__/class-names.js.snap
index ffcafa7178..5f521a70b0 100644
--- a/packages/react/__tests__/__snapshots__/class-names.js.snap
+++ b/packages/react/__tests__/__snapshots__/class-names.js.snap
@@ -6,7 +6,7 @@ exports[`css 1`] = `
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 />
 `;
 
@@ -17,7 +17,7 @@ exports[`cx 1`] = `
 }
 
 <div
-  className="some-other-class emotion-0"
+  class="some-other-class emotion-0"
 />
 `;
 
@@ -27,6 +27,6 @@ exports[`should get the theme 1`] = `
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 />
 `;
diff --git a/packages/react/__tests__/__snapshots__/css-cache-hash.js.snap b/packages/react/__tests__/__snapshots__/css-cache-hash.js.snap
index 9abee3ee10..4a95ec99d8 100644
--- a/packages/react/__tests__/__snapshots__/css-cache-hash.js.snap
+++ b/packages/react/__tests__/__snapshots__/css-cache-hash.js.snap
@@ -7,7 +7,7 @@ exports[`does not rehash if value is css call return value 1`] = `
 
 <div>
   <div
-    className="emotion-0"
+    class="emotion-0"
   />
 </div>
 `;
diff --git a/packages/react/__tests__/__snapshots__/css.js.snap b/packages/react/__tests__/__snapshots__/css.js.snap
index 2acf8a0d1d..5d97fd568a 100644
--- a/packages/react/__tests__/__snapshots__/css.js.snap
+++ b/packages/react/__tests__/__snapshots__/css.js.snap
@@ -1,26 +1,22 @@
 // Jest Snapshot v1, https://goo.gl/fbAQLP
 
 exports[`applies class when css prop is set to nil on wrapper component 1`] = `
-[
-  .emotion-0 {
+.emotion-0 {
   color: hotpink;
 }
 
-<button
-    className="emotion-0"
+<div>
+  <button
+    class="emotion-0"
   >
     I'm hotpink!
-  </button>,
-  .emotion-0 {
-  color: hotpink;
-}
-
-<button
-    className="emotion-0"
+  </button>
+  <button
+    class="emotion-0"
   >
     I'm hotpink too!
-  </button>,
-]
+  </button>
+</div>
 `;
 
 exports[`array fallback (using camelCased property) 1`] = `
@@ -31,7 +27,7 @@ exports[`array fallback (using camelCased property) 1`] = `
 
 <div>
   <div
-    className="emotion-0"
+    class="emotion-0"
   >
     something
   </div>
@@ -46,7 +42,7 @@ exports[`array fallback 1`] = `
 
 <div>
   <div
-    className="emotion-0"
+    class="emotion-0"
   >
     something
   </div>
@@ -60,7 +56,7 @@ exports[`child selector array 1`] = `
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 />
 `;
 
@@ -70,7 +66,7 @@ exports[`css call composition 1`] = `
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 />
 `;
 
@@ -81,7 +77,7 @@ exports[`handles camelCased custom properties in object styles properly 1`] = `
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 />
 `;
 
@@ -94,7 +90,7 @@ exports[`handles composition of an array css prop containing no final semi with
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 >
   I'm hotpink on the green background.
 </div>
@@ -107,7 +103,7 @@ exports[`handles composition of styles without a final semi in a declaration blo
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 >
   I'm hotpink on the green background.
 </div>
@@ -120,7 +116,7 @@ exports[`label in css call 1`] = `
 
 <div>
   <div
-    className="emotion-0"
+    class="emotion-0"
   >
     something
   </div>
@@ -141,7 +137,7 @@ exports[`nested at rule 1`] = `
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 >
   something
 </div>
@@ -154,7 +150,7 @@ exports[`object with false 1`] = `
 
 <div>
   <div
-    className="emotion-0"
+    class="emotion-0"
   >
     something
   </div>
@@ -169,7 +165,7 @@ exports[`overwrite styles from parent 1`] = `
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 />
 `;
 
@@ -189,7 +185,7 @@ exports[`theming with the array css prop 1`] = `
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 />
 `;
 
@@ -199,7 +195,7 @@ exports[`theming with the css prop 1`] = `
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 />
 `;
 
@@ -213,7 +209,7 @@ exports[`thing 1`] = `
 
 <div>
   <div
-    className="emotion-0"
+    class="emotion-0"
   >
     something
   </div>
diff --git a/packages/react/__tests__/__snapshots__/keyframes.js.snap b/packages/react/__tests__/__snapshots__/keyframes.js.snap
index 80d81c0193..9e1bac3eee 100644
--- a/packages/react/__tests__/__snapshots__/keyframes.js.snap
+++ b/packages/react/__tests__/__snapshots__/keyframes.js.snap
@@ -17,7 +17,7 @@ exports[`keyframes basic 1`] = `
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 >
   animation-1bi8wtt
 </div>
@@ -58,7 +58,7 @@ exports[`keyframes keyframes used in css call 1`] = `
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 >
   animation-1bi8wtt
 </div>
@@ -101,7 +101,7 @@ exports[`keyframes multiple keyframes object 1`] = `
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 >
   animation-1bi8wtt
 </div>
@@ -134,7 +134,7 @@ exports[`keyframes object 1`] = `
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 >
   animation-o4c3es
 </div>
@@ -167,7 +167,7 @@ exports[`keyframes object with animation and opaque keyframes as value 1`] = `
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 >
   animation-1bi8wtt
 </div>
@@ -200,7 +200,7 @@ exports[`keyframes object with animationName and opaque keyframes as value 1`] =
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 >
   animation-1bi8wtt
 </div>
@@ -233,7 +233,7 @@ exports[`keyframes object with animationName and string keyframes as value 1`] =
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 >
   animation-1bi8wtt
 </div>
@@ -264,7 +264,7 @@ exports[`keyframes object with string keyframes 1`] = `
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 >
   animation-1bi8wtt
 </div>
@@ -295,7 +295,7 @@ exports[`keyframes without css call 1`] = `
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 >
   animation-1bi8wtt
 </div>
diff --git a/packages/react/__tests__/__snapshots__/legacy-class-name.js.snap b/packages/react/__tests__/__snapshots__/legacy-class-name.js.snap
index ffe08d0613..e18b76c929 100644
--- a/packages/react/__tests__/__snapshots__/legacy-class-name.js.snap
+++ b/packages/react/__tests__/__snapshots__/legacy-class-name.js.snap
@@ -6,7 +6,7 @@ exports[`object className 1`] = `
 }
 
 <div
-  className="legacy__class emotion-0"
+  class="legacy__class emotion-0"
 />
 `;
 
@@ -16,6 +16,6 @@ exports[`string className 1`] = `
 }
 
 <div
-  className="legacy__class emotion-0"
+  class="legacy__class emotion-0"
 />
 `;
diff --git a/packages/react/__tests__/__snapshots__/prod.js.snap b/packages/react/__tests__/__snapshots__/prod.js.snap
new file mode 100644
index 0000000000..c2a3bbbcd7
--- /dev/null
+++ b/packages/react/__tests__/__snapshots__/prod.js.snap
@@ -0,0 +1,10 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`props work 1`] = `
+<div>
+  <div
+    class="css-1lrxbo5"
+    hidden=""
+  />
+</div>
+`;
diff --git a/packages/react/__tests__/__snapshots__/theme-provider.js.snap b/packages/react/__tests__/__snapshots__/theme-provider.js.snap
index e5790bc1cc..ab96d93c83 100644
--- a/packages/react/__tests__/__snapshots__/theme-provider.js.snap
+++ b/packages/react/__tests__/__snapshots__/theme-provider.js.snap
@@ -18,7 +18,7 @@ exports[`nested provider 1`] = `
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 />
 `;
 
@@ -30,6 +30,6 @@ exports[`nested provider with function 1`] = `
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 />
 `;
diff --git a/packages/react/__tests__/__snapshots__/use-theme.js.snap b/packages/react/__tests__/__snapshots__/use-theme.js.snap
index d855c4a143..53ab7f26cb 100644
--- a/packages/react/__tests__/__snapshots__/use-theme.js.snap
+++ b/packages/react/__tests__/__snapshots__/use-theme.js.snap
@@ -18,11 +18,11 @@ exports[`Nested useTheme works 1`] = `
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 >
   Should be green
   <div
-    className="emotion-1"
+    class="emotion-1"
   >
     Should be lawngreen
   </div>
@@ -39,7 +39,7 @@ exports[`useTheme works 1`] = `
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 >
   Should be green
 </div>
diff --git a/packages/react/__tests__/__snapshots__/warnings.js.snap b/packages/react/__tests__/__snapshots__/warnings.js.snap
index eca2e7bdca..359ec84745 100644
--- a/packages/react/__tests__/__snapshots__/warnings.js.snap
+++ b/packages/react/__tests__/__snapshots__/warnings.js.snap
@@ -27,21 +27,17 @@ exports[`does not warn when valid values are passed for the content property 1`]
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 />
 `;
 
-exports[`global with css prop 1`] = `null`;
-
-exports[`unsafe pseudo classes does not warn when using with flag: /* emotion-disable-server-rendering-unsafe-selector-warning-please-do-not-use-this-the-warning-exists-for-a-reason */ does not warn when using the flag on a global rule 1`] = `null`;
-
 exports[`unsafe pseudo classes does not warn when using with flag: /* emotion-disable-server-rendering-unsafe-selector-warning-please-do-not-use-this-the-warning-exists-for-a-reason */ does not warn when using the flag on a rule that is defined in another one 1`] = `
 .emotion-0 div span:first-child {
   border-bottom-left-radius: 0;
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 />
 `;
 
@@ -55,7 +51,7 @@ exports[`unsafe pseudo classes does not warn when using with flag: /* emotion-di
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 />
 `;
 
@@ -69,7 +65,7 @@ exports[`unsafe pseudo classes does not warn when using with flag: /* emotion-di
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 />
 `;
 
@@ -83,7 +79,7 @@ exports[`unsafe pseudo classes does not warn when using with flag: /* emotion-di
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 />
 `;
 
@@ -97,19 +93,17 @@ exports[`unsafe pseudo classes does not warn when using with flag: /* emotion-di
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 />
 `;
 
-exports[`unsafe pseudo classes does not warn when using with flag: /* emotion-disable-server-rendering-unsafe-selector-warning-please-do-not-use-this-the-warning-exists-for-a-reason */ does warn when not using the flag on a global rule 1`] = `null`;
-
 exports[`unsafe pseudo classes does not warn when using with flag: /* emotion-disable-server-rendering-unsafe-selector-warning-please-do-not-use-this-the-warning-exists-for-a-reason */ does warn when not using the flag on a rule that is defined in another one 1`] = `
 .emotion-0 div span:first-child {
   border-bottom-left-radius: 0;
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 />
 `;
 
@@ -123,7 +117,7 @@ exports[`unsafe pseudo classes does not warn when using with flag: /* emotion-di
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 />
 `;
 
@@ -137,7 +131,7 @@ exports[`unsafe pseudo classes does not warn when using with flag: /* emotion-di
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 />
 `;
 
@@ -151,7 +145,7 @@ exports[`unsafe pseudo classes does not warn when using with flag: /* emotion-di
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 />
 `;
 
@@ -165,7 +159,7 @@ exports[`unsafe pseudo classes does not warn when using with flag: /* emotion-di
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 />
 `;
 
@@ -175,7 +169,7 @@ exports[`unsafe pseudo classes does not warn when using with flag: /* emotion-di
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 />
 `;
 
@@ -185,7 +179,7 @@ exports[`unsafe pseudo classes does not warn when using with flag: /* emotion-di
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 />
 `;
 
@@ -195,7 +189,7 @@ exports[`unsafe pseudo classes does not warn when using with flag: /* emotion-di
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 />
 `;
 
@@ -206,7 +200,7 @@ exports[`unsafe pseudo classes does not warn when using with flag: /* emotion-di
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 />
 `;
 
@@ -217,7 +211,7 @@ exports[`unsafe pseudo classes does not warn when using with flag: /* emotion-di
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 />
 `;
 
@@ -227,7 +221,7 @@ exports[`unsafe pseudo classes does not warn when using with flag: /* emotion-di
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 />
 `;
 
@@ -237,7 +231,7 @@ exports[`unsafe pseudo classes does not warn when using with flag: /* emotion-di
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 />
 `;
 
@@ -247,7 +241,7 @@ exports[`unsafe pseudo classes does not warn when using with flag: /* emotion-di
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 />
 `;
 
@@ -257,7 +251,7 @@ exports[`unsafe pseudo classes does not warn when using with flag: /* emotion-di
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 />
 `;
 
@@ -267,7 +261,7 @@ exports[`unsafe pseudo classes does not warn when using with flag: /* emotion-di
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 />
 `;
 
@@ -277,7 +271,7 @@ exports[`unsafe pseudo classes does not warn when using with flag: /* emotion-di
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 />
 `;
 
@@ -287,7 +281,7 @@ exports[`unsafe pseudo classes does not warn when using with flag: /* emotion-di
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 />
 `;
 
@@ -297,7 +291,7 @@ exports[`unsafe pseudo classes does not warn when using with flag: /* emotion-di
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 />
 `;
 
@@ -308,7 +302,7 @@ exports[`unsafe pseudo classes does not warn when using with flag: /* emotion-di
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 />
 `;
 
@@ -319,7 +313,7 @@ exports[`unsafe pseudo classes does not warn when using with flag: /* emotion-di
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 />
 `;
 
@@ -329,7 +323,7 @@ exports[`unsafe pseudo classes does not warn when using with flag: /* emotion-di
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 />
 `;
 
@@ -339,7 +333,7 @@ exports[`unsafe pseudo classes does not warn when using with flag: /* emotion-di
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 />
 `;
 
@@ -349,7 +343,7 @@ exports[`unsafe pseudo classes does not warn when using with flag: /* emotion-di
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 />
 `;
 
@@ -359,7 +353,7 @@ exports[`unsafe pseudo classes does not warn when using with flag: /* emotion-di
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 />
 `;
 
@@ -369,7 +363,7 @@ exports[`unsafe pseudo classes does not warn when using with flag: /* emotion-di
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 />
 `;
 
@@ -379,7 +373,7 @@ exports[`unsafe pseudo classes warns when using without flag: /* emotion-disable
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 />
 `;
 
@@ -389,7 +383,7 @@ exports[`unsafe pseudo classes warns when using without flag: /* emotion-disable
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 />
 `;
 
@@ -399,7 +393,7 @@ exports[`unsafe pseudo classes warns when using without flag: /* emotion-disable
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 />
 `;
 
@@ -409,7 +403,7 @@ exports[`unsafe pseudo classes warns when using without flag: /* emotion-disable
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 />
 `;
 
@@ -419,6 +413,6 @@ exports[`unsafe pseudo classes warns when using without flag: /* emotion-disable
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 />
 `;
diff --git a/packages/react/__tests__/__snapshots__/with-theme.js.snap b/packages/react/__tests__/__snapshots__/with-theme.js.snap
index f7691fa5ba..1548e5db43 100644
--- a/packages/react/__tests__/__snapshots__/with-theme.js.snap
+++ b/packages/react/__tests__/__snapshots__/with-theme.js.snap
@@ -1,3 +1,3 @@
 // Jest Snapshot v1, https://goo.gl/fbAQLP
 
-exports[`withTheme works 1`] = `"green"`;
+exports[`withTheme works 1`] = `green`;
diff --git a/packages/react/__tests__/at-import.js b/packages/react/__tests__/at-import.js
index 338b8077a6..6a18a1fbbe 100644
--- a/packages/react/__tests__/at-import.js
+++ b/packages/react/__tests__/at-import.js
@@ -1,17 +1,17 @@
-import * as React from 'react'
 /** @jsx jsx */
+import React from 'react'
 import { jsx } from '@emotion/react'
-import { render, unmountComponentAtNode } from 'react-dom'
+import { render } from '@testing-library/react'
 import { Global, css } from '@emotion/react'
 
 beforeEach(() => {
   document.head.innerHTML = ''
-  document.body.innerHTML = `<div id="root"></div>`
+  document.body.innerHTML = ``
 })
 
 gate({ development: false }, ({ test }) => {
   test('basic', () => {
-    render(
+    const { unmount } = render(
       <React.Fragment>
         <div css={{ color: 'hotpink' }} />
         <Global
@@ -23,8 +23,7 @@ gate({ development: false }, ({ test }) => {
             }
           `}
         />
-      </React.Fragment>,
-      document.getElementById('root')
+      </React.Fragment>
     )
     expect(document.head).toMatchSnapshot()
     expect(document.body).toMatchSnapshot()
@@ -42,7 +41,7 @@ gate({ development: false }, ({ test }) => {
       ".css-1lrxbo5 {color: hotpink;}",
     ]
   `)
-    unmountComponentAtNode(document.getElementById('root'))
+    unmount()
     expect(document.head).toMatchSnapshot()
     expect(document.body).toMatchSnapshot()
   })
diff --git a/packages/react/__tests__/babel/__snapshots__/css.js.snap b/packages/react/__tests__/babel/__snapshots__/css.js.snap
index 8376e8b419..352e1fa713 100644
--- a/packages/react/__tests__/babel/__snapshots__/css.js.snap
+++ b/packages/react/__tests__/babel/__snapshots__/css.js.snap
@@ -9,7 +9,7 @@ exports[`composition of dynamic array css prop with cssprop-generated className
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 >
   I'm hotpink on the green background.
 </div>
@@ -23,7 +23,7 @@ exports[`tagged template args forwarded 1`] = `
 }
 
 <h2
-  className="emotion-0"
+  class="emotion-0"
 >
   something
 </h2>
diff --git a/packages/react/__tests__/babel/css.js b/packages/react/__tests__/babel/css.js
index 57ceef7bf6..9490aa40d4 100644
--- a/packages/react/__tests__/babel/css.js
+++ b/packages/react/__tests__/babel/css.js
@@ -1,7 +1,8 @@
 /** @jsx jsx */
 import 'test-utils/setup-env'
 import { jsx, css } from '@emotion/react'
-import renderer from 'react-test-renderer'
+import { render } from '@testing-library/react'
+import { act } from 'react'
 
 test('tagged template args forwarded', () => {
   function media(...args) {
@@ -12,7 +13,7 @@ test('tagged template args forwarded', () => {
     `
   }
 
-  const tree = renderer.create(
+  const { container } = render(
     <h2
       css={css`
         ${media`color: red;`};
@@ -22,7 +23,7 @@ test('tagged template args forwarded', () => {
     </h2>
   )
 
-  expect(tree.toJSON()).toMatchSnapshot()
+  expect(container.firstChild).toMatchSnapshot()
 })
 
 test('composition of dynamic array css prop with cssprop-generated className (#1730)', () => {
@@ -37,9 +38,9 @@ test('composition of dynamic array css prop with cssprop-generated className (#1
       {children}
     </Child>
   )
-  const tree = renderer.create(
+  const { container } = render(
     <Parent>{"I'm hotpink on the green background."}</Parent>
   )
 
-  expect(tree.toJSON()).toMatchSnapshot()
+  expect(container.firstChild).toMatchSnapshot()
 })
diff --git a/packages/react/__tests__/class-names.js b/packages/react/__tests__/class-names.js
index 6b214ddee1..ac62235a3d 100644
--- a/packages/react/__tests__/class-names.js
+++ b/packages/react/__tests__/class-names.js
@@ -1,10 +1,10 @@
-import * as React from 'react'
 import 'test-utils/setup-env'
+import React from 'react'
 import { ClassNames, ThemeProvider } from '@emotion/react'
-import renderer from 'react-test-renderer'
+import { render } from '@testing-library/react'
 
 test('css', () => {
-  const tree = renderer.create(
+  const { container } = render(
     <ClassNames>
       {({ css }) => (
         <div
@@ -16,11 +16,11 @@ test('css', () => {
     </ClassNames>
   )
 
-  expect(tree.toJSON()).toMatchSnapshot()
+  expect(container.firstChild).toMatchSnapshot()
 })
 
 test('should get the theme', () => {
-  const tree = renderer.create(
+  const { container } = render(
     <ThemeProvider theme={{ color: 'green' }}>
       <ClassNames>
         {({ css, theme }) => (
@@ -33,11 +33,11 @@ test('should get the theme', () => {
       </ClassNames>
     </ThemeProvider>
   )
-  expect(tree.toJSON()).toMatchSnapshot()
+  expect(container.firstChild).toMatchSnapshot()
 })
 
 test('cx', () => {
-  const tree = renderer.create(
+  const { container } = render(
     <ClassNames>
       {({ css, cx }) => {
         let secondClassButItsInsertedFirst = css`
@@ -60,12 +60,12 @@ test('cx', () => {
     </ClassNames>
   )
 
-  expect(tree.toJSON()).toMatchSnapshot()
+  expect(container.firstChild).toMatchSnapshot()
 })
 
 test('css and cx throws when used after render', () => {
   let cx, css
-  renderer.create(
+  render(
     <ClassNames>
       {arg => {
         ;({ cx, css } = arg)
diff --git a/packages/react/__tests__/css-cache-hash.js b/packages/react/__tests__/css-cache-hash.js
index ef885b7e70..630af62963 100644
--- a/packages/react/__tests__/css-cache-hash.js
+++ b/packages/react/__tests__/css-cache-hash.js
@@ -2,7 +2,7 @@
 import 'test-utils/setup-env'
 import { jsx, css } from '@emotion/react'
 import { serializeStyles } from '@emotion/serialize'
-import * as renderer from 'react-test-renderer'
+import { render } from '@testing-library/react'
 const utils = require('@emotion/utils')
 
 const spy = jest.spyOn(utils, 'insertStyles')
@@ -11,7 +11,7 @@ test('does not rehash if value is css call return value', () => {
   const val = css`
     color: hotpink;
   `
-  const tree = renderer.create(
+  const { container } = render(
     <div>
       <div css={val} />
     </div>
@@ -19,5 +19,5 @@ test('does not rehash if value is css call return value', () => {
   expect(serializeStyles([val])).toBe(val)
 
   expect(spy.mock.calls[0][1]).toBe(val)
-  expect(tree.toJSON()).toMatchSnapshot()
+  expect(container.firstChild).toMatchSnapshot()
 })
diff --git a/packages/react/__tests__/css.js b/packages/react/__tests__/css.js
index 510e143a1e..5e1a495c51 100644
--- a/packages/react/__tests__/css.js
+++ b/packages/react/__tests__/css.js
@@ -1,10 +1,9 @@
 /** @jsx jsx */
 import 'test-utils/setup-env'
 import { safeQuerySelector } from 'test-utils'
-import * as React from 'react'
+import React from 'react'
 import { jsx, css, Global, CacheProvider, ThemeProvider } from '@emotion/react'
 import { render } from '@testing-library/react'
-import renderer from 'react-test-renderer'
 import createCache from '@emotion/cache'
 
 console.error = jest.fn()
@@ -27,55 +26,55 @@ const SomeComponent = (props /*: { lol: true } */) => (props.lol ? 'yes' : 'no')
 ;<SomeComponent /> // eslint-disable-line no-unused-expressions
 
 test('thing', () => {
-  const tree = renderer.create(
+  const { container } = render(
     <div>
       <div css={{ display: 'flex' }}>something</div>
     </div>
   )
 
-  expect(tree.toJSON()).toMatchSnapshot()
+  expect(container.firstChild).toMatchSnapshot()
 })
 
 test('css call composition', () => {
   let first = css`
     color: hotpink;
   `
-  let tree = renderer.create(<div css={css({ ':hover': first })} />)
+  let { container } = render(<div css={css({ ':hover': first })} />)
 
-  expect(tree.toJSON()).toMatchSnapshot()
+  expect(container.firstChild).toMatchSnapshot()
 })
 
 test('theming with the css prop', () => {
-  const tree = renderer.create(
+  const { container } = render(
     <ThemeProvider theme={{ primary: 'hotpink' }}>
       <div css={theme => ({ color: theme.primary })} />
     </ThemeProvider>
   )
-  expect(tree.toJSON()).toMatchSnapshot()
+  expect(container.firstChild).toMatchSnapshot()
 })
 
 test('theming with the array css prop', () => {
-  const tree = renderer.create(
+  const { container } = render(
     <ThemeProvider theme={{ primary: 'hotpink' }}>
       <div css={[theme => ({ color: theme.primary }), { display: 'flex' }]} />
     </ThemeProvider>
   )
 
-  expect(tree.toJSON()).toMatchSnapshot()
+  expect(container.firstChild).toMatchSnapshot()
 })
 
 test('object with false', () => {
-  const tree = renderer.create(
+  const { container } = render(
     <div>
       <div css={{ color: 'hotpink', display: false }}>something</div>
     </div>
   )
 
-  expect(tree.toJSON()).toMatchSnapshot()
+  expect(container.firstChild).toMatchSnapshot()
 })
 
 test('label in css call', () => {
-  const tree = renderer.create(
+  const { container } = render(
     <div>
       <div
         css={css`
@@ -88,12 +87,12 @@ test('label in css call', () => {
     </div>
   )
 
-  expect(tree.toJSON()).toMatchSnapshot()
+  expect(container.firstChild).toMatchSnapshot()
 })
 
 test('string as css prop throws', () => {
   expect(() => {
-    renderer.create(
+    render(
       <div>
         <div
           css={`
@@ -108,7 +107,7 @@ test('string as css prop throws', () => {
 })
 
 test('array fallback', () => {
-  const tree = renderer.create(
+  const { container } = render(
     <div>
       <div
         css={{
@@ -120,11 +119,11 @@ test('array fallback', () => {
     </div>
   )
 
-  expect(tree.toJSON()).toMatchSnapshot()
+  expect(container.firstChild).toMatchSnapshot()
 })
 
 test('array fallback (using camelCased property)', () => {
-  const tree = renderer.create(
+  const { container } = render(
     <div>
       <div
         css={{
@@ -136,11 +135,11 @@ test('array fallback (using camelCased property)', () => {
     </div>
   )
 
-  expect(tree.toJSON()).toMatchSnapshot()
+  expect(container.firstChild).toMatchSnapshot()
 })
 
 test('nested at rule', () => {
-  const tree = renderer.create(
+  const { container } = render(
     <div
       css={{
         '@media (min-width: 980px)': {
@@ -155,12 +154,13 @@ test('nested at rule', () => {
     </div>
   )
 
-  expect(tree.toJSON()).toMatchSnapshot()
+  expect(container.firstChild).toMatchSnapshot()
 })
 
 test('can set speedy via custom cache', () => {
   let cache = createCache({ key: 'speedy-test', speedy: true })
-  renderer.create(
+
+  render(
     <CacheProvider value={cache}>
       <div
         css={{
@@ -172,6 +172,7 @@ test('can set speedy via custom cache', () => {
       </div>
     </CacheProvider>
   )
+
   expect(cache.sheet.tags).toHaveLength(1)
 })
 
@@ -181,11 +182,13 @@ test('speedy option from a custom cache is inherited for <Global/> styles', () =
     container: safeQuerySelector('body'),
     speedy: true
   })
-  renderer.create(
+
+  render(
     <CacheProvider value={cache}>
       <Global styles={{ html: { fontSize: 16 } }} />
     </CacheProvider>
   )
+
   expect(safeQuerySelector('body style').textContent).toEqual('')
 })
 
@@ -202,9 +205,9 @@ test('does not autoLabel without babel or EMOTION_RUNTIME_AUTO_LABEL', () => {
       </div>
     )
   }
-  const tree = renderer.create(<SomeComp />)
+  const { container } = render(<SomeComp />)
 
-  expect(tree.toJSON().props.className).toMatch(/css-[^-]+/)
+  expect(container.firstChild.className).toMatch(/css-[^-]+/)
 })
 
 test('autoLabel without babel', () => {
@@ -222,9 +225,9 @@ test('autoLabel without babel', () => {
       </div>
     )
   }
-  const tree = renderer.create(<SomeComp />)
+  const { container } = render(<SomeComp />)
 
-  expect(tree.toJSON().props.className.endsWith('-SomeComp')).toBe(true)
+  expect(container.firstChild.className.endsWith('-SomeComp')).toBe(true)
 })
 
 test('autoLabel without babel (sanitized)', () => {
@@ -239,9 +242,9 @@ test('autoLabel without babel (sanitized)', () => {
   }
 
   // eslint-disable-next-line react/jsx-pascal-case
-  const tree = renderer.create(<SomeComp$ />)
+  const { container } = render(<SomeComp$ />)
 
-  expect(tree.toJSON().props.className.endsWith('-SomeComp-')).toBe(true)
+  expect(container.firstChild.className.endsWith('-SomeComp-')).toBe(true)
 })
 
 test('overwrite styles from parent', () => {
@@ -254,7 +257,7 @@ test('overwrite styles from parent', () => {
       {...props}
     />
   )
-  const tree = renderer.create(
+  const { container } = render(
     <SomeComponent
       css={{
         color: 'hotpink'
@@ -262,11 +265,11 @@ test('overwrite styles from parent', () => {
     />
   )
 
-  expect(tree.toJSON()).toMatchSnapshot()
+  expect(container.firstChild).toMatchSnapshot()
 })
 
 test('child selector array', () => {
-  const tree = renderer.create(
+  const { container } = render(
     <div
       css={{
         ':hover': [{ color: 'green' }, { backgroundColor: 'yellow' }]
@@ -274,11 +277,11 @@ test('child selector array', () => {
     />
   )
 
-  expect(tree.toJSON()).toMatchSnapshot()
+  expect(container.firstChild).toMatchSnapshot()
 })
 
 test('handles camelCased custom properties in object styles properly', () => {
-  const tree = renderer.create(
+  const { container } = render(
     <div
       css={{
         '--textColor': 'green',
@@ -287,7 +290,7 @@ test('handles camelCased custom properties in object styles properly', () => {
     />
   )
 
-  expect(tree.toJSON()).toMatchSnapshot()
+  expect(container.firstChild).toMatchSnapshot()
 })
 
 test('applies class when css prop is set to nil on wrapper component', () => {
@@ -300,18 +303,18 @@ test('applies class when css prop is set to nil on wrapper component', () => {
   } */
   ) => <Button css={buttonStyles}>{children}</Button>
 
-  const tree = renderer.create(
+  const { container } = render(
     <React.Fragment>
       <WrappedButton>{"I'm hotpink!"}</WrappedButton>
       <WrappedButton buttonStyles={null}>{"I'm hotpink too!"}</WrappedButton>
     </React.Fragment>
   )
 
-  expect(tree.toJSON()).toMatchSnapshot()
+  expect(container).toMatchSnapshot()
 })
 
 test('handles composition of styles without a final semi in a declaration block', () => {
-  const tree = renderer.create(
+  const { container } = render(
     <div
       css={[
         // prettier-ignore
@@ -327,7 +330,7 @@ test('handles composition of styles without a final semi in a declaration block'
     </div>
   )
 
-  expect(tree.toJSON()).toMatchSnapshot()
+  expect(container.firstChild).toMatchSnapshot()
 })
 
 test('handles composition of an array css prop containing no final semi with cssprop-generated className (runtime variant of #1730)', () => {
@@ -342,11 +345,11 @@ test('handles composition of an array css prop containing no final semi with css
       {children}
     </Child>
   )
-  const tree = renderer.create(
+  const { container } = render(
     <Parent>{"I'm hotpink on the green background."}</Parent>
   )
 
-  expect(tree.toJSON()).toMatchSnapshot()
+  expect(container.firstChild).toMatchSnapshot()
 })
 
 it("doesn't try to insert invalid rules caused by object style's value being falsy", () => {
diff --git a/packages/react/__tests__/custom-cache.js b/packages/react/__tests__/custom-cache.js
index 8062dae39e..b614d270a7 100644
--- a/packages/react/__tests__/custom-cache.js
+++ b/packages/react/__tests__/custom-cache.js
@@ -2,7 +2,7 @@
 import createCache from '@emotion/cache'
 import { CacheProvider, Global, jsx } from '@emotion/react'
 import { StyleSheet } from '@emotion/sheet'
-import renderer from 'react-test-renderer'
+import { render } from '@testing-library/react'
 import { safeQuerySelector } from 'test-utils'
 import 'test-utils/setup-env'
 
@@ -12,10 +12,6 @@ function stylisPlugin(element) {
   }
 }
 
-function render(ele) {
-  return renderer.create(ele).toJSON()
-}
-
 beforeEach(() => {
   safeQuerySelector('head').innerHTML = ''
   safeQuerySelector('body').innerHTML = ''
@@ -32,7 +28,7 @@ test('with custom plugins', () => {
       <CacheProvider value={cache}>
         <div css={{ display: 'flex', color: 'blue' }} />
       </CacheProvider>
-    )
+    ).container.firstChild
   ).toMatchInlineSnapshot(`
     .emotion-0 {
       display: flex;
@@ -40,7 +36,7 @@ test('with custom plugins', () => {
     }
 
     <div
-      className="emotion-0"
+      class="emotion-0"
     />
   `)
 })
diff --git a/packages/react/__tests__/import-prod.js b/packages/react/__tests__/import-prod.js
index 4ab884bf21..1ce8689036 100644
--- a/packages/react/__tests__/import-prod.js
+++ b/packages/react/__tests__/import-prod.js
@@ -1,5 +1,6 @@
-import * as React from 'react'
-import * as ReactDOM from 'react-dom'
+import React from 'react'
+import ReactDOM from 'react-dom'
+import { render } from '@testing-library/react'
 import { css, Global } from '@emotion/react'
 import styled from '@emotion/styled'
 import prettify from '@emotion/css-prettifier'
@@ -19,23 +20,9 @@ expect.addSnapshotSerializer({
   }
 })
 
-// can't use RTL as production React 18 throws when it's trying to use `act`
-const render = children =>
-  new Promise(resolve => {
-    const el = document.createElement('div')
-    document.body.appendChild(el)
-
-    if (ReactDOM.createRoot) {
-      const root = ReactDOM.createRoot(el)
-      root.render(<div ref={resolve}>{children}</div>)
-    } else {
-      ReactDOM.render(children, el, resolve)
-    }
-  })
-
 gate({ development: false }, ({ test }) => {
-  test('it works', async () => {
-    await render(
+  test('it works', () => {
+    render(
       <div>
         <Comp>something</Comp>
 
diff --git a/packages/react/__tests__/keyframes.js b/packages/react/__tests__/keyframes.js
index 2e13f0652f..6848cafb08 100644
--- a/packages/react/__tests__/keyframes.js
+++ b/packages/react/__tests__/keyframes.js
@@ -3,7 +3,7 @@ import 'test-utils/setup-env'
 import { jsx, css, keyframes } from '@emotion/react'
 import { safeQuerySelector, throwIfFalsy } from 'test-utils'
 import cases from 'jest-in-case'
-import * as renderer from 'react-test-renderer'
+import { render } from '@testing-library/react'
 import createCache from '@emotion/cache'
 import { CacheProvider } from '@emotion/react'
 
@@ -13,9 +13,8 @@ cases(
     safeQuerySelector('head').innerHTML = ''
     let cache = createCache({ key: 'css' })
     expect(
-      renderer
-        .create(<CacheProvider value={cache}>{opts.render()}</CacheProvider>)
-        .toJSON()
+      render(<CacheProvider value={cache}>{opts.render()}</CacheProvider>)
+        .container.firstChild
     ).toMatchSnapshot()
     expect(
       throwIfFalsy(cache.sheet.tags).map(tag => tag.textContent || '')
diff --git a/packages/react/__tests__/legacy-class-name.js b/packages/react/__tests__/legacy-class-name.js
index e67518b5f5..80481cbdf7 100644
--- a/packages/react/__tests__/legacy-class-name.js
+++ b/packages/react/__tests__/legacy-class-name.js
@@ -1,34 +1,30 @@
 /** @jsx jsx */
 import 'test-utils/setup-env'
 import { jsx, css } from '@emotion/react'
-import renderer from 'react-test-renderer'
+import { render } from '@testing-library/react'
 
 test('string className', () => {
-  const tree = renderer
-    .create(
-      <div
-        className="legacy__class"
-        css={css`
-          color: hotpink;
-        `}
-      />
-    )
-    .toJSON()
+  const { container } = render(
+    <div
+      className="legacy__class"
+      css={css`
+        color: hotpink;
+      `}
+    />
+  )
 
-  expect(tree).toMatchSnapshot()
+  expect(container.firstChild).toMatchSnapshot()
 })
 
 test('object className', () => {
-  const tree = renderer
-    .create(
-      <div
-        className={{ toString: () => 'legacy__class' }}
-        css={css`
-          color: hotpink;
-        `}
-      />
-    )
-    .toJSON()
+  const { container } = render(
+    <div
+      className={{ toString: () => 'legacy__class' }}
+      css={css`
+        color: hotpink;
+      `}
+    />
+  )
 
-  expect(tree).toMatchSnapshot()
+  expect(container.firstChild).toMatchSnapshot()
 })
diff --git a/packages/react/__tests__/prod.js b/packages/react/__tests__/prod.js
index ae3ec5895d..c4b2a9126e 100644
--- a/packages/react/__tests__/prod.js
+++ b/packages/react/__tests__/prod.js
@@ -1,6 +1,6 @@
 /** @jsx jsx */
 import { css, jsx } from '@emotion/react'
-import renderer from 'react-test-renderer'
+import { render } from '@testing-library/react'
 
 gate({ development: false }, ({ test }) => {
   test('css works', () => {
@@ -16,7 +16,7 @@ gate({ development: false }, ({ test }) => {
   })
 
   test('props work', () => {
-    let tree = renderer.create(<div css={{ color: 'hotpink' }} hidden />)
-    expect(tree.toJSON().props.hidden).toBe(true)
+    let { container } = render(<div css={{ color: 'hotpink' }} hidden />)
+    expect(container).toMatchSnapshot()
   })
 })
diff --git a/packages/react/__tests__/ref.js b/packages/react/__tests__/ref.js
index 792ef18716..0b82cce60b 100644
--- a/packages/react/__tests__/ref.js
+++ b/packages/react/__tests__/ref.js
@@ -5,7 +5,7 @@ import { render, cleanup } from '@testing-library/react'
 
 afterEach(cleanup)
 
-test.skip('ref works', () => {
+test('ref works', () => {
   let ref = React.createRef()
   let { getByTestId } = render(
     <div data-testid="test" css={{ color: 'hotpink' }} ref={ref} />
diff --git a/packages/react/__tests__/rehydration.js b/packages/react/__tests__/rehydration.js
index ae9cdc85c4..b4cb40d142 100644
--- a/packages/react/__tests__/rehydration.js
+++ b/packages/react/__tests__/rehydration.js
@@ -604,7 +604,8 @@ test('duplicated global styles can be removed safely after rehydrating HTML SSRe
     </head>
   `)
 })
-;(React.useId ? describe : describe.skip)('useId', () => {
+
+describe('useId', () => {
   test('no hydration mismatch for styled when using useId', async () => {
     const finalHTML = await disableBrowserEnvTemporarily(() => {
       resetAllModules()
diff --git a/packages/react/__tests__/theme-provider.js b/packages/react/__tests__/theme-provider.js
index 2d1ff63e24..e3e06f5361 100644
--- a/packages/react/__tests__/theme-provider.js
+++ b/packages/react/__tests__/theme-provider.js
@@ -2,59 +2,55 @@
 import 'test-utils/setup-env'
 import { ignoreConsoleErrors } from 'test-utils'
 import { jsx, ThemeProvider } from '@emotion/react'
-import renderer from 'react-test-renderer'
+import { render } from '@testing-library/react'
 import cases from 'jest-in-case'
 
 test('nested provider', () => {
-  const tree = renderer
-    .create(
-      <ThemeProvider theme={{ color: 'hotpink', padding: 4 }}>
-        <ThemeProvider theme={{ backgroundColor: 'darkgreen', color: 'white' }}>
-          <div
-            css={({ color, padding, backgroundColor }) => ({
-              color,
-              padding,
-              backgroundColor
-            })}
-          />
-        </ThemeProvider>
+  const { container } = render(
+    <ThemeProvider theme={{ color: 'hotpink', padding: 4 }}>
+      <ThemeProvider theme={{ backgroundColor: 'darkgreen', color: 'white' }}>
+        <div
+          css={({ color, padding, backgroundColor }) => ({
+            color,
+            padding,
+            backgroundColor
+          })}
+        />
       </ThemeProvider>
-    )
-    .toJSON()
-  expect(tree).toMatchSnapshot()
+    </ThemeProvider>
+  )
+  expect(container.firstChild).toMatchSnapshot()
 })
 
 test('nested provider with function', () => {
-  const tree = renderer
-    .create(
-      <ThemeProvider theme={{ color: 'hotpink', padding: 4 }}>
-        <ThemeProvider
-          theme={theme => ({
-            backgroundColor: 'darkgreen',
-            ...theme,
-            padding: 8
+  const { container } = render(
+    <ThemeProvider theme={{ color: 'hotpink', padding: 4 }}>
+      <ThemeProvider
+        theme={theme => ({
+          backgroundColor: 'darkgreen',
+          ...theme,
+          padding: 8
+        })}
+      >
+        <div
+          css={({ color, padding, backgroundColor }) => ({
+            color,
+            padding,
+            backgroundColor
           })}
-        >
-          <div
-            css={({ color, padding, backgroundColor }) => ({
-              color,
-              padding,
-              backgroundColor
-            })}
-          />
-        </ThemeProvider>
+        />
       </ThemeProvider>
-    )
-    .toJSON()
-  expect(tree).toMatchSnapshot()
+    </ThemeProvider>
+  )
+  expect(container.firstChild).toMatchSnapshot()
 })
 
 cases(
   'ThemeProvider throws the correct errors',
   ({ value }) => {
     ignoreConsoleErrors(() => {
-      expect(() => {
-        renderer.create(
+      expect(() =>
+        render(
           <ThemeProvider theme={{ color: 'hotpink', padding: 4 }}>
             <ThemeProvider theme={value}>
               <div
@@ -67,7 +63,7 @@ cases(
             </ThemeProvider>
           </ThemeProvider>
         )
-      }).toThrowErrorMatchingSnapshot()
+      ).toThrowErrorMatchingSnapshot()
     })
   },
   {
diff --git a/packages/react/__tests__/use-theme.js b/packages/react/__tests__/use-theme.js
index 130fd91594..911331330c 100644
--- a/packages/react/__tests__/use-theme.js
+++ b/packages/react/__tests__/use-theme.js
@@ -1,6 +1,6 @@
 /** @jsx jsx */
 import 'test-utils/setup-env'
-import * as renderer from 'react-test-renderer'
+import { render } from '@testing-library/react'
 import { jsx, useTheme, ThemeProvider } from '@emotion/react'
 
 test('useTheme works', () => {
@@ -16,17 +16,15 @@ test('useTheme works', () => {
   }
 
   expect(
-    renderer
-      .create(
-        <ThemeProvider theme={{ lightGreen: 'green', darkGreen: 'darkgreen' }}>
-          <TestComponent />
-        </ThemeProvider>
-      )
-      .toJSON()
+    render(
+      <ThemeProvider theme={{ lightGreen: 'green', darkGreen: 'darkgreen' }}>
+        <TestComponent />
+      </ThemeProvider>
+    ).container.firstChild
   ).toMatchSnapshot()
 })
 
-test('Nested useTheme works', () => {
+test('Nested useTheme works', async () => {
   function TestComponent1(props) {
     const theme = useTheme()
     return (
@@ -64,12 +62,10 @@ test('Nested useTheme works', () => {
   }
 
   expect(
-    renderer
-      .create(
-        <ThemeProvider theme={{ lightGreen: 'green', darkGreen: 'darkgreen' }}>
-          <TestComponent2 />
-        </ThemeProvider>
-      )
-      .toJSON()
+    render(
+      <ThemeProvider theme={{ lightGreen: 'green', darkGreen: 'darkgreen' }}>
+        <TestComponent2 />
+      </ThemeProvider>
+    ).container.firstChild
   ).toMatchSnapshot()
 })
diff --git a/packages/react/__tests__/warnings.js b/packages/react/__tests__/warnings.js
index 55d68d4cae..ee5e358c52 100644
--- a/packages/react/__tests__/warnings.js
+++ b/packages/react/__tests__/warnings.js
@@ -2,7 +2,6 @@
 import 'test-utils/setup-env'
 import { jsx, css, Global, keyframes, ClassNames } from '@emotion/react'
 import styled from '@emotion/styled'
-import renderer from 'react-test-renderer'
 import { render } from '@testing-library/react'
 
 console.error = jest.fn()
@@ -40,16 +39,14 @@ beforeEach(() => {
 test('does not warn when valid values are passed for the content property', () => {
   const style = css(validValues.map(value => ({ content: value })))
   expect(console.error).not.toBeCalled()
-  expect(renderer.create(<div css={style} />).toJSON()).toMatchSnapshot()
+  expect(render(<div css={style} />).container.firstChild).toMatchSnapshot()
 })
 
 const invalidValues = ['this is not valid', '', 'element']
 
 test('does warn when invalid values are passed for the content property', () => {
   invalidValues.forEach(value => {
-    expect(() =>
-      renderer.create(<div css={{ content: value }} />)
-    ).toThrowError(
+    expect(() => render(<div css={{ content: value }} />)).toThrowError(
       `You seem to be using a value for 'content' without quotes, try replacing it with \`content: '"${value}"'\``
     )
   })
@@ -77,7 +74,9 @@ describe('unsafe pseudo classes', () => {
         `
         const match = pseudoClass.match(/(:first|:nth|:nth-last)-child/)
         expect(match).not.toBeNull()
-        expect(renderer.create(<div css={style} />).toJSON()).toMatchSnapshot()
+        expect(
+          render(<div css={style} />).container.firstChild
+        ).toMatchSnapshot()
         expect(console.error).toBeCalledWith(
           `The pseudo class "${match[0]}" is potentially unsafe when doing server-side rendering. Try changing it to "${match[1]}-of-type".`
         )
@@ -119,7 +118,7 @@ describe('unsafe pseudo classes', () => {
         const match = pseudoClass.match(/(:first|:nth|:nth-last)-child/)
         expect(match).not.toBeNull()
         expect(
-          renderer.create(<div css={getStyle(pseudoClass)} />).toJSON()
+          render(<div css={getStyle(pseudoClass)} />).container.firstChild
         ).toMatchSnapshot()
         expect(console.error).not.toBeCalled()
       })
@@ -127,20 +126,18 @@ describe('unsafe pseudo classes', () => {
 
     test('does warn when not using the flag on the rule that follows another rule', () => {
       expect(
-        renderer
-          .create(
-            <div
-              css={{
-                '& > *': {
-                  marginLeft: 10
-                },
-                [`& > *:first-child$`]: {
-                  marginLeft: 0
-                }
-              }}
-            />
-          )
-          .toJSON()
+        render(
+          <div
+            css={{
+              '& > *': {
+                marginLeft: 10
+              },
+              [`& > *:first-child$`]: {
+                marginLeft: 0
+              }
+            }}
+          />
+        ).container.firstChild
       ).toMatchSnapshot()
       expect(console.error.mock.calls).toMatchInlineSnapshot(`
         [
@@ -153,20 +150,18 @@ describe('unsafe pseudo classes', () => {
 
     test('does warn when not using the flag on the rule that preceeds another rule', () => {
       expect(
-        renderer
-          .create(
-            <div
-              css={{
-                [`& > *:first-child`]: {
-                  marginLeft: 0
-                },
-                '& > *': {
-                  marginLeft: 10
-                }
-              }}
-            />
-          )
-          .toJSON()
+        render(
+          <div
+            css={{
+              [`& > *:first-child`]: {
+                marginLeft: 0
+              },
+              '& > *': {
+                marginLeft: 10
+              }
+            }}
+          />
+        ).container.firstChild
       ).toMatchSnapshot()
       expect(console.error.mock.calls).toMatchInlineSnapshot(`
         [
@@ -179,18 +174,16 @@ describe('unsafe pseudo classes', () => {
 
     test('does warn when not using the flag on the rule that follows a declaration', () => {
       expect(
-        renderer
-          .create(
-            <div
-              css={{
-                color: 'hotpink',
-                [`& > *:first-child`]: {
-                  marginLeft: 0
-                }
-              }}
-            />
-          )
-          .toJSON()
+        render(
+          <div
+            css={{
+              color: 'hotpink',
+              [`& > *:first-child`]: {
+                marginLeft: 0
+              }
+            }}
+          />
+        ).container.firstChild
       ).toMatchSnapshot()
       expect(console.error.mock.calls).toMatchInlineSnapshot(`
         [
@@ -203,18 +196,16 @@ describe('unsafe pseudo classes', () => {
 
     test('does warn when not using the flag on the rule that preceeds a declaration', () => {
       expect(
-        renderer
-          .create(
-            <div
-              css={{
-                [`& > *:first-child`]: {
-                  marginLeft: 0
-                },
-                color: 'hotpink'
-              }}
-            />
-          )
-          .toJSON()
+        render(
+          <div
+            css={{
+              [`& > *:first-child`]: {
+                marginLeft: 0
+              },
+              color: 'hotpink'
+            }}
+          />
+        ).container.firstChild
       ).toMatchSnapshot()
       expect(console.error.mock.calls).toMatchInlineSnapshot(`
         [
@@ -226,19 +217,15 @@ describe('unsafe pseudo classes', () => {
     })
 
     test('does warn when not using the flag on a global rule', () => {
-      expect(
-        renderer
-          .create(
-            <Global
-              styles={{
-                [`body > *:first-child`]: {
-                  marginLeft: 0
-                }
-              }}
-            />
-          )
-          .toJSON()
-      ).toMatchSnapshot()
+      render(
+        <Global
+          styles={{
+            [`body > *:first-child`]: {
+              marginLeft: 0
+            }
+          }}
+        />
+      )
       expect(console.error.mock.calls).toMatchInlineSnapshot(`
         [
           [
@@ -250,112 +237,98 @@ describe('unsafe pseudo classes', () => {
 
     test('does not warn when using the flag on the rule that follows another rule', () => {
       expect(
-        renderer
-          .create(
-            <div
-              css={{
-                '& > *': {
-                  marginLeft: 10
-                },
-                [`& > *:first-child${ignoreSsrFlag}`]: {
-                  marginLeft: 0
-                }
-              }}
-            />
-          )
-          .toJSON()
+        render(
+          <div
+            css={{
+              '& > *': {
+                marginLeft: 10
+              },
+              [`& > *:first-child${ignoreSsrFlag}`]: {
+                marginLeft: 0
+              }
+            }}
+          />
+        ).container.firstChild
       ).toMatchSnapshot()
       expect(console.error).not.toBeCalled()
     })
 
     test('does not warn when using the flag on the rule that preceeds another rule', () => {
       expect(
-        renderer
-          .create(
-            <div
-              css={{
-                [`& > *:first-child${ignoreSsrFlag}`]: {
-                  marginLeft: 0
-                },
-                '& > *': {
-                  marginLeft: 10
-                }
-              }}
-            />
-          )
-          .toJSON()
+        render(
+          <div
+            css={{
+              [`& > *:first-child${ignoreSsrFlag}`]: {
+                marginLeft: 0
+              },
+              '& > *': {
+                marginLeft: 10
+              }
+            }}
+          />
+        ).container.firstChild
       ).toMatchSnapshot()
       expect(console.error).not.toBeCalled()
     })
 
     test('does not warn when using the flag on the rule that follows a declaration', () => {
       expect(
-        renderer
-          .create(
-            <div
-              css={{
-                color: 'hotpink',
-                [`& > *:first-child${ignoreSsrFlag}`]: {
-                  marginLeft: 0
-                }
-              }}
-            />
-          )
-          .toJSON()
+        render(
+          <div
+            css={{
+              color: 'hotpink',
+              [`& > *:first-child${ignoreSsrFlag}`]: {
+                marginLeft: 0
+              }
+            }}
+          />
+        ).container.firstChild
       ).toMatchSnapshot()
       expect(console.error).not.toBeCalled()
     })
 
     test('does not warn when using the flag on the rule that preceeds a declaration', () => {
       expect(
-        renderer
-          .create(
-            <div
-              css={{
-                [`& > *:first-child${ignoreSsrFlag}`]: {
-                  marginLeft: 0
-                },
-                color: 'hotpink'
-              }}
-            />
-          )
-          .toJSON()
+        render(
+          <div
+            css={{
+              [`& > *:first-child${ignoreSsrFlag}`]: {
+                marginLeft: 0
+              },
+              color: 'hotpink'
+            }}
+          />
+        ).container.firstChild
       ).toMatchSnapshot()
       expect(console.error).not.toBeCalled()
     })
 
     test('does not warn when using the flag on a global rule', () => {
-      expect(
-        renderer
-          .create(
-            <Global
-              styles={{
-                [`body > *:first-child${ignoreSsrFlag}`]: {
-                  marginLeft: 0
-                }
-              }}
-            />
-          )
-          .toJSON()
-      ).toMatchSnapshot()
+      render(
+        <Global
+          styles={{
+            [`body > *:first-child${ignoreSsrFlag}`]: {
+              marginLeft: 0
+            }
+          }}
+        />
+      )
       expect(console.error).not.toBeCalled()
     })
 
     test('does warn when not using the flag on a rule that is defined in another one', () => {
       expect(
-        renderer
-          .create(
-            <div
-              css={css`
-                div {
-                  span:first-child {
-                    border-bottom-left-radius: 0;
-                  }
+        render(
+          <div
+            css={css`
+              div {
+                span:first-child {
+                  border-bottom-left-radius: 0;
                 }
-              `}
-            />
-          )
-          .toJSON()
+              }
+            `}
+          />
+        ).container.firstChild
       ).toMatchSnapshot()
       expect(console.error.mock.calls).toMatchInlineSnapshot(`
         [
@@ -368,19 +341,17 @@ describe('unsafe pseudo classes', () => {
 
     test('does not warn when using the flag on a rule that is defined in another one', () => {
       expect(
-        renderer
-          .create(
-            <div
-              css={css`
-                div {
-                  span:first-child${ignoreSsrFlag} {
-                    border-bottom-left-radius: 0;
-                  }
+        render(
+          <div
+            css={css`
+              div {
+                span:first-child${ignoreSsrFlag} {
+                  border-bottom-left-radius: 0;
                 }
-              `}
-            />
-          )
-          .toJSON()
+              }
+            `}
+          />
+        ).container.firstChild
       ).toMatchSnapshot()
       expect(console.error).not.toBeCalled()
     })
@@ -388,22 +359,18 @@ describe('unsafe pseudo classes', () => {
 })
 
 test('global with css prop', () => {
-  let tree = renderer
-    .create(
-      <Global
-        css={{
-          html: {
-            backgroundColor: 'hotpink'
-          },
-          '@font-face': {
-            fontFamily: 'some-name'
-          }
-        }}
-      />
-    )
-    .toJSON()
-  expect(tree).toMatchSnapshot()
-
+  render(
+    <Global
+      css={{
+        html: {
+          backgroundColor: 'hotpink'
+        },
+        '@font-face': {
+          fontFamily: 'some-name'
+        }
+      }}
+    />
+  )
   expect(console.error).toBeCalledWith(
     "It looks like you're using the css prop on Global, did you mean to use the styles prop instead?"
   )
@@ -442,9 +409,7 @@ test('keyframes interpolated into plain string', () => {
     }
   })
 
-  renderer.create(
-    <div css={[`animation: ${animateColor} 10s ${rotate360} 5s;`]} />
-  )
+  render(<div css={[`animation: ${animateColor} 10s ${rotate360} 5s;`]} />)
   expect(console.error.mock.calls).toMatchInlineSnapshot(`
             [
               [
@@ -509,7 +474,7 @@ test('`css` opaque object passed to `cx` from <ClassNames/>', () => {
 })
 
 test('@import nested in scoped `css`', () => {
-  renderer.create(
+  render(
     <div
       css={css`
         @import url('https://some-url');
@@ -531,7 +496,7 @@ test('@import nested in scoped `css`', () => {
 })
 
 test('@import prepended with other rules', () => {
-  renderer.create(
+  render(
     <Global
       styles={css`
         h1 {
@@ -553,7 +518,7 @@ test('@import prepended with other rules', () => {
 })
 
 test('@import prepended by other @import', () => {
-  renderer.create(
+  render(
     <Global
       styles={css`
         @import url('https://some-url');
@@ -566,7 +531,7 @@ test('@import prepended by other @import', () => {
 })
 
 test('when using `jsx` multiple static children should not result in a key-related warning', () => {
-  renderer.create(
+  render(
     <div css={{ color: 'hotpink' }}>
       <div />
       <div />
diff --git a/packages/react/__tests__/with-theme.js b/packages/react/__tests__/with-theme.js
index 78c4944590..5fc1eb3124 100644
--- a/packages/react/__tests__/with-theme.js
+++ b/packages/react/__tests__/with-theme.js
@@ -1,5 +1,5 @@
-import * as React from 'react'
-import * as renderer from 'react-test-renderer'
+import React from 'react'
+import { render } from '@testing-library/react'
 import { withTheme, ThemeProvider } from '@emotion/react'
 
 test('withTheme works', () => {
@@ -10,24 +10,22 @@ test('withTheme works', () => {
   }
   let SomeComponentWithTheme = withTheme(SomeComponent)
   expect(
-    renderer
-      .create(
-        <ThemeProvider theme={{ color: 'green' }}>
-          <SomeComponentWithTheme />
-        </ThemeProvider>
-      )
-      .toJSON()
+    render(
+      <ThemeProvider theme={{ color: 'green' }}>
+        <SomeComponentWithTheme />
+      </ThemeProvider>
+    ).container.firstChild
   ).toMatchSnapshot()
 })
 
-test.skip('should forward the ref', () => {
+test('should forward the ref', () => {
   function SomeComponent(props) {
     return <div ref={props.ref}>{props.theme.color}</div>
   }
 
   const ComponentWithTheme = withTheme(SomeComponent)
   let ref = React.createRef()
-  renderer.create(
+  render(
     <ThemeProvider theme={{ color: 'green' }}>
       <ComponentWithTheme ref={ref} />
     </ThemeProvider>
diff --git a/packages/react/package.json b/packages/react/package.json
index eaa93caaa9..ee5b873c25 100644
--- a/packages/react/package.json
+++ b/packages/react/package.json
@@ -215,7 +215,7 @@
     "@emotion/weak-memoize": "^0.4.0"
   },
   "peerDependencies": {
-    "react": ">=16.8.0"
+    "react": "^19.0.0"
   },
   "peerDependenciesMeta": {
     "@types/react": {
@@ -229,7 +229,7 @@
     "@emotion/server": "11.11.0",
     "@emotion/styled": "11.14.0",
     "html-tag-names": "^1.1.2",
-    "react": "16.14.0",
+    "react": "19.0.0",
     "svg-tag-names": "^1.1.1",
     "typescript": "^5.4.5"
   },
diff --git a/packages/react/src/global.tsx b/packages/react/src/global.tsx
index 77e1952e84..f1627662f0 100644
--- a/packages/react/src/global.tsx
+++ b/packages/react/src/global.tsx
@@ -1,11 +1,10 @@
-import * as React from 'react'
+import React from 'react'
 import isDevelopment from '#is-development'
 import { withEmotionCache } from './context'
 import { Theme, ThemeContext } from './theming'
 import { insertStyles } from '@emotion/utils'
 import { Options as SheetOptions, StyleSheet } from '@emotion/sheet'
 import isBrowser from '#is-browser'
-import { useInsertionEffectWithLayoutFallback } from '@emotion/use-insertion-effect-with-fallbacks'
 
 import { Interpolation, serializeStyles } from '@emotion/serialize'
 
@@ -84,9 +83,9 @@ export let Global = /* #__PURE__ */ withEmotionCache<GlobalProps>(
 
     let sheetRef = React.useRef<
       [sheet: StyleSheet, isRehydrating: boolean] | undefined
-    >()
+    >(undefined)
 
-    useInsertionEffectWithLayoutFallback(() => {
+    React.useInsertionEffect(() => {
       const key = `${cache.key}-global`
 
       // use case of https://github.com/emotion-js/emotion/issues/2675
@@ -117,7 +116,7 @@ export let Global = /* #__PURE__ */ withEmotionCache<GlobalProps>(
       }
     }, [cache])
 
-    useInsertionEffectWithLayoutFallback(() => {
+    React.useInsertionEffect(() => {
       let sheetRefCurrent = sheetRef.current!
       let [sheet, rehydrating] = sheetRefCurrent
       if (rehydrating) {
diff --git a/packages/react/src/jsx-namespace.ts b/packages/react/src/jsx-namespace.ts
index 5bfd22c1e4..d7b5916e7c 100644
--- a/packages/react/src/jsx-namespace.ts
+++ b/packages/react/src/jsx-namespace.ts
@@ -1,106 +1,32 @@
-import 'react'
+import React from 'react'
 import { Interpolation } from '@emotion/serialize'
 import { Theme } from './theming'
 
-type IsPreReact19 = 2 extends Parameters<React.FunctionComponent<any>>['length']
-  ? true
-  : false
-
 type WithConditionalCSSProp<P> = 'className' extends keyof P
   ? string extends P['className' & keyof P]
     ? { css?: Interpolation<Theme> }
     : {}
   : {}
 
-// unpack all here to avoid infinite self-referencing when defining our own JSX namespace for the pre-React 19 case
-
-// the IsPreReact19 and @ts-ignore comments are to allow @emotion/react to support three different cases of types
-// - pre-React 18.something which didn't have `React.JSX`
-// - React 18.something with `React.JSX`
-// - React 19 with `React.JSX` and no global `JSX`
-// we support both pre-React 19 cases by using the global `JSX` and with the React 19 types, we use `React.JSX`
-// to make this work, we need @ts-ignore comments to ignore references that are invalid
-// though note that the error types resulting from ignoring the errors will never be used
-// since the pre vs post React 19 conditional will pick the one that won't error
-
-// prettier-ignore
-/** @ts-ignore */
-type ReactJSXElement = true extends IsPreReact19 ? JSX.Element : React.JSX.Element
-
-// prettier-ignore
-/** @ts-ignore */
-type ReactJSXElementClass = true extends IsPreReact19 ? JSX.ElementClass : React.JSX.ElementClass
-
-// prettier-ignore
-/** @ts-ignore */
-type ReactJSXElementAttributesProperty = true extends IsPreReact19 ? JSX.ElementAttributesProperty : React.JSX.ElementAttributesProperty
-
-// prettier-ignore
-/** @ts-ignore */
-type ReactJSXElementChildrenAttribute = true extends IsPreReact19 ? JSX.ElementChildrenAttribute : React.JSX.ElementChildrenAttribute
-
-// prettier-ignore
-/** @ts-ignore */
-type ReactJSXLibraryManagedAttributes<C, P> = true extends IsPreReact19 ? JSX.LibraryManagedAttributes<C, P> : React.JSX.LibraryManagedAttributes<C, P>
-
-// prettier-ignore
-/** @ts-ignore */
-type ReactJSXIntrinsicAttributes = true extends IsPreReact19 ? JSX.IntrinsicAttributes : React.JSX.IntrinsicAttributes
-
-// prettier-ignore
-/** @ts-ignore */
-type ReactJSXIntrinsicClassAttributes<T> = true extends IsPreReact19 ? JSX.IntrinsicClassAttributes<T> : React.JSX.IntrinsicClassAttributes<T>
-
-// prettier-ignore
-/** @ts-ignore */
-type ReactJSXIntrinsicElements = true extends IsPreReact19 ? JSX.IntrinsicElements : React.JSX.IntrinsicElements
-
-// based on the code from @types/react@18.2.8
-// https://github.com/DefinitelyTyped/DefinitelyTyped/blob/3197efc097d522c4bf02b94e1a0766d007d6cdeb/types/react/index.d.ts#LL3204C13-L3204C13
-// prettier-ignore
-/** @ts-ignore */
-type ReactJSXElementType = true extends IsPreReact19 ? string | React.JSXElementConstructor<any> : React.JSX.ElementType
-
-export namespace ReactJSX {
-  export type ElementType = ReactJSXElementType
-  export interface Element extends ReactJSXElement {}
-  export interface ElementClass extends ReactJSXElementClass {}
-  export interface ElementAttributesProperty
-    extends ReactJSXElementAttributesProperty {}
-  export interface ElementChildrenAttribute
-    extends ReactJSXElementChildrenAttribute {}
-
-  export type LibraryManagedAttributes<C, P> = ReactJSXLibraryManagedAttributes<
-    C,
-    P
-  >
-
-  export interface IntrinsicAttributes extends ReactJSXIntrinsicAttributes {}
-  export interface IntrinsicClassAttributes<T>
-    extends ReactJSXIntrinsicClassAttributes<T> {}
-
-  export type IntrinsicElements = ReactJSXIntrinsicElements
-}
-
 export namespace EmotionJSX {
-  export type ElementType = ReactJSXElementType
-  export interface Element extends ReactJSXElement {}
-  export interface ElementClass extends ReactJSXElementClass {}
+  export type ElementType = React.JSX.ElementType
+  export interface Element extends React.JSX.Element {}
+  export interface ElementClass extends React.JSX.ElementClass {}
   export interface ElementAttributesProperty
-    extends ReactJSXElementAttributesProperty {}
+    extends React.JSX.ElementAttributesProperty {}
   export interface ElementChildrenAttribute
-    extends ReactJSXElementChildrenAttribute {}
+    extends React.JSX.ElementChildrenAttribute {}
 
   export type LibraryManagedAttributes<C, P> = P extends unknown
-    ? WithConditionalCSSProp<P> & ReactJSXLibraryManagedAttributes<C, P>
+    ? WithConditionalCSSProp<P> & React.JSX.LibraryManagedAttributes<C, P>
     : never
 
-  export interface IntrinsicAttributes extends ReactJSXIntrinsicAttributes {}
+  export interface IntrinsicAttributes extends React.JSX.IntrinsicAttributes {}
   export interface IntrinsicClassAttributes<T>
-    extends ReactJSXIntrinsicClassAttributes<T> {}
+    extends React.JSX.IntrinsicClassAttributes<T> {}
 
   export type IntrinsicElements = {
-    [K in keyof ReactJSXIntrinsicElements]: ReactJSXIntrinsicElements[K] & {
+    [K in keyof React.JSX.IntrinsicElements]: React.JSX.IntrinsicElements[K] & {
       css?: Interpolation<Theme>
     }
   }
diff --git a/packages/react/types/index.d.ts b/packages/react/types/index.d.ts
index 343fcf296e..c2bb25fe48 100644
--- a/packages/react/types/index.d.ts
+++ b/packages/react/types/index.d.ts
@@ -1,2 +1,2 @@
-// TypeScript Version: 4.1
+// TypeScript Version: 5.1
 export * from '..'
diff --git a/packages/react/types/tests-theming.tsx b/packages/react/types/tests-theming.tsx
index 0519d3fd0c..af70dc8bf5 100644
--- a/packages/react/types/tests-theming.tsx
+++ b/packages/react/types/tests-theming.tsx
@@ -1,5 +1,5 @@
 // Definitions by: Junyoung Clare Jang <https://github.com/Ailrun>
-// TypeScript Version: 3.1
+// TypeScript Version: 5.0
 
 import * as React from 'react'
 import { useTheme, ThemeProvider, withTheme, Theme } from '@emotion/react'
diff --git a/packages/react/types/tests.tsx b/packages/react/types/tests.tsx
index b3bd3179a7..7d3749f95e 100644
--- a/packages/react/types/tests.tsx
+++ b/packages/react/types/tests.tsx
@@ -198,30 +198,6 @@ const anim1 = keyframes`
   />
 }
 
-{
-  // based on the code from @types/react@17.x
-  // https://github.com/DefinitelyTyped/DefinitelyTyped/blob/98fa4486aefd5a1916aa385402467a7157e3c73f/types/react/v17/index.d.ts#L540-L548
-  type OldFC<P = {}> = OldFunctionComponent<P>
-  interface OldFunctionComponent<P = {}> {
-    (
-      props: React.PropsWithChildren<P>,
-      context?: any
-    ): React.ReactElement<any, any> | null
-    propTypes?: React.WeakValidationMap<P> | undefined
-    contextTypes?: React.ValidationMap<any> | undefined
-    defaultProps?: Partial<P> | undefined
-    displayName?: string | undefined
-  }
-  // https://github.com/DefinitelyTyped/DefinitelyTyped/issues/40993
-  // this is really problematic behaviour by @types/react@<18 IMO
-  // but it's what @types/react did so let's not break it.
-  const CompWithImplicitChildren: OldFC = () => null
-  ;<CompWithImplicitChildren>
-    content
-    <div />
-  </CompWithImplicitChildren>
-}
-
 // Tests for WithConditionalCSSProp
 {
   const WithOptionalClassName = (props: { className?: string }) => null
diff --git a/packages/server/test/inline.test.js b/packages/server/test/inline.test.js
index 0378b0c5a2..b5f551b0ad 100644
--- a/packages/server/test/inline.test.js
+++ b/packages/server/test/inline.test.js
@@ -1,8 +1,4 @@
-import {
-  stripDataReactRoot,
-  disableBrowserEnvTemporarily,
-  safeQuerySelector
-} from 'test-utils'
+import { disableBrowserEnvTemporarily, safeQuerySelector } from 'test-utils'
 
 let React
 let renderToString
@@ -51,18 +47,18 @@ describe('renderStylesToString', () => {
       )
 
       expect(output).toEqual(expect.not.stringContaining('undefined'))
-      expect(stripDataReactRoot(output)).toMatchSnapshot()
+      expect(output).toMatchSnapshot()
     })
   })
-  test('renders large recursive component', async () => {
+
+  // blocked on https://github.com/facebook/react/issues/31754
+  test.skip('renders large recursive component', async () => {
     await disableBrowserEnvTemporarily(() => {
       resetAllModules()
       const BigComponent = util.createBigComponent(emotion)
       expect(
-        stripDataReactRoot(
-          emotionServer.renderStylesToString(
-            renderToString(<BigComponent count={200} />)
-          )
+        emotionServer.renderStylesToString(
+          renderToString(<BigComponent count={200} />)
         )
       ).toMatchSnapshot()
     })
diff --git a/packages/server/test/stream.test.js b/packages/server/test/stream.test.js
index 6c95301bb2..f6242519cf 100644
--- a/packages/server/test/stream.test.js
+++ b/packages/server/test/stream.test.js
@@ -1,8 +1,6 @@
-import {
-  stripDataReactRoot,
-  disableBrowserEnvTemporarily,
-  safeQuerySelector
-} from 'test-utils'
+import { disableBrowserEnvTemporarily, safeQuerySelector } from 'test-utils'
+
+globalThis.setImmediate ??= cb => setTimeout(cb, 0)
 
 let React
 let renderToString
@@ -36,16 +34,16 @@ describe('renderStylesToNodeStream', () => {
       ).toMatchSnapshot()
     })
   })
-  test('renders large recursive component', async () => {
+
+  // blocked on https://github.com/facebook/react/issues/31754
+  test.skip('renders large recursive component', async () => {
     await disableBrowserEnvTemporarily(async () => {
       resetAllModules()
       const BigComponent = util.createBigComponent(emotion)
       expect(
-        stripDataReactRoot(
-          await util.renderToStringWithStream(
-            <BigComponent count={200} />,
-            emotionServer
-          )
+        await util.renderToStringWithStream(
+          <BigComponent count={200} />,
+          emotionServer
         )
       ).toMatchSnapshot()
     })
diff --git a/packages/server/test/util.js b/packages/server/test/util.js
index 2a9a045a80..1563001d36 100644
--- a/packages/server/test/util.js
+++ b/packages/server/test/util.js
@@ -2,8 +2,10 @@
 import * as React from 'react'
 import prettify from '@emotion/css-prettifier'
 /* import type { Emotion } from '@emotion/css/create-instance' */
-import { renderToNodeStream } from 'react-dom/server'
+import { renderToPipeableStream } from 'react-dom/server'
 import HTMLSerializer from 'jest-serializer-html'
+import { Buffer } from 'buffer'
+import { Transform } from 'stream'
 
 /*
 type EmotionServer = {
@@ -215,12 +217,24 @@ export const getInjectedRules = () =>
       .join('')
   )
 
+class TransformToBuffer extends Transform {
+  constructor() {
+    super({ readableObjectMode: false, writableObjectMode: false })
+  }
+  _transform(chunk, encoding, callback) {
+    this.push(!Buffer.isBuffer(chunk) ? Buffer.from(chunk) : chunk)
+    callback()
+  }
+}
+
 export const renderToStringWithStream = (
   element /*: React.Element<*> */,
   { renderStylesToNodeStream } /*: EmotionServer */
 ) /*: Promise<string> */ =>
   new Promise((resolve, reject) => {
-    const stream = renderToNodeStream(element).pipe(renderStylesToNodeStream())
+    const stream = renderStylesToNodeStream()
+    const { pipe } = renderToPipeableStream(element)
+    pipe(new TransformToBuffer()).pipe(stream)
     let html = ''
     stream.on('data', data => {
       html += data.toString()
diff --git a/packages/server/types/create-instance.d.ts b/packages/server/types/create-instance.d.ts
index 1e11db8bc0..b1586b3538 100644
--- a/packages/server/types/create-instance.d.ts
+++ b/packages/server/types/create-instance.d.ts
@@ -1,5 +1,5 @@
 // Definitions by: Junyoung Clare Jang <https://github.com/Ailrun>
-// TypeScript Version: 2.8
+// TypeScript Version: 5.0
 
 /// <reference types="node" preserve="true" />
 import { EmotionCache } from '@emotion/utils'
diff --git a/packages/server/types/index.d.ts b/packages/server/types/index.d.ts
index 4acb432821..7b3dd584f7 100644
--- a/packages/server/types/index.d.ts
+++ b/packages/server/types/index.d.ts
@@ -1,5 +1,5 @@
 // Definitions by: Junyoung Clare Jang <https://github.com/Ailrun>
-// TypeScript Version: 2.8
+// TypeScript Version: 5.0
 
 import { EmotionServer } from '@emotion/server/create-instance'
 
diff --git a/packages/styled/__tests__/__snapshots__/edge-cases.js.snap b/packages/styled/__tests__/__snapshots__/edge-cases.js.snap
index 7f2962d6b1..9ffd72ea73 100644
--- a/packages/styled/__tests__/__snapshots__/edge-cases.js.snap
+++ b/packages/styled/__tests__/__snapshots__/edge-cases.js.snap
@@ -9,7 +9,7 @@ exports[`nested function using css 1`] = `
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 />
 `;
 
@@ -30,6 +30,6 @@ exports[`nested function using css and keyframes 1`] = `
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 />
 `;
diff --git a/packages/styled/__tests__/__snapshots__/styled.js.snap b/packages/styled/__tests__/__snapshots__/styled.js.snap
index 79db824663..7546e156c5 100644
--- a/packages/styled/__tests__/__snapshots__/styled.js.snap
+++ b/packages/styled/__tests__/__snapshots__/styled.js.snap
@@ -13,7 +13,7 @@ exports[`styled basic render 1`] = `
 }
 
 <h1
-  className="emotion-0"
+  class="emotion-0"
 >
   hello world
 </h1>
@@ -25,7 +25,7 @@ exports[`styled basic render with object as style 1`] = `
 }
 
 <h1
-  className="emotion-0"
+  class="emotion-0"
 >
   hello world
 </h1>
@@ -37,7 +37,7 @@ exports[`styled call expression 1`] = `
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 >
   hello world
 </div>
@@ -57,10 +57,10 @@ exports[`styled component selectors 1`] = `
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 >
   <div
-    className="emotion-1 emotion-2"
+    class="emotion-1 emotion-2"
   />
 </div>
 `;
@@ -80,7 +80,7 @@ exports[`styled composing components 1`] = `
 }
 
 <button
-  className="emotion-0"
+  class="emotion-0"
 >
   hello world
 </button>
@@ -93,7 +93,7 @@ exports[`styled composition 1`] = `
 }
 
 <h1
-  className="legacy__class emotion-0"
+  class="legacy__class emotion-0"
 >
   hello world
 </h1>
@@ -109,8 +109,8 @@ exports[`styled composition 2`] = `
 }
 
 <h1
-  className="legacy__class emotion-0"
-  scale={2}
+  class="legacy__class emotion-0"
+  scale="2"
 >
   hello world
 </h1>
@@ -122,7 +122,7 @@ exports[`styled composition based on props 1`] = `
 }
 
 <h1
-  className="emotion-0"
+  class="emotion-0"
 >
   hello world
 </h1>
@@ -134,7 +134,7 @@ exports[`styled composition based on props 2`] = `
 }
 
 <h1
-  className="emotion-0"
+  class="emotion-0"
 >
   hello world
 </h1>
@@ -167,7 +167,7 @@ exports[`styled composition of nested pseudo selectors 1`] = `
 }
 
 <button
-  className="emotion-0"
+  class="emotion-0"
 >
   Should be purple
 </button>
@@ -180,8 +180,8 @@ exports[`styled function in expression 1`] = `
 }
 
 <h1
-  className="legacy__class emotion-0"
-  scale={2}
+  class="legacy__class emotion-0"
+  scale="2"
 >
   hello world
 </h1>
@@ -200,8 +200,8 @@ exports[`styled glamorous style api & composition 1`] = `
 }
 
 <h1
-  className="emotion-0"
-  fontSize={20}
+  class="emotion-0"
+  font-size="20"
 >
   hello world
 </h1>
@@ -225,7 +225,7 @@ exports[`styled handles more than 10 dynamic properties 1`] = `
 }
 
 <h1
-  className="legacy__class emotion-0"
+  class="legacy__class emotion-0"
 >
   hello world
 </h1>
@@ -242,7 +242,7 @@ exports[`styled higher order component 1`] = `
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 />
 `;
 
@@ -252,7 +252,7 @@ exports[`styled inline function return value is a function 1`] = `
 }
 
 <h1
-  className="emotion-0"
+  class="emotion-0"
 >
   hello world
 </h1>
@@ -276,10 +276,9 @@ exports[`styled input placeholder 1`] = `
 }
 
 <input
-  className="emotion-0"
->
-  hello world
-</input>
+  class="emotion-0"
+  value="hello world"
+/>
 `;
 
 exports[`styled input placeholder object 1`] = `
@@ -300,10 +299,9 @@ exports[`styled input placeholder object 1`] = `
 }
 
 <input
-  className="emotion-0"
->
-  hello world
-</input>
+  class="emotion-0"
+  value="hello world"
+/>
 `;
 
 exports[`styled keyframes with css call 1`] = `
@@ -323,7 +321,7 @@ exports[`styled keyframes with css call 1`] = `
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 />
 `;
 
@@ -348,11 +346,11 @@ exports[`styled nested 1`] = `
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 >
   hello 
   <h1
-    className="emotion-1"
+    class="emotion-1"
   >
     This will be green
   </h1>
@@ -366,7 +364,7 @@ exports[`styled no dynamic 1`] = `
 }
 
 <h1
-  className="emotion-0"
+  class="emotion-0"
 >
   hello world
 </h1>
@@ -378,17 +376,17 @@ exports[`styled no prop filtering on non string tags 1`] = `
 }
 
 <a
-  a={true}
+  a="true"
   aria-label="some label"
-  b={true}
-  className="emotion-0"
-  cool={true}
+  b="true"
+  class="emotion-0"
+  cool="true"
   data-wow="value"
-  filtering={true}
+  filtering="true"
   href="link"
-  is={true}
-  prop={true}
-  wow={true}
+  is="true"
+  prop="true"
+  wow="true"
 >
   hello world
 </a>
@@ -399,26 +397,26 @@ exports[`styled no prop filtering on string tags started with upper case 1`] = `
   color: green;
 }
 
-<SomeCustomLink
-  a={true}
+<somecustomlink
+  a="true"
   aria-label="some label"
-  b={true}
-  className="emotion-0"
-  cool={true}
+  b="true"
+  class="emotion-0"
+  cool="true"
   data-wow="value"
-  filtering={true}
+  filtering="true"
   href="link"
-  is={true}
-  prop={true}
-  wow={true}
+  is="true"
+  prop="true"
+  wow="true"
 >
   hello world
-</SomeCustomLink>
+</somecustomlink>
 `;
 
 exports[`styled object as className 1`] = `
 <div
-  className="myclass emotion-0"
+  class="myclass emotion-0"
 />
 `;
 
@@ -435,8 +433,8 @@ exports[`styled object as style 1`] = `
 }
 
 <h1
-  className="emotion-0"
-  fontSize={20}
+  class="emotion-0"
+  font-size="20"
 >
   hello world
 </h1>
@@ -462,7 +460,7 @@ exports[`styled object composition 1`] = `
 }
 
 <img
-  className="emotion-0"
+  class="emotion-0"
 />
 `;
 
@@ -476,7 +474,7 @@ exports[`styled objects 1`] = `
 }
 
 <h1
-  className="emotion-0"
+  class="emotion-0"
   display="flex"
 >
   hello world
@@ -489,7 +487,7 @@ exports[`styled objects with spread properties 1`] = `
 }
 
 <figure
-  className="emotion-0"
+  class="emotion-0"
 >
   hello world
 </figure>
@@ -502,10 +500,10 @@ exports[`styled prop filtering 1`] = `
 
 <a
   aria-label="some label"
-  className="emotion-0"
+  class="emotion-0"
   data-wow="value"
   href="link"
-  is={true}
+  is="true"
 >
   hello world
 </a>
@@ -519,10 +517,10 @@ exports[`styled prop filtering on composed styled components that are string tag
 
 <a
   aria-label="some label"
-  className="emotion-0"
+  class="emotion-0"
   data-wow="value"
   href="link"
-  is={true}
+  is="true"
 >
   hello world
 </a>
@@ -534,7 +532,7 @@ exports[`styled random expressions undefined return 1`] = `
 }
 
 <h1
-  className="legacy__class emotion-0"
+  class="legacy__class emotion-0"
 >
   hello world
 </h1>
@@ -552,7 +550,7 @@ exports[`styled random object expression 1`] = `
 }
 
 <h1
-  className="legacy__class emotion-0"
+  class="legacy__class emotion-0"
 >
   hello world
 </h1>
@@ -564,7 +562,7 @@ exports[`styled same component rendered multiple times 1`] = `
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 />
 `;
 
@@ -574,13 +572,13 @@ exports[`styled same component rendered multiple times 2`] = `
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 >
   <div
-    className="emotion-0"
+    class="emotion-0"
   />
   <div
-    className="emotion-0"
+    class="emotion-0"
   />
 </div>
 `;
@@ -591,7 +589,7 @@ exports[`styled theming 1`] = `
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 >
   this should be hotpink
 </div>
@@ -613,7 +611,7 @@ exports[`styled with higher order component that hoists statics 1`] = `
 }
 
 <div
-  className="emotion-0"
+  class="emotion-0"
 />
 `;
 
@@ -624,7 +622,7 @@ exports[`styled withComponent does carry styles from flattened component 1`] = `
 }
 
 <p
-  className="emotion-0"
+  class="emotion-0"
 />
 `;
 
@@ -635,12 +633,12 @@ exports[`styled withComponent will replace tags but keep styling classes 1`] = `
 
 <article>
   <h1
-    className="emotion-0"
+    class="emotion-0"
   >
     My Title
   </h1>
   <h2
-    className="emotion-0"
+    class="emotion-0"
   >
     My Subtitle
   </h2>
@@ -654,12 +652,12 @@ exports[`styled withComponent with function interpolation 1`] = `
 
 <article>
   <h1
-    className="emotion-0"
+    class="emotion-0"
   >
     My Title
   </h1>
   <h2
-    className="emotion-0"
+    class="emotion-0"
   >
     My Subtitle
   </h2>
diff --git a/packages/styled/__tests__/edge-cases.js b/packages/styled/__tests__/edge-cases.js
index 30b08bf534..ed553629eb 100644
--- a/packages/styled/__tests__/edge-cases.js
+++ b/packages/styled/__tests__/edge-cases.js
@@ -1,6 +1,6 @@
 import 'test-utils/setup-env'
-import * as React from 'react'
-import renderer from 'react-test-renderer'
+import React from 'react'
+import { render } from '@testing-library/react'
 import styled from '@emotion/styled'
 import { css, keyframes } from '@emotion/react'
 
@@ -13,9 +13,9 @@ test('nested function using css', () => {
     `};
     padding: 30px;
   `
-  const tree = renderer.create(<Comp />)
+  const { container } = render(<Comp />)
 
-  expect(tree.toJSON()).toMatchSnapshot()
+  expect(container.firstChild).toMatchSnapshot()
 })
 
 test('nested function using css and keyframes', () => {
@@ -29,7 +29,7 @@ test('nested function using css and keyframes', () => {
       })};
     `};
   `
-  const tree = renderer.create(<Comp />)
+  const { container } = render(<Comp />)
 
-  expect(tree.toJSON()).toMatchSnapshot()
+  expect(container.firstChild).toMatchSnapshot()
 })
diff --git a/packages/styled/__tests__/styled-dom.js b/packages/styled/__tests__/styled-dom.js
index 2b4a00cdc1..91d35fae08 100644
--- a/packages/styled/__tests__/styled-dom.js
+++ b/packages/styled/__tests__/styled-dom.js
@@ -4,7 +4,7 @@ import { render, cleanup } from '@testing-library/react'
 
 afterEach(cleanup)
 
-test.skip('ref', () => {
+test('ref', () => {
   const H1 = styled.h1`
     font-size: 12px;
   `
diff --git a/packages/styled/__tests__/styled.js b/packages/styled/__tests__/styled.js
index 1890607fcb..a92a3ef0f6 100644
--- a/packages/styled/__tests__/styled.js
+++ b/packages/styled/__tests__/styled.js
@@ -1,22 +1,23 @@
 /** @jsx jsx */
 import 'test-utils/setup-env'
-import renderer from 'react-test-renderer'
+import { render } from '@testing-library/react'
+import { act } from 'react'
 import hoistNonReactStatics from 'hoist-non-react-statics'
 import styled from '@emotion/styled'
 import { jsx, keyframes, css, ThemeProvider } from '@emotion/react'
 
 describe('styled', () => {
-  test('no dynamic', () => {
+  test('no dynamic', async () => {
     const H1 = styled.h1`
       float: left;
     `
 
-    const tree = renderer.create(<H1>hello world</H1>).toJSON()
+    const { container } = render(<H1>hello world</H1>)
 
-    expect(tree).toMatchSnapshot()
+    expect(container.firstChild).toMatchSnapshot()
   })
 
-  test('basic render', () => {
+  test('basic render', async () => {
     const fontSize = 20
     const H1 = styled.h1`
       color: blue;
@@ -26,21 +27,21 @@ describe('styled', () => {
       }
     `
 
-    const tree = renderer.create(<H1>hello world</H1>).toJSON()
+    const { container } = render(<H1>hello world</H1>)
 
-    expect(tree).toMatchSnapshot()
+    expect(container.firstChild).toMatchSnapshot()
   })
 
-  test('basic render with object as style', () => {
+  test('basic render with object as style', async () => {
     const fontSize = 20
     const H1 = styled.h1({ fontSize })
 
-    const tree = renderer.create(<H1>hello world</H1>).toJSON()
+    const { container } = render(<H1>hello world</H1>)
 
-    expect(tree).toMatchSnapshot()
+    expect(container.firstChild).toMatchSnapshot()
   })
 
-  test('object as style', () => {
+  test('object as style', async () => {
     const H1 = styled.h1(
       props => ({
         fontSize: props.fontSize
@@ -49,66 +50,62 @@ describe('styled', () => {
       { display: 'flex' }
     )
 
-    const tree = renderer
-      .create(
-        <H1 fontSize={20} flex={1}>
-          hello world
-        </H1>
-      )
-      .toJSON()
+    const { container } = render(
+      <H1 fontSize={20} flex={1}>
+        hello world
+      </H1>
+    )
 
-    expect(tree).toMatchSnapshot()
+    expect(container.firstChild).toMatchSnapshot()
   })
 
-  test('object as className', () => {
+  test('object as className', async () => {
     const myclass = { toString: () => 'myclass' }
     const Comp = styled.div``
 
-    const tree = renderer.create(<Comp className={myclass} />).toJSON()
+    const { container } = render(<Comp className={myclass} />)
 
-    expect(tree).toMatchSnapshot()
+    expect(container.firstChild).toMatchSnapshot()
   })
 
-  test('glamorous style api & composition', () => {
+  test('glamorous style api & composition', async () => {
     const H1 = styled.h1(props => ({ fontSize: props.fontSize }))
     const H2 = styled(H1)(props => ({ flex: props.flex }), {
       display: 'flex'
     })
 
-    const tree = renderer
-      .create(
-        <H2 fontSize={20} flex={1}>
-          hello world
-        </H2>
-      )
-      .toJSON()
+    const { container } = render(
+      <H2 fontSize={20} flex={1}>
+        hello world
+      </H2>
+    )
 
-    expect(tree).toMatchSnapshot()
+    expect(container.firstChild).toMatchSnapshot()
   })
 
-  test('inline function return value is a function', () => {
+  test('inline function return value is a function', async () => {
     const fontSize = () => 20
     const Blue = styled('h1')`
       font-size: ${() => fontSize}px;
     `
 
-    const tree = renderer.create(<Blue>hello world</Blue>).toJSON()
+    const { container } = render(<Blue>hello world</Blue>)
 
-    expect(tree).toMatchSnapshot()
+    expect(container.firstChild).toMatchSnapshot()
   })
 
-  test('call expression', () => {
+  test('call expression', async () => {
     const fontSize = 20
     const Div = styled('div')`
       font-size: ${fontSize}px;
     `
 
-    const tree = renderer.create(<Div>hello world</Div>).toJSON()
+    const { container } = render(<Div>hello world</Div>)
 
-    expect(tree).toMatchSnapshot()
+    expect(container.firstChild).toMatchSnapshot()
   })
 
-  test('nested', () => {
+  test('nested', async () => {
     const fontSize = '20px'
     const H1 = styled.h1`
       font-size: ${fontSize};
@@ -125,18 +122,16 @@ describe('styled', () => {
       }
     `
 
-    const tree = renderer
-      .create(
-        <Thing>
-          hello <H1>This will be green</H1> world
-        </Thing>
-      )
-      .toJSON()
+    const { container } = render(
+      <Thing>
+        hello <H1>This will be green</H1> world
+      </Thing>
+    )
 
-    expect(tree).toMatchSnapshot()
+    expect(container.firstChild).toMatchSnapshot()
   })
 
-  test('random expressions undefined return', () => {
+  test('random expressions undefined return', async () => {
     const H1 = styled('h1')`
       ${props =>
         props.prop &&
@@ -146,14 +141,14 @@ describe('styled', () => {
       color: green;
     `
 
-    const tree = renderer
-      .create(<H1 className={'legacy__class'}>hello world</H1>)
-      .toJSON()
+    const { container } = render(
+      <H1 className={'legacy__class'}>hello world</H1>
+    )
 
-    expect(tree).toMatchSnapshot()
+    expect(container.firstChild).toMatchSnapshot()
   })
 
-  test('random object expression', () => {
+  test('random object expression', async () => {
     const margin = (t, r, b, l) => {
       return props => ({
         marginTop: t,
@@ -169,18 +164,16 @@ describe('styled', () => {
       color: green;
     `
 
-    const tree = renderer
-      .create(
-        <H1 className={'legacy__class'} prop>
-          hello world
-        </H1>
-      )
-      .toJSON()
+    const { container } = render(
+      <H1 className={'legacy__class'} prop>
+        hello world
+      </H1>
+    )
 
-    expect(tree).toMatchSnapshot()
+    expect(container.firstChild).toMatchSnapshot()
   })
 
-  test('composition', () => {
+  test('composition', async () => {
     const fontSize = 20
     const H1 = styled('h1')`
       font-size: ${fontSize + 'px'};
@@ -190,36 +183,41 @@ describe('styled', () => {
       font-size: ${(fontSize * 2) / 3 + 'px'};
     `
 
-    const tree = renderer
-      .create(<H2 className={'legacy__class'}>hello world</H2>)
-      .toJSON()
-    expect(tree).toMatchSnapshot()
+    const { container } = render(
+      <H2 className={'legacy__class'}>hello world</H2>
+    )
+
+    expect(container.firstChild).toMatchSnapshot()
   })
 
-  test('input placeholder', () => {
+  test('input placeholder', async () => {
     const Input = styled.input`
       ::placeholder {
         background-color: green;
       }
     `
-    const tree = renderer.create(<Input>hello world</Input>).toJSON()
+    const { container } = render(
+      <Input value="hello world" onChange={() => {}} />
+    )
 
-    expect(tree).toMatchSnapshot()
+    expect(container.firstChild).toMatchSnapshot()
   })
 
-  test('input placeholder object', () => {
+  test('input placeholder object', async () => {
     const Input = styled('input')({
       '::placeholder': {
         backgroundColor: 'green'
       }
     })
 
-    const tree = renderer.create(<Input>hello world</Input>).toJSON()
+    const { container } = render(
+      <Input value="hello world" onChange={() => {}} />
+    )
 
-    expect(tree).toMatchSnapshot()
+    expect(container.firstChild).toMatchSnapshot()
   })
 
-  test('object composition', () => {
+  test('object composition', async () => {
     const imageStyles = css({ width: 96, height: 96 })
 
     css([{ color: 'blue' }])
@@ -245,12 +243,12 @@ describe('styled', () => {
       ${blue};
     `
 
-    const tree = renderer.create(<Avatar />).toJSON()
+    const { container } = render(<Avatar />)
 
-    expect(tree).toMatchSnapshot()
+    expect(container.firstChild).toMatchSnapshot()
   })
 
-  test('handles more than 10 dynamic properties', () => {
+  test('handles more than 10 dynamic properties', async () => {
     const H1 = styled('h1')`
       text-decoration: ${'underline'};
       border-right: solid blue 54px;
@@ -266,18 +264,16 @@ describe('styled', () => {
       border-left: ${p => p.theme.blue};
     `
 
-    const tree = renderer
-      .create(
-        <H1 className={'legacy__class'} theme={{ blue: 'blue' }}>
-          hello world
-        </H1>
-      )
-      .toJSON()
+    const { container } = render(
+      <H1 className={'legacy__class'} theme={{ blue: 'blue' }}>
+        hello world
+      </H1>
+    )
 
-    expect(tree).toMatchSnapshot()
+    expect(container.firstChild).toMatchSnapshot()
   })
 
-  test('function in expression', () => {
+  test('function in expression', async () => {
     const fontSize = 20
     const H1 = styled('h1', { label: 'H1' })`
       font-size: ${fontSize + 'px'};
@@ -287,18 +283,16 @@ describe('styled', () => {
       font-size: ${({ scale }) => fontSize * scale + 'px'};
     `
 
-    const tree = renderer
-      .create(
-        <H2 scale={2} className={'legacy__class'}>
-          hello world
-        </H2>
-      )
-      .toJSON()
+    const { container } = render(
+      <H2 scale={2} className={'legacy__class'}>
+        hello world
+      </H2>
+    )
 
-    expect(tree).toMatchSnapshot()
+    expect(container.firstChild).toMatchSnapshot()
   })
 
-  test('composition', () => {
+  test('composition', async () => {
     const fontSize = '20px'
 
     const cssA = css`
@@ -320,18 +314,16 @@ describe('styled', () => {
       font-size: 32px;
     `
 
-    const tree = renderer
-      .create(
-        <FinalH2 scale={2} className={'legacy__class'}>
-          hello world
-        </FinalH2>
-      )
-      .toJSON()
+    const { container } = render(
+      <FinalH2 scale={2} className={'legacy__class'}>
+        hello world
+      </FinalH2>
+    )
 
-    expect(tree).toMatchSnapshot()
+    expect(container.firstChild).toMatchSnapshot()
   })
 
-  test('higher order component', () => {
+  test('higher order component', async () => {
     const fontSize = 20
     const Content = styled('div')`
       font-size: ${fontSize}px;
@@ -353,12 +345,12 @@ describe('styled', () => {
 
     const ColumnContent = flexColumn(Content)
 
-    const tree = renderer.create(<ColumnContent />).toJSON()
+    const { container } = render(<ColumnContent />)
 
-    expect(tree).toMatchSnapshot()
+    expect(container.firstChild).toMatchSnapshot()
   })
 
-  test('composition based on props', () => {
+  test('composition based on props', async () => {
     const cssA = css`
       color: blue;
     `
@@ -371,15 +363,15 @@ describe('styled', () => {
       ${props => (props.a ? cssA : cssB)};
     `
 
-    const tree = renderer.create(<H1 a>hello world</H1>).toJSON()
+    const { container: container1 } = render(<H1 a>hello world</H1>)
 
-    expect(tree).toMatchSnapshot()
-    const tree2 = renderer.create(<H1>hello world</H1>).toJSON()
+    expect(container1.firstChild).toMatchSnapshot()
+    const { container: container2 } = render(<H1>hello world</H1>)
 
-    expect(tree2).toMatchSnapshot()
+    expect(container2.firstChild).toMatchSnapshot()
   })
 
-  test('composition of nested pseudo selectors', () => {
+  test('composition of nested pseudo selectors', async () => {
     const defaultLinkStyles = {
       '&:hover': {
         color: 'blue',
@@ -397,46 +389,44 @@ describe('styled', () => {
 
     const Button = styled('button')(buttonStyles)
 
-    const tree = renderer
-      .create(
-        <Button
-          css={css({
-            '&:hover': {
-              color: 'pink',
-              '&:active': {
-                color: 'purple'
-              },
-              '&.some-class': {
-                color: 'yellow'
-              }
+    const { container } = render(
+      <Button
+        css={css({
+          '&:hover': {
+            color: 'pink',
+            '&:active': {
+              color: 'purple'
+            },
+            '&.some-class': {
+              color: 'yellow'
             }
-          })}
-        >
-          Should be purple
-        </Button>
-      )
-      .toJSON()
-    expect(tree).toMatchSnapshot()
+          }
+        })}
+      >
+        Should be purple
+      </Button>
+    )
+    expect(container.firstChild).toMatchSnapshot()
   })
 
-  test('objects', () => {
+  test('objects', async () => {
     const H1 = styled('h1')({ padding: 10 }, props => ({
       display: props.display
     }))
-    const tree = renderer.create(<H1 display="flex">hello world</H1>).toJSON()
+    const { container } = render(<H1 display="flex">hello world</H1>)
 
-    expect(tree).toMatchSnapshot()
+    expect(container.firstChild).toMatchSnapshot()
   })
 
-  test('objects with spread properties', () => {
+  test('objects with spread properties', async () => {
     const defaultText = { fontSize: 20 }
     const Figure = styled.figure({ ...defaultText })
-    const tree = renderer.create(<Figure>hello world</Figure>).toJSON()
+    const { container } = render(<Figure>hello world</Figure>)
 
-    expect(tree).toMatchSnapshot()
+    expect(container.firstChild).toMatchSnapshot()
   })
 
-  test('composing components', () => {
+  test('composing components', async () => {
     const Button = styled.button`
       color: green;
     `
@@ -448,14 +438,12 @@ describe('styled', () => {
       display: flex;
       justify-content: center;
     `
-    const tree = renderer
-      .create(<AnotherButton>hello world</AnotherButton>)
-      .toJSON()
+    const { container } = render(<AnotherButton>hello world</AnotherButton>)
 
-    expect(tree).toMatchSnapshot()
+    expect(container.firstChild).toMatchSnapshot()
   })
 
-  test('with higher order component that hoists statics', () => {
+  test('with higher order component that hoists statics', async () => {
     const superImportantValue = 'hotpink'
     const hoc = BaseComponent => {
       const NewComponent = props => (
@@ -470,93 +458,87 @@ describe('styled', () => {
     const FinalComponent = styled(SomeComponent)`
       padding: 8px;
     `
-    const tree = renderer.create(<FinalComponent />).toJSON()
-    expect(tree).toMatchSnapshot()
+    const { container } = render(<FinalComponent />)
+    expect(container.firstChild).toMatchSnapshot()
   })
 
-  test('prop filtering', () => {
+  test('prop filtering', async () => {
     const Link = styled.a`
       color: green;
     `
     const rest = { m: [3], pt: [4] }
 
-    const tree = renderer
-      .create(
-        <Link
-          a
-          b
-          wow
-          prop
-          filtering
-          is
-          cool
-          aria-label="some label"
-          data-wow="value"
-          href="link"
-          {...rest}
-        >
-          hello world
-        </Link>
-      )
-      .toJSON()
+    const { container } = render(
+      <Link
+        a="true"
+        b="true"
+        wow="true"
+        prop="true"
+        filtering="true"
+        is="true"
+        cool="true"
+        aria-label="some label"
+        data-wow="value"
+        href="link"
+        {...rest}
+      >
+        hello world
+      </Link>
+    )
 
-    expect(tree).toMatchSnapshot()
+    expect(container.firstChild).toMatchSnapshot()
   })
-  test('no prop filtering on non string tags', () => {
+  test('no prop filtering on non string tags', async () => {
     const Link = styled(props => <a {...props} />)`
       color: green;
     `
 
-    const tree = renderer
-      .create(
-        <Link
-          a
-          b
-          wow
-          prop
-          filtering
-          is
-          cool
-          aria-label="some label"
-          data-wow="value"
-          href="link"
-        >
-          hello world
-        </Link>
-      )
-      .toJSON()
+    const { container } = render(
+      <Link
+        a="true"
+        b="true"
+        wow="true"
+        prop="true"
+        filtering="true"
+        is="true"
+        cool="true"
+        aria-label="some label"
+        data-wow="value"
+        href="link"
+      >
+        hello world
+      </Link>
+    )
 
-    expect(tree).toMatchSnapshot()
+    expect(container.firstChild).toMatchSnapshot()
   })
 
-  test('no prop filtering on string tags started with upper case', () => {
+  test('no prop filtering on string tags started with upper case', async () => {
     const Link = styled('SomeCustomLink')`
       color: green;
     `
 
-    const tree = renderer
-      .create(
-        <Link
-          a
-          b
-          wow
-          prop
-          filtering
-          is
-          cool
-          aria-label="some label"
-          data-wow="value"
-          href="link"
-        >
-          hello world
-        </Link>
-      )
-      .toJSON()
+    const { container } = render(
+      <Link
+        a="true"
+        b="true"
+        wow="true"
+        prop="true"
+        filtering="true"
+        is="true"
+        cool="true"
+        aria-label="some label"
+        data-wow="value"
+        href="link"
+      >
+        hello world
+      </Link>
+    )
 
-    expect(tree).toMatchSnapshot()
+    expect(container.firstChild).toMatchSnapshot()
   })
 
-  test('prop filtering on composed styled components that are string tags', () => {
+  test('prop filtering on composed styled components that are string tags', async () => {
     const BaseLink = styled.a`
       background-color: hotpink;
     `
@@ -564,71 +546,65 @@ describe('styled', () => {
       color: green;
     `
 
-    const tree = renderer
-      .create(
-        <Link
-          a
-          b
-          wow
-          prop
-          filtering
-          is
-          cool
-          aria-label="some label"
-          data-wow="value"
-          href="link"
-        >
-          hello world
-        </Link>
-      )
-      .toJSON()
+    const { container } = render(
+      <Link
+        a="true"
+        b="true"
+        wow="true"
+        prop="true"
+        filtering="true"
+        is="true"
+        cool="true"
+        aria-label="some label"
+        data-wow="value"
+        href="link"
+      >
+        hello world
+      </Link>
+    )
 
-    expect(tree).toMatchSnapshot()
+    expect(container.firstChild).toMatchSnapshot()
   })
 
-  test('throws if undefined is passed as the component', () => {
+  test('throws if undefined is passed as the component', async () => {
     expect(
       () => styled(undefined)`
         display: flex;
       `
     ).toThrowErrorMatchingSnapshot()
   })
-  test('withComponent will replace tags but keep styling classes', () => {
+  test('withComponent will replace tags but keep styling classes', async () => {
     const Title = styled('h1')`
       color: green;
     `
     const Subtitle = Title.withComponent('h2')
 
-    const tree = renderer
-      .create(
-        <article>
-          <Title>My Title</Title>
-          <Subtitle>My Subtitle</Subtitle>
-        </article>
-      )
-      .toJSON()
+    const { container } = render(
+      <article>
+        <Title>My Title</Title>
+        <Subtitle>My Subtitle</Subtitle>
+      </article>
+    )
 
-    expect(tree).toMatchSnapshot()
+    expect(container.firstChild).toMatchSnapshot()
   })
-  test('withComponent with function interpolation', () => {
+  test('withComponent with function interpolation', async () => {
     const Title = styled('h1')`
       color: ${props => props.color || 'green'};
     `
     const Subtitle = Title.withComponent('h2')
 
-    const tree = renderer
-      .create(
-        <article>
-          <Title>My Title</Title>
-          <Subtitle>My Subtitle</Subtitle>
-        </article>
-      )
-      .toJSON()
+    const { container } = render(
+      <article>
+        <Title>My Title</Title>
+        <Subtitle>My Subtitle</Subtitle>
+      </article>
+    )
 
-    expect(tree).toMatchSnapshot()
+    expect(container.firstChild).toMatchSnapshot()
   })
 
-  test('withComponent does carry styles from flattened component', () => {
+  test('withComponent does carry styles from flattened component', async () => {
     const SomeComponent = styled.div`
       color: green;
     `
@@ -636,45 +612,38 @@ describe('styled', () => {
       color: hotpink;
     `
     const OneMoreComponent = AnotherComponent.withComponent('p')
-    const tree = renderer.create(<OneMoreComponent />).toJSON()
-    expect(tree).toMatchSnapshot()
+    const { container } = render(<OneMoreComponent />)
+    expect(container.firstChild).toMatchSnapshot()
   })
 
-  test('theming', () => {
+  test('theming', async () => {
     const Div = styled.div`
       color: ${props => props.theme.primary};
     `
-    const tree = renderer
-      .create(
-        <ThemeProvider theme={{ primary: 'hotpink' }}>
-          <Div>this should be hotpink</Div>
-        </ThemeProvider>
-      )
-      .toJSON()
-    expect(tree).toMatchSnapshot()
+    const { container } = render(
+      <ThemeProvider theme={{ primary: 'hotpink' }}>
+        <Div>this should be hotpink</Div>
+      </ThemeProvider>
+    )
+    expect(container.firstChild).toMatchSnapshot()
   })
-  test('same component rendered multiple times', () => {
+  test('same component rendered multiple times', async () => {
     const SomeComponent = styled.div`
       color: green;
     `
 
-    const tree = renderer.create(<SomeComponent />).toJSON()
-    expect(tree).toMatchSnapshot()
-    expect(renderer.create(<SomeComponent />).toJSON()).toEqual(
-      renderer.create(<SomeComponent />).toJSON()
-    )
+    const { container } = render(<SomeComponent />)
+    expect(container.firstChild).toMatchSnapshot()
     expect(
-      renderer
-        .create(
-          <SomeComponent>
-            <SomeComponent />
-            <SomeComponent />
-          </SomeComponent>
-        )
-        .toJSON()
+      render(
+        <SomeComponent>
+          <SomeComponent />
+          <SomeComponent />
+        </SomeComponent>
+      ).container.firstChild
     ).toMatchSnapshot()
   })
-  test('component selectors', () => {
+  test('component selectors', async () => {
     let Target = styled('div', {
       // if anyone is looking this
       // please don't do this.
@@ -690,22 +659,20 @@ describe('styled', () => {
       }
     `
     expect(
-      renderer
-        .create(
-          <SomeComponent>
-            <Target />
-          </SomeComponent>
-        )
-        .toJSON()
+      render(
+        <SomeComponent>
+          <Target />
+        </SomeComponent>
+      ).container.firstChild
     ).toMatchSnapshot()
   })
-  test('keyframes with css call', () => {
+  test('keyframes with css call', async () => {
     let SomeComp = styled.div(css`
       animation: ${keyframes({
         'from,to': { color: 'green' },
         '50%': { color: 'hotpink' }
       })};
     `)
-    expect(renderer.create(<SomeComp />).toJSON()).toMatchSnapshot()
+    expect(render(<SomeComp />).container.firstChild).toMatchSnapshot()
   })
 })
diff --git a/packages/styled/package.json b/packages/styled/package.json
index c9686f24e9..73426edad5 100644
--- a/packages/styled/package.json
+++ b/packages/styled/package.json
@@ -20,7 +20,7 @@
   },
   "peerDependencies": {
     "@emotion/react": "^11.0.0-rc.0",
-    "react": ">=16.8.0"
+    "react": "^19.0.0"
   },
   "peerDependenciesMeta": {
     "@types/react": {
@@ -32,7 +32,7 @@
     "@emotion/react": "11.14.0",
     "@types/hoist-non-react-statics": "^3.3.5",
     "hoist-non-react-statics": "^3.3.1",
-    "react": "16.14.0",
+    "react": "19.0.0",
     "typescript": "^5.4.5"
   },
   "publishConfig": {
diff --git a/packages/styled/src/index.ts b/packages/styled/src/index.ts
index 2d8877ff1a..d1ea418d95 100644
--- a/packages/styled/src/index.ts
+++ b/packages/styled/src/index.ts
@@ -1,6 +1,6 @@
+import React from 'react'
 import { Theme } from '@emotion/react'
 import styled from './base'
-import { ReactJSXIntrinsicElements } from './jsx-namespace'
 import { tags } from './tags'
 import {
   CreateStyledComponent,
@@ -21,12 +21,12 @@ export type {
 } from './types'
 
 export type StyledTags = {
-  [Tag in keyof ReactJSXIntrinsicElements]: CreateStyledComponent<
+  [Tag in keyof React.JSX.IntrinsicElements]: CreateStyledComponent<
     {
       theme?: Theme
       as?: React.ElementType
     },
-    ReactJSXIntrinsicElements[Tag]
+    React.JSX.IntrinsicElements[Tag]
   >
 }
 
diff --git a/packages/styled/src/jsx-namespace.ts b/packages/styled/src/jsx-namespace.ts
deleted file mode 100644
index 612e28f115..0000000000
--- a/packages/styled/src/jsx-namespace.ts
+++ /dev/null
@@ -1,12 +0,0 @@
-// this is basically a slimmed down copy of https://github.com/emotion-js/emotion/blob/main/packages/react/types/jsx-namespace.d.ts
-// it helps to avoid issues when combining newer `@emotion/styled` and older `@emotion/react` versions
-// in such setup, ReactJSX namespace won't exist in `@emotion/react` and that would lead to errors
-import 'react'
-
-type IsPreReact19 = 2 extends Parameters<React.FunctionComponent<any>>['length']
-  ? true
-  : false
-
-// prettier-ignore
-/** @ts-ignore */
-export type ReactJSXIntrinsicElements = true extends IsPreReact19 ? JSX.IntrinsicElements : React.JSX.IntrinsicElements
diff --git a/packages/styled/src/types.ts b/packages/styled/src/types.ts
index b66897604a..b1fb5bb946 100644
--- a/packages/styled/src/types.ts
+++ b/packages/styled/src/types.ts
@@ -1,5 +1,5 @@
+import React from 'react'
 import { ComponentSelector, Interpolation } from '@emotion/serialize'
-import { ReactJSXIntrinsicElements } from './jsx-namespace'
 import { Theme } from '@emotion/react'
 
 /** Same as StyledOptions but shouldForwardProp must be a type guard */
@@ -38,9 +38,9 @@ export interface StyledComponent<
   withComponent<C extends React.ComponentType<React.ComponentProps<C>>>(
     component: C
   ): StyledComponent<ComponentProps & React.ComponentProps<C>>
-  withComponent<Tag extends keyof ReactJSXIntrinsicElements>(
+  withComponent<Tag extends keyof React.JSX.IntrinsicElements>(
     tag: Tag
-  ): StyledComponent<ComponentProps, ReactJSXIntrinsicElements[Tag]>
+  ): StyledComponent<ComponentProps, React.JSX.IntrinsicElements[Tag]>
 }
 
 /**
@@ -158,26 +158,26 @@ export interface CreateStyled {
   >
 
   <
-    Tag extends keyof ReactJSXIntrinsicElements,
-    ForwardedProps extends keyof ReactJSXIntrinsicElements[Tag] &
-      string = keyof ReactJSXIntrinsicElements[Tag] & string
+    Tag extends keyof React.JSX.IntrinsicElements,
+    ForwardedProps extends keyof React.JSX.IntrinsicElements[Tag] &
+      string = keyof React.JSX.IntrinsicElements[Tag] & string
   >(
     tag: Tag,
     options: FilteringStyledOptions<
-      ReactJSXIntrinsicElements[Tag],
+      React.JSX.IntrinsicElements[Tag],
       ForwardedProps
     >
   ): CreateStyledComponent<
     { theme?: Theme; as?: React.ElementType },
-    Pick<ReactJSXIntrinsicElements[Tag], ForwardedProps>
+    Pick<React.JSX.IntrinsicElements[Tag], ForwardedProps>
   >
 
-  <Tag extends keyof ReactJSXIntrinsicElements>(
+  <Tag extends keyof React.JSX.IntrinsicElements>(
     tag: Tag,
-    options?: StyledOptions<ReactJSXIntrinsicElements[Tag]>
+    options?: StyledOptions<React.JSX.IntrinsicElements[Tag]>
   ): CreateStyledComponent<
     { theme?: Theme; as?: React.ElementType },
-    ReactJSXIntrinsicElements[Tag]
+    React.JSX.IntrinsicElements[Tag]
   >
 }
 
diff --git a/packages/styled/test/__snapshots__/babel-plugin.test.js.snap b/packages/styled/test/__snapshots__/babel-plugin.test.js.snap
new file mode 100644
index 0000000000..d084dcdb8a
--- /dev/null
+++ b/packages/styled/test/__snapshots__/babel-plugin.test.js.snap
@@ -0,0 +1,11 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`config merging works even if it's referenced by variable 1`] = `
+<div>
+  <button
+    class="emotion-0 emotion-1"
+  >
+    not forwarded
+  </button>
+</div>
+`;
diff --git a/packages/styled/test/__snapshots__/component-selector.test.js.snap b/packages/styled/test/__snapshots__/component-selector.test.js.snap
index d9181b3f63..2c3b80fd73 100644
--- a/packages/styled/test/__snapshots__/component-selector.test.js.snap
+++ b/packages/styled/test/__snapshots__/component-selector.test.js.snap
@@ -17,11 +17,11 @@ exports[`component as selector (object syntax) 1`] = `
 }
 
 <div
-  className="emotion-0 emotion-1"
+  class="emotion-0 emotion-1"
 >
   hello 
   <h1
-    className="emotion-2 emotion-3"
+    class="emotion-2 emotion-3"
   >
     This will be green
   </h1>
@@ -46,11 +46,11 @@ exports[`component as selector 1`] = `
 }
 
 <div
-  className="emotion-0 emotion-1"
+  class="emotion-0 emotion-1"
 >
   hello 
   <h1
-    className="emotion-2 emotion-3"
+    class="emotion-2 emotion-3"
   >
     This will be green
   </h1>
@@ -75,13 +75,13 @@ exports[`component as selector function interpolation (object syntax) 1`] = `
 }
 
 <div
-  className="emotion-0 emotion-1"
-  fontSize={10}
+  class="emotion-0 emotion-1"
+  font-size="10"
 >
   hello 
   <h1
-    className="emotion-2 emotion-3"
-    fontSize={20}
+    class="emotion-2 emotion-3"
+    font-size="20"
   >
     This will be green
   </h1>
@@ -106,13 +106,13 @@ exports[`component as selector function interpolation 1`] = `
 }
 
 <div
-  className="emotion-0 emotion-1"
-  fontSize={10}
+  class="emotion-0 emotion-1"
+  font-size="10"
 >
   hello 
   <h1
-    className="emotion-2 emotion-3"
-    fontSize={20}
+    class="emotion-2 emotion-3"
+    font-size="20"
   >
     This will be green
   </h1>
diff --git a/packages/styled/test/__snapshots__/composition.test.js.snap b/packages/styled/test/__snapshots__/composition.test.js.snap
index abd0c0b8b2..019c5105d5 100644
--- a/packages/styled/test/__snapshots__/composition.test.js.snap
+++ b/packages/styled/test/__snapshots__/composition.test.js.snap
@@ -15,7 +15,7 @@ exports[`composing components 1`] = `
 }
 
 <button
-  className="emotion-0 emotion-1"
+  class="emotion-0 emotion-1"
 >
   hello world
 </button>
@@ -31,8 +31,8 @@ exports[`composition 1`] = `
 }
 
 <h1
-  className="legacy__class emotion-0 emotion-1"
-  scale={2}
+  class="legacy__class emotion-0 emotion-1"
+  scale="2"
 >
   hello world
 </h1>
@@ -45,7 +45,7 @@ exports[`composition 2`] = `
 }
 
 <h1
-  className="legacy__class emotion-0 emotion-1"
+  class="legacy__class emotion-0 emotion-1"
 >
   hello world
 </h1>
@@ -78,7 +78,7 @@ exports[`composition of nested pseudo selectors 1`] = `
 }
 
 <button
-  className="emotion-0 emotion-1"
+  class="emotion-0 emotion-1"
 >
   Should be purple
 </button>
@@ -100,8 +100,8 @@ exports[`composition with objects 1`] = `
 }
 
 <h1
-  className="legacy__class emotion-0 emotion-1"
-  scale={2}
+  class="legacy__class emotion-0 emotion-1"
+  scale="2"
 >
   hello world
 </h1>
@@ -120,8 +120,8 @@ exports[`glamorous style api & composition 1`] = `
 }
 
 <h1
-  className="emotion-0 emotion-1"
-  fontSize={20}
+  class="emotion-0 emotion-1"
+  font-size="20"
 >
   hello world
 </h1>
@@ -147,6 +147,6 @@ exports[`object composition 1`] = `
 }
 
 <img
-  className="emotion-0 emotion-1"
+  class="emotion-0 emotion-1"
 />
 `;
diff --git a/packages/styled/test/__snapshots__/index.test.js.snap b/packages/styled/test/__snapshots__/index.test.js.snap
index ea9b2bf5d5..f988c14394 100644
--- a/packages/styled/test/__snapshots__/index.test.js.snap
+++ b/packages/styled/test/__snapshots__/index.test.js.snap
@@ -13,7 +13,7 @@ exports[`styled basic render 1`] = `
 }
 
 <h1
-  className="emotion-0 emotion-1"
+  class="emotion-0 emotion-1"
 >
   hello world
 </h1>
@@ -25,7 +25,7 @@ exports[`styled basic render with object as style 1`] = `
 }
 
 <h1
-  className="emotion-0 emotion-1"
+  class="emotion-0 emotion-1"
 >
   hello world
 </h1>
@@ -37,7 +37,7 @@ exports[`styled call expression 1`] = `
 }
 
 <div
-  className="emotion-0 emotion-1"
+  class="emotion-0 emotion-1"
 >
   hello world
 </div>
@@ -49,7 +49,7 @@ exports[`styled composition based on props 1`] = `
 }
 
 <h1
-  className="emotion-0 emotion-1"
+  class="emotion-0 emotion-1"
 >
   hello world
 </h1>
@@ -61,7 +61,7 @@ exports[`styled composition based on props 2`] = `
 }
 
 <h1
-  className="emotion-0 emotion-1"
+  class="emotion-0 emotion-1"
 >
   hello world
 </h1>
@@ -74,8 +74,8 @@ exports[`styled function in expression 1`] = `
 }
 
 <h1
-  className="legacy__class emotion-0 emotion-1"
-  scale={2}
+  class="legacy__class emotion-0 emotion-1"
+  scale="2"
 >
   hello world
 </h1>
@@ -88,7 +88,7 @@ exports[`styled function that function returns gets called with props 1`] = `
 }
 
 <div
-  className="emotion-0 emotion-1"
+  class="emotion-0 emotion-1"
   color="hotpink"
 />
 `;
@@ -111,7 +111,7 @@ exports[`styled handles more than 10 dynamic properties 1`] = `
 }
 
 <h1
-  className="legacy__class emotion-0 emotion-1"
+  class="legacy__class emotion-0 emotion-1"
 >
   hello world
 </h1>
@@ -123,7 +123,7 @@ exports[`styled inline function return value is a function 1`] = `
 }
 
 <h1
-  className="emotion-0 emotion-1"
+  class="emotion-0 emotion-1"
 >
   hello world
 </h1>
@@ -147,10 +147,9 @@ exports[`styled input placeholder 1`] = `
 }
 
 <input
-  className="emotion-0 emotion-1"
->
-  hello world
-</input>
+  class="emotion-0 emotion-1"
+  value="hello world"
+/>
 `;
 
 exports[`styled input placeholder object 1`] = `
@@ -171,10 +170,9 @@ exports[`styled input placeholder object 1`] = `
 }
 
 <input
-  className="emotion-0 emotion-1"
->
-  hello world
-</input>
+  class="emotion-0 emotion-1"
+  value="hello world"
+/>
 `;
 
 exports[`styled nested 1`] = `
@@ -198,11 +196,11 @@ exports[`styled nested 1`] = `
 }
 
 <div
-  className="emotion-0 emotion-1"
+  class="emotion-0 emotion-1"
 >
   hello 
   <h1
-    className="emotion-2 emotion-3"
+    class="emotion-2 emotion-3"
   >
     This will be green
   </h1>
@@ -216,7 +214,7 @@ exports[`styled no dynamic 1`] = `
 }
 
 <h1
-  className="emotion-0 emotion-1"
+  class="emotion-0 emotion-1"
 >
   hello world
 </h1>
@@ -235,8 +233,8 @@ exports[`styled object as style 1`] = `
 }
 
 <h1
-  className="emotion-0 emotion-1"
-  fontSize={20}
+  class="emotion-0 emotion-1"
+  font-size="20"
 >
   hello world
 </h1>
@@ -252,7 +250,7 @@ exports[`styled objects 1`] = `
 }
 
 <h1
-  className="emotion-0 emotion-1"
+  class="emotion-0 emotion-1"
   display="flex"
 >
   hello world
@@ -265,7 +263,7 @@ exports[`styled objects with spread properties 1`] = `
 }
 
 <figure
-  className="emotion-0 emotion-1"
+  class="emotion-0 emotion-1"
 >
   hello world
 </figure>
@@ -277,7 +275,7 @@ exports[`styled random expressions undefined return 1`] = `
 }
 
 <h1
-  className="legacy__class emotion-0 emotion-1"
+  class="legacy__class emotion-0 emotion-1"
 >
   hello world
 </h1>
@@ -295,7 +293,7 @@ exports[`styled random object expression 1`] = `
 }
 
 <h1
-  className="legacy__class emotion-0 emotion-1"
+  class="legacy__class emotion-0 emotion-1"
 >
   hello world
 </h1>
@@ -307,7 +305,7 @@ exports[`styled ref 1`] = `
 }
 
 <h1
-  className="emotion-0 emotion-1"
+  class="emotion-0 emotion-1"
 >
   hello world
 </h1>
@@ -329,7 +327,7 @@ exports[`styled with higher order component that hoists statics 1`] = `
 }
 
 <div
-  className="emotion-0 emotion-1 emotion-2"
+  class="emotion-0 emotion-1 emotion-2"
 />
 `;
 
@@ -340,7 +338,7 @@ exports[`styled withComponent carries styles from flattened components 1`] = `
 }
 
 <p
-  className="emotion-0 emotion-1"
+  class="emotion-0 emotion-1"
 />
 `;
 
@@ -355,12 +353,12 @@ exports[`styled withComponent will replace tags but keep styling classes 1`] = `
 
 <article>
   <h1
-    className="emotion-0 emotion-1"
+    class="emotion-0 emotion-1"
   >
     My Title
   </h1>
   <h2
-    className="emotion-2 emotion-19"
+    class="emotion-2 emotion-19"
   >
     My Subtitle
   </h2>
@@ -378,12 +376,12 @@ exports[`styled withComponent with function interpolation 1`] = `
 
 <article>
   <h1
-    className="emotion-0 emotion-1"
+    class="emotion-0 emotion-1"
   >
     My Title
   </h1>
   <h2
-    className="emotion-2 emotion-3"
+    class="emotion-2 emotion-3"
     color="hotpink"
   >
     My Subtitle
diff --git a/packages/styled/test/__snapshots__/prop-filtering.test.js.snap b/packages/styled/test/__snapshots__/prop-filtering.test.js.snap
index 1ef597ea52..41acd95d97 100644
--- a/packages/styled/test/__snapshots__/prop-filtering.test.js.snap
+++ b/packages/styled/test/__snapshots__/prop-filtering.test.js.snap
@@ -2,8 +2,8 @@
 
 exports[`composes shouldForwardProp on composed styled components 1`] = `
 <div
-  className="emotion-0 emotion-1"
-  xyz={true}
+  class="emotion-0 emotion-1"
+  xyz="true"
 />
 `;
 
@@ -14,17 +14,13 @@ exports[`custom shouldForwardProp works 1`] = `
 }
 
 <svg
-  className="emotion-0 emotion-1"
+  class="emotion-0 emotion-1"
   height="100px"
   width="100px"
 >
   <rect
     height="100"
-    style={
-      {
-        "stroke": "#ff0000",
-      }
-    }
+    style="stroke: #ff0000;"
     width="100"
     x="10"
     y="10"
@@ -38,17 +34,17 @@ exports[`no prop filtering on non string tags 1`] = `
 }
 
 <a
-  a={true}
+  a="true"
   aria-label="some label"
-  b={true}
-  className="emotion-0 emotion-1"
-  cool={true}
+  b="true"
+  class="emotion-0 emotion-1"
+  cool="true"
   data-wow="value"
-  filtering={true}
+  filtering="true"
   href="link"
-  is={true}
-  prop={true}
-  wow={true}
+  is="true"
+  prop="true"
+  wow="true"
 >
   hello world
 </a>
@@ -59,21 +55,21 @@ exports[`no prop filtering on string tags started with upper case 1`] = `
   color: green;
 }
 
-<SomeCustomLink
-  a={true}
+<somecustomlink
+  a="true"
   aria-label="some label"
-  b={true}
-  className="emotion-0 emotion-1"
-  cool={true}
+  b="true"
+  class="emotion-0 emotion-1"
+  cool="true"
   data-wow="value"
-  filtering={true}
+  filtering="true"
   href="link"
-  is={true}
-  prop={true}
-  wow={true}
+  is="true"
+  prop="true"
+  wow="true"
 >
   hello world
-</SomeCustomLink>
+</somecustomlink>
 `;
 
 exports[`prop filtering 1`] = `
@@ -83,10 +79,10 @@ exports[`prop filtering 1`] = `
 
 <a
   aria-label="some label"
-  className="emotion-0 emotion-1"
+  class="emotion-0 emotion-1"
   data-wow="value"
   href="link"
-  is={true}
+  is="true"
 >
   hello world
 </a>
@@ -100,36 +96,26 @@ exports[`prop filtering on composed styled components that are string tags 1`] =
 
 <a
   aria-label="some label"
-  className="emotion-0 emotion-1"
+  class="emotion-0 emotion-1"
   data-wow="value"
   for="other reasons"
   href="link"
-  is={true}
-  kind={true}
+  is="true"
+  kind="true"
 >
   hello world
 </a>
 `;
 
 exports[`shouldForwardProp should get inherited for wrapped styled components 1`] = `
-[
-  .emotion-0 {
+.emotion-0 {
   background-color: red;
 }
 
 <div
-    className="emotion-0 emotion-1"
-    id="test-1"
-  />,
-  .emotion-0 {
-  background-color: green;
-}
-
-<div
-    className="emotion-0 emotion-1"
-    id="test-2"
-  />,
-]
+  class="emotion-0 emotion-1"
+  id="test-1"
+/>
 `;
 
 exports[`withComponent inherits explicit shouldForwardProp 1`] = `
@@ -138,8 +124,8 @@ exports[`withComponent inherits explicit shouldForwardProp 1`] = `
 }
 
 <span
-  className="emotion-0 emotion-1"
-  foo={true}
+  class="emotion-0 emotion-1"
+  foo="true"
 />
 `;
 
@@ -150,8 +136,8 @@ exports[`withComponent inherits explicit shouldForwardProp from flattened compon
 }
 
 <span
-  className="emotion-0 emotion-1"
-  foo={true}
+  class="emotion-0 emotion-1"
+  foo="true"
 />
 `;
 
@@ -161,8 +147,8 @@ exports[`withComponent should accept shouldForwardProp 1`] = `
 }
 
 <span
-  className="emotion-0 emotion-1"
-  xyz={true}
+  class="emotion-0 emotion-1"
+  xyz="true"
 />
 `;
 
@@ -172,9 +158,9 @@ exports[`withComponent should compose shouldForwardProp 1`] = `
 }
 
 <span
-  className="emotion-0 emotion-1"
-  qwe={true}
-  xyz={true}
+  class="emotion-0 emotion-1"
+  qwe="true"
+  xyz="true"
 />
 `;
 
@@ -184,8 +170,8 @@ exports[`withComponent should compose shouldForwardProp with a flattened compone
 }
 
 <span
-  className="emotion-0 emotion-1"
-  qwe={true}
-  xyz={true}
+  class="emotion-0 emotion-1"
+  qwe="true"
+  xyz="true"
 />
 `;
diff --git a/packages/styled/test/__snapshots__/source-map.test.js.snap b/packages/styled/test/__snapshots__/source-map.test.js.snap
index 7e199ee456..e387d33919 100644
--- a/packages/styled/test/__snapshots__/source-map.test.js.snap
+++ b/packages/styled/test/__snapshots__/source-map.test.js.snap
@@ -8,10 +8,16 @@ exports[`inserts source map 1`] = `
       data-s=""
     >
       
-      .css-1xjhfcy-Comp{color:hotpink;}/*# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInNvdXJjZS1tYXAudGVzdC5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFNdUIiLCJmaWxlIjoic291cmNlLW1hcC50ZXN0LmpzIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IFJlYWN0IGZyb20gJ3JlYWN0J1xuaW1wb3J0IHsgY3NzIH0gZnJvbSAnQGVtb3Rpb24vcmVhY3QnXG5pbXBvcnQgc3R5bGVkIGZyb20gJ0BlbW90aW9uL3N0eWxlZCdcbmltcG9ydCByZW5kZXJlciBmcm9tICdyZWFjdC10ZXN0LXJlbmRlcmVyJ1xuXG50ZXN0KCdpbnNlcnRzIHNvdXJjZSBtYXAnLCAoKSA9PiB7XG4gIGxldCBDb21wID0gc3R5bGVkLmRpdmBcbiAgICBjb2xvcjogaG90cGluaztcbiAgYFxuICByZW5kZXJlci5jcmVhdGUoPENvbXAgLz4pXG4gIGV4cGVjdChkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQpLnRvTWF0Y2hTbmFwc2hvdCgpXG59KVxuXG50ZXN0KCdzb3VyY2UgbWFwIHdpdGggY29tcG9zZWQgY29tcG9uZW50JywgKCkgPT4ge1xuICBsZXQgQ29tcCA9IHN0eWxlZC5kaXZgXG4gICAgY29sb3I6IGhvdHBpbms7XG4gIGBcbiAgbGV0IENvbXAyID0gc3R5bGVkKENvbXApYFxuICAgIGJhY2tncm91bmQ6IHllbGxvdztcbiAgYFxuICByZW5kZXJlci5jcmVhdGUoPENvbXAyIC8+KVxuICBleHBlY3QoZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50KS50b01hdGNoU25hcHNob3QoKVxufSlcblxudGVzdCgnc291cmNlIG1hcCB3aXRoIGNvbXBvc2VkIHN0eWxlJywgKCkgPT4ge1xuICBsZXQgc3R5bGUgPSBjc3MoeyBjb2xvcjogJ2dyZWVuJyB9KVxuICBsZXQgQ29tcDIgPSBzdHlsZWQuZGl2YFxuICAgIGJhY2tncm91bmQ6IHllbGxvdztcbiAgICAke3N0eWxlfVxuICBgXG4gIHJlbmRlcmVyLmNyZWF0ZSg8Q29tcDIgLz4pXG4gIGV4cGVjdChkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQpLnRvTWF0Y2hTbmFwc2hvdCgpXG59KVxuIl19 */
+      .css-baf0kh-Comp{color:hotpink;}/*# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInNvdXJjZS1tYXAudGVzdC5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFNdUIiLCJmaWxlIjoic291cmNlLW1hcC50ZXN0LmpzIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IFJlYWN0IGZyb20gJ3JlYWN0J1xuaW1wb3J0IHsgY3NzIH0gZnJvbSAnQGVtb3Rpb24vcmVhY3QnXG5pbXBvcnQgc3R5bGVkIGZyb20gJ0BlbW90aW9uL3N0eWxlZCdcbmltcG9ydCB7IHJlbmRlciB9IGZyb20gJ0B0ZXN0aW5nLWxpYnJhcnkvcmVhY3QnXG5cbnRlc3QoJ2luc2VydHMgc291cmNlIG1hcCcsICgpID0+IHtcbiAgbGV0IENvbXAgPSBzdHlsZWQuZGl2YFxuICAgIGNvbG9yOiBob3RwaW5rO1xuICBgXG4gIHJlbmRlcig8Q29tcCAvPilcbiAgZXhwZWN0KGRvY3VtZW50LmRvY3VtZW50RWxlbWVudCkudG9NYXRjaFNuYXBzaG90KClcbn0pXG5cbnRlc3QoJ3NvdXJjZSBtYXAgd2l0aCBjb21wb3NlZCBjb21wb25lbnQnLCAoKSA9PiB7XG4gIGxldCBDb21wID0gc3R5bGVkLmRpdmBcbiAgICBjb2xvcjogaG90cGluaztcbiAgYFxuICBsZXQgQ29tcDIgPSBzdHlsZWQoQ29tcClgXG4gICAgYmFja2dyb3VuZDogeWVsbG93O1xuICBgXG4gIHJlbmRlcig8Q29tcDIgLz4pXG4gIGV4cGVjdChkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQpLnRvTWF0Y2hTbmFwc2hvdCgpXG59KVxuXG50ZXN0KCdzb3VyY2UgbWFwIHdpdGggY29tcG9zZWQgc3R5bGUnLCAoKSA9PiB7XG4gIGxldCBzdHlsZSA9IGNzcyh7IGNvbG9yOiAnZ3JlZW4nIH0pXG4gIGxldCBDb21wMiA9IHN0eWxlZC5kaXZgXG4gICAgYmFja2dyb3VuZDogeWVsbG93O1xuICAgICR7c3R5bGV9XG4gIGBcbiAgcmVuZGVyKDxDb21wMiAvPilcbiAgZXhwZWN0KGRvY3VtZW50LmRvY3VtZW50RWxlbWVudCkudG9NYXRjaFNuYXBzaG90KClcbn0pXG4iXX0= */
     </style>
   </head>
-  <body />
+  <body>
+    <div>
+      <div
+        class="css-baf0kh-Comp e1gz73mp3"
+      />
+    </div>
+  </body>
 </html>
 `;
 
@@ -23,17 +29,23 @@ exports[`source map with composed component 1`] = `
       data-s=""
     >
       
-      .css-1xjhfcy-Comp{color:hotpink;}/*# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInNvdXJjZS1tYXAudGVzdC5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFNdUIiLCJmaWxlIjoic291cmNlLW1hcC50ZXN0LmpzIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IFJlYWN0IGZyb20gJ3JlYWN0J1xuaW1wb3J0IHsgY3NzIH0gZnJvbSAnQGVtb3Rpb24vcmVhY3QnXG5pbXBvcnQgc3R5bGVkIGZyb20gJ0BlbW90aW9uL3N0eWxlZCdcbmltcG9ydCByZW5kZXJlciBmcm9tICdyZWFjdC10ZXN0LXJlbmRlcmVyJ1xuXG50ZXN0KCdpbnNlcnRzIHNvdXJjZSBtYXAnLCAoKSA9PiB7XG4gIGxldCBDb21wID0gc3R5bGVkLmRpdmBcbiAgICBjb2xvcjogaG90cGluaztcbiAgYFxuICByZW5kZXJlci5jcmVhdGUoPENvbXAgLz4pXG4gIGV4cGVjdChkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQpLnRvTWF0Y2hTbmFwc2hvdCgpXG59KVxuXG50ZXN0KCdzb3VyY2UgbWFwIHdpdGggY29tcG9zZWQgY29tcG9uZW50JywgKCkgPT4ge1xuICBsZXQgQ29tcCA9IHN0eWxlZC5kaXZgXG4gICAgY29sb3I6IGhvdHBpbms7XG4gIGBcbiAgbGV0IENvbXAyID0gc3R5bGVkKENvbXApYFxuICAgIGJhY2tncm91bmQ6IHllbGxvdztcbiAgYFxuICByZW5kZXJlci5jcmVhdGUoPENvbXAyIC8+KVxuICBleHBlY3QoZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50KS50b01hdGNoU25hcHNob3QoKVxufSlcblxudGVzdCgnc291cmNlIG1hcCB3aXRoIGNvbXBvc2VkIHN0eWxlJywgKCkgPT4ge1xuICBsZXQgc3R5bGUgPSBjc3MoeyBjb2xvcjogJ2dyZWVuJyB9KVxuICBsZXQgQ29tcDIgPSBzdHlsZWQuZGl2YFxuICAgIGJhY2tncm91bmQ6IHllbGxvdztcbiAgICAke3N0eWxlfVxuICBgXG4gIHJlbmRlcmVyLmNyZWF0ZSg8Q29tcDIgLz4pXG4gIGV4cGVjdChkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQpLnRvTWF0Y2hTbmFwc2hvdCgpXG59KVxuIl19 */
+      .css-baf0kh-Comp{color:hotpink;}/*# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInNvdXJjZS1tYXAudGVzdC5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFNdUIiLCJmaWxlIjoic291cmNlLW1hcC50ZXN0LmpzIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IFJlYWN0IGZyb20gJ3JlYWN0J1xuaW1wb3J0IHsgY3NzIH0gZnJvbSAnQGVtb3Rpb24vcmVhY3QnXG5pbXBvcnQgc3R5bGVkIGZyb20gJ0BlbW90aW9uL3N0eWxlZCdcbmltcG9ydCB7IHJlbmRlciB9IGZyb20gJ0B0ZXN0aW5nLWxpYnJhcnkvcmVhY3QnXG5cbnRlc3QoJ2luc2VydHMgc291cmNlIG1hcCcsICgpID0+IHtcbiAgbGV0IENvbXAgPSBzdHlsZWQuZGl2YFxuICAgIGNvbG9yOiBob3RwaW5rO1xuICBgXG4gIHJlbmRlcig8Q29tcCAvPilcbiAgZXhwZWN0KGRvY3VtZW50LmRvY3VtZW50RWxlbWVudCkudG9NYXRjaFNuYXBzaG90KClcbn0pXG5cbnRlc3QoJ3NvdXJjZSBtYXAgd2l0aCBjb21wb3NlZCBjb21wb25lbnQnLCAoKSA9PiB7XG4gIGxldCBDb21wID0gc3R5bGVkLmRpdmBcbiAgICBjb2xvcjogaG90cGluaztcbiAgYFxuICBsZXQgQ29tcDIgPSBzdHlsZWQoQ29tcClgXG4gICAgYmFja2dyb3VuZDogeWVsbG93O1xuICBgXG4gIHJlbmRlcig8Q29tcDIgLz4pXG4gIGV4cGVjdChkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQpLnRvTWF0Y2hTbmFwc2hvdCgpXG59KVxuXG50ZXN0KCdzb3VyY2UgbWFwIHdpdGggY29tcG9zZWQgc3R5bGUnLCAoKSA9PiB7XG4gIGxldCBzdHlsZSA9IGNzcyh7IGNvbG9yOiAnZ3JlZW4nIH0pXG4gIGxldCBDb21wMiA9IHN0eWxlZC5kaXZgXG4gICAgYmFja2dyb3VuZDogeWVsbG93O1xuICAgICR7c3R5bGV9XG4gIGBcbiAgcmVuZGVyKDxDb21wMiAvPilcbiAgZXhwZWN0KGRvY3VtZW50LmRvY3VtZW50RWxlbWVudCkudG9NYXRjaFNuYXBzaG90KClcbn0pXG4iXX0= */
     </style>
     <style
       data-emotion="css"
       data-s=""
     >
       
-      .css-116dvkb-Comp-Comp2{color:hotpink;background:yellow;}/*# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInNvdXJjZS1tYXAudGVzdC5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFpQjBCIiwiZmlsZSI6InNvdXJjZS1tYXAudGVzdC5qcyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBSZWFjdCBmcm9tICdyZWFjdCdcbmltcG9ydCB7IGNzcyB9IGZyb20gJ0BlbW90aW9uL3JlYWN0J1xuaW1wb3J0IHN0eWxlZCBmcm9tICdAZW1vdGlvbi9zdHlsZWQnXG5pbXBvcnQgcmVuZGVyZXIgZnJvbSAncmVhY3QtdGVzdC1yZW5kZXJlcidcblxudGVzdCgnaW5zZXJ0cyBzb3VyY2UgbWFwJywgKCkgPT4ge1xuICBsZXQgQ29tcCA9IHN0eWxlZC5kaXZgXG4gICAgY29sb3I6IGhvdHBpbms7XG4gIGBcbiAgcmVuZGVyZXIuY3JlYXRlKDxDb21wIC8+KVxuICBleHBlY3QoZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50KS50b01hdGNoU25hcHNob3QoKVxufSlcblxudGVzdCgnc291cmNlIG1hcCB3aXRoIGNvbXBvc2VkIGNvbXBvbmVudCcsICgpID0+IHtcbiAgbGV0IENvbXAgPSBzdHlsZWQuZGl2YFxuICAgIGNvbG9yOiBob3RwaW5rO1xuICBgXG4gIGxldCBDb21wMiA9IHN0eWxlZChDb21wKWBcbiAgICBiYWNrZ3JvdW5kOiB5ZWxsb3c7XG4gIGBcbiAgcmVuZGVyZXIuY3JlYXRlKDxDb21wMiAvPilcbiAgZXhwZWN0KGRvY3VtZW50LmRvY3VtZW50RWxlbWVudCkudG9NYXRjaFNuYXBzaG90KClcbn0pXG5cbnRlc3QoJ3NvdXJjZSBtYXAgd2l0aCBjb21wb3NlZCBzdHlsZScsICgpID0+IHtcbiAgbGV0IHN0eWxlID0gY3NzKHsgY29sb3I6ICdncmVlbicgfSlcbiAgbGV0IENvbXAyID0gc3R5bGVkLmRpdmBcbiAgICBiYWNrZ3JvdW5kOiB5ZWxsb3c7XG4gICAgJHtzdHlsZX1cbiAgYFxuICByZW5kZXJlci5jcmVhdGUoPENvbXAyIC8+KVxuICBleHBlY3QoZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50KS50b01hdGNoU25hcHNob3QoKVxufSlcbiJdfQ== */
+      .css-fle4cv-Comp-Comp2{color:hotpink;background:yellow;}/*# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInNvdXJjZS1tYXAudGVzdC5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFpQjBCIiwiZmlsZSI6InNvdXJjZS1tYXAudGVzdC5qcyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBSZWFjdCBmcm9tICdyZWFjdCdcbmltcG9ydCB7IGNzcyB9IGZyb20gJ0BlbW90aW9uL3JlYWN0J1xuaW1wb3J0IHN0eWxlZCBmcm9tICdAZW1vdGlvbi9zdHlsZWQnXG5pbXBvcnQgeyByZW5kZXIgfSBmcm9tICdAdGVzdGluZy1saWJyYXJ5L3JlYWN0J1xuXG50ZXN0KCdpbnNlcnRzIHNvdXJjZSBtYXAnLCAoKSA9PiB7XG4gIGxldCBDb21wID0gc3R5bGVkLmRpdmBcbiAgICBjb2xvcjogaG90cGluaztcbiAgYFxuICByZW5kZXIoPENvbXAgLz4pXG4gIGV4cGVjdChkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQpLnRvTWF0Y2hTbmFwc2hvdCgpXG59KVxuXG50ZXN0KCdzb3VyY2UgbWFwIHdpdGggY29tcG9zZWQgY29tcG9uZW50JywgKCkgPT4ge1xuICBsZXQgQ29tcCA9IHN0eWxlZC5kaXZgXG4gICAgY29sb3I6IGhvdHBpbms7XG4gIGBcbiAgbGV0IENvbXAyID0gc3R5bGVkKENvbXApYFxuICAgIGJhY2tncm91bmQ6IHllbGxvdztcbiAgYFxuICByZW5kZXIoPENvbXAyIC8+KVxuICBleHBlY3QoZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50KS50b01hdGNoU25hcHNob3QoKVxufSlcblxudGVzdCgnc291cmNlIG1hcCB3aXRoIGNvbXBvc2VkIHN0eWxlJywgKCkgPT4ge1xuICBsZXQgc3R5bGUgPSBjc3MoeyBjb2xvcjogJ2dyZWVuJyB9KVxuICBsZXQgQ29tcDIgPSBzdHlsZWQuZGl2YFxuICAgIGJhY2tncm91bmQ6IHllbGxvdztcbiAgICAke3N0eWxlfVxuICBgXG4gIHJlbmRlcig8Q29tcDIgLz4pXG4gIGV4cGVjdChkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQpLnRvTWF0Y2hTbmFwc2hvdCgpXG59KVxuIl19 */
     </style>
   </head>
-  <body />
+  <body>
+    <div>
+      <div
+        class="css-fle4cv-Comp-Comp2 e1gz73mp1"
+      />
+    </div>
+  </body>
 </html>
 `;
 
@@ -45,23 +57,29 @@ exports[`source map with composed style 1`] = `
       data-s=""
     >
       
-      .css-1xjhfcy-Comp{color:hotpink;}/*# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInNvdXJjZS1tYXAudGVzdC5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFNdUIiLCJmaWxlIjoic291cmNlLW1hcC50ZXN0LmpzIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IFJlYWN0IGZyb20gJ3JlYWN0J1xuaW1wb3J0IHsgY3NzIH0gZnJvbSAnQGVtb3Rpb24vcmVhY3QnXG5pbXBvcnQgc3R5bGVkIGZyb20gJ0BlbW90aW9uL3N0eWxlZCdcbmltcG9ydCByZW5kZXJlciBmcm9tICdyZWFjdC10ZXN0LXJlbmRlcmVyJ1xuXG50ZXN0KCdpbnNlcnRzIHNvdXJjZSBtYXAnLCAoKSA9PiB7XG4gIGxldCBDb21wID0gc3R5bGVkLmRpdmBcbiAgICBjb2xvcjogaG90cGluaztcbiAgYFxuICByZW5kZXJlci5jcmVhdGUoPENvbXAgLz4pXG4gIGV4cGVjdChkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQpLnRvTWF0Y2hTbmFwc2hvdCgpXG59KVxuXG50ZXN0KCdzb3VyY2UgbWFwIHdpdGggY29tcG9zZWQgY29tcG9uZW50JywgKCkgPT4ge1xuICBsZXQgQ29tcCA9IHN0eWxlZC5kaXZgXG4gICAgY29sb3I6IGhvdHBpbms7XG4gIGBcbiAgbGV0IENvbXAyID0gc3R5bGVkKENvbXApYFxuICAgIGJhY2tncm91bmQ6IHllbGxvdztcbiAgYFxuICByZW5kZXJlci5jcmVhdGUoPENvbXAyIC8+KVxuICBleHBlY3QoZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50KS50b01hdGNoU25hcHNob3QoKVxufSlcblxudGVzdCgnc291cmNlIG1hcCB3aXRoIGNvbXBvc2VkIHN0eWxlJywgKCkgPT4ge1xuICBsZXQgc3R5bGUgPSBjc3MoeyBjb2xvcjogJ2dyZWVuJyB9KVxuICBsZXQgQ29tcDIgPSBzdHlsZWQuZGl2YFxuICAgIGJhY2tncm91bmQ6IHllbGxvdztcbiAgICAke3N0eWxlfVxuICBgXG4gIHJlbmRlcmVyLmNyZWF0ZSg8Q29tcDIgLz4pXG4gIGV4cGVjdChkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQpLnRvTWF0Y2hTbmFwc2hvdCgpXG59KVxuIl19 */
+      .css-baf0kh-Comp{color:hotpink;}/*# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInNvdXJjZS1tYXAudGVzdC5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFNdUIiLCJmaWxlIjoic291cmNlLW1hcC50ZXN0LmpzIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IFJlYWN0IGZyb20gJ3JlYWN0J1xuaW1wb3J0IHsgY3NzIH0gZnJvbSAnQGVtb3Rpb24vcmVhY3QnXG5pbXBvcnQgc3R5bGVkIGZyb20gJ0BlbW90aW9uL3N0eWxlZCdcbmltcG9ydCB7IHJlbmRlciB9IGZyb20gJ0B0ZXN0aW5nLWxpYnJhcnkvcmVhY3QnXG5cbnRlc3QoJ2luc2VydHMgc291cmNlIG1hcCcsICgpID0+IHtcbiAgbGV0IENvbXAgPSBzdHlsZWQuZGl2YFxuICAgIGNvbG9yOiBob3RwaW5rO1xuICBgXG4gIHJlbmRlcig8Q29tcCAvPilcbiAgZXhwZWN0KGRvY3VtZW50LmRvY3VtZW50RWxlbWVudCkudG9NYXRjaFNuYXBzaG90KClcbn0pXG5cbnRlc3QoJ3NvdXJjZSBtYXAgd2l0aCBjb21wb3NlZCBjb21wb25lbnQnLCAoKSA9PiB7XG4gIGxldCBDb21wID0gc3R5bGVkLmRpdmBcbiAgICBjb2xvcjogaG90cGluaztcbiAgYFxuICBsZXQgQ29tcDIgPSBzdHlsZWQoQ29tcClgXG4gICAgYmFja2dyb3VuZDogeWVsbG93O1xuICBgXG4gIHJlbmRlcig8Q29tcDIgLz4pXG4gIGV4cGVjdChkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQpLnRvTWF0Y2hTbmFwc2hvdCgpXG59KVxuXG50ZXN0KCdzb3VyY2UgbWFwIHdpdGggY29tcG9zZWQgc3R5bGUnLCAoKSA9PiB7XG4gIGxldCBzdHlsZSA9IGNzcyh7IGNvbG9yOiAnZ3JlZW4nIH0pXG4gIGxldCBDb21wMiA9IHN0eWxlZC5kaXZgXG4gICAgYmFja2dyb3VuZDogeWVsbG93O1xuICAgICR7c3R5bGV9XG4gIGBcbiAgcmVuZGVyKDxDb21wMiAvPilcbiAgZXhwZWN0KGRvY3VtZW50LmRvY3VtZW50RWxlbWVudCkudG9NYXRjaFNuYXBzaG90KClcbn0pXG4iXX0= */
     </style>
     <style
       data-emotion="css"
       data-s=""
     >
       
-      .css-116dvkb-Comp-Comp2{color:hotpink;background:yellow;}/*# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInNvdXJjZS1tYXAudGVzdC5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFpQjBCIiwiZmlsZSI6InNvdXJjZS1tYXAudGVzdC5qcyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBSZWFjdCBmcm9tICdyZWFjdCdcbmltcG9ydCB7IGNzcyB9IGZyb20gJ0BlbW90aW9uL3JlYWN0J1xuaW1wb3J0IHN0eWxlZCBmcm9tICdAZW1vdGlvbi9zdHlsZWQnXG5pbXBvcnQgcmVuZGVyZXIgZnJvbSAncmVhY3QtdGVzdC1yZW5kZXJlcidcblxudGVzdCgnaW5zZXJ0cyBzb3VyY2UgbWFwJywgKCkgPT4ge1xuICBsZXQgQ29tcCA9IHN0eWxlZC5kaXZgXG4gICAgY29sb3I6IGhvdHBpbms7XG4gIGBcbiAgcmVuZGVyZXIuY3JlYXRlKDxDb21wIC8+KVxuICBleHBlY3QoZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50KS50b01hdGNoU25hcHNob3QoKVxufSlcblxudGVzdCgnc291cmNlIG1hcCB3aXRoIGNvbXBvc2VkIGNvbXBvbmVudCcsICgpID0+IHtcbiAgbGV0IENvbXAgPSBzdHlsZWQuZGl2YFxuICAgIGNvbG9yOiBob3RwaW5rO1xuICBgXG4gIGxldCBDb21wMiA9IHN0eWxlZChDb21wKWBcbiAgICBiYWNrZ3JvdW5kOiB5ZWxsb3c7XG4gIGBcbiAgcmVuZGVyZXIuY3JlYXRlKDxDb21wMiAvPilcbiAgZXhwZWN0KGRvY3VtZW50LmRvY3VtZW50RWxlbWVudCkudG9NYXRjaFNuYXBzaG90KClcbn0pXG5cbnRlc3QoJ3NvdXJjZSBtYXAgd2l0aCBjb21wb3NlZCBzdHlsZScsICgpID0+IHtcbiAgbGV0IHN0eWxlID0gY3NzKHsgY29sb3I6ICdncmVlbicgfSlcbiAgbGV0IENvbXAyID0gc3R5bGVkLmRpdmBcbiAgICBiYWNrZ3JvdW5kOiB5ZWxsb3c7XG4gICAgJHtzdHlsZX1cbiAgYFxuICByZW5kZXJlci5jcmVhdGUoPENvbXAyIC8+KVxuICBleHBlY3QoZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50KS50b01hdGNoU25hcHNob3QoKVxufSlcbiJdfQ== */
+      .css-fle4cv-Comp-Comp2{color:hotpink;background:yellow;}/*# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInNvdXJjZS1tYXAudGVzdC5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFpQjBCIiwiZmlsZSI6InNvdXJjZS1tYXAudGVzdC5qcyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBSZWFjdCBmcm9tICdyZWFjdCdcbmltcG9ydCB7IGNzcyB9IGZyb20gJ0BlbW90aW9uL3JlYWN0J1xuaW1wb3J0IHN0eWxlZCBmcm9tICdAZW1vdGlvbi9zdHlsZWQnXG5pbXBvcnQgeyByZW5kZXIgfSBmcm9tICdAdGVzdGluZy1saWJyYXJ5L3JlYWN0J1xuXG50ZXN0KCdpbnNlcnRzIHNvdXJjZSBtYXAnLCAoKSA9PiB7XG4gIGxldCBDb21wID0gc3R5bGVkLmRpdmBcbiAgICBjb2xvcjogaG90cGluaztcbiAgYFxuICByZW5kZXIoPENvbXAgLz4pXG4gIGV4cGVjdChkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQpLnRvTWF0Y2hTbmFwc2hvdCgpXG59KVxuXG50ZXN0KCdzb3VyY2UgbWFwIHdpdGggY29tcG9zZWQgY29tcG9uZW50JywgKCkgPT4ge1xuICBsZXQgQ29tcCA9IHN0eWxlZC5kaXZgXG4gICAgY29sb3I6IGhvdHBpbms7XG4gIGBcbiAgbGV0IENvbXAyID0gc3R5bGVkKENvbXApYFxuICAgIGJhY2tncm91bmQ6IHllbGxvdztcbiAgYFxuICByZW5kZXIoPENvbXAyIC8+KVxuICBleHBlY3QoZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50KS50b01hdGNoU25hcHNob3QoKVxufSlcblxudGVzdCgnc291cmNlIG1hcCB3aXRoIGNvbXBvc2VkIHN0eWxlJywgKCkgPT4ge1xuICBsZXQgc3R5bGUgPSBjc3MoeyBjb2xvcjogJ2dyZWVuJyB9KVxuICBsZXQgQ29tcDIgPSBzdHlsZWQuZGl2YFxuICAgIGJhY2tncm91bmQ6IHllbGxvdztcbiAgICAke3N0eWxlfVxuICBgXG4gIHJlbmRlcig8Q29tcDIgLz4pXG4gIGV4cGVjdChkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQpLnRvTWF0Y2hTbmFwc2hvdCgpXG59KVxuIl19 */
     </style>
     <style
       data-emotion="css"
       data-s=""
     >
       
-      .css-1nwg2t9-Comp2-style{background:yellow;color:green;}/*# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInNvdXJjZS1tYXAudGVzdC5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUEwQndCIiwiZmlsZSI6InNvdXJjZS1tYXAudGVzdC5qcyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBSZWFjdCBmcm9tICdyZWFjdCdcbmltcG9ydCB7IGNzcyB9IGZyb20gJ0BlbW90aW9uL3JlYWN0J1xuaW1wb3J0IHN0eWxlZCBmcm9tICdAZW1vdGlvbi9zdHlsZWQnXG5pbXBvcnQgcmVuZGVyZXIgZnJvbSAncmVhY3QtdGVzdC1yZW5kZXJlcidcblxudGVzdCgnaW5zZXJ0cyBzb3VyY2UgbWFwJywgKCkgPT4ge1xuICBsZXQgQ29tcCA9IHN0eWxlZC5kaXZgXG4gICAgY29sb3I6IGhvdHBpbms7XG4gIGBcbiAgcmVuZGVyZXIuY3JlYXRlKDxDb21wIC8+KVxuICBleHBlY3QoZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50KS50b01hdGNoU25hcHNob3QoKVxufSlcblxudGVzdCgnc291cmNlIG1hcCB3aXRoIGNvbXBvc2VkIGNvbXBvbmVudCcsICgpID0+IHtcbiAgbGV0IENvbXAgPSBzdHlsZWQuZGl2YFxuICAgIGNvbG9yOiBob3RwaW5rO1xuICBgXG4gIGxldCBDb21wMiA9IHN0eWxlZChDb21wKWBcbiAgICBiYWNrZ3JvdW5kOiB5ZWxsb3c7XG4gIGBcbiAgcmVuZGVyZXIuY3JlYXRlKDxDb21wMiAvPilcbiAgZXhwZWN0KGRvY3VtZW50LmRvY3VtZW50RWxlbWVudCkudG9NYXRjaFNuYXBzaG90KClcbn0pXG5cbnRlc3QoJ3NvdXJjZSBtYXAgd2l0aCBjb21wb3NlZCBzdHlsZScsICgpID0+IHtcbiAgbGV0IHN0eWxlID0gY3NzKHsgY29sb3I6ICdncmVlbicgfSlcbiAgbGV0IENvbXAyID0gc3R5bGVkLmRpdmBcbiAgICBiYWNrZ3JvdW5kOiB5ZWxsb3c7XG4gICAgJHtzdHlsZX1cbiAgYFxuICByZW5kZXJlci5jcmVhdGUoPENvbXAyIC8+KVxuICBleHBlY3QoZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50KS50b01hdGNoU25hcHNob3QoKVxufSlcbiJdfQ== */
+      .css-hulrp8-Comp2-style{background:yellow;color:green;}/*# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInNvdXJjZS1tYXAudGVzdC5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUEwQndCIiwiZmlsZSI6InNvdXJjZS1tYXAudGVzdC5qcyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBSZWFjdCBmcm9tICdyZWFjdCdcbmltcG9ydCB7IGNzcyB9IGZyb20gJ0BlbW90aW9uL3JlYWN0J1xuaW1wb3J0IHN0eWxlZCBmcm9tICdAZW1vdGlvbi9zdHlsZWQnXG5pbXBvcnQgeyByZW5kZXIgfSBmcm9tICdAdGVzdGluZy1saWJyYXJ5L3JlYWN0J1xuXG50ZXN0KCdpbnNlcnRzIHNvdXJjZSBtYXAnLCAoKSA9PiB7XG4gIGxldCBDb21wID0gc3R5bGVkLmRpdmBcbiAgICBjb2xvcjogaG90cGluaztcbiAgYFxuICByZW5kZXIoPENvbXAgLz4pXG4gIGV4cGVjdChkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQpLnRvTWF0Y2hTbmFwc2hvdCgpXG59KVxuXG50ZXN0KCdzb3VyY2UgbWFwIHdpdGggY29tcG9zZWQgY29tcG9uZW50JywgKCkgPT4ge1xuICBsZXQgQ29tcCA9IHN0eWxlZC5kaXZgXG4gICAgY29sb3I6IGhvdHBpbms7XG4gIGBcbiAgbGV0IENvbXAyID0gc3R5bGVkKENvbXApYFxuICAgIGJhY2tncm91bmQ6IHllbGxvdztcbiAgYFxuICByZW5kZXIoPENvbXAyIC8+KVxuICBleHBlY3QoZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50KS50b01hdGNoU25hcHNob3QoKVxufSlcblxudGVzdCgnc291cmNlIG1hcCB3aXRoIGNvbXBvc2VkIHN0eWxlJywgKCkgPT4ge1xuICBsZXQgc3R5bGUgPSBjc3MoeyBjb2xvcjogJ2dyZWVuJyB9KVxuICBsZXQgQ29tcDIgPSBzdHlsZWQuZGl2YFxuICAgIGJhY2tncm91bmQ6IHllbGxvdztcbiAgICAke3N0eWxlfVxuICBgXG4gIHJlbmRlcig8Q29tcDIgLz4pXG4gIGV4cGVjdChkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQpLnRvTWF0Y2hTbmFwc2hvdCgpXG59KVxuIl19 */
     </style>
   </head>
-  <body />
+  <body>
+    <div>
+      <div
+        class="css-hulrp8-Comp2-style e1gz73mp0"
+      />
+    </div>
+  </body>
 </html>
 `;
diff --git a/packages/styled/test/__snapshots__/theming.test.js.snap b/packages/styled/test/__snapshots__/theming.test.js.snap
index a85b5ae7a7..1608d2f475 100644
--- a/packages/styled/test/__snapshots__/theming.test.js.snap
+++ b/packages/styled/test/__snapshots__/theming.test.js.snap
@@ -7,7 +7,7 @@ exports[`theme prop exists without ThemeProvider 1`] = `
 }
 
 <div
-  className="emotion-0 emotion-1"
+  class="emotion-0 emotion-1"
 />
 `;
 
@@ -18,7 +18,7 @@ exports[`theme prop exists without ThemeProvider with a theme prop on the compon
 }
 
 <div
-  className="emotion-0 emotion-1"
+  class="emotion-0 emotion-1"
 />
 `;
 
@@ -28,7 +28,7 @@ exports[`theme with react-test-renderer 1`] = `
 }
 
 <div
-  className="emotion-0 emotion-1"
+  class="emotion-0 emotion-1"
 >
   this will be pink
 </div>
@@ -45,7 +45,7 @@ exports[`themes 1`] = `
 }
 
 <span
-  className="emotion-0 emotion-1"
+  class="emotion-0 emotion-1"
 >
   hello world
 </span>
diff --git a/packages/styled/test/babel-plugin.test.js b/packages/styled/test/babel-plugin.test.js
index 053ba35078..52563d86d4 100644
--- a/packages/styled/test/babel-plugin.test.js
+++ b/packages/styled/test/babel-plugin.test.js
@@ -1,6 +1,7 @@
 import 'test-utils/setup-env'
 import React from 'react'
-import * as renderer from 'react-test-renderer'
+import { act } from 'react'
+import { render } from '@testing-library/react'
 import styled from '@emotion/styled'
 
 test("config merging works even if it's referenced by variable", () => {
@@ -10,6 +11,6 @@ test("config merging works even if it's referenced by variable", () => {
 
   const cfg = { shouldForwardProp: p => p !== 'isRed' }
   const StyledButton = styled(Button, cfg)({})
-  const tree = renderer.create(<StyledButton isRed />).toJSON()
-  expect(tree.children).toEqual(['not forwarded'])
+  const { container } = render(<StyledButton isRed />)
+  expect(container).toMatchSnapshot()
 })
diff --git a/packages/styled/test/component-selector.test.js b/packages/styled/test/component-selector.test.js
index f87565d585..95385db6f1 100644
--- a/packages/styled/test/component-selector.test.js
+++ b/packages/styled/test/component-selector.test.js
@@ -1,7 +1,7 @@
 import 'test-utils/setup-env'
 import React from 'react'
+import { render } from '@testing-library/react'
 import styled from '@emotion/styled'
-import * as renderer from 'react-test-renderer'
 
 test('component as selector', () => {
   const fontSize = '20px'
@@ -16,15 +16,13 @@ test('component as selector', () => {
     }
   `
 
-  const tree = renderer
-    .create(
-      <Thing>
-        hello <H1>This will be green</H1> world
-      </Thing>
-    )
-    .toJSON()
+  const { container } = render(
+    <Thing>
+      hello <H1>This will be green</H1> world
+    </Thing>
+  )
 
-  expect(tree).toMatchSnapshot()
+  expect(container.firstChild).toMatchSnapshot()
 })
 
 test('component as selector function interpolation', () => {
@@ -39,15 +37,13 @@ test('component as selector function interpolation', () => {
     }
   `
 
-  const tree = renderer
-    .create(
-      <Thing fontSize={10}>
-        hello <H1 fontSize={20}>This will be green</H1> world
-      </Thing>
-    )
-    .toJSON()
+  const { container } = render(
+    <Thing fontSize={10}>
+      hello <H1 fontSize={20}>This will be green</H1> world
+    </Thing>
+  )
 
-  expect(tree).toMatchSnapshot()
+  expect(container.firstChild).toMatchSnapshot()
 })
 
 test('component as selector (object syntax)', () => {
@@ -61,15 +57,13 @@ test('component as selector (object syntax)', () => {
     }
   })
 
-  const tree = renderer
-    .create(
-      <Thing>
-        hello <H1>This will be green</H1> world
-      </Thing>
-    )
-    .toJSON()
+  const { container } = render(
+    <Thing>
+      hello <H1>This will be green</H1> world
+    </Thing>
+  )
 
-  expect(tree).toMatchSnapshot()
+  expect(container.firstChild).toMatchSnapshot()
 })
 
 test('component as selector function interpolation (object syntax)', () => {
@@ -84,13 +78,11 @@ test('component as selector function interpolation (object syntax)', () => {
     }
   })
 
-  const tree = renderer
-    .create(
-      <Thing fontSize={10}>
-        hello <H1 fontSize={20}>This will be green</H1> world
-      </Thing>
-    )
-    .toJSON()
+  const { container } = render(
+    <Thing fontSize={10}>
+      hello <H1 fontSize={20}>This will be green</H1> world
+    </Thing>
+  )
 
-  expect(tree).toMatchSnapshot()
+  expect(container.firstChild).toMatchSnapshot()
 })
diff --git a/packages/styled/test/composition.test.js b/packages/styled/test/composition.test.js
index a4676b9dd8..58da897b64 100644
--- a/packages/styled/test/composition.test.js
+++ b/packages/styled/test/composition.test.js
@@ -1,6 +1,6 @@
 /** @jsx jsx */
 import 'test-utils/setup-env'
-import * as renderer from 'react-test-renderer'
+import { render } from '@testing-library/react'
 import { jsx, css } from '@emotion/react'
 import styled from '@emotion/styled'
 
@@ -28,15 +28,13 @@ test('composition', () => {
     font-size: 32px;
   `
 
-  const tree = renderer
-    .create(
-      <FinalH2 scale={2} className={'legacy__class'}>
-        hello world
-      </FinalH2>
-    )
-    .toJSON()
+  const { container } = render(
+    <FinalH2 scale={2} className={'legacy__class'}>
+      hello world
+    </FinalH2>
+  )
 
-  expect(tree).toMatchSnapshot()
+  expect(container.firstChild).toMatchSnapshot()
 })
 
 test('composition with objects', () => {
@@ -60,15 +58,13 @@ test('composition with objects', () => {
     font-size: 32px;
   `
 
-  const tree = renderer
-    .create(
-      <H2 scale={2} className={'legacy__class'}>
-        hello world
-      </H2>
-    )
-    .toJSON()
+  const { container } = render(
+    <H2 scale={2} className={'legacy__class'}>
+      hello world
+    </H2>
+  )
 
-  expect(tree).toMatchSnapshot()
+  expect(container.firstChild).toMatchSnapshot()
 })
 test('object composition', () => {
   const imageStyles = css({ width: 96, height: 96 })
@@ -96,9 +92,9 @@ test('object composition', () => {
     ${blue};
   `
 
-  const tree = renderer.create(<Avatar />).toJSON()
+  const { container } = render(<Avatar />)
 
-  expect(tree).toMatchSnapshot()
+  expect(container.firstChild).toMatchSnapshot()
 })
 
 test('composition', () => {
@@ -111,10 +107,8 @@ test('composition', () => {
     font-size: ${(fontSize * 2) / 3 + 'px'};
   `
 
-  const tree = renderer
-    .create(<H2 className={'legacy__class'}>hello world</H2>)
-    .toJSON()
-  expect(tree).toMatchSnapshot()
+  const { container } = render(<H2 className={'legacy__class'}>hello world</H2>)
+  expect(container.firstChild).toMatchSnapshot()
 })
 
 test('composing components', () => {
@@ -129,11 +123,9 @@ test('composing components', () => {
     display: flex;
     justify-content: center;
   `
-  const tree = renderer
-    .create(<AnotherButton>hello world</AnotherButton>)
-    .toJSON()
+  const { container } = render(<AnotherButton>hello world</AnotherButton>)
 
-  expect(tree).toMatchSnapshot()
+  expect(container.firstChild).toMatchSnapshot()
 })
 
 test('composition of nested pseudo selectors', () => {
@@ -154,39 +146,35 @@ test('composition of nested pseudo selectors', () => {
 
   const Button = styled('button')(buttonStyles)
 
-  const tree = renderer
-    .create(
-      <Button
-        css={css({
-          '&:hover': {
-            color: 'pink',
-            '&:active': {
-              color: 'purple'
-            },
-            '&.some-class': {
-              color: 'yellow'
-            }
+  const { container } = render(
+    <Button
+      css={css({
+        '&:hover': {
+          color: 'pink',
+          '&:active': {
+            color: 'purple'
+          },
+          '&.some-class': {
+            color: 'yellow'
           }
-        })}
-      >
-        Should be purple
-      </Button>
-    )
-    .toJSON()
-  expect(tree).toMatchSnapshot()
+        }
+      })}
+    >
+      Should be purple
+    </Button>
+  )
+  expect(container.firstChild).toMatchSnapshot()
 })
 
 test('glamorous style api & composition', () => {
   const H1 = styled.h1(props => ({ fontSize: props.fontSize }))
   const H2 = styled(H1)(props => ({ flex: props.flex }), { display: 'flex' })
 
-  const tree = renderer
-    .create(
-      <H2 fontSize={20} flex={1}>
-        hello world
-      </H2>
-    )
-    .toJSON()
+  const { container } = render(
+    <H2 fontSize={20} flex={1}>
+      hello world
+    </H2>
+  )
 
-  expect(tree).toMatchSnapshot()
+  expect(container.firstChild).toMatchSnapshot()
 })
diff --git a/packages/styled/test/index.test.js b/packages/styled/test/index.test.js
index bca425ef6e..e0d8b24e87 100644
--- a/packages/styled/test/index.test.js
+++ b/packages/styled/test/index.test.js
@@ -1,6 +1,6 @@
 import 'test-utils/setup-env'
 import React from 'react'
-import * as renderer from 'react-test-renderer'
+import { render } from '@testing-library/react'
 import { css } from '@emotion/react'
 import styled from '@emotion/styled'
 import hoistNonReactStatics from 'hoist-non-react-statics'
@@ -11,9 +11,9 @@ describe('styled', () => {
       float: left;
     `
 
-    const tree = renderer.create(<H1>hello world</H1>).toJSON()
+    const { container } = render(<H1>hello world</H1>)
 
-    expect(tree).toMatchSnapshot()
+    expect(container.firstChild).toMatchSnapshot()
   })
 
   test('basic render', () => {
@@ -26,18 +26,18 @@ describe('styled', () => {
       }
     `
 
-    const tree = renderer.create(<H1>hello world</H1>).toJSON()
+    const { container } = render(<H1>hello world</H1>)
 
-    expect(tree).toMatchSnapshot()
+    expect(container.firstChild).toMatchSnapshot()
   })
 
   test('basic render with object as style', () => {
     const fontSize = 20
     const H1 = styled.h1({ fontSize })
 
-    const tree = renderer.create(<H1>hello world</H1>).toJSON()
+    const { container } = render(<H1>hello world</H1>)
 
-    expect(tree).toMatchSnapshot()
+    expect(container.firstChild).toMatchSnapshot()
   })
 
   test('object as style', () => {
@@ -49,15 +49,13 @@ describe('styled', () => {
       { display: 'flex' }
     )
 
-    const tree = renderer
-      .create(
-        <H1 fontSize={20} flex={1}>
-          hello world
-        </H1>
-      )
-      .toJSON()
+    const { container } = render(
+      <H1 fontSize={20} flex={1}>
+        hello world
+      </H1>
+    )
 
-    expect(tree).toMatchSnapshot()
+    expect(container.firstChild).toMatchSnapshot()
   })
 
   test('inline function return value is a function', () => {
@@ -66,9 +64,9 @@ describe('styled', () => {
       font-size: ${() => fontSize}px;
     `
 
-    const tree = renderer.create(<Blue>hello world</Blue>).toJSON()
+    const { container } = render(<Blue>hello world</Blue>)
 
-    expect(tree).toMatchSnapshot()
+    expect(container.firstChild).toMatchSnapshot()
   })
 
   test('call expression', () => {
@@ -77,9 +75,9 @@ describe('styled', () => {
       font-size: ${fontSize}px;
     `
 
-    const tree = renderer.create(<Div>hello world</Div>).toJSON()
+    const { container } = render(<Div>hello world</Div>)
 
-    expect(tree).toMatchSnapshot()
+    expect(container.firstChild).toMatchSnapshot()
   })
 
   test('nested', () => {
@@ -99,15 +97,13 @@ describe('styled', () => {
       }
     `
 
-    const tree = renderer
-      .create(
-        <Thing>
-          hello <H1>This will be green</H1> world
-        </Thing>
-      )
-      .toJSON()
+    const { container } = render(
+      <Thing>
+        hello <H1>This will be green</H1> world
+      </Thing>
+    )
 
-    expect(tree).toMatchSnapshot()
+    expect(container.firstChild).toMatchSnapshot()
   })
 
   test('random expressions undefined return', () => {
@@ -120,11 +116,11 @@ describe('styled', () => {
       color: green;
     `
 
-    const tree = renderer
-      .create(<H1 className={'legacy__class'}>hello world</H1>)
-      .toJSON()
+    const { container } = render(
+      <H1 className={'legacy__class'}>hello world</H1>
+    )
 
-    expect(tree).toMatchSnapshot()
+    expect(container.firstChild).toMatchSnapshot()
   })
 
   test('random object expression', () => {
@@ -143,15 +139,13 @@ describe('styled', () => {
       color: green;
     `
 
-    const tree = renderer
-      .create(
-        <H1 className={'legacy__class'} prop>
-          hello world
-        </H1>
-      )
-      .toJSON()
+    const { container } = render(
+      <H1 className={'legacy__class'} prop>
+        hello world
+      </H1>
+    )
 
-    expect(tree).toMatchSnapshot()
+    expect(container.firstChild).toMatchSnapshot()
   })
 
   test('input placeholder', () => {
@@ -160,9 +154,11 @@ describe('styled', () => {
         background-color: green;
       }
     `
-    const tree = renderer.create(<Input>hello world</Input>).toJSON()
+    const { container } = render(
+      <Input value="hello world" onChange={() => {}} />
+    )
 
-    expect(tree).toMatchSnapshot()
+    expect(container.firstChild).toMatchSnapshot()
   })
 
   test('input placeholder object', () => {
@@ -172,9 +168,11 @@ describe('styled', () => {
       }
     })
 
-    const tree = renderer.create(<Input>hello world</Input>).toJSON()
+    const { container } = render(
+      <Input value="hello world" onChange={() => {}} />
+    )
 
-    expect(tree).toMatchSnapshot()
+    expect(container.firstChild).toMatchSnapshot()
   })
 
   test('handles more than 10 dynamic properties', () => {
@@ -193,15 +191,13 @@ describe('styled', () => {
       border-left: ${p => p.theme.blue};
     `
 
-    const tree = renderer
-      .create(
-        <H1 className={'legacy__class'} theme={{ blue: 'blue' }}>
-          hello world
-        </H1>
-      )
-      .toJSON()
+    const { container } = render(
+      <H1 className={'legacy__class'} theme={{ blue: 'blue' }}>
+        hello world
+      </H1>
+    )
 
-    expect(tree).toMatchSnapshot()
+    expect(container.firstChild).toMatchSnapshot()
   })
 
   test('function in expression', () => {
@@ -214,29 +210,25 @@ describe('styled', () => {
       font-size: ${({ scale }) => fontSize * scale + 'px'};
     `
 
-    const tree = renderer
-      .create(
-        <H2 scale={2} className={'legacy__class'}>
-          hello world
-        </H2>
-      )
-      .toJSON()
+    const { container } = render(
+      <H2 scale={2} className={'legacy__class'}>
+        hello world
+      </H2>
+    )
 
-    expect(tree).toMatchSnapshot()
+    expect(container.firstChild).toMatchSnapshot()
   })
 
-  test.skip('ref', () => {
+  test('ref', () => {
     const H1 = styled.h1`
       font-size: 12px;
     `
 
     const refFunction = jest.fn()
 
-    const tree = renderer
-      .create(<H1 ref={refFunction}>hello world</H1>)
-      .toJSON()
+    const { container } = render(<H1 ref={refFunction}>hello world</H1>)
 
-    expect(tree).toMatchSnapshot()
+    expect(container.firstChild).toMatchSnapshot()
     expect(refFunction).toBeCalled()
   })
 
@@ -253,29 +245,29 @@ describe('styled', () => {
       ${props => (props.a ? cssA : cssB)};
     `
 
-    const tree = renderer.create(<H1 a>hello world</H1>).toJSON()
+    const { container: container1 } = render(<H1 a>hello world</H1>)
 
-    expect(tree).toMatchSnapshot()
-    const tree2 = renderer.create(<H1>hello world</H1>).toJSON()
+    expect(container1.firstChild).toMatchSnapshot()
+    const { container: container2 } = render(<H1>hello world</H1>)
 
-    expect(tree2).toMatchSnapshot()
+    expect(container2.firstChild).toMatchSnapshot()
   })
 
   test('objects', () => {
     const H1 = styled('h1')({ padding: 10 }, props => ({
       display: props.display
     }))
-    const tree = renderer.create(<H1 display="flex">hello world</H1>).toJSON()
+    const { container } = render(<H1 display="flex">hello world</H1>)
 
-    expect(tree).toMatchSnapshot()
+    expect(container.firstChild).toMatchSnapshot()
   })
 
   test('objects with spread properties', () => {
     const defaultText = { fontSize: 20 }
     const Figure = styled.figure({ ...defaultText })
-    const tree = renderer.create(<Figure>hello world</Figure>).toJSON()
+    const { container } = render(<Figure>hello world</Figure>)
 
-    expect(tree).toMatchSnapshot()
+    expect(container.firstChild).toMatchSnapshot()
   })
 
   test('with higher order component that hoists statics', () => {
@@ -293,8 +285,8 @@ describe('styled', () => {
     const FinalComponent = styled(SomeComponent)`
       padding: 8px;
     `
-    const tree = renderer.create(<FinalComponent />).toJSON()
-    expect(tree).toMatchSnapshot()
+    const { container } = render(<FinalComponent />)
+    expect(container.firstChild).toMatchSnapshot()
   })
 
   test('throws if undefined is passed as the component', () => {
@@ -310,8 +302,8 @@ describe('styled', () => {
       color: ${() => props => props.color};
       background-color: yellow;
     `
-    const tree = renderer.create(<SomeComponent color="hotpink" />).toJSON()
-    expect(tree).toMatchSnapshot()
+    const { container } = render(<SomeComponent color="hotpink" />)
+    expect(container.firstChild).toMatchSnapshot()
   })
 
   test('withComponent carries styles from flattened components', () => {
@@ -322,8 +314,8 @@ describe('styled', () => {
       color: hotpink;
     `
     const OneMoreComponent = AnotherComponent.withComponent('p')
-    const tree = renderer.create(<OneMoreComponent />).toJSON()
-    expect(tree).toMatchSnapshot()
+    const { container } = render(<OneMoreComponent />)
+    expect(container.firstChild).toMatchSnapshot()
   })
 
   test('withComponent will replace tags but keep styling classes', () => {
@@ -332,16 +324,14 @@ describe('styled', () => {
     `
     const Subtitle = Title.withComponent('h2')
 
-    const tree = renderer
-      .create(
-        <article>
-          <Title>My Title</Title>
-          <Subtitle>My Subtitle</Subtitle>
-        </article>
-      )
-      .toJSON()
+    const { container } = render(
+      <article>
+        <Title>My Title</Title>
+        <Subtitle>My Subtitle</Subtitle>
+      </article>
+    )
 
-    expect(tree).toMatchSnapshot()
+    expect(container.firstChild).toMatchSnapshot()
   })
   test('withComponent with function interpolation', () => {
     const Title = styled('h1')`
@@ -349,16 +339,14 @@ describe('styled', () => {
     `
     const Subtitle = Title.withComponent('h2')
 
-    const tree = renderer
-      .create(
-        <article>
-          <Title>My Title</Title>
-          <Subtitle color="hotpink">My Subtitle</Subtitle>
-        </article>
-      )
-      .toJSON()
+    const { container } = render(
+      <article>
+        <Title>My Title</Title>
+        <Subtitle color="hotpink">My Subtitle</Subtitle>
+      </article>
+    )
 
-    expect(tree).toMatchSnapshot()
+    expect(container.firstChild).toMatchSnapshot()
   })
 
   test('name with class component', () => {
diff --git a/packages/styled/test/prop-filtering.test.js b/packages/styled/test/prop-filtering.test.js
index 5931a974c0..c4aa9d85f7 100644
--- a/packages/styled/test/prop-filtering.test.js
+++ b/packages/styled/test/prop-filtering.test.js
@@ -1,6 +1,7 @@
 import 'test-utils/setup-env'
 import React from 'react'
-import * as renderer from 'react-test-renderer'
+import { act } from 'react'
+import { render } from '@testing-library/react'
 import styled from '@emotion/styled'
 
 test('composes shouldForwardProp on composed styled components', () => {
@@ -12,9 +13,9 @@ test('composes shouldForwardProp on composed styled components', () => {
     shouldForwardProp: prop => prop !== 'bar'
   })()
 
-  const tree = renderer.create(<ComposedDiv foo bar xyz />).toJSON()
+  const { container } = render(<ComposedDiv foo bar xyz="true" />)
 
-  expect(tree).toMatchSnapshot()
+  expect(container.firstChild).toMatchSnapshot()
 })
 
 test('custom shouldForwardProp works', () => {
@@ -40,10 +41,10 @@ test('custom shouldForwardProp works', () => {
     }
   `
 
-  const tree = renderer
-    .create(<StyledSvg color="#0000ff" width="100px" height="100px" />)
-    .toJSON()
-  expect(tree).toMatchSnapshot()
+  const { container } = render(
+    <StyledSvg color="#0000ff" width="100px" height="100px" />
+  )
+  expect(container.firstChild).toMatchSnapshot()
 })
 
 test('shouldForwardProp should get inherited for wrapped styled components', () => {
@@ -55,15 +56,13 @@ test('shouldForwardProp should get inherited for wrapped styled components', ()
 
   const Div2 = styled(Div1)``
 
-  const tree = renderer
-    .create(
-      <>
-        <Div1 color="red" id="test-1" />
-        <Div2 color="green" id="test-2" />
-      </>
-    )
-    .toJSON()
-  expect(tree).toMatchSnapshot()
+  const { container } = render(
+    <>
+      <Div1 color="red" id="test-1" />
+      <Div2 color="green" id="test-2" />
+    </>
+  )
+  expect(container.firstChild).toMatchSnapshot()
 })
 
 test('prop filtering', () => {
@@ -72,53 +71,49 @@ test('prop filtering', () => {
   `
   const rest = { m: [3], pt: [4] }
 
-  const tree = renderer
-    .create(
-      <Link
-        a
-        b
-        wow
-        prop
-        filtering
-        is
-        cool
-        aria-label="some label"
-        data-wow="value"
-        href="link"
-        {...rest}
-      >
-        hello world
-      </Link>
-    )
-    .toJSON()
-
-  expect(tree).toMatchSnapshot()
+  const { container } = render(
+    <Link
+      a="true"
+      b="true"
+      wow="true"
+      prop="true"
+      filtering="true"
+      is="true"
+      cool="true"
+      aria-label="some label"
+      data-wow="value"
+      href="link"
+      {...rest}
+    >
+      hello world
+    </Link>
+  )
+
+  expect(container.firstChild).toMatchSnapshot()
 })
 test('no prop filtering on non string tags', () => {
   const Link = styled(props => <a {...props} />)`
     color: green;
   `
 
-  const tree = renderer
-    .create(
-      <Link
-        a
-        b
-        wow
-        prop
-        filtering
-        is
-        cool
-        aria-label="some label"
-        data-wow="value"
-        href="link"
-      >
-        hello world
-      </Link>
-    )
-    .toJSON()
-
-  expect(tree).toMatchSnapshot()
+  const { container } = render(
+    <Link
+      a="true"
+      b="true"
+      wow="true"
+      prop="true"
+      filtering="true"
+      is="true"
+      cool="true"
+      aria-label="some label"
+      data-wow="value"
+      href="link"
+    >
+      hello world
+    </Link>
+  )
+
+  expect(container.firstChild).toMatchSnapshot()
 })
 
 test('no prop filtering on string tags started with upper case', () => {
@@ -126,26 +121,24 @@ test('no prop filtering on string tags started with upper case', () => {
     color: green;
   `
 
-  const tree = renderer
-    .create(
-      <Link
-        a
-        b
-        wow
-        prop
-        filtering
-        is
-        cool
-        aria-label="some label"
-        data-wow="value"
-        href="link"
-      >
-        hello world
-      </Link>
-    )
-    .toJSON()
-
-  expect(tree).toMatchSnapshot()
+  const { container } = render(
+    <Link
+      a="true"
+      b="true"
+      wow="true"
+      prop="true"
+      filtering="true"
+      is="true"
+      cool="true"
+      aria-label="some label"
+      data-wow="value"
+      href="link"
+    >
+      hello world
+    </Link>
+  )
+
+  expect(container.firstChild).toMatchSnapshot()
 })
 
 test('basic SVG attributes survive prop filtering', () => {
@@ -154,18 +147,18 @@ test('basic SVG attributes survive prop filtering', () => {
     stroke-width: 0.26458332;
   `
 
-  const svg = renderer
-    .create(<RedCircle r="9.8273811" cy="49.047619" cx="65.011902" />)
-    .toJSON()
+  const { container } = render(
+    <RedCircle r="9.8273811" cy="49.047619" cx="65.011902" />
+  )
 
-  expect(svg).toMatchInlineSnapshot(`
+  expect(container.firstChild).toMatchInlineSnapshot(`
 .emotion-0 {
   fill: #ff0000;
   stroke-width: 0.26458332;
 }
 
 <circle
-  className="emotion-0 emotion-1"
+  class="emotion-0 emotion-1"
   cx="65.011902"
   cy="49.047619"
   r="9.8273811"
@@ -418,9 +411,9 @@ test('all SVG attributes survive prop filtering', () => {
     stroke-width: 0.26458332;
   `
 
-  const svg = renderer.create(<RedPath {...svgAttributes} />).toJSON()
+  const { container } = render(<RedPath {...svgAttributes} />)
 
-  expect(svg.props).toEqual({ ...svgAttributes, className: expect.any(String) })
+  expect(container).toMatchSnapshot
 })
 
 test('prop filtering on composed styled components that are string tags', () => {
@@ -431,42 +424,40 @@ test('prop filtering on composed styled components that are string tags', () =>
     color: green;
   `
 
-  const tree = renderer
-    .create(
-      <Link
-        wow
-        prop
-        filtering
-        looks
-        cool
-        but
-        is
-        kind
-        of
-        a
-        bad
-        idea
-        since
-        the
-        react
-        warnings
-        will
-        not
-        work
-        and
-        it="is"
-        problematic
-        for="other reasons"
-        aria-label="some label"
-        data-wow="value"
-        href="link"
-      >
-        hello world
-      </Link>
-    )
-    .toJSON()
-
-  expect(tree).toMatchSnapshot()
+  const { container } = render(
+    <Link
+      wow="true"
+      prop="true"
+      filtering="true"
+      looks="true"
+      cool="true"
+      but="true"
+      is="true"
+      kind="true"
+      of="true"
+      a="true"
+      bad="true"
+      idea="true"
+      since="true"
+      the="true"
+      react="true"
+      warnings="true"
+      will="true"
+      not="true"
+      work="true"
+      and="true"
+      it="is"
+      problematic="true"
+      for="other reasons"
+      aria-label="some label"
+      data-wow="value"
+      href="link"
+    >
+      hello world
+    </Link>
+  )
+
+  expect(container.firstChild).toMatchSnapshot()
 })
 
 test('withComponent inherits explicit shouldForwardProp', () => {
@@ -476,8 +467,8 @@ test('withComponent inherits explicit shouldForwardProp', () => {
     color: hotpink;
   `
   const AnotherComponent = SomeComponent.withComponent('span')
-  const tree = renderer.create(<AnotherComponent foo bar />).toJSON()
-  expect(tree).toMatchSnapshot()
+  const { container } = render(<AnotherComponent foo="true" bar="true" />)
+  expect(container.firstChild).toMatchSnapshot()
 })
 
 test('withComponent inherits explicit shouldForwardProp from flattened component', () => {
@@ -490,8 +481,8 @@ test('withComponent inherits explicit shouldForwardProp from flattened component
     background-color: blue;
   `
   const YetAnotherComponent = AnotherComponent.withComponent('span')
-  const tree = renderer.create(<YetAnotherComponent foo bar />).toJSON()
-  expect(tree).toMatchSnapshot()
+  const { container } = render(<YetAnotherComponent foo="true" bar="true" />)
+  expect(container.firstChild).toMatchSnapshot()
 })
 
 test('withComponent should accept shouldForwardProp', () => {
@@ -501,8 +492,8 @@ test('withComponent should accept shouldForwardProp', () => {
   const AnotherComponent = SomeComponent.withComponent('span', {
     shouldForwardProp: prop => prop === 'xyz'
   })
-  const tree = renderer.create(<AnotherComponent qwe xyz />).toJSON()
-  expect(tree).toMatchSnapshot()
+  const { container } = render(<AnotherComponent qwe="true" xyz="true" />)
+  expect(container.firstChild).toMatchSnapshot()
 })
 
 test('withComponent should compose shouldForwardProp', () => {
@@ -514,8 +505,10 @@ test('withComponent should compose shouldForwardProp', () => {
   const AnotherComponent = SomeComponent.withComponent('span', {
     shouldForwardProp: prop => prop !== 'bar'
   })
-  const tree = renderer.create(<AnotherComponent foo bar qwe xyz />).toJSON()
-  expect(tree).toMatchSnapshot()
+  const { container } = render(
+    <AnotherComponent foo="true" bar="true" qwe="true" xyz="true" />
+  )
+  expect(container.firstChild).toMatchSnapshot()
 })
 
 test('withComponent should compose shouldForwardProp with a flattened component', () => {
@@ -530,6 +523,8 @@ test('withComponent should compose shouldForwardProp with a flattened component'
   const YetAnotherComponent = SomeComponent.withComponent('span', {
     shouldForwardProp: prop => prop !== 'bar'
   })
-  const tree = renderer.create(<YetAnotherComponent foo bar qwe xyz />).toJSON()
-  expect(tree).toMatchSnapshot()
+  const { container } = render(
+    <YetAnotherComponent foo="true" bar="true" qwe="true" xyz="true" />
+  )
+  expect(container.firstChild).toMatchSnapshot()
 })
diff --git a/packages/styled/test/source-map.test.js b/packages/styled/test/source-map.test.js
index 69df83a07f..290c49add6 100644
--- a/packages/styled/test/source-map.test.js
+++ b/packages/styled/test/source-map.test.js
@@ -1,13 +1,13 @@
 import React from 'react'
 import { css } from '@emotion/react'
 import styled from '@emotion/styled'
-import renderer from 'react-test-renderer'
+import { render } from '@testing-library/react'
 
 test('inserts source map', () => {
   let Comp = styled.div`
     color: hotpink;
   `
-  renderer.create(<Comp />)
+  render(<Comp />)
   expect(document.documentElement).toMatchSnapshot()
 })
 
@@ -18,7 +18,7 @@ test('source map with composed component', () => {
   let Comp2 = styled(Comp)`
     background: yellow;
   `
-  renderer.create(<Comp2 />)
+  render(<Comp2 />)
   expect(document.documentElement).toMatchSnapshot()
 })
 
@@ -28,6 +28,6 @@ test('source map with composed style', () => {
     background: yellow;
     ${style}
   `
-  renderer.create(<Comp2 />)
+  render(<Comp2 />)
   expect(document.documentElement).toMatchSnapshot()
 })
diff --git a/packages/styled/test/theming.test.js b/packages/styled/test/theming.test.js
index 18375f21b5..b01b7a68a3 100644
--- a/packages/styled/test/theming.test.js
+++ b/packages/styled/test/theming.test.js
@@ -1,6 +1,6 @@
 import 'test-utils/setup-env'
 import React from 'react'
-import * as renderer from 'react-test-renderer'
+import { render } from '@testing-library/react'
 import styled from '@emotion/styled'
 import { css, ThemeProvider } from '@emotion/react'
 
@@ -8,15 +8,13 @@ test('theme with react-test-renderer', () => {
   const Div = styled.div`
     color: ${props => props.theme.primary};
   `
-  const tree = renderer
-    .create(
-      <ThemeProvider theme={{ primary: 'pink' }}>
-        <Div>this will be pink</Div>
-      </ThemeProvider>
-    )
-    .toJSON()
+  const { container } = render(
+    <ThemeProvider theme={{ primary: 'pink' }}>
+      <Div>this will be pink</Div>
+    </ThemeProvider>
+  )
 
-  expect(tree).toMatchSnapshot()
+  expect(container.firstChild).toMatchSnapshot()
 })
 
 test('themes', () => {
@@ -47,14 +45,13 @@ test('themes', () => {
     font-size: 32px;
   `
 
-  const tree = renderer
-    .create(
-      <ThemeProvider theme={theme}>
-        <H2>hello world</H2>
-      </ThemeProvider>
-    )
-    .toJSON()
-  expect(tree).toMatchSnapshot()
+  const { container } = render(
+    <ThemeProvider theme={theme}>
+      <H2>hello world</H2>
+    </ThemeProvider>
+  )
+
+  expect(container.firstChild).toMatchSnapshot()
 })
 
 test('theme prop exists without ThemeProvider', () => {
@@ -62,16 +59,14 @@ test('theme prop exists without ThemeProvider', () => {
     color: ${props => props.theme.color || 'green'};
     background-color: yellow;
   `
-  const tree = renderer.create(<SomeComponent />).toJSON()
-  expect(tree).toMatchSnapshot()
+  const { container } = render(<SomeComponent />)
+  expect(container.firstChild).toMatchSnapshot()
 })
 test('theme prop exists without ThemeProvider with a theme prop on the component', () => {
   const SomeComponent = styled.div`
     color: ${props => props.theme.color || 'green'};
     background-color: yellow;
   `
-  const tree = renderer
-    .create(<SomeComponent theme={{ color: 'hotpink' }} />)
-    .toJSON()
-  expect(tree).toMatchSnapshot()
+  const { container } = render(<SomeComponent theme={{ color: 'hotpink' }} />)
+  expect(container.firstChild).toMatchSnapshot()
 })
diff --git a/packages/styled/types/base.d.ts b/packages/styled/types/base.d.ts
index f8265bd861..e5ad6bffec 100644
--- a/packages/styled/types/base.d.ts
+++ b/packages/styled/types/base.d.ts
@@ -1,2 +1,2 @@
-// TypeScript Version: 4.1
+// TypeScript Version: 5.1
 export * from '../base'
diff --git a/packages/styled/types/index.d.ts b/packages/styled/types/index.d.ts
index 343fcf296e..c2bb25fe48 100644
--- a/packages/styled/types/index.d.ts
+++ b/packages/styled/types/index.d.ts
@@ -1,2 +1,2 @@
-// TypeScript Version: 4.1
+// TypeScript Version: 5.1
 export * from '..'
diff --git a/packages/use-insertion-effect-with-fallbacks/package.json b/packages/use-insertion-effect-with-fallbacks/package.json
index 95152098cd..40a7a8535a 100644
--- a/packages/use-insertion-effect-with-fallbacks/package.json
+++ b/packages/use-insertion-effect-with-fallbacks/package.json
@@ -18,7 +18,7 @@
     "react": ">=16.8.0"
   },
   "devDependencies": {
-    "react": "16.14.0"
+    "react": "19.0.0"
   },
   "exports": {
     ".": {
diff --git a/playgrounds/cra/package.json b/playgrounds/cra/package.json
index 7704589fba..19a0cb191e 100644
--- a/playgrounds/cra/package.json
+++ b/playgrounds/cra/package.json
@@ -3,8 +3,8 @@
   "version": "0.1.0",
   "private": true,
   "dependencies": {
-    "react": "16.14.0",
-    "react-dom": "16.14.0",
+    "react": "19.0.0",
+    "react-dom": "19.0.0",
     "react-scripts": "4.0.3",
     "theme-ui": "^0.12.0"
   },
diff --git a/playgrounds/nextjs/package.json b/playgrounds/nextjs/package.json
index 5cbfb34cad..690436e5d7 100644
--- a/playgrounds/nextjs/package.json
+++ b/playgrounds/nextjs/package.json
@@ -9,7 +9,7 @@
   },
   "dependencies": {
     "next": "^12.2.0",
-    "react": "16.14.0",
-    "react-dom": "16.14.0"
+    "react": "19.0.0",
+    "react-dom": "19.0.0"
   }
 }
diff --git a/scripts/benchmarks/package.json b/scripts/benchmarks/package.json
index c1db9f44ed..b1bff0d8a1 100644
--- a/scripts/benchmarks/package.json
+++ b/scripts/benchmarks/package.json
@@ -15,8 +15,8 @@
     "http-server": "^14.0.0",
     "parcel": "^2.0.1",
     "puppeteer": "^11.0.0",
-    "react": "16.14.0",
-    "react-dom": "16.14.0",
+    "react": "19.0.0",
+    "react-dom": "19.0.0",
     "react-native-web": "0.17.5",
     "stats-analysis": "^2.0.0"
   },
diff --git a/scripts/ssr-benchmarks/package.json b/scripts/ssr-benchmarks/package.json
index 23cd0c5243..18fab89893 100644
--- a/scripts/ssr-benchmarks/package.json
+++ b/scripts/ssr-benchmarks/package.json
@@ -10,7 +10,7 @@
   "dependencies": {
     "benchmark": "^2.1.4",
     "d3-scale-chromatic": "^3.0.0",
-    "react": "16.14.0",
-    "react-dom": "16.14.0"
+    "react": "19.0.0",
+    "react-dom": "19.0.0"
   }
 }
diff --git a/scripts/test-utils/src/index.js b/scripts/test-utils/src/index.js
index 0321886503..8f7d808ce6 100644
--- a/scripts/test-utils/src/index.js
+++ b/scripts/test-utils/src/index.js
@@ -12,7 +12,7 @@ export function ignoreConsoleErrors(cb /*: () => mixed */) {
   console.error = jest.fn()
 
   try {
-    cb()
+    return cb()
   } finally {
     console.error = oldConsoleError
   }
@@ -26,11 +26,6 @@ export let safeQuerySelector = (selector /*: string */) /*: HTMLElement */ => {
   return element
 }
 
-// React 18 doesn't use this attribute anymore
-// we normalize this to avoid snapshot mismatches between React versions
-export let stripDataReactRoot = (html /*: string*/) /*: string*/ =>
-  html.replace(' data-reactroot=""', '')
-
 const removeGlobalProp = prop => {
   let descriptor = Object.getOwnPropertyDescriptor(global, prop)
   Object.defineProperty(global, prop, {
diff --git a/site/package.json b/site/package.json
index 7ee8e2186f..4e29c48204 100644
--- a/site/package.json
+++ b/site/package.json
@@ -19,7 +19,7 @@
     "@types/js-yaml": "^4.0.5",
     "@types/node": "^12.20.37",
     "@types/prismjs": "^1.26.0",
-    "@types/react": "18.3.12",
+    "@types/react": "19.0.1",
     "@types/remark-prism": "^1.3.3",
     "facepaint": "^1.2.1",
     "gray-matter": "^4.0.3",
@@ -27,8 +27,8 @@
     "next": "^12.2.0",
     "next-mdx-remote": "^4.0.3",
     "prism-react-renderer": "^1.3.5",
-    "react": "16.14.0",
-    "react-dom": "16.14.0",
+    "react": "19.0.0",
+    "react-dom": "19.0.0",
     "react-simple-code-editor": "^0.11.2",
     "rehype-autolink-headings": "^6.1.1",
     "rehype-slug": "^5.0.1",
diff --git a/yarn.lock b/yarn.lock
index a5121e8ee2..b2495f0d2f 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2612,13 +2612,20 @@ __metadata:
   languageName: node
   linkType: hard
 
-"@definitelytyped/typescript-versions@npm:^0.0.112":
+"@definitelytyped/typescript-versions@npm:0.0.112":
   version: 0.0.112
   resolution: "@definitelytyped/typescript-versions@npm:0.0.112"
   checksum: eb3407eeb7af220206870024edafe9eb5fc9cc0835910cbf8b368fe3bf6e41f832d0be7ddbfbe5efe22c29e431f106183de844087edf49ecb2e4614b024a9ab4
   languageName: node
   linkType: hard
 
+"@definitelytyped/typescript-versions@patch:@definitelytyped/typescript-versions@npm%3A0.0.112#./.yarn/patches/@definitelytyped-typescript-versions-npm-0.0.112-f668f50e03.patch::locator=emotion-monorepo%40workspace%3A.":
+  version: 0.0.112
+  resolution: "@definitelytyped/typescript-versions@patch:@definitelytyped/typescript-versions@npm%3A0.0.112#./.yarn/patches/@definitelytyped-typescript-versions-npm-0.0.112-f668f50e03.patch::version=0.0.112&hash=1df6e3&locator=emotion-monorepo%40workspace%3A."
+  checksum: 962aa73c633040d247dfeeda0d9548b6a48342c6be1fac1586c75dc5c5cfbb1c0e6d11a187d6e7100eddef311f21c8cccf399d5ec271b9500e930064e050cc45
+  languageName: node
+  linkType: hard
+
 "@definitelytyped/utils@npm:^0.0.112":
   version: 0.0.112
   resolution: "@definitelytyped/utils@npm:0.0.112"
@@ -2798,9 +2805,10 @@ __metadata:
     chalk: ^4.1.0
     enzyme-to-json: ^3.6.1
     pretty-format: ^22.4.3
-    react: 16.14.0
-    react-dom: 16.14.0
+    react: 19.0.0
+    react-dom: 19.0.0
     specificity: ^0.4.1
+    strip-ansi: ^6.0.1
     stylis: 4.2.0
     typescript: ^5.4.5
   peerDependencies:
@@ -2844,7 +2852,7 @@ __metadata:
     "@definitelytyped/dtslint": 0.0.112
     "@emotion/primitives-core": ^11.11.0
     "@types/react-native": ^0.63.2
-    react: 16.14.0
+    react: 19.0.0
     react-native: ^0.63.2
     typescript: ^5.4.5
   peerDependencies:
@@ -2859,10 +2867,10 @@ __metadata:
     "@emotion/react": 11.14.0
     "@types/css-to-react-native": ^3.0.0
     css-to-react-native: ^3.0.0
-    react: 16.14.0
+    react: 19.0.0
   peerDependencies:
     "@emotion/react": ^11.0.0-rc.0
-    react: ">=16.8.0"
+    react: ^19.0.0
   languageName: unknown
   linkType: soft
 
@@ -2873,10 +2881,10 @@ __metadata:
     "@emotion/babel-plugin": ^11.11.0
     "@emotion/is-prop-valid": ^1.2.1
     "@emotion/primitives-core": ^11.13.0
-    react: 16.14.0
+    react: 19.0.0
     react-primitives: ^0.8.1
   peerDependencies:
-    react: ">=16.8.0"
+    react: ^19.0.0
     react-primitives: ^0.8.1
   languageName: unknown
   linkType: soft
@@ -2898,11 +2906,11 @@ __metadata:
     "@emotion/utils": ^1.4.2
     "@emotion/weak-memoize": ^0.4.0
     html-tag-names: ^1.1.2
-    react: 16.14.0
+    react: 19.0.0
     svg-tag-names: ^1.1.1
     typescript: ^5.4.5
   peerDependencies:
-    react: ">=16.8.0"
+    react: ^19.0.0
   peerDependenciesMeta:
     "@types/react":
       optional: true
@@ -2968,11 +2976,11 @@ __metadata:
     "@emotion/utils": ^1.4.2
     "@types/hoist-non-react-statics": ^3.3.5
     hoist-non-react-statics: ^3.3.1
-    react: 16.14.0
+    react: 19.0.0
     typescript: ^5.4.5
   peerDependencies:
     "@emotion/react": ^11.0.0-rc.0
-    react: ">=16.8.0"
+    react: ^19.0.0
   peerDependenciesMeta:
     "@types/react":
       optional: true
@@ -2989,7 +2997,7 @@ __metadata:
   version: 0.0.0-use.local
   resolution: "@emotion/use-insertion-effect-with-fallbacks@workspace:packages/use-insertion-effect-with-fallbacks"
   dependencies:
-    react: 16.14.0
+    react: 19.0.0
   peerDependencies:
     react: ">=16.8.0"
   languageName: unknown
@@ -3768,19 +3776,6 @@ __metadata:
   languageName: node
   linkType: hard
 
-"@jest/types@npm:^27.4.2":
-  version: 27.4.2
-  resolution: "@jest/types@npm:27.4.2"
-  dependencies:
-    "@types/istanbul-lib-coverage": ^2.0.0
-    "@types/istanbul-reports": ^3.0.0
-    "@types/node": "*"
-    "@types/yargs": ^16.0.0
-    chalk: ^4.0.0
-  checksum: 1191022023e32763063cc1c8b1143fa316fb05db2f9698280a7bdbafcabd989e5fd64f8eb875b8a2e54c53f25dba45ed2eea8ced394d9e484da0fda674cd17a5
-  languageName: node
-  linkType: hard
-
 "@jest/types@npm:^29.6.3":
   version: 29.6.3
   resolution: "@jest/types@npm:29.6.3"
@@ -5728,32 +5723,39 @@ __metadata:
   languageName: node
   linkType: hard
 
-"@testing-library/dom@npm:^8.5.0":
-  version: 8.11.1
-  resolution: "@testing-library/dom@npm:8.11.1"
+"@testing-library/dom@npm:^10.4.0":
+  version: 10.4.0
+  resolution: "@testing-library/dom@npm:10.4.0"
   dependencies:
     "@babel/code-frame": ^7.10.4
     "@babel/runtime": ^7.12.5
-    "@types/aria-query": ^4.2.0
-    aria-query: ^5.0.0
+    "@types/aria-query": ^5.0.1
+    aria-query: 5.3.0
     chalk: ^4.1.0
     dom-accessibility-api: ^0.5.9
-    lz-string: ^1.4.4
+    lz-string: ^1.5.0
     pretty-format: ^27.0.2
-  checksum: 082104b104def94db071fe35f967124c52d387d995a61327cd60ed39c310126f4cde2fa51054c37977cd3a2082311795417413506ad1a14df1010bd1cbb02bc5
+  checksum: bb128b90be0c8cd78c5f5e67aa45f53de614cc048a2b50b230e736ec710805ac6c73375af354b83c74d710b3928d52b83a273a4cb89de4eb3efe49e91e706837
   languageName: node
   linkType: hard
 
-"@testing-library/react@npm:13.0.0-alpha.5":
-  version: 13.0.0-alpha.5
-  resolution: "@testing-library/react@npm:13.0.0-alpha.5"
+"@testing-library/react@npm:^16.1.0":
+  version: 16.1.0
+  resolution: "@testing-library/react@npm:16.1.0"
   dependencies:
     "@babel/runtime": ^7.12.5
-    "@testing-library/dom": ^8.5.0
   peerDependencies:
-    react: "*"
-    react-dom: "*"
-  checksum: cc9e684adcacb3ad7cb8265d52f3ef9fb292f8aece9ac54d22b55f9a89cfdee409fdcb940a14f374aa7ea5f52b22dcc9baa15ad98b7e6bdec3fe44d8082f4e88
+    "@testing-library/dom": ^10.0.0
+    "@types/react": ^18.0.0 || ^19.0.0
+    "@types/react-dom": ^18.0.0 || ^19.0.0
+    react: ^18.0.0 || ^19.0.0
+    react-dom: ^18.0.0 || ^19.0.0
+  peerDependenciesMeta:
+    "@types/react":
+      optional: true
+    "@types/react-dom":
+      optional: true
+  checksum: 5dc8e7abda23d108c29f43cdacd43fad750e981ee87ee8902fb349a2683f2f774ef1136f2d3ef3d9efb87e8b04426c43d7b46e95511cd7c9d37b10c3bdd3e9e2
   languageName: node
   linkType: hard
 
@@ -5884,10 +5886,10 @@ __metadata:
   languageName: node
   linkType: hard
 
-"@types/aria-query@npm:^4.2.0":
-  version: 4.2.0
-  resolution: "@types/aria-query@npm:4.2.0"
-  checksum: e4a3748c5511deb88e93c6faf2acb0730233ff75018e9aaed95e3d2833880e9d0eda7e08e4315a827872471779471585671d08bae00ac8b9813fc140194b52e5
+"@types/aria-query@npm:^5.0.1":
+  version: 5.0.4
+  resolution: "@types/aria-query@npm:5.0.4"
+  checksum: ad8b87e4ad64255db5f0a73bc2b4da9b146c38a3a8ab4d9306154334e0fc67ae64e76bfa298eebd1e71830591fb15987e5de7111bdb36a2221bdc379e3415fb0
   languageName: node
   linkType: hard
 
@@ -6356,13 +6358,6 @@ __metadata:
   languageName: node
   linkType: hard
 
-"@types/prop-types@npm:*":
-  version: 15.7.1
-  resolution: "@types/prop-types@npm:15.7.1"
-  checksum: f8b33d7d15a70d0b709bcf5f281c7647ca8aaeaf377431725b4fda4949f2845476652d355eec0cde2a62ba3f7a5fb3194788aebaecc2048eb28db201121c2310
-  languageName: node
-  linkType: hard
-
 "@types/q@npm:^1.5.1":
   version: 1.5.2
   resolution: "@types/q@npm:1.5.2"
@@ -6379,13 +6374,12 @@ __metadata:
   languageName: node
   linkType: hard
 
-"@types/react@npm:*, @types/react@npm:18.3.12, @types/react@npm:>=16":
-  version: 18.3.12
-  resolution: "@types/react@npm:18.3.12"
+"@types/react@npm:*, @types/react@npm:19.0.1, @types/react@npm:>=16":
+  version: 19.0.1
+  resolution: "@types/react@npm:19.0.1"
   dependencies:
-    "@types/prop-types": "*"
     csstype: ^3.0.2
-  checksum: 4ab1577a8c2105a5e316536f724117c90eee5f4bd5c137fc82a2253d8c1fd299dedaa07e8dfc95d6e2f04a4be3cb8b0e1b06098c6233ebd55c508d88099395b7
+  checksum: e5e05cdf5fc53804e94548ca4e139102fffaab95d4c19be821d30d81dbab75ca3e30b72f2e2e750b90fcb535058cb694c4403402f14eb8a19a1282629c8222d8
   languageName: node
   linkType: hard
 
@@ -6557,15 +6551,6 @@ __metadata:
   languageName: node
   linkType: hard
 
-"@types/yargs@npm:^16.0.0":
-  version: 16.0.4
-  resolution: "@types/yargs@npm:16.0.4"
-  dependencies:
-    "@types/yargs-parser": "*"
-  checksum: caa21d2c957592fe2184a8368c8cbe5a82a6c2e2f2893722e489f842dc5963293d2f3120bc06fe3933d60a3a0d1e2eb269649fd6b1947fe1820f8841ba611dd9
-  languageName: node
-  linkType: hard
-
 "@types/yargs@npm:^17.0.8":
   version: 17.0.32
   resolution: "@types/yargs@npm:17.0.32"
@@ -7822,6 +7807,15 @@ __metadata:
   languageName: node
   linkType: hard
 
+"aria-query@npm:5.3.0":
+  version: 5.3.0
+  resolution: "aria-query@npm:5.3.0"
+  dependencies:
+    dequal: ^2.0.3
+  checksum: 305bd73c76756117b59aba121d08f413c7ff5e80fa1b98e217a3443fcddb9a232ee790e24e432b59ae7625aebcf4c47cb01c2cac872994f0b426f5bdfcd96ba9
+  languageName: node
+  linkType: hard
+
 "aria-query@npm:^4.2.2":
   version: 4.2.2
   resolution: "aria-query@npm:4.2.2"
@@ -7832,13 +7826,6 @@ __metadata:
   languageName: node
   linkType: hard
 
-"aria-query@npm:^5.0.0":
-  version: 5.0.0
-  resolution: "aria-query@npm:5.0.0"
-  checksum: c41f98866c5a304561ee8cae55856711cddad6f3f85d8cb43cc5f79667078d9b8979ce32d244c1ff364e6463a4d0b6865804a33ccc717fed701b281cf7dc6296
-  languageName: node
-  linkType: hard
-
 "arity-n@npm:^1.0.4":
   version: 1.0.4
   resolution: "arity-n@npm:1.0.4"
@@ -8969,8 +8956,8 @@ __metadata:
     http-server: ^14.0.0
     parcel: ^2.0.1
     puppeteer: ^11.0.0
-    react: 16.14.0
-    react-dom: 16.14.0
+    react: 19.0.0
+    react-dom: 19.0.0
     react-native-web: 0.17.5
     stats-analysis: ^2.0.0
   languageName: unknown
@@ -10763,8 +10750,8 @@ __metadata:
   version: 0.0.0-use.local
   resolution: "cra-playground@workspace:playgrounds/cra"
   dependencies:
-    react: 16.14.0
-    react-dom: 16.14.0
+    react: 19.0.0
+    react-dom: 19.0.0
     react-scripts: 4.0.3
     theme-ui: ^0.12.0
   languageName: unknown
@@ -11991,6 +11978,13 @@ __metadata:
   languageName: node
   linkType: hard
 
+"dequal@npm:^2.0.3":
+  version: 2.0.3
+  resolution: "dequal@npm:2.0.3"
+  checksum: 8679b850e1a3d0ebbc46ee780d5df7b478c23f335887464023a631d1b9af051ad4a6595a44220f9ff8ff95a8ddccf019b5ad778a976fd7bbf77383d36f412f90
+  languageName: node
+  linkType: hard
+
 "des.js@npm:^1.0.0":
   version: 1.0.0
   resolution: "des.js@npm:1.0.0"
@@ -12193,9 +12187,9 @@ __metadata:
   linkType: hard
 
 "dom-accessibility-api@npm:^0.5.9":
-  version: 0.5.10
-  resolution: "dom-accessibility-api@npm:0.5.10"
-  checksum: c05949889b02f5313d100778e9f736f9bddfb1da47387d351833f0b5d60d6230d4fcb849e124a8a1591706b6200337fa40f0f4f3817dce1459309e075f48371c
+  version: 0.5.16
+  resolution: "dom-accessibility-api@npm:0.5.16"
+  checksum: 005eb283caef57fc1adec4d5df4dd49189b628f2f575af45decb210e04d634459e3f1ee64f18b41e2dcf200c844bc1d9279d80807e686a30d69a4756151ad248
   languageName: node
   linkType: hard
 
@@ -12560,10 +12554,11 @@ __metadata:
     "@changesets/cli": ^2.27.7
     "@manypkg/cli": ^0.19.1
     "@preconstruct/cli": ^2.8.8
-    "@testing-library/react": 13.0.0-alpha.5
+    "@testing-library/dom": ^10.4.0
+    "@testing-library/react": ^16.1.0
     "@types/jest": ^29.5.12
     "@types/node": ^12.20.37
-    "@types/react": 18.3.12
+    "@types/react": 19.0.1
     "@typescript-eslint/eslint-plugin": ^7.13.0
     "@typescript-eslint/parser": ^7.13.0
     babel-check-duplicated-nodes: ^1.0.0
@@ -12601,14 +12596,11 @@ __metadata:
     polished: ^1.2.1
     prettier: ^3.3.2
     raf: ^3.4.0
-    react: 16.14.0
-    react-dom: 16.14.0
+    react: 19.0.0
+    react-dom: 19.0.0
     react-native: ^0.63.2
     react-primitives: ^0.8.1
-    react-test-renderer: 16.8.6
-    react18: "npm:react@18.0.0-rc.0-next-aa8f2bdbc-20211215"
-    react18-dom: "npm:react-dom@18.0.0-rc.0-next-aa8f2bdbc-20211215"
-    react18-test-renderer: "npm:react-test-renderer@18.0.0-rc.0-next-aa8f2bdbc-20211215"
+    react-test-renderer: 19.0.0
     svg-tag-names: ^1.1.1
     through: ^2.3.8
     typescript: ^5.4.5
@@ -12632,7 +12624,7 @@ __metadata:
     "@types/js-yaml": ^4.0.5
     "@types/node": ^12.20.37
     "@types/prismjs": ^1.26.0
-    "@types/react": 18.3.12
+    "@types/react": 19.0.1
     "@types/remark-prism": ^1.3.3
     facepaint: ^1.2.1
     gray-matter: ^4.0.3
@@ -12640,8 +12632,8 @@ __metadata:
     next: ^12.2.0
     next-mdx-remote: ^4.0.3
     prism-react-renderer: ^1.3.5
-    react: 16.14.0
-    react-dom: 16.14.0
+    react: 19.0.0
+    react-dom: 19.0.0
     react-simple-code-editor: ^0.11.2
     rehype-autolink-headings: ^6.1.1
     rehype-slug: ^5.0.1
@@ -20504,12 +20496,12 @@ __metadata:
   languageName: node
   linkType: hard
 
-"lz-string@npm:^1.4.4":
-  version: 1.4.4
-  resolution: "lz-string@npm:1.4.4"
+"lz-string@npm:^1.5.0":
+  version: 1.5.0
+  resolution: "lz-string@npm:1.5.0"
   bin:
     lz-string: bin/bin.js
-  checksum: 54e31238a61a84d8f664d9860a9fba7310c5b97a52c444f80543069bc084815eff40b8d4474ae1d93992fdf6c252dca37cf27f6adbeb4dbc3df2f3ac773d0e61
+  checksum: 1ee98b4580246fd90dd54da6e346fb1caefcf05f677c686d9af237a157fdea3fd7c83a4bc58f858cd5b10a34d27afe0fdcbd0505a47e0590726a873dc8b8f65d
   languageName: node
   linkType: hard
 
@@ -22603,8 +22595,8 @@ __metadata:
   resolution: "nextjs-playground@workspace:playgrounds/nextjs"
   dependencies:
     next: ^12.2.0
-    react: 16.14.0
-    react-dom: 16.14.0
+    react: 19.0.0
+    react-dom: 19.0.0
   languageName: unknown
   linkType: soft
 
@@ -25998,14 +25990,13 @@ __metadata:
   linkType: hard
 
 "pretty-format@npm:^27.0.2":
-  version: 27.4.2
-  resolution: "pretty-format@npm:27.4.2"
+  version: 27.5.1
+  resolution: "pretty-format@npm:27.5.1"
   dependencies:
-    "@jest/types": ^27.4.2
     ansi-regex: ^5.0.1
     ansi-styles: ^5.0.0
     react-is: ^17.0.1
-  checksum: 0daaf00c4dcb35493e57d30147e8045d0c45cb47fc4c94e3ab1892401abe939627c39975c77cc81eb2581aaa5b12bf23ef669fa550bec68b396fb79dd8c10afa
+  checksum: cf610cffcb793885d16f184a62162f2dd0df31642d9a18edf4ca298e909a8fe80bdbf556d5c9573992c102ce8bf948691da91bf9739bee0ffb6e79c8a8a6e088
   languageName: node
   linkType: hard
 
@@ -26133,7 +26124,7 @@ __metadata:
   languageName: node
   linkType: hard
 
-"prop-types@npm:^15.6.0, prop-types@npm:^15.6.2, prop-types@npm:^15.7.2":
+"prop-types@npm:^15.6.0, prop-types@npm:^15.7.2":
   version: 15.7.2
   resolution: "prop-types@npm:15.7.2"
   dependencies:
@@ -26520,17 +26511,14 @@ __metadata:
   languageName: node
   linkType: hard
 
-"react-dom@npm:16.14.0":
-  version: 16.14.0
-  resolution: "react-dom@npm:16.14.0"
+"react-dom@npm:19.0.0":
+  version: 19.0.0
+  resolution: "react-dom@npm:19.0.0"
   dependencies:
-    loose-envify: ^1.1.0
-    object-assign: ^4.1.1
-    prop-types: ^15.6.2
-    scheduler: ^0.19.1
+    scheduler: ^0.25.0
   peerDependencies:
-    react: ^16.14.0
-  checksum: 5a5c49da0f106b2655a69f96c622c347febcd10532db391c262b26aec225b235357d9da1834103457683482ab1b229af7a50f6927a6b70e53150275e31785544
+    react: ^19.0.0
+  checksum: 009cc6e575263a0d1906f9dd4aa6532d2d3d0d71e4c2b7777c8fe4de585fa06b5b77cdc2e0fbaa2f3a4a5e5d3305c189ba152153f358ee7da4d9d9ba5d3a8975
   languageName: node
   linkType: hard
 
@@ -26541,21 +26529,7 @@ __metadata:
   languageName: node
   linkType: hard
 
-"react-is@npm:18.0.0-rc.0-next-aa8f2bdbc-20211215":
-  version: 18.0.0-rc.0-next-aa8f2bdbc-20211215
-  resolution: "react-is@npm:18.0.0-rc.0-next-aa8f2bdbc-20211215"
-  checksum: fe6a2d1ce2c876f7dd950a04ed4f19b40b0ccca22f6d139f9dda294c1f332c5b987cccf17f9f0b84087df54460b0c43f60f572fbf53d75b16aff73b59e38db58
-  languageName: node
-  linkType: hard
-
-"react-is@npm:^16.12.0 || ^17.0.0, react-is@npm:^17.0.1":
-  version: 17.0.2
-  resolution: "react-is@npm:17.0.2"
-  checksum: 9d6d111d8990dc98bc5402c1266a808b0459b5d54830bbea24c12d908b536df7883f268a7868cfaedde3dd9d4e0d574db456f84d2e6df9c4526f99bb4b5344d8
-  languageName: node
-  linkType: hard
-
-"react-is@npm:^16.12.0, react-is@npm:^16.7.0, react-is@npm:^16.8.1, react-is@npm:^16.8.4, react-is@npm:^16.8.6":
+"react-is@npm:^16.12.0, react-is@npm:^16.7.0, react-is@npm:^16.8.1, react-is@npm:^16.8.4":
   version: 16.12.0
   resolution: "react-is@npm:16.12.0"
   checksum: 344dea88c669e94043426bffa8375414efcece8a84f0afba115b9d4d528d74f79e181e9ec57f60f0efb7204e631fb1ac885da2b2c5c67f1348a4f1e8e1654653
@@ -26569,6 +26543,13 @@ __metadata:
   languageName: node
   linkType: hard
 
+"react-is@npm:^17.0.1":
+  version: 17.0.2
+  resolution: "react-is@npm:17.0.2"
+  checksum: 9d6d111d8990dc98bc5402c1266a808b0459b5d54830bbea24c12d908b536df7883f268a7868cfaedde3dd9d4e0d574db456f84d2e6df9c4526f99bb4b5344d8
+  languageName: node
+  linkType: hard
+
 "react-is@npm:^18.0.0":
   version: 18.2.0
   resolution: "react-is@npm:18.2.0"
@@ -26576,6 +26557,13 @@ __metadata:
   languageName: node
   linkType: hard
 
+"react-is@npm:^19.0.0":
+  version: 19.0.0
+  resolution: "react-is@npm:19.0.0"
+  checksum: fbb3060bcb6b3e8e525b17f0872d1cf62a40b73fa7c5de02419069e2edd3e01cf1e8e86c8888f0733cff006175ee76ae927b40b6f0c4332bdda21020505ac90b
+  languageName: node
+  linkType: hard
+
 "react-native-web@npm:0.17.5":
   version: 0.17.5
   resolution: "react-native-web@npm:0.17.5"
@@ -26749,18 +26737,6 @@ __metadata:
   languageName: node
   linkType: hard
 
-"react-shallow-renderer@npm:^16.13.1":
-  version: 16.14.1
-  resolution: "react-shallow-renderer@npm:16.14.1"
-  dependencies:
-    object-assign: ^4.1.1
-    react-is: ^16.12.0 || ^17.0.0
-  peerDependencies:
-    react: ^16.0.0 || ^17.0.0
-  checksum: f344c663c48720d19559b4198b1f63ad47a3f11bedc92ede053a6c0706b5209e6110086f3ccc6db04eda9f0d1a415845956ddfb6ce09a922167d4831fcba9314
-  languageName: node
-  linkType: hard
-
 "react-simple-code-editor@npm:^0.11.2":
   version: 0.11.2
   resolution: "react-simple-code-editor@npm:0.11.2"
@@ -26771,17 +26747,15 @@ __metadata:
   languageName: node
   linkType: hard
 
-"react-test-renderer@npm:16.8.6":
-  version: 16.8.6
-  resolution: "react-test-renderer@npm:16.8.6"
+"react-test-renderer@npm:19.0.0":
+  version: 19.0.0
+  resolution: "react-test-renderer@npm:19.0.0"
   dependencies:
-    object-assign: ^4.1.1
-    prop-types: ^15.6.2
-    react-is: ^16.8.6
-    scheduler: ^0.13.6
+    react-is: ^19.0.0
+    scheduler: ^0.25.0
   peerDependencies:
-    react: ^16.0.0
-  checksum: b35014a515ee8c90432a9bf677e6d3a59af9ac7fb2ae8b59e54278596bb34e22a13788b7bc4348aa19acdfac48cf40d514d2dfa53fe972d92c4c4194e4f2b7c9
+    react: ^19.0.0
+  checksum: 2e1e527588c69e822b7aa25262c9f4a48161ede9cee5109b88228ecafbd91ce82f7afed176645efcba903ba5a43d05842a8229cdde220049e42a0cf679715dbc
   languageName: node
   linkType: hard
 
@@ -26792,51 +26766,10 @@ __metadata:
   languageName: node
   linkType: hard
 
-"react18-dom@npm:react-dom@18.0.0-rc.0-next-aa8f2bdbc-20211215":
-  version: 18.0.0-rc.0-next-aa8f2bdbc-20211215
-  resolution: "react-dom@npm:18.0.0-rc.0-next-aa8f2bdbc-20211215"
-  dependencies:
-    loose-envify: ^1.1.0
-    object-assign: ^4.1.1
-    scheduler: 0.21.0-rc.0-next-aa8f2bdbc-20211215
-  peerDependencies:
-    react: 18.0.0-rc.0-next-aa8f2bdbc-20211215
-  checksum: 66b259a0ff51455ca5d6f9f7760833495d3389f8d35b373360db868b1de32de8344e594895c63cd8c5dfa37bb3b7a53273b79a96731bbc3ce14c84079f95c86c
-  languageName: node
-  linkType: hard
-
-"react18-test-renderer@npm:react-test-renderer@18.0.0-rc.0-next-aa8f2bdbc-20211215":
-  version: 18.0.0-rc.0-next-aa8f2bdbc-20211215
-  resolution: "react-test-renderer@npm:18.0.0-rc.0-next-aa8f2bdbc-20211215"
-  dependencies:
-    object-assign: ^4.1.1
-    react-is: 18.0.0-rc.0-next-aa8f2bdbc-20211215
-    react-shallow-renderer: ^16.13.1
-    scheduler: 0.21.0-rc.0-next-aa8f2bdbc-20211215
-  peerDependencies:
-    react: 18.0.0-rc.0-next-aa8f2bdbc-20211215
-  checksum: 2f2e280bf83b264d26ffe1e75fcb4d00fe125920cb83eb1bd1afe6817b8098a6aa4edcb7cd5751c2cb78160fd7cce3ae5ccf3fbd7b80b9e3283a6fa5327e835b
-  languageName: node
-  linkType: hard
-
-"react18@npm:react@18.0.0-rc.0-next-aa8f2bdbc-20211215":
-  version: 18.0.0-rc.0-next-aa8f2bdbc-20211215
-  resolution: "react@npm:18.0.0-rc.0-next-aa8f2bdbc-20211215"
-  dependencies:
-    loose-envify: ^1.1.0
-    object-assign: ^4.1.1
-  checksum: 7be918fe040ef467c37035d8ef497aaafc64564588f8f9cfe49aeeecbdd0189e8d6a698821af91b17b05afc06ac15bbdc7e2ab1a59f74d2d4735284e74a2b8f9
-  languageName: node
-  linkType: hard
-
-"react@npm:16.14.0":
-  version: 16.14.0
-  resolution: "react@npm:16.14.0"
-  dependencies:
-    loose-envify: ^1.1.0
-    object-assign: ^4.1.1
-    prop-types: ^15.6.2
-  checksum: 8484f3ecb13414526f2a7412190575fc134da785c02695eb92bb6028c930bfe1c238d7be2a125088fec663cc7cda0a3623373c46807cf2c281f49c34b79881ac
+"react@npm:19.0.0":
+  version: 19.0.0
+  resolution: "react@npm:19.0.0"
+  checksum: 86de15d85b2465feb40297a90319c325cb07cf27191a361d47bcfe8c6126c973d660125aa67b8f4cbbe39f15a2f32efd0c814e98196d8e5b68c567ba40a399c6
   languageName: node
   linkType: hard
 
@@ -28194,7 +28127,7 @@ __metadata:
   languageName: node
   linkType: hard
 
-"scheduler@npm:0.19.1, scheduler@npm:^0.19.1":
+"scheduler@npm:0.19.1":
   version: 0.19.1
   resolution: "scheduler@npm:0.19.1"
   dependencies:
@@ -28204,23 +28137,10 @@ __metadata:
   languageName: node
   linkType: hard
 
-"scheduler@npm:0.21.0-rc.0-next-aa8f2bdbc-20211215":
-  version: 0.21.0-rc.0-next-aa8f2bdbc-20211215
-  resolution: "scheduler@npm:0.21.0-rc.0-next-aa8f2bdbc-20211215"
-  dependencies:
-    loose-envify: ^1.1.0
-    object-assign: ^4.1.1
-  checksum: 24ff46a9cb6645fb0ea6506dc3e090c0befcd03707cf4d962a972a19cbdbe4eeb34cf06b127e2c58417c21e7939edb3baa6805b319f8f7779c4addf0fd15d3c2
-  languageName: node
-  linkType: hard
-
-"scheduler@npm:^0.13.6":
-  version: 0.13.6
-  resolution: "scheduler@npm:0.13.6"
-  dependencies:
-    loose-envify: ^1.1.0
-    object-assign: ^4.1.1
-  checksum: c82c705f6d0d6df87b26bf2cca33f427e91889438c0435ade3ee7f41860eda4dd7f3171ca2d93e8fe9431f3bd831ca0e267a401a0296e4b14de05e389f82d320
+"scheduler@npm:^0.25.0":
+  version: 0.25.0
+  resolution: "scheduler@npm:0.25.0"
+  checksum: b7bb9fddbf743e521e9aaa5198a03ae823f5e104ebee0cb9ec625392bb7da0baa1c28ab29cee4b1e407a94e76acc6eee91eeb749614f91f853efda2613531566
   languageName: node
   linkType: hard
 
@@ -29163,8 +29083,8 @@ __metadata:
   dependencies:
     benchmark: ^2.1.4
     d3-scale-chromatic: ^3.0.0
-    react: 16.14.0
-    react-dom: 16.14.0
+    react: 19.0.0
+    react-dom: 19.0.0
   languageName: unknown
   linkType: soft