diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml new file mode 100644 index 0000000..647683f --- /dev/null +++ b/.github/workflows/lint.yml @@ -0,0 +1,18 @@ +name: Lint + +on: + pull_request: + push: + branches: + - main + +jobs: + lint: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Setup Biome + uses: biomejs/setup-biome@v2 + - name: Run Biome + run: biome ci . diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..d9fd2d6 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,54 @@ +name: Test + +on: + pull_request: + +jobs: + test: + runs-on: ubuntu-latest + strategy: + matrix: + branch: + - ${{ github.head_ref }} + - "main" + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Setup pnpm + uses: pnpm/action-setup@v4 + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: 20 + cache: pnpm + - name: pnpm install + shell: bash + run: | + pnpm install --frozen-lockfile + - name: Run test + run: pnpm run test:coverage + - name: "Upload Coverage" + uses: actions/upload-artifact@v4 + with: + name: coverage-${{ matrix.branch }} + path: coverage + report-coverage: + needs: test + runs-on: ubuntu-latest + permissions: + contents: read + pull-requests: write + steps: + - name: "Download Coverage Artifacts" + uses: actions/download-artifact@v4 + with: + name: coverage-${{ github.head_ref }} + path: coverage + - uses: actions/download-artifact@v4 + with: + name: coverage-main + path: coverage-main + - name: "Report Coverage" + uses: davelosert/vitest-coverage-report-action@v2 + with: + json-summary-compare-path: coverage-main/coverage-summary.json diff --git a/.github/workflows/type-check.yml b/.github/workflows/type-check.yml new file mode 100644 index 0000000..7c6909b --- /dev/null +++ b/.github/workflows/type-check.yml @@ -0,0 +1,27 @@ +name: TypeCheck + +on: + pull_request: + push: + branches: + - main + +jobs: + type-check: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Setup pnpm + uses: pnpm/action-setup@v4 + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: 20 + cache: pnpm + - name: pnpm install + shell: bash + run: | + pnpm install --frozen-lockfile + - name: Run tsc + run: pnpm run check:tsc diff --git a/.gitignore b/.gitignore index 69192d0..7a2f6b9 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ node_modules/ dist/ +coverage/ diff --git a/package.json b/package.json index 3754b48..782aa8a 100644 --- a/package.json +++ b/package.json @@ -20,6 +20,7 @@ "fix": "biome check --write ./", "test": "vitest run", "test:watch": "vitest --watch", + "test:coverage": "vitest run --coverage.enabled true", "prepublish": "pnpm run build" }, "dependencies": { @@ -27,13 +28,14 @@ "csstype": "^3.1.3" }, "devDependencies": { - "@biomejs/biome": "^1.9.3", + "@biomejs/biome": "^1.9.4", "@testing-library/jest-dom": "^6.5.0", "@testing-library/react": "^16.0.1", "@types/jsdom": "^21.1.7", "@types/react": "^18", "@types/react-dom": "^18", "@vitejs/plugin-react": "^4.3.2", + "@vitest/coverage-v8": "2.1.2", "jsdom": "^25.0.1", "react": "19.0.0-rc-f994737d14-20240522", "react-dom": "19.0.0-rc-f994737d14-20240522", @@ -45,6 +47,10 @@ "react": "^19.0.0", "react-dom": "^19.0.0" }, + "engines": { + "pnpm": ">=9.12.0" + }, + "packageManager": "pnpm@9.12.2", "description": "", "keywords": ["React", "CSS-in-JS", "Next.js"], "author": "Yuku Kotani (yukukotani@gmail.com)", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a1a0d66..317369e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -16,8 +16,8 @@ importers: version: 3.1.3 devDependencies: '@biomejs/biome': - specifier: ^1.9.3 - version: 1.9.3 + specifier: ^1.9.4 + version: 1.9.4 '@testing-library/jest-dom': specifier: ^6.5.0 version: 6.5.0 @@ -36,6 +36,9 @@ importers: '@vitejs/plugin-react': specifier: ^4.3.2 version: 4.3.2(vite@5.4.8(@types/node@22.7.5)) + '@vitest/coverage-v8': + specifier: 2.1.2 + version: 2.1.2(@vitest/browser@2.1.2)(vitest@2.1.2) jsdom: specifier: ^25.0.1 version: 25.0.1 @@ -155,55 +158,58 @@ packages: resolution: {integrity: sha512-JWtuCu8VQsMladxVz/P4HzHUGCAwpuqacmowgXFs5XjxIgKuNjnLokQzuVjlTvIzODaDmpjT3oxcC48vyk9EWg==} engines: {node: '>=6.9.0'} - '@biomejs/biome@1.9.3': - resolution: {integrity: sha512-POjAPz0APAmX33WOQFGQrwLvlu7WLV4CFJMlB12b6ZSg+2q6fYu9kZwLCOA+x83zXfcPd1RpuWOKJW0GbBwLIQ==} + '@bcoe/v8-coverage@0.2.3': + resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==} + + '@biomejs/biome@1.9.4': + resolution: {integrity: sha512-1rkd7G70+o9KkTn5KLmDYXihGoTaIGO9PIIN2ZB7UJxFrWw04CZHPYiMRjYsaDvVV7hP1dYNRLxSANLaBFGpog==} engines: {node: '>=14.21.3'} hasBin: true - '@biomejs/cli-darwin-arm64@1.9.3': - resolution: {integrity: sha512-QZzD2XrjJDUyIZK+aR2i5DDxCJfdwiYbUKu9GzkCUJpL78uSelAHAPy7m0GuPMVtF/Uo+OKv97W3P9nuWZangQ==} + '@biomejs/cli-darwin-arm64@1.9.4': + resolution: {integrity: sha512-bFBsPWrNvkdKrNCYeAp+xo2HecOGPAy9WyNyB/jKnnedgzl4W4Hb9ZMzYNbf8dMCGmUdSavlYHiR01QaYR58cw==} engines: {node: '>=14.21.3'} cpu: [arm64] os: [darwin] - '@biomejs/cli-darwin-x64@1.9.3': - resolution: {integrity: sha512-vSCoIBJE0BN3SWDFuAY/tRavpUtNoqiceJ5PrU3xDfsLcm/U6N93JSM0M9OAiC/X7mPPfejtr6Yc9vSgWlEgVw==} + '@biomejs/cli-darwin-x64@1.9.4': + resolution: {integrity: sha512-ngYBh/+bEedqkSevPVhLP4QfVPCpb+4BBe2p7Xs32dBgs7rh9nY2AIYUL6BgLw1JVXV8GlpKmb/hNiuIxfPfZg==} engines: {node: '>=14.21.3'} cpu: [x64] os: [darwin] - '@biomejs/cli-linux-arm64-musl@1.9.3': - resolution: {integrity: sha512-VBzyhaqqqwP3bAkkBrhVq50i3Uj9+RWuj+pYmXrMDgjS5+SKYGE56BwNw4l8hR3SmYbLSbEo15GcV043CDSk+Q==} + '@biomejs/cli-linux-arm64-musl@1.9.4': + resolution: {integrity: sha512-v665Ct9WCRjGa8+kTr0CzApU0+XXtRgwmzIf1SeKSGAv+2scAlW6JR5PMFo6FzqqZ64Po79cKODKf3/AAmECqA==} engines: {node: '>=14.21.3'} cpu: [arm64] os: [linux] - '@biomejs/cli-linux-arm64@1.9.3': - resolution: {integrity: sha512-vJkAimD2+sVviNTbaWOGqEBy31cW0ZB52KtpVIbkuma7PlfII3tsLhFa+cwbRAcRBkobBBhqZ06hXoZAN8NODQ==} + '@biomejs/cli-linux-arm64@1.9.4': + resolution: {integrity: sha512-fJIW0+LYujdjUgJJuwesP4EjIBl/N/TcOX3IvIHJQNsAqvV2CHIogsmA94BPG6jZATS4Hi+xv4SkBBQSt1N4/g==} engines: {node: '>=14.21.3'} cpu: [arm64] os: [linux] - '@biomejs/cli-linux-x64-musl@1.9.3': - resolution: {integrity: sha512-TJmnOG2+NOGM72mlczEsNki9UT+XAsMFAOo8J0me/N47EJ/vkLXxf481evfHLlxMejTY6IN8SdRSiPVLv6AHlA==} + '@biomejs/cli-linux-x64-musl@1.9.4': + resolution: {integrity: sha512-gEhi/jSBhZ2m6wjV530Yy8+fNqG8PAinM3oV7CyO+6c3CEh16Eizm21uHVsyVBEB6RIM8JHIl6AGYCv6Q6Q9Tg==} engines: {node: '>=14.21.3'} cpu: [x64] os: [linux] - '@biomejs/cli-linux-x64@1.9.3': - resolution: {integrity: sha512-x220V4c+romd26Mu1ptU+EudMXVS4xmzKxPVb9mgnfYlN4Yx9vD5NZraSx/onJnd3Gh/y8iPUdU5CDZJKg9COA==} + '@biomejs/cli-linux-x64@1.9.4': + resolution: {integrity: sha512-lRCJv/Vi3Vlwmbd6K+oQ0KhLHMAysN8lXoCI7XeHlxaajk06u7G+UsFSO01NAs5iYuWKmVZjmiOzJ0OJmGsMwg==} engines: {node: '>=14.21.3'} cpu: [x64] os: [linux] - '@biomejs/cli-win32-arm64@1.9.3': - resolution: {integrity: sha512-lg/yZis2HdQGsycUvHWSzo9kOvnGgvtrYRgoCEwPBwwAL8/6crOp3+f47tPwI/LI1dZrhSji7PNsGKGHbwyAhw==} + '@biomejs/cli-win32-arm64@1.9.4': + resolution: {integrity: sha512-tlbhLk+WXZmgwoIKwHIHEBZUwxml7bRJgk0X2sPyNR3S93cdRq6XulAZRQJ17FYGGzWne0fgrXBKpl7l4M87Hg==} engines: {node: '>=14.21.3'} cpu: [arm64] os: [win32] - '@biomejs/cli-win32-x64@1.9.3': - resolution: {integrity: sha512-cQMy2zanBkVLpmmxXdK6YePzmZx0s5Z7KEnwmrW54rcXK3myCNbQa09SwGZ8i/8sLw0H9F3X7K4rxVNGU8/D4Q==} + '@biomejs/cli-win32-x64@1.9.4': + resolution: {integrity: sha512-8Y5wMhVIPaWe6jw2H+KlEm4wP/f7EW3810ZLmDlrEEy5KvBsb9ECEfu/kMWD484ijfQ8+nIi0giMgu9g1UAuuA==} engines: {node: '>=14.21.3'} cpu: [x64] os: [win32] @@ -523,6 +529,10 @@ packages: resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} engines: {node: '>=12'} + '@istanbuljs/schema@0.1.3': + resolution: {integrity: sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==} + engines: {node: '>=8'} + '@jridgewell/gen-mapping@0.3.5': resolution: {integrity: sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==} engines: {node: '>=6.0.0'} @@ -743,6 +753,15 @@ packages: webdriverio: optional: true + '@vitest/coverage-v8@2.1.2': + resolution: {integrity: sha512-b7kHrFrs2urS0cOk5N10lttI8UdJ/yP3nB4JYTREvR5o18cR99yPpK4gK8oQgI42BVv0ILWYUSYB7AXkAUDc0g==} + peerDependencies: + '@vitest/browser': 2.1.2 + vitest: 2.1.2 + peerDependenciesMeta: + '@vitest/browser': + optional: true + '@vitest/expect@2.1.2': resolution: {integrity: sha512-FEgtlN8mIUSEAAnlvn7mP8vzaWhEaAEvhSXCqrsijM7K6QqjB11qoRZYEd4AKSCDz8p0/+yH5LzhZ47qt+EyPg==} @@ -1080,6 +1099,9 @@ packages: resolution: {integrity: sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==} engines: {node: '>=18'} + html-escaper@2.0.2: + resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==} + http-proxy-agent@7.0.2: resolution: {integrity: sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==} engines: {node: '>= 14'} @@ -1133,6 +1155,22 @@ packages: isexe@2.0.0: resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + istanbul-lib-coverage@3.2.2: + resolution: {integrity: sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==} + engines: {node: '>=8'} + + istanbul-lib-report@3.0.1: + resolution: {integrity: sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==} + engines: {node: '>=10'} + + istanbul-lib-source-maps@5.0.6: + resolution: {integrity: sha512-yg2d+Em4KizZC5niWhQaIomgf5WlL4vOOjZ5xGCmF8SnPE/mDWWXgvRExdcpCgh9lLRRa1/fSYp2ymmbJ1pI+A==} + engines: {node: '>=10'} + + istanbul-reports@3.1.7: + resolution: {integrity: sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==} + engines: {node: '>=8'} + jackspeak@3.4.3: resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==} @@ -1195,6 +1233,13 @@ packages: magic-string@0.30.12: resolution: {integrity: sha512-Ea8I3sQMVXr8JhN4z+H/d8zwo+tYDgHE9+5G4Wnrwhs0gaK9fXTKx0Tw5Xwsd/bCPTTZNRAdpyzvoeORe9LYpw==} + magicast@0.3.5: + resolution: {integrity: sha512-L0WhttDl+2BOsybvEOLK7fW3UA0OQ0IQ2d6Zl2x/a6vVRs3bAY0ECOSHHeL5jD+SbOpOCUEi0y1DgHEn9Qn1AQ==} + + make-dir@4.0.0: + resolution: {integrity: sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==} + engines: {node: '>=10'} + merge-stream@2.0.0: resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} @@ -1421,6 +1466,11 @@ packages: resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} hasBin: true + semver@7.6.3: + resolution: {integrity: sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==} + engines: {node: '>=10'} + hasBin: true + shebang-command@2.0.0: resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} engines: {node: '>=8'} @@ -1504,6 +1554,10 @@ packages: symbol-tree@3.2.4: resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==} + test-exclude@7.0.1: + resolution: {integrity: sha512-pFYqmTw68LXVjeWJMST4+borgQP2AyMNbg1BpZh9LbyhUeNkeaPF9gzfPGUAnSMV3qPYdWUwDIjjCLiSDOl7vg==} + engines: {node: '>=18'} + thenify-all@1.6.0: resolution: {integrity: sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==} engines: {node: '>=0.8'} @@ -1906,39 +1960,41 @@ snapshots: '@babel/helper-validator-identifier': 7.25.7 to-fast-properties: 2.0.0 - '@biomejs/biome@1.9.3': + '@bcoe/v8-coverage@0.2.3': {} + + '@biomejs/biome@1.9.4': optionalDependencies: - '@biomejs/cli-darwin-arm64': 1.9.3 - '@biomejs/cli-darwin-x64': 1.9.3 - '@biomejs/cli-linux-arm64': 1.9.3 - '@biomejs/cli-linux-arm64-musl': 1.9.3 - '@biomejs/cli-linux-x64': 1.9.3 - '@biomejs/cli-linux-x64-musl': 1.9.3 - '@biomejs/cli-win32-arm64': 1.9.3 - '@biomejs/cli-win32-x64': 1.9.3 + '@biomejs/cli-darwin-arm64': 1.9.4 + '@biomejs/cli-darwin-x64': 1.9.4 + '@biomejs/cli-linux-arm64': 1.9.4 + '@biomejs/cli-linux-arm64-musl': 1.9.4 + '@biomejs/cli-linux-x64': 1.9.4 + '@biomejs/cli-linux-x64-musl': 1.9.4 + '@biomejs/cli-win32-arm64': 1.9.4 + '@biomejs/cli-win32-x64': 1.9.4 - '@biomejs/cli-darwin-arm64@1.9.3': + '@biomejs/cli-darwin-arm64@1.9.4': optional: true - '@biomejs/cli-darwin-x64@1.9.3': + '@biomejs/cli-darwin-x64@1.9.4': optional: true - '@biomejs/cli-linux-arm64-musl@1.9.3': + '@biomejs/cli-linux-arm64-musl@1.9.4': optional: true - '@biomejs/cli-linux-arm64@1.9.3': + '@biomejs/cli-linux-arm64@1.9.4': optional: true - '@biomejs/cli-linux-x64-musl@1.9.3': + '@biomejs/cli-linux-x64-musl@1.9.4': optional: true - '@biomejs/cli-linux-x64@1.9.3': + '@biomejs/cli-linux-x64@1.9.4': optional: true - '@biomejs/cli-win32-arm64@1.9.3': + '@biomejs/cli-win32-arm64@1.9.4': optional: true - '@biomejs/cli-win32-x64@1.9.3': + '@biomejs/cli-win32-x64@1.9.4': optional: true '@bundled-es-modules/cookie@2.0.0': @@ -2142,6 +2198,8 @@ snapshots: wrap-ansi: 8.1.0 wrap-ansi-cjs: wrap-ansi@7.0.0 + '@istanbuljs/schema@0.1.3': {} + '@jridgewell/gen-mapping@0.3.5': dependencies: '@jridgewell/set-array': 1.2.1 @@ -2368,6 +2426,26 @@ snapshots: - vite optional: true + '@vitest/coverage-v8@2.1.2(@vitest/browser@2.1.2)(vitest@2.1.2)': + dependencies: + '@ampproject/remapping': 2.3.0 + '@bcoe/v8-coverage': 0.2.3 + debug: 4.3.7 + istanbul-lib-coverage: 3.2.2 + istanbul-lib-report: 3.0.1 + istanbul-lib-source-maps: 5.0.6 + istanbul-reports: 3.1.7 + magic-string: 0.30.12 + magicast: 0.3.5 + std-env: 3.7.0 + test-exclude: 7.0.1 + tinyrainbow: 1.2.0 + vitest: 2.1.2(@types/node@22.7.5)(@vitest/browser@2.1.2)(jsdom@25.0.1)(msw@2.4.10(typescript@5.6.3)) + optionalDependencies: + '@vitest/browser': 2.1.2(@vitest/spy@2.1.2)(playwright@1.48.0)(typescript@5.6.3)(vite@5.4.8(@types/node@22.7.5))(vitest@2.1.2) + transitivePeerDependencies: + - supports-color + '@vitest/expect@2.1.2': dependencies: '@vitest/spy': 2.1.2 @@ -2731,6 +2809,8 @@ snapshots: dependencies: whatwg-encoding: 3.1.1 + html-escaper@2.0.2: {} + http-proxy-agent@7.0.2: dependencies: agent-base: 7.1.1 @@ -2776,6 +2856,27 @@ snapshots: isexe@2.0.0: {} + istanbul-lib-coverage@3.2.2: {} + + istanbul-lib-report@3.0.1: + dependencies: + istanbul-lib-coverage: 3.2.2 + make-dir: 4.0.0 + supports-color: 7.2.0 + + istanbul-lib-source-maps@5.0.6: + dependencies: + '@jridgewell/trace-mapping': 0.3.25 + debug: 4.3.7 + istanbul-lib-coverage: 3.2.2 + transitivePeerDependencies: + - supports-color + + istanbul-reports@3.1.7: + dependencies: + html-escaper: 2.0.2 + istanbul-lib-report: 3.0.1 + jackspeak@3.4.3: dependencies: '@isaacs/cliui': 8.0.2 @@ -2842,6 +2943,16 @@ snapshots: dependencies: '@jridgewell/sourcemap-codec': 1.5.0 + magicast@0.3.5: + dependencies: + '@babel/parser': 7.25.8 + '@babel/types': 7.25.8 + source-map-js: 1.2.1 + + make-dir@4.0.0: + dependencies: + semver: 7.6.3 + merge-stream@2.0.0: {} mime-db@1.52.0: {} @@ -3046,6 +3157,8 @@ snapshots: semver@6.3.1: {} + semver@7.6.3: {} + shebang-command@2.0.0: dependencies: shebang-regex: 3.0.0 @@ -3127,6 +3240,12 @@ snapshots: symbol-tree@3.2.4: {} + test-exclude@7.0.1: + dependencies: + '@istanbuljs/schema': 0.1.3 + glob: 10.4.5 + minimatch: 9.0.5 + thenify-all@1.6.0: dependencies: thenify: 3.3.1 diff --git a/src/__snapshots__/styled.test.tsx.snap b/src/__snapshots__/styled.test.tsx.snap index a6f78f8..77b65a5 100644 --- a/src/__snapshots__/styled.test.tsx.snap +++ b/src/__snapshots__/styled.test.tsx.snap @@ -1,11 +1,5 @@ // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html -exports[`styled > renders dynamic style 1`] = `".j1dqz { color: red; }"`; - -exports[`styled > renders dynamic style 2`] = `".jyt81 { gap: var(--j-spaces-md); }"`; - -exports[`styled > renders dynamic style 3`] = `".j1o5l { background-color: gray; }"`; - exports[`styled > renders style tag in head 1`] = `".j1dqz { color: red; }"`; exports[`styled > renders style tag in head 2`] = `".jyt81 { gap: var(--j-spaces-md); }"`; diff --git a/src/index.ts b/src/index.ts index 2df0b4c..ffd426f 100644 --- a/src/index.ts +++ b/src/index.ts @@ -2,6 +2,6 @@ export { Box } from "./Box"; export { defineConfig, type JustStyledConfig } from "./config"; -export { type StyleProps } from "./style-props"; +export type { StyleProps } from "./style-props"; export { styled } from "./styled"; export { ThemeProvider } from "./theme"; diff --git a/src/styled.test.tsx b/src/styled.test.tsx index b5f9478..20948a5 100644 --- a/src/styled.test.tsx +++ b/src/styled.test.tsx @@ -1,18 +1,30 @@ import { render, waitFor } from "@testing-library/react"; -import React from "react"; -import { describe, expect, test } from "vitest"; +import React, { type ComponentProps } from "react"; +import { beforeEach, describe, expect, test, vi } from "vitest"; +import { generateSheets } from "./sheet"; import { styled } from "./styled"; describe("styled", async () => { + beforeEach(() => { + vi.clearAllMocks(); + vi.mock("./sheet", { spy: true }); + }); + test("renders style tag in head", async () => { const RedDiv = styled("div", { color: "red", gap: "$spaces.md", }); - render(RedDiv); + render(RedDiv); await waitFor(() => { + expect(generateSheets).toHaveBeenCalledTimes(1); + expect(generateSheets).toHaveBeenCalledWith({ + color: "red", + gap: "$spaces.md", + }); + const styleTags = Array.from( document.getElementsByTagName("style"), ).filter((e) => e.dataset.href != null); @@ -26,29 +38,57 @@ describe("styled", async () => { }); test("renders dynamic style", async () => { - const RedDiv = styled("div", { - color: "red", + const YellowDiv = styled("div", { + color: "yellow", }); render( - + RedDiv - , + , ); await waitFor(() => { - const styleTags = Array.from( - document.getElementsByTagName("style"), - ).filter((e) => e.dataset.href != null); - expect(styleTags).toHaveLength(3); - for (const styleTag of styleTags) { - expect(document.head).toContainElement(styleTag); - expect(styleTag).toHaveAttribute("data-precedence", "medium"); - expect(styleTag.textContent).toMatchSnapshot(); - } + expect(generateSheets).toHaveBeenCalledTimes(2); + expect(generateSheets).toHaveBeenCalledWith({ color: "yellow" }); + expect(generateSheets).toHaveBeenCalledWith({ + backgroundColor: "gray", + padding: "$spaces.md", + }); + }); + }); + + test("renders styled custom component", async () => { + const BlueComp = styled(Comp, { + color: "blue", + }); + + const res = render( + + BlueComp + , + ); + const el = await res.findByTestId("blue-comp"); + + await waitFor(() => { + expect(generateSheets).toHaveBeenCalledTimes(1); + expect(generateSheets).toHaveBeenCalledWith({ color: "blue" }); + + expect(el.className).not.toBe(""); + expect(el).toHaveAttribute("data-title", "Blue"); }); }); }); + +function Comp({ + children, + title, + ...props +}: ComponentProps<"div"> & { title: string }) { + return ( +
+ {title} +
{children}
+
+ ); +} diff --git a/vitest.config.ts b/vitest.config.ts index f53b286..12ca2b5 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -7,5 +7,9 @@ export default defineConfig({ setupFiles: "./vitest.setup.ts", globals: true, environment: "jsdom", + coverage: { + reporter: ["text", "json-summary", "json"], + reportOnFailure: true, + }, }, });