From 5e89d423468856ad8dee7e88e813b939976cf332 Mon Sep 17 00:00:00 2001 From: Sebastian Jeltsch Date: Thu, 27 Feb 2025 13:28:11 +0100 Subject: [PATCH] Add component tests for form ui abstractions. --- examples/collab-clicker-ssr/package.json | 2 +- pnpm-lock.yaml | 255 ++++++++++++++---- trailbase-core/js/admin/.prettierignore | 2 + trailbase-core/js/admin/README.md | 4 +- trailbase-core/js/admin/index.html | 7 +- trailbase-core/js/admin/package.json | 5 +- .../js/admin/src/components/FormFields.tsx | 3 + trailbase-core/js/admin/tests/form.test.tsx | 219 +++++++++++++++ trailbase-core/js/admin/tests/util.test.ts | 22 +- trailbase-core/js/admin/tsconfig.json | 8 +- trailbase-core/js/admin/vite.config.mts | 13 +- 11 files changed, 457 insertions(+), 83 deletions(-) create mode 100644 trailbase-core/js/admin/tests/form.test.tsx diff --git a/examples/collab-clicker-ssr/package.json b/examples/collab-clicker-ssr/package.json index f450babb..18219c2f 100644 --- a/examples/collab-clicker-ssr/package.json +++ b/examples/collab-clicker-ssr/package.json @@ -31,6 +31,6 @@ "typescript-eslint": "^8.25.0", "vite": "^6.2.0", "vite-plugin-eslint": "^1.8.1", - "vite-plugin-solid": "^2.11.4" + "vite-plugin-solid": "^2.11.5" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 00e64d7d..e97923d7 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -59,7 +59,7 @@ importers: version: 3.2.1 '@astrojs/solid-js': specifier: ^5.0.4 - version: 5.0.4(@types/node@22.13.5)(jiti@2.4.2)(lightningcss@1.29.1)(solid-devtools@0.30.1(solid-js@1.9.5)(vite@6.2.0(@types/node@22.13.5)(jiti@2.4.2)(lightningcss@1.29.1)(yaml@2.7.0)))(solid-js@1.9.5)(yaml@2.7.0) + version: 5.0.4(@testing-library/jest-dom@6.6.3)(@types/node@22.13.5)(jiti@2.4.2)(lightningcss@1.29.1)(solid-devtools@0.30.1(solid-js@1.9.5)(vite@6.2.0(@types/node@22.13.5)(jiti@2.4.2)(lightningcss@1.29.1)(yaml@2.7.0)))(solid-js@1.9.5)(yaml@2.7.0) astro-robots-txt: specifier: ^1.0.0 version: 1.0.0 @@ -130,7 +130,7 @@ importers: devDependencies: '@astrojs/solid-js': specifier: ^5.0.4 - version: 5.0.4(@types/node@16.18.126)(jiti@2.4.2)(lightningcss@1.29.1)(solid-devtools@0.30.1(solid-js@1.9.5)(vite@5.4.14(@types/node@16.18.126)(lightningcss@1.29.1)))(solid-js@1.9.5)(yaml@2.7.0) + version: 5.0.4(@testing-library/jest-dom@6.6.3)(@types/node@16.18.126)(jiti@2.4.2)(lightningcss@1.29.1)(solid-devtools@0.30.1(solid-js@1.9.5)(vite@5.4.14(@types/node@16.18.126)(lightningcss@1.29.1)))(solid-js@1.9.5)(yaml@2.7.0) '@iconify-json/tabler': specifier: ^1.2.16 version: 1.2.16 @@ -254,8 +254,8 @@ importers: specifier: ^1.8.1 version: 1.8.1(eslint@9.21.0(jiti@2.4.2))(vite@6.2.0(@types/node@22.13.5)(jiti@2.4.2)(lightningcss@1.29.1)(yaml@2.7.0)) vite-plugin-solid: - specifier: ^2.11.4 - version: 2.11.4(solid-js@1.9.5)(vite@6.2.0(@types/node@22.13.5)(jiti@2.4.2)(lightningcss@1.29.1)(yaml@2.7.0)) + specifier: ^2.11.5 + version: 2.11.5(@testing-library/jest-dom@6.6.3)(solid-js@1.9.5)(vite@6.2.0(@types/node@22.13.5)(jiti@2.4.2)(lightningcss@1.29.1)(yaml@2.7.0)) examples/data-cli-tutorial: dependencies: @@ -396,9 +396,18 @@ importers: '@iconify-json/tabler': specifier: ^1.2.16 version: 1.2.16 + '@solidjs/testing-library': + specifier: ^0.8.10 + version: 0.8.10(@solidjs/router@0.15.3(solid-js@1.9.5))(solid-js@1.9.5) '@tailwindcss/typography': specifier: ^0.5.16 version: 0.5.16(tailwindcss@3.4.17(ts-node@10.9.2(@types/node@22.13.5)(typescript@5.7.3))) + '@testing-library/jest-dom': + specifier: ^6.6.3 + version: 6.6.3 + '@testing-library/user-event': + specifier: ^14.6.1 + version: 14.6.1(@testing-library/dom@10.4.0) '@types/geojson': specifier: ^7946.0.16 version: 7946.0.16 @@ -443,7 +452,7 @@ importers: version: 6.2.0(@types/node@22.13.5)(jiti@2.4.2)(lightningcss@1.29.1)(yaml@2.7.0) vite-plugin-solid: specifier: ^2.11.5 - version: 2.11.5(solid-js@1.9.5)(vite@6.2.0(@types/node@22.13.5)(jiti@2.4.2)(lightningcss@1.29.1)(yaml@2.7.0)) + version: 2.11.5(@testing-library/jest-dom@6.6.3)(solid-js@1.9.5)(vite@6.2.0(@types/node@22.13.5)(jiti@2.4.2)(lightningcss@1.29.1)(yaml@2.7.0)) vite-tsconfig-paths: specifier: ^5.1.4 version: 5.1.4(typescript@5.7.3)(vite@6.2.0(@types/node@22.13.5)(jiti@2.4.2)(lightningcss@1.29.1)(yaml@2.7.0)) @@ -458,7 +467,7 @@ importers: version: 0.9.4(prettier-plugin-astro@0.14.1)(prettier@3.5.2)(typescript@5.7.3) '@astrojs/solid-js': specifier: ^5.0.4 - version: 5.0.4(@types/node@22.13.5)(jiti@2.4.2)(lightningcss@1.29.1)(solid-devtools@0.30.1(solid-js@1.9.5)(vite@5.4.14(@types/node@22.13.5)(lightningcss@1.29.1)))(solid-js@1.9.5)(yaml@2.7.0) + version: 5.0.4(@testing-library/jest-dom@6.6.3)(@types/node@22.13.5)(jiti@2.4.2)(lightningcss@1.29.1)(solid-devtools@0.30.1(solid-js@1.9.5)(vite@5.4.14(@types/node@22.13.5)(lightningcss@1.29.1)))(solid-js@1.9.5)(yaml@2.7.0) '@astrojs/tailwind': specifier: ^5.1.5 version: 5.1.5(astro@5.3.1(@types/node@22.13.5)(jiti@2.4.2)(lightningcss@1.29.1)(rollup@4.34.8)(typescript@5.7.3)(yaml@2.7.0))(tailwindcss@3.4.17(ts-node@10.9.2(@types/node@22.13.5)(typescript@5.7.3)))(ts-node@10.9.2(@types/node@22.13.5)(typescript@5.7.3)) @@ -578,6 +587,9 @@ importers: packages: + '@adobe/css-tools@4.4.2': + resolution: {integrity: sha512-baYZExFpsdkBNuvGKTKWCwKH57HRZLVtycZS05WTQNVOiXVSeAki3nU35zlRbToeMW8aHlJfyS+1C4BOv27q0A==} + '@alloc/quick-lru@5.2.0': resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==} engines: {node: '>=10'} @@ -1905,6 +1917,16 @@ packages: peerDependencies: solid-js: ^1.8.6 + '@solidjs/testing-library@0.8.10': + resolution: {integrity: sha512-qdeuIerwyq7oQTIrrKvV0aL9aFeuwTd86VYD3afdq5HYEwoox1OBTJy4y8A3TFZr8oAR0nujYgCzY/8wgHGfeQ==} + engines: {node: '>= 14'} + peerDependencies: + '@solidjs/router': '>=0.9.0' + solid-js: '>=1.0.0' + peerDependenciesMeta: + '@solidjs/router': + optional: true + '@swc/helpers@0.5.15': resolution: {integrity: sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g==} @@ -1947,6 +1969,20 @@ packages: resolution: {integrity: sha512-uvXk/U4cBiFMxt+p9/G7yUWI/UbHYbyghLCjlpWZ3mLeIZiUBSKcUnw9UnKkdRz7Z/N4UBuFLWQdJCjUe7HjvA==} engines: {node: '>=12'} + '@testing-library/dom@10.4.0': + resolution: {integrity: sha512-pemlzrSESWbdAloYml3bAJMEfNh1Z7EduzqPKprCH5S341frlpYnUEW0H72dLxa6IsYr+mPno20GiSm+h9dEdQ==} + engines: {node: '>=18'} + + '@testing-library/jest-dom@6.6.3': + resolution: {integrity: sha512-IteBhl4XqYNkM54f4ejhLRJiZNqcSCoXUOG2CPK7qbD322KjQozM4kHQOfkG2oln9b9HTYqs+Sae8vBATubxxA==} + engines: {node: '>=14', npm: '>=6', yarn: '>=1'} + + '@testing-library/user-event@14.6.1': + resolution: {integrity: sha512-vq7fv0rnt+QTXgPxr5Hjc210p6YKq2kmdziLgnsZGgLJ9e6VAShx1pACLuRjd/AS/sr7phAR58OIIpf0LlmQNw==} + engines: {node: '>=12', npm: '>=6'} + peerDependencies: + '@testing-library/dom': '>=7.21.4' + '@trysound/sax@0.2.0': resolution: {integrity: sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==} engines: {node: '>=10.13.0'} @@ -1966,6 +2002,9 @@ packages: '@types/acorn@4.0.6': resolution: {integrity: sha512-veQTnWP+1D/xbxVrPC3zHnCZRjSrKfhbMUlEA43iMZLu7EsnTtkJklIuwrCPbOi8YkvDQAiW05VQQFvvz9oieQ==} + '@types/aria-query@5.0.4': + resolution: {integrity: sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==} + '@types/babel__core@7.20.5': resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==} @@ -2249,6 +2288,10 @@ packages: resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} engines: {node: '>=8'} + ansi-styles@5.2.0: + resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==} + engines: {node: '>=10'} + ansi-styles@6.2.1: resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} engines: {node: '>=12'} @@ -2272,6 +2315,9 @@ packages: argparse@2.0.1: resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + aria-query@5.3.0: + resolution: {integrity: sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==} + aria-query@5.3.2: resolution: {integrity: sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==} engines: {node: '>= 0.4'} @@ -2441,6 +2487,10 @@ packages: resolution: {integrity: sha512-/ghrgmhfY8RaSdeo43hNXxpoHAtxdbskUHjPpfqUWGttFgycUhYPGx3YZBCnUCvOa7Doivn1IZec3DEGFoMgLg==} engines: {node: '>=12'} + chalk@3.0.0: + resolution: {integrity: sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==} + engines: {node: '>=8'} + chalk@4.1.2: resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} engines: {node: '>=10'} @@ -2639,6 +2689,9 @@ packages: resolution: {integrity: sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==} engines: {node: '>= 6'} + css.escape@1.5.1: + resolution: {integrity: sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==} + cssesc@3.0.0: resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} engines: {node: '>=4'} @@ -2763,6 +2816,12 @@ packages: dlv@1.1.3: resolution: {integrity: sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==} + dom-accessibility-api@0.5.16: + resolution: {integrity: sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==} + + dom-accessibility-api@0.6.3: + resolution: {integrity: sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w==} + dom-serializer@2.0.0: resolution: {integrity: sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==} @@ -2793,8 +2852,8 @@ packages: ee-first@1.1.1: resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} - electron-to-chromium@1.5.106: - resolution: {integrity: sha512-12keJGdXQWPnfVOu6/6ZzZgPPNodiDOSe3LjA8qk2yXTjnCnw2LeGUsAmtlNAmH4UW0K7tOLcz0j9lI2eJCJRA==} + electron-to-chromium@1.5.107: + resolution: {integrity: sha512-dJr1o6yCntRkXElnhsHh1bAV19bo/hKyFf7tCcWgpXbuFIF0Lakjgqv5LRfSDaNzAII8Fnxg2tqgHkgCvxdbxw==} emmet@2.4.11: resolution: {integrity: sha512-23QPJB3moh/U9sT4rQzGgeyyGIrcM+GH5uVYg2C6wZIxAIJq7Ng3QLT79tl8FUwDXhyq9SusfknOrofAKqvgyQ==} @@ -3368,6 +3427,10 @@ packages: resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} engines: {node: '>=0.8.19'} + indent-string@4.0.0: + resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==} + engines: {node: '>=8'} + inflight@1.0.6: resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful. @@ -3639,8 +3702,8 @@ packages: resolution: {integrity: sha512-9rrA30MRRP3gBD3HTGnC6cDFpaE1kVDWxWgqWJUN0RvDNAo+Nz/9GxB+nHOH0ifbVFy0hSA1V6vFDvnx54lTEQ==} engines: {node: '>=14'} - local-pkg@1.0.0: - resolution: {integrity: sha512-bbgPw/wmroJsil/GgL4qjDzs5YLTBMQ99weRsok1XCDccQeehbHA/I1oRvk2NPtr7KGZgT/Y5tPRnAtMqeG2Kg==} + local-pkg@1.1.0: + resolution: {integrity: sha512-xbZBuX6gYIWrlLmZG43aAVer4ocntYO09vPy9lxd6Ns8DnR4U7N+IIeDkubinqFOHHzoMlPxTxwo0jhE7oYjAw==} engines: {node: '>=14'} locate-path@5.0.0: @@ -3681,6 +3744,10 @@ packages: lru-cache@5.1.1: resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} + lz-string@1.5.0: + resolution: {integrity: sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==} + hasBin: true + magic-string@0.30.17: resolution: {integrity: sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==} @@ -3909,6 +3976,10 @@ packages: resolution: {integrity: sha512-XqoSHeCGjVClAmoGFG3lVFqQFRIrTVw2OH3axRqAcfaw+gHWIfnASS92AV+Rl/mk0MupgZTRHQOjxY6YVnzK5w==} engines: {node: '>= 0.6'} + min-indent@1.0.1: + resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==} + engines: {node: '>=4'} + minimatch@3.1.2: resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} @@ -4284,6 +4355,10 @@ packages: engines: {node: '>=14'} hasBin: true + pretty-format@27.5.1: + resolution: {integrity: sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + pretty-ms@9.2.0: resolution: {integrity: sha512-4yf0QO/sllf/1zbZWYnvWw3NxCQwLXKzIj0G849LSufP15BXKM0rbD2Z3wVnkMfjdn/CB0Dpp444gYAACdsplg==} engines: {node: '>=18'} @@ -4332,6 +4407,9 @@ packages: resolution: {integrity: sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==} engines: {node: '>=0.6'} + quansync@0.2.1: + resolution: {integrity: sha512-/TVkmtJM+2Uf026dN921iQH229IqJ+4MhcYoGypKQQWGetWiiRjP0PDWKarids4smgSTsNTtCoZswre1sqQn5w==} + queue-microtask@1.2.3: resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} @@ -4365,6 +4443,9 @@ packages: peerDependencies: react: ^19.0.0 + react-is@17.0.2: + resolution: {integrity: sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==} + react-refresh@0.14.2: resolution: {integrity: sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==} engines: {node: '>=0.10.0'} @@ -4408,6 +4489,10 @@ packages: recma-stringify@1.0.0: resolution: {integrity: sha512-cjwII1MdIIVloKvC9ErQ+OgAtwHBmcZ0Bg4ciz78FtbT8In39aAYbaA7zvxQ61xVMSPE8WxhLwLbhif4Js2C+g==} + redent@3.0.0: + resolution: {integrity: sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==} + engines: {node: '>=8'} + regenerator-runtime@0.14.1: resolution: {integrity: sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==} @@ -4746,6 +4831,10 @@ packages: resolution: {integrity: sha512-aulFJcD6YK8V1G7iRB5tigAP4TsHBZZrOV8pjV++zdUwmeV8uzbY7yn6h9MswN62adStNZFuCIx4haBnRuMDaw==} engines: {node: '>=18'} + strip-indent@3.0.0: + resolution: {integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==} + engines: {node: '>=8'} + strip-json-comments@3.1.1: resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} engines: {node: '>=8'} @@ -4837,11 +4926,11 @@ packages: resolution: {integrity: sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q==} engines: {node: '>=14.0.0'} - tldts-core@6.1.78: - resolution: {integrity: sha512-jS0svNsB99jR6AJBmfmEWuKIgz91Haya91Z43PATaeHJ24BkMoNRb/jlaD37VYjb0mYf6gRL/HOnvS1zEnYBiw==} + tldts-core@6.1.79: + resolution: {integrity: sha512-HM+Ud/2oQuHt4I43Nvjc213Zji/z25NSH5OkJskJwHXNtYh9DTRlHMDFhms9dFMP7qyve/yVaXFIxmcJ7TdOjw==} - tldts@6.1.78: - resolution: {integrity: sha512-fSgYrW0ITH0SR/CqKMXIruYIPpNu5aDgUp22UhYoSrnUQwc7SBqifEBFNce7AAcygUPBo6a/gbtcguWdmko4RQ==} + tldts@6.1.79: + resolution: {integrity: sha512-wjlYwK8lC/WcywLWf3A7qbK07SexezXjTRVwuPWXHvcjD7MnpPS2RXY5rLO3g12a8CNc7Y7jQRQsV7XyuBZjig==} hasBin: true to-regex-range@5.0.1: @@ -5149,16 +5238,6 @@ packages: eslint: '>=7' vite: '>=2' - vite-plugin-solid@2.11.4: - resolution: {integrity: sha512-qTy8FbA1oAwIaCl8+lmAJwMZ9fR7UcwQ68nVuX4VH6b1l059MrbKffgmJharcMJhqD/yJ+pD/EdSna6HEddEmw==} - peerDependencies: - '@testing-library/jest-dom': ^5.16.6 || ^5.17.0 || ^6.* - solid-js: ^1.7.2 - vite: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 - peerDependenciesMeta: - '@testing-library/jest-dom': - optional: true - vite-plugin-solid@2.11.5: resolution: {integrity: sha512-XRXToYfVPDMZmlLzPoyYebGLCNa5pI/jv6LQxJBIadclaR1chyl8IDwdwJ7GY49whjDlom3cfDAI+00JQLgpzw==} peerDependencies: @@ -5569,6 +5648,8 @@ packages: snapshots: + '@adobe/css-tools@4.4.2': {} + '@alloc/quick-lru@5.2.0': {} '@ampproject/remapping@2.3.0': @@ -5686,11 +5767,11 @@ snapshots: stream-replace-string: 2.0.0 zod: 3.24.2 - '@astrojs/solid-js@5.0.4(@types/node@16.18.126)(jiti@2.4.2)(lightningcss@1.29.1)(solid-devtools@0.30.1(solid-js@1.9.5)(vite@5.4.14(@types/node@16.18.126)(lightningcss@1.29.1)))(solid-js@1.9.5)(yaml@2.7.0)': + '@astrojs/solid-js@5.0.4(@testing-library/jest-dom@6.6.3)(@types/node@16.18.126)(jiti@2.4.2)(lightningcss@1.29.1)(solid-devtools@0.30.1(solid-js@1.9.5)(vite@5.4.14(@types/node@16.18.126)(lightningcss@1.29.1)))(solid-js@1.9.5)(yaml@2.7.0)': dependencies: solid-js: 1.9.5 vite: 6.2.0(@types/node@16.18.126)(jiti@2.4.2)(lightningcss@1.29.1)(yaml@2.7.0) - vite-plugin-solid: 2.11.4(solid-js@1.9.5)(vite@6.2.0(@types/node@16.18.126)(jiti@2.4.2)(lightningcss@1.29.1)(yaml@2.7.0)) + vite-plugin-solid: 2.11.5(@testing-library/jest-dom@6.6.3)(solid-js@1.9.5)(vite@6.2.0(@types/node@16.18.126)(jiti@2.4.2)(lightningcss@1.29.1)(yaml@2.7.0)) optionalDependencies: solid-devtools: 0.30.1(solid-js@1.9.5)(vite@5.4.14(@types/node@16.18.126)(lightningcss@1.29.1)) transitivePeerDependencies: @@ -5708,11 +5789,11 @@ snapshots: - tsx - yaml - '@astrojs/solid-js@5.0.4(@types/node@22.13.5)(jiti@2.4.2)(lightningcss@1.29.1)(solid-devtools@0.30.1(solid-js@1.9.5)(vite@5.4.14(@types/node@22.13.5)(lightningcss@1.29.1)))(solid-js@1.9.5)(yaml@2.7.0)': + '@astrojs/solid-js@5.0.4(@testing-library/jest-dom@6.6.3)(@types/node@22.13.5)(jiti@2.4.2)(lightningcss@1.29.1)(solid-devtools@0.30.1(solid-js@1.9.5)(vite@5.4.14(@types/node@22.13.5)(lightningcss@1.29.1)))(solid-js@1.9.5)(yaml@2.7.0)': dependencies: solid-js: 1.9.5 vite: 6.2.0(@types/node@22.13.5)(jiti@2.4.2)(lightningcss@1.29.1)(yaml@2.7.0) - vite-plugin-solid: 2.11.4(solid-js@1.9.5)(vite@6.2.0(@types/node@22.13.5)(jiti@2.4.2)(lightningcss@1.29.1)(yaml@2.7.0)) + vite-plugin-solid: 2.11.5(@testing-library/jest-dom@6.6.3)(solid-js@1.9.5)(vite@6.2.0(@types/node@22.13.5)(jiti@2.4.2)(lightningcss@1.29.1)(yaml@2.7.0)) optionalDependencies: solid-devtools: 0.30.1(solid-js@1.9.5)(vite@5.4.14(@types/node@22.13.5)(lightningcss@1.29.1)) transitivePeerDependencies: @@ -5730,11 +5811,11 @@ snapshots: - tsx - yaml - '@astrojs/solid-js@5.0.4(@types/node@22.13.5)(jiti@2.4.2)(lightningcss@1.29.1)(solid-devtools@0.30.1(solid-js@1.9.5)(vite@6.2.0(@types/node@22.13.5)(jiti@2.4.2)(lightningcss@1.29.1)(yaml@2.7.0)))(solid-js@1.9.5)(yaml@2.7.0)': + '@astrojs/solid-js@5.0.4(@testing-library/jest-dom@6.6.3)(@types/node@22.13.5)(jiti@2.4.2)(lightningcss@1.29.1)(solid-devtools@0.30.1(solid-js@1.9.5)(vite@6.2.0(@types/node@22.13.5)(jiti@2.4.2)(lightningcss@1.29.1)(yaml@2.7.0)))(solid-js@1.9.5)(yaml@2.7.0)': dependencies: solid-js: 1.9.5 vite: 6.2.0(@types/node@22.13.5)(jiti@2.4.2)(lightningcss@1.29.1)(yaml@2.7.0) - vite-plugin-solid: 2.11.4(solid-js@1.9.5)(vite@6.2.0(@types/node@22.13.5)(jiti@2.4.2)(lightningcss@1.29.1)(yaml@2.7.0)) + vite-plugin-solid: 2.11.5(@testing-library/jest-dom@6.6.3)(solid-js@1.9.5)(vite@6.2.0(@types/node@22.13.5)(jiti@2.4.2)(lightningcss@1.29.1)(yaml@2.7.0)) optionalDependencies: solid-devtools: 0.30.1(solid-js@1.9.5)(vite@6.2.0(@types/node@22.13.5)(jiti@2.4.2)(lightningcss@1.29.1)(yaml@2.7.0)) transitivePeerDependencies: @@ -6406,7 +6487,7 @@ snapshots: debug: 4.4.0 globals: 15.15.0 kolorist: 1.8.0 - local-pkg: 1.0.0 + local-pkg: 1.1.0 mlly: 1.7.4 transitivePeerDependencies: - supports-color @@ -6937,6 +7018,13 @@ snapshots: dependencies: solid-js: 1.9.5 + '@solidjs/testing-library@0.8.10(@solidjs/router@0.15.3(solid-js@1.9.5))(solid-js@1.9.5)': + dependencies: + '@testing-library/dom': 10.4.0 + solid-js: 1.9.5 + optionalDependencies: + '@solidjs/router': 0.15.3(solid-js@1.9.5) + '@swc/helpers@0.5.15': dependencies: tslib: 2.8.1 @@ -6988,6 +7076,31 @@ snapshots: '@tanstack/table-core@8.21.2': {} + '@testing-library/dom@10.4.0': + dependencies: + '@babel/code-frame': 7.26.2 + '@babel/runtime': 7.26.9 + '@types/aria-query': 5.0.4 + aria-query: 5.3.0 + chalk: 4.1.2 + dom-accessibility-api: 0.5.16 + lz-string: 1.5.0 + pretty-format: 27.5.1 + + '@testing-library/jest-dom@6.6.3': + dependencies: + '@adobe/css-tools': 4.4.2 + aria-query: 5.3.2 + chalk: 3.0.0 + css.escape: 1.5.1 + dom-accessibility-api: 0.6.3 + lodash: 4.17.21 + redent: 3.0.0 + + '@testing-library/user-event@14.6.1(@testing-library/dom@10.4.0)': + dependencies: + '@testing-library/dom': 10.4.0 + '@trysound/sax@0.2.0': {} '@tsconfig/node10@1.0.11': {} @@ -7002,6 +7115,8 @@ snapshots: dependencies: '@types/estree': 1.0.6 + '@types/aria-query@5.0.4': {} + '@types/babel__core@7.20.5': dependencies: '@babel/parser': 7.26.9 @@ -7375,6 +7490,8 @@ snapshots: dependencies: color-convert: 2.0.1 + ansi-styles@5.2.0: {} + ansi-styles@6.2.1: {} any-promise@1.3.0: {} @@ -7394,6 +7511,10 @@ snapshots: argparse@2.0.1: {} + aria-query@5.3.0: + dependencies: + dequal: 2.0.3 + aria-query@5.3.2: {} array-back@3.1.0: {} @@ -7719,7 +7840,7 @@ snapshots: browserslist@4.24.4: dependencies: caniuse-lite: 1.0.30001701 - electron-to-chromium: 1.5.106 + electron-to-chromium: 1.5.107 node-releases: 2.0.19 update-browserslist-db: 1.1.3(browserslist@4.24.4) @@ -7768,6 +7889,11 @@ snapshots: dependencies: chalk: 4.1.2 + chalk@3.0.0: + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + chalk@4.1.2: dependencies: ansi-styles: 4.3.0 @@ -7980,6 +8106,8 @@ snapshots: css-what@6.1.0: {} + css.escape@1.5.1: {} + cssesc@3.0.0: {} csso@5.0.5: @@ -8060,6 +8188,10 @@ snapshots: dlv@1.1.3: {} + dom-accessibility-api@0.5.16: {} + + dom-accessibility-api@0.6.3: {} + dom-serializer@2.0.0: dependencies: domelementtype: 2.3.0 @@ -8094,7 +8226,7 @@ snapshots: ee-first@1.1.1: {} - electron-to-chromium@1.5.106: {} + electron-to-chromium@1.5.107: {} emmet@2.4.11: dependencies: @@ -8934,6 +9066,8 @@ snapshots: imurmurhash@0.1.4: {} + indent-string@4.0.0: {} + inflight@1.0.6: dependencies: once: 1.4.0 @@ -9157,10 +9291,11 @@ snapshots: mlly: 1.7.4 pkg-types: 1.3.1 - local-pkg@1.0.0: + local-pkg@1.1.0: dependencies: mlly: 1.7.4 pkg-types: 1.3.1 + quansync: 0.2.1 locate-path@5.0.0: dependencies: @@ -9192,6 +9327,8 @@ snapshots: dependencies: yallist: 3.1.1 + lz-string@1.5.0: {} + magic-string@0.30.17: dependencies: '@jridgewell/sourcemap-codec': 1.5.0 @@ -9702,6 +9839,8 @@ snapshots: dependencies: mime-db: 1.53.0 + min-indent@1.0.1: {} + minimatch@3.1.2: dependencies: brace-expansion: 1.1.11 @@ -10038,6 +10177,12 @@ snapshots: prettier@3.5.2: {} + pretty-format@27.5.1: + dependencies: + ansi-regex: 5.0.1 + ansi-styles: 5.2.0 + react-is: 17.0.2 + pretty-ms@9.2.0: dependencies: parse-ms: 4.0.0 @@ -10092,6 +10237,8 @@ snapshots: dependencies: side-channel: 1.1.0 + quansync@0.2.1: {} + queue-microtask@1.2.3: {} quicktype-core@23.0.171: @@ -10170,6 +10317,8 @@ snapshots: react: 19.0.0 scheduler: 0.25.0 + react-is@17.0.2: {} + react-refresh@0.14.2: {} react@19.0.0: {} @@ -10236,6 +10385,11 @@ snapshots: unified: 11.0.5 vfile: 6.0.3 + redent@3.0.0: + dependencies: + indent-string: 4.0.0 + strip-indent: 3.0.0 + regenerator-runtime@0.14.1: {} regex-recursion@5.1.1: @@ -10738,6 +10892,10 @@ snapshots: strip-final-newline@4.0.0: {} + strip-indent@3.0.0: + dependencies: + min-indent: 1.0.1 + strip-json-comments@3.1.1: {} style-mod@4.1.2: {} @@ -10879,11 +11037,11 @@ snapshots: tinyspy@3.0.2: {} - tldts-core@6.1.78: {} + tldts-core@6.1.79: {} - tldts@6.1.78: + tldts@6.1.79: dependencies: - tldts-core: 6.1.78 + tldts-core: 6.1.79 to-regex-range@5.0.1: dependencies: @@ -10895,7 +11053,7 @@ snapshots: tough-cookie@5.1.1: dependencies: - tldts: 6.1.78 + tldts: 6.1.79 tr46@0.0.3: {} @@ -11180,7 +11338,7 @@ snapshots: rollup: 2.79.2 vite: 6.2.0(@types/node@22.13.5)(jiti@2.4.2)(lightningcss@1.29.1)(yaml@2.7.0) - vite-plugin-solid@2.11.4(solid-js@1.9.5)(vite@6.2.0(@types/node@16.18.126)(jiti@2.4.2)(lightningcss@1.29.1)(yaml@2.7.0)): + vite-plugin-solid@2.11.5(@testing-library/jest-dom@6.6.3)(solid-js@1.9.5)(vite@6.2.0(@types/node@16.18.126)(jiti@2.4.2)(lightningcss@1.29.1)(yaml@2.7.0)): dependencies: '@babel/core': 7.26.9 '@types/babel__core': 7.20.5 @@ -11190,23 +11348,12 @@ snapshots: solid-refresh: 0.6.3(solid-js@1.9.5) vite: 6.2.0(@types/node@16.18.126)(jiti@2.4.2)(lightningcss@1.29.1)(yaml@2.7.0) vitefu: 1.0.6(vite@6.2.0(@types/node@16.18.126)(jiti@2.4.2)(lightningcss@1.29.1)(yaml@2.7.0)) + optionalDependencies: + '@testing-library/jest-dom': 6.6.3 transitivePeerDependencies: - supports-color - vite-plugin-solid@2.11.4(solid-js@1.9.5)(vite@6.2.0(@types/node@22.13.5)(jiti@2.4.2)(lightningcss@1.29.1)(yaml@2.7.0)): - dependencies: - '@babel/core': 7.26.9 - '@types/babel__core': 7.20.5 - babel-preset-solid: 1.9.5(@babel/core@7.26.9) - merge-anything: 5.1.7 - solid-js: 1.9.5 - solid-refresh: 0.6.3(solid-js@1.9.5) - vite: 6.2.0(@types/node@22.13.5)(jiti@2.4.2)(lightningcss@1.29.1)(yaml@2.7.0) - vitefu: 1.0.6(vite@6.2.0(@types/node@22.13.5)(jiti@2.4.2)(lightningcss@1.29.1)(yaml@2.7.0)) - transitivePeerDependencies: - - supports-color - - vite-plugin-solid@2.11.5(solid-js@1.9.5)(vite@6.2.0(@types/node@22.13.5)(jiti@2.4.2)(lightningcss@1.29.1)(yaml@2.7.0)): + vite-plugin-solid@2.11.5(@testing-library/jest-dom@6.6.3)(solid-js@1.9.5)(vite@6.2.0(@types/node@22.13.5)(jiti@2.4.2)(lightningcss@1.29.1)(yaml@2.7.0)): dependencies: '@babel/core': 7.26.9 '@types/babel__core': 7.20.5 @@ -11216,6 +11363,8 @@ snapshots: solid-refresh: 0.6.3(solid-js@1.9.5) vite: 6.2.0(@types/node@22.13.5)(jiti@2.4.2)(lightningcss@1.29.1)(yaml@2.7.0) vitefu: 1.0.6(vite@6.2.0(@types/node@22.13.5)(jiti@2.4.2)(lightningcss@1.29.1)(yaml@2.7.0)) + optionalDependencies: + '@testing-library/jest-dom': 6.6.3 transitivePeerDependencies: - supports-color diff --git a/trailbase-core/js/admin/.prettierignore b/trailbase-core/js/admin/.prettierignore index fd50c4f3..35321354 100644 --- a/trailbase-core/js/admin/.prettierignore +++ b/trailbase-core/js/admin/.prettierignore @@ -4,3 +4,5 @@ package-lock.json yarn.lock src/components/ui +node_modules/ +proto/ diff --git a/trailbase-core/js/admin/README.md b/trailbase-core/js/admin/README.md index 491b8f98..5dee9a3b 100644 --- a/trailbase-core/js/admin/README.md +++ b/trailbase-core/js/admin/README.md @@ -28,8 +28,8 @@ $ pnpm run proto , which requires the following system dependencies: - * **protoc**, e.g. via the `protobuf-compiler` Debian/Ubuntu package - * **descriptor.proto**, e.g. via the `libprotobuf-dev` Debian/Ubuntu package. +- **protoc**, e.g. via the `protobuf-compiler` Debian/Ubuntu package +- **descriptor.proto**, e.g. via the `libprotobuf-dev` Debian/Ubuntu package. ## Rust-TypeScript codegen diff --git a/trailbase-core/js/admin/index.html b/trailbase-core/js/admin/index.html index 12a4910c..51f19d96 100644 --- a/trailbase-core/js/admin/index.html +++ b/trailbase-core/js/admin/index.html @@ -1,4 +1,4 @@ - + @@ -6,7 +6,10 @@ - + diff --git a/trailbase-core/js/admin/package.json b/trailbase-core/js/admin/package.json index 081c131e..82dd4867 100644 --- a/trailbase-core/js/admin/package.json +++ b/trailbase-core/js/admin/package.json @@ -7,7 +7,7 @@ "dev": "vite", "build": "vite build", "serve": "vite preview", - "format": "prettier -w src", + "format": "prettier -w .", "proto": "protoc --plugin=protoc-gen-ts=${PWD}/node_modules/ts-proto/protoc-gen-ts_proto ../../proto/*.proto -I../../proto -I/usr/include --ts_out=./proto/ --ts_opt=esModuleInterop=true,initializeFieldsAsUndefined=false", "check": "tsc --noEmit --skipLibCheck && eslint && vitest run", "test": "vitest run" @@ -49,7 +49,10 @@ "devDependencies": { "@eslint/js": "^9.21.0", "@iconify-json/tabler": "^1.2.16", + "@solidjs/testing-library": "^0.8.10", "@tailwindcss/typography": "^0.5.16", + "@testing-library/jest-dom": "^6.6.3", + "@testing-library/user-event": "^14.6.1", "@types/geojson": "^7946.0.16", "@types/leaflet": "^1.9.16", "@types/wicg-file-system-access": "^2023.10.5", diff --git a/trailbase-core/js/admin/src/components/FormFields.tsx b/trailbase-core/js/admin/src/components/FormFields.tsx index b3eaefcb..4a18004b 100644 --- a/trailbase-core/js/admin/src/components/FormFields.tsx +++ b/trailbase-core/js/admin/src/components/FormFields.tsx @@ -71,6 +71,7 @@ export function buildTextFormFieldT( onKeyUp={(e) => field().handleChange((e.target as HTMLInputElement).value as T) } + data-testid="input" />
@@ -123,6 +124,7 @@ export function buildOptionalTextFormFieldT( onKeyUp={(e) => field().handleChange((e.target as HTMLInputElement).value as T) } + data-testid="input" /> ( const value = enabled ? (initialValue ?? "") : null; field().handleChange(value as T); }} + data-testid="toggle" />
diff --git a/trailbase-core/js/admin/tests/form.test.tsx b/trailbase-core/js/admin/tests/form.test.tsx new file mode 100644 index 00000000..9e3ee81d --- /dev/null +++ b/trailbase-core/js/admin/tests/form.test.tsx @@ -0,0 +1,219 @@ +import { createSignal, type Setter, type JSX } from "solid-js"; +import { describe, test, expect } from "vitest"; +import { render } from "@solidjs/testing-library"; +import userEvent from "@testing-library/user-event"; +import { createForm, type FieldApi } from "@tanstack/solid-form"; + +import { + buildTextFormField, + buildOptionalTextFormField, +} from "@/components/FormFields"; + +const user = userEvent.setup(); + +describe("form fields", () => { + interface MyForm { + required: string; + optional: string | undefined; + nullable: string | null; + optionalNullable: string | null | undefined; + } + + function newMyForm( + setter: Setter, + defaultValue?: MyForm, + ) { + const form = createForm(() => ({ + defaultValues: + defaultValue ?? + ({ + required: "default", + nullable: null, + } as MyForm), + onSubmit: async ({ value }: { value: MyForm }) => setter(value), + })); + + return form; + } + + function Form(props: { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + name: any; + setForm: Setter; + defaultValue?: MyForm; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + field: (field: () => FieldApi) => JSX.Element; + }) { + const form = newMyForm(props.setForm, props.defaultValue); + + return ( +
{ + e.preventDefault(); + e.stopPropagation(); + form.handleSubmit(); + }} + > + {props.field} + + + + +
+ ); + } + + test("test required form", async () => { + const [form, setForm] = createSignal(); + + const result = render(() => ( +
"required" })} + /> + )); + + const input: HTMLInputElement = result.getByTestId("input"); + await user.type(input, " test"); + + await user.click(result.getByTestId("sub")); + + const value = form()!; + expect(value.required).toBe("default test"); + }); + + describe("optional nullable", () => { + test("set", async () => { + const [form, setForm] = createSignal(); + + const result = render(() => ( + "optional" })} + /> + )); + + const input: HTMLInputElement = result.getByTestId("input"); + expect(input.disabled); + + // The input field is disabled to to it's initial value being null. + // NOTE: The solid-ui Checkbox component wraps the input in a parent div. + const toggle = result.getByTestId("toggle") + .firstChild! as HTMLInputElement; + await user.click(toggle); + expect(toggle.value); + + await user.type(input, "optional"); + expect(input.value, "optional"); + + await user.click(result.getByTestId("sub")); + + const value = form()!; + expect(value.optionalNullable).toBe("optional"); + }); + + test("set and unset", async () => { + const [form, setForm] = createSignal(); + + const result = render(() => ( + "optional" })} + /> + )); + + const input: HTMLInputElement = result.getByTestId("input"); + expect(input.disabled); + + // The input field is disabled to to it's initial value being null. + // NOTE: The solid-ui Checkbox component wraps the input in a parent div. + const toggle = result.getByTestId("toggle") + .firstChild! as HTMLInputElement; + await user.click(toggle); + expect(toggle.value); + + await user.type(input, "optional"); + expect(input.value, "optional"); + + await user.click(toggle); + expect(!toggle.value); + + await user.click(result.getByTestId("sub")); + + const value = form()!; + expect(value.optionalNullable).toBe(null); + }); + }); + + describe("optional", () => { + test("set", async () => { + const [form, setForm] = createSignal(); + + const result = render(() => ( + "optional" })} + /> + )); + + const input: HTMLInputElement = result.getByTestId("input"); + expect(input.disabled); + + // The input field is disabled to to it's initial value being null. + // NOTE: The solid-ui Checkbox component wraps the input in a parent div. + const toggle = result.getByTestId("toggle") + .firstChild! as HTMLInputElement; + await user.click(toggle); + expect(toggle.value); + + await user.type(input, "optional"); + expect(input.value, "optional"); + + await user.click(result.getByTestId("sub")); + + const value = form()!; + expect(value.optional).toBe("optional"); + }); + + test("set and unset", async () => { + const [form, setForm] = createSignal(); + + const result = render(() => ( + "optional" })} + /> + )); + + const input: HTMLInputElement = result.getByTestId("input"); + expect(input.disabled); + + // The input field is disabled to to it's initial value being null. + // NOTE: The solid-ui Checkbox component wraps the input in a parent div. + const toggle = result.getByTestId("toggle") + .firstChild! as HTMLInputElement; + await user.click(toggle); + expect(toggle.value); + + await user.type(input, "optional"); + expect(input.value, "optional"); + + await user.click(toggle); + expect(!toggle.value); + + await user.click(result.getByTestId("sub")); + + const value = form()!; + // FIXME: This should be undefined. We've circumvented the type-checking, + // optional should not be allowed to be null. + expect(value.optional).toBe(null); + }); + }); +}); diff --git a/trailbase-core/js/admin/tests/util.test.ts b/trailbase-core/js/admin/tests/util.test.ts index 5eb67b21..b2b0833e 100644 --- a/trailbase-core/js/admin/tests/util.test.ts +++ b/trailbase-core/js/admin/tests/util.test.ts @@ -1,15 +1,17 @@ -import { expect, test } from "vitest" +import { expect, test, describe } from "vitest"; import { copyAndConvertRow } from "@/lib/convert"; type UnknownRow = { [key: string]: unknown }; -test("utils", () => { - const x: UnknownRow = { - "foo": "test", - "bar": "test", - }; - const y = copyAndConvertRow(x); - for (const key of Object.keys(x)) { - expect(x[key]).toBe(y[key]); - } +describe("utils", () => { + test("coypAndConvertRow", () => { + const x: UnknownRow = { + foo: "test", + bar: "test", + }; + const y = copyAndConvertRow(x); + for (const key of Object.keys(x)) { + expect(x[key]).toBe(y[key]); + } + }); }); diff --git a/trailbase-core/js/admin/tsconfig.json b/trailbase-core/js/admin/tsconfig.json index 13c4d520..0a559b1b 100644 --- a/trailbase-core/js/admin/tsconfig.json +++ b/trailbase-core/js/admin/tsconfig.json @@ -10,6 +10,7 @@ "jsx": "preserve", "jsxImportSource": "solid-js", "types": [ + "@testing-library/jest-dom", "@types/wicg-file-system-access", "vite/client" ], @@ -20,10 +21,5 @@ "@styles/*": ["../styles/*"] } }, - "exclude": [ - "tailwind.config.ts", - "dist/", - "node_modules/", - "public/" - ] + "exclude": ["tailwind.config.ts", "dist/", "node_modules/", "public/"] } diff --git a/trailbase-core/js/admin/vite.config.mts b/trailbase-core/js/admin/vite.config.mts index bc9fc1fe..40fd7ed1 100644 --- a/trailbase-core/js/admin/vite.config.mts +++ b/trailbase-core/js/admin/vite.config.mts @@ -1,18 +1,15 @@ -import { defineConfig } from 'vite'; +import { defineConfig } from "vite"; -import tsconfigPaths from 'vite-tsconfig-paths'; -import solidPlugin from 'vite-plugin-solid'; +import tsconfigPaths from "vite-tsconfig-paths"; +import solidPlugin from "vite-plugin-solid"; export default defineConfig({ base: "/_/admin", - plugins: [ - solidPlugin(), - tsconfigPaths(), - ], + plugins: [solidPlugin(), tsconfigPaths()], server: { port: 3000, }, build: { - target: 'esnext', + target: "esnext", }, });