Skip to content

Comments

[jest] @emotion/babel-preset-css-prop#216489

Merged
delanni merged 37 commits intoelastic:mainfrom
Dosant:d/2025-03-31-jest-babel-css
Apr 14, 2025
Merged

[jest] @emotion/babel-preset-css-prop#216489
delanni merged 37 commits intoelastic:mainfrom
Dosant:d/2025-03-31-jest-babel-css

Conversation

@Dosant
Copy link
Contributor

@Dosant Dosant commented Mar 31, 2025

Summary

Partially address #216459

This PR adds @emotion/babel-preset-css-prop to jest config to improve jest and emotion integration. There are some tradeoffs: this is a better setup for emotion + testing library, but there are some seemingly regressions for enzyme. We think these are right tradeoffs to make, since we optimize for emotion+testing library.

Main upsides are 😄

🟢 Fixes snapshots with css prop

You have tried to stringify object returned from \css` function. It isn't supposed to be used directly (e.g. as value of the `className` prop), but rather handed to emotion so it can handle it (e.g. as value of `css` prop).` is replaced with proper emotion css classname.

Screenshot 2025-04-04 at 14 57 52

🟢 We will be able to use jest style matchers for emotion toHaveStyleRule

https://emotion.sh/docs/@emotion/jest#tohavestylerule

they can be used locally now, but we plan to follow up with global extend

Considerations 🫤

🟡 jsx doesn't work inside jest.mock function

Example:

jest.mock('./components/alert_header_title', () => ({
    > 27 |   AlertHeaderTitle: jest.fn().mockReturnValue(<div></div>), 
         |                                                                           ^
      28 | }));

Fails with an error. can't read jsx of undefined.

This is because babel compiles this into:

import { jsx as ___EmotionJSX } from '@emotion/react'

jest.mock('./components/alert_header_title', () => ({
    > 27 |   AlertHeaderTitle: jest.fn().mockReturnValue(___EmotionJSX.jsx(….)), 
         |                                                                                   ^
      28 | }));

And, apparently, due to how jest imports work, __EmotionJSX is not yet in the scope.

The applied workaround is to rewrite to:

jest.mock('./components/alert_header_title', () => ({
  AlertHeaderTitle: jest.fn(() => <div></div>), 
     }));

🟡 euiTheme needs to be available when euiTheme is accessed inside css function

Example:

DashboardGrid removes panel when removed from container
    TypeError: Cannot read properties of undefined (reading 'size')
      42 |     margin: '-2px',
      43 |     position: 'absolute',
    > 44 |     width: euiTheme.size.l,

The fix was to wrap failing tests with <EuiProvider/>

Drawbacks 😢

Mostly related to Enzyme

🔴 Enzyme shallow snapshot no longer include css prop

Since css prop is compiled away there are bunch of snapshots that looks like a regression:

Example:

Screenshot 2025-04-04 at 15 50 16

This is unfortunate. We've tried @emotion/jest/enzyme-serializer but it didn't work (likely because enzyme ecosystem no longer supported?)
If it is important that the snapshot captures css, we recommend to use mount or rtl

🔴 Asserting against css prop with shallow render also doesn't work

Possible solution is to use

import { matchers } from '@emotion/jest';
expect.extend(matchers);

(We plan to add these matches globally in a follow up)

and

 expect(button).toHaveStyleRule('background-color', '#FFFFFF');

🔴 Some shallow Enzyme tests find() breaks because of code transformations of emotion

Example:

const component = shallow(
      <MetricVisValue />
)

component.find('button') // fails because instead of <button/> there is <EmotionInternalCss/> element now 

Solutions:

  • Use full mount or react testing library
  • Or target by data-test-subj

@Dosant Dosant changed the title D/2025 03 31 jest babel css [jest] @emotion/babel-preset-css-prop Apr 3, 2025
Dosant added 2 commits April 4, 2025 14:27
…st-babel-css

# Conflicts:
#	src/platform/plugins/shared/discover/public/application/main/components/session_view/main_app.test.tsx
Copy link
Contributor

@dplumlee dplumlee left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rule management changes lgtm

Copy link
Contributor

@adcoelho adcoelho left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

response-ops OK

Dosant added 5 commits April 10, 2025 17:54
…st-babel-css-merge

# Conflicts:
#	src/platform/packages/shared/shared-ux/code_editor/impl/__snapshots__/code_editor.test.tsx.snap
#	x-pack/solutions/security/plugins/security_solution/public/explore/network/components/arrows/__snapshots__/index.test.tsx.snap
Copy link
Contributor

@vitaliidm vitaliidm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

detection engine area LGTM

@elasticmachine
Copy link
Contributor

💚 Build Succeeded

Metrics [docs]

Async chunks

Total size of all lazy-loaded chunks that will be downloaded as the user navigates the app

id before after diff
enterpriseSearch 1.3MB 1.3MB +194.0B
expressionLegacyMetricVis 6.3KB 6.3KB +39.0B
monitoring 633.8KB 633.9KB +108.0B
total +341.0B
Unknown metric groups

ESLint disabled line counts

id before after diff
@kbn/ecs-data-quality-dashboard 11 8 -3
securitySolution 579 575 -4
total -7

Total ESLint disabled count

id before after diff
@kbn/ecs-data-quality-dashboard 11 8 -3
securitySolution 662 658 -4
total -7

History

@Dosant Dosant added backport:version Backport to applied version labels v8.19.0 and removed backport:skip This PR does not require backporting labels Apr 14, 2025
@delanni delanni merged commit ef0322d into elastic:main Apr 14, 2025
14 checks passed
@kibanamachine
Copy link
Contributor

Starting backport for target branches: 8.x

https://github.com/elastic/kibana/actions/runs/14445653423

@kibanamachine
Copy link
Contributor

💔 All backports failed

Status Branch Result
8.x Backport failed because of merge conflicts

You might need to backport the following PRs to 8.x:
- NavigationItemOpenPanel: remove handling of landing page ("four squares" design) (#210893)
- [Security Solution] EUI Refresh Followup Pt. 1 (#205990)

Manual backport

To create the backport manually run:

node scripts/backport --pr 216489

Questions ?

Please refer to the Backport tool documentation

@Dosant
Copy link
Contributor Author

Dosant commented Apr 14, 2025

💚 All backports created successfully

Status Branch Result
8.x

Note: Successful backport PRs will be merged automatically after passing CI.

Questions ?

Please refer to the Backport tool documentation

Dosant added a commit to Dosant/kibana that referenced this pull request Apr 14, 2025
## Summary

Partially address elastic#216459

This PR adds `@emotion/babel-preset-css-prop` to jest config to improve
jest and emotion integration. There are some tradeoffs: this is a better
setup for emotion + testing library, but there are some seemingly
regressions for enzyme. We think these are right tradeoffs to make,
since we optimize for emotion+testing library.

### Main upsides are 😄

#### 🟢 Fixes snapshots with css prop

`You have tried to stringify object returned from \`css\` function. It
isn't supposed to be used directly (e.g. as value of the \`className\`
prop), but rather handed to emotion so it can handle it (e.g. as value
of \`css\` prop).` is replaced with proper emotion css classname.

![Screenshot 2025-04-04 at 14 57
52](https://github.com/user-attachments/assets/f4a746d6-2451-4703-ab39-57be7171b10b)

#### 🟢 We will be able to use jest style matchers for emotion
`toHaveStyleRule`

https://emotion.sh/docs/@emotion/jest#tohavestylerule

_they can be used locally now, but we plan to follow up with global
extend_

###  Considerations 🫤

#### 🟡 jsx doesn't work inside jest.mock function

Example:

```
jest.mock('./components/alert_header_title', () => ({
    > 27 |   AlertHeaderTitle: jest.fn().mockReturnValue(<div></div>),
         |                                                                           ^
      28 | }));
```

Fails with an error. `can't read jsx of undefined`.

This is because babel compiles this into:

```
import { jsx as ___EmotionJSX } from '@emotion/react'

jest.mock('./components/alert_header_title', () => ({
    > 27 |   AlertHeaderTitle: jest.fn().mockReturnValue(___EmotionJSX.jsx(….)),
         |                                                                                   ^
      28 | }));
```

And, apparently, due to how jest imports work, __EmotionJSX is not yet
in the scope.

The applied workaround is to rewrite to:

```
jest.mock('./components/alert_header_title', () => ({
  AlertHeaderTitle: jest.fn(() => <div></div>),
     }));
```

#### 🟡 euiTheme needs to be available when euiTheme is accessed inside
`css` function

Example:

```
DashboardGrid removes panel when removed from container
    TypeError: Cannot read properties of undefined (reading 'size')
      42 |     margin: '-2px',
      43 |     position: 'absolute',
    > 44 |     width: euiTheme.size.l,
```

The fix was to wrap failing tests with `<EuiProvider/>`

### Drawbacks 😢

Mostly related to Enzyme

#### 🔴  Enzyme shallow snapshot no longer include `css` prop

Since `css` prop is compiled away there are bunch of snapshots that
looks like a regression:

Example:

![Screenshot 2025-04-04 at 15 50
16](https://github.com/user-attachments/assets/61c1d027-1e8a-48e6-a242-1fa53f8ec9b7)

This is unfortunate. We've tried `@emotion/jest/enzyme-serializer` but
it didn't work (likely because enzyme ecosystem no longer supported?)
If it is important that the snapshot captures css, we recommend to use
mount or rtl

#### 🔴 Asserting against `css` prop with shallow render also doesn't
work

Possible solution is to use

```
import { matchers } from '@emotion/jest';
expect.extend(matchers);
```

(We plan to add these matches globally in a follow up)

and

```
 expect(button).toHaveStyleRule('background-color', '#FFFFFF');
```

#### 🔴 Some shallow Enzyme tests `find()` breaks because of code
transformations of emotion

Example:

```
const component = shallow(
      <MetricVisValue />
)

component.find('button') // fails because instead of <button/> there is <EmotionInternalCss/> element now

```

Solutions:
- Use full mount or react testing library
- Or target by data-test-subj

---------

Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
Co-authored-by: Karen Grigoryan <karen.grigoryan@elastic.co>
(cherry picked from commit ef0322d)

# Conflicts:
#	src/core/packages/chrome/browser-internal/src/ui/header/__snapshots__/header.test.tsx.snap
#	src/core/packages/overlays/browser-internal/src/banners/banners_list.test.tsx
#	src/core/packages/overlays/browser-internal/src/flyout/__snapshots__/flyout_service.test.tsx.snap
#	src/platform/packages/private/kbn-reporting/public/share/share_context_menu/__snapshots__/screen_capture_panel_content.test.tsx.snap
#	src/platform/packages/shared/kbn-unified-data-table/src/components/compare_documents/hooks/__snapshots__/use_comparison_css.test.ts.snap
#	src/platform/packages/shared/shared-ux/avatar/solution/src/__snapshots__/solution_avatar.test.tsx.snap
#	src/platform/packages/shared/shared-ux/button_toolbar/src/popover/popover.test.tsx
#	src/platform/packages/shared/shared-ux/code_editor/impl/__snapshots__/code_editor.test.tsx.snap
#	src/platform/packages/shared/shared-ux/page/solution_nav/src/__snapshots__/solution_nav.test.tsx.snap
#	src/platform/plugins/private/input_control_vis/public/components/vis/__snapshots__/input_control_vis.test.tsx.snap
#	src/platform/plugins/private/vis_type_markdown/public/__snapshots__/markdown_options.test.tsx.snap
#	src/platform/plugins/shared/discover/public/application/main/discover_main_app.test.tsx
#	src/platform/plugins/shared/home/public/application/components/manage_data/__snapshots__/manage_data.test.tsx.snap
#	src/platform/plugins/shared/home/public/application/components/solutions_section/__snapshots__/solution_panel.test.tsx.snap
#	src/platform/plugins/shared/inspector/public/ui/__snapshots__/inspector_panel.test.tsx.snap
#	src/platform/plugins/shared/kibana_react/public/page_template/solution_nav/__snapshots__/solution_nav_avatar.test.tsx.snap
#	src/platform/plugins/shared/navigation/public/top_nav_menu/__snapshots__/top_nav_menu.test.tsx.snap
#	src/platform/plugins/shared/navigation/public/top_nav_menu/top_nav_menu.test.tsx
#	x-pack/platform/plugins/private/canvas/shareable_runtime/components/__snapshots__/app.test.tsx.snap
#	x-pack/platform/plugins/private/graph/public/components/graph_visualization/__snapshots__/graph_visualization.test.tsx.snap
#	x-pack/platform/plugins/private/index_lifecycle_management/__jest__/__snapshots__/policy_flyout.test.tsx.snap
#	x-pack/platform/plugins/private/monitoring/public/components/elasticsearch/ccr/__snapshots__/ccr.test.js.snap
#	x-pack/platform/plugins/private/monitoring/public/components/elasticsearch/nodes/__snapshots__/cells.test.js.snap
#	x-pack/platform/plugins/private/monitoring/public/components/logstash/pipeline_viewer/views/__snapshots__/collapsible_statement.test.js.snap
#	x-pack/platform/plugins/private/monitoring/public/components/logstash/pipeline_viewer/views/__snapshots__/detail_drawer.test.js.snap
#	x-pack/platform/plugins/private/monitoring/public/components/logstash/pipeline_viewer/views/__snapshots__/metric.test.js.snap
#	x-pack/platform/plugins/private/monitoring/public/components/logstash/pipeline_viewer/views/__snapshots__/plugin_statement.test.js.snap
#	x-pack/platform/plugins/private/monitoring/public/components/logstash/pipeline_viewer/views/__snapshots__/queue.test.js.snap
#	x-pack/platform/plugins/private/monitoring/public/components/logstash/pipeline_viewer/views/__snapshots__/statement.test.js.snap
#	x-pack/platform/plugins/private/monitoring/public/components/sparkline/__snapshots__/index.test.js.snap
#	x-pack/platform/plugins/private/monitoring/public/components/summary_status/__snapshots__/summary_status.test.js.snap
#	x-pack/platform/plugins/shared/spaces/public/nav_control/components/__snapshots__/manage_spaces_button.test.tsx.snap
#	x-pack/platform/plugins/shared/spaces/public/space_selector/__snapshots__/space_selector.test.tsx.snap
#	x-pack/solutions/observability/plugins/apm/public/components/shared/charts/timeline/__snapshots__/timeline.test.tsx.snap
#	x-pack/solutions/observability/plugins/apm/public/components/shared/charts/timeline/marker/__snapshots__/index.test.tsx.snap
#	x-pack/solutions/observability/plugins/apm/public/components/shared/sticky_properties/__snapshots__/sticky_properties.test.tsx.snap
#	x-pack/solutions/observability/plugins/exploratory_view/public/components/shared/exploratory_view/series_editor/columns/filter_value_btn.test.tsx
#	x-pack/solutions/observability/plugins/infra/public/components/asset_details/tabs/processes/__snapshots__/processes_table.test.tsx.snap
#	x-pack/solutions/observability/plugins/observability_shared/public/components/field_value_suggestions/field_value_selection.test.tsx
#	x-pack/solutions/observability/plugins/slo/public/utils/test_helper.tsx
#	x-pack/solutions/observability/plugins/ux/public/components/app/rum_dashboard/visitor_breakdown_map/__snapshots__/embedded_map.test.tsx.snap
#	x-pack/solutions/observability/plugins/ux/public/components/app/rum_dashboard/visitor_breakdown_map/__snapshots__/map_tooltip.test.tsx.snap
#	x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/conditions/entry_content/__snapshots__/entry_content.test.tsx.snap
#	x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/meta/details_info/__snapshots__/details_info.test.tsx.snap
#	x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/generate_linked_rules_menu_item/__snapshots__/generate_linked_rules_menu_item.test.tsx.snap
#	x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/list_header/__snapshots__/list_header.test.tsx.snap
#	x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/list_header/menu_items/__snapshots__/menu_items.test.tsx.snap
#	x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/text_with_edit/__snapshots__/text_with_edit.test.tsx.snap
#	x-pack/solutions/security/plugins/security_solution/public/explore/network/components/arrows/__snapshots__/index.test.tsx.snap
#	x-pack/solutions/security/plugins/security_solution/public/timelines/components/netflow/__snapshots__/index.test.tsx.snap
#	x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/renderers/netflow/__snapshots__/netflow_row_renderer.test.tsx.snap
#	x-pack/solutions/security/plugins/session_view/public/components/detail_panel_copy/__snapshots__/index.test.tsx.snap
#	x-pack/solutions/security/plugins/session_view/public/components/process_tree_alert/__snapshots__/index.test.tsx.snap
@kibanamachine kibanamachine added the backport missing Added to PRs automatically when the are determined to be missing a backport. label Apr 15, 2025
@kibanamachine
Copy link
Contributor

Looks like this PR has a backport PR but it still hasn't been merged. Please merge it ASAP to keep the branches relatively in sync.

Dosant added a commit that referenced this pull request Apr 15, 2025
# Backport

This will backport the following commits from `main` to `8.x`:
- [[jest] @emotion/babel-preset-css-prop
(#216489)](#216489)

<!--- Backport version: 9.6.6 -->

### Questions ?
Please refer to the [Backport tool
documentation](https://github.com/sorenlouv/backport)

<!--BACKPORT [{"author":{"name":"Anton
Dosov","email":"anton.dosov@elastic.co"},"sourceCommit":{"committedDate":"2025-04-14T12:29:47Z","message":"[jest]
@emotion/babel-preset-css-prop (#216489)\n\n## Summary\n\nPartially
address https://github.com/elastic/kibana/issues/216459\n\nThis PR adds
`@emotion/babel-preset-css-prop` to jest config to improve\njest and
emotion integration. There are some tradeoffs: this is a better\nsetup
for emotion + testing library, but there are some seemingly\nregressions
for enzyme. We think these are right tradeoffs to make,\nsince we
optimize for emotion+testing library.\n\n### Main upsides are 😄 \n\n####
🟢 Fixes snapshots with css prop\n\n`You have tried to stringify object
returned from \\`css\\` function. It\nisn't supposed to be used directly
(e.g. as value of the \\`className\\`\nprop), but rather handed to
emotion so it can handle it (e.g. as value\nof \\`css\\` prop).` is
replaced with proper emotion css classname.\n\n![Screenshot 2025-04-04
at 14
57\n52](https://github.com/user-attachments/assets/f4a746d6-2451-4703-ab39-57be7171b10b)\n\n####
🟢 We will be able to use jest style matchers for
emotion\n`toHaveStyleRule`\n\nhttps://emotion.sh/docs/@emotion/jest#tohavestylerule\n\n_they
can be used locally now, but we plan to follow up with
global\nextend_\n\n### Considerations 🫤 \n\n#### 🟡 jsx doesn't work
inside jest.mock function \n\nExample:
\n\n```\njest.mock('./components/alert_header_title', () => ({\n > 27 |
AlertHeaderTitle: jest.fn().mockReturnValue(<div></div>), \n | ^\n 28 |
}));\n```\n\nFails with an error. `can't read jsx of undefined`.
\n\nThis is because babel compiles this into: \n\n```\nimport { jsx as
___EmotionJSX } from
'@emotion/react'\n\njest.mock('./components/alert_header_title', () =>
({\n > 27 | AlertHeaderTitle:
jest.fn().mockReturnValue(___EmotionJSX.jsx(….)), \n | ^\n 28 |
}));\n```\n\nAnd, apparently, due to how jest imports work, __EmotionJSX
is not yet\nin the scope.\n\nThe applied workaround is to rewrite to:
\n\n```\njest.mock('./components/alert_header_title', () => ({\n
AlertHeaderTitle: jest.fn(() => <div></div>), \n }));\n```\n\n\n#### 🟡
euiTheme needs to be available when euiTheme is accessed inside\n`css`
function\n\nExample: \n\n```\nDashboardGrid removes panel when removed
from container\n TypeError: Cannot read properties of undefined (reading
'size')\n 42 | margin: '-2px',\n 43 | position: 'absolute',\n > 44 |
width: euiTheme.size.l,\n```\n\nThe fix was to wrap failing tests with
`<EuiProvider/>` \n\n### Drawbacks 😢 \n\nMostly related to Enzyme
\n\n#### 🔴 Enzyme shallow snapshot no longer include `css` prop
\n\nSince `css` prop is compiled away there are bunch of snapshots
that\nlooks like a regression:\n\nExample:\n\n![Screenshot 2025-04-04 at
15
50\n16](https://github.com/user-attachments/assets/61c1d027-1e8a-48e6-a242-1fa53f8ec9b7)\n\nThis
is unfortunate. We've tried `@emotion/jest/enzyme-serializer` but\nit
didn't work (likely because enzyme ecosystem no longer supported?)\nIf
it is important that the snapshot captures css, we recommend to
use\nmount or rtl\n\n#### 🔴 Asserting against `css` prop with shallow
render also doesn't\nwork\n\nPossible solution is to use \n\n```\nimport
{ matchers } from '@emotion/jest';\nexpect.extend(matchers);\n```\n\n(We
plan to add these matches globally in a follow up)\n\nand \n\n```\n
expect(button).toHaveStyleRule('background-color',
'#FFFFFF');\n```\n\n\n\n#### 🔴 Some shallow Enzyme tests `find()` breaks
because of code\ntransformations of emotion\n\nExample:\n\n```\nconst
component = shallow(\n <MetricVisValue />\n)\n\ncomponent.find('button')
// fails because instead of <button/> there is <EmotionInternalCss/>
element now \n\n```\n\nSolutions:\n- Use full mount or react testing
library \n- Or target by data-test-subj\n\n---------\n\nCo-authored-by:
kibanamachine
<42973632+kibanamachine@users.noreply.github.com>\nCo-authored-by: Karen
Grigoryan
<karen.grigoryan@elastic.co>","sha":"ef0322d8d05be4a2a02b16133a5f8488fe506900","branchLabelMapping":{"^v9.1.0$":"main","^v8.19.0$":"8.x","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["Feature:ExpressionLanguage","release_note:skip","ci:skip-cypress-osquery","Team:obs-ux-infra_services","Team:obs-ux-management","backport:version","v9.1.0","v8.19.0"],"title":"[jest]
@emotion/babel-preset-css-prop","number":216489,"url":"https://github.com/elastic/kibana/pull/216489","mergeCommit":{"message":"[jest]
@emotion/babel-preset-css-prop (#216489)\n\n## Summary\n\nPartially
address https://github.com/elastic/kibana/issues/216459\n\nThis PR adds
`@emotion/babel-preset-css-prop` to jest config to improve\njest and
emotion integration. There are some tradeoffs: this is a better\nsetup
for emotion + testing library, but there are some seemingly\nregressions
for enzyme. We think these are right tradeoffs to make,\nsince we
optimize for emotion+testing library.\n\n### Main upsides are 😄 \n\n####
🟢 Fixes snapshots with css prop\n\n`You have tried to stringify object
returned from \\`css\\` function. It\nisn't supposed to be used directly
(e.g. as value of the \\`className\\`\nprop), but rather handed to
emotion so it can handle it (e.g. as value\nof \\`css\\` prop).` is
replaced with proper emotion css classname.\n\n![Screenshot 2025-04-04
at 14
57\n52](https://github.com/user-attachments/assets/f4a746d6-2451-4703-ab39-57be7171b10b)\n\n####
🟢 We will be able to use jest style matchers for
emotion\n`toHaveStyleRule`\n\nhttps://emotion.sh/docs/@emotion/jest#tohavestylerule\n\n_they
can be used locally now, but we plan to follow up with
global\nextend_\n\n### Considerations 🫤 \n\n#### 🟡 jsx doesn't work
inside jest.mock function \n\nExample:
\n\n```\njest.mock('./components/alert_header_title', () => ({\n > 27 |
AlertHeaderTitle: jest.fn().mockReturnValue(<div></div>), \n | ^\n 28 |
}));\n```\n\nFails with an error. `can't read jsx of undefined`.
\n\nThis is because babel compiles this into: \n\n```\nimport { jsx as
___EmotionJSX } from
'@emotion/react'\n\njest.mock('./components/alert_header_title', () =>
({\n > 27 | AlertHeaderTitle:
jest.fn().mockReturnValue(___EmotionJSX.jsx(….)), \n | ^\n 28 |
}));\n```\n\nAnd, apparently, due to how jest imports work, __EmotionJSX
is not yet\nin the scope.\n\nThe applied workaround is to rewrite to:
\n\n```\njest.mock('./components/alert_header_title', () => ({\n
AlertHeaderTitle: jest.fn(() => <div></div>), \n }));\n```\n\n\n#### 🟡
euiTheme needs to be available when euiTheme is accessed inside\n`css`
function\n\nExample: \n\n```\nDashboardGrid removes panel when removed
from container\n TypeError: Cannot read properties of undefined (reading
'size')\n 42 | margin: '-2px',\n 43 | position: 'absolute',\n > 44 |
width: euiTheme.size.l,\n```\n\nThe fix was to wrap failing tests with
`<EuiProvider/>` \n\n### Drawbacks 😢 \n\nMostly related to Enzyme
\n\n#### 🔴 Enzyme shallow snapshot no longer include `css` prop
\n\nSince `css` prop is compiled away there are bunch of snapshots
that\nlooks like a regression:\n\nExample:\n\n![Screenshot 2025-04-04 at
15
50\n16](https://github.com/user-attachments/assets/61c1d027-1e8a-48e6-a242-1fa53f8ec9b7)\n\nThis
is unfortunate. We've tried `@emotion/jest/enzyme-serializer` but\nit
didn't work (likely because enzyme ecosystem no longer supported?)\nIf
it is important that the snapshot captures css, we recommend to
use\nmount or rtl\n\n#### 🔴 Asserting against `css` prop with shallow
render also doesn't\nwork\n\nPossible solution is to use \n\n```\nimport
{ matchers } from '@emotion/jest';\nexpect.extend(matchers);\n```\n\n(We
plan to add these matches globally in a follow up)\n\nand \n\n```\n
expect(button).toHaveStyleRule('background-color',
'#FFFFFF');\n```\n\n\n\n#### 🔴 Some shallow Enzyme tests `find()` breaks
because of code\ntransformations of emotion\n\nExample:\n\n```\nconst
component = shallow(\n <MetricVisValue />\n)\n\ncomponent.find('button')
// fails because instead of <button/> there is <EmotionInternalCss/>
element now \n\n```\n\nSolutions:\n- Use full mount or react testing
library \n- Or target by data-test-subj\n\n---------\n\nCo-authored-by:
kibanamachine
<42973632+kibanamachine@users.noreply.github.com>\nCo-authored-by: Karen
Grigoryan
<karen.grigoryan@elastic.co>","sha":"ef0322d8d05be4a2a02b16133a5f8488fe506900"}},"sourceBranch":"main","suggestedTargetBranches":["8.x"],"targetPullRequestStates":[{"branch":"main","label":"v9.1.0","branchLabelMappingKey":"^v9.1.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/216489","number":216489,"mergeCommit":{"message":"[jest]
@emotion/babel-preset-css-prop (#216489)\n\n## Summary\n\nPartially
address https://github.com/elastic/kibana/issues/216459\n\nThis PR adds
`@emotion/babel-preset-css-prop` to jest config to improve\njest and
emotion integration. There are some tradeoffs: this is a better\nsetup
for emotion + testing library, but there are some seemingly\nregressions
for enzyme. We think these are right tradeoffs to make,\nsince we
optimize for emotion+testing library.\n\n### Main upsides are 😄 \n\n####
🟢 Fixes snapshots with css prop\n\n`You have tried to stringify object
returned from \\`css\\` function. It\nisn't supposed to be used directly
(e.g. as value of the \\`className\\`\nprop), but rather handed to
emotion so it can handle it (e.g. as value\nof \\`css\\` prop).` is
replaced with proper emotion css classname.\n\n![Screenshot 2025-04-04
at 14
57\n52](https://github.com/user-attachments/assets/f4a746d6-2451-4703-ab39-57be7171b10b)\n\n####
🟢 We will be able to use jest style matchers for
emotion\n`toHaveStyleRule`\n\nhttps://emotion.sh/docs/@emotion/jest#tohavestylerule\n\n_they
can be used locally now, but we plan to follow up with
global\nextend_\n\n### Considerations 🫤 \n\n#### 🟡 jsx doesn't work
inside jest.mock function \n\nExample:
\n\n```\njest.mock('./components/alert_header_title', () => ({\n > 27 |
AlertHeaderTitle: jest.fn().mockReturnValue(<div></div>), \n | ^\n 28 |
}));\n```\n\nFails with an error. `can't read jsx of undefined`.
\n\nThis is because babel compiles this into: \n\n```\nimport { jsx as
___EmotionJSX } from
'@emotion/react'\n\njest.mock('./components/alert_header_title', () =>
({\n > 27 | AlertHeaderTitle:
jest.fn().mockReturnValue(___EmotionJSX.jsx(….)), \n | ^\n 28 |
}));\n```\n\nAnd, apparently, due to how jest imports work, __EmotionJSX
is not yet\nin the scope.\n\nThe applied workaround is to rewrite to:
\n\n```\njest.mock('./components/alert_header_title', () => ({\n
AlertHeaderTitle: jest.fn(() => <div></div>), \n }));\n```\n\n\n#### 🟡
euiTheme needs to be available when euiTheme is accessed inside\n`css`
function\n\nExample: \n\n```\nDashboardGrid removes panel when removed
from container\n TypeError: Cannot read properties of undefined (reading
'size')\n 42 | margin: '-2px',\n 43 | position: 'absolute',\n > 44 |
width: euiTheme.size.l,\n```\n\nThe fix was to wrap failing tests with
`<EuiProvider/>` \n\n### Drawbacks 😢 \n\nMostly related to Enzyme
\n\n#### 🔴 Enzyme shallow snapshot no longer include `css` prop
\n\nSince `css` prop is compiled away there are bunch of snapshots
that\nlooks like a regression:\n\nExample:\n\n![Screenshot 2025-04-04 at
15
50\n16](https://github.com/user-attachments/assets/61c1d027-1e8a-48e6-a242-1fa53f8ec9b7)\n\nThis
is unfortunate. We've tried `@emotion/jest/enzyme-serializer` but\nit
didn't work (likely because enzyme ecosystem no longer supported?)\nIf
it is important that the snapshot captures css, we recommend to
use\nmount or rtl\n\n#### 🔴 Asserting against `css` prop with shallow
render also doesn't\nwork\n\nPossible solution is to use \n\n```\nimport
{ matchers } from '@emotion/jest';\nexpect.extend(matchers);\n```\n\n(We
plan to add these matches globally in a follow up)\n\nand \n\n```\n
expect(button).toHaveStyleRule('background-color',
'#FFFFFF');\n```\n\n\n\n#### 🔴 Some shallow Enzyme tests `find()` breaks
because of code\ntransformations of emotion\n\nExample:\n\n```\nconst
component = shallow(\n <MetricVisValue />\n)\n\ncomponent.find('button')
// fails because instead of <button/> there is <EmotionInternalCss/>
element now \n\n```\n\nSolutions:\n- Use full mount or react testing
library \n- Or target by data-test-subj\n\n---------\n\nCo-authored-by:
kibanamachine
<42973632+kibanamachine@users.noreply.github.com>\nCo-authored-by: Karen
Grigoryan
<karen.grigoryan@elastic.co>","sha":"ef0322d8d05be4a2a02b16133a5f8488fe506900"}},{"branch":"8.x","label":"v8.19.0","branchLabelMappingKey":"^v8.19.0$","isSourceBranch":false,"state":"NOT_CREATED"}]}]
BACKPORT-->
@kibanamachine kibanamachine removed the backport missing Added to PRs automatically when the are determined to be missing a backport. label Apr 15, 2025
Dosant added a commit that referenced this pull request Apr 25, 2025
## Summary

close #216459
follow-up to #216489

Since we're migrating to Emotion from SCSS/styled-components, this PR
globally aligns the Jest setup by adding '@emotion/jest' matchers.

However, the matchers conflict with the styled-components Jest matchers,
so I had to disable them globally and reapply them in the tests where
they were used (either the matchers or styled components snapshot
serializer) . Tracking issue to clean this up
#219037 when migrated to Emotion
kibanamachine pushed a commit to kibanamachine/kibana that referenced this pull request Apr 25, 2025
## Summary

close elastic#216459
follow-up to elastic#216489

Since we're migrating to Emotion from SCSS/styled-components, this PR
globally aligns the Jest setup by adding '@emotion/jest' matchers.

However, the matchers conflict with the styled-components Jest matchers,
so I had to disable them globally and reapply them in the tests where
they were used (either the matchers or styled components snapshot
serializer) . Tracking issue to clean this up
elastic#219037 when migrated to Emotion

(cherry picked from commit a5502b0)
akowalska622 pushed a commit to akowalska622/kibana that referenced this pull request May 29, 2025
## Summary

close elastic#216459
follow-up to elastic#216489

Since we're migrating to Emotion from SCSS/styled-components, this PR
globally aligns the Jest setup by adding '@emotion/jest' matchers.

However, the matchers conflict with the styled-components Jest matchers,
so I had to disable them globally and reapply them in the tests where
they were used (either the matchers or styled components snapshot
serializer) . Tracking issue to clean this up
elastic#219037 when migrated to Emotion
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backport:version Backport to applied version labels ci:skip-cypress-osquery Skips osquery cypress checks Feature:ExpressionLanguage Interpreter expression language (aka canvas pipeline) release_note:skip Skip the PR/issue when compiling release notes Team:actionable-obs Formerly "obs-ux-management", responsible for SLO, o11y alerting, significant events, & synthetics. Team:obs-ux-infra_services - DEPRECATED DEPRECATED - Use Team:obs-presentation. v8.19.0 v9.1.0

Projects

None yet

Development

Successfully merging this pull request may close these issues.