[READ-ONLY] Mirror of https://github.com/bombshell-dev/clack. Effortlessly build beautiful command-line apps bomb.sh/docs/clack/basics/getting-started/
cli command-line command-line-app node prompt prompts
5

Configure Feed

Select the types of activity you want to include in your feed.

test: add tests for group multiselect (#275)

authored by

James Garbutt and committed by
GitHub
(Apr 6, 2025, 5:02 PM +0100) 3ec796ed 85c885d8

+1148
+866
packages/prompts/src/__snapshots__/index.test.ts.snap
··· 149 149 ] 150 150 `; 151 151 152 + exports[`prompts (isCI = false) > groupMultiselect > can deselect an option 1`] = ` 153 + [ 154 + "[?25l", 155 + "│ 156 + ◆ foo 157 + │ ◻ group1 158 + │ │ ◻ group1value0 159 + │ └ ◻ group1value1 160 + └ 161 + ", 162 + "", 163 + "", 164 + "", 165 + "│ ◻ group1 166 + │ │ ◻ group1value0 167 + │ └ ◻ group1value1 168 + └ 169 + ", 170 + "", 171 + "", 172 + "", 173 + "│ │ ◼ group1value0", 174 + "", 175 + "", 176 + "", 177 + "", 178 + "│ │ ◼ group1value0 179 + │ └ ◻ group1value1 180 + └ 181 + ", 182 + "", 183 + "", 184 + "", 185 + "│ ◼ group1 186 + │ │ ◼ group1value0 187 + │ └ ◼ group1value1 188 + └ 189 + ", 190 + "", 191 + "", 192 + "", 193 + "│ ◻ group1 194 + │ │ ◼ group1value0 195 + │ └ ◻ group1value1 196 + └ 197 + ", 198 + "", 199 + "", 200 + "", 201 + "◇ foo 202 + │ group1value0", 203 + " 204 + ", 205 + "[?25h", 206 + ] 207 + `; 208 + 209 + exports[`prompts (isCI = false) > groupMultiselect > can select a group 1`] = ` 210 + [ 211 + "[?25l", 212 + "│ 213 + ◆ foo 214 + │ ◻ group1 215 + │ │ ◻ group1value0 216 + │ └ ◻ group1value1 217 + └ 218 + ", 219 + "", 220 + "", 221 + "", 222 + "│ ◼ group1 223 + │ │ ◼ group1value0 224 + │ └ ◼ group1value1 225 + └ 226 + ", 227 + "", 228 + "", 229 + "", 230 + "◇ foo 231 + │ group1value0, group1value1", 232 + " 233 + ", 234 + "[?25h", 235 + ] 236 + `; 237 + 238 + exports[`prompts (isCI = false) > groupMultiselect > can select a group by selecting all members 1`] = ` 239 + [ 240 + "[?25l", 241 + "│ 242 + ◆ foo 243 + │ ◻ group1 244 + │ │ ◻ group1value0 245 + │ └ ◻ group1value1 246 + └ 247 + ", 248 + "", 249 + "", 250 + "", 251 + "│ ◻ group1 252 + │ │ ◻ group1value0 253 + │ └ ◻ group1value1 254 + └ 255 + ", 256 + "", 257 + "", 258 + "", 259 + "│ │ ◼ group1value0", 260 + "", 261 + "", 262 + "", 263 + "", 264 + "│ │ ◼ group1value0 265 + │ └ ◻ group1value1 266 + └ 267 + ", 268 + "", 269 + "", 270 + "", 271 + "│ ◼ group1 272 + │ │ ◼ group1value0 273 + │ └ ◼ group1value1 274 + └ 275 + ", 276 + "", 277 + "", 278 + "", 279 + "◇ foo 280 + │ group1value0, group1value1", 281 + " 282 + ", 283 + "[?25h", 284 + ] 285 + `; 286 + 287 + exports[`prompts (isCI = false) > groupMultiselect > can select multiple options 1`] = ` 288 + [ 289 + "[?25l", 290 + "│ 291 + ◆ foo 292 + │ ◻ group1 293 + │ │ ◻ group1value0 294 + │ │ ◻ group1value1 295 + │ └ ◻ group1value2 296 + └ 297 + ", 298 + "", 299 + "", 300 + "", 301 + "│ ◻ group1 302 + │ │ ◻ group1value0 303 + │ │ ◻ group1value1 304 + │ └ ◻ group1value2 305 + └ 306 + ", 307 + "", 308 + "", 309 + "", 310 + "│ │ ◼ group1value0", 311 + "", 312 + "", 313 + "", 314 + "", 315 + "│ │ ◼ group1value0 316 + │ │ ◻ group1value1 317 + │ └ ◻ group1value2 318 + └ 319 + ", 320 + "", 321 + "", 322 + "", 323 + "│ │ ◼ group1value1", 324 + "", 325 + "", 326 + "", 327 + "", 328 + "◇ foo 329 + │ group1value0, group1value1", 330 + " 331 + ", 332 + "[?25h", 333 + ] 334 + `; 335 + 336 + exports[`prompts (isCI = false) > groupMultiselect > can submit empty selection when require = false 1`] = ` 337 + [ 338 + "[?25l", 339 + "│ 340 + ◆ foo 341 + │ ◻ group1 342 + │ │ ◻ group1value0 343 + │ └ ◻ group1value1 344 + └ 345 + ", 346 + "", 347 + "", 348 + "", 349 + "◇ foo 350 + │", 351 + " 352 + ", 353 + "[?25h", 354 + ] 355 + `; 356 + 357 + exports[`prompts (isCI = false) > groupMultiselect > cursorAt sets initial selection 1`] = ` 358 + [ 359 + "[?25l", 360 + "│ 361 + ◆ foo 362 + │ ◻ group1 363 + │ │ ◻ group1value0 364 + │ └ ◻ group1value1 365 + └ 366 + ", 367 + "", 368 + "", 369 + "", 370 + "│ └ ◼ group1value1", 371 + "", 372 + "", 373 + "", 374 + "", 375 + "◇ foo 376 + │ group1value1", 377 + " 378 + ", 379 + "[?25h", 380 + ] 381 + `; 382 + 383 + exports[`prompts (isCI = false) > groupMultiselect > initial values can be set 1`] = ` 384 + [ 385 + "[?25l", 386 + "│ 387 + ◆ foo 388 + │ ◻ group1 389 + │ │ ◻ group1value0 390 + │ └ ◼ group1value1 391 + └ 392 + ", 393 + "", 394 + "", 395 + "", 396 + "◇ foo 397 + │ group1value1", 398 + " 399 + ", 400 + "[?25h", 401 + ] 402 + `; 403 + 404 + exports[`prompts (isCI = false) > groupMultiselect > renders error when nothing selected 1`] = ` 405 + [ 406 + "[?25l", 407 + "│ 408 + ◆ foo 409 + │ ◻ group1 410 + │ │ ◻ group1value0 411 + │ └ ◻ group1value1 412 + └ 413 + ", 414 + "", 415 + "", 416 + "", 417 + "▲ foo 418 + │ ◻ group1 419 + │ │ ◻ group1value0 420 + │ └ ◻ group1value1 421 + └ Please select at least one option. 422 + Press  space  to select,  enter  to submit 423 + ", 424 + "", 425 + "", 426 + "", 427 + "◆ foo 428 + │ ◻ group1 429 + │ │ ◻ group1value0 430 + │ └ ◻ group1value1 431 + └ 432 + ", 433 + "", 434 + "", 435 + "", 436 + "│ │ ◼ group1value0", 437 + "", 438 + "", 439 + "", 440 + "", 441 + "◇ foo 442 + │ group1value0", 443 + " 444 + ", 445 + "[?25h", 446 + ] 447 + `; 448 + 449 + exports[`prompts (isCI = false) > groupMultiselect > renders message with options 1`] = ` 450 + [ 451 + "[?25l", 452 + "│ 453 + ◆ foo 454 + │ ◻ group1 455 + │ │ ◻ group1value0 456 + │ └ ◻ group1value1 457 + │ ◻ group2 458 + │ └ ◻ group2value0 459 + └ 460 + ", 461 + "", 462 + "", 463 + "", 464 + "│ ◻ group1 465 + │ │ ◻ group1value0 466 + │ └ ◻ group1value1 467 + │ ◻ group2 468 + │ └ ◻ group2value0 469 + └ 470 + ", 471 + "", 472 + "", 473 + "", 474 + "│ │ ◼ group1value0", 475 + "", 476 + "", 477 + "", 478 + "", 479 + "◇ foo 480 + │ group1value0", 481 + " 482 + ", 483 + "[?25h", 484 + ] 485 + `; 486 + 487 + exports[`prompts (isCI = false) > groupMultiselect > selectableGroups = false > cannot select groups 1`] = ` 488 + [ 489 + "[?25l", 490 + "│ 491 + ◆ foo 492 + │  group1 493 + │  ◻ group1value0 494 + │  ◻ group1value1 495 + └ 496 + ", 497 + "", 498 + "", 499 + "", 500 + "│  ◼ group1value0", 501 + "", 502 + "", 503 + "", 504 + "", 505 + "◇ foo 506 + │ group1value0", 507 + " 508 + ", 509 + "[?25h", 510 + ] 511 + `; 512 + 513 + exports[`prompts (isCI = false) > groupMultiselect > selectableGroups = false > selecting all members of group does not select group 1`] = ` 514 + [ 515 + "[?25l", 516 + "│ 517 + ◆ foo 518 + │  group1 519 + │  ◻ group1value0 520 + │  ◻ group1value1 521 + └ 522 + ", 523 + "", 524 + "", 525 + "", 526 + "│  ◼ group1value0", 527 + "", 528 + "", 529 + "", 530 + "", 531 + "│  ◼ group1value0 532 + │  ◻ group1value1 533 + └ 534 + ", 535 + "", 536 + "", 537 + "", 538 + "│  ◼ group1value1", 539 + "", 540 + "", 541 + "", 542 + "", 543 + "◇ foo 544 + │ group1value0, group1value1", 545 + " 546 + ", 547 + "[?25h", 548 + ] 549 + `; 550 + 551 + exports[`prompts (isCI = false) > groupMultiselect > values can be non-primitive 1`] = ` 552 + [ 553 + "[?25l", 554 + "│ 555 + ◆ foo 556 + │ ◻ group1 557 + │ │ ◻ value0 558 + │ └ ◻ value1 559 + └ 560 + ", 561 + "", 562 + "", 563 + "", 564 + "│ ◻ group1 565 + │ │ ◻ value0 566 + │ └ ◻ value1 567 + └ 568 + ", 569 + "", 570 + "", 571 + "", 572 + "│ │ ◼ value0", 573 + "", 574 + "", 575 + "", 576 + "", 577 + "◇ foo 578 + │ value0", 579 + " 580 + ", 581 + "[?25h", 582 + ] 583 + `; 584 + 152 585 exports[`prompts (isCI = false) > multiselect > can cancel 1`] = ` 153 586 [ 154 587 "[?25l", ··· 1448 1881 "", 1449 1882 "◇ foo 1450 1883 │ No", 1884 + " 1885 + ", 1886 + "[?25h", 1887 + ] 1888 + `; 1889 + 1890 + exports[`prompts (isCI = true) > groupMultiselect > can deselect an option 1`] = ` 1891 + [ 1892 + "[?25l", 1893 + "│ 1894 + ◆ foo 1895 + │ ◻ group1 1896 + │ │ ◻ group1value0 1897 + │ └ ◻ group1value1 1898 + └ 1899 + ", 1900 + "", 1901 + "", 1902 + "", 1903 + "│ ◻ group1 1904 + │ │ ◻ group1value0 1905 + │ └ ◻ group1value1 1906 + └ 1907 + ", 1908 + "", 1909 + "", 1910 + "", 1911 + "│ │ ◼ group1value0", 1912 + "", 1913 + "", 1914 + "", 1915 + "", 1916 + "│ │ ◼ group1value0 1917 + │ └ ◻ group1value1 1918 + └ 1919 + ", 1920 + "", 1921 + "", 1922 + "", 1923 + "│ ◼ group1 1924 + │ │ ◼ group1value0 1925 + │ └ ◼ group1value1 1926 + └ 1927 + ", 1928 + "", 1929 + "", 1930 + "", 1931 + "│ ◻ group1 1932 + │ │ ◼ group1value0 1933 + │ └ ◻ group1value1 1934 + └ 1935 + ", 1936 + "", 1937 + "", 1938 + "", 1939 + "◇ foo 1940 + │ group1value0", 1941 + " 1942 + ", 1943 + "[?25h", 1944 + ] 1945 + `; 1946 + 1947 + exports[`prompts (isCI = true) > groupMultiselect > can select a group 1`] = ` 1948 + [ 1949 + "[?25l", 1950 + "│ 1951 + ◆ foo 1952 + │ ◻ group1 1953 + │ │ ◻ group1value0 1954 + │ └ ◻ group1value1 1955 + └ 1956 + ", 1957 + "", 1958 + "", 1959 + "", 1960 + "│ ◼ group1 1961 + │ │ ◼ group1value0 1962 + │ └ ◼ group1value1 1963 + └ 1964 + ", 1965 + "", 1966 + "", 1967 + "", 1968 + "◇ foo 1969 + │ group1value0, group1value1", 1970 + " 1971 + ", 1972 + "[?25h", 1973 + ] 1974 + `; 1975 + 1976 + exports[`prompts (isCI = true) > groupMultiselect > can select a group by selecting all members 1`] = ` 1977 + [ 1978 + "[?25l", 1979 + "│ 1980 + ◆ foo 1981 + │ ◻ group1 1982 + │ │ ◻ group1value0 1983 + │ └ ◻ group1value1 1984 + └ 1985 + ", 1986 + "", 1987 + "", 1988 + "", 1989 + "│ ◻ group1 1990 + │ │ ◻ group1value0 1991 + │ └ ◻ group1value1 1992 + └ 1993 + ", 1994 + "", 1995 + "", 1996 + "", 1997 + "│ │ ◼ group1value0", 1998 + "", 1999 + "", 2000 + "", 2001 + "", 2002 + "│ │ ◼ group1value0 2003 + │ └ ◻ group1value1 2004 + └ 2005 + ", 2006 + "", 2007 + "", 2008 + "", 2009 + "│ ◼ group1 2010 + │ │ ◼ group1value0 2011 + │ └ ◼ group1value1 2012 + └ 2013 + ", 2014 + "", 2015 + "", 2016 + "", 2017 + "◇ foo 2018 + │ group1value0, group1value1", 2019 + " 2020 + ", 2021 + "[?25h", 2022 + ] 2023 + `; 2024 + 2025 + exports[`prompts (isCI = true) > groupMultiselect > can select multiple options 1`] = ` 2026 + [ 2027 + "[?25l", 2028 + "│ 2029 + ◆ foo 2030 + │ ◻ group1 2031 + │ │ ◻ group1value0 2032 + │ │ ◻ group1value1 2033 + │ └ ◻ group1value2 2034 + └ 2035 + ", 2036 + "", 2037 + "", 2038 + "", 2039 + "│ ◻ group1 2040 + │ │ ◻ group1value0 2041 + │ │ ◻ group1value1 2042 + │ └ ◻ group1value2 2043 + └ 2044 + ", 2045 + "", 2046 + "", 2047 + "", 2048 + "│ │ ◼ group1value0", 2049 + "", 2050 + "", 2051 + "", 2052 + "", 2053 + "│ │ ◼ group1value0 2054 + │ │ ◻ group1value1 2055 + │ └ ◻ group1value2 2056 + └ 2057 + ", 2058 + "", 2059 + "", 2060 + "", 2061 + "│ │ ◼ group1value1", 2062 + "", 2063 + "", 2064 + "", 2065 + "", 2066 + "◇ foo 2067 + │ group1value0, group1value1", 2068 + " 2069 + ", 2070 + "[?25h", 2071 + ] 2072 + `; 2073 + 2074 + exports[`prompts (isCI = true) > groupMultiselect > can submit empty selection when require = false 1`] = ` 2075 + [ 2076 + "[?25l", 2077 + "│ 2078 + ◆ foo 2079 + │ ◻ group1 2080 + │ │ ◻ group1value0 2081 + │ └ ◻ group1value1 2082 + └ 2083 + ", 2084 + "", 2085 + "", 2086 + "", 2087 + "◇ foo 2088 + │", 2089 + " 2090 + ", 2091 + "[?25h", 2092 + ] 2093 + `; 2094 + 2095 + exports[`prompts (isCI = true) > groupMultiselect > cursorAt sets initial selection 1`] = ` 2096 + [ 2097 + "[?25l", 2098 + "│ 2099 + ◆ foo 2100 + │ ◻ group1 2101 + │ │ ◻ group1value0 2102 + │ └ ◻ group1value1 2103 + └ 2104 + ", 2105 + "", 2106 + "", 2107 + "", 2108 + "│ └ ◼ group1value1", 2109 + "", 2110 + "", 2111 + "", 2112 + "", 2113 + "◇ foo 2114 + │ group1value1", 2115 + " 2116 + ", 2117 + "[?25h", 2118 + ] 2119 + `; 2120 + 2121 + exports[`prompts (isCI = true) > groupMultiselect > initial values can be set 1`] = ` 2122 + [ 2123 + "[?25l", 2124 + "│ 2125 + ◆ foo 2126 + │ ◻ group1 2127 + │ │ ◻ group1value0 2128 + │ └ ◼ group1value1 2129 + └ 2130 + ", 2131 + "", 2132 + "", 2133 + "", 2134 + "◇ foo 2135 + │ group1value1", 2136 + " 2137 + ", 2138 + "[?25h", 2139 + ] 2140 + `; 2141 + 2142 + exports[`prompts (isCI = true) > groupMultiselect > renders error when nothing selected 1`] = ` 2143 + [ 2144 + "[?25l", 2145 + "│ 2146 + ◆ foo 2147 + │ ◻ group1 2148 + │ │ ◻ group1value0 2149 + │ └ ◻ group1value1 2150 + └ 2151 + ", 2152 + "", 2153 + "", 2154 + "", 2155 + "▲ foo 2156 + │ ◻ group1 2157 + │ │ ◻ group1value0 2158 + │ └ ◻ group1value1 2159 + └ Please select at least one option. 2160 + Press  space  to select,  enter  to submit 2161 + ", 2162 + "", 2163 + "", 2164 + "", 2165 + "◆ foo 2166 + │ ◻ group1 2167 + │ │ ◻ group1value0 2168 + │ └ ◻ group1value1 2169 + └ 2170 + ", 2171 + "", 2172 + "", 2173 + "", 2174 + "│ │ ◼ group1value0", 2175 + "", 2176 + "", 2177 + "", 2178 + "", 2179 + "◇ foo 2180 + │ group1value0", 2181 + " 2182 + ", 2183 + "[?25h", 2184 + ] 2185 + `; 2186 + 2187 + exports[`prompts (isCI = true) > groupMultiselect > renders message with options 1`] = ` 2188 + [ 2189 + "[?25l", 2190 + "│ 2191 + ◆ foo 2192 + │ ◻ group1 2193 + │ │ ◻ group1value0 2194 + │ └ ◻ group1value1 2195 + │ ◻ group2 2196 + │ └ ◻ group2value0 2197 + └ 2198 + ", 2199 + "", 2200 + "", 2201 + "", 2202 + "│ ◻ group1 2203 + │ │ ◻ group1value0 2204 + │ └ ◻ group1value1 2205 + │ ◻ group2 2206 + │ └ ◻ group2value0 2207 + └ 2208 + ", 2209 + "", 2210 + "", 2211 + "", 2212 + "│ │ ◼ group1value0", 2213 + "", 2214 + "", 2215 + "", 2216 + "", 2217 + "◇ foo 2218 + │ group1value0", 2219 + " 2220 + ", 2221 + "[?25h", 2222 + ] 2223 + `; 2224 + 2225 + exports[`prompts (isCI = true) > groupMultiselect > selectableGroups = false > cannot select groups 1`] = ` 2226 + [ 2227 + "[?25l", 2228 + "│ 2229 + ◆ foo 2230 + │  group1 2231 + │  ◻ group1value0 2232 + │  ◻ group1value1 2233 + └ 2234 + ", 2235 + "", 2236 + "", 2237 + "", 2238 + "│  ◼ group1value0", 2239 + "", 2240 + "", 2241 + "", 2242 + "", 2243 + "◇ foo 2244 + │ group1value0", 2245 + " 2246 + ", 2247 + "[?25h", 2248 + ] 2249 + `; 2250 + 2251 + exports[`prompts (isCI = true) > groupMultiselect > selectableGroups = false > selecting all members of group does not select group 1`] = ` 2252 + [ 2253 + "[?25l", 2254 + "│ 2255 + ◆ foo 2256 + │  group1 2257 + │  ◻ group1value0 2258 + │  ◻ group1value1 2259 + └ 2260 + ", 2261 + "", 2262 + "", 2263 + "", 2264 + "│  ◼ group1value0", 2265 + "", 2266 + "", 2267 + "", 2268 + "", 2269 + "│  ◼ group1value0 2270 + │  ◻ group1value1 2271 + └ 2272 + ", 2273 + "", 2274 + "", 2275 + "", 2276 + "│  ◼ group1value1", 2277 + "", 2278 + "", 2279 + "", 2280 + "", 2281 + "◇ foo 2282 + │ group1value0, group1value1", 2283 + " 2284 + ", 2285 + "[?25h", 2286 + ] 2287 + `; 2288 + 2289 + exports[`prompts (isCI = true) > groupMultiselect > values can be non-primitive 1`] = ` 2290 + [ 2291 + "[?25l", 2292 + "│ 2293 + ◆ foo 2294 + │ ◻ group1 2295 + │ │ ◻ value0 2296 + │ └ ◻ value1 2297 + └ 2298 + ", 2299 + "", 2300 + "", 2301 + "", 2302 + "│ ◻ group1 2303 + │ │ ◻ value0 2304 + │ └ ◻ value1 2305 + └ 2306 + ", 2307 + "", 2308 + "", 2309 + "", 2310 + "│ │ ◼ value0", 2311 + "", 2312 + "", 2313 + "", 2314 + "", 2315 + "◇ foo 2316 + │ value0", 1451 2317 " 1452 2318 ", 1453 2319 "[?25h",
+282
packages/prompts/src/index.test.ts
··· 899 899 expect(output.buffer).toMatchSnapshot(); 900 900 }); 901 901 }); 902 + 903 + describe('groupMultiselect', () => { 904 + test('renders message with options', async () => { 905 + const result = prompts.groupMultiselect({ 906 + message: 'foo', 907 + input, 908 + output, 909 + options: { 910 + group1: [{ value: 'group1value0' }, { value: 'group1value1' }], 911 + group2: [{ value: 'group2value0' }], 912 + }, 913 + }); 914 + 915 + // Select the first non-group option 916 + input.emit('keypress', '', { name: 'down' }); 917 + input.emit('keypress', '', { name: 'space' }); 918 + 919 + // submit 920 + input.emit('keypress', '', { name: 'return' }); 921 + 922 + const value = await result; 923 + 924 + expect(value).toEqual(['group1value0']); 925 + expect(output.buffer).toMatchSnapshot(); 926 + }); 927 + 928 + test('can select multiple options', async () => { 929 + const result = prompts.groupMultiselect({ 930 + message: 'foo', 931 + input, 932 + output, 933 + options: { 934 + group1: [{ value: 'group1value0' }, { value: 'group1value1' }, { value: 'group1value2' }], 935 + }, 936 + }); 937 + 938 + // Select the first non-group option 939 + input.emit('keypress', '', { name: 'down' }); 940 + input.emit('keypress', '', { name: 'space' }); 941 + // Select the second non-group option 942 + input.emit('keypress', '', { name: 'down' }); 943 + input.emit('keypress', '', { name: 'space' }); 944 + 945 + // submit 946 + input.emit('keypress', '', { name: 'return' }); 947 + 948 + const value = await result; 949 + 950 + expect(value).toEqual(['group1value0', 'group1value1']); 951 + expect(output.buffer).toMatchSnapshot(); 952 + }); 953 + 954 + test('can select a group', async () => { 955 + const result = prompts.groupMultiselect({ 956 + message: 'foo', 957 + input, 958 + output, 959 + options: { 960 + group1: [{ value: 'group1value0' }, { value: 'group1value1' }], 961 + }, 962 + }); 963 + 964 + // Select the group as a whole 965 + input.emit('keypress', '', { name: 'space' }); 966 + 967 + // submit 968 + input.emit('keypress', '', { name: 'return' }); 969 + 970 + const value = await result; 971 + 972 + expect(value).toEqual(['group1value0', 'group1value1']); 973 + expect(output.buffer).toMatchSnapshot(); 974 + }); 975 + 976 + test('can select a group by selecting all members', async () => { 977 + const result = prompts.groupMultiselect({ 978 + message: 'foo', 979 + input, 980 + output, 981 + options: { 982 + group1: [{ value: 'group1value0' }, { value: 'group1value1' }], 983 + }, 984 + }); 985 + 986 + // Select the first group option 987 + input.emit('keypress', '', { name: 'down' }); 988 + input.emit('keypress', '', { name: 'space' }); 989 + // Select the second group option 990 + input.emit('keypress', '', { name: 'down' }); 991 + input.emit('keypress', '', { name: 'space' }); 992 + 993 + // submit 994 + input.emit('keypress', '', { name: 'return' }); 995 + 996 + const value = await result; 997 + 998 + expect(value).toEqual(['group1value0', 'group1value1']); 999 + expect(output.buffer).toMatchSnapshot(); 1000 + }); 1001 + 1002 + test('can deselect an option', async () => { 1003 + const result = prompts.groupMultiselect({ 1004 + message: 'foo', 1005 + input, 1006 + output, 1007 + options: { 1008 + group1: [{ value: 'group1value0' }, { value: 'group1value1' }], 1009 + }, 1010 + }); 1011 + 1012 + // Select the first group option 1013 + input.emit('keypress', '', { name: 'down' }); 1014 + input.emit('keypress', '', { name: 'space' }); 1015 + // Select the second group option 1016 + input.emit('keypress', '', { name: 'down' }); 1017 + input.emit('keypress', '', { name: 'space' }); 1018 + // Deselect it 1019 + input.emit('keypress', '', { name: 'space' }); 1020 + 1021 + // submit 1022 + input.emit('keypress', '', { name: 'return' }); 1023 + 1024 + const value = await result; 1025 + 1026 + expect(value).toEqual(['group1value0']); 1027 + expect(output.buffer).toMatchSnapshot(); 1028 + }); 1029 + 1030 + test('renders error when nothing selected', async () => { 1031 + const result = prompts.groupMultiselect({ 1032 + message: 'foo', 1033 + input, 1034 + output, 1035 + options: { 1036 + group1: [{ value: 'group1value0' }, { value: 'group1value1' }], 1037 + }, 1038 + }); 1039 + 1040 + // try submit 1041 + input.emit('keypress', '', { name: 'return' }); 1042 + // now select something and submit 1043 + input.emit('keypress', '', { name: 'down' }); 1044 + input.emit('keypress', '', { name: 'space' }); 1045 + input.emit('keypress', '', { name: 'return' }); 1046 + 1047 + const value = await result; 1048 + 1049 + expect(value).toEqual(['group1value0']); 1050 + expect(output.buffer).toMatchSnapshot(); 1051 + }); 1052 + 1053 + describe('selectableGroups = false', () => { 1054 + test('cannot select groups', async () => { 1055 + const result = prompts.groupMultiselect({ 1056 + message: 'foo', 1057 + input, 1058 + output, 1059 + options: { 1060 + group1: [{ value: 'group1value0' }, { value: 'group1value1' }], 1061 + }, 1062 + selectableGroups: false, 1063 + }); 1064 + 1065 + // first selectable item should be group's child 1066 + input.emit('keypress', '', { name: 'space' }); 1067 + input.emit('keypress', '', { name: 'return' }); 1068 + 1069 + const value = await result; 1070 + 1071 + expect(value).toEqual(['group1value0']); 1072 + expect(output.buffer).toMatchSnapshot(); 1073 + }); 1074 + 1075 + test('selecting all members of group does not select group', async () => { 1076 + const result = prompts.groupMultiselect({ 1077 + message: 'foo', 1078 + input, 1079 + output, 1080 + options: { 1081 + group1: [{ value: 'group1value0' }, { value: 'group1value1' }], 1082 + }, 1083 + selectableGroups: false, 1084 + }); 1085 + 1086 + // first selectable item should be group's child 1087 + input.emit('keypress', '', { name: 'space' }); 1088 + // select second item 1089 + input.emit('keypress', '', { name: 'down' }); 1090 + input.emit('keypress', '', { name: 'space' }); 1091 + // submit 1092 + input.emit('keypress', '', { name: 'return' }); 1093 + 1094 + const value = await result; 1095 + 1096 + expect(value).toEqual(['group1value0', 'group1value1']); 1097 + expect(output.buffer).toMatchSnapshot(); 1098 + }); 1099 + }); 1100 + 1101 + test('can submit empty selection when require = false', async () => { 1102 + const result = prompts.groupMultiselect({ 1103 + message: 'foo', 1104 + input, 1105 + output, 1106 + options: { 1107 + group1: [{ value: 'group1value0' }, { value: 'group1value1' }], 1108 + }, 1109 + required: false, 1110 + }); 1111 + 1112 + input.emit('keypress', '', { name: 'return' }); 1113 + 1114 + const value = await result; 1115 + 1116 + expect(value).toEqual([]); 1117 + expect(output.buffer).toMatchSnapshot(); 1118 + }); 1119 + 1120 + test('cursorAt sets initial selection', async () => { 1121 + const result = prompts.groupMultiselect({ 1122 + message: 'foo', 1123 + input, 1124 + output, 1125 + options: { 1126 + group1: [{ value: 'group1value0' }, { value: 'group1value1' }], 1127 + }, 1128 + cursorAt: 'group1value1', 1129 + }); 1130 + 1131 + input.emit('keypress', '', { name: 'space' }); 1132 + input.emit('keypress', '', { name: 'return' }); 1133 + 1134 + const value = await result; 1135 + 1136 + expect(value).toEqual(['group1value1']); 1137 + expect(output.buffer).toMatchSnapshot(); 1138 + }); 1139 + 1140 + test('initial values can be set', async () => { 1141 + const result = prompts.groupMultiselect({ 1142 + message: 'foo', 1143 + input, 1144 + output, 1145 + options: { 1146 + group1: [{ value: 'group1value0' }, { value: 'group1value1' }], 1147 + }, 1148 + initialValues: ['group1value1'], 1149 + }); 1150 + 1151 + input.emit('keypress', '', { name: 'return' }); 1152 + 1153 + const value = await result; 1154 + 1155 + expect(value).toEqual(['group1value1']); 1156 + expect(output.buffer).toMatchSnapshot(); 1157 + }); 1158 + 1159 + test('values can be non-primitive', async () => { 1160 + const value0 = Symbol(); 1161 + const value1 = Symbol(); 1162 + const result = prompts.groupMultiselect({ 1163 + message: 'foo', 1164 + input, 1165 + output, 1166 + options: { 1167 + group1: [ 1168 + { value: value0, label: 'value0' }, 1169 + { value: value1, label: 'value1' }, 1170 + ], 1171 + }, 1172 + }); 1173 + 1174 + input.emit('keypress', '', { name: 'down' }); 1175 + input.emit('keypress', '', { name: 'space' }); 1176 + input.emit('keypress', '', { name: 'return' }); 1177 + 1178 + const value = await result; 1179 + 1180 + expect(value).toEqual([value0]); 1181 + expect(output.buffer).toMatchSnapshot(); 1182 + }); 1183 + }); 902 1184 });