UNPKG

@theme-ui/css

Version:

Theme UI CSS lets you write style objects with responsive, theme-aware ergonomic shortcuts. This package powers the `sx` prop in Theme UI.

152 lines (126 loc) 3.94 kB
import { expecter } from '@theme-ui/test-utils' import { css, get, Theme } from '../src' const expectSnippet = expecter(` import { css } from './packages/css/src' `) describe('Theme', () => { test('shows friendly error only on bad property', () => { expectSnippet(` css({ bg: 'salmon', widows: 'foo', '> form': { color: 'blue', widows: 'bar', // unknown CSS property is accepted windows: 'baz', }, }) `).toFail( /Error snippet\.tsx \(\d+,\d+\): Type '"foo"' is not assignable to type [\s\S]+'./ ) }) test('shows friendly error on nested object', () => { expectSnippet(` css({ bg: 'salmon', '> form': { color: 'blue', widows: 'bar', }, }) `).toFail( new RegExp( `Error snippet\.tsx \\(\\d+,\\d+\\): Type '{ color: "blue"; widows: "bar"; }'` + ` is not assignable to type '[\\s\\S]+'.\\n\\s+` + `Types of property 'widows' are incompatible.\\n\\s+` + `Type '"bar"' is not assignable to type [\\s\\S]+` ) ) }) test('accepts unknown CSS property without error', () => { expect(css({ '> form': { windows: 'baz' } })({})).toStrictEqual({ '> form': { windows: 'baz' }, }) }) test('infers Theme argument in computed style function', () => { expectSnippet(` import { get } from 'theme-ui' css({ p: t => { const theme = t; return get(t, 'sizes.5') } }) `).toInfer('theme', 'Theme') }) test('accepts additional properties by declaration merging', () => { expectSnippet(` import { Theme } from 'theme-ui'; interface MySyntaxHighlightingTheme { foreground: string } declare module 'theme-ui' { interface Theme { syntaxHighlighting?: MySyntaxHighlightingTheme } } const theme: Theme = { syntaxHighlighting: { foreground: '#222', }, } const syntaxHighlighting = theme.syntaxHighlighting! `).toInfer('syntaxHighlighting', 'MySyntaxHighlightingTheme') }) test('works as described in the docs', () => { const theme: Theme = { colors: { background: 'white', text: 'black', primary: '#07f' }, space: [0, 8, 16, 32, 64, 128, 256], sizes: [0, 8, 16, 32, 64, 128, 256], } css({ size: (t) => get(t, 'space.3') + get(t, 'sizes.5') }) const parse = (x: string | number | undefined | {}) => parseInt(String(x)) css({ size: (t) => parse(t.space?.[3]) + parse(t.sizes?.[5]), }) // Current limitation. If you broke this one, that's actually pretty awesome, // but TypeScript chapter in the docs needs an update. expectSnippet(` css({ size: (t) => t.space?.['xs'] + t.sizes?.['lg'] }) `).toFail( /Element implicitly has an 'any' type because index expression is not of type 'number'/ ) }) }) // This is not a feature, but the TypeScript chapter in the docs will need an // update if this test fails. test('inferred type `string` is too wide for `whiteSpace`', () => { expectSnippet(` const style = { whiteSpace: 'pre-line' } css(style); `).toFail( /Type '{ whiteSpace: string; }' is not assignable to type 'ThemeUICSSObject'./ ) expectSnippet(` import { ThemeUICSSObject } from 'theme-ui' const style: ThemeUICSSObject = { whiteSpace: 'pre-line' } css(style); `).toSucceed() }) describe('ColorMode', () => { const expectedSnippet = expectSnippet(` import { ColorMode } from './packages/css/src' const colorMode: ColorMode = {} const seriousPink = colorMode.seriousPink if (Array.isArray(seriousPink)) { const [light, medium, dark] = seriousPink } `) expectedSnippet.toInfer('light', 'Color') expectedSnippet.toInfer('dark', 'Color') })