{"id":13452099,"url":"https://github.com/styled-components/jest-styled-components","last_synced_at":"2026-04-01T22:35:38.170Z","repository":{"id":18831538,"uuid":"85395980","full_name":"styled-components/jest-styled-components","owner":"styled-components","description":"🔧 💅 Jest utilities for Styled Components","archived":false,"fork":false,"pushed_at":"2026-03-23T20:14:02.000Z","size":2370,"stargazers_count":1583,"open_issues_count":8,"forks_count":146,"subscribers_count":30,"default_branch":"main","last_synced_at":"2026-03-27T00:52:49.643Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/styled-components.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":"probablyup","open_collective":null,"ko_fi":null,"tidelift":null,"community_bridge":null,"liberapay":null,"issuehunt":null,"otechie":null,"custom":null}},"created_at":"2017-03-18T11:22:41.000Z","updated_at":"2026-03-22T05:21:24.000Z","dependencies_parsed_at":"2024-07-31T07:24:05.579Z","dependency_job_id":null,"html_url":"https://github.com/styled-components/jest-styled-components","commit_stats":{"total_commits":331,"total_committers":60,"mean_commits":5.516666666666667,"dds":"0.47432024169184295","last_synced_commit":"7cc67f78d92f747cee64d81b2ea711d6ec39e0a9"},"previous_names":["michelebertoli/jest-styled-components"],"tags_count":79,"template":false,"template_full_name":null,"purl":"pkg:github/styled-components/jest-styled-components","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/styled-components%2Fjest-styled-components","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/styled-components%2Fjest-styled-components/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/styled-components%2Fjest-styled-components/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/styled-components%2Fjest-styled-components/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/styled-components","download_url":"https://codeload.github.com/styled-components/jest-styled-components/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/styled-components%2Fjest-styled-components/sbom","scorecard":{"id":114060,"data":{"date":"2025-08-04","repo":{"name":"github.com/styled-components/jest-styled-components","commit":"7cc67f78d92f747cee64d81b2ea711d6ec39e0a9"},"scorecard":{"version":"v5.2.1-28-gc1d103a9","commit":"c1d103a9bb9f635ec7260bf9aa0699466fa4be0e"},"score":3.7,"checks":[{"name":"Code-Review","score":4,"reason":"Found 6/15 approved changesets -- score normalized to 4","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/c1d103a9bb9f635ec7260bf9aa0699466fa4be0e/docs/checks.md#code-review"}},{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/c1d103a9bb9f635ec7260bf9aa0699466fa4be0e/docs/checks.md#dangerous-workflow"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/c1d103a9bb9f635ec7260bf9aa0699466fa4be0e/docs/checks.md#packaging"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/c1d103a9bb9f635ec7260bf9aa0699466fa4be0e/docs/checks.md#maintained"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/c1d103a9bb9f635ec7260bf9aa0699466fa4be0e/docs/checks.md#binary-artifacts"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Info: jobLevel 'actions' permission set to 'read': .github/workflows/codeql-analysis.yml:28","Info: jobLevel 'contents' permission set to 'read': .github/workflows/codeql-analysis.yml:29","Warn: no topLevel permission defined: .github/workflows/ci.yml:1","Warn: no topLevel permission defined: .github/workflows/codeql-analysis.yml:1","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/c1d103a9bb9f635ec7260bf9aa0699466fa4be0e/docs/checks.md#token-permissions"}},{"name":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:13: update your workflow using https://app.stepsecurity.io/secureworkflow/styled-components/jest-styled-components/ci.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:16: update your workflow using https://app.stepsecurity.io/secureworkflow/styled-components/jest-styled-components/ci.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:25: update your workflow using https://app.stepsecurity.io/secureworkflow/styled-components/jest-styled-components/ci.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/codeql-analysis.yml:42: update your workflow using https://app.stepsecurity.io/secureworkflow/styled-components/jest-styled-components/codeql-analysis.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/codeql-analysis.yml:46: update your workflow using https://app.stepsecurity.io/secureworkflow/styled-components/jest-styled-components/codeql-analysis.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/codeql-analysis.yml:57: update your workflow using https://app.stepsecurity.io/secureworkflow/styled-components/jest-styled-components/codeql-analysis.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/codeql-analysis.yml:71: update your workflow using https://app.stepsecurity.io/secureworkflow/styled-components/jest-styled-components/codeql-analysis.yml/main?enable=pin","Info:   0 out of   7 GitHub-owned GitHubAction dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/c1d103a9bb9f635ec7260bf9aa0699466fa4be0e/docs/checks.md#pinned-dependencies"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/c1d103a9bb9f635ec7260bf9aa0699466fa4be0e/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/c1d103a9bb9f635ec7260bf9aa0699466fa4be0e/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/c1d103a9bb9f635ec7260bf9aa0699466fa4be0e/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/c1d103a9bb9f635ec7260bf9aa0699466fa4be0e/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/c1d103a9bb9f635ec7260bf9aa0699466fa4be0e/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":-1,"reason":"internal error: error during branchesHandler.setup: internal error: githubv4.Query: Resource not accessible by integration","details":null,"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/c1d103a9bb9f635ec7260bf9aa0699466fa4be0e/docs/checks.md#branch-protection"}},{"name":"SAST","score":7,"reason":"SAST tool detected but not run on all commits","details":["Info: SAST configuration detected: CodeQL","Warn: 0 commits out of 22 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/c1d103a9bb9f635ec7260bf9aa0699466fa4be0e/docs/checks.md#sast"}},{"name":"Vulnerabilities","score":0,"reason":"19 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: GHSA-prr3-c3m5-p7q2","Warn: Project is vulnerable to: GHSA-968p-4wvh-cqc8","Warn: Project is vulnerable to: GHSA-67hx-6x53-jw92","Warn: Project is vulnerable to: GHSA-v6h2-p8h4-qcjw","Warn: Project is vulnerable to: GHSA-grv7-fg5c-xmjg","Warn: Project is vulnerable to: GHSA-3xgq-45jj-v275","Warn: Project is vulnerable to: GHSA-fjxv-7rqg-78g4","Warn: Project is vulnerable to: GHSA-7mhc-prgv-r3q4","Warn: Project is vulnerable to: GHSA-78xj-cgh5-2h22","Warn: Project is vulnerable to: GHSA-2p57-rm9w-gvfp","Warn: Project is vulnerable to: GHSA-952p-6rrq-rcjv","Warn: Project is vulnerable to: GHSA-mwcw-c2x4-8c55","Warn: Project is vulnerable to: GHSA-76c9-3jph-rj3q","Warn: Project is vulnerable to: GHSA-rxrc-rgv4-jpvx","Warn: Project is vulnerable to: GHSA-c2qf-rxjj-qqgw","Warn: Project is vulnerable to: GHSA-m6fv-jmcg-4jfg","Warn: Project is vulnerable to: GHSA-cm22-4g7w-348p","Warn: Project is vulnerable to: GHSA-g4rg-993r-mgx7","Warn: Project is vulnerable to: GHSA-3h5v-q93c-6h6q"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/c1d103a9bb9f635ec7260bf9aa0699466fa4be0e/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-15T22:37:37.515Z","repository_id":18831538,"created_at":"2025-08-15T22:37:37.515Z","updated_at":"2025-08-15T22:37:37.515Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31292666,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-01T21:15:39.731Z","status":"ssl_error","status_checked_at":"2026-04-01T21:15:34.046Z","response_time":53,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-07-31T07:01:12.901Z","updated_at":"2026-04-01T22:35:38.154Z","avatar_url":"https://github.com/styled-components.png","language":"JavaScript","funding_links":["https://github.com/sponsors/probablyup","https://opencollective.com/styled-components"],"categories":["JavaScript","Please find below the links to awesome cheat-sheet and resources:","Packages"],"sub_categories":["React/React-Native:","Snapshot"],"readme":"[![NPM version](https://img.shields.io/npm/v/jest-styled-components.svg)](https://www.npmjs.com/package/jest-styled-components)\n[![CI](https://github.com/styled-components/jest-styled-components/actions/workflows/ci.yml/badge.svg)](https://github.com/styled-components/jest-styled-components/actions/workflows/ci.yml)\n\n# jest-styled-components\n\nTesting utilities for [styled-components](https://github.com/styled-components/styled-components) (v5+). Works with Jest, Vitest, and Bun.\n\nstyled-components is largely maintained by one person. Please help fund the project for consistent long-term support and updates: [Open Collective](https://opencollective.com/styled-components)\n\n---\n\n**The problem:** styled-components snapshots contain opaque hashed class names and no CSS rules. When styles change, diffs show meaningless class name changes.\n\n**The solution:** This library inlines actual CSS rules into snapshots with deterministic class placeholders (`c0`, `c1`, `k0`, `k1`) and provides a `toHaveStyleRule` matcher for asserting specific style values.\n\n```diff\n- Snapshot\n+ Received\n\n .c0 {\n-  color: green;\n+  color: blue;\n }\n\n \u003cbutton\n   class=\"c0\"\n /\u003e\n```\n\n## Table of Contents\n\n- [Installation](#installation)\n- [Setup](#setup)\n- [Quick Example](#quick-example)\n- [Snapshot Testing](#snapshot-testing)\n- [toHaveStyleRule](#tohavestylerule)\n- [React Native](#react-native)\n- [Advanced Usage](#advanced-usage)\n- [Version Compatibility](#version-compatibility)\n- [Troubleshooting](#troubleshooting)\n- [Legacy: Enzyme](#legacy-enzyme)\n\n## Installation\n\n```sh\nnpm install --save-dev jest-styled-components\n```\n```sh\npnpm add -D jest-styled-components\n```\n```sh\nyarn add -D jest-styled-components\n```\n```sh\nbun add -D jest-styled-components\n```\n\n## Setup\n\nImport once in a setup file to register the snapshot serializer and `toHaveStyleRule` matcher globally.\n\n### Jest\n\n```js\n// setupTests.js\nimport 'jest-styled-components'\n```\n\n```js\n// jest.config.js\nmodule.exports = {\n  testEnvironment: 'jsdom',\n  setupFilesAfterEnv: ['\u003crootDir\u003e/setupTests.js'],\n}\n```\n\nNote: Jest 27+ defaults to the `node` environment. styled-components requires a DOM, so `testEnvironment: 'jsdom'` is required. You may also need to install `jest-environment-jsdom` separately for Jest 28+.\n\n### Vitest\n\n```js\n// setupTests.ts\nimport 'jest-styled-components/vitest'\n```\n\n```ts\n// vitest.config.ts\nimport { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    setupFiles: ['./setupTests.ts'],\n  },\n})\n```\n\nThe Vitest entry point imports `expect` and `beforeEach` from Vitest explicitly. TypeScript types are included.\n\n### Bun\n\n```js\n// setupTests.ts\nimport 'jest-styled-components'\n```\n\nBun provides the `expect` and `beforeEach` globals that the library hooks into. Configure `preload` in your `bunfig.toml`:\n\n```toml\n[test]\npreload = [\"./setupTests.ts\"]\n```\n\n## Quick Example\n\n```js\nimport React from 'react'\nimport styled from 'styled-components'\nimport { render } from '@testing-library/react'\nimport 'jest-styled-components'\n\nconst Button = styled.button`\n  color: red;\n`\n\ntest('it works', () =\u003e {\n  const { container } = render(\u003cButton /\u003e)\n  expect(container.firstChild).toMatchSnapshot()\n  expect(container.firstChild).toHaveStyleRule('color', 'red')\n})\n```\n\n## Snapshot Testing\n\nThe serializer replaces hashed class names with sequential placeholders (`c0`, `c1` for classes, `k0`, `k1` for keyframes) and prepends the matching CSS rules to the snapshot output. This works with `@testing-library/react`, `react-test-renderer`, and Enzyme.\n\n### Theming\n\nWrap with `ThemeProvider` as you would in your app:\n\n```js\nimport { ThemeProvider } from 'styled-components'\n\nconst theme = { main: 'mediumseagreen' }\n\ntest('themed component', () =\u003e {\n  const { container } = render(\n    \u003cThemeProvider theme={theme}\u003e\n      \u003cButton /\u003e\n    \u003c/ThemeProvider\u003e\n  )\n  expect(container.firstChild).toHaveStyleRule('color', 'mediumseagreen')\n})\n```\n\n## toHaveStyleRule\n\n```\nexpect(element).toHaveStyleRule(property, value?, options?)\n```\n\nAsserts that a CSS property has the expected value on a styled component. The `value` argument accepts a string, RegExp, asymmetric matcher (e.g. `expect.stringContaining()`), or `undefined` to assert the property is not set. When used with `.not`, `value` is optional.\n\n```js\nconst Button = styled.button`\n  color: red;\n  border: 0.05em solid ${props =\u003e props.transparent ? 'transparent' : 'black'};\n  cursor: ${props =\u003e !props.disabled \u0026\u0026 'pointer'};\n  opacity: ${props =\u003e props.disabled \u0026\u0026 '.65'};\n`\n\ntest('default styles', () =\u003e {\n  const { container } = render(\u003cButton /\u003e)\n  expect(container.firstChild).toHaveStyleRule('color', 'red')\n  expect(container.firstChild).toHaveStyleRule('border', '0.05em solid black')\n  expect(container.firstChild).toHaveStyleRule('cursor', 'pointer')\n  expect(container.firstChild).not.toHaveStyleRule('opacity')\n  expect(container.firstChild).toHaveStyleRule('opacity', undefined)\n})\n\ntest('prop-dependent styles', () =\u003e {\n  const { container } = render(\u003cButton disabled transparent /\u003e)\n  expect(container.firstChild).toHaveStyleRule('border', expect.stringContaining('transparent'))\n  expect(container.firstChild).toHaveStyleRule('cursor', undefined)\n  expect(container.firstChild).toHaveStyleRule('opacity', '.65')\n})\n```\n\n### Options\n\nThe third argument targets rules within at-rules, with selector modifiers, or by raw CSS selector.\n\n| Option | Type | Description |\n|---|---|---|\n| `container` | `string` | Match within a `@container` at-rule, e.g. `'(min-width: 400px)'` |\n| `layer` | `string` | Match within a `@layer` at-rule, e.g. `'utilities'` |\n| `media` | `string` | Match within a `@media` at-rule, e.g. `'(max-width: 640px)'` |\n| `supports` | `string` | Match within a `@supports` at-rule, e.g. `'(display: grid)'` |\n| `modifier` | `string \\| css` | Refine the selector: pseudo-selectors, combinators, `\u0026` references, or the `css` helper for component selectors |\n| `namespace` | `string` | Match rules prefixed by a `StyleSheetManager` namespace, e.g. `'#app'` |\n| `selector` | `string` | Match by raw CSS selector instead of component class. Useful for `createGlobalStyle` |\n\n### media and modifier\n\n```js\nconst Button = styled.button`\n  @media (max-width: 640px) {\n    \u0026:hover {\n      color: red;\n    }\n  }\n`\n\ntest('media + modifier', () =\u003e {\n  const { container } = render(\u003cButton /\u003e)\n  expect(container.firstChild).toHaveStyleRule('color', 'red', {\n    media: '(max-width:640px)',\n    modifier: ':hover',\n  })\n})\n```\n\n### supports\n\n```js\nconst Layout = styled.div`\n  @supports (display: grid) {\n    display: grid;\n  }\n`\n\ntest('supports query', () =\u003e {\n  const { container } = render(\u003cLayout /\u003e)\n  expect(container.firstChild).toHaveStyleRule('display', 'grid', {\n    supports: '(display:grid)',\n  })\n})\n```\n\n### container\n\n```js\nconst Card = styled.div`\n  container-type: inline-size;\n  @container (min-width: 400px) {\n    font-size: 1.5rem;\n  }\n`\n\ntest('container query', () =\u003e {\n  const { container } = render(\u003cCard /\u003e)\n  expect(container.firstChild).toHaveStyleRule('font-size', '1.5rem', {\n    container: '(min-width: 400px)',\n  })\n})\n```\n\n### layer\n\n```js\nconst Themed = styled.div`\n  @layer utilities {\n    color: red;\n  }\n`\n\ntest('layer query', () =\u003e {\n  const { container } = render(\u003cThemed /\u003e)\n  expect(container.firstChild).toHaveStyleRule('color', 'red', {\n    layer: 'utilities',\n  })\n})\n```\n\n### namespace (StyleSheetManager)\n\nWhen using `StyleSheetManager` with a `namespace` prop, all CSS selectors are prefixed with the namespace. Pass `namespace` so the matcher knows to expect the prefix:\n\n```js\nimport { StyleSheetManager } from 'styled-components'\n\nconst Box = styled.div`\n  color: blue;\n`\n\ntest('namespaced styles', () =\u003e {\n  const { container } = render(\n    \u003cStyleSheetManager namespace=\"#app\"\u003e\n      \u003cBox /\u003e\n    \u003c/StyleSheetManager\u003e\n  )\n  expect(container.firstChild).toHaveStyleRule('color', 'blue', {\n    namespace: '#app',\n  })\n})\n```\n\nTo avoid passing `namespace` on every assertion, set it globally in your setup file:\n\n```js\nimport { setStyleRuleOptions } from 'jest-styled-components'\n\nsetStyleRuleOptions({ namespace: '#app' })\n```\n\nThis applies to all subsequent `toHaveStyleRule` calls. Individual assertions can still override with their own `namespace` option.\n\n### modifier with component selectors\n\nWhen a rule targets another styled-component, use the `css` helper:\n\n```js\nimport { css } from 'styled-components'\n\nconst Button = styled.button`\n  color: red;\n`\n\nconst ButtonList = styled.div`\n  ${Button} {\n    flex: 1 0 auto;\n  }\n`\n\ntest('nested component selector', () =\u003e {\n  const { container } = render(\u003cButtonList\u003e\u003cButton /\u003e\u003c/ButtonList\u003e)\n  expect(container.firstChild).toHaveStyleRule('flex', '1 0 auto', {\n    modifier: css`${Button}`,\n  })\n})\n```\n\nClass name overrides work similarly:\n\n```js\nconst Button = styled.button`\n  background-color: red;\n  \u0026.override {\n    background-color: blue;\n  }\n`\n\ntest('class override', () =\u003e {\n  const { container } = render(\u003cButton className=\"override\" /\u003e)\n  expect(container.firstChild).toHaveStyleRule('background-color', 'blue', {\n    modifier: '\u0026.override',\n  })\n})\n```\n\n### selector (createGlobalStyle)\n\nThe `selector` option matches rules by raw CSS selector, bypassing component class name detection. This is the way to test `createGlobalStyle`:\n\n```js\nimport { createGlobalStyle } from 'styled-components'\n\nconst GlobalStyle = createGlobalStyle`\n  body {\n    background: white;\n  }\n`\n\ntest('global styles', () =\u003e {\n  render(\u003cGlobalStyle /\u003e)\n  expect(document.documentElement).toHaveStyleRule('background', 'white', {\n    selector: 'body',\n  })\n})\n```\n\nWhen `selector` is set, the component argument is ignored---any rendered element will work as the receiver.\n\n### Element selection\n\nThe matcher checks styles on the element it receives. To assert on nested elements, query for them first:\n\n```js\nconst { getByTestId } = render(\u003cMyComponent /\u003e)\nexpect(getByTestId('inner-button')).toHaveStyleRule('color', 'blue')\n```\n\n## React Native\n\nImport the native entry point instead:\n\n```js\nimport 'jest-styled-components/native'\n```\n\nThis registers only the `toHaveStyleRule` matcher adapted for React Native's style objects (no snapshot serializer needed). It handles style arrays and converts kebab-case properties to camelCase.\n\n```js\nimport React from 'react'\nimport styled from 'styled-components/native'\nimport renderer from 'react-test-renderer'\nimport 'jest-styled-components/native'\n\nconst Label = styled.Text`\n  color: green;\n`\n\ntest('native styles', () =\u003e {\n  const tree = renderer.create(\u003cLabel /\u003e).toJSON()\n  expect(tree).toHaveStyleRule('color', 'green')\n})\n```\n\n## Advanced Usage\n\n### Standalone Serializer\n\nThe serializer can be imported separately for use with libraries like [jest-specific-snapshot](https://github.com/igor-dv/jest-specific-snapshot):\n\n```js\nimport { styleSheetSerializer } from 'jest-styled-components/serializer'\nimport { addSerializer } from 'jest-specific-snapshot'\n\naddSerializer(styleSheetSerializer)\n```\n\n### Serializer Options\n\n```js\nimport { setStyleSheetSerializerOptions } from 'jest-styled-components/serializer'\n\nsetStyleSheetSerializerOptions({\n  addStyles: false,                          // omit CSS from snapshots\n  classNameFormatter: (index) =\u003e `styled${index}`,  // custom class placeholders\n})\n```\n\n### CSS Parse Caching\n\nBy default, `toHaveStyleRule` re-parses the stylesheet on every assertion. For test suites with many assertions, import the cached entry point to parse once and reuse the result when the stylesheet hasn't changed:\n\n```js\nimport 'jest-styled-components/cache'\n```\n\nThe cache automatically invalidates when the stylesheet changes and when `resetStyleSheet` runs between tests. No manual cleanup needed.\n\n### resetStyleSheet\n\nThe main entry point calls `resetStyleSheet()` in a `beforeEach` hook automatically. If you use the standalone serializer or a custom test setup where `beforeEach` is not globally available, call it manually:\n\n```js\nimport { resetStyleSheet } from 'jest-styled-components'\n\nresetStyleSheet()\n```\n\n## Version Compatibility\n\n| jest-styled-components | styled-components | Test Runner |\n|---|---|---|\n| 7.2+ | 5.x, 6.x | Jest 27+, Vitest 1+, Bun |\n| 7.0--7.1 | 5.x | Jest 27+ |\n| 6.x | 4.x--5.x | Jest 24--26 |\n\n## Troubleshooting\n\n### \"No style rules found on passed Component\"\n\nThe most common issue. Check these causes in order:\n\n1. **Wrong element.** The matcher needs the actual DOM element or react-test-renderer JSON node, not a wrapper. With `@testing-library/react`, use `container.firstChild`. With Enzyme, use `mount()` (not `shallow()` for most cases).\n2. **Multiple styled-components instances.** Common in monorepos. Run `npm ls styled-components` (or `pnpm why styled-components`) to check. See the [styled-components FAQ](https://www.styled-components.com/docs/faqs#why-am-i-getting-a-warning-about-several-instances-of-module-on-the-page) for resolution.\n3. **Version mismatch.** Ensure your jest-styled-components version supports your styled-components version (see [Version Compatibility](#version-compatibility)).\n\n### TypeScript: `toHaveStyleRule` not recognized\n\nThe package ships type declarations that augment Jest's `Matchers` interface. If TypeScript doesn't pick them up:\n\n**Jest:** Ensure your `tsconfig.json` includes the package in `types`, or that your setup file import (`import 'jest-styled-components'`) is within the TypeScript project's `include` paths.\n\n**Vitest:** Import from `jest-styled-components/vitest` (not the base entry point). This augments Vitest's `Assertion` interface.\n\n### Styles missing from snapshots\n\nIf snapshots show hashed class names instead of CSS rules, the serializer isn't registered. Verify:\n\n1. You're importing `jest-styled-components` (or `jest-styled-components/vitest` for Vitest) in your setup file.\n2. The setup file is referenced in your test runner config (`setupFilesAfterEnv` for Jest, `setupFiles` for Vitest).\n3. You don't have multiple instances of styled-components loaded (see above).\n\n### Testing `createGlobalStyle`\n\nGlobal styles don't attach to a specific component. Use the `selector` option to match by CSS selector:\n\n```js\nrender(\u003cGlobalStyle /\u003e)\nexpect(document.documentElement).toHaveStyleRule('background', 'white', {\n  selector: 'body',\n})\n```\n\n### Jest environment errors (`document is not defined`)\n\nJest 27+ defaults to the `node` test environment. Add `testEnvironment: 'jsdom'` to your Jest config. For Jest 28+, install `jest-environment-jsdom` as a separate dependency.\n\n## Legacy: Enzyme\n\n[Enzyme](https://github.com/enzymejs/enzyme) is no longer actively maintained. If you still use it, snapshot testing requires [enzyme-to-json](https://www.npmjs.com/package/enzyme-to-json) and `toHaveStyleRule` works with both shallow and mounted wrappers. Consider migrating to `@testing-library/react`.\n\n## Contributing\n\n[Open an issue](https://github.com/styled-components/jest-styled-components/issues/new) to discuss before submitting a PR.\n\n## License\n\nLicensed under the [MIT License](LICENSE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstyled-components%2Fjest-styled-components","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fstyled-components%2Fjest-styled-components","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstyled-components%2Fjest-styled-components/lists"}