From e12b1d25c8e5a221b2a0a8f52172181c52272d7b Mon Sep 17 00:00:00 2001 From: Lukas Oppermann Date: Mon, 2 Sep 2024 12:48:17 +0200 Subject: [PATCH] add tests (#1040) --- .eslintrc.cjs | 1 + .github/workflows/build_config.yml | 33 +++++++++++++ .github/workflows/hasChanged.yml | 6 +++ .gitignore | 1 + integration/build.test.ts | 62 +++++++++++++++++++++++++ integration/tokens/base.json5 | 13 ++++++ integration/tokens/functional.json5 | 8 ++++ integrationbuild/css/variables.css | 4 ++ package.json | 3 +- src/formats/cssAdvanced.test.ts | 48 ++++++++++--------- src/formats/cssAdvanced.ts | 26 ++++------- src/formats/jsonNestedPrefixed.test.ts | 3 +- src/test-utilities/getMockDictionary.ts | 2 + tsconfig.json | 2 +- vitest.config.ts | 3 +- 15 files changed, 173 insertions(+), 42 deletions(-) create mode 100644 .github/workflows/build_config.yml create mode 100644 integration/build.test.ts create mode 100644 integration/tokens/base.json5 create mode 100644 integration/tokens/functional.json5 create mode 100644 integrationbuild/css/variables.css diff --git a/.eslintrc.cjs b/.eslintrc.cjs index aac217dbf..d13e14f88 100644 --- a/.eslintrc.cjs +++ b/.eslintrc.cjs @@ -35,6 +35,7 @@ module.exports = { }, // rules which apply to JS, TS, etc. rules: { + 'import/no-nodejs-modules': 0, 'filenames/match-regex': 0, 'eslint-comments/no-unused-disable': 0, 'react/prop-types': 0, diff --git a/.github/workflows/build_config.yml b/.github/workflows/build_config.yml new file mode 100644 index 000000000..5266e2bd5 --- /dev/null +++ b/.github/workflows/build_config.yml @@ -0,0 +1,33 @@ +name: Testing custom transforms, formats, etc. for Style Dictionary + +on: + pull_request: + branches-ignore: + - 'changeset-release/**' + workflow_dispatch: + +jobs: + changes: + uses: ./.github/workflows/hasChanged.yml + + build: + needs: changes + if: needs.changes.outputs.buildConfig == 'true' || github.event_name == 'workflow_dispatch' + name: Test if custom transforms, formats, etc. are working + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Set up Node.js + uses: actions/setup-node@v4 + with: + node-version: 20 + cache: 'npm' + + - name: Install dependencies + run: npm i --no-audit --no-fund --ignore-scripts + + - name: Run test + run: | + npm run test:integration \ No newline at end of file diff --git a/.github/workflows/hasChanged.yml b/.github/workflows/hasChanged.yml index b38a34f4d..9a4a8bd1c 100644 --- a/.github/workflows/hasChanged.yml +++ b/.github/workflows/hasChanged.yml @@ -12,6 +12,9 @@ on: src: description: "Boolean value indicating change in src folder" value: ${{ jobs.hasChanged.outputs.src }} + buildConfig: + description: "Boolean value indicating changes of the build configuration in src folder" + value: ${{ jobs.hasChanged.outputs.buildConfig }} scripts: description: "Boolean value indicating change in scripts folder" value: ${{ jobs.hasChanged.outputs.scripts }} @@ -35,6 +38,7 @@ jobs: outputAffected: ${{ steps.filter.outputs.outputAffected }} tokens: ${{ steps.filter.outputs.tokens }} src: ${{ steps.filter.outputs.src }} + buildConfig: ${{ steps.filter.outputs.buildConfig }} scripts: ${{ steps.filter.outputs.scripts }} buildScripts: ${{ steps.filter.outputs.buildScripts }} dependencies: ${{ steps.filter.outputs.dependencies }} @@ -53,6 +57,8 @@ jobs: - 'src/**/**.ts' - 'src/**/**.json' - 'src/**/**.json5' + buildConfig: + - 'src/**/**.ts' scripts: - 'scripts/**' buildScripts: diff --git a/.gitignore b/.gitignore index 2c4d19036..c5227b9f8 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,4 @@ coverage/ docs/public/ color-contrast-check.json blob-report +integration/build \ No newline at end of file diff --git a/integration/build.test.ts b/integration/build.test.ts new file mode 100644 index 000000000..065e34e0f --- /dev/null +++ b/integration/build.test.ts @@ -0,0 +1,62 @@ +import {PrimerStyleDictionary} from '../src/PrimerStyleDictionary' +import fs from 'fs' + +describe('PrimerStyleDictionary', () => { + const basePath = `./integration` + const extendedSD = PrimerStyleDictionary.extend({ + source: [`${basePath}/tokens/**/*.json5`], + platforms: { + css: { + prefix: 'PREFIX', + transformGroup: 'css', + buildPath: `${basePath}/build/css/`, + files: [ + { + options: { + showFileHeader: false, + }, + destination: 'variables.css', + format: 'css/variables', + }, + ], + }, + advancedCss: { + prefix: 'PREFIX', + transformGroup: 'css', + buildPath: `${basePath}/build/css/`, + files: [ + { + options: { + showFileHeader: false, + }, + destination: 'advanced.css', + format: 'css/advanced', + }, + ], + }, + }, + }) + + extendedSD.cleanAllPlatforms() + extendedSD.buildAllPlatforms() + + it('it should transform with css/variables format', () => { + const output = fs.readFileSync(`${basePath}/build/css/variables.css`, 'utf8') + const expectedOutput = `:root { + --prefix-base-color-blue-500: #2C29FF; /* The primary color for interactive elements. */ + --prefix-fg-color-link: #2C29FF; +} +` + expect(output).toBe(expectedOutput) + }) + + it('it should transform with css/advanced format', () => { + const output = fs.readFileSync(`${basePath}/build/css/advanced.css`, 'utf8') + const expectedOutput = `:root { + --prefix-base-color-blue-500: #2c29ff; /* The primary color for interactive elements. */ + --prefix-fg-color-link: #2c29ff; +} +` + expect(output).toBe(expectedOutput) + }) +}) diff --git a/integration/tokens/base.json5 b/integration/tokens/base.json5 new file mode 100644 index 000000000..c6c9a998d --- /dev/null +++ b/integration/tokens/base.json5 @@ -0,0 +1,13 @@ +{ + base: { + color: { + blue: { + "500": { + "$value": '#2C29FF', + "$type": 'color', + "$description": 'The primary color for interactive elements.', + }, + } + } + } +} \ No newline at end of file diff --git a/integration/tokens/functional.json5 b/integration/tokens/functional.json5 new file mode 100644 index 000000000..6b73f4ca2 --- /dev/null +++ b/integration/tokens/functional.json5 @@ -0,0 +1,8 @@ +{ + fgColor: { + link: { + $value: '{base.color.blue.500}', + $type: 'color', + } + } +} \ No newline at end of file diff --git a/integrationbuild/css/variables.css b/integrationbuild/css/variables.css new file mode 100644 index 000000000..6921e1798 --- /dev/null +++ b/integrationbuild/css/variables.css @@ -0,0 +1,4 @@ +:root { + --prefix-base-color-blue-500: #2c29ff; /* The primary color for interactive elements. */ + --prefix-fg-color-link: #2c29ff; +} diff --git a/package.json b/package.json index 201e35b88..0aed69abf 100644 --- a/package.json +++ b/package.json @@ -40,7 +40,8 @@ "prepack": "npm run build", "release": "changeset publish", "start:storybook": "npm run build && cd docs/storybook && npm run storybook", - "test": "vitest run --coverage" + "test": "vitest run --coverage", + "test:integration": "vitest run -r integration" }, "prettier": "@github/prettier-config", "devDependencies": { diff --git a/src/formats/cssAdvanced.test.ts b/src/formats/cssAdvanced.test.ts index fe54a2262..c3fccb543 100644 --- a/src/formats/cssAdvanced.test.ts +++ b/src/formats/cssAdvanced.test.ts @@ -224,7 +224,7 @@ describe('Format: tokens nested in media query', () => { /** * Test cases for formatting tokens with simple css variables */ - it('Shows comment if option.description is true', () => { + it('Shows comment if option.formatting.commentStyle is long or not set', () => { const input = getMockFormatterArguments({ dictionary: getMockDictionary({ tokens: { @@ -238,7 +238,9 @@ describe('Format: tokens nested in media query', () => { }, }), options: { - descriptions: true, + formatting: { + commentStyle: 'long', + }, }, file: { destination: 'size-fine.css', @@ -253,19 +255,7 @@ describe('Format: tokens nested in media query', () => { }, }) - const expectedOutput = syncPrettier.format( - ` @media (prefers-color-scheme: light){ - :root { - --red: transformedValue; /* This is a description */ - } - }`, - {parser: 'css', printWidth: 500}, - ) - expect(cssAdvanced(input)).toStrictEqual(expectedOutput) - }) - - it('Hides comment if option.description is false or not set', () => { - const input = getMockFormatterArguments({ + const inputUnset = getMockFormatterArguments({ dictionary: getMockDictionary({ tokens: { subgroup: { @@ -277,23 +267,34 @@ describe('Format: tokens nested in media query', () => { }, }, }), - options: { - descriptions: false, - }, + options: {}, // description not set file: { destination: 'size-fine.css', options: { showFileHeader: false, queries: [ { - query: '@media (prefers-color-scheme: dark)', + query: '@media (prefers-color-scheme: light)', }, ], }, }, }) - const inputUnset = getMockFormatterArguments({ + const expectedOutput = syncPrettier.format( + ` @media (prefers-color-scheme: light){ + :root { + --red: transformedValue; /* This is a description */ + } + }`, + {parser: 'css', printWidth: 500}, + ) + expect(cssAdvanced(input)).toStrictEqual(expectedOutput) + expect(cssAdvanced(inputUnset)).toStrictEqual(expectedOutput) + }) + + it('Hides comment if option.formatting.commentStle is set to none', () => { + const input = getMockFormatterArguments({ dictionary: getMockDictionary({ tokens: { subgroup: { @@ -305,7 +306,11 @@ describe('Format: tokens nested in media query', () => { }, }, }), - options: {}, // description not set + options: { + formatting: { + commentStyle: 'none', + }, + }, file: { destination: 'size-fine.css', options: { @@ -328,6 +333,5 @@ describe('Format: tokens nested in media query', () => { {parser: 'css', printWidth: 500}, ) expect(cssAdvanced(input)).toStrictEqual(expectedOutput) - expect(cssAdvanced(inputUnset)).toStrictEqual(expectedOutput) }) }) diff --git a/src/formats/cssAdvanced.ts b/src/formats/cssAdvanced.ts index e11841088..75e07963f 100644 --- a/src/formats/cssAdvanced.ts +++ b/src/formats/cssAdvanced.ts @@ -18,10 +18,9 @@ export const cssAdvanced: StyleDictionary.Formatter = ({ queries: [], }, file, - platform, }: FormatterArguments): string => { // get options - const {outputReferences, descriptions} = options + const {outputReferences, formatting} = options // selector const selector = file.options?.selector !== undefined ? file.options.selector : ':root' // query extension property @@ -34,22 +33,12 @@ export const cssAdvanced: StyleDictionary.Formatter = ({ }, ] // set formatting - const formatting: LineFormatting = { - commentStyle: descriptions ? 'long' : 'none', + const mergedFormatting: LineFormatting = { + commentStyle: 'long', + ...formatting, } // clone dictionary const dictionary = {...originalDictionary} - // add prefix to tokens - if (platform.prefix) { - dictionary.allTokens = dictionary.allTokens.map( - token => - ({ - ...token, - name: `${platform.prefix}-${token.name}`, - path: [platform.prefix, ...token.path], - }) as TransformedToken, - ) - } // get queries from tokens for (const designToken of dictionary.allTokens) { const query = designToken.$extensions?.[queryExtProp] @@ -88,7 +77,12 @@ export const cssAdvanced: StyleDictionary.Formatter = ({ // early abort if no matches if (!filteredDictionary.allTokens.length) continue // add tokens into root - const css = formattedVariables({format: 'css', dictionary: filteredDictionary, outputReferences, formatting}) + const css = formattedVariables({ + format: 'css', + dictionary: filteredDictionary, + outputReferences, + formatting: mergedFormatting, + }) // wrap css const cssWithSelector = wrapWithSelector(css, query.selector !== undefined ? query.selector : selector) // add css with or without query diff --git a/src/formats/jsonNestedPrefixed.test.ts b/src/formats/jsonNestedPrefixed.test.ts index 27ac8b92c..36b82a14e 100644 --- a/src/formats/jsonNestedPrefixed.test.ts +++ b/src/formats/jsonNestedPrefixed.test.ts @@ -61,7 +61,8 @@ describe('Format: Json nested with prefixes', () => { "filePath": "file.json", "isSource": true, "value": "transformedValue", - "attributes": {} + "attributes": {}, + "description": "This is a description" } } } diff --git a/src/test-utilities/getMockDictionary.ts b/src/test-utilities/getMockDictionary.ts index 75e1080dd..924bf6305 100644 --- a/src/test-utilities/getMockDictionary.ts +++ b/src/test-utilities/getMockDictionary.ts @@ -6,6 +6,8 @@ const mockDictionaryDefault = { subgroup: { red: getMockToken({ name: 'red', + description: 'This is a description', + value: 'transformedValue', path: ['tokens', 'subgroup', 'red'], }), }, diff --git a/tsconfig.json b/tsconfig.json index 4f5973a81..d5fca2ab0 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -18,6 +18,6 @@ "~/*": ["*"] } }, - "include": ["src/", "scripts/", "docs/", "config/", "playwright.config.ts", "e2e", "vitest.config.ts"], + "include": ["src/", "scripts/", "docs/", "config/", "playwright.config.ts", "e2e", "integration", "vitest.config.ts"], "exclude": ["./src/@types"] } diff --git a/vitest.config.ts b/vitest.config.ts index f0b2ab00b..0c0c41ecd 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -3,11 +3,12 @@ import {defineConfig, configDefaults} from 'vitest/config' export default defineConfig({ test: { globals: true, - exclude: [...configDefaults.exclude, 'e2e/*', 'docs/*'], + exclude: [...configDefaults.exclude, 'e2e/*', 'integration/*', 'docs/*'], coverage: { exclude: [ 'docs/*', 'e2e/*', + 'integration/*', '.eslintrc.cjs', 'vitest.config.ts', '.prettierrc.js',