termcast 1.3.19 β 1.3.24
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ai.d.ts +104 -0
- package/dist/ai.d.ts.map +1 -0
- package/dist/ai.js +135 -0
- package/dist/ai.js.map +1 -0
- package/dist/apis/browser-extension.d.ts +18 -0
- package/dist/apis/browser-extension.d.ts.map +1 -0
- package/dist/apis/browser-extension.js +14 -0
- package/dist/apis/browser-extension.js.map +1 -0
- package/dist/apis/localstorage.d.ts.map +1 -1
- package/dist/apis/localstorage.js +4 -7
- package/dist/apis/localstorage.js.map +1 -1
- package/dist/apis/oauth.d.ts.map +1 -1
- package/dist/apis/oauth.js +5 -1
- package/dist/apis/oauth.js.map +1 -1
- package/dist/apis/preferences.d.ts.map +1 -1
- package/dist/apis/preferences.js +38 -19
- package/dist/apis/preferences.js.map +1 -1
- package/dist/build.d.ts.map +1 -1
- package/dist/build.js +2 -1
- package/dist/build.js.map +1 -1
- package/dist/cache.d.ts +32 -0
- package/dist/cache.d.ts.map +1 -0
- package/dist/cache.js +205 -0
- package/dist/cache.js.map +1 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +69 -33
- package/dist/cli.js.map +1 -1
- package/dist/clipboard.d.ts +36 -0
- package/dist/clipboard.d.ts.map +1 -0
- package/dist/clipboard.js +154 -0
- package/dist/clipboard.js.map +1 -0
- package/dist/compile.d.ts.map +1 -1
- package/dist/compile.js +24 -6
- package/dist/compile.js.map +1 -1
- package/dist/components/actions.d.ts.map +1 -1
- package/dist/components/actions.js +56 -30
- package/dist/components/actions.js.map +1 -1
- package/dist/components/detail.d.ts.map +1 -1
- package/dist/components/detail.js +4 -0
- package/dist/components/detail.js.map +1 -1
- package/dist/components/dropdown.d.ts.map +1 -1
- package/dist/components/dropdown.js +38 -15
- package/dist/components/dropdown.js.map +1 -1
- package/dist/components/extension-preferences.d.ts.map +1 -1
- package/dist/components/extension-preferences.js +40 -13
- package/dist/components/extension-preferences.js.map +1 -1
- package/dist/components/form/checkbox.d.ts.map +1 -1
- package/dist/components/form/checkbox.js +5 -3
- package/dist/components/form/checkbox.js.map +1 -1
- package/dist/components/form/date-picker.d.ts.map +1 -1
- package/dist/components/form/date-picker.js +5 -3
- package/dist/components/form/date-picker.js.map +1 -1
- package/dist/components/form/description.d.ts.map +1 -1
- package/dist/components/form/description.js +2 -2
- package/dist/components/form/description.js.map +1 -1
- package/dist/components/form/dropdown.d.ts.map +1 -1
- package/dist/components/form/dropdown.js +84 -80
- package/dist/components/form/dropdown.js.map +1 -1
- package/dist/components/form/file-autocomplete.d.ts +3 -6
- package/dist/components/form/file-autocomplete.d.ts.map +1 -1
- package/dist/components/form/file-autocomplete.js +61 -66
- package/dist/components/form/file-autocomplete.js.map +1 -1
- package/dist/components/form/file-picker.d.ts.map +1 -1
- package/dist/components/form/file-picker.js +33 -30
- package/dist/components/form/file-picker.js.map +1 -1
- package/dist/components/form/form-end.d.ts.map +1 -1
- package/dist/components/form/form-end.js +21 -1
- package/dist/components/form/form-end.js.map +1 -1
- package/dist/components/form/form-type-only.d.ts +174 -0
- package/dist/components/form/form-type-only.d.ts.map +1 -0
- package/dist/components/form/form-type-only.js +2 -0
- package/dist/components/form/form-type-only.js.map +1 -0
- package/dist/components/form/index.d.ts +3 -1
- package/dist/components/form/index.d.ts.map +1 -1
- package/dist/components/form/index.js +100 -28
- package/dist/components/form/index.js.map +1 -1
- package/dist/components/form/password-field.d.ts.map +1 -1
- package/dist/components/form/password-field.js +5 -3
- package/dist/components/form/password-field.js.map +1 -1
- package/dist/components/form/text-area.d.ts.map +1 -1
- package/dist/components/form/text-area.js +5 -3
- package/dist/components/form/text-area.js.map +1 -1
- package/dist/components/form/text-field.d.ts.map +1 -1
- package/dist/components/form/text-field.js +6 -4
- package/dist/components/form/text-field.js.map +1 -1
- package/dist/components/form/types.d.ts +5 -0
- package/dist/components/form/types.d.ts.map +1 -1
- package/dist/components/form/use-form-handling.d.ts +4 -0
- package/dist/components/form/use-form-handling.d.ts.map +1 -0
- package/dist/components/form/use-form-handling.js +37 -0
- package/dist/components/form/use-form-handling.js.map +1 -0
- package/dist/components/form/with-left-border.d.ts +2 -1
- package/dist/components/form/with-left-border.d.ts.map +1 -1
- package/dist/components/form/with-left-border.js +27 -3
- package/dist/components/form/with-left-border.js.map +1 -1
- package/dist/components/icon.d.ts +1 -0
- package/dist/components/icon.d.ts.map +1 -1
- package/dist/components/icon.js +24 -8
- package/dist/components/icon.js.map +1 -1
- package/dist/components/list.d.ts +2 -2
- package/dist/components/list.d.ts.map +1 -1
- package/dist/components/list.js +140 -62
- package/dist/components/list.js.map +1 -1
- package/dist/components/loading-bar.d.ts.map +1 -1
- package/dist/components/loading-bar.js +2 -2
- package/dist/components/loading-bar.js.map +1 -1
- package/dist/components/loading-text.d.ts +8 -0
- package/dist/components/loading-text.d.ts.map +1 -0
- package/dist/components/loading-text.js +58 -0
- package/dist/components/loading-text.js.map +1 -0
- package/dist/descendants.js +1 -1
- package/dist/descendants.js.map +1 -1
- package/dist/dev-ui.d.ts +7 -0
- package/dist/dev-ui.d.ts.map +1 -0
- package/dist/dev-ui.js +118 -0
- package/dist/dev-ui.js.map +1 -0
- package/dist/environment.d.ts +63 -0
- package/dist/environment.d.ts.map +1 -0
- package/dist/environment.js +189 -0
- package/dist/environment.js.map +1 -0
- package/dist/examples/datepicker.d.ts +2 -0
- package/dist/examples/datepicker.d.ts.map +1 -0
- package/dist/examples/datepicker.js +344 -0
- package/dist/examples/datepicker.js.map +1 -0
- package/dist/examples/file-autocomplete.vitest.d.ts +2 -0
- package/dist/examples/file-autocomplete.vitest.d.ts.map +1 -0
- package/dist/examples/file-autocomplete.vitest.js +223 -0
- package/dist/examples/file-autocomplete.vitest.js.map +1 -0
- package/dist/examples/form-basic-arrow-keys.vitest.d.ts +2 -0
- package/dist/examples/form-basic-arrow-keys.vitest.d.ts.map +1 -0
- package/dist/examples/form-basic-arrow-keys.vitest.js +46 -0
- package/dist/examples/form-basic-arrow-keys.vitest.js.map +1 -0
- package/dist/examples/form-basic.vitest.d.ts +2 -0
- package/dist/examples/form-basic.vitest.d.ts.map +1 -0
- package/dist/examples/form-basic.vitest.js +630 -0
- package/dist/examples/form-basic.vitest.js.map +1 -0
- package/dist/examples/form-dropdown-with-sections.d.ts +2 -0
- package/dist/examples/form-dropdown-with-sections.d.ts.map +1 -0
- package/dist/examples/form-dropdown-with-sections.js +13 -0
- package/dist/examples/form-dropdown-with-sections.js.map +1 -0
- package/dist/examples/form-dropdown-with-sections.vitest.d.ts +2 -0
- package/dist/examples/form-dropdown-with-sections.vitest.d.ts.map +1 -0
- package/dist/examples/form-dropdown-with-sections.vitest.js +75 -0
- package/dist/examples/form-dropdown-with-sections.vitest.js.map +1 -0
- package/dist/examples/form-dropdown.vitest.d.ts +2 -0
- package/dist/examples/form-dropdown.vitest.d.ts.map +1 -0
- package/dist/examples/form-dropdown.vitest.js +854 -0
- package/dist/examples/form-dropdown.vitest.js.map +1 -0
- package/dist/examples/form-multiselect-dropdown.d.ts +2 -0
- package/dist/examples/form-multiselect-dropdown.d.ts.map +1 -0
- package/dist/examples/form-multiselect-dropdown.js +13 -0
- package/dist/examples/form-multiselect-dropdown.js.map +1 -0
- package/dist/examples/form-scroll.d.ts.map +1 -1
- package/dist/examples/form-scroll.js +7 -1
- package/dist/examples/form-scroll.js.map +1 -1
- package/dist/examples/form-scroll.vitest.d.ts +2 -0
- package/dist/examples/form-scroll.vitest.d.ts.map +1 -0
- package/dist/examples/form-scroll.vitest.js +211 -0
- package/dist/examples/form-scroll.vitest.js.map +1 -0
- package/dist/examples/form-tagpicker.vitest.d.ts +2 -0
- package/dist/examples/form-tagpicker.vitest.d.ts.map +1 -0
- package/dist/examples/form-tagpicker.vitest.js +736 -0
- package/dist/examples/form-tagpicker.vitest.js.map +1 -0
- package/dist/examples/internal/descendants-filtering.js +1 -1
- package/dist/examples/internal/descendants-filtering.js.map +1 -1
- package/dist/examples/internal/descendants.js +1 -1
- package/dist/examples/internal/descendants.js.map +1 -1
- package/dist/examples/internal/nested-boxes.d.ts +2 -0
- package/dist/examples/internal/nested-boxes.d.ts.map +1 -0
- package/dist/examples/internal/nested-boxes.js +7 -0
- package/dist/examples/internal/nested-boxes.js.map +1 -0
- package/dist/examples/internal/rhf-custom-ref.js +2 -2
- package/dist/examples/internal/rhf-custom-ref.js.map +1 -1
- package/dist/examples/internal/scrollbox-demo.js +3 -22
- package/dist/examples/internal/scrollbox-demo.js.map +1 -1
- package/dist/examples/internal/scrollbox-descendants.d.ts +2 -0
- package/dist/examples/internal/scrollbox-descendants.d.ts.map +1 -0
- package/dist/examples/internal/scrollbox-descendants.js +83 -0
- package/dist/examples/internal/scrollbox-descendants.js.map +1 -0
- package/dist/examples/internal/scrollbox-with-descendants.js +4 -8
- package/dist/examples/internal/scrollbox-with-descendants.js.map +1 -1
- package/dist/examples/internal/simple-scrollbox.vitest.d.ts +2 -0
- package/dist/examples/internal/simple-scrollbox.vitest.d.ts.map +1 -0
- package/dist/examples/internal/simple-scrollbox.vitest.js +96 -0
- package/dist/examples/internal/simple-scrollbox.vitest.js.map +1 -0
- package/dist/examples/internal/unicode-square-repro.d.ts +2 -0
- package/dist/examples/internal/unicode-square-repro.d.ts.map +1 -0
- package/dist/examples/internal/unicode-square-repro.js +7 -0
- package/dist/examples/internal/unicode-square-repro.js.map +1 -0
- package/dist/examples/list-detail-metadata.d.ts +2 -0
- package/dist/examples/list-detail-metadata.d.ts.map +1 -0
- package/dist/examples/list-detail-metadata.js +8 -0
- package/dist/examples/list-detail-metadata.js.map +1 -0
- package/dist/examples/list-dropdown-default.vitest.d.ts +2 -0
- package/dist/examples/list-dropdown-default.vitest.d.ts.map +1 -0
- package/dist/examples/list-dropdown-default.vitest.js +234 -0
- package/dist/examples/list-dropdown-default.vitest.js.map +1 -0
- package/dist/examples/list-fetch-data.vitest.d.ts +2 -0
- package/dist/examples/list-fetch-data.vitest.d.ts.map +1 -0
- package/dist/examples/list-fetch-data.vitest.js +111 -0
- package/dist/examples/list-fetch-data.vitest.js.map +1 -0
- package/dist/examples/list-filter-navigation.d.ts +2 -0
- package/dist/examples/list-filter-navigation.d.ts.map +1 -0
- package/dist/examples/list-filter-navigation.js +8 -0
- package/dist/examples/list-filter-navigation.js.map +1 -0
- package/dist/examples/list-scrollbox.vitest.d.ts +2 -0
- package/dist/examples/list-scrollbox.vitest.d.ts.map +1 -0
- package/dist/examples/list-scrollbox.vitest.js +93 -0
- package/dist/examples/list-scrollbox.vitest.js.map +1 -0
- package/dist/examples/list-with-detail-long.d.ts +2 -0
- package/dist/examples/list-with-detail-long.d.ts.map +1 -0
- package/dist/examples/list-with-detail-long.js +53 -0
- package/dist/examples/list-with-detail-long.js.map +1 -0
- package/dist/examples/list-with-detail.vitest.d.ts +2 -0
- package/dist/examples/list-with-detail.vitest.d.ts.map +1 -0
- package/dist/examples/list-with-detail.vitest.js +434 -0
- package/dist/examples/list-with-detail.vitest.js.map +1 -0
- package/dist/examples/list-with-dropdown.vitest.d.ts +2 -0
- package/dist/examples/list-with-dropdown.vitest.d.ts.map +1 -0
- package/dist/examples/list-with-dropdown.vitest.js +337 -0
- package/dist/examples/list-with-dropdown.vitest.js.map +1 -0
- package/dist/examples/list-with-sections.js +5 -1
- package/dist/examples/list-with-sections.js.map +1 -1
- package/dist/examples/list-with-sections.vitest.d.ts +2 -0
- package/dist/examples/list-with-sections.vitest.d.ts.map +1 -0
- package/dist/examples/list-with-sections.vitest.js +601 -0
- package/dist/examples/list-with-sections.vitest.js.map +1 -0
- package/dist/examples/scrollbox-vertical-centering.d.ts +6 -0
- package/dist/examples/scrollbox-vertical-centering.d.ts.map +1 -0
- package/dist/examples/scrollbox-vertical-centering.js +17 -0
- package/dist/examples/scrollbox-vertical-centering.js.map +1 -0
- package/dist/examples/simple-file-picker.vitest.d.ts +2 -0
- package/dist/examples/simple-file-picker.vitest.d.ts.map +1 -0
- package/dist/examples/simple-file-picker.vitest.js +678 -0
- package/dist/examples/simple-file-picker.vitest.js.map +1 -0
- package/dist/examples/simple-grid.vitest.d.ts +2 -0
- package/dist/examples/simple-grid.vitest.d.ts.map +1 -0
- package/dist/examples/simple-grid.vitest.js +521 -0
- package/dist/examples/simple-grid.vitest.js.map +1 -0
- package/dist/examples/simple-navigation.js +10 -4
- package/dist/examples/simple-navigation.js.map +1 -1
- package/dist/examples/simple-navigation.vitest.d.ts +2 -0
- package/dist/examples/simple-navigation.vitest.d.ts.map +1 -0
- package/dist/examples/simple-navigation.vitest.js +718 -0
- package/dist/examples/simple-navigation.vitest.js.map +1 -0
- package/dist/examples/store.vitest.d.ts +2 -0
- package/dist/examples/store.vitest.d.ts.map +1 -0
- package/dist/examples/store.vitest.js +69 -0
- package/dist/examples/store.vitest.js.map +1 -0
- package/dist/extensions/dev.d.ts +4 -2
- package/dist/extensions/dev.d.ts.map +1 -1
- package/dist/extensions/dev.js +61 -10
- package/dist/extensions/dev.js.map +1 -1
- package/dist/extensions/dev.vitest.d.ts +2 -0
- package/dist/extensions/dev.vitest.d.ts.map +1 -0
- package/dist/extensions/dev.vitest.js +197 -0
- package/dist/extensions/dev.vitest.js.map +1 -0
- package/dist/extensions/home.d.ts.map +1 -1
- package/dist/extensions/home.js +3 -0
- package/dist/extensions/home.js.map +1 -1
- package/dist/home-command.d.ts +8 -0
- package/dist/home-command.d.ts.map +1 -0
- package/dist/home-command.js +181 -0
- package/dist/home-command.js.map +1 -0
- package/dist/hover-repro.d.ts +2 -0
- package/dist/hover-repro.d.ts.map +1 -0
- package/dist/hover-repro.js +20 -0
- package/dist/hover-repro.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/internal/dialog.d.ts +1 -0
- package/dist/internal/dialog.d.ts.map +1 -1
- package/dist/internal/dialog.js +27 -18
- package/dist/internal/dialog.js.map +1 -1
- package/dist/internal/navigation.d.ts +9 -1
- package/dist/internal/navigation.d.ts.map +1 -1
- package/dist/internal/navigation.js +5 -5
- package/dist/internal/navigation.js.map +1 -1
- package/dist/internal/offscreen.d.ts +6 -0
- package/dist/internal/offscreen.d.ts.map +1 -0
- package/dist/internal/offscreen.js +10 -0
- package/dist/internal/offscreen.js.map +1 -0
- package/dist/internal/providers.d.ts.map +1 -1
- package/dist/internal/providers.js +2 -2
- package/dist/internal/providers.js.map +1 -1
- package/dist/internal/scrollbox.d.ts +1 -10
- package/dist/internal/scrollbox.d.ts.map +1 -1
- package/dist/internal/scrollbox.js +2 -1
- package/dist/internal/scrollbox.js.map +1 -1
- package/dist/localstorage.d.ts +13 -0
- package/dist/localstorage.d.ts.map +1 -0
- package/dist/localstorage.js +190 -0
- package/dist/localstorage.js.map +1 -0
- package/dist/oauth.d.ts +142 -0
- package/dist/oauth.d.ts.map +1 -0
- package/dist/oauth.js +551 -0
- package/dist/oauth.js.map +1 -0
- package/dist/preferences.d.ts +23 -0
- package/dist/preferences.d.ts.map +1 -0
- package/dist/preferences.js +105 -0
- package/dist/preferences.js.map +1 -0
- package/dist/state.d.ts +2 -0
- package/dist/state.d.ts.map +1 -1
- package/dist/state.js +3 -0
- package/dist/state.js.map +1 -1
- package/dist/store.d.ts +21 -0
- package/dist/store.d.ts.map +1 -0
- package/dist/store.js +84 -0
- package/dist/store.js.map +1 -0
- package/dist/swift-loader.d.ts +3 -0
- package/dist/swift-loader.d.ts.map +1 -0
- package/dist/swift-loader.js +193 -0
- package/dist/swift-loader.js.map +1 -0
- package/dist/swift-runtime.d.ts +2 -0
- package/dist/swift-runtime.d.ts.map +1 -0
- package/dist/swift-runtime.js +27 -0
- package/dist/swift-runtime.js.map +1 -0
- package/dist/toast.d.ts +44 -0
- package/dist/toast.d.ts.map +1 -0
- package/dist/toast.js +221 -0
- package/dist/toast.js.map +1 -0
- package/dist/utils/file-system.d.ts +9 -0
- package/dist/utils/file-system.d.ts.map +1 -1
- package/dist/utils/file-system.js +49 -0
- package/dist/utils/file-system.js.map +1 -1
- package/dist/utils/run-command.d.ts +25 -1
- package/dist/utils/run-command.d.ts.map +1 -1
- package/dist/utils/run-command.js +47 -4
- package/dist/utils/run-command.js.map +1 -1
- package/dist/window.d.ts +12 -0
- package/dist/window.d.ts.map +1 -0
- package/dist/window.js +48 -0
- package/dist/window.js.map +1 -0
- package/package.json +13 -11
- package/src/apis/browser-extension.tsx +29 -0
- package/src/apis/localstorage.test.ts +14 -6
- package/src/apis/localstorage.tsx +8 -5
- package/src/apis/oauth.tsx +5 -1
- package/src/apis/preferences.tsx +48 -22
- package/src/build.test.tsx +52 -0
- package/src/build.tsx +2 -1
- package/src/cli.tsx +80 -39
- package/src/compile.tsx +24 -6
- package/src/components/actions.tsx +94 -32
- package/src/components/detail.tsx +4 -0
- package/src/components/dropdown.tsx +47 -14
- package/src/components/extension-preferences.tsx +44 -16
- package/src/components/form/checkbox.tsx +12 -6
- package/src/components/form/date-picker.tsx +12 -6
- package/src/components/form/description.tsx +7 -2
- package/src/components/form/dropdown.tsx +131 -119
- package/src/components/form/file-autocomplete.tsx +90 -108
- package/src/components/form/file-picker.tsx +54 -43
- package/src/components/form/form-end.tsx +23 -2
- package/src/components/form/index.tsx +152 -34
- package/src/components/form/password-field.tsx +12 -6
- package/src/components/form/text-area.tsx +13 -6
- package/src/components/form/text-field.tsx +13 -6
- package/src/components/form/types.tsx +6 -0
- package/src/components/form/with-left-border.tsx +41 -8
- package/src/components/icon.tsx +27 -8
- package/src/components/list.tsx +193 -74
- package/src/components/loading-bar.tsx +3 -2
- package/src/components/loading-text.tsx +79 -0
- package/src/descendants.tsx +1 -0
- package/src/examples/file-autocomplete.vitest.tsx +130 -125
- package/src/examples/form-basic.vitest.tsx +376 -176
- package/src/examples/form-dropdown.vitest.tsx +126 -126
- package/src/examples/form-scroll.tsx +2 -0
- package/src/examples/form-scroll.vitest.tsx +58 -58
- package/src/examples/form-tagpicker.vitest.tsx +99 -99
- package/src/examples/internal/descendants-filtering.tsx +1 -0
- package/src/examples/internal/descendants.tsx +1 -0
- package/src/examples/internal/rhf-custom-ref.tsx +2 -0
- package/src/examples/internal/scrollbox-demo.tsx +3 -27
- package/src/examples/internal/scrollbox-with-descendants.tsx +4 -7
- package/src/examples/internal/simple-scrollbox.vitest.tsx +7 -5
- package/src/examples/list-detail-metadata.tsx +49 -0
- package/src/examples/list-detail-metadata.vitest.tsx +88 -0
- package/src/examples/list-dropdown-default.vitest.tsx +51 -51
- package/src/examples/list-fetch-data.vitest.tsx +4 -4
- package/src/examples/list-scrollbox.vitest.tsx +73 -14
- package/src/examples/list-with-detail-long.tsx +70 -0
- package/src/examples/list-with-detail.vitest.tsx +198 -92
- package/src/examples/list-with-dropdown.vitest.tsx +53 -53
- package/src/examples/list-with-sections.tsx +1 -0
- package/src/examples/list-with-sections.vitest.tsx +213 -89
- package/src/examples/list-with-toast.vitest.tsx +4 -4
- package/src/examples/simple-file-picker.vitest.tsx +61 -471
- package/src/examples/simple-grid.vitest.tsx +238 -233
- package/src/examples/simple-navigation.tsx +15 -7
- package/src/examples/simple-navigation.vitest.tsx +121 -210
- package/src/examples/store.vitest.tsx +1 -1
- package/src/examples/swift-extension.vitest.tsx +148 -0
- package/src/examples/synonyms.vitest.tsx +159 -0
- package/src/extensions/dev.tsx +74 -7
- package/src/extensions/dev.vitest.tsx +97 -31
- package/src/extensions/home.tsx +6 -0
- package/src/index.tsx +3 -0
- package/src/internal/dialog.tsx +43 -30
- package/src/internal/navigation.tsx +3 -1
- package/src/internal/offscreen.tsx +15 -0
- package/src/internal/providers.tsx +4 -2
- package/src/internal/scrollbox.tsx +4 -8
- package/src/keyboard.test.tsx +69 -0
- package/src/state.tsx +7 -0
- package/src/swift-loader.tsx +239 -0
- package/src/swift-runtime.tsx +36 -0
- package/src/utils/file-system.ts +61 -0
- package/src/utils/run-command.tsx +75 -6
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import { test, expect, beforeEach, afterEach } from 'vitest'
|
|
2
|
+
import { launchTerminal, Session } from 'tuistory/src'
|
|
3
|
+
import { execSync } from 'node:child_process'
|
|
4
|
+
import fs from 'node:fs'
|
|
5
|
+
import path from 'node:path'
|
|
6
|
+
|
|
7
|
+
const fixtureDir = path.resolve(__dirname, '../../fixtures/swift-extension')
|
|
8
|
+
|
|
9
|
+
// Find binary - check debug first, then release
|
|
10
|
+
function findSwiftBinary(): string {
|
|
11
|
+
const debugPath = path.join(fixtureDir, 'swift/.build/debug/SwiftAPI')
|
|
12
|
+
const releasePath = path.join(fixtureDir, 'swift/.build/release/SwiftAPI')
|
|
13
|
+
if (fs.existsSync(debugPath)) {
|
|
14
|
+
return debugPath
|
|
15
|
+
}
|
|
16
|
+
if (fs.existsSync(releasePath)) {
|
|
17
|
+
return releasePath
|
|
18
|
+
}
|
|
19
|
+
throw new Error(`Swift binary not found at ${debugPath} or ${releasePath}`)
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const swiftBinary = findSwiftBinary()
|
|
23
|
+
|
|
24
|
+
test('swift binary returns items correctly', () => {
|
|
25
|
+
const stdout = execSync(`${swiftBinary} getItems`, { encoding: 'utf-8' })
|
|
26
|
+
expect(JSON.parse(stdout)).toMatchInlineSnapshot(`
|
|
27
|
+
[
|
|
28
|
+
{
|
|
29
|
+
"id": "1",
|
|
30
|
+
"subtitle": "Generated by Swift",
|
|
31
|
+
"title": "Swift Item One",
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
"id": "2",
|
|
35
|
+
"subtitle": "From native code",
|
|
36
|
+
"title": "Swift Item Two",
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
"id": "3",
|
|
40
|
+
"subtitle": "Fast and safe",
|
|
41
|
+
"title": "Swift Item Three",
|
|
42
|
+
},
|
|
43
|
+
]
|
|
44
|
+
`)
|
|
45
|
+
})
|
|
46
|
+
|
|
47
|
+
test('swift binary greet function works', () => {
|
|
48
|
+
const stdout = execSync(`${swiftBinary} greet '"World"'`, { encoding: 'utf-8' })
|
|
49
|
+
expect(JSON.parse(stdout)).toMatchInlineSnapshot(`"Hello, World! Greetings from Swift."`)
|
|
50
|
+
})
|
|
51
|
+
|
|
52
|
+
let session: Session
|
|
53
|
+
|
|
54
|
+
beforeEach(async () => {
|
|
55
|
+
session = await launchTerminal({
|
|
56
|
+
command: 'bun',
|
|
57
|
+
args: ['src/cli.tsx', 'dev', fixtureDir],
|
|
58
|
+
cwd: path.resolve(__dirname, '../..'),
|
|
59
|
+
cols: 70,
|
|
60
|
+
rows: 25,
|
|
61
|
+
})
|
|
62
|
+
})
|
|
63
|
+
|
|
64
|
+
afterEach(() => {
|
|
65
|
+
session?.close()
|
|
66
|
+
})
|
|
67
|
+
|
|
68
|
+
test('swift extension dev mode shows command list', async () => {
|
|
69
|
+
// Wait for command list to appear
|
|
70
|
+
const commandList = await session.text({
|
|
71
|
+
waitFor: (text) => /Swift List/i.test(text),
|
|
72
|
+
timeout: 30000,
|
|
73
|
+
})
|
|
74
|
+
|
|
75
|
+
expect(commandList).toMatchInlineSnapshot(`
|
|
76
|
+
"
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
Swift Test Extension βββββββββββββββββββββββββββββββββββββββββββ
|
|
80
|
+
|
|
81
|
+
Search commands...
|
|
82
|
+
|
|
83
|
+
Commands
|
|
84
|
+
βΊList Items Displays a simple list with some items view
|
|
85
|
+
Swift List Displays a list of items returned by a Swift f view
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
β΅ run command ββ navigate ^k actions"
|
|
100
|
+
`)
|
|
101
|
+
}, 60000)
|
|
102
|
+
|
|
103
|
+
test('swift extension runs Swift List command and shows items', async () => {
|
|
104
|
+
// Wait for command list to appear
|
|
105
|
+
await session.text({
|
|
106
|
+
waitFor: (text) => /Swift List/i.test(text),
|
|
107
|
+
timeout: 30000,
|
|
108
|
+
})
|
|
109
|
+
|
|
110
|
+
// Navigate down to Swift List (it's the second item)
|
|
111
|
+
await session.press('down')
|
|
112
|
+
|
|
113
|
+
// Select the Swift List command
|
|
114
|
+
await session.press('return')
|
|
115
|
+
|
|
116
|
+
// Wait for Swift items to load and display
|
|
117
|
+
const swiftListOutput = await session.text({
|
|
118
|
+
waitFor: (text) => text.includes('Swift Item One'),
|
|
119
|
+
timeout: 30000,
|
|
120
|
+
})
|
|
121
|
+
|
|
122
|
+
expect(swiftListOutput).toMatchInlineSnapshot(`
|
|
123
|
+
"
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
Swift Items ββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
127
|
+
|
|
128
|
+
Search...
|
|
129
|
+
|
|
130
|
+
Items from Swift
|
|
131
|
+
βΊSwift Item One Generated by Swift
|
|
132
|
+
Swift Item Two From native code
|
|
133
|
+
Swift Item Three Fast and safe
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
ββ navigate ^k actions"
|
|
147
|
+
`)
|
|
148
|
+
}, 60000)
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import { test, expect, beforeEach, afterEach, beforeAll } from 'vitest'
|
|
2
|
+
import { launchTerminal, Session } from 'tuistory/src'
|
|
3
|
+
import { execSync } from 'node:child_process'
|
|
4
|
+
import path from 'node:path'
|
|
5
|
+
|
|
6
|
+
const extensionDir = path.resolve(__dirname, '../../extensions/synonyms')
|
|
7
|
+
|
|
8
|
+
// Install dependencies before running tests
|
|
9
|
+
beforeAll(() => {
|
|
10
|
+
execSync('bun install', { cwd: extensionDir, stdio: 'inherit' })
|
|
11
|
+
}, 60000)
|
|
12
|
+
|
|
13
|
+
let session: Session
|
|
14
|
+
|
|
15
|
+
beforeEach(async () => {
|
|
16
|
+
session = await launchTerminal({
|
|
17
|
+
command: 'bun',
|
|
18
|
+
args: ['src/cli.tsx', 'dev', extensionDir],
|
|
19
|
+
cwd: path.resolve(__dirname, '../..'),
|
|
20
|
+
cols: 80,
|
|
21
|
+
rows: 30,
|
|
22
|
+
})
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
afterEach(() => {
|
|
26
|
+
session?.close()
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
test('synonyms extension shows preferences form on first launch', async () => {
|
|
30
|
+
// Wait for preferences form to appear (extension requires LLM provider setup)
|
|
31
|
+
await session.text({
|
|
32
|
+
waitFor: (text) => /LLM Provider/i.test(text),
|
|
33
|
+
timeout: 30000,
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
// Wait for auto-focus to settle
|
|
37
|
+
await session.waitIdle()
|
|
38
|
+
|
|
39
|
+
const preferencesForm = await session.text()
|
|
40
|
+
|
|
41
|
+
expect(preferencesForm).toMatchInlineSnapshot(`
|
|
42
|
+
"
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
β LLM Provider β
|
|
46
|
+
β Select...
|
|
47
|
+
β
|
|
48
|
+
β β Raycast AI
|
|
49
|
+
β β OpenAI
|
|
50
|
+
β β OpenAI Compatible
|
|
51
|
+
β β Anthropic
|
|
52
|
+
β β Fireworks.ai
|
|
53
|
+
β
|
|
54
|
+
β Select the LLM provider you want to use
|
|
55
|
+
β
|
|
56
|
+
β OpenAI API Key
|
|
57
|
+
β
|
|
58
|
+
β API Key for OpenAI
|
|
59
|
+
β
|
|
60
|
+
β OpenAI Model
|
|
61
|
+
β gpt-4.1-mini
|
|
62
|
+
β
|
|
63
|
+
β Model name for OpenAI
|
|
64
|
+
β
|
|
65
|
+
β OpenAI Compatible URL
|
|
66
|
+
β
|
|
67
|
+
β
|
|
68
|
+
β Base URL for OpenAI compatible provider
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
ctrl β΅ submit tab navigate ^k actions"
|
|
72
|
+
`)
|
|
73
|
+
}, 60000)
|
|
74
|
+
|
|
75
|
+
test('synonyms extension preferences form can be navigated', async () => {
|
|
76
|
+
// Wait for preferences form to appear
|
|
77
|
+
await session.text({
|
|
78
|
+
waitFor: (text) => /LLM Provider/i.test(text),
|
|
79
|
+
timeout: 30000,
|
|
80
|
+
})
|
|
81
|
+
|
|
82
|
+
// Wait for auto-focus to settle
|
|
83
|
+
await session.waitIdle()
|
|
84
|
+
|
|
85
|
+
// Navigate down in the dropdown
|
|
86
|
+
await session.press('down')
|
|
87
|
+
await session.press('down')
|
|
88
|
+
|
|
89
|
+
const afterNavigate = await session.text()
|
|
90
|
+
expect(afterNavigate).toMatchInlineSnapshot(`
|
|
91
|
+
"
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
β LLM Provider β
|
|
95
|
+
β Select...
|
|
96
|
+
β
|
|
97
|
+
β β Raycast AI
|
|
98
|
+
β β OpenAI
|
|
99
|
+
β β OpenAI Compatible
|
|
100
|
+
β β Anthropic
|
|
101
|
+
β β Fireworks.ai
|
|
102
|
+
β
|
|
103
|
+
β Select the LLM provider you want to use
|
|
104
|
+
β
|
|
105
|
+
β OpenAI API Key
|
|
106
|
+
β
|
|
107
|
+
β API Key for OpenAI
|
|
108
|
+
β
|
|
109
|
+
β OpenAI Model
|
|
110
|
+
β gpt-4.1-mini
|
|
111
|
+
β
|
|
112
|
+
β Model name for OpenAI
|
|
113
|
+
β
|
|
114
|
+
β OpenAI Compatible URL
|
|
115
|
+
β
|
|
116
|
+
β
|
|
117
|
+
β Base URL for OpenAI compatible provider
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
ctrl β΅ submit tab navigate ^k actions"
|
|
121
|
+
`)
|
|
122
|
+
|
|
123
|
+
// Press tab to move to next field
|
|
124
|
+
await session.press('tab')
|
|
125
|
+
|
|
126
|
+
const afterTab = await session.text()
|
|
127
|
+
expect(afterTab).toMatchInlineSnapshot(`
|
|
128
|
+
"
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
β LLM Provider β
|
|
132
|
+
β Select...
|
|
133
|
+
β
|
|
134
|
+
ββΊ β Raycast AI
|
|
135
|
+
β β OpenAI
|
|
136
|
+
β β OpenAI Compatible
|
|
137
|
+
β β Anthropic
|
|
138
|
+
β β Fireworks.ai
|
|
139
|
+
β
|
|
140
|
+
β Select the LLM provider you want to use
|
|
141
|
+
β
|
|
142
|
+
β OpenAI API Key
|
|
143
|
+
β
|
|
144
|
+
β API Key for OpenAI
|
|
145
|
+
β
|
|
146
|
+
β OpenAI Model
|
|
147
|
+
β gpt-4.1-mini
|
|
148
|
+
β
|
|
149
|
+
β Model name for OpenAI
|
|
150
|
+
β
|
|
151
|
+
β OpenAI Compatible URL
|
|
152
|
+
β
|
|
153
|
+
β
|
|
154
|
+
β Base URL for OpenAI compatible provider
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
ctrl β΅ submit tab navigate ^k actions"
|
|
158
|
+
`)
|
|
159
|
+
}, 60000)
|
package/src/extensions/dev.tsx
CHANGED
|
@@ -11,7 +11,12 @@ import { showToast, Toast } from 'termcast/src/apis/toast'
|
|
|
11
11
|
import { Icon } from 'termcast'
|
|
12
12
|
import { getCommandsWithFiles, CommandWithFile } from '../package-json'
|
|
13
13
|
import { buildExtensionCommands } from '../build'
|
|
14
|
-
import {
|
|
14
|
+
import {
|
|
15
|
+
runCommand,
|
|
16
|
+
clearCommandArguments,
|
|
17
|
+
parseExtensionArgs,
|
|
18
|
+
handleHelpFlag,
|
|
19
|
+
} from '../utils/run-command'
|
|
15
20
|
|
|
16
21
|
interface BundledCommand extends CommandWithFile {
|
|
17
22
|
bundledPath: string
|
|
@@ -21,15 +26,18 @@ interface BundledCommand extends CommandWithFile {
|
|
|
21
26
|
function ExtensionCommandsList({
|
|
22
27
|
extensionPath,
|
|
23
28
|
commands,
|
|
29
|
+
skipArgv,
|
|
24
30
|
}: {
|
|
25
31
|
extensionPath: string
|
|
26
32
|
commands: BundledCommand[]
|
|
33
|
+
skipArgv?: number
|
|
27
34
|
}): any {
|
|
28
35
|
const { push } = useNavigation()
|
|
29
36
|
const { packageJson } = getCommandsWithFiles({
|
|
30
37
|
packageJsonPath: path.join(extensionPath, 'package.json'),
|
|
31
38
|
})
|
|
32
|
-
|
|
39
|
+
|
|
40
|
+
const visibleCommands = commands.filter((cmd) => cmd.mode !== 'menu-bar')
|
|
33
41
|
|
|
34
42
|
const handleCommandSelect = async (command: BundledCommand) => {
|
|
35
43
|
clearCommandArguments()
|
|
@@ -51,7 +59,6 @@ function ExtensionCommandsList({
|
|
|
51
59
|
bundledPath: command.bundledPath,
|
|
52
60
|
Component: command.Component,
|
|
53
61
|
push,
|
|
54
|
-
cacheBustParam: String(devRebuildCount),
|
|
55
62
|
})
|
|
56
63
|
} catch (error: any) {
|
|
57
64
|
await showToast({
|
|
@@ -62,13 +69,43 @@ function ExtensionCommandsList({
|
|
|
62
69
|
}
|
|
63
70
|
}
|
|
64
71
|
|
|
72
|
+
// Auto-run command from CLI arg or single command
|
|
73
|
+
React.useLayoutEffect(() => {
|
|
74
|
+
// Only parse argv on initial load (when skipArgv is provided), not on rebuilds
|
|
75
|
+
if (skipArgv != null) {
|
|
76
|
+
const { commandName } = parseExtensionArgs({ skipArgv })
|
|
77
|
+
|
|
78
|
+
if (commandName) {
|
|
79
|
+
const command = visibleCommands.find((cmd) => cmd.name === commandName)
|
|
80
|
+
if (command) {
|
|
81
|
+
handleCommandSelect(command)
|
|
82
|
+
} else {
|
|
83
|
+
showToast({
|
|
84
|
+
style: Toast.Style.Failure,
|
|
85
|
+
title: 'Command not found',
|
|
86
|
+
message: `No command named "${commandName}"`,
|
|
87
|
+
})
|
|
88
|
+
}
|
|
89
|
+
return
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
if (visibleCommands.length === 1) {
|
|
94
|
+
handleCommandSelect(visibleCommands[0])
|
|
95
|
+
}
|
|
96
|
+
}, [])
|
|
97
|
+
|
|
98
|
+
if (visibleCommands.length === 1) {
|
|
99
|
+
return null
|
|
100
|
+
}
|
|
101
|
+
|
|
65
102
|
return (
|
|
66
103
|
<List
|
|
67
104
|
navigationTitle={packageJson.title || 'Extension Commands'}
|
|
68
105
|
searchBarPlaceholder='Search commands...'
|
|
69
106
|
>
|
|
70
107
|
<List.Section title='Commands'>
|
|
71
|
-
{
|
|
108
|
+
{visibleCommands.map((command) => (
|
|
72
109
|
<List.Item
|
|
73
110
|
key={command.name}
|
|
74
111
|
id={command.name}
|
|
@@ -111,7 +148,7 @@ function ExtensionCommandsList({
|
|
|
111
148
|
))}
|
|
112
149
|
</List.Section>
|
|
113
150
|
|
|
114
|
-
{
|
|
151
|
+
{visibleCommands.length === 0 && (
|
|
115
152
|
<List.Section title='No Commands'>
|
|
116
153
|
<List.Item
|
|
117
154
|
title='No commands found'
|
|
@@ -125,8 +162,10 @@ function ExtensionCommandsList({
|
|
|
125
162
|
|
|
126
163
|
export async function startDevMode({
|
|
127
164
|
extensionPath,
|
|
165
|
+
skipArgv = 0,
|
|
128
166
|
}: {
|
|
129
167
|
extensionPath: string
|
|
168
|
+
skipArgv?: number
|
|
130
169
|
}): Promise<void> {
|
|
131
170
|
const resolvedPath = path.resolve(extensionPath)
|
|
132
171
|
|
|
@@ -149,13 +188,24 @@ export async function startDevMode({
|
|
|
149
188
|
target: 'bun',
|
|
150
189
|
})
|
|
151
190
|
|
|
191
|
+
// Handle --help before rendering
|
|
192
|
+
handleHelpFlag({
|
|
193
|
+
extensionName: packageJson.title || packageJson.name,
|
|
194
|
+
commands: commands.map((cmd) => ({
|
|
195
|
+
name: cmd.name,
|
|
196
|
+
title: cmd.title,
|
|
197
|
+
description: cmd.description,
|
|
198
|
+
})),
|
|
199
|
+
skipArgv,
|
|
200
|
+
})
|
|
201
|
+
|
|
152
202
|
// Reset state and set extension information
|
|
153
203
|
useStore.setState({
|
|
154
204
|
...useStore.getInitialState(),
|
|
155
205
|
extensionPath: resolvedPath,
|
|
156
206
|
extensionPackageJson: packageJson,
|
|
157
207
|
devElement: (
|
|
158
|
-
<ExtensionCommandsList extensionPath={resolvedPath} commands={commands} />
|
|
208
|
+
<ExtensionCommandsList extensionPath={resolvedPath} commands={commands} skipArgv={skipArgv} />
|
|
159
209
|
),
|
|
160
210
|
devRebuildCount: 1,
|
|
161
211
|
})
|
|
@@ -174,6 +224,7 @@ export async function startDevMode({
|
|
|
174
224
|
export async function startCompiledExtension({
|
|
175
225
|
extensionPath,
|
|
176
226
|
compiledCommands,
|
|
227
|
+
skipArgv = 0,
|
|
177
228
|
}: {
|
|
178
229
|
extensionPath: string
|
|
179
230
|
compiledCommands: Array<{
|
|
@@ -181,6 +232,7 @@ export async function startCompiledExtension({
|
|
|
181
232
|
bundledPath: string
|
|
182
233
|
Component: (props: any) => any
|
|
183
234
|
}>
|
|
235
|
+
skipArgv?: number
|
|
184
236
|
}): Promise<void> {
|
|
185
237
|
const packageJsonPath = path.join(extensionPath, 'package.json')
|
|
186
238
|
const { packageJson, commands: commandsMetadata } = getCommandsWithFiles({
|
|
@@ -196,13 +248,25 @@ export async function startCompiledExtension({
|
|
|
196
248
|
}
|
|
197
249
|
})
|
|
198
250
|
|
|
251
|
+
// Handle --help before rendering
|
|
252
|
+
handleHelpFlag({
|
|
253
|
+
extensionName: packageJson.title || packageJson.name,
|
|
254
|
+
commands: commands.map((cmd) => ({
|
|
255
|
+
name: cmd.name,
|
|
256
|
+
title: cmd.title,
|
|
257
|
+
description: cmd.description,
|
|
258
|
+
})),
|
|
259
|
+
skipArgv,
|
|
260
|
+
})
|
|
261
|
+
|
|
199
262
|
useStore.setState({
|
|
200
263
|
...useStore.getInitialState(),
|
|
201
264
|
extensionPath,
|
|
202
265
|
extensionPackageJson: packageJson,
|
|
203
266
|
devElement: (
|
|
204
|
-
<ExtensionCommandsList extensionPath={extensionPath} commands={commands} />
|
|
267
|
+
<ExtensionCommandsList extensionPath={extensionPath} commands={commands} skipArgv={skipArgv} />
|
|
205
268
|
),
|
|
269
|
+
devRebuildCount: 1,
|
|
206
270
|
})
|
|
207
271
|
|
|
208
272
|
function App(): any {
|
|
@@ -242,6 +306,9 @@ export async function triggerRebuild({
|
|
|
242
306
|
/>
|
|
243
307
|
),
|
|
244
308
|
devRebuildCount: state.devRebuildCount + 1,
|
|
309
|
+
navigationStack: [], // Reset navigation so NavigationProvider re-initializes with new devElement
|
|
310
|
+
dialogStack: [], // Clear any open dialogs/toasts on rebuild
|
|
311
|
+
toast: null,
|
|
245
312
|
})
|
|
246
313
|
} catch (error: any) {
|
|
247
314
|
await showToast({
|
|
@@ -38,11 +38,10 @@ test('dev command shows extension commands list', async () => {
|
|
|
38
38
|
βΊList Items Displays a simple list with some ite view β
|
|
39
39
|
Search Items Search and filter through a list o view
|
|
40
40
|
Google Oauth view
|
|
41
|
-
usePromise Demo Shows how to use the usePromise view
|
|
42
|
-
βΌ
|
|
41
|
+
usePromise Demo Shows how to use the usePromise view βΌ
|
|
43
42
|
|
|
44
43
|
|
|
45
|
-
β΅
|
|
44
|
+
β΅ run command ββ navigate ^k actions"
|
|
46
45
|
`)
|
|
47
46
|
}, 30000)
|
|
48
47
|
|
|
@@ -68,15 +67,14 @@ test('selecting command with arguments shows arguments form', async () => {
|
|
|
68
67
|
|
|
69
68
|
Search commands...
|
|
70
69
|
|
|
71
|
-
|
|
72
|
-
Google Oauth view
|
|
73
|
-
usePromise Demo Shows how to use the usePromise view β
|
|
70
|
+
usePromise Demo Shows how to use the usePromise view β²
|
|
74
71
|
Show State Shows the current application state view
|
|
75
72
|
βΊWith Arguments Demonstrates command arguments ( view
|
|
73
|
+
Quick Action Copies current timestamp to cli no-view β
|
|
76
74
|
βΌ
|
|
77
75
|
|
|
78
76
|
|
|
79
|
-
β΅
|
|
77
|
+
β΅ run command ββ navigate ^k actions"
|
|
80
78
|
`)
|
|
81
79
|
|
|
82
80
|
// Select the command to show arguments form (enter opens action panel, enter again runs)
|
|
@@ -93,19 +91,19 @@ test('selecting command with arguments shows arguments form', async () => {
|
|
|
93
91
|
"
|
|
94
92
|
|
|
95
93
|
|
|
96
|
-
|
|
97
|
-
β Enter the arguments to run this command.
|
|
94
|
+
β With Arguments β
|
|
95
|
+
β Enter the arguments to run this command.
|
|
96
|
+
β
|
|
97
|
+
β Search query
|
|
98
|
+
β Search query
|
|
98
99
|
β
|
|
99
|
-
β Search query
|
|
100
|
-
β Search query
|
|
101
|
-
β
|
|
102
100
|
β Secret key
|
|
103
101
|
β Secret key
|
|
104
102
|
β Category
|
|
105
103
|
β Category
|
|
106
104
|
|
|
107
105
|
|
|
108
|
-
|
|
106
|
+
ctrl β΅ submit tab navigate ^k actions"
|
|
109
107
|
`)
|
|
110
108
|
}, 30000)
|
|
111
109
|
|
|
@@ -137,19 +135,19 @@ test('can fill arguments and run command', async () => {
|
|
|
137
135
|
"
|
|
138
136
|
|
|
139
137
|
|
|
140
|
-
|
|
141
|
-
β Enter the arguments to run this command.
|
|
138
|
+
β With Arguments β
|
|
139
|
+
β Enter the arguments to run this command.
|
|
140
|
+
β
|
|
141
|
+
β Search query
|
|
142
|
+
β Search query
|
|
142
143
|
β
|
|
143
|
-
β Search query
|
|
144
|
-
β my search term
|
|
145
|
-
β
|
|
146
144
|
β Secret key
|
|
147
145
|
β Secret key
|
|
148
146
|
β Category
|
|
149
147
|
β Category
|
|
150
148
|
|
|
151
149
|
|
|
152
|
-
|
|
150
|
+
ctrl β΅ submit tab navigate ^k actions"
|
|
153
151
|
`)
|
|
154
152
|
|
|
155
153
|
// Submit the form with Alt+Enter (opens action panel), then Enter (selects submit)
|
|
@@ -171,15 +169,15 @@ test('can fill arguments and run command', async () => {
|
|
|
171
169
|
Search...
|
|
172
170
|
|
|
173
171
|
Received Arguments
|
|
174
|
-
|
|
175
|
-
Secret Key (empty)
|
|
176
|
-
Category (empty)
|
|
172
|
+
βΊβΌ Search Query (empty)
|
|
173
|
+
βΌ Secret Key (empty)
|
|
174
|
+
βΌ Category (empty)
|
|
177
175
|
|
|
178
176
|
|
|
179
177
|
|
|
180
|
-
β΅
|
|
181
|
-
|
|
182
|
-
|
|
178
|
+
β΅ copy valβββββββββββββββββββββββββββββββββββ
|
|
179
|
+
β β Copied to Clipboard - (empty) β
|
|
180
|
+
βββββββββββββββββββββββββββββββββββ"
|
|
183
181
|
`)
|
|
184
182
|
}, 30000)
|
|
185
183
|
|
|
@@ -208,13 +206,81 @@ test('can run simple view command without arguments', async () => {
|
|
|
208
206
|
Search...
|
|
209
207
|
|
|
210
208
|
Items β²
|
|
211
|
-
|
|
212
|
-
Second Item This is the second item
|
|
213
|
-
Third Item This is the third item
|
|
214
|
-
Fourth Item This is the fourth item
|
|
215
|
-
βΌ
|
|
209
|
+
βΊβ² First Item This is the first item β
|
|
210
|
+
β² Second Item This is the second item
|
|
211
|
+
β² Third Item This is the third item
|
|
212
|
+
β² Fourth Item This is the fourth item βΌ
|
|
216
213
|
|
|
217
214
|
|
|
218
|
-
β΅
|
|
215
|
+
β΅ copy item title ββ navigate ^k actions"
|
|
219
216
|
`)
|
|
220
217
|
}, 30000)
|
|
218
|
+
|
|
219
|
+
test('hot reload updates TUI when source file changes', async () => {
|
|
220
|
+
const hotReloadFixtureDir = path.resolve(__dirname, '../../fixtures/hot-reload-extension')
|
|
221
|
+
const sourceFilePath = path.join(hotReloadFixtureDir, 'src/detail-view.tsx')
|
|
222
|
+
const fs = await import('node:fs')
|
|
223
|
+
|
|
224
|
+
// Read original content to restore later
|
|
225
|
+
const originalContent = fs.readFileSync(sourceFilePath, 'utf-8')
|
|
226
|
+
|
|
227
|
+
// Start a new session for this test
|
|
228
|
+
const hotReloadSession = await launchTerminal({
|
|
229
|
+
command: 'bun',
|
|
230
|
+
args: ['src/cli.tsx', 'dev', hotReloadFixtureDir],
|
|
231
|
+
cols: 60,
|
|
232
|
+
rows: 16,
|
|
233
|
+
})
|
|
234
|
+
|
|
235
|
+
try {
|
|
236
|
+
// Wait for the extension to load
|
|
237
|
+
await hotReloadSession.text({
|
|
238
|
+
waitFor: (text) => /Hot Reload Test/i.test(text) && /Detail View/i.test(text),
|
|
239
|
+
timeout: 5000,
|
|
240
|
+
})
|
|
241
|
+
await hotReloadSession.waitIdle()
|
|
242
|
+
|
|
243
|
+
// Run the Detail View command
|
|
244
|
+
await hotReloadSession.press('enter')
|
|
245
|
+
await hotReloadSession.press('enter')
|
|
246
|
+
await hotReloadSession.waitIdle()
|
|
247
|
+
|
|
248
|
+
// Wait for the detail view to show
|
|
249
|
+
await hotReloadSession.text({
|
|
250
|
+
waitFor: (text) => /MARKER_VALUE/i.test(text),
|
|
251
|
+
timeout: 10000,
|
|
252
|
+
})
|
|
253
|
+
|
|
254
|
+
// Generate a random number
|
|
255
|
+
const randomNumber = Math.floor(Math.random() * 1000000)
|
|
256
|
+
|
|
257
|
+
// Update the source file with the random number
|
|
258
|
+
const newContent = originalContent.replace('MARKER_VALUE', `UPDATED_${randomNumber}`)
|
|
259
|
+
fs.writeFileSync(sourceFilePath, newContent)
|
|
260
|
+
|
|
261
|
+
// Wait for rebuild - navigation resets to commands list
|
|
262
|
+
await hotReloadSession.text({
|
|
263
|
+
waitFor: (text) => /Hot Reload Test/i.test(text) && /Detail View/i.test(text),
|
|
264
|
+
timeout: 5000,
|
|
265
|
+
})
|
|
266
|
+
await hotReloadSession.waitIdle()
|
|
267
|
+
|
|
268
|
+
// Run the command again to see updated content
|
|
269
|
+
await hotReloadSession.press('enter')
|
|
270
|
+
await hotReloadSession.press('enter')
|
|
271
|
+
await hotReloadSession.waitIdle()
|
|
272
|
+
|
|
273
|
+
// Wait for the updated content
|
|
274
|
+
await hotReloadSession.text({
|
|
275
|
+
waitFor: (text) => text.includes(`UPDATED_${randomNumber}`),
|
|
276
|
+
timeout: 10000,
|
|
277
|
+
})
|
|
278
|
+
|
|
279
|
+
const updatedSnapshot = await hotReloadSession.text()
|
|
280
|
+
expect(updatedSnapshot).toContain(`UPDATED_${randomNumber}`)
|
|
281
|
+
} finally {
|
|
282
|
+
// Restore original content
|
|
283
|
+
fs.writeFileSync(sourceFilePath, originalContent)
|
|
284
|
+
hotReloadSession?.close()
|
|
285
|
+
}
|
|
286
|
+
}, 60000)
|