import { transform } from '../test-utils'; describe('import specifiers', () => { it('should evaluate simple expressions', () => { const actual = transform(` import '@compiled/react';
hello world
`); expect(actual).toInclude('{font-size:16px}'); }); it('should inline mutable identifier that is not mutated', () => { const actual = transform(` import '@compiled/react'; let notMutatedAgain = 20;
hello world
`); expect(actual).toInclude('{font-size:20px}'); }); it('should bail out evaluating expression referencing a mutable identifier', () => { const actual = transform(` import '@compiled/react'; let mutable = 2; mutable = 1;
hello world
`); expect(actual).toInclude('{font-size:var(--_i47brp)}'); }); it('should bail out evaluating identifier expression referencing a mutated identifier', () => { const actual = transform(` import '@compiled/react'; let mutable = 2; const dontchange = mutable; mutable = 3;
hello world
`); expect(actual).toInclude('{font-size:var(--_uta6jk)}'); }); it('should not exhaust the stack when an identifier references itself', () => { expect(() => { transform(` import '@compiled/react'; let heading = heading || 20;
hello world
`); }).not.toThrow(); }); it('should bail out evaluating expression that references a constant expression referencing a mutated expression', () => { const actual = transform(` import '@compiled/react'; let mutable = false; const dontchange = mutable ? 1 : 2; mutable = true;
hello world
`); expect(actual).toInclude('{font-size:var(--_uta6jk)}'); }); it('should bail out evaluating a binary expression referencing a mutated identifier', () => { const actual = transform(` import '@compiled/react'; let mutable = 2; mutable = 3;
hello world
`); expect(actual).toInclude('{font-size:var(--_1bs2x4k)}'); }); it('should not blow up when referencing local destructured args in arrow func', () => { expect(() => { transform(` import '@compiled/react'; export const Component = ({ foo, color }) => { return ( ); }; `); }).not.toThrow(); }); it('should not blow up when referencing local args in arrow func', () => { expect(() => { transform(` import '@compiled/react'; export const Component = (props) => { return ( ); }; `); }).not.toThrow(); }); it('should not blow up when referencing local destructured args in func', () => { expect(() => { transform(` import '@compiled/react'; function Component({ foo, color }) { return ( ); } `); }).not.toThrow(); }); it('should not blow up when referencing local args in func', () => { expect(() => { transform(` import '@compiled/react'; function Component(props) { return ( ); } `); }).not.toThrow(); }); it('should not blow up when destructured local args in func', () => { expect(() => { transform(` import '@compiled/react'; function DestructuredComp(props) { const { foo, color } = props; return ( ); } `); }).not.toThrow(); }); it('handles object destructuring', () => { const actual = transform(` import '@compiled/react'; const { foo, color } = { foo: 14, color: 'blue' }; function Component() { return ( ); } `); expect(actual).toIncludeMultiple([ '{font-size:14px}', '{color:blue}', '{background-color:blue}', ]); }); it('statically evaluates deconstructed values from deeply nested objects', () => { const actual = transform(` import '@compiled/react'; const theme = { borders: '1px solid black', colors: { light: { primary: '#fff', }, dark: { primary: '#000', } }, fonts: { small: '12px', weight: { bold: { headings: '700', body: '600' } } } }; const { borders } = theme; const { small } = theme.fonts; const { primary } = theme.colors.dark; const { headings } = theme.fonts.weight.bold; function Component() { return ( ); } `); expect(actual).toIncludeMultiple([ '{border:1px solid black}', '{color:#000}', '{font-size:12px}', '{font-weight:700}', ]); }); it('handles the destructuring coming from an identifier', () => { const actual = transform(` import '@compiled/react'; const obj = { foo: 14, color: 'blue' }; const { foo, color } = obj; function Component() { return ( ); } `); expect(actual).toIncludeMultiple([ '{font-size:14px}', '{color:blue}', '{background-color:blue}', ]); }); it('should build css template literal from the css api', () => { const actual = transform(` import { css } from '@compiled/react'; const primary = css\` color: red; \`; `); expect(actual).toIncludeMultiple(['{color:red}']); }); it('handles the destructuring coming from a referenced identifier', () => { const actual = transform(` import '@compiled/react'; const obj = { foo: 14, color: 'blue' }; const bar = obj; const { foo, color } = bar; function Component() { return ( ); } `); expect(actual).toIncludeMultiple([ '{font-size:14px}', '{color:blue}', '{background-color:blue}', ]); }); it('handles the function call destructuring coming from a referenced identifier', () => { const actual = transform(` import '@compiled/react'; const obj = { foo: () => ({ bar: 14 }), color: 'blue' }; const bar = obj; const { foo, color } = bar; function Component() { return ( ); } `); expect(actual).toIncludeMultiple([ '{font-size:14px}', '{color:blue}', '{background-color:blue}', ]); }); it('should not blow up when member expression object is other than "Identifier" or "Call Expression"', () => { expect(() => { transform(` import '@compiled/react'; function Component() { return ( ); } `); }).not.toThrow(); }); it('handles the computed object property with static evaluation of variable', () => { const actual = transform(` import { styled } from '@compiled/react'; const media = '@media screen' const obj = { [media]: { color: 'blue' } }; const Span = styled.span(obj); function Component() { return ( ); } `); expect(actual).toInclude('@media screen{._434713q2{color:blue}}'); }); it('handles the computed object property, where the variable in property is defined inside `as const` expression', () => { const actual = transform( ` import '@compiled/react'; const something = { large: '@media screen' } as const;
`, { parserBabelPlugins: ['typescript', 'jsx'], } ); expect(actual).toInclude('@media screen{._434713q2{color:blue}}'); }); it('uses fallback node when evaluating a non expression returning a non static value', () => { const actual = transform(` import '@compiled/react'; function getLineHeight() { return Math.random(); } `); expect(actual).toIncludeMultiple([ '._vwz41rme{line-height:var(--_12w6gfj)', 'ax(["_vwz41rme"])', '"--_12w6gfj": ix(getLineHeight())', ]); }); describe('binary expresssions', () => { it('statically evaluates calculated value with identifier', () => { const actual = transform(` import '@compiled/react'; const spacing = 8;
`); expect(actual).toIncludeMultiple(['._19pkexct{margin-top:16px}', 'ax(["_19pkexct"])']); }); it('statically evaluates calculated value with nested binary', () => { const actual = transform(` import '@compiled/react'; const spacing = 8;
`); expect(actual).toIncludeMultiple(['._19pkftgi{margin-top:8px}', 'ax(["_19pkftgi"])']); }); it('statically evaluates calculated value with multiple identifiers', () => { const actual = transform(` import '@compiled/react'; const one = 1; const two = 2; const three = 3;
`); expect(actual).toIncludeMultiple(['._19pkidpf{margin-top:0}', 'ax(["_19pkidpf"])']); }); it('statically evaluates calculated value within calc utility', () => { const actual = transform(` import '@compiled/react'; const spacing = 8;
`); expect(actual).toIncludeMultiple([ '._1bsbj0q6{width:calc(100% - 16px)}', 'ax(["_1bsbj0q6"])', ]); }); it('statically evaluates calculated value with string literal containing numeric value', () => { const actual = transform(` import '@compiled/react'; const stringSpacing = '8';
`); expect(actual).toIncludeMultiple(['._19pkexct{margin-top:16px}', 'ax(["_19pkexct"])']); }); it('statically evaluates calculated value with unary expression', () => { const actual = transform(` import '@compiled/react'; const getSpacing = () => 8;
`); expect(actual).toIncludeMultiple(['._19pk4h84{margin-top:-16px}', 'ax(["_19pk4h84"])']); }); it('falls back to dynamic evaluation when non static value used', () => { const actual = transform(` import '@compiled/react'; const getSpacing = () => Math.random();
`); expect(actual).toIncludeMultiple([ '._19pk19vg{margin-top:var(--_lb6tu)}', '"--_lb6tu": ix(getSpacing() * 2)', 'ax(["_19pk19vg"])', ]); }); it('statically evaluates a TS const expression', () => { const actual = transform( ` import '@compiled/react'; const styles = { color: 'red' } as const;
; `, { parserBabelPlugins: ['typescript', 'jsx'], } ); expect(actual).toIncludeMultiple(['._syaz5scu{color:red}', 'ax(["_syaz5scu"])']); }); it('statically evaluates a TS const expression in a resolved binding', () => { const actual = transform( ` import { styled } from "@compiled/react"; const style = { backgroundColor: 'red' } as const; const Component = styled.div({ "input": style, }); `, { parserBabelPlugins: ['typescript', 'jsx'], } ); expect(actual).toIncludeMultiple([ '._1rwq5scu input{background-color:red}', 'ax(["_1rwq5scu", __cmplp.className]', ]); }); it('should bail out evaluating non-exist call expression, which has member expression', () => { const actual = transform(` import '@compiled/react';
`); expect(actual).toInclude('ix(foo.bar())'); }); }); });