diff --git a/packages/babel-plugin/src/__tests__/css-builder.test.ts b/packages/babel-plugin/src/__tests__/css-builder.test.ts index 4519ad912..7e8a3e147 100644 --- a/packages/babel-plugin/src/__tests__/css-builder.test.ts +++ b/packages/babel-plugin/src/__tests__/css-builder.test.ts @@ -49,4 +49,110 @@ describe('css builder', () => { " `); }); + + it('works with css map', () => { + const actual = transform(` + import { cssMap } from '@compiled/react'; + + const styles = cssMap({ red: { color: 'red' }, blue: { color: 'blue' } }); + + function Component({ color }) { + return
+ } + `); + + expect(actual).toMatchInlineSnapshot(` + "import * as React from "react"; + import { ax, ix, CC, CS } from "@compiled/react/runtime"; + const _2 = "._syaz13q2{color:blue}"; + const _ = "._syaz5scu{color:red}"; + const styles = { + red: "_syaz5scu", + blue: "_syaz13q2", + }; + function Component({ color }) { + return ( + + {[_, _2]} + {
} + + ); + } + " + `); + }); + + it('works in spite of a style override', () => { + const actual = transform(` + import { css } from '@compiled/react'; + + const styles = css({ color: ({ color }) => color }); + + function Component({ color }) { + return
+ } + `); + + expect(actual).toMatchInlineSnapshot(` + "import * as React from "react"; + import { ax, ix, CC, CS } from "@compiled/react/runtime"; + const _ = "._syaz1cj8{color:var(--_xexnhp)}"; + const styles = null; + function Component({ color }) { + return ( + + {[_]} + { +
__cmplp.color), + }} + /> + } + + ); + } + " + `); + }); + + it('works when there is a clear member expression', () => { + const actual = transform(` + import { css } from '@compiled/react'; + + const styles = { + test: { + red: css({ color: 'red' }), + blue: css({ color: 'blue' }), + }, + }; + + function Component({ color }) { + return
+ } + `); + + expect(actual).toMatchInlineSnapshot(` + "import * as React from "react"; + import { ax, ix, CC, CS } from "@compiled/react/runtime"; + const _ = "._syaz5scu{color:red}"; + const styles = { + test: { + red: null, + blue: null, + }, + }; + function Component({ color }) { + return ( + + {[_]} + {
} + + ); + } + " + `); + }); }); diff --git a/packages/babel-plugin/src/utils/__tests__/css-builders.test.ts b/packages/babel-plugin/src/utils/__tests__/css-builders.test.ts new file mode 100644 index 000000000..74d032b60 --- /dev/null +++ b/packages/babel-plugin/src/utils/__tests__/css-builders.test.ts @@ -0,0 +1,77 @@ +import generate from '@babel/generator'; +import { parse } from '@babel/parser'; +import type { NodePath } from '@babel/traverse'; +import traverse from '@babel/traverse'; +import type { Identifier, MemberExpression } from '@babel/types'; + +import type { Metadata } from '../../types'; +import { buildCss } from '../css-builders'; + +describe('buildCss', () => { + it('returns a css string and variables array for an identifier node', () => { + const file = parse(` + const color = { background: 'red' }; + const styles = color; + + run(styles); + `); + + let path: NodePath | null = null; + traverse(file, { + CallExpression(nodePath) { + nodePath.traverse({ + Identifier(innerPath) { + if (innerPath.node.name === 'styles') { + path = innerPath; + } + }, + }); + }, + }); + + expect(path).not.toEqual(null); + const meta: Metadata = { + parentPath: path!.parentPath, + state: { + filename: '', + }, + } as any; + + const { css, variables } = buildCss(path!.node, meta); + expect(css).toEqual([{ css: 'background: red;', type: 'unconditional' }]); + expect(variables).toEqual([]); + }); + + it('returns a css string and variables array for a member expression node', () => { + const file = parse(` + const styles = { option1: { background: 'red' } }; + + run(styles.option1); + `); + + let path: NodePath | null = null; + traverse(file, { + CallExpression(nodePath) { + nodePath.traverse({ + MemberExpression(innerPath) { + path = innerPath; + }, + }); + }, + }); + + expect(path).not.toEqual(null); + + const meta: Metadata = { + parentPath: path!.parentPath, + state: { + cssMap: {}, + filename: '', + }, + } as any; + + const { css, variables } = buildCss(path!.node, meta); + expect(css).toEqual([{ css: 'background: red;', type: 'unconditional' }]); + expect(variables).toEqual([]); + }); +}); diff --git a/packages/babel-plugin/src/utils/__tests__/evaluate-expression.test.ts b/packages/babel-plugin/src/utils/__tests__/evaluate-expression.test.ts new file mode 100644 index 000000000..b22e1a3ca --- /dev/null +++ b/packages/babel-plugin/src/utils/__tests__/evaluate-expression.test.ts @@ -0,0 +1,63 @@ +import { parse } from '@babel/parser'; +import type { NodePath } from '@babel/traverse'; +import traverse from '@babel/traverse'; +import type { Identifier, MemberExpression } from '@babel/types'; +import { identifier, memberExpression, stringLiteral } from '@babel/types'; + +import type { Metadata } from '../../types'; +import { evaluateExpression } from '../evaluate-expression'; + +describe('evaluateExpression', () => { + it('should evaluate a variable reference to its value', () => { + const file = parse(` + const color = 'red'; + const styles = color; + + run(styles); + `); + + let path: NodePath | null = null; + traverse(file, { + CallExpression(nodePath) { + nodePath.traverse({ + Identifier(innerPath) { + if (innerPath.node.name === 'styles') { + path = innerPath; + } + }, + }); + }, + }); + + expect(path).not.toEqual(null); + const meta: Metadata = { + parentPath: path!.parentPath, + } as any; + + const { value } = evaluateExpression(path!.node, meta); + expect(value).toEqual(stringLiteral('red')); + }); + + it('should evaluate a member expression', () => { + const file = parse(` + const styles = foo.bar; + `); + + let path: NodePath | null = null; + traverse(file, { + MemberExpression(nodePath) { + path = nodePath; + }, + }); + + expect(path).not.toEqual(null); + const meta: Metadata = { + parentPath: path!.parentPath, + } as any; + + const { value } = evaluateExpression(path!.node, meta); + const expected = memberExpression(identifier('foo'), identifier('bar')); + delete expected.optional; + expect(value).toMatchObject(expected); + }); +});