@shopify/cli-kit 3.47.4 → 3.48.0

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.
Files changed (138) hide show
  1. package/assets/cli-ruby/lib/project_types/extension/messages/messages.rb +18 -1
  2. package/assets/cli-ruby/lib/shopify_cli/constants.rb +1 -0
  3. package/assets/cli-ruby/lib/shopify_cli/environment.rb +7 -0
  4. package/assets/cli-ruby/lib/shopify_cli/theme/extension/dev_server.rb +8 -2
  5. package/dist/private/node/ui/alert.js +3 -1
  6. package/dist/private/node/ui/alert.js.map +1 -1
  7. package/dist/private/node/ui/components/Alert.d.ts +1 -1
  8. package/dist/private/node/ui/components/Alert.js.map +1 -1
  9. package/dist/private/node/ui/components/AutocompletePrompt.d.ts +7 -2
  10. package/dist/private/node/ui/components/AutocompletePrompt.js +28 -91
  11. package/dist/private/node/ui/components/AutocompletePrompt.js.map +1 -1
  12. package/dist/private/node/ui/components/AutocompletePrompt.test.js +317 -257
  13. package/dist/private/node/ui/components/AutocompletePrompt.test.js.map +1 -1
  14. package/dist/private/node/ui/components/ConcurrentOutput.d.ts +1 -0
  15. package/dist/private/node/ui/components/ConcurrentOutput.js +59 -32
  16. package/dist/private/node/ui/components/ConcurrentOutput.js.map +1 -1
  17. package/dist/private/node/ui/components/ConcurrentOutput.test.js +62 -22
  18. package/dist/private/node/ui/components/ConcurrentOutput.test.js.map +1 -1
  19. package/dist/private/node/ui/components/DangerousConfirmationPrompt.d.ts +12 -0
  20. package/dist/private/node/ui/components/DangerousConfirmationPrompt.js +77 -0
  21. package/dist/private/node/ui/components/DangerousConfirmationPrompt.js.map +1 -0
  22. package/dist/private/node/ui/components/DangerousConfirmationPrompt.test.js +101 -0
  23. package/dist/private/node/ui/components/DangerousConfirmationPrompt.test.js.map +1 -0
  24. package/dist/private/node/ui/components/List.d.ts +1 -0
  25. package/dist/private/node/ui/components/List.js +2 -2
  26. package/dist/private/node/ui/components/List.js.map +1 -1
  27. package/dist/private/node/ui/components/{GitDiff.d.ts → Prompts/GitDiff.d.ts} +4 -2
  28. package/dist/private/node/ui/components/{GitDiff.js → Prompts/GitDiff.js} +3 -2
  29. package/dist/private/node/ui/components/Prompts/GitDiff.js.map +1 -0
  30. package/dist/private/node/ui/components/Prompts/GitDiff.test.d.ts +1 -0
  31. package/dist/private/node/ui/components/{GitDiff.test.js → Prompts/GitDiff.test.js} +50 -28
  32. package/dist/private/node/ui/components/Prompts/GitDiff.test.js.map +1 -0
  33. package/dist/private/node/ui/components/Prompts/InfoMessage.d.ts +14 -0
  34. package/dist/private/node/ui/components/Prompts/InfoMessage.js +11 -0
  35. package/dist/private/node/ui/components/Prompts/InfoMessage.js.map +1 -0
  36. package/dist/private/node/ui/components/Prompts/InfoMessage.test.d.ts +1 -0
  37. package/dist/private/node/ui/components/Prompts/InfoMessage.test.js +21 -0
  38. package/dist/private/node/ui/components/Prompts/InfoMessage.test.js.map +1 -0
  39. package/dist/private/node/ui/components/Prompts/InfoTable.d.ts +1 -0
  40. package/dist/private/node/ui/components/Prompts/InfoTable.js +11 -7
  41. package/dist/private/node/ui/components/Prompts/InfoTable.js.map +1 -1
  42. package/dist/private/node/ui/components/Prompts/InfoTable.test.js +6 -4
  43. package/dist/private/node/ui/components/Prompts/InfoTable.test.js.map +1 -1
  44. package/dist/private/node/ui/components/Prompts/PromptLayout.d.ts +21 -0
  45. package/dist/private/node/ui/components/Prompts/PromptLayout.js +73 -0
  46. package/dist/private/node/ui/components/Prompts/PromptLayout.js.map +1 -0
  47. package/dist/private/node/ui/components/Prompts/PromptLayout.test.d.ts +1 -0
  48. package/dist/private/node/ui/components/Prompts/PromptLayout.test.js +129 -0
  49. package/dist/private/node/ui/components/Prompts/PromptLayout.test.js.map +1 -0
  50. package/dist/private/node/ui/components/Scrollbar.d.ts +10 -0
  51. package/dist/private/node/ui/components/Scrollbar.js +44 -0
  52. package/dist/private/node/ui/components/Scrollbar.js.map +1 -0
  53. package/dist/private/node/ui/components/Scrollbar.test.d.ts +1 -0
  54. package/dist/private/node/ui/components/Scrollbar.test.js +96 -0
  55. package/dist/private/node/ui/components/Scrollbar.test.js.map +1 -0
  56. package/dist/private/node/ui/components/SelectInput.d.ts +3 -6
  57. package/dist/private/node/ui/components/SelectInput.js +57 -41
  58. package/dist/private/node/ui/components/SelectInput.js.map +1 -1
  59. package/dist/private/node/ui/components/SelectInput.test.js +120 -192
  60. package/dist/private/node/ui/components/SelectInput.test.js.map +1 -1
  61. package/dist/private/node/ui/components/SelectPrompt.d.ts +7 -6
  62. package/dist/private/node/ui/components/SelectPrompt.js +11 -68
  63. package/dist/private/node/ui/components/SelectPrompt.js.map +1 -1
  64. package/dist/private/node/ui/components/SelectPrompt.test.js +135 -65
  65. package/dist/private/node/ui/components/SelectPrompt.test.js.map +1 -1
  66. package/dist/private/node/ui/components/Table/Row.js +2 -1
  67. package/dist/private/node/ui/components/Table/Row.js.map +1 -1
  68. package/dist/private/node/ui/components/Table/Table.js +2 -1
  69. package/dist/private/node/ui/components/Table/Table.js.map +1 -1
  70. package/dist/private/node/ui/components/Tasks.js +1 -8
  71. package/dist/private/node/ui/components/Tasks.js.map +1 -1
  72. package/dist/private/node/ui/components/TextInput.d.ts +1 -0
  73. package/dist/private/node/ui/components/TextInput.js +10 -4
  74. package/dist/private/node/ui/components/TextInput.js.map +1 -1
  75. package/dist/private/node/ui/components/TextInput.test.js +27 -18
  76. package/dist/private/node/ui/components/TextInput.test.js.map +1 -1
  77. package/dist/private/node/ui/components/TextPrompt.d.ts +2 -3
  78. package/dist/private/node/ui/components/TextPrompt.js +18 -16
  79. package/dist/private/node/ui/components/TextPrompt.js.map +1 -1
  80. package/dist/private/node/ui/components/TextPrompt.test.js +25 -11
  81. package/dist/private/node/ui/components/TextPrompt.test.js.map +1 -1
  82. package/dist/private/node/ui/hooks/use-prompt.d.ts +18 -0
  83. package/dist/private/node/ui/hooks/use-prompt.js +20 -0
  84. package/dist/private/node/ui/hooks/use-prompt.js.map +1 -0
  85. package/dist/private/node/ui/hooks/use-select-state.d.ts +4 -4
  86. package/dist/private/node/ui/hooks/use-select-state.js +9 -9
  87. package/dist/private/node/ui/hooks/use-select-state.js.map +1 -1
  88. package/dist/public/common/object.d.ts +16 -0
  89. package/dist/public/common/object.js +26 -0
  90. package/dist/public/common/object.js.map +1 -1
  91. package/dist/public/common/string.d.ts +16 -0
  92. package/dist/public/common/string.js +30 -0
  93. package/dist/public/common/string.js.map +1 -1
  94. package/dist/public/common/version.d.ts +1 -1
  95. package/dist/public/common/version.js +1 -1
  96. package/dist/public/common/version.js.map +1 -1
  97. package/dist/public/node/analytics.js +3 -1
  98. package/dist/public/node/analytics.js.map +1 -1
  99. package/dist/public/node/base-command.d.ts +1 -0
  100. package/dist/public/node/base-command.js +21 -1
  101. package/dist/public/node/base-command.js.map +1 -1
  102. package/dist/public/node/figures.d.ts +2 -0
  103. package/dist/public/node/figures.js +3 -0
  104. package/dist/public/node/figures.js.map +1 -0
  105. package/dist/public/node/metadata.d.ts +2 -1
  106. package/dist/public/node/metadata.js +5 -2
  107. package/dist/public/node/metadata.js.map +1 -1
  108. package/dist/public/node/monorail.d.ts +22 -1
  109. package/dist/public/node/monorail.js +1 -1
  110. package/dist/public/node/monorail.js.map +1 -1
  111. package/dist/public/node/output.d.ts +1 -1
  112. package/dist/public/node/output.js +1 -1
  113. package/dist/public/node/output.js.map +1 -1
  114. package/dist/public/node/ruby.d.ts +1 -0
  115. package/dist/public/node/ruby.js +1 -0
  116. package/dist/public/node/ruby.js.map +1 -1
  117. package/dist/public/node/system.js +2 -2
  118. package/dist/public/node/system.js.map +1 -1
  119. package/dist/public/node/themes/models/theme.d.ts +2 -1
  120. package/dist/public/node/themes/models/theme.js +2 -1
  121. package/dist/public/node/themes/models/theme.js.map +1 -1
  122. package/dist/public/node/themes/theme-urls.d.ts +1 -0
  123. package/dist/public/node/themes/theme-urls.js +4 -0
  124. package/dist/public/node/themes/theme-urls.js.map +1 -1
  125. package/dist/public/node/themes/themes-api.d.ts +9 -1
  126. package/dist/public/node/themes/themes-api.js +14 -3
  127. package/dist/public/node/themes/themes-api.js.map +1 -1
  128. package/dist/public/node/toml.d.ts +3 -2
  129. package/dist/public/node/toml.js +5 -2
  130. package/dist/public/node/toml.js.map +1 -1
  131. package/dist/public/node/ui.d.ts +82 -27
  132. package/dist/public/node/ui.js +97 -32
  133. package/dist/public/node/ui.js.map +1 -1
  134. package/dist/tsconfig.tsbuildinfo +1 -1
  135. package/package.json +14 -14
  136. package/dist/private/node/ui/components/GitDiff.js.map +0 -1
  137. package/dist/private/node/ui/components/GitDiff.test.js.map +0 -1
  138. /package/dist/private/node/ui/components/{GitDiff.test.d.ts → DangerousConfirmationPrompt.test.d.ts} +0 -0
@@ -1 +1 @@
1
- {"version":3,"file":"AutocompletePrompt.test.js","sourceRoot":"","sources":["../../../../../src/private/node/ui/components/AutocompletePrompt.test.tsx"],"names":[],"mappings":"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","sourcesContent":["import {AutocompletePrompt, SearchResults} from './AutocompletePrompt.js'\nimport {\n getLastFrameAfterUnmount,\n sendInputAndWait,\n sendInputAndWaitForChange,\n sendInputAndWaitForContent,\n waitForInputsToBeReady,\n render,\n} from '../../testing/ui.js'\nimport {Stdout} from '../../ui.js'\nimport {AbortController} from '../../../../public/node/abort.js'\nimport {beforeEach, describe, expect, test, vi} from 'vitest'\nimport React from 'react'\nimport {useStdout} from 'ink'\n\nvi.mock('ink', async () => {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const original: any = await vi.importActual('ink')\n return {\n ...original,\n useStdout: vi.fn(),\n }\n})\n\nconst ARROW_DOWN = '\\u001B[B'\nconst ENTER = '\\r'\nconst DELETE = '\\u007F'\n\nconst DATABASE = [\n {label: 'first', value: 'first'},\n {label: 'second', value: 'second'},\n {label: 'third', value: 'third'},\n {label: 'fourth', value: 'fourth'},\n {label: 'fifth', value: 'fifth'},\n {label: 'sixth', value: 'sixth'},\n {label: 'seventh', value: 'seventh'},\n {label: 'eighth', value: 'eighth'},\n {label: 'ninth', value: 'ninth'},\n {label: 'tenth', value: 'tenth'},\n {label: 'eleventh', value: 'eleventh'},\n {label: 'twelfth', value: 'twelfth'},\n {label: 'thirteenth', value: 'thirteenth'},\n {label: 'fourteenth', value: 'fourteenth'},\n {label: 'fifteenth', value: 'fifteenth'},\n {label: 'sixteenth', value: 'sixteenth'},\n {label: 'seventeenth', value: 'seventeenth'},\n {label: 'eighteenth', value: 'eighteenth'},\n {label: 'nineteenth', value: 'nineteenth'},\n {label: 'twentieth', value: 'twentieth'},\n {label: 'twenty-first', value: 'twenty-first'},\n {label: 'twenty-second', value: 'twenty-second'},\n {label: 'twenty-third', value: 'twenty-third'},\n {label: 'twenty-fourth', value: 'twenty-fourth'},\n {label: 'twenty-fifth', value: 'twenty-fifth'},\n {label: 'twenty-sixth', value: 'twenty-sixth'},\n {label: 'twenty-seventh', value: 'twenty-seventh'},\n {label: 'twenty-eighth', value: 'twenty-eighth'},\n {label: 'twenty-ninth', value: 'twenty-ninth'},\n {label: 'thirtieth', value: 'thirtieth'},\n {label: 'thirty-first', value: 'thirty-first'},\n {label: 'thirty-second', value: 'thirty-second'},\n {label: 'thirty-third', value: 'thirty-third'},\n {label: 'thirty-fourth', value: 'thirty-fourth'},\n {label: 'thirty-fifth', value: 'thirty-fifth'},\n {label: 'thirty-sixth', value: 'thirty-sixth'},\n {label: 'thirty-seventh', value: 'thirty-seventh'},\n {label: 'thirty-eighth', value: 'thirty-eighth'},\n {label: 'thirty-ninth', value: 'thirty-ninth'},\n {label: 'fortieth', value: 'fortieth'},\n {label: 'forty-first', value: 'forty-first'},\n {label: 'forty-second', value: 'forty-second'},\n {label: 'forty-third', value: 'forty-third'},\n {label: 'forty-fourth', value: 'forty-fourth'},\n {label: 'forty-fifth', value: 'forty-fifth'},\n {label: 'forty-sixth', value: 'forty-sixth'},\n {label: 'forty-seventh', value: 'forty-seventh'},\n {label: 'forty-eighth', value: 'forty-eighth'},\n {label: 'forty-ninth', value: 'forty-ninth'},\n {label: 'fiftieth', value: 'fiftieth'},\n]\n\nbeforeEach(() => {\n vi.mocked(useStdout).mockReturnValue({\n stdout: new Stdout({\n columns: 80,\n rows: 80,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n }) as any,\n write: () => {},\n })\n})\n\ndescribe('AutocompletePrompt', async () => {\n test('choose an answer', async () => {\n const onEnter = vi.fn()\n\n const items = [\n {label: 'first', value: 'first'},\n {label: 'second', value: 'second'},\n {label: 'third', value: 'third'},\n ]\n\n const infoTable = {Add: ['new-ext'], Remove: ['integrated-demand-ext', 'order-discount']}\n\n const renderInstance = render(\n <AutocompletePrompt\n message=\"Associate your project with the org Castile Ventures?\"\n choices={items}\n infoTable={infoTable}\n onSubmit={onEnter}\n search={() =>\n Promise.resolve({\n data: [],\n } as SearchResults<string>)\n }\n />,\n )\n\n await waitForInputsToBeReady()\n await sendInputAndWaitForChange(renderInstance, ARROW_DOWN)\n await sendInputAndWaitForChange(renderInstance, ENTER)\n\n expect(getLastFrameAfterUnmount(renderInstance)).toMatchInlineSnapshot(`\n \"? Associate your project with the org Castile Ventures?\n \u001b[36m✔\u001b[39m \u001b[36msecond\u001b[39m\n \"\n `)\n\n expect(onEnter).toHaveBeenCalledWith(items[1]!.value)\n })\n\n test('renders groups', async () => {\n const items = [\n {label: 'first', value: 'first', group: 'Automations', key: 'f'},\n {label: 'second', value: 'second', group: 'Automations', key: 's'},\n {label: 'third', value: 'third', group: 'Merchant Admin'},\n {label: 'fourth', value: 'fourth', group: 'Merchant Admin'},\n {label: 'fifth', value: 'fifth', key: 'a'},\n {label: 'sixth', value: 'sixth'},\n {label: 'seventh', value: 'seventh'},\n {label: 'eighth', value: 'eighth'},\n {label: 'ninth', value: 'ninth'},\n {label: 'tenth', value: 'tenth'},\n ]\n\n const renderInstance = render(\n <AutocompletePrompt\n message=\"Associate your project with the org Castile Ventures?\"\n choices={items}\n onSubmit={() => {}}\n search={() =>\n Promise.resolve({\n data: [],\n } as SearchResults<string>)\n }\n />,\n )\n\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot(`\n \"? Associate your project with the org Castile Ventures?\n\n \u001b[1mAutomations\u001b[22m\n \u001b[36m>\u001b[39m \u001b[36mfirst\u001b[39m\n second\n\n \u001b[1mMerchant Admin\u001b[22m\n third\n fourth\n\n \u001b[1mOther\u001b[22m\n fifth\n sixth\n seventh\n eighth\n ninth\n tenth\n\n \u001b[2mPress ↑↓ arrows to select, enter to confirm\u001b[22m\n \"\n `)\n })\n\n test('supports an info table', async () => {\n const items = [\n {label: 'first', value: 'first'},\n {label: 'second', value: 'second'},\n {label: 'third', value: 'third'},\n {label: 'fourth', value: 'fourth'},\n ]\n\n const infoTable = {\n Add: ['new-ext'],\n Remove: ['integrated-demand-ext', 'order-discount'],\n }\n\n const renderInstance = render(\n <AutocompletePrompt\n message=\"Associate your project with the org Castile Ventures?\"\n choices={items}\n infoTable={infoTable}\n onSubmit={() => {}}\n search={() => Promise.resolve({data: []} as SearchResults<string>)}\n />,\n )\n\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot(`\n \"? Associate your project with the org Castile Ventures?\n\n Add: • new-ext\n\n Remove: • integrated-demand-ext\n • order-discount\n\n \u001b[36m>\u001b[39m \u001b[36mfirst\u001b[39m\n second\n third\n fourth\n\n \u001b[2mPress ↑↓ arrows to select, enter to confirm\u001b[22m\n \"\n `)\n })\n\n test(\"doesn't submit if there are no choices\", async () => {\n const onEnter = vi.fn()\n const searchPromise = Promise.resolve({\n data: [],\n } as SearchResults<string>)\n const search = () => {\n return searchPromise\n }\n\n const renderInstance = render(\n <AutocompletePrompt\n message=\"Associate your project with the org Castile Ventures?\"\n choices={DATABASE}\n onSubmit={onEnter}\n search={search}\n />,\n )\n\n await waitForInputsToBeReady()\n await sendInputAndWaitForContent(renderInstance, 'No results found', 'a')\n // prompt doesn't change when enter is pressed\n await sendInputAndWait(renderInstance, 100, ENTER)\n\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot(`\n \"? Associate your project with the org Castile Ventures? \u001b[36ma\u001b[7m \u001b[27m\u001b[39m\n\n \u001b[2mNo results found.\u001b[22m\n \"\n `)\n\n expect(onEnter).not.toHaveBeenCalled()\n })\n\n test('has a loading state', async () => {\n const onEnter = vi.fn()\n\n const search = () => {\n return new Promise<SearchResults<string>>((resolve) => {\n setTimeout(() => {\n resolve({data: [{label: 'a', value: 'b'}]})\n }, 2000)\n })\n }\n\n const renderInstance = render(\n <AutocompletePrompt\n message=\"Associate your project with the org Castile Ventures?\"\n choices={DATABASE}\n onSubmit={onEnter}\n search={search}\n />,\n )\n\n await waitForInputsToBeReady()\n await sendInputAndWaitForContent(renderInstance, 'Loading...', 'a')\n // prompt doesn't change when enter is pressed\n await new Promise((resolve) => setTimeout(resolve, 100))\n await sendInputAndWait(renderInstance, 100, ENTER)\n\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot(`\n \"? Associate your project with the org Castile Ventures? \u001b[36ma\u001b[7m \u001b[27m\u001b[39m\n\n \u001b[2mLoading...\u001b[22m\n \"\n `)\n\n expect(onEnter).not.toHaveBeenCalled()\n })\n\n test('allows searching with pagination', async () => {\n const onEnter = vi.fn()\n\n const search = async (term: string) => {\n return {\n data: DATABASE.filter((item) => item.label.includes(term)),\n }\n }\n\n const renderInstance = render(\n <AutocompletePrompt\n message=\"Associate your project with the org Castile Ventures?\"\n choices={DATABASE}\n onSubmit={onEnter}\n search={search}\n />,\n )\n\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot(`\n \"? Associate your project with the org Castile Ventures? \u001b[36m\u001b[7mT\u001b[27m\u001b[2mype to search...\u001b[22m\u001b[39m\n\n \u001b[36m>\u001b[39m \u001b[36mfirst\u001b[39m\n second\n third\n fourth\n fifth\n sixth\n seventh\n eighth\n ninth\n tenth\n eleventh\n twelfth\n thirteenth\n fourteenth\n fifteenth\n sixteenth\n seventeenth\n eighteenth\n nineteenth\n twentieth\n twenty-first\n twenty-second\n twenty-third\n twenty-fourth\n twenty-fifth\n\n \u001b[2mPress ↑↓ arrows to select, enter to confirm\u001b[22m\n \"\n `)\n\n await waitForInputsToBeReady()\n await sendInputAndWaitForContent(renderInstance, 'th\u001b[1mi\u001b[22mrty-sixth', 'i')\n\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot(`\n \"? Associate your project with the org Castile Ventures? \u001b[36mi\u001b[7m \u001b[27m\u001b[39m\n\n \u001b[36m>\u001b[39m \u001b[36mf\u001b[1mi\u001b[22mrst\u001b[39m\n th\u001b[1mi\u001b[22mrd\n f\u001b[1mi\u001b[22mfth\n s\u001b[1mi\u001b[22mxth\n e\u001b[1mi\u001b[22mghth\n n\u001b[1mi\u001b[22mnth\n th\u001b[1mi\u001b[22mrteenth\n f\u001b[1mi\u001b[22mfteenth\n s\u001b[1mi\u001b[22mxteenth\n e\u001b[1mi\u001b[22mghteenth\n n\u001b[1mi\u001b[22mneteenth\n twent\u001b[1mi\u001b[22meth\n twenty-f\u001b[1mi\u001b[22mrst\n twenty-th\u001b[1mi\u001b[22mrd\n twenty-f\u001b[1mi\u001b[22mfth\n twenty-s\u001b[1mi\u001b[22mxth\n twenty-e\u001b[1mi\u001b[22mghth\n twenty-n\u001b[1mi\u001b[22mnth\n th\u001b[1mi\u001b[22mrtieth\n th\u001b[1mi\u001b[22mrty-first\n th\u001b[1mi\u001b[22mrty-second\n th\u001b[1mi\u001b[22mrty-third\n th\u001b[1mi\u001b[22mrty-fourth\n th\u001b[1mi\u001b[22mrty-fifth\n th\u001b[1mi\u001b[22mrty-sixth\n\n \u001b[2mPress ↑↓ arrows to select, enter to confirm\u001b[22m\n \"\n `)\n\n await sendInputAndWaitForChange(renderInstance, DELETE)\n\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot(`\n \"? Associate your project with the org Castile Ventures? \u001b[36m\u001b[7mT\u001b[27m\u001b[2mype to search...\u001b[22m\u001b[39m\n\n \u001b[36m>\u001b[39m \u001b[36mfirst\u001b[39m\n second\n third\n fourth\n fifth\n sixth\n seventh\n eighth\n ninth\n tenth\n eleventh\n twelfth\n thirteenth\n fourteenth\n fifteenth\n sixteenth\n seventeenth\n eighteenth\n nineteenth\n twentieth\n twenty-first\n twenty-second\n twenty-third\n twenty-fourth\n twenty-fifth\n\n \u001b[2mPress ↑↓ arrows to select, enter to confirm\u001b[22m\n \"\n `)\n\n await sendInputAndWaitForContent(renderInstance, 'th\u001b[1mi\u001b[22mrty-sixth', 'i')\n await sendInputAndWaitForChange(renderInstance, ARROW_DOWN)\n await sendInputAndWaitForChange(renderInstance, ARROW_DOWN)\n\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot(`\n \"? Associate your project with the org Castile Ventures? \u001b[36mi\u001b[7m \u001b[27m\u001b[39m\n\n f\u001b[1mi\u001b[22mrst\n th\u001b[1mi\u001b[22mrd\n \u001b[36m>\u001b[39m \u001b[36mf\u001b[1mi\u001b[22mfth\u001b[39m\n s\u001b[1mi\u001b[22mxth\n e\u001b[1mi\u001b[22mghth\n n\u001b[1mi\u001b[22mnth\n th\u001b[1mi\u001b[22mrteenth\n f\u001b[1mi\u001b[22mfteenth\n s\u001b[1mi\u001b[22mxteenth\n e\u001b[1mi\u001b[22mghteenth\n n\u001b[1mi\u001b[22mneteenth\n twent\u001b[1mi\u001b[22meth\n twenty-f\u001b[1mi\u001b[22mrst\n twenty-th\u001b[1mi\u001b[22mrd\n twenty-f\u001b[1mi\u001b[22mfth\n twenty-s\u001b[1mi\u001b[22mxth\n twenty-e\u001b[1mi\u001b[22mghth\n twenty-n\u001b[1mi\u001b[22mnth\n th\u001b[1mi\u001b[22mrtieth\n th\u001b[1mi\u001b[22mrty-first\n th\u001b[1mi\u001b[22mrty-second\n th\u001b[1mi\u001b[22mrty-third\n th\u001b[1mi\u001b[22mrty-fourth\n th\u001b[1mi\u001b[22mrty-fifth\n th\u001b[1mi\u001b[22mrty-sixth\n\n \u001b[2mPress ↑↓ arrows to select, enter to confirm\u001b[22m\n \"\n `)\n\n await sendInputAndWaitForChange(renderInstance, ENTER)\n\n expect(getLastFrameAfterUnmount(renderInstance)).toMatchInlineSnapshot(`\n \"? Associate your project with the org Castile Ventures?\n \u001b[36m✔\u001b[39m \u001b[36mfifth\u001b[39m\n \"\n `)\n\n expect(onEnter).toHaveBeenCalledWith('fifth')\n })\n\n test('allows selecting the first item after searching', async () => {\n const onEnter = vi.fn()\n\n const search = async (term: string) => {\n await new Promise((resolve) => setTimeout(resolve, 300))\n return {\n data: DATABASE.filter((item) => item.label.includes(term)),\n }\n }\n\n const renderInstance = render(\n <AutocompletePrompt\n message=\"Associate your project with the org Castile Ventures?\"\n choices={DATABASE}\n onSubmit={onEnter}\n search={search}\n />,\n )\n\n await waitForInputsToBeReady()\n await sendInputAndWaitForContent(renderInstance, '\u001b[1mfiftieth\u001b[22m', 'fiftieth')\n\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot(`\n \"? Associate your project with the org Castile Ventures? \u001b[36mfiftieth\u001b[7m \u001b[27m\u001b[39m\n\n \u001b[36m>\u001b[39m \u001b[36m\u001b[1mfiftieth\u001b[22m\u001b[39m\n\n \u001b[2mPress ↑↓ arrows to select, enter to confirm\u001b[22m\n \"\n `)\n\n await sendInputAndWaitForChange(renderInstance, ENTER)\n\n expect(getLastFrameAfterUnmount(renderInstance)).toMatchInlineSnapshot(`\n \"? Associate your project with the org Castile Ventures?\n \u001b[36m✔\u001b[39m \u001b[36mfiftieth\u001b[39m\n \"\n `)\n\n expect(onEnter).toHaveBeenCalledWith('fiftieth')\n })\n\n test('displays an error message if the search fails', async () => {\n const search = (_term: string) => {\n return Promise.reject(new Error('Something went wrong'))\n }\n\n const renderInstance = render(\n <AutocompletePrompt\n message=\"Associate your project with the org Castile Ventures?\"\n choices={DATABASE}\n onSubmit={() => {}}\n search={search}\n />,\n )\n\n await waitForInputsToBeReady()\n await sendInputAndWaitForContent(renderInstance, 'There has been an error', 'i')\n\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot(`\n \"? Associate your project with the org Castile Ventures? \u001b[36mi\u001b[7m \u001b[27m\u001b[39m\n\n \u001b[31mThere has been an error while searching. Please try again later.\u001b[39m\n \"\n `)\n })\n\n test('immediately shows the initial items if the search is empty', async () => {\n const search = (term: string) => {\n return Promise.resolve({\n data: DATABASE.filter((item) => item.label.includes(term)),\n })\n }\n\n const renderInstance = render(\n <AutocompletePrompt\n message=\"Associate your project with the org Castile Ventures?\"\n choices={DATABASE}\n onSubmit={() => {}}\n search={search}\n />,\n )\n\n await waitForInputsToBeReady()\n await sendInputAndWaitForContent(renderInstance, 'th\u001b[1mi\u001b[22mrty-sixth', 'i')\n\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot(`\n \"? Associate your project with the org Castile Ventures? \u001b[36mi\u001b[7m \u001b[27m\u001b[39m\n\n \u001b[36m>\u001b[39m \u001b[36mf\u001b[1mi\u001b[22mrst\u001b[39m\n th\u001b[1mi\u001b[22mrd\n f\u001b[1mi\u001b[22mfth\n s\u001b[1mi\u001b[22mxth\n e\u001b[1mi\u001b[22mghth\n n\u001b[1mi\u001b[22mnth\n th\u001b[1mi\u001b[22mrteenth\n f\u001b[1mi\u001b[22mfteenth\n s\u001b[1mi\u001b[22mxteenth\n e\u001b[1mi\u001b[22mghteenth\n n\u001b[1mi\u001b[22mneteenth\n twent\u001b[1mi\u001b[22meth\n twenty-f\u001b[1mi\u001b[22mrst\n twenty-th\u001b[1mi\u001b[22mrd\n twenty-f\u001b[1mi\u001b[22mfth\n twenty-s\u001b[1mi\u001b[22mxth\n twenty-e\u001b[1mi\u001b[22mghth\n twenty-n\u001b[1mi\u001b[22mnth\n th\u001b[1mi\u001b[22mrtieth\n th\u001b[1mi\u001b[22mrty-first\n th\u001b[1mi\u001b[22mrty-second\n th\u001b[1mi\u001b[22mrty-third\n th\u001b[1mi\u001b[22mrty-fourth\n th\u001b[1mi\u001b[22mrty-fifth\n th\u001b[1mi\u001b[22mrty-sixth\n\n \u001b[2mPress ↑↓ arrows to select, enter to confirm\u001b[22m\n \"\n `)\n\n await sendInputAndWaitForChange(renderInstance, DELETE)\n\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot(`\n \"? Associate your project with the org Castile Ventures? \u001b[36m\u001b[7mT\u001b[27m\u001b[2mype to search...\u001b[22m\u001b[39m\n\n \u001b[36m>\u001b[39m \u001b[36mfirst\u001b[39m\n second\n third\n fourth\n fifth\n sixth\n seventh\n eighth\n ninth\n tenth\n eleventh\n twelfth\n thirteenth\n fourteenth\n fifteenth\n sixteenth\n seventeenth\n eighteenth\n nineteenth\n twentieth\n twenty-first\n twenty-second\n twenty-third\n twenty-fourth\n twenty-fifth\n\n \u001b[2mPress ↑↓ arrows to select, enter to confirm\u001b[22m\n \"\n `)\n })\n\n test('shows a message that indicates there are more results than shown', async () => {\n const search = (_term: string) => {\n return Promise.resolve({\n data: DATABASE,\n meta: {hasNextPage: true},\n })\n }\n\n const renderInstance = render(\n <AutocompletePrompt\n message=\"Associate your project with the org Castile Ventures?\"\n choices={DATABASE}\n onSubmit={() => {}}\n hasMorePages\n search={search}\n />,\n )\n\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot(`\n \"? Associate your project with the org Castile Ventures? \u001b[36m\u001b[7mT\u001b[27m\u001b[2mype to search...\u001b[22m\u001b[39m\n\n \u001b[36m>\u001b[39m \u001b[36mfirst\u001b[39m\n second\n third\n fourth\n fifth\n sixth\n seventh\n eighth\n ninth\n tenth\n eleventh\n twelfth\n thirteenth\n fourteenth\n fifteenth\n sixteenth\n seventeenth\n eighteenth\n nineteenth\n twentieth\n twenty-first\n twenty-second\n twenty-third\n twenty-fourth\n twenty-fifth\n\n \u001b[1m1-25 of many\u001b[22m Find what you're looking for by typing its name.\n \u001b[2mPress ↑↓ arrows to select, enter to confirm\u001b[22m\n \"\n `)\n })\n\n test('adapts to the height of the container', async () => {\n vi.mocked(useStdout).mockReturnValue({\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n stdout: new Stdout({rows: 10}) as any,\n write: () => {},\n })\n\n const items = [\n {label: 'first', value: 'first', group: 'Automations', key: 'f'},\n {label: 'second', value: 'second', group: 'Automations', key: 's'},\n {label: 'third', value: 'third', group: 'Merchant Admin'},\n {label: 'fourth', value: 'fourth', group: 'Merchant Admin'},\n {label: 'fifth', value: 'fifth', key: 'a'},\n {label: 'sixth', value: 'sixth'},\n {label: 'seventh', value: 'seventh'},\n {label: 'eighth', value: 'eighth'},\n {label: 'ninth', value: 'ninth'},\n {label: 'tenth', value: 'tenth'},\n ]\n\n const renderInstance = render(\n <AutocompletePrompt\n message=\"Associate your project with the org Castile Ventures?\"\n choices={items}\n onSubmit={() => {}}\n hasMorePages\n search={() =>\n Promise.resolve({\n data: items,\n } as SearchResults<string>)\n }\n />,\n )\n\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot(`\n \"? Associate your project with the org Castile Ventures?\n\n \u001b[1mAutomations\u001b[22m\n \u001b[36m>\u001b[39m \u001b[36mfirst\u001b[39m\n second\n\n \u001b[1m1-10 of many\u001b[22m Find what you're looking for by typing its name.\n \u001b[2mShowing 2 of 10 items.\u001b[22m\n \u001b[2mPress ↑↓ arrows to select, enter to confirm\u001b[22m\n \"\n `)\n })\n\n test('abortController can be used to exit the prompt from outside', async () => {\n const items = [\n {label: 'a', value: 'a'},\n {label: 'b', value: 'b'},\n ]\n\n const abortController = new AbortController()\n\n const renderInstance = render(\n <AutocompletePrompt\n message=\"Associate your project with the org Castile Ventures?\"\n choices={items}\n onSubmit={() => {}}\n search={() =>\n Promise.resolve({\n data: [],\n } as SearchResults<string>)\n }\n abortSignal={abortController.signal}\n />,\n )\n const promise = renderInstance.waitUntilExit()\n\n abortController.abort()\n\n expect(getLastFrameAfterUnmount(renderInstance)).toEqual('')\n await expect(promise).resolves.toEqual(undefined)\n })\n})\n"]}
1
+ {"version":3,"file":"AutocompletePrompt.test.js","sourceRoot":"","sources":["../../../../../src/private/node/ui/components/AutocompletePrompt.test.tsx"],"names":[],"mappings":"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","sourcesContent":["import {AutocompletePrompt, SearchResults} from './AutocompletePrompt.js'\nimport {\n getLastFrameAfterUnmount,\n sendInputAndWait,\n sendInputAndWaitForChange,\n sendInputAndWaitForContent,\n waitForInputsToBeReady,\n render,\n} from '../../testing/ui.js'\nimport {Stdout} from '../../ui.js'\nimport {AbortController} from '../../../../public/node/abort.js'\nimport {beforeEach, describe, expect, test, vi} from 'vitest'\nimport React from 'react'\nimport {useStdout} from 'ink'\n\nvi.mock('ink', async () => {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const original: any = await vi.importActual('ink')\n return {\n ...original,\n useStdout: vi.fn(),\n }\n})\n\nconst ARROW_DOWN = '\\u001B[B'\nconst ENTER = '\\r'\nconst DELETE = '\\u007F'\n\nconst DATABASE = [\n {label: 'first', value: 'first'},\n {label: 'second', value: 'second'},\n {label: 'third', value: 'third'},\n {label: 'fourth', value: 'fourth'},\n {label: 'fifth', value: 'fifth'},\n {label: 'sixth', value: 'sixth'},\n {label: 'seventh', value: 'seventh'},\n {label: 'eighth', value: 'eighth'},\n {label: 'ninth', value: 'ninth'},\n {label: 'tenth', value: 'tenth'},\n {label: 'eleventh', value: 'eleventh'},\n {label: 'twelfth', value: 'twelfth'},\n {label: 'thirteenth', value: 'thirteenth'},\n {label: 'fourteenth', value: 'fourteenth'},\n {label: 'fifteenth', value: 'fifteenth'},\n {label: 'sixteenth', value: 'sixteenth'},\n {label: 'seventeenth', value: 'seventeenth'},\n {label: 'eighteenth', value: 'eighteenth'},\n {label: 'nineteenth', value: 'nineteenth'},\n {label: 'twentieth', value: 'twentieth'},\n {label: 'twenty-first', value: 'twenty-first'},\n {label: 'twenty-second', value: 'twenty-second'},\n {label: 'twenty-third', value: 'twenty-third'},\n {label: 'twenty-fourth', value: 'twenty-fourth'},\n {label: 'twenty-fifth', value: 'twenty-fifth'},\n {label: 'twenty-sixth', value: 'twenty-sixth'},\n {label: 'twenty-seventh', value: 'twenty-seventh'},\n {label: 'twenty-eighth', value: 'twenty-eighth'},\n {label: 'twenty-ninth', value: 'twenty-ninth'},\n {label: 'thirtieth', value: 'thirtieth'},\n {label: 'thirty-first', value: 'thirty-first'},\n {label: 'thirty-second', value: 'thirty-second'},\n {label: 'thirty-third', value: 'thirty-third'},\n {label: 'thirty-fourth', value: 'thirty-fourth'},\n {label: 'thirty-fifth', value: 'thirty-fifth'},\n {label: 'thirty-sixth', value: 'thirty-sixth'},\n {label: 'thirty-seventh', value: 'thirty-seventh'},\n {label: 'thirty-eighth', value: 'thirty-eighth'},\n {label: 'thirty-ninth', value: 'thirty-ninth'},\n {label: 'fortieth', value: 'fortieth'},\n {label: 'forty-first', value: 'forty-first'},\n {label: 'forty-second', value: 'forty-second'},\n {label: 'forty-third', value: 'forty-third'},\n {label: 'forty-fourth', value: 'forty-fourth'},\n {label: 'forty-fifth', value: 'forty-fifth'},\n {label: 'forty-sixth', value: 'forty-sixth'},\n {label: 'forty-seventh', value: 'forty-seventh'},\n {label: 'forty-eighth', value: 'forty-eighth'},\n {label: 'forty-ninth', value: 'forty-ninth'},\n {label: 'fiftieth', value: 'fiftieth'},\n]\n\nbeforeEach(() => {\n vi.mocked(useStdout).mockReturnValue({\n stdout: new Stdout({\n columns: 80,\n rows: 80,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n }) as any,\n write: () => {},\n })\n})\n\ndescribe('AutocompletePrompt', async () => {\n test('choose an answer', async () => {\n const onEnter = vi.fn()\n\n const items = [\n {label: 'first', value: 'first'},\n {label: 'second', value: 'second'},\n {label: 'third', value: 'third'},\n ]\n\n const infoTable = {Add: ['new-ext'], Remove: ['integrated-demand-ext', 'order-discount']}\n\n const renderInstance = render(\n <AutocompletePrompt\n message={['Associate your project with the org', {userInput: 'Castile Ventures'}, {char: '?'}]}\n choices={items}\n infoTable={infoTable}\n onSubmit={onEnter}\n search={() =>\n Promise.resolve({\n data: [],\n } as SearchResults<string>)\n }\n />,\n )\n\n await waitForInputsToBeReady()\n await sendInputAndWaitForChange(renderInstance, ARROW_DOWN)\n await sendInputAndWaitForChange(renderInstance, ENTER)\n\n expect(getLastFrameAfterUnmount(renderInstance)).toMatchInlineSnapshot(`\n \"? Associate your project with the org \u001b[36mCastile Ventures\u001b[39m?\n \u001b[36m✔\u001b[39m \u001b[36msecond\u001b[39m\n \"\n `)\n\n expect(onEnter).toHaveBeenCalledWith(items[1]!.value)\n })\n\n test('renders groups', async () => {\n const items = [\n {label: 'first', value: 'first', group: 'Automations'},\n {label: 'second', value: 'second', group: 'Automations'},\n {label: 'third', value: 'third', group: 'Merchant Admin'},\n {label: 'fourth', value: 'fourth', group: 'Merchant Admin'},\n {label: 'fifth', value: 'fifth'},\n {label: 'sixth', value: 'sixth'},\n {label: 'seventh', value: 'seventh'},\n {label: 'eighth', value: 'eighth'},\n {label: 'ninth', value: 'ninth'},\n {label: 'tenth', value: 'tenth'},\n ]\n\n const renderInstance = render(\n <AutocompletePrompt\n message=\"Associate your project with the org Castile Ventures?\"\n choices={items}\n onSubmit={() => {}}\n search={() =>\n Promise.resolve({\n data: [],\n } as SearchResults<string>)\n }\n />,\n )\n\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot(`\n \"? Associate your project with the org Castile Ventures? \u001b[36m\u001b[7mT\u001b[27m\u001b[2mype to search...\u001b[22m\u001b[39m\n\n \u001b[1mAutomations\u001b[22m\n \u001b[36m>\u001b[39m \u001b[36mfirst\u001b[39m\n second\n\n \u001b[1mMerchant Admin\u001b[22m\n third\n fourth\n\n \u001b[1mOther\u001b[22m\n fifth\n sixth\n seventh\n eighth\n ninth\n tenth\n\n \u001b[2mPress ↑↓ arrows to select, enter to confirm.\u001b[22m\n \"\n `)\n })\n\n test('supports an info table', async () => {\n const items = [\n {label: 'first', value: 'first'},\n {label: 'second', value: 'second'},\n {label: 'third', value: 'third'},\n {label: 'fourth', value: 'fourth'},\n ]\n\n const infoTable = {\n Add: ['new-ext'],\n Remove: ['integrated-demand-ext', 'order-discount'],\n }\n\n const renderInstance = render(\n <AutocompletePrompt\n message=\"Associate your project with the org Castile Ventures?\"\n choices={items}\n infoTable={infoTable}\n onSubmit={() => {}}\n search={() => Promise.resolve({data: []} as SearchResults<string>)}\n />,\n )\n\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot(`\n \"? Associate your project with the org Castile Ventures?\n\n ┃ \\u001b[1mAdd\\u001b[22m\n ┃ • new-ext\n ┃\n ┃ \\u001b[1mRemove\\u001b[22m\n ┃ • integrated-demand-ext\n ┃ • order-discount\n\n \u001b[36m>\u001b[39m \u001b[36mfirst\u001b[39m\n second\n third\n fourth\n\n \u001b[2mPress ↑↓ arrows to select, enter to confirm.\u001b[22m\n \"\n `)\n })\n\n test('supports a git diff', async () => {\n const items = [\n {label: 'first', value: 'first'},\n {label: 'second', value: 'second'},\n {label: 'third', value: 'third'},\n {label: 'fourth', value: 'fourth'},\n ]\n\n const gitDiff = {\n baselineContent: 'hello\\n',\n updatedContent: 'world\\n',\n }\n\n const renderInstance = render(\n <AutocompletePrompt\n message=\"Associate your project with the org Castile Ventures?\"\n choices={items}\n gitDiff={gitDiff}\n onSubmit={() => {}}\n search={() => Promise.resolve({data: []} as SearchResults<string>)}\n />,\n )\n\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot(`\n \"? Associate your project with the org Castile Ventures?\n\n ┃ \u001b[31m- hello\u001b[m\n ┃ \u001b[32m+ \u001b[m\u001b[32mworld\u001b[m\n\n \u001b[36m>\u001b[39m \u001b[36mfirst\u001b[39m\n second\n third\n fourth\n\n \u001b[2mPress ↑↓ arrows to select, enter to confirm.\u001b[22m\n \"\n `)\n })\n\n test('supports an info message', async () => {\n const items = [\n {label: 'first', value: 'first'},\n {label: 'second', value: 'second'},\n {label: 'third', value: 'third'},\n {label: 'fourth', value: 'fourth'},\n ]\n\n const infoMessage = {\n title: {\n color: 'red',\n text: 'Info message title',\n },\n body: 'Info message body',\n }\n\n const renderInstance = render(\n <AutocompletePrompt\n message=\"Associate your project with the org Castile Ventures?\"\n choices={items}\n infoMessage={infoMessage}\n onSubmit={() => {}}\n search={() => Promise.resolve({data: []} as SearchResults<string>)}\n />,\n )\n\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot(`\n \"? Associate your project with the org Castile Ventures?\n\n ┃ \u001b[31mInfo message title\u001b[39m\n ┃\n ┃ Info message body\n\n \u001b[36m>\u001b[39m \u001b[36mfirst\u001b[39m\n second\n third\n fourth\n\n \u001b[2mPress ↑↓ arrows to select, enter to confirm.\u001b[22m\n \"\n `)\n })\n\n test(\"doesn't submit if there are no choices\", async () => {\n const onEnter = vi.fn()\n const searchPromise = Promise.resolve({\n data: [],\n } as SearchResults<string>)\n const search = () => {\n return searchPromise\n }\n\n const renderInstance = render(\n <AutocompletePrompt\n message=\"Associate your project with the org Castile Ventures?\"\n choices={DATABASE}\n onSubmit={onEnter}\n search={search}\n />,\n )\n\n await waitForInputsToBeReady()\n await sendInputAndWaitForContent(renderInstance, 'No results found', 'a')\n // prompt doesn't change when enter is pressed\n await sendInputAndWait(renderInstance, 100, ENTER)\n\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot(`\n \"? Associate your project with the org Castile Ventures? \u001b[36ma\u001b[46m█\u001b[49m\u001b[39m\n\n \u001b[2mNo results found.\u001b[22m\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \u001b[2mTry again with a different keyword.\u001b[22m\n \"\n `)\n\n expect(onEnter).not.toHaveBeenCalled()\n })\n\n test('has a loading state', async () => {\n const onEnter = vi.fn()\n\n const search = () => {\n return new Promise<SearchResults<string>>((resolve) => {\n setTimeout(() => {\n resolve({data: [{label: 'a', value: 'b'}]})\n }, 2000)\n })\n }\n\n const renderInstance = render(\n <AutocompletePrompt\n message=\"Associate your project with the org Castile Ventures?\"\n choices={DATABASE}\n onSubmit={onEnter}\n search={search}\n />,\n )\n\n await waitForInputsToBeReady()\n await sendInputAndWaitForContent(renderInstance, 'Loading...', 'a')\n // prompt doesn't change when enter is pressed\n await new Promise((resolve) => setTimeout(resolve, 100))\n await sendInputAndWait(renderInstance, 100, ENTER)\n\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot(`\n \"? Associate your project with the org Castile Ventures? \u001b[36ma\u001b[46m█\u001b[49m\u001b[39m\n\n \u001b[2mLoading...\u001b[22m\n \"\n `)\n\n expect(onEnter).not.toHaveBeenCalled()\n })\n\n test('allows searching with pagination', async () => {\n const onEnter = vi.fn()\n\n const search = async (term: string) => {\n return {\n data: DATABASE.filter((item) => item.label.includes(term)),\n }\n }\n\n const renderInstance = render(\n <AutocompletePrompt\n message=\"Associate your project with the org Castile Ventures?\"\n choices={DATABASE}\n onSubmit={onEnter}\n search={search}\n />,\n )\n\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot(`\n \"? Associate your project with the org Castile Ventures? \u001b[36m\u001b[7mT\u001b[27m\u001b[2mype to search...\u001b[22m\u001b[39m\n\n \u001b[36m>\u001b[39m \u001b[36mfirst\u001b[39m \u001b[46m \u001b[49m\n second \u001b[46m \u001b[49m\n third \u001b[46m \u001b[49m\n fourth \u001b[46m \u001b[49m\n fifth \u001b[46m \u001b[49m\n sixth \u001b[46m \u001b[49m\n seventh \u001b[46m \u001b[49m\n eighth \u001b[46m \u001b[49m\n ninth \u001b[46m \u001b[49m\n tenth \u001b[46m \u001b[49m\n eleventh \u001b[46m \u001b[49m\n twelfth \u001b[46m \u001b[49m\n thirteenth \u001b[46m \u001b[49m\n fourteenth \u001b[100m \u001b[49m\n fifteenth \u001b[100m \u001b[49m\n sixteenth \u001b[100m \u001b[49m\n seventeenth \u001b[100m \u001b[49m\n eighteenth \u001b[100m \u001b[49m\n nineteenth \u001b[100m \u001b[49m\n twentieth \u001b[100m \u001b[49m\n twenty-first \u001b[100m \u001b[49m\n twenty-second \u001b[100m \u001b[49m\n twenty-third \u001b[100m \u001b[49m\n twenty-fourth \u001b[100m \u001b[49m\n twenty-fifth \u001b[100m \u001b[49m\n\n \u001b[2mPress ↑↓ arrows to select, enter to confirm.\u001b[22m\n \"\n `)\n\n await waitForInputsToBeReady()\n await sendInputAndWaitForContent(renderInstance, 'th\u001b[1mi\u001b[22mrty-sixth', 'i')\n\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot(`\n \"? Associate your project with the org Castile Ventures? \u001b[36mi\u001b[46m█\u001b[49m\u001b[39m\n\n \u001b[36m>\u001b[39m \u001b[36mf\u001b[1mi\u001b[22mrst\u001b[39m \u001b[46m \u001b[49m\n th\u001b[1mi\u001b[22mrd \u001b[46m \u001b[49m\n f\u001b[1mi\u001b[22mfth \u001b[46m \u001b[49m\n s\u001b[1mi\u001b[22mxth \u001b[46m \u001b[49m\n e\u001b[1mi\u001b[22mghth \u001b[46m \u001b[49m\n n\u001b[1mi\u001b[22mnth \u001b[46m \u001b[49m\n th\u001b[1mi\u001b[22mrteenth \u001b[46m \u001b[49m\n f\u001b[1mi\u001b[22mfteenth \u001b[46m \u001b[49m\n s\u001b[1mi\u001b[22mxteenth \u001b[46m \u001b[49m\n e\u001b[1mi\u001b[22mghteenth \u001b[46m \u001b[49m\n n\u001b[1mi\u001b[22mneteenth \u001b[46m \u001b[49m\n twent\u001b[1mi\u001b[22meth \u001b[46m \u001b[49m\n twenty-f\u001b[1mi\u001b[22mrst \u001b[46m \u001b[49m\n twenty-th\u001b[1mi\u001b[22mrd \u001b[46m \u001b[49m\n twenty-f\u001b[1mi\u001b[22mfth \u001b[46m \u001b[49m\n twenty-s\u001b[1mi\u001b[22mxth \u001b[46m \u001b[49m\n twenty-e\u001b[1mi\u001b[22mghth \u001b[46m \u001b[49m\n twenty-n\u001b[1mi\u001b[22mnth \u001b[46m \u001b[49m\n th\u001b[1mi\u001b[22mrtieth \u001b[100m \u001b[49m\n th\u001b[1mi\u001b[22mrty-first \u001b[100m \u001b[49m\n th\u001b[1mi\u001b[22mrty-second \u001b[100m \u001b[49m\n th\u001b[1mi\u001b[22mrty-third \u001b[100m \u001b[49m\n th\u001b[1mi\u001b[22mrty-fourth \u001b[100m \u001b[49m\n th\u001b[1mi\u001b[22mrty-fifth \u001b[100m \u001b[49m\n th\u001b[1mi\u001b[22mrty-sixth \u001b[100m \u001b[49m\n\n \u001b[2mPress ↑↓ arrows to select, enter to confirm.\u001b[22m\n \"\n `)\n\n await sendInputAndWaitForChange(renderInstance, DELETE)\n\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot(`\n \"? Associate your project with the org Castile Ventures? \u001b[36m\u001b[7mT\u001b[27m\u001b[2mype to search...\u001b[22m\u001b[39m\n\n \u001b[36m>\u001b[39m \u001b[36mfirst\u001b[39m \u001b[46m \u001b[49m\n second \u001b[46m \u001b[49m\n third \u001b[46m \u001b[49m\n fourth \u001b[46m \u001b[49m\n fifth \u001b[46m \u001b[49m\n sixth \u001b[46m \u001b[49m\n seventh \u001b[46m \u001b[49m\n eighth \u001b[46m \u001b[49m\n ninth \u001b[46m \u001b[49m\n tenth \u001b[46m \u001b[49m\n eleventh \u001b[46m \u001b[49m\n twelfth \u001b[46m \u001b[49m\n thirteenth \u001b[46m \u001b[49m\n fourteenth \u001b[100m \u001b[49m\n fifteenth \u001b[100m \u001b[49m\n sixteenth \u001b[100m \u001b[49m\n seventeenth \u001b[100m \u001b[49m\n eighteenth \u001b[100m \u001b[49m\n nineteenth \u001b[100m \u001b[49m\n twentieth \u001b[100m \u001b[49m\n twenty-first \u001b[100m \u001b[49m\n twenty-second \u001b[100m \u001b[49m\n twenty-third \u001b[100m \u001b[49m\n twenty-fourth \u001b[100m \u001b[49m\n twenty-fifth \u001b[100m \u001b[49m\n\n \u001b[2mPress ↑↓ arrows to select, enter to confirm.\u001b[22m\n \"\n `)\n\n await sendInputAndWaitForContent(renderInstance, 'th\u001b[1mi\u001b[22mrty-sixth', 'i')\n await sendInputAndWaitForChange(renderInstance, ARROW_DOWN)\n await sendInputAndWaitForChange(renderInstance, ARROW_DOWN)\n\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot(`\n \"? Associate your project with the org Castile Ventures? \u001b[36mi\u001b[46m█\u001b[49m\u001b[39m\n\n f\u001b[1mi\u001b[22mrst \u001b[46m \u001b[49m\n th\u001b[1mi\u001b[22mrd \u001b[46m \u001b[49m\n \u001b[36m>\u001b[39m \u001b[36mf\u001b[1mi\u001b[22mfth\u001b[39m \u001b[46m \u001b[49m\n s\u001b[1mi\u001b[22mxth \u001b[46m \u001b[49m\n e\u001b[1mi\u001b[22mghth \u001b[46m \u001b[49m\n n\u001b[1mi\u001b[22mnth \u001b[46m \u001b[49m\n th\u001b[1mi\u001b[22mrteenth \u001b[46m \u001b[49m\n f\u001b[1mi\u001b[22mfteenth \u001b[46m \u001b[49m\n s\u001b[1mi\u001b[22mxteenth \u001b[46m \u001b[49m\n e\u001b[1mi\u001b[22mghteenth \u001b[46m \u001b[49m\n n\u001b[1mi\u001b[22mneteenth \u001b[46m \u001b[49m\n twent\u001b[1mi\u001b[22meth \u001b[46m \u001b[49m\n twenty-f\u001b[1mi\u001b[22mrst \u001b[46m \u001b[49m\n twenty-th\u001b[1mi\u001b[22mrd \u001b[46m \u001b[49m\n twenty-f\u001b[1mi\u001b[22mfth \u001b[46m \u001b[49m\n twenty-s\u001b[1mi\u001b[22mxth \u001b[46m \u001b[49m\n twenty-e\u001b[1mi\u001b[22mghth \u001b[46m \u001b[49m\n twenty-n\u001b[1mi\u001b[22mnth \u001b[46m \u001b[49m\n th\u001b[1mi\u001b[22mrtieth \u001b[100m \u001b[49m\n th\u001b[1mi\u001b[22mrty-first \u001b[100m \u001b[49m\n th\u001b[1mi\u001b[22mrty-second \u001b[100m \u001b[49m\n th\u001b[1mi\u001b[22mrty-third \u001b[100m \u001b[49m\n th\u001b[1mi\u001b[22mrty-fourth \u001b[100m \u001b[49m\n th\u001b[1mi\u001b[22mrty-fifth \u001b[100m \u001b[49m\n th\u001b[1mi\u001b[22mrty-sixth \u001b[100m \u001b[49m\n\n \u001b[2mPress ↑↓ arrows to select, enter to confirm.\u001b[22m\n \"\n `)\n\n await sendInputAndWaitForChange(renderInstance, ENTER)\n\n expect(getLastFrameAfterUnmount(renderInstance)).toMatchInlineSnapshot(`\n \"? Associate your project with the org Castile Ventures?\n \u001b[36m✔\u001b[39m \u001b[36mfifth\u001b[39m\n \"\n `)\n\n expect(onEnter).toHaveBeenCalledWith('fifth')\n })\n\n test('displays an error message if the search fails', async () => {\n const search = (_term: string) => {\n return Promise.reject(new Error('Something went wrong'))\n }\n\n const renderInstance = render(\n <AutocompletePrompt\n message=\"Associate your project with the org Castile Ventures?\"\n choices={DATABASE}\n onSubmit={() => {}}\n search={search}\n />,\n )\n\n await waitForInputsToBeReady()\n await sendInputAndWaitForContent(renderInstance, 'There has been an error', 'i')\n\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot(`\n \"? Associate your project with the org Castile Ventures? \u001b[36mi\u001b[46m█\u001b[49m\u001b[39m\n\n \u001b[31mThere has been an error while searching. Please try again later.\u001b[39m\n \"\n `)\n })\n\n test('immediately shows the initial items if the search is empty', async () => {\n const search = (term: string) => {\n return Promise.resolve({\n data: DATABASE.filter((item) => item.label.includes(term)),\n })\n }\n\n const renderInstance = render(\n <AutocompletePrompt\n message=\"Associate your project with the org Castile Ventures?\"\n choices={DATABASE}\n onSubmit={() => {}}\n search={search}\n />,\n )\n\n await waitForInputsToBeReady()\n await sendInputAndWaitForContent(renderInstance, 'th\u001b[1mi\u001b[22mrty-sixth', 'i')\n\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot(`\n \"? Associate your project with the org Castile Ventures? \u001b[36mi\u001b[46m█\u001b[49m\u001b[39m\n\n \u001b[36m>\u001b[39m \u001b[36mf\u001b[1mi\u001b[22mrst\u001b[39m \u001b[46m \u001b[49m\n th\u001b[1mi\u001b[22mrd \u001b[46m \u001b[49m\n f\u001b[1mi\u001b[22mfth \u001b[46m \u001b[49m\n s\u001b[1mi\u001b[22mxth \u001b[46m \u001b[49m\n e\u001b[1mi\u001b[22mghth \u001b[46m \u001b[49m\n n\u001b[1mi\u001b[22mnth \u001b[46m \u001b[49m\n th\u001b[1mi\u001b[22mrteenth \u001b[46m \u001b[49m\n f\u001b[1mi\u001b[22mfteenth \u001b[46m \u001b[49m\n s\u001b[1mi\u001b[22mxteenth \u001b[46m \u001b[49m\n e\u001b[1mi\u001b[22mghteenth \u001b[46m \u001b[49m\n n\u001b[1mi\u001b[22mneteenth \u001b[46m \u001b[49m\n twent\u001b[1mi\u001b[22meth \u001b[46m \u001b[49m\n twenty-f\u001b[1mi\u001b[22mrst \u001b[46m \u001b[49m\n twenty-th\u001b[1mi\u001b[22mrd \u001b[46m \u001b[49m\n twenty-f\u001b[1mi\u001b[22mfth \u001b[46m \u001b[49m\n twenty-s\u001b[1mi\u001b[22mxth \u001b[46m \u001b[49m\n twenty-e\u001b[1mi\u001b[22mghth \u001b[46m \u001b[49m\n twenty-n\u001b[1mi\u001b[22mnth \u001b[46m \u001b[49m\n th\u001b[1mi\u001b[22mrtieth \u001b[100m \u001b[49m\n th\u001b[1mi\u001b[22mrty-first \u001b[100m \u001b[49m\n th\u001b[1mi\u001b[22mrty-second \u001b[100m \u001b[49m\n th\u001b[1mi\u001b[22mrty-third \u001b[100m \u001b[49m\n th\u001b[1mi\u001b[22mrty-fourth \u001b[100m \u001b[49m\n th\u001b[1mi\u001b[22mrty-fifth \u001b[100m \u001b[49m\n th\u001b[1mi\u001b[22mrty-sixth \u001b[100m \u001b[49m\n\n \u001b[2mPress ↑↓ arrows to select, enter to confirm.\u001b[22m\n \"\n `)\n\n await sendInputAndWaitForChange(renderInstance, DELETE)\n\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot(`\n \"? Associate your project with the org Castile Ventures? \u001b[36m\u001b[7mT\u001b[27m\u001b[2mype to search...\u001b[22m\u001b[39m\n\n \u001b[36m>\u001b[39m \u001b[36mfirst\u001b[39m \u001b[46m \u001b[49m\n second \u001b[46m \u001b[49m\n third \u001b[46m \u001b[49m\n fourth \u001b[46m \u001b[49m\n fifth \u001b[46m \u001b[49m\n sixth \u001b[46m \u001b[49m\n seventh \u001b[46m \u001b[49m\n eighth \u001b[46m \u001b[49m\n ninth \u001b[46m \u001b[49m\n tenth \u001b[46m \u001b[49m\n eleventh \u001b[46m \u001b[49m\n twelfth \u001b[46m \u001b[49m\n thirteenth \u001b[46m \u001b[49m\n fourteenth \u001b[100m \u001b[49m\n fifteenth \u001b[100m \u001b[49m\n sixteenth \u001b[100m \u001b[49m\n seventeenth \u001b[100m \u001b[49m\n eighteenth \u001b[100m \u001b[49m\n nineteenth \u001b[100m \u001b[49m\n twentieth \u001b[100m \u001b[49m\n twenty-first \u001b[100m \u001b[49m\n twenty-second \u001b[100m \u001b[49m\n twenty-third \u001b[100m \u001b[49m\n twenty-fourth \u001b[100m \u001b[49m\n twenty-fifth \u001b[100m \u001b[49m\n\n \u001b[2mPress ↑↓ arrows to select, enter to confirm.\u001b[22m\n \"\n `)\n })\n\n test('shows a message that indicates there are more results than shown', async () => {\n const search = (_term: string) => {\n return Promise.resolve({\n data: DATABASE,\n meta: {hasNextPage: true},\n })\n }\n\n const renderInstance = render(\n <AutocompletePrompt\n message=\"Associate your project with the org Castile Ventures?\"\n choices={DATABASE}\n onSubmit={() => {}}\n hasMorePages\n search={search}\n />,\n )\n\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot(`\n \"? Associate your project with the org Castile Ventures? \u001b[36m\u001b[7mT\u001b[27m\u001b[2mype to search...\u001b[22m\u001b[39m\n\n \u001b[36m>\u001b[39m \u001b[36mfirst\u001b[39m \u001b[46m \u001b[49m\n second \u001b[46m \u001b[49m\n third \u001b[46m \u001b[49m\n fourth \u001b[46m \u001b[49m\n fifth \u001b[46m \u001b[49m\n sixth \u001b[46m \u001b[49m\n seventh \u001b[46m \u001b[49m\n eighth \u001b[46m \u001b[49m\n ninth \u001b[46m \u001b[49m\n tenth \u001b[46m \u001b[49m\n eleventh \u001b[46m \u001b[49m\n twelfth \u001b[46m \u001b[49m\n thirteenth \u001b[46m \u001b[49m\n fourteenth \u001b[100m \u001b[49m\n fifteenth \u001b[100m \u001b[49m\n sixteenth \u001b[100m \u001b[49m\n seventeenth \u001b[100m \u001b[49m\n eighteenth \u001b[100m \u001b[49m\n nineteenth \u001b[100m \u001b[49m\n twentieth \u001b[100m \u001b[49m\n twenty-first \u001b[100m \u001b[49m\n twenty-second \u001b[100m \u001b[49m\n twenty-third \u001b[100m \u001b[49m\n twenty-fourth \u001b[100m \u001b[49m\n twenty-fifth \u001b[100m \u001b[49m\n\n \u001b[2mPress ↑↓ arrows to select, enter to confirm.\u001b[22m\n \u001b[1m1-50 of many\u001b[22m Find what you're looking for by typing its name.\n \"\n `)\n })\n\n test('adapts to the height of the container', async () => {\n vi.mocked(useStdout).mockReturnValue({\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n stdout: new Stdout({rows: 10}) as any,\n write: () => {},\n })\n\n const items = [\n {label: 'first', value: 'first', group: 'Automations'},\n {label: 'second', value: 'second', group: 'Automations'},\n {label: 'third', value: 'third', group: 'Merchant Admin'},\n {label: 'fourth', value: 'fourth', group: 'Merchant Admin'},\n {label: 'fifth', value: 'fifth'},\n {label: 'sixth', value: 'sixth'},\n {label: 'seventh', value: 'seventh'},\n {label: 'eighth', value: 'eighth'},\n {label: 'ninth', value: 'ninth'},\n {label: 'tenth', value: 'tenth'},\n ]\n\n const renderInstance = render(\n <AutocompletePrompt\n message=\"Associate your project with the org Castile Ventures?\"\n choices={items}\n onSubmit={() => {}}\n hasMorePages\n search={() =>\n Promise.resolve({\n data: items,\n } as SearchResults<string>)\n }\n />,\n )\n\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot(`\n \"? Associate your project with the org Castile Ventures? \u001b[36m\u001b[7mT\u001b[27m\u001b[2mype to search...\u001b[22m\u001b[39m\n\n \u001b[1mAutomations\u001b[22m \\u001b[46m \\u001b[49m\n \u001b[36m>\u001b[39m \u001b[36mfirst\u001b[39m \\u001b[100m \\u001b[49m\n second \\u001b[100m \\u001b[49m\n \\u001b[100m \\u001b[49m\n \u001b[1mMerchant Admin\u001b[22m \\u001b[100m \\u001b[49m\n\n \u001b[2mPress ↑↓ arrows to select, enter to confirm.\u001b[22m\n \u001b[1m1-10 of many\u001b[22m Find what you're looking for by typing its name.\n \"\n `)\n })\n\n test('abortController can be used to exit the prompt from outside', async () => {\n const items = [\n {label: 'a', value: 'a'},\n {label: 'b', value: 'b'},\n ]\n\n const abortController = new AbortController()\n\n const renderInstance = render(\n <AutocompletePrompt\n message=\"Associate your project with the org Castile Ventures?\"\n choices={items}\n onSubmit={() => {}}\n search={() =>\n Promise.resolve({\n data: [],\n } as SearchResults<string>)\n }\n abortSignal={abortController.signal}\n />,\n )\n const promise = renderInstance.waitUntilExit()\n\n abortController.abort()\n\n expect(getLastFrameAfterUnmount(renderInstance)).toEqual('')\n await expect(promise).resolves.toEqual(undefined)\n })\n})\n"]}
@@ -18,6 +18,7 @@ export interface ConcurrentOutputProps {
18
18
  shortcuts: Shortcut[];
19
19
  subTitle?: string;
20
20
  };
21
+ keepRunningAfterProcessesResolve?: boolean;
21
22
  }
22
23
  /**
23
24
  * Renders output from concurrent processes to the terminal.
@@ -1,10 +1,9 @@
1
- import useAsyncAndUnmount from '../hooks/use-async-and-unmount.js';
2
1
  import { handleCtrlC } from '../../ui.js';
3
2
  import { addOrUpdateConcurrentUIEventOutput } from '../../demo-recorder.js';
4
3
  import { treeKill } from '../../tree-kill.js';
5
4
  import useAbortSignal from '../hooks/use-abort-signal.js';
6
- import React, { useState } from 'react';
7
- import { Box, Static, Text, useInput, useStdin } from 'ink';
5
+ import React, { useCallback, useEffect, useMemo, useState } from 'react';
6
+ import { Box, Static, Text, useInput, useStdin, useApp } from 'ink';
8
7
  import stripAnsi from 'strip-ansi';
9
8
  import figures from 'figures';
10
9
  import { Writable } from 'stream';
@@ -13,6 +12,21 @@ var ConcurrentOutputState;
13
12
  ConcurrentOutputState["Running"] = "running";
14
13
  ConcurrentOutputState["Stopped"] = "stopped";
15
14
  })(ConcurrentOutputState || (ConcurrentOutputState = {}));
15
+ function addLeadingZero(number) {
16
+ if (number < 10) {
17
+ return `0${number}`;
18
+ }
19
+ else {
20
+ return number.toString();
21
+ }
22
+ }
23
+ function currentTime() {
24
+ const currentDateTime = new Date();
25
+ const hours = addLeadingZero(currentDateTime.getHours());
26
+ const minutes = addLeadingZero(currentDateTime.getMinutes());
27
+ const seconds = addLeadingZero(currentDateTime.getSeconds());
28
+ return `${hours}:${minutes}:${seconds}`;
29
+ }
16
30
  /**
17
31
  * Renders output from concurrent processes to the terminal.
18
32
  * Output will be divided in a three column layout
@@ -46,17 +60,18 @@ var ConcurrentOutputState;
46
60
  *
47
61
  * ```
48
62
  */
49
- const ConcurrentOutput = ({ processes, abortSignal, showTimestamps = true, onInput, footer, }) => {
63
+ const ConcurrentOutput = ({ processes, abortSignal, showTimestamps = true, onInput, footer, keepRunningAfterProcessesResolve, }) => {
50
64
  const [processOutput, setProcessOutput] = useState([]);
51
- const concurrentColors = ['yellow', 'cyan', 'magenta', 'green', 'blue'];
65
+ const { exit: unmountInk } = useApp();
52
66
  const prefixColumnSize = Math.max(...processes.map((process) => process.prefix.length));
53
67
  const { isRawModeSupported } = useStdin();
54
68
  const [state, setState] = useState(ConcurrentOutputState.Running);
55
- function lineColor(index) {
69
+ const concurrentColors = useMemo(() => ['yellow', 'cyan', 'magenta', 'green', 'blue'], []);
70
+ const lineColor = useCallback((index) => {
56
71
  const colorIndex = index < concurrentColors.length ? index : index % concurrentColors.length;
57
72
  return concurrentColors[colorIndex];
58
- }
59
- const writableStream = (process, index) => {
73
+ }, [concurrentColors]);
74
+ const writableStream = useCallback((process, index) => {
60
75
  return new Writable({
61
76
  write(chunk, _encoding, next) {
62
77
  const lines = stripAnsi(chunk.toString('utf8').replace(/(\n)$/, '')).split(/\n/);
@@ -72,39 +87,51 @@ const ConcurrentOutput = ({ processes, abortSignal, showTimestamps = true, onInp
72
87
  next();
73
88
  },
74
89
  });
75
- };
76
- const runProcesses = () => {
77
- return Promise.all(processes.map(async (process, index) => {
78
- const stdout = writableStream(process, index);
79
- const stderr = writableStream(process, index);
80
- await process.action(stdout, stderr, abortSignal);
81
- }));
82
- };
90
+ }, [footer, lineColor]);
83
91
  const { isAborted } = useAbortSignal(abortSignal);
84
92
  const useShortcuts = isRawModeSupported && state === ConcurrentOutputState.Running && !isAborted;
85
93
  useInput((input, key) => {
86
94
  handleCtrlC(input, key);
87
95
  onInput(input, key, () => treeKill('SIGINT'));
88
96
  }, { isActive: typeof onInput !== 'undefined' && useShortcuts });
89
- useAsyncAndUnmount(runProcesses, {
90
- onFulfilled: () => {
97
+ useEffect(() => {
98
+ ;
99
+ (() => {
100
+ return Promise.all(processes.map(async (process, index) => {
101
+ const stdout = writableStream(process, index);
102
+ const stderr = writableStream(process, index);
103
+ await process.action(stdout, stderr, abortSignal);
104
+ }));
105
+ })()
106
+ .then(() => {
107
+ if (!keepRunningAfterProcessesResolve) {
108
+ setState(ConcurrentOutputState.Stopped);
109
+ unmountInk();
110
+ }
111
+ })
112
+ .catch((error) => {
91
113
  setState(ConcurrentOutputState.Stopped);
92
- },
93
- onRejected: () => {
94
- setState(ConcurrentOutputState.Stopped);
95
- },
96
- });
114
+ unmountInk(error);
115
+ });
116
+ }, [abortSignal, processes, writableStream, unmountInk, keepRunningAfterProcessesResolve]);
117
+ const { lineVertical } = figures;
97
118
  return (React.createElement(React.Fragment, null,
98
119
  React.createElement(Static, { items: processOutput }, (chunk, index) => {
99
- return (React.createElement(Box, { flexDirection: "column", key: index }, chunk.lines.map((line, index) => (React.createElement(Box, { key: index, flexDirection: "row", gap: 1 },
100
- showTimestamps ? (React.createElement(Box, { gap: 1 },
101
- React.createElement(Text, { color: chunk.color }, new Date().toISOString().replace(/T/, ' ').replace(/\..+/, '')),
102
- React.createElement(Text, { bold: true, color: chunk.color }, figures.lineVertical))) : null,
103
- React.createElement(Box, { width: prefixColumnSize },
104
- React.createElement(Text, { color: chunk.color }, chunk.prefix)),
105
- React.createElement(Text, { bold: true, color: chunk.color }, figures.lineVertical),
106
- React.createElement(Box, { flexGrow: 1 },
107
- React.createElement(Text, { color: chunk.color }, line)))))));
120
+ const prefixBuffer = ' '.repeat(prefixColumnSize - chunk.prefix.length);
121
+ return (React.createElement(Box, { flexDirection: "column", key: index }, chunk.lines.map((line, index) => (React.createElement(Box, { key: index, flexDirection: "row" },
122
+ React.createElement(Text, { color: chunk.color },
123
+ showTimestamps ? (React.createElement(Text, null,
124
+ currentTime(),
125
+ " ",
126
+ lineVertical,
127
+ ' ')) : null,
128
+ React.createElement(Text, null,
129
+ chunk.prefix,
130
+ prefixBuffer,
131
+ " ",
132
+ lineVertical,
133
+ " ",
134
+ line)))))));
108
135
  }),
109
136
  footer ? (React.createElement(Box, { marginY: 1, flexDirection: "column", flexGrow: 1 },
110
137
  useShortcuts ? (React.createElement(Box, { flexDirection: "column" }, footer.shortcuts.map((shortcut, index) => (React.createElement(Text, { key: index },
@@ -1 +1 @@
1
- {"version":3,"file":"ConcurrentOutput.js","sourceRoot":"","sources":["../../../../../src/private/node/ui/components/ConcurrentOutput.tsx"],"names":[],"mappings":"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","sourcesContent":["import {OutputProcess} from '../../../../public/node/output.js'\nimport useAsyncAndUnmount from '../hooks/use-async-and-unmount.js'\nimport {AbortSignal} from '../../../../public/node/abort.js'\nimport {handleCtrlC} from '../../ui.js'\nimport {addOrUpdateConcurrentUIEventOutput} from '../../demo-recorder.js'\nimport {treeKill} from '../../tree-kill.js'\nimport useAbortSignal from '../hooks/use-abort-signal.js'\nimport React, {FunctionComponent, useState} from 'react'\nimport {Box, Key, Static, Text, useInput, TextProps, useStdin} from 'ink'\nimport stripAnsi from 'strip-ansi'\nimport figures from 'figures'\nimport {Writable} from 'stream'\n\nexport type WritableStream = (process: OutputProcess, index: number) => Writable\n\ninterface Shortcut {\n key: string\n action: string\n}\nexport interface ConcurrentOutputProps {\n processes: OutputProcess[]\n abortSignal: AbortSignal\n showTimestamps?: boolean\n onInput?: (input: string, key: Key, exit: () => void) => void\n footer?: {\n shortcuts: Shortcut[]\n subTitle?: string\n }\n}\ninterface Chunk {\n color: TextProps['color']\n prefix: string\n lines: string[]\n}\n\nenum ConcurrentOutputState {\n Running = 'running',\n Stopped = 'stopped',\n}\n\n/**\n * Renders output from concurrent processes to the terminal.\n * Output will be divided in a three column layout\n * with the left column containing the timestamp,\n * the right column containing the output,\n * and the middle column containing the process prefix.\n * Every process will be rendered with a different color, up to 4 colors.\n *\n * For example running `shopify app dev`:\n *\n * ```shell\n * 2022-10-10 13:11:03 | backend | npm\n * 2022-10-10 13:11:03 | backend | WARN ignoring workspace config at ...\n * 2022-10-10 13:11:03 | backend |\n * 2022-10-10 13:11:03 | backend |\n * 2022-10-10 13:11:03 | backend | > shopify-app-template-node@0.1.0 dev\n * 2022-10-10 13:11:03 | backend | > cross-env NODE_ENV=development nodemon backend/index.js --watch ./backend\n * 2022-10-10 13:11:03 | backend |\n * 2022-10-10 13:11:03 | backend |\n * 2022-10-10 13:11:03 | frontend |\n * 2022-10-10 13:11:03 | frontend | > starter-react-frontend-app@0.1.0 dev\n * 2022-10-10 13:11:03 | frontend | > cross-env NODE_ENV=development node vite-server.js\n * 2022-10-10 13:11:03 | frontend |\n * 2022-10-10 13:11:03 | frontend |\n * 2022-10-10 13:11:03 | backend |\n * 2022-10-10 13:11:03 | backend | [nodemon] to restart at any time, enter `rs`\n * 2022-10-10 13:11:03 | backend | [nodemon] watching path(s): backend/\n * 2022-10-10 13:11:03 | backend | [nodemon] watching extensions: js,mjs,json\n * 2022-10-10 13:11:03 | backend | [nodemon] starting `node backend/index.js`\n * 2022-10-10 13:11:03 | backend |\n *\n * ```\n */\nconst ConcurrentOutput: FunctionComponent<ConcurrentOutputProps> = ({\n processes,\n abortSignal,\n showTimestamps = true,\n onInput,\n footer,\n}) => {\n const [processOutput, setProcessOutput] = useState<Chunk[]>([])\n const concurrentColors: TextProps['color'][] = ['yellow', 'cyan', 'magenta', 'green', 'blue']\n const prefixColumnSize = Math.max(...processes.map((process) => process.prefix.length))\n const {isRawModeSupported} = useStdin()\n const [state, setState] = useState<ConcurrentOutputState>(ConcurrentOutputState.Running)\n\n function lineColor(index: number) {\n const colorIndex = index < concurrentColors.length ? index : index % concurrentColors.length\n return concurrentColors[colorIndex]!\n }\n\n const writableStream = (process: OutputProcess, index: number) => {\n return new Writable({\n write(chunk, _encoding, next) {\n const lines = stripAnsi(chunk.toString('utf8').replace(/(\\n)$/, '')).split(/\\n/)\n addOrUpdateConcurrentUIEventOutput({prefix: process.prefix, index, output: lines.join('\\n')}, {footer})\n\n setProcessOutput((previousProcessOutput) => [\n ...previousProcessOutput,\n {\n color: lineColor(index),\n prefix: process.prefix,\n lines,\n },\n ])\n\n next()\n },\n })\n }\n\n const runProcesses = () => {\n return Promise.all(\n processes.map(async (process, index) => {\n const stdout = writableStream(process, index)\n const stderr = writableStream(process, index)\n\n await process.action(stdout, stderr, abortSignal)\n }),\n )\n }\n\n const {isAborted} = useAbortSignal(abortSignal)\n\n const useShortcuts = isRawModeSupported && state === ConcurrentOutputState.Running && !isAborted\n\n useInput(\n (input, key) => {\n handleCtrlC(input, key)\n\n onInput!(input, key, () => treeKill('SIGINT'))\n },\n {isActive: typeof onInput !== 'undefined' && useShortcuts},\n )\n\n useAsyncAndUnmount(runProcesses, {\n onFulfilled: () => {\n setState(ConcurrentOutputState.Stopped)\n },\n onRejected: () => {\n setState(ConcurrentOutputState.Stopped)\n },\n })\n\n return (\n <>\n <Static items={processOutput}>\n {(chunk, index) => {\n return (\n <Box flexDirection=\"column\" key={index}>\n {chunk.lines.map((line, index) => (\n <Box key={index} flexDirection=\"row\" gap={1}>\n {showTimestamps ? (\n <Box gap={1}>\n <Text color={chunk.color}>{new Date().toISOString().replace(/T/, ' ').replace(/\\..+/, '')}</Text>\n\n <Text bold color={chunk.color}>\n {figures.lineVertical}\n </Text>\n </Box>\n ) : null}\n\n <Box width={prefixColumnSize}>\n <Text color={chunk.color}>{chunk.prefix}</Text>\n </Box>\n\n <Text bold color={chunk.color}>\n {figures.lineVertical}\n </Text>\n\n <Box flexGrow={1}>\n <Text color={chunk.color}>{line}</Text>\n </Box>\n </Box>\n ))}\n </Box>\n )\n }}\n </Static>\n {footer ? (\n <Box marginY={1} flexDirection=\"column\" flexGrow={1}>\n {useShortcuts ? (\n <Box flexDirection=\"column\">\n {footer.shortcuts.map((shortcut, index) => (\n <Text key={index}>\n {figures.pointerSmall} Press <Text bold>{shortcut.key}</Text> {figures.lineVertical} {shortcut.action}\n </Text>\n ))}\n </Box>\n ) : null}\n {footer.subTitle ? (\n <Box marginTop={useShortcuts ? 1 : 0}>\n <Text>{footer.subTitle}</Text>\n </Box>\n ) : null}\n </Box>\n ) : null}\n </>\n )\n}\n\nexport {ConcurrentOutput}\n"]}
1
+ {"version":3,"file":"ConcurrentOutput.js","sourceRoot":"","sources":["../../../../../src/private/node/ui/components/ConcurrentOutput.tsx"],"names":[],"mappings":"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","sourcesContent":["import {OutputProcess} from '../../../../public/node/output.js'\nimport {AbortSignal} from '../../../../public/node/abort.js'\nimport {handleCtrlC} from '../../ui.js'\nimport {addOrUpdateConcurrentUIEventOutput} from '../../demo-recorder.js'\nimport {treeKill} from '../../tree-kill.js'\nimport useAbortSignal from '../hooks/use-abort-signal.js'\nimport React, {FunctionComponent, useCallback, useEffect, useMemo, useState} from 'react'\nimport {Box, Key, Static, Text, useInput, TextProps, useStdin, useApp} from 'ink'\nimport stripAnsi from 'strip-ansi'\nimport figures from 'figures'\nimport {Writable} from 'stream'\n\nexport type WritableStream = (process: OutputProcess, index: number) => Writable\n\ninterface Shortcut {\n key: string\n action: string\n}\nexport interface ConcurrentOutputProps {\n processes: OutputProcess[]\n abortSignal: AbortSignal\n showTimestamps?: boolean\n onInput?: (input: string, key: Key, exit: () => void) => void\n footer?: {\n shortcuts: Shortcut[]\n subTitle?: string\n }\n // If set, the component is not automatically unmounted once the processes have all finished\n keepRunningAfterProcessesResolve?: boolean\n}\ninterface Chunk {\n color: TextProps['color']\n prefix: string\n lines: string[]\n}\n\nenum ConcurrentOutputState {\n Running = 'running',\n Stopped = 'stopped',\n}\n\nfunction addLeadingZero(number: number) {\n if (number < 10) {\n return `0${number}`\n } else {\n return number.toString()\n }\n}\n\nfunction currentTime() {\n const currentDateTime = new Date()\n\n const hours = addLeadingZero(currentDateTime.getHours())\n const minutes = addLeadingZero(currentDateTime.getMinutes())\n const seconds = addLeadingZero(currentDateTime.getSeconds())\n\n return `${hours}:${minutes}:${seconds}`\n}\n\n/**\n * Renders output from concurrent processes to the terminal.\n * Output will be divided in a three column layout\n * with the left column containing the timestamp,\n * the right column containing the output,\n * and the middle column containing the process prefix.\n * Every process will be rendered with a different color, up to 4 colors.\n *\n * For example running `shopify app dev`:\n *\n * ```shell\n * 2022-10-10 13:11:03 | backend | npm\n * 2022-10-10 13:11:03 | backend | WARN ignoring workspace config at ...\n * 2022-10-10 13:11:03 | backend |\n * 2022-10-10 13:11:03 | backend |\n * 2022-10-10 13:11:03 | backend | > shopify-app-template-node@0.1.0 dev\n * 2022-10-10 13:11:03 | backend | > cross-env NODE_ENV=development nodemon backend/index.js --watch ./backend\n * 2022-10-10 13:11:03 | backend |\n * 2022-10-10 13:11:03 | backend |\n * 2022-10-10 13:11:03 | frontend |\n * 2022-10-10 13:11:03 | frontend | > starter-react-frontend-app@0.1.0 dev\n * 2022-10-10 13:11:03 | frontend | > cross-env NODE_ENV=development node vite-server.js\n * 2022-10-10 13:11:03 | frontend |\n * 2022-10-10 13:11:03 | frontend |\n * 2022-10-10 13:11:03 | backend |\n * 2022-10-10 13:11:03 | backend | [nodemon] to restart at any time, enter `rs`\n * 2022-10-10 13:11:03 | backend | [nodemon] watching path(s): backend/\n * 2022-10-10 13:11:03 | backend | [nodemon] watching extensions: js,mjs,json\n * 2022-10-10 13:11:03 | backend | [nodemon] starting `node backend/index.js`\n * 2022-10-10 13:11:03 | backend |\n *\n * ```\n */\nconst ConcurrentOutput: FunctionComponent<ConcurrentOutputProps> = ({\n processes,\n abortSignal,\n showTimestamps = true,\n onInput,\n footer,\n keepRunningAfterProcessesResolve,\n}) => {\n const [processOutput, setProcessOutput] = useState<Chunk[]>([])\n const {exit: unmountInk} = useApp()\n const prefixColumnSize = Math.max(...processes.map((process) => process.prefix.length))\n const {isRawModeSupported} = useStdin()\n const [state, setState] = useState<ConcurrentOutputState>(ConcurrentOutputState.Running)\n const concurrentColors: TextProps['color'][] = useMemo(() => ['yellow', 'cyan', 'magenta', 'green', 'blue'], [])\n const lineColor = useCallback(\n (index: number) => {\n const colorIndex = index < concurrentColors.length ? index : index % concurrentColors.length\n return concurrentColors[colorIndex]!\n },\n [concurrentColors],\n )\n\n const writableStream = useCallback(\n (process: OutputProcess, index: number) => {\n return new Writable({\n write(chunk, _encoding, next) {\n const lines = stripAnsi(chunk.toString('utf8').replace(/(\\n)$/, '')).split(/\\n/)\n addOrUpdateConcurrentUIEventOutput({prefix: process.prefix, index, output: lines.join('\\n')}, {footer})\n\n setProcessOutput((previousProcessOutput) => [\n ...previousProcessOutput,\n {\n color: lineColor(index),\n prefix: process.prefix,\n lines,\n },\n ])\n\n next()\n },\n })\n },\n [footer, lineColor],\n )\n\n const {isAborted} = useAbortSignal(abortSignal)\n const useShortcuts = isRawModeSupported && state === ConcurrentOutputState.Running && !isAborted\n\n useInput(\n (input, key) => {\n handleCtrlC(input, key)\n\n onInput!(input, key, () => treeKill('SIGINT'))\n },\n {isActive: typeof onInput !== 'undefined' && useShortcuts},\n )\n\n useEffect(() => {\n ;(() => {\n return Promise.all(\n processes.map(async (process, index) => {\n const stdout = writableStream(process, index)\n const stderr = writableStream(process, index)\n\n await process.action(stdout, stderr, abortSignal)\n }),\n )\n })()\n .then(() => {\n if (!keepRunningAfterProcessesResolve) {\n setState(ConcurrentOutputState.Stopped)\n unmountInk()\n }\n })\n .catch((error) => {\n setState(ConcurrentOutputState.Stopped)\n unmountInk(error)\n })\n }, [abortSignal, processes, writableStream, unmountInk, keepRunningAfterProcessesResolve])\n\n const {lineVertical} = figures\n\n return (\n <>\n <Static items={processOutput}>\n {(chunk, index) => {\n const prefixBuffer = ' '.repeat(prefixColumnSize - chunk.prefix.length)\n return (\n <Box flexDirection=\"column\" key={index}>\n {chunk.lines.map((line, index) => (\n <Box key={index} flexDirection=\"row\">\n <Text color={chunk.color}>\n {showTimestamps ? (\n <Text>\n {currentTime()} {lineVertical}{' '}\n </Text>\n ) : null}\n\n <Text>\n {chunk.prefix}\n {prefixBuffer} {lineVertical} {line}\n </Text>\n </Text>\n </Box>\n ))}\n </Box>\n )\n }}\n </Static>\n {footer ? (\n <Box marginY={1} flexDirection=\"column\" flexGrow={1}>\n {useShortcuts ? (\n <Box flexDirection=\"column\">\n {footer.shortcuts.map((shortcut, index) => (\n <Text key={index}>\n {figures.pointerSmall} Press <Text bold>{shortcut.key}</Text> {figures.lineVertical} {shortcut.action}\n </Text>\n ))}\n </Box>\n ) : null}\n {footer.subTitle ? (\n <Box marginTop={useShortcuts ? 1 : 0}>\n <Text>{footer.subTitle}</Text>\n </Box>\n ) : null}\n </Box>\n ) : null}\n </>\n )\n}\n\nexport {ConcurrentOutput}\n"]}
@@ -53,12 +53,12 @@ describe('ConcurrentOutput', () => {
53
53
  await frontendPromise;
54
54
  // Then
55
55
  expect(unstyled(renderInstance.lastFrame().replace(/\d/g, '0'))).toMatchInlineSnapshot(`
56
- "0000-00-00 00:00:00 │ backend │ first backend message
57
- 0000-00-00 00:00:00 │ backend │ second backend message
58
- 0000-00-00 00:00:00 │ backend │ third backend message
59
- 0000-00-00 00:00:00 │ frontend │ first frontend message
60
- 0000-00-00 00:00:00 │ frontend │ second frontend message
61
- 0000-00-00 00:00:00 │ frontend │ third frontend message
56
+ "00:00:00 │ backend │ first backend message
57
+ 00:00:00 │ backend │ second backend message
58
+ 00:00:00 │ backend │ third backend message
59
+ 00:00:00 │ frontend │ first frontend message
60
+ 00:00:00 │ frontend │ second frontend message
61
+ 00:00:00 │ frontend │ third frontend message
62
62
 
63
63
  › Press p │ preview in your browser
64
64
  › Press q │ quit
@@ -115,12 +115,12 @@ describe('ConcurrentOutput', () => {
115
115
  await frontendPromise;
116
116
  // Then
117
117
  expect(unstyled(getLastFrameAfterUnmount(renderInstance).replace(/\d/g, '0'))).toMatchInlineSnapshot(`
118
- "0000-00-00 00:00:00 │ backend │ first backend message
119
- 0000-00-00 00:00:00 │ backend │ second backend message
120
- 0000-00-00 00:00:00 │ backend │ third backend message
121
- 0000-00-00 00:00:00 │ frontend │ first frontend message
122
- 0000-00-00 00:00:00 │ frontend │ second frontend message
123
- 0000-00-00 00:00:00 │ frontend │ third frontend message
118
+ "00:00:00 │ backend │ first backend message
119
+ 00:00:00 │ backend │ second backend message
120
+ 00:00:00 │ backend │ third backend message
121
+ 00:00:00 │ frontend │ first frontend message
122
+ 00:00:00 │ frontend │ second frontend message
123
+ 00:00:00 │ frontend │ third frontend message
124
124
 
125
125
  Preview URL: https://shopify.com
126
126
  "
@@ -137,7 +137,6 @@ describe('ConcurrentOutput', () => {
137
137
  const onInput = vi.fn();
138
138
  const renderInstance = render(React.createElement(ConcurrentOutput, { processes: [neverEndingProcess], onInput: (input, key) => onInput(input, key), abortSignal: new AbortController().signal }));
139
139
  await waitForInputsToBeReady();
140
- expect(onInput).toHaveBeenCalledTimes(0);
141
140
  renderInstance.stdin.write('a');
142
141
  expect(onInput).toHaveBeenCalledTimes(1);
143
142
  expect(onInput.mock.calls[0][0]).toBe('a');
@@ -172,9 +171,9 @@ describe('ConcurrentOutput', () => {
172
171
  const promise = renderInstance.waitUntilExit();
173
172
  abortController.abort();
174
173
  expect(unstyled(getLastFrameAfterUnmount(renderInstance)).replace(/\d/g, '0')).toMatchInlineSnapshot(`
175
- "0000-00-00 00:00:00 │ backend │ first backend message
176
- 0000-00-00 00:00:00 │ backend │ second backend message
177
- 0000-00-00 00:00:00 │ backend │ third backend message
174
+ "00:00:00 │ backend │ first backend message
175
+ 00:00:00 │ backend │ second backend message
176
+ 00:00:00 │ backend │ third backend message
178
177
 
179
178
  Preview URL: https://shopify.com
180
179
  "
@@ -208,9 +207,9 @@ describe('ConcurrentOutput', () => {
208
207
  } }));
209
208
  await expect(renderInstance.waitUntilExit()).rejects.toThrowError('something went wrong');
210
209
  expect(unstyled(getLastFrameAfterUnmount(renderInstance)).replace(/\d/g, '0')).toMatchInlineSnapshot(`
211
- "0000-00-00 00:00:00 │ backend │ first backend message
212
- 0000-00-00 00:00:00 │ backend │ second backend message
213
- 0000-00-00 00:00:00 │ backend │ third backend message
210
+ "00:00:00 │ backend │ first backend message
211
+ 00:00:00 │ backend │ second backend message
212
+ 00:00:00 │ backend │ third backend message
214
213
 
215
214
  Preview URL: https://shopify.com
216
215
  "
@@ -242,13 +241,54 @@ describe('ConcurrentOutput', () => {
242
241
  } }));
243
242
  await renderInstance.waitUntilExit();
244
243
  expect(unstyled(getLastFrameAfterUnmount(renderInstance)).replace(/\d/g, '0')).toMatchInlineSnapshot(`
245
- "0000-00-00 00:00:00 │ backend │ first backend message
246
- 0000-00-00 00:00:00 │ backend │ second backend message
247
- 0000-00-00 00:00:00 │ backend │ third backend message
244
+ "00:00:00 │ backend │ first backend message
245
+ 00:00:00 │ backend │ second backend message
246
+ 00:00:00 │ backend │ third backend message
248
247
 
249
248
  Preview URL: https://shopify.com
250
249
  "
251
250
  `);
252
251
  });
252
+ test('renders the shortcuts and accepts inputs when the processes resolve and keepRunningAfterProcessesResolve is true', async () => {
253
+ const onInput = vi.fn();
254
+ // Given
255
+ const backendProcess = {
256
+ prefix: 'backend',
257
+ action: async (stdout, _stderr, _signal) => {
258
+ stdout.write('first backend message');
259
+ stdout.write('second backend message');
260
+ stdout.write('third backend message');
261
+ },
262
+ };
263
+ // When
264
+ const renderInstance = render(React.createElement(ConcurrentOutput, { processes: [backendProcess], abortSignal: new AbortController().signal, footer: {
265
+ shortcuts: [
266
+ {
267
+ key: 'p',
268
+ action: 'preview in your browser',
269
+ },
270
+ {
271
+ key: 'q',
272
+ action: 'quit',
273
+ },
274
+ ],
275
+ subTitle: `Preview URL: https://shopify.com`,
276
+ }, onInput: onInput, keepRunningAfterProcessesResolve: true }));
277
+ await new Promise((resolve) => setTimeout(resolve, 1000));
278
+ expect(unstyled(getLastFrameAfterUnmount(renderInstance)).replace(/\d/g, '0')).toMatchInlineSnapshot(`
279
+ "00:00:00 │ backend │ first backend message
280
+ 00:00:00 │ backend │ second backend message
281
+ 00:00:00 │ backend │ third backend message
282
+
283
+ › Press p │ preview in your browser
284
+ › Press q │ quit
285
+
286
+ Preview URL: https://shopify.com
287
+ "
288
+ `);
289
+ renderInstance.stdin.write('a');
290
+ expect(onInput).toHaveBeenCalledTimes(1);
291
+ expect(onInput.mock.calls[0][0]).toBe('a');
292
+ });
253
293
  });
254
294
  //# sourceMappingURL=ConcurrentOutput.test.js.map