Skip to content

Commit ef5e2b5

Browse files
authored
theme: update proxy to handle JSON serialization (#106208)
If value is used outside of a string literal, then it escapes our proxy and does not get coerced to the correct value
1 parent fc71ff8 commit ef5e2b5

File tree

2 files changed

+85
-3
lines changed

2 files changed

+85
-3
lines changed

static/app/utils/theme/compat.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,12 @@ function createBackwardsCompatibleToken<
1313
if (prop === '__emotion_styles') {
1414
return target.vibrant;
1515
}
16-
if (prop === 'toString' || prop === 'valueOf' || prop === Symbol.toPrimitive) {
16+
if (
17+
prop === 'toString' ||
18+
prop === 'valueOf' ||
19+
prop === 'toJSON' ||
20+
prop === Symbol.toPrimitive
21+
) {
1722
return () => target.vibrant;
1823
}
1924
return Reflect.get(target, prop, receiver);

static/app/utils/theme/theme.spec.tsx

Lines changed: 79 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
import {useTheme} from '@emotion/react';
1+
import {css, useTheme} from '@emotion/react';
22
import {expectTypeOf} from 'expect-type';
33

4-
import {renderHookWithProviders} from 'sentry-test/reactTestingLibrary';
4+
import {render, renderHookWithProviders, screen} from 'sentry-test/reactTestingLibrary';
55

66
describe('theme', () => {
77
describe('getColorPalette', () => {
@@ -26,4 +26,81 @@ describe('theme', () => {
2626
>();
2727
});
2828
});
29+
30+
describe('backwards compatibility tokens', () => {
31+
it.each<['border' | 'graphics']>([['border'], ['graphics']])(
32+
'%s should coerce to vibrant in template literals',
33+
name => {
34+
const theme = renderHookWithProviders(useTheme).result.current;
35+
const token = theme.tokens[name].promotion;
36+
expect(`color: ${token}`).toBe(`color: ${token.vibrant}`);
37+
}
38+
);
39+
40+
it.each<['border' | 'graphics']>([['border'], ['graphics']])(
41+
'%s token should equal its vibrant value when coerced',
42+
name => {
43+
const theme = renderHookWithProviders(useTheme).result.current;
44+
const token = theme.tokens[name].promotion;
45+
46+
// Test coercion to string equals vibrant value
47+
expect(String(token)).toBe(token.vibrant);
48+
expect(`${token}`).toBe(token.vibrant);
49+
}
50+
);
51+
52+
it('should work with Emotion css function for border tokens', () => {
53+
const theme = renderHookWithProviders(useTheme).result.current;
54+
55+
expect(css`
56+
border: 1px solid ${theme.tokens.border.promotion};
57+
`).toMatchObject({
58+
styles: expect.stringContaining(theme.tokens.border.promotion.vibrant),
59+
});
60+
});
61+
62+
it('should work with css template', () => {
63+
const theme = renderHookWithProviders(useTheme).result.current;
64+
65+
expect(css`
66+
background: ${theme.tokens.graphics.promotion};
67+
`).toMatchObject({
68+
styles: expect.stringContaining(theme.tokens.graphics.promotion.vibrant),
69+
});
70+
});
71+
72+
it('should work via object reference', () => {
73+
const theme = renderHookWithProviders(useTheme).result.current;
74+
const config = {iconBorder: theme.tokens.border.danger};
75+
76+
expect(css`
77+
border-color: ${config.iconBorder};
78+
`).toMatchObject({
79+
styles: expect.stringContaining(theme.tokens.border.danger.vibrant),
80+
});
81+
});
82+
83+
it.each<['border' | 'graphics']>([['border'], ['graphics']])(
84+
'%s token should serialize to vibrant value in JSON',
85+
name => {
86+
const theme = renderHookWithProviders(useTheme).result.current;
87+
const token = theme.tokens[name].promotion;
88+
89+
const serialized = JSON.stringify({color: token});
90+
const expected = JSON.stringify({color: token.vibrant});
91+
92+
expect(serialized).toBe(expected);
93+
}
94+
);
95+
});
96+
97+
it('serializes style object to vibrant value in JSON', () => {
98+
const theme = renderHookWithProviders(useTheme).result.current;
99+
100+
render(<div style={{borderColor: theme.tokens.border.promotion}}>Hello</div>);
101+
102+
expect(screen.getByText('Hello')).toHaveStyle({
103+
borderColor: theme.tokens.border.promotion.vibrant,
104+
});
105+
});
29106
});

0 commit comments

Comments
 (0)