@shopify/cli-kit 3.44.1 → 3.45.0-pre.1
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/README.md +15 -7
- package/assets/cli-ruby/lib/project_types/extension/messages/messages.rb +0 -2
- package/assets/cli-ruby/lib/project_types/theme/commands/pull.rb +6 -0
- package/assets/cli-ruby/lib/project_types/theme/commands/push.rb +6 -0
- package/assets/cli-ruby/lib/shopify_cli/constants.rb +1 -0
- package/assets/cli-ruby/lib/shopify_cli/environment.rb +4 -0
- package/assets/cli-ruby/lib/shopify_cli/theme/dev_server/proxy.rb +3 -0
- package/assets/cli-ruby/lib/shopify_cli/theme/extension/dev_server.rb +3 -3
- package/assets/cli-ruby/lib/shopify_cli/theme/extension/host_theme.rb +4 -4
- package/assets/cli-ruby/lib/shopify_cli/theme/extension/syncer/extension_serve_job.rb +4 -6
- package/assets/cli-ruby/lib/shopify_cli/theme/extension/ui/host_theme_raw_progress_bar.rb +40 -0
- package/assets/cli-ruby/vendor/deps/cli-ui/lib/cli/ui/progress_plain.rb +50 -0
- package/assets/cli-ruby/vendor/deps/cli-ui/lib/cli/ui.rb +15 -14
- package/dist/private/node/api/graphql.js +12 -23
- package/dist/private/node/api/graphql.js.map +1 -1
- package/dist/private/node/api.d.ts +1 -1
- package/dist/private/node/api.js +28 -9
- package/dist/private/node/api.js.map +1 -1
- package/dist/private/node/constants.d.ts +0 -1
- package/dist/private/node/constants.js +0 -1
- package/dist/private/node/constants.js.map +1 -1
- package/dist/private/node/testing/ui.d.ts +11 -0
- package/dist/private/node/testing/ui.js +15 -1
- package/dist/private/node/testing/ui.js.map +1 -1
- package/dist/private/node/ui/alert.d.ts +5 -1
- package/dist/private/node/ui/alert.js +2 -2
- package/dist/private/node/ui/alert.js.map +1 -1
- package/dist/private/node/ui/components/AutocompletePrompt.js +38 -12
- package/dist/private/node/ui/components/AutocompletePrompt.js.map +1 -1
- package/dist/private/node/ui/components/AutocompletePrompt.test.js +56 -36
- package/dist/private/node/ui/components/AutocompletePrompt.test.js.map +1 -1
- package/dist/private/node/ui/components/ConcurrentOutput.d.ts +5 -1
- package/dist/private/node/ui/components/ConcurrentOutput.js +15 -13
- package/dist/private/node/ui/components/ConcurrentOutput.js.map +1 -1
- package/dist/private/node/ui/components/ConcurrentOutput.test.js +20 -11
- package/dist/private/node/ui/components/ConcurrentOutput.test.js.map +1 -1
- package/dist/private/node/ui/components/FullScreen.js +1 -1
- package/dist/private/node/ui/components/FullScreen.js.map +1 -1
- package/dist/private/node/ui/components/SelectInput.d.ts +7 -2
- package/dist/private/node/ui/components/SelectInput.js +73 -60
- package/dist/private/node/ui/components/SelectInput.js.map +1 -1
- package/dist/private/node/ui/components/SelectInput.test.js +72 -2
- package/dist/private/node/ui/components/SelectInput.test.js.map +1 -1
- package/dist/private/node/ui/components/SelectPrompt.js +38 -12
- package/dist/private/node/ui/components/SelectPrompt.js.map +1 -1
- package/dist/private/node/ui/components/SelectPrompt.test.js +52 -1
- package/dist/private/node/ui/components/SelectPrompt.test.js.map +1 -1
- package/dist/private/node/ui/components/Tasks.js +9 -1
- package/dist/private/node/ui/components/Tasks.js.map +1 -1
- package/dist/private/node/ui/components/TextAnimation.js +4 -4
- package/dist/private/node/ui/components/TextAnimation.js.map +1 -1
- package/dist/private/node/ui/components/TextPrompt.js +4 -4
- package/dist/private/node/ui/components/TextPrompt.js.map +1 -1
- package/dist/private/node/ui/hooks/use-layout.d.ts +6 -0
- package/dist/private/node/ui/hooks/use-layout.js +31 -12
- package/dist/private/node/ui/hooks/use-layout.js.map +1 -1
- package/dist/private/node/ui.d.ts +11 -3
- package/dist/private/node/ui.js +14 -10
- package/dist/private/node/ui.js.map +1 -1
- package/dist/public/common/object.d.ts +1 -1
- package/dist/public/common/object.js +1 -1
- package/dist/public/common/object.js.map +1 -1
- package/dist/public/common/version.d.ts +1 -1
- package/dist/public/common/version.js +1 -1
- package/dist/public/common/version.js.map +1 -1
- package/dist/public/node/base-command.d.ts +1 -4
- package/dist/public/node/base-command.js +17 -19
- package/dist/public/node/base-command.js.map +1 -1
- package/dist/public/node/context/local.d.ts +0 -7
- package/dist/public/node/context/local.js +0 -9
- package/dist/public/node/context/local.js.map +1 -1
- package/dist/public/node/environments.d.ts +7 -8
- package/dist/public/node/environments.js +23 -25
- package/dist/public/node/environments.js.map +1 -1
- package/dist/public/node/node-package-manager.d.ts +1 -1
- package/dist/public/node/node-package-manager.js.map +1 -1
- package/dist/public/node/output.d.ts +1 -1
- package/dist/public/node/output.js.map +1 -1
- package/dist/public/node/path.js +1 -1
- package/dist/public/node/path.js.map +1 -1
- package/dist/public/node/ruby.d.ts +1 -0
- package/dist/public/node/ruby.js +35 -15
- package/dist/public/node/ruby.js.map +1 -1
- package/dist/public/node/themes/theme-manager.d.ts +1 -1
- package/dist/public/node/themes/theme-manager.js.map +1 -1
- package/dist/public/node/ui.d.ts +182 -121
- package/dist/public/node/ui.js +172 -120
- package/dist/public/node/ui.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +20 -18
- package/dist/private/node/ui/components/TextWithBackground.d.ts +0 -12
- package/dist/private/node/ui/components/TextWithBackground.js +0 -39
- package/dist/private/node/ui/components/TextWithBackground.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"alert.js","sourceRoot":"","sources":["../../../../src/private/node/ui/alert.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAC,KAAK,EAAa,MAAM,uBAAuB,CAAA;AACvD,OAAO,EAAC,UAAU,EAAC,MAAM,UAAU,CAAA;AACnC,OAAO,EAAC,UAAU,EAAE,WAAW,EAAmB,MAAM,gCAAgC,CAAA;AACxF,OAAO,KAAK,MAAM,OAAO,CAAA;
|
|
1
|
+
{"version":3,"file":"alert.js","sourceRoot":"","sources":["../../../../src/private/node/ui/alert.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAC,KAAK,EAAa,MAAM,uBAAuB,CAAA;AACvD,OAAO,EAAC,UAAU,EAAC,MAAM,UAAU,CAAA;AACnC,OAAO,EAAC,UAAU,EAAE,WAAW,EAAmB,MAAM,gCAAgC,CAAA;AACxF,OAAO,KAAK,MAAM,OAAO,CAAA;AAGzB,MAAM,cAAc,GAA4C;IAC9D,IAAI,EAAE,MAAM;IACZ,OAAO,EAAE,MAAM;IACf,OAAO,EAAE,MAAM;CAChB,CAAA;AAED,MAAM,YAAY,GAA0C;IAC1D,IAAI,EAAE,UAAU;IAChB,OAAO,EAAE,WAAW;IACpB,OAAO,EAAE,UAAU;CACpB,CAAA;AAMD,MAAM,UAAU,KAAK,CAAC,EACpB,IAAI,EACJ,QAAQ,EACR,IAAI,EACJ,SAAS,EACT,SAAS,EACT,IAAI,EACJ,cAAc,EACd,gBAAgB,GAAG,KAAK,EACxB,aAAa,GACA;IACb,OAAO,UAAU,CACf,oBAAC,KAAK,IACJ,IAAI,EAAE,IAAI,EACV,QAAQ,EAAE,QAAQ,EAClB,IAAI,EAAE,IAAI,EACV,SAAS,EAAE,SAAS,EACpB,SAAS,EAAE,SAAS,EACpB,IAAI,EAAE,IAAI,EACV,gBAAgB,EAAE,gBAAgB,EAClC,cAAc,EAAE,cAAc,GAC9B,EACF,EAAC,QAAQ,EAAE,cAAc,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,YAAY,CAAC,IAAI,CAAC,EAAE,aAAa,EAAC,CAC5E,CAAA;AACH,CAAC","sourcesContent":["import {Alert, AlertProps} from './components/Alert.js'\nimport {renderOnce} from '../ui.js'\nimport {consoleLog, consoleWarn, Logger, LogLevel} from '../../../public/node/output.js'\nimport React from 'react'\nimport {RenderOptions} from 'ink'\n\nconst typeToLogLevel: {[key in AlertProps['type']]: LogLevel} = {\n info: 'info',\n warning: 'warn',\n success: 'info',\n}\n\nconst typeToLogger: {[key in AlertProps['type']]: Logger} = {\n info: consoleLog,\n warning: consoleWarn,\n success: consoleLog,\n}\n\nexport interface AlertOptions extends AlertProps {\n renderOptions?: RenderOptions\n}\n\nexport function alert({\n type,\n headline,\n body,\n nextSteps,\n reference,\n link,\n customSections,\n orderedNextSteps = false,\n renderOptions,\n}: AlertOptions) {\n return renderOnce(\n <Alert\n type={type}\n headline={headline}\n body={body}\n nextSteps={nextSteps}\n reference={reference}\n link={link}\n orderedNextSteps={orderedNextSteps}\n customSections={customSections}\n />,\n {logLevel: typeToLogLevel[type], logger: typeToLogger[type], renderOptions},\n )\n}\n"]}
|
|
@@ -4,10 +4,10 @@ import { TextInput } from './TextInput.js';
|
|
|
4
4
|
import { TokenizedText } from './TokenizedText.js';
|
|
5
5
|
import { handleCtrlC } from '../../ui.js';
|
|
6
6
|
import { messageWithPunctuation } from '../utilities.js';
|
|
7
|
-
import
|
|
7
|
+
import { debounce } from '../../../../public/common/function.js';
|
|
8
|
+
import React, { useCallback, useEffect, useRef, useState } from 'react';
|
|
8
9
|
import { Box, measureElement, Text, useApp, useInput, useStdout } from 'ink';
|
|
9
10
|
import figures from 'figures';
|
|
10
|
-
import { debounce } from '@shopify/cli-kit/common/function';
|
|
11
11
|
import ansiEscapes from 'ansi-escapes';
|
|
12
12
|
var PromptState;
|
|
13
13
|
(function (PromptState) {
|
|
@@ -26,25 +26,49 @@ function AutocompletePrompt({ message, choices: initialChoices, infoTable, onSub
|
|
|
26
26
|
const [searchTerm, setSearchTerm] = useState('');
|
|
27
27
|
const [searchResults, setSearchResults] = useState(paginatedInitialChoices.slice(0, PAGE_SIZE));
|
|
28
28
|
const { stdout } = useStdout();
|
|
29
|
-
const [height, setHeight] = useState(0);
|
|
30
29
|
const canSearch = initialChoices.length >= PAGE_SIZE;
|
|
31
30
|
const [hasMorePages, setHasMorePages] = useState(initialHasMorePages);
|
|
31
|
+
const [wrapperHeight, setWrapperHeight] = useState(0);
|
|
32
|
+
const [selectInputHeight, setSelectInputHeight] = useState(0);
|
|
33
|
+
const [limit, setLimit] = useState(searchResults.length);
|
|
32
34
|
const paginatedSearch = useCallback(async (term) => {
|
|
33
35
|
const results = await search(term);
|
|
34
36
|
results.data = results.data.slice(0, PAGE_SIZE);
|
|
35
37
|
return results;
|
|
38
|
+
}, [search]);
|
|
39
|
+
const wrapperRef = useCallback((node) => {
|
|
40
|
+
if (node !== null) {
|
|
41
|
+
const { height } = measureElement(node);
|
|
42
|
+
setWrapperHeight(height);
|
|
43
|
+
}
|
|
36
44
|
}, []);
|
|
37
|
-
const
|
|
45
|
+
const inputRef = useCallback((node) => {
|
|
38
46
|
if (node !== null) {
|
|
39
47
|
const { height } = measureElement(node);
|
|
40
|
-
|
|
48
|
+
setSelectInputHeight(height);
|
|
49
|
+
}
|
|
50
|
+
}, []);
|
|
51
|
+
useEffect(() => {
|
|
52
|
+
function onResize() {
|
|
53
|
+
const availableSpace = stdout.rows - (wrapperHeight - selectInputHeight);
|
|
54
|
+
// rough estimate of the limit needed based on the space available
|
|
55
|
+
const newLimit = Math.max(2, availableSpace - 6);
|
|
56
|
+
if (newLimit < limit) {
|
|
57
|
+
stdout.write(ansiEscapes.clearTerminal);
|
|
58
|
+
}
|
|
59
|
+
setLimit(Math.min(newLimit, searchResults.length));
|
|
41
60
|
}
|
|
42
|
-
|
|
43
|
-
|
|
61
|
+
onResize();
|
|
62
|
+
stdout.on('resize', onResize);
|
|
63
|
+
return () => {
|
|
64
|
+
stdout.off('resize', onResize);
|
|
65
|
+
};
|
|
66
|
+
}, [wrapperHeight, selectInputHeight, searchResults.length, stdout, limit]);
|
|
67
|
+
useInput((input, key) => {
|
|
44
68
|
handleCtrlC(input, key);
|
|
45
69
|
if (key.return && promptState === PromptState.Idle && answer) {
|
|
46
70
|
// -1 is for the last row with the terminal cursor
|
|
47
|
-
if (stdout &&
|
|
71
|
+
if (stdout && wrapperHeight >= stdout.rows - 1) {
|
|
48
72
|
stdout.write(ansiEscapes.clearTerminal);
|
|
49
73
|
}
|
|
50
74
|
setPromptState(PromptState.Submitted);
|
|
@@ -52,12 +76,14 @@ function AutocompletePrompt({ message, choices: initialChoices, infoTable, onSub
|
|
|
52
76
|
unmountInk();
|
|
53
77
|
onSubmit(answer.value);
|
|
54
78
|
}
|
|
55
|
-
}
|
|
79
|
+
});
|
|
56
80
|
const setLoadingWhenSlow = useRef();
|
|
57
81
|
// we want to set it each time so that searchTermRef always tracks searchTerm,
|
|
58
82
|
// this is NOT the same as writing useRef(searchTerm)
|
|
59
83
|
const searchTermRef = useRef('');
|
|
60
84
|
searchTermRef.current = searchTerm;
|
|
85
|
+
// disable exhaustive-deps because we want to memoize the debounce function itself
|
|
86
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
61
87
|
const debounceSearch = useCallback(debounce((term) => {
|
|
62
88
|
setLoadingWhenSlow.current = setTimeout(() => {
|
|
63
89
|
setPromptState(PromptState.Loading);
|
|
@@ -83,8 +109,8 @@ function AutocompletePrompt({ message, choices: initialChoices, infoTable, onSub
|
|
|
83
109
|
.finally(() => {
|
|
84
110
|
clearTimeout(setLoadingWhenSlow.current);
|
|
85
111
|
});
|
|
86
|
-
}, 300), []);
|
|
87
|
-
return (React.createElement(Box, { flexDirection: "column", marginBottom: 1, ref:
|
|
112
|
+
}, 300), [initialHasMorePages, paginatedInitialChoices, paginatedSearch]);
|
|
113
|
+
return (React.createElement(Box, { flexDirection: "column", marginBottom: 1, ref: wrapperRef },
|
|
88
114
|
React.createElement(Box, null,
|
|
89
115
|
React.createElement(Box, { marginRight: 2 },
|
|
90
116
|
React.createElement(Text, null, "?")),
|
|
@@ -111,7 +137,7 @@ function AutocompletePrompt({ message, choices: initialChoices, infoTable, onSub
|
|
|
111
137
|
setAnswer(item);
|
|
112
138
|
}, enableShortcuts: false, emptyMessage: "No results found.", highlightedTerm: searchTerm, loading: promptState === PromptState.Loading, errorMessage: promptState === PromptState.Error
|
|
113
139
|
? 'There has been an error while searching. Please try again later.'
|
|
114
|
-
: undefined, hasMorePages: hasMorePages, morePagesMessage: "Find what you're looking for by typing its name." })))));
|
|
140
|
+
: undefined, hasMorePages: hasMorePages, morePagesMessage: "Find what you're looking for by typing its name.", ref: inputRef, limit: limit })))));
|
|
115
141
|
}
|
|
116
142
|
export { AutocompletePrompt };
|
|
117
143
|
//# sourceMappingURL=AutocompletePrompt.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AutocompletePrompt.js","sourceRoot":"","sources":["../../../../../src/private/node/ui/components/AutocompletePrompt.tsx"],"names":[],"mappings":"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","sourcesContent":["import {SelectInput, SelectInputProps, Item as SelectItem} from './SelectInput.js'\nimport {InfoTable, InfoTableProps} from './Prompts/InfoTable.js'\nimport {TextInput} from './TextInput.js'\nimport {TokenizedText} from './TokenizedText.js'\nimport {handleCtrlC} from '../../ui.js'\nimport {messageWithPunctuation} from '../utilities.js'\nimport React, {ReactElement, useCallback, useRef, useState} from 'react'\nimport {Box, measureElement, Text, useApp, useInput, useStdout} from 'ink'\nimport figures from 'figures'\nimport {debounce} from '@shopify/cli-kit/common/function'\nimport ansiEscapes from 'ansi-escapes'\n\nexport interface SearchResults<T> {\n data: SelectItem<T>[]\n meta?: {\n hasNextPage: boolean\n }\n}\n\nexport interface AutocompletePromptProps<T> {\n message: string\n choices: SelectInputProps<T>['items']\n onSubmit: (value: T) => void\n infoTable?: InfoTableProps['table']\n hasMorePages?: boolean\n search: (term: string) => Promise<SearchResults<T>>\n}\n\nenum PromptState {\n Idle = 'idle',\n Loading = 'loading',\n Submitted = 'submitted',\n Error = 'error',\n}\n\nconst PAGE_SIZE = 25\n\n// eslint-disable-next-line react/function-component-definition\nfunction AutocompletePrompt<T>({\n message,\n choices: initialChoices,\n infoTable,\n onSubmit,\n search,\n hasMorePages: initialHasMorePages = false,\n}: React.PropsWithChildren<AutocompletePromptProps<T>>): ReactElement | null {\n const paginatedInitialChoices = initialChoices.slice(0, PAGE_SIZE)\n const [answer, setAnswer] = useState<SelectItem<T> | undefined>(paginatedInitialChoices[0])\n const {exit: unmountInk} = useApp()\n const [promptState, setPromptState] = useState<PromptState>(PromptState.Idle)\n const [searchTerm, setSearchTerm] = useState('')\n const [searchResults, setSearchResults] = useState<SelectItem<T>[]>(paginatedInitialChoices.slice(0, PAGE_SIZE))\n const {stdout} = useStdout()\n const [height, setHeight] = useState(0)\n const canSearch = initialChoices.length >= PAGE_SIZE\n const [hasMorePages, setHasMorePages] = useState(initialHasMorePages)\n\n const paginatedSearch = useCallback(async (term: string) => {\n const results = await search(term)\n results.data = results.data.slice(0, PAGE_SIZE)\n return results\n }, [])\n\n const measuredRef = useCallback(\n (node) => {\n if (node !== null) {\n const {height} = measureElement(node)\n setHeight(height)\n }\n },\n [searchResults, promptState],\n )\n\n useInput(\n useCallback(\n (input, key) => {\n handleCtrlC(input, key)\n\n if (key.return && promptState === PromptState.Idle && answer) {\n // -1 is for the last row with the terminal cursor\n if (stdout && height >= stdout.rows - 1) {\n stdout.write(ansiEscapes.clearTerminal)\n }\n setPromptState(PromptState.Submitted)\n setSearchTerm('')\n unmountInk()\n onSubmit(answer.value)\n }\n },\n [answer, onSubmit, height, promptState],\n ),\n )\n\n const setLoadingWhenSlow = useRef<NodeJS.Timeout>()\n\n // we want to set it each time so that searchTermRef always tracks searchTerm,\n // this is NOT the same as writing useRef(searchTerm)\n const searchTermRef = useRef('')\n searchTermRef.current = searchTerm\n\n const debounceSearch = useCallback(\n debounce((term) => {\n setLoadingWhenSlow.current = setTimeout(() => {\n setPromptState(PromptState.Loading)\n }, 100)\n paginatedSearch(term)\n .then((result) => {\n // while we were waiting for the promise to resolve, the user\n // has emptied the search term, so we want to show the default\n // choices instead\n if (searchTermRef.current.length === 0) {\n setSearchResults(paginatedInitialChoices)\n setHasMorePages(initialHasMorePages)\n } else {\n setSearchResults(result.data)\n setHasMorePages(result.meta?.hasNextPage ?? false)\n }\n\n setPromptState(PromptState.Idle)\n })\n .catch(() => {\n setPromptState(PromptState.Error)\n })\n .finally(() => {\n clearTimeout(setLoadingWhenSlow.current)\n })\n }, 300),\n [],\n )\n\n return (\n <Box flexDirection=\"column\" marginBottom={1} ref={measuredRef}>\n <Box>\n <Box marginRight={2}>\n <Text>?</Text>\n </Box>\n <TokenizedText item={messageWithPunctuation(message)} />\n {promptState !== PromptState.Submitted && canSearch ? (\n <Box marginLeft={3}>\n <TextInput\n value={searchTerm}\n onChange={(term) => {\n setSearchTerm(term)\n\n if (term.length > 0) {\n debounceSearch(term)\n } else {\n debounceSearch.cancel()\n setPromptState(PromptState.Idle)\n setSearchResults(paginatedInitialChoices)\n }\n }}\n placeholder=\"Type to search...\"\n />\n </Box>\n ) : null}\n </Box>\n\n {infoTable && promptState !== PromptState.Submitted ? (\n <Box marginLeft={7} marginTop={1}>\n <InfoTable table={infoTable} />\n </Box>\n ) : null}\n\n {promptState === PromptState.Submitted ? (\n <Box>\n <Box marginRight={2}>\n <Text color=\"cyan\">{figures.tick}</Text>\n </Box>\n\n <Text color=\"cyan\">{answer!.label}</Text>\n </Box>\n ) : (\n <Box marginTop={1}>\n <SelectInput\n items={searchResults}\n onChange={({item}) => {\n setAnswer(item)\n }}\n enableShortcuts={false}\n emptyMessage=\"No results found.\"\n highlightedTerm={searchTerm}\n loading={promptState === PromptState.Loading}\n errorMessage={\n promptState === PromptState.Error\n ? 'There has been an error while searching. Please try again later.'\n : undefined\n }\n hasMorePages={hasMorePages}\n morePagesMessage=\"Find what you're looking for by typing its name.\"\n />\n </Box>\n )}\n </Box>\n )\n}\n\nexport {AutocompletePrompt}\n"]}
|
|
1
|
+
{"version":3,"file":"AutocompletePrompt.js","sourceRoot":"","sources":["../../../../../src/private/node/ui/components/AutocompletePrompt.tsx"],"names":[],"mappings":"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","sourcesContent":["import {SelectInput, SelectInputProps, Item as SelectItem} from './SelectInput.js'\nimport {InfoTable, InfoTableProps} from './Prompts/InfoTable.js'\nimport {TextInput} from './TextInput.js'\nimport {TokenizedText} from './TokenizedText.js'\nimport {handleCtrlC} from '../../ui.js'\nimport {messageWithPunctuation} from '../utilities.js'\nimport {debounce} from '../../../../public/common/function.js'\nimport React, {ReactElement, useCallback, useEffect, useRef, useState} from 'react'\nimport {Box, measureElement, Text, useApp, useInput, useStdout} from 'ink'\nimport figures from 'figures'\nimport ansiEscapes from 'ansi-escapes'\n\nexport interface SearchResults<T> {\n data: SelectItem<T>[]\n meta?: {\n hasNextPage: boolean\n }\n}\n\nexport interface AutocompletePromptProps<T> {\n message: string\n choices: SelectInputProps<T>['items']\n onSubmit: (value: T) => void\n infoTable?: InfoTableProps['table']\n hasMorePages?: boolean\n search: (term: string) => Promise<SearchResults<T>>\n}\n\nenum PromptState {\n Idle = 'idle',\n Loading = 'loading',\n Submitted = 'submitted',\n Error = 'error',\n}\n\nconst PAGE_SIZE = 25\n\n// eslint-disable-next-line react/function-component-definition\nfunction AutocompletePrompt<T>({\n message,\n choices: initialChoices,\n infoTable,\n onSubmit,\n search,\n hasMorePages: initialHasMorePages = false,\n}: React.PropsWithChildren<AutocompletePromptProps<T>>): ReactElement | null {\n const paginatedInitialChoices = initialChoices.slice(0, PAGE_SIZE)\n const [answer, setAnswer] = useState<SelectItem<T> | undefined>(paginatedInitialChoices[0])\n const {exit: unmountInk} = useApp()\n const [promptState, setPromptState] = useState<PromptState>(PromptState.Idle)\n const [searchTerm, setSearchTerm] = useState('')\n const [searchResults, setSearchResults] = useState<SelectItem<T>[]>(paginatedInitialChoices.slice(0, PAGE_SIZE))\n const {stdout} = useStdout()\n const canSearch = initialChoices.length >= PAGE_SIZE\n const [hasMorePages, setHasMorePages] = useState(initialHasMorePages)\n const [wrapperHeight, setWrapperHeight] = useState(0)\n const [selectInputHeight, setSelectInputHeight] = useState(0)\n const [limit, setLimit] = useState(searchResults.length)\n\n const paginatedSearch = useCallback(\n async (term: string) => {\n const results = await search(term)\n results.data = results.data.slice(0, PAGE_SIZE)\n return results\n },\n [search],\n )\n\n const wrapperRef = useCallback((node) => {\n if (node !== null) {\n const {height} = measureElement(node)\n setWrapperHeight(height)\n }\n }, [])\n\n const inputRef = useCallback((node) => {\n if (node !== null) {\n const {height} = measureElement(node)\n setSelectInputHeight(height)\n }\n }, [])\n\n useEffect(() => {\n function onResize() {\n const availableSpace = stdout!.rows - (wrapperHeight - selectInputHeight)\n // rough estimate of the limit needed based on the space available\n const newLimit = Math.max(2, availableSpace - 6)\n\n if (newLimit < limit) {\n stdout!.write(ansiEscapes.clearTerminal)\n }\n\n setLimit(Math.min(newLimit, searchResults.length))\n }\n\n onResize()\n\n stdout!.on('resize', onResize)\n return () => {\n stdout!.off('resize', onResize)\n }\n }, [wrapperHeight, selectInputHeight, searchResults.length, stdout, limit])\n\n useInput((input, key) => {\n handleCtrlC(input, key)\n\n if (key.return && promptState === PromptState.Idle && answer) {\n // -1 is for the last row with the terminal cursor\n if (stdout && wrapperHeight >= stdout.rows - 1) {\n stdout.write(ansiEscapes.clearTerminal)\n }\n setPromptState(PromptState.Submitted)\n setSearchTerm('')\n unmountInk()\n onSubmit(answer.value)\n }\n })\n\n const setLoadingWhenSlow = useRef<NodeJS.Timeout>()\n\n // we want to set it each time so that searchTermRef always tracks searchTerm,\n // this is NOT the same as writing useRef(searchTerm)\n const searchTermRef = useRef('')\n searchTermRef.current = searchTerm\n\n // disable exhaustive-deps because we want to memoize the debounce function itself\n // eslint-disable-next-line react-hooks/exhaustive-deps\n const debounceSearch = useCallback(\n debounce((term: string) => {\n setLoadingWhenSlow.current = setTimeout(() => {\n setPromptState(PromptState.Loading)\n }, 100)\n paginatedSearch(term)\n .then((result) => {\n // while we were waiting for the promise to resolve, the user\n // has emptied the search term, so we want to show the default\n // choices instead\n if (searchTermRef.current.length === 0) {\n setSearchResults(paginatedInitialChoices)\n setHasMorePages(initialHasMorePages)\n } else {\n setSearchResults(result.data)\n setHasMorePages(result.meta?.hasNextPage ?? false)\n }\n\n setPromptState(PromptState.Idle)\n })\n .catch(() => {\n setPromptState(PromptState.Error)\n })\n .finally(() => {\n clearTimeout(setLoadingWhenSlow.current)\n })\n }, 300),\n [initialHasMorePages, paginatedInitialChoices, paginatedSearch],\n )\n\n return (\n <Box flexDirection=\"column\" marginBottom={1} ref={wrapperRef}>\n <Box>\n <Box marginRight={2}>\n <Text>?</Text>\n </Box>\n <TokenizedText item={messageWithPunctuation(message)} />\n {promptState !== PromptState.Submitted && canSearch ? (\n <Box marginLeft={3}>\n <TextInput\n value={searchTerm}\n onChange={(term) => {\n setSearchTerm(term)\n\n if (term.length > 0) {\n debounceSearch(term)\n } else {\n debounceSearch.cancel()\n setPromptState(PromptState.Idle)\n setSearchResults(paginatedInitialChoices)\n }\n }}\n placeholder=\"Type to search...\"\n />\n </Box>\n ) : null}\n </Box>\n\n {infoTable && promptState !== PromptState.Submitted ? (\n <Box marginLeft={7} marginTop={1}>\n <InfoTable table={infoTable} />\n </Box>\n ) : null}\n\n {promptState === PromptState.Submitted ? (\n <Box>\n <Box marginRight={2}>\n <Text color=\"cyan\">{figures.tick}</Text>\n </Box>\n\n <Text color=\"cyan\">{answer!.label}</Text>\n </Box>\n ) : (\n <Box marginTop={1}>\n <SelectInput\n items={searchResults}\n onChange={({item}) => {\n setAnswer(item)\n }}\n enableShortcuts={false}\n emptyMessage=\"No results found.\"\n highlightedTerm={searchTerm}\n loading={promptState === PromptState.Loading}\n errorMessage={\n promptState === PromptState.Error\n ? 'There has been an error while searching. Please try again later.'\n : undefined\n }\n hasMorePages={hasMorePages}\n morePagesMessage=\"Find what you're looking for by typing its name.\"\n ref={inputRef}\n limit={limit}\n />\n </Box>\n )}\n </Box>\n )\n}\n\nexport {AutocompletePrompt}\n"]}
|
|
@@ -1,8 +1,18 @@
|
|
|
1
1
|
import { AutocompletePrompt } from './AutocompletePrompt.js';
|
|
2
|
-
import { getLastFrameAfterUnmount, sendInputAndWait, sendInputAndWaitForChange, sendInputAndWaitForContent,
|
|
3
|
-
import {
|
|
2
|
+
import { getLastFrameAfterUnmount, sendInputAndWait, sendInputAndWaitForChange, sendInputAndWaitForContent, waitForInputsToBeReady, } from '../../testing/ui.js';
|
|
3
|
+
import { OutputStream } from '../../ui.js';
|
|
4
|
+
import { beforeEach, describe, expect, test, vi } from 'vitest';
|
|
4
5
|
import React from 'react';
|
|
5
6
|
import { render } from 'ink-testing-library';
|
|
7
|
+
import { useStdout } from 'ink';
|
|
8
|
+
vi.mock('ink', async () => {
|
|
9
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
10
|
+
const original = await vi.importActual('ink');
|
|
11
|
+
return {
|
|
12
|
+
...original,
|
|
13
|
+
useStdout: vi.fn(),
|
|
14
|
+
};
|
|
15
|
+
});
|
|
6
16
|
const ARROW_DOWN = '\u001B[B';
|
|
7
17
|
const ENTER = '\r';
|
|
8
18
|
const DELETE = '\u007F';
|
|
@@ -58,6 +68,16 @@ const DATABASE = [
|
|
|
58
68
|
{ label: 'forty-ninth', value: 'forty-ninth' },
|
|
59
69
|
{ label: 'fiftieth', value: 'fiftieth' },
|
|
60
70
|
];
|
|
71
|
+
beforeEach(() => {
|
|
72
|
+
vi.mocked(useStdout).mockReturnValue({
|
|
73
|
+
stdout: new OutputStream({
|
|
74
|
+
columns: 80,
|
|
75
|
+
rows: 80,
|
|
76
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
77
|
+
}),
|
|
78
|
+
write: () => { },
|
|
79
|
+
});
|
|
80
|
+
});
|
|
61
81
|
describe('AutocompletePrompt', async () => {
|
|
62
82
|
test('choose an answer', async () => {
|
|
63
83
|
const onEnter = vi.fn();
|
|
@@ -160,8 +180,9 @@ describe('AutocompletePrompt', async () => {
|
|
|
160
180
|
await waitForInputsToBeReady();
|
|
161
181
|
await sendInputAndWaitForContent(renderInstance, 'No results found', 'a');
|
|
162
182
|
// prompt doesn't change when enter is pressed
|
|
183
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
163
184
|
await sendInputAndWait(renderInstance, 100, ENTER);
|
|
164
|
-
expect(
|
|
185
|
+
expect(renderInstance.lastFrame()).toMatchInlineSnapshot(`
|
|
165
186
|
"? Associate your project with the org Castile Ventures? [36ma[7m [27m[39m
|
|
166
187
|
|
|
167
188
|
[2mNo results found.[22m
|
|
@@ -181,8 +202,9 @@ describe('AutocompletePrompt', async () => {
|
|
|
181
202
|
await waitForInputsToBeReady();
|
|
182
203
|
await sendInputAndWaitForContent(renderInstance, 'Loading...', 'a');
|
|
183
204
|
// prompt doesn't change when enter is pressed
|
|
205
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
184
206
|
await sendInputAndWait(renderInstance, 100, ENTER);
|
|
185
|
-
expect(
|
|
207
|
+
expect(renderInstance.lastFrame()).toMatchInlineSnapshot(`
|
|
186
208
|
"? Associate your project with the org Castile Ventures? [36ma[7m [27m[39m
|
|
187
209
|
|
|
188
210
|
[2mLoading...[22m
|
|
@@ -340,46 +362,21 @@ describe('AutocompletePrompt', async () => {
|
|
|
340
362
|
`);
|
|
341
363
|
expect(onEnter).toHaveBeenCalledWith('fifth');
|
|
342
364
|
});
|
|
343
|
-
test('allows selecting the first item after searching
|
|
365
|
+
test('allows selecting the first item after searching', async () => {
|
|
344
366
|
const onEnter = vi.fn();
|
|
345
367
|
const search = async (term) => {
|
|
346
|
-
await new Promise((resolve) => setTimeout(resolve,
|
|
368
|
+
await new Promise((resolve) => setTimeout(resolve, 300));
|
|
347
369
|
return {
|
|
348
370
|
data: DATABASE.filter((item) => item.label.includes(term)),
|
|
349
371
|
};
|
|
350
372
|
};
|
|
351
373
|
const renderInstance = render(React.createElement(AutocompletePrompt, { message: "Associate your project with the org Castile Ventures?", choices: DATABASE, onSubmit: onEnter, search: search }));
|
|
352
374
|
await waitForInputsToBeReady();
|
|
353
|
-
await sendInputAndWaitForContent(renderInstance, '
|
|
354
|
-
await waitForContent(renderInstance, 'Press ↑↓ arrows to select, enter to confirm');
|
|
375
|
+
await sendInputAndWaitForContent(renderInstance, '[1mfiftieth[22m', 'fiftieth');
|
|
355
376
|
expect(renderInstance.lastFrame()).toMatchInlineSnapshot(`
|
|
356
|
-
"? Associate your project with the org Castile Ventures? [
|
|
377
|
+
"? Associate your project with the org Castile Ventures? [36mfiftieth[7m [27m[39m
|
|
357
378
|
|
|
358
|
-
[36m>[39m [
|
|
359
|
-
s[1me[22mventh
|
|
360
|
-
[1me[22mighth
|
|
361
|
-
t[1me[22mnth
|
|
362
|
-
[1me[22mleventh
|
|
363
|
-
tw[1me[22mlfth
|
|
364
|
-
thirt[1me[22menth
|
|
365
|
-
fourt[1me[22menth
|
|
366
|
-
fift[1me[22menth
|
|
367
|
-
sixt[1me[22menth
|
|
368
|
-
s[1me[22mventeenth
|
|
369
|
-
[1me[22mighteenth
|
|
370
|
-
nin[1me[22mteenth
|
|
371
|
-
tw[1me[22mntieth
|
|
372
|
-
tw[1me[22mnty-first
|
|
373
|
-
tw[1me[22mnty-second
|
|
374
|
-
tw[1me[22mnty-third
|
|
375
|
-
tw[1me[22mnty-fourth
|
|
376
|
-
tw[1me[22mnty-fifth
|
|
377
|
-
tw[1me[22mnty-sixth
|
|
378
|
-
tw[1me[22mnty-seventh
|
|
379
|
-
tw[1me[22mnty-eighth
|
|
380
|
-
tw[1me[22mnty-ninth
|
|
381
|
-
thirti[1me[22mth
|
|
382
|
-
thirty-s[1me[22mcond
|
|
379
|
+
[36m>[39m [36m[1mfiftieth[22m[39m
|
|
383
380
|
|
|
384
381
|
[2mPress ↑↓ arrows to select, enter to confirm[22m
|
|
385
382
|
"
|
|
@@ -387,10 +384,10 @@ describe('AutocompletePrompt', async () => {
|
|
|
387
384
|
await sendInputAndWaitForChange(renderInstance, ENTER);
|
|
388
385
|
expect(getLastFrameAfterUnmount(renderInstance)).toMatchInlineSnapshot(`
|
|
389
386
|
"? Associate your project with the org Castile Ventures?
|
|
390
|
-
[36m✔[39m [
|
|
387
|
+
[36m✔[39m [36mfiftieth[39m
|
|
391
388
|
"
|
|
392
389
|
`);
|
|
393
|
-
expect(onEnter).toHaveBeenCalledWith('
|
|
390
|
+
expect(onEnter).toHaveBeenCalledWith('fiftieth');
|
|
394
391
|
});
|
|
395
392
|
test('displays an error message if the search fails', async () => {
|
|
396
393
|
const search = (_term) => {
|
|
@@ -523,5 +520,28 @@ describe('AutocompletePrompt', async () => {
|
|
|
523
520
|
"
|
|
524
521
|
`);
|
|
525
522
|
});
|
|
523
|
+
test('adapts to the height of the container', async () => {
|
|
524
|
+
vi.mocked(useStdout).mockReturnValue({
|
|
525
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
526
|
+
stdout: new OutputStream({ rows: 10 }),
|
|
527
|
+
write: () => { },
|
|
528
|
+
});
|
|
529
|
+
const renderInstance = render(React.createElement(AutocompletePrompt, { message: "Associate your project with the org Castile Ventures?", choices: DATABASE, onSubmit: () => { }, hasMorePages: true, search: () => Promise.resolve({
|
|
530
|
+
data: DATABASE,
|
|
531
|
+
}) }));
|
|
532
|
+
expect(renderInstance.lastFrame()).toMatchInlineSnapshot(`
|
|
533
|
+
"? Associate your project with the org Castile Ventures? [36m[7mT[27m[2mype to search...[22m[39m
|
|
534
|
+
|
|
535
|
+
[36m>[39m [36mfirst[39m
|
|
536
|
+
second
|
|
537
|
+
third
|
|
538
|
+
fourth
|
|
539
|
+
|
|
540
|
+
[1m1-25 of many[22m Find what you're looking for by typing its name.
|
|
541
|
+
[2mShowing 4 of 25 items.[22m
|
|
542
|
+
[2mPress ↑↓ arrows to select, enter to confirm[22m
|
|
543
|
+
"
|
|
544
|
+
`);
|
|
545
|
+
});
|
|
526
546
|
});
|
|
527
547
|
//# sourceMappingURL=AutocompletePrompt.test.js.map
|
|
@@ -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 waitForContent,\n waitForInputsToBeReady,\n} from '../../testing/ui.js'\nimport {describe, expect, test, vi} from 'vitest'\nimport React from 'react'\nimport {render} from 'ink-testing-library'\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\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(getLastFrameAfterUnmount(renderInstance)).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 const searchPromise = new Promise<SearchResults<string>>((resolve) => {\n setTimeout(() => resolve({data: [{label: 'a', value: 'b'}]}), 2000)\n })\n\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, 'Loading...', 'a')\n // prompt doesn't change when enter is pressed\n await sendInputAndWait(renderInstance, 100, ENTER)\n\n expect(getLastFrameAfterUnmount(renderInstance)).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 and triggering the loading state', async () => {\n const onEnter = vi.fn()\n\n const search = async (term: string) => {\n await new Promise((resolve) => setTimeout(resolve, 500))\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, 'Loading...', 'e')\n await waitForContent(renderInstance, 'Press ↑↓ arrows to select, enter to confirm')\n\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot(`\n \"? Associate your project with the org Castile Ventures? \u001b[36me\u001b[7m \u001b[27m\u001b[39m\n\n \u001b[36m>\u001b[39m \u001b[36ms\u001b[1me\u001b[22mcond\u001b[39m\n s\u001b[1me\u001b[22mventh\n \u001b[1me\u001b[22mighth\n t\u001b[1me\u001b[22mnth\n \u001b[1me\u001b[22mleventh\n tw\u001b[1me\u001b[22mlfth\n thirt\u001b[1me\u001b[22menth\n fourt\u001b[1me\u001b[22menth\n fift\u001b[1me\u001b[22menth\n sixt\u001b[1me\u001b[22menth\n s\u001b[1me\u001b[22mventeenth\n \u001b[1me\u001b[22mighteenth\n nin\u001b[1me\u001b[22mteenth\n tw\u001b[1me\u001b[22mntieth\n tw\u001b[1me\u001b[22mnty-first\n tw\u001b[1me\u001b[22mnty-second\n tw\u001b[1me\u001b[22mnty-third\n tw\u001b[1me\u001b[22mnty-fourth\n tw\u001b[1me\u001b[22mnty-fifth\n tw\u001b[1me\u001b[22mnty-sixth\n tw\u001b[1me\u001b[22mnty-seventh\n tw\u001b[1me\u001b[22mnty-eighth\n tw\u001b[1me\u001b[22mnty-ninth\n thirti\u001b[1me\u001b[22mth\n thirty-s\u001b[1me\u001b[22mcond\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[36msecond\u001b[39m\n \"\n `)\n\n expect(onEnter).toHaveBeenCalledWith('second')\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"]}
|
|
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} from '../../testing/ui.js'\nimport {OutputStream} from '../../ui.js'\nimport {beforeEach, describe, expect, test, vi} from 'vitest'\nimport React from 'react'\nimport {render} from 'ink-testing-library'\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 OutputStream({\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 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[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 const searchPromise = new Promise<SearchResults<string>>((resolve) => {\n setTimeout(() => resolve({data: [{label: 'a', value: 'b'}]}), 2000)\n })\n\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, '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 OutputStream({rows: 10}) as any,\n write: () => {},\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={() =>\n Promise.resolve({\n data: DATABASE,\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[36m>\u001b[39m \u001b[36mfirst\u001b[39m\n second\n third\n fourth\n\n \u001b[1m1-25 of many\u001b[22m Find what you're looking for by typing its name.\n \u001b[2mShowing 4 of 25 items.\u001b[22m\n \u001b[2mPress ↑↓ arrows to select, enter to confirm\u001b[22m\n \"\n `)\n })\n})\n"]}
|
|
@@ -5,13 +5,17 @@ import { FunctionComponent } from 'react';
|
|
|
5
5
|
import { Key } from 'ink';
|
|
6
6
|
import { Writable } from 'stream';
|
|
7
7
|
export type WritableStream = (process: OutputProcess, index: number) => Writable;
|
|
8
|
+
interface Shortcut {
|
|
9
|
+
key: string;
|
|
10
|
+
action: string;
|
|
11
|
+
}
|
|
8
12
|
export interface ConcurrentOutputProps {
|
|
9
13
|
processes: OutputProcess[];
|
|
10
14
|
abortController: AbortController;
|
|
11
15
|
showTimestamps?: boolean;
|
|
12
16
|
onInput?: (input: string, key: Key, exit: () => void) => void;
|
|
13
17
|
footer?: {
|
|
14
|
-
|
|
18
|
+
shortcuts: Shortcut[];
|
|
15
19
|
subTitle?: string;
|
|
16
20
|
};
|
|
17
21
|
}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { TextWithBackground } from './TextWithBackground.js';
|
|
2
1
|
import useAsyncAndUnmount from '../hooks/use-async-and-unmount.js';
|
|
3
2
|
import { handleCtrlC } from '../../ui.js';
|
|
4
|
-
import React, {
|
|
3
|
+
import React, { useState } from 'react';
|
|
5
4
|
import { Box, Static, Text, useInput } from 'ink';
|
|
6
5
|
import stripAnsi from 'strip-ansi';
|
|
7
6
|
import treeKill from 'tree-kill';
|
|
7
|
+
import figures from 'figures';
|
|
8
8
|
import { Writable } from 'stream';
|
|
9
9
|
/**
|
|
10
10
|
* Renders output from concurrent processes to the terminal.
|
|
@@ -50,7 +50,7 @@ const ConcurrentOutput = ({ processes, abortController, showTimestamps = true, o
|
|
|
50
50
|
const writableStream = (process, index) => {
|
|
51
51
|
return new Writable({
|
|
52
52
|
write(chunk, _encoding, next) {
|
|
53
|
-
const lines = stripAnsi(chunk.toString('
|
|
53
|
+
const lines = stripAnsi(chunk.toString('utf8').replace(/(\n)$/, '')).split(/\n/);
|
|
54
54
|
setProcessOutput((previousProcessOutput) => [
|
|
55
55
|
...previousProcessOutput,
|
|
56
56
|
{
|
|
@@ -70,12 +70,10 @@ const ConcurrentOutput = ({ processes, abortController, showTimestamps = true, o
|
|
|
70
70
|
await process.action(stdout, stderr, abortController.signal);
|
|
71
71
|
}));
|
|
72
72
|
};
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
}, [onInput]));
|
|
78
|
-
}
|
|
73
|
+
useInput((input, key) => {
|
|
74
|
+
handleCtrlC(input, key);
|
|
75
|
+
onInput(input, key, () => treeKill(process.pid, 'SIGINT'));
|
|
76
|
+
}, { isActive: typeof onInput !== 'undefined' });
|
|
79
77
|
useAsyncAndUnmount(runProcesses, { onRejected: () => abortController.abort() });
|
|
80
78
|
return (React.createElement(React.Fragment, null,
|
|
81
79
|
React.createElement(Static, { items: processOutput }, (chunk, index) => {
|
|
@@ -90,10 +88,14 @@ const ConcurrentOutput = ({ processes, abortController, showTimestamps = true, o
|
|
|
90
88
|
React.createElement(Box, { flexGrow: 1, paddingLeft: 1 },
|
|
91
89
|
React.createElement(Text, { color: chunk.color }, line)))))));
|
|
92
90
|
}),
|
|
93
|
-
footer ? (React.createElement(Box, { marginY: 1, flexDirection: "column" },
|
|
94
|
-
React.createElement(Box, {
|
|
95
|
-
|
|
96
|
-
|
|
91
|
+
footer ? (React.createElement(Box, { marginY: 1, flexDirection: "column", flexGrow: 1 },
|
|
92
|
+
React.createElement(Box, { flexDirection: "column" }, footer.shortcuts.map((shortcut, index) => (React.createElement(Text, { key: index },
|
|
93
|
+
figures.pointerSmall,
|
|
94
|
+
" Press ",
|
|
95
|
+
React.createElement(Text, { bold: true }, shortcut.key),
|
|
96
|
+
" | ",
|
|
97
|
+
shortcut.action)))),
|
|
98
|
+
footer.subTitle ? (React.createElement(Box, { marginTop: 1 },
|
|
97
99
|
React.createElement(Text, null, footer.subTitle))) : null)) : null));
|
|
98
100
|
};
|
|
99
101
|
export { ConcurrentOutput };
|