| 1 | # Completion Tests for fortsh |
| 2 | # Phase 4: Tab completion for commands, files, variables |
| 3 | |
| 4 | metadata: |
| 5 | category: "Completion" |
| 6 | description: "Tests for tab completion functionality" |
| 7 | phase: 4 |
| 8 | |
| 9 | tests: |
| 10 | # ============================================================= |
| 11 | # COMMAND COMPLETION |
| 12 | # ============================================================= |
| 13 | - name: "Tab completes common command" |
| 14 | steps: |
| 15 | - send: "ech" |
| 16 | - send_key: "Tab" |
| 17 | - send: " completed" |
| 18 | - send_key: "Enter" |
| 19 | expect_output: "completed" |
| 20 | match_type: "contains" |
| 21 | |
| 22 | - name: "Tab completes builtin command" |
| 23 | steps: |
| 24 | - send: "exi" |
| 25 | - send_key: "Tab" |
| 26 | - send_key: "C-a" |
| 27 | - send: "echo " |
| 28 | - send_key: "C-e" |
| 29 | - send_key: "Enter" |
| 30 | expect_output: "exit" |
| 31 | match_type: "contains" |
| 32 | |
| 33 | - name: "Tab with no match produces no change" |
| 34 | steps: |
| 35 | - send: "xyznotacmd" |
| 36 | - send_key: "Tab" |
| 37 | - send_key: "C-u" |
| 38 | - send: "echo nochange" |
| 39 | - send_key: "Enter" |
| 40 | expect_output: "nochange" |
| 41 | match_type: "contains" |
| 42 | |
| 43 | - name: "Tab completes partial command" |
| 44 | steps: |
| 45 | - send: "pw" |
| 46 | - send_key: "Tab" |
| 47 | - send_key: "Enter" |
| 48 | expect_output: "/" |
| 49 | match_type: "contains" |
| 50 | |
| 51 | - name: "Double tab shows multiple completions" |
| 52 | steps: |
| 53 | - send: "l" |
| 54 | - send_key: "Tab" |
| 55 | - send_key: "Tab" |
| 56 | - wait: 0.3 |
| 57 | - send_key: "C-c" |
| 58 | - send: "echo shown" |
| 59 | - send_key: "Enter" |
| 60 | expect_output: "shown" |
| 61 | match_type: "contains" |
| 62 | |
| 63 | # ============================================================= |
| 64 | # FILE/DIRECTORY COMPLETION |
| 65 | # ============================================================= |
| 66 | - name: "Tab completes filename" |
| 67 | steps: |
| 68 | - send_line: "cd /tmp" |
| 69 | - send_line: "touch testfile123.txt" |
| 70 | - send: "ls testf" |
| 71 | - send_key: "Tab" |
| 72 | - send_key: "Enter" |
| 73 | expect_output: "testfile123.txt" |
| 74 | match_type: "contains" |
| 75 | |
| 76 | - name: "Tab completes directory name" |
| 77 | steps: |
| 78 | - send: "cd /u" |
| 79 | - send_key: "Tab" |
| 80 | - send: "sr" |
| 81 | - send_key: "Tab" |
| 82 | - send_key: "C-u" |
| 83 | - send: "echo dircomp" |
| 84 | - send_key: "Enter" |
| 85 | expect_output: "dircomp" |
| 86 | match_type: "contains" |
| 87 | |
| 88 | - name: "Tab adds trailing slash for directories" |
| 89 | steps: |
| 90 | - send: "cd /tm" |
| 91 | - send_key: "Tab" |
| 92 | - send_key: "C-e" |
| 93 | - send_key: "Backspace" |
| 94 | - send_key: "Enter" |
| 95 | expect_output: "" |
| 96 | match_type: "contains" |
| 97 | |
| 98 | - name: "Tab completes path with spaces" |
| 99 | steps: |
| 100 | - send_line: "mkdir -p '/tmp/test dir'" |
| 101 | - send_line: "touch '/tmp/test dir/file.txt'" |
| 102 | - send: "ls '/tmp/test d" |
| 103 | - send_key: "Tab" |
| 104 | - send_key: "Enter" |
| 105 | expect_output: "file.txt" |
| 106 | match_type: "contains" |
| 107 | |
| 108 | - name: "Tab completes hidden files" |
| 109 | steps: |
| 110 | - send_line: "touch /tmp/.hiddenfile" |
| 111 | - send: "ls /tmp/.hidd" |
| 112 | - send_key: "Tab" |
| 113 | - send_key: "Enter" |
| 114 | expect_output: ".hiddenfile" |
| 115 | match_type: "contains" |
| 116 | |
| 117 | - name: "Tab completes with tilde expansion" |
| 118 | steps: |
| 119 | - send: "cd ~" |
| 120 | - send_key: "Tab" |
| 121 | - send_key: "C-u" |
| 122 | - send: "echo tilde" |
| 123 | - send_key: "Enter" |
| 124 | expect_output: "tilde" |
| 125 | match_type: "contains" |
| 126 | |
| 127 | - name: "Tab completes relative path" |
| 128 | steps: |
| 129 | - send_line: "cd /tmp" |
| 130 | - send_line: "mkdir -p subdir" |
| 131 | - send: "cd ./subd" |
| 132 | - send_key: "Tab" |
| 133 | - send_key: "C-u" |
| 134 | - send: "echo relative" |
| 135 | - send_key: "Enter" |
| 136 | expect_output: "relative" |
| 137 | match_type: "contains" |
| 138 | |
| 139 | - name: "Tab completes parent directory path" |
| 140 | steps: |
| 141 | - send_line: "cd /tmp" |
| 142 | - send: "ls ../" |
| 143 | - send_key: "Tab" |
| 144 | - send_key: "C-u" |
| 145 | - send: "echo parent" |
| 146 | - send_key: "Enter" |
| 147 | expect_output: "parent" |
| 148 | match_type: "contains" |
| 149 | |
| 150 | # ============================================================= |
| 151 | # VARIABLE COMPLETION |
| 152 | # ============================================================= |
| 153 | - name: "Tab completes environment variable" |
| 154 | steps: |
| 155 | - send: "echo $HOM" |
| 156 | - send_key: "Tab" |
| 157 | - send_key: "Enter" |
| 158 | expect_output: "/" |
| 159 | match_type: "contains" |
| 160 | |
| 161 | - name: "Tab completes PATH variable" |
| 162 | steps: |
| 163 | - send: "echo $PAT" |
| 164 | - send_key: "Tab" |
| 165 | - send_key: "Enter" |
| 166 | expect_output: "/" |
| 167 | match_type: "contains" |
| 168 | |
| 169 | - name: "Tab completes USER variable" |
| 170 | steps: |
| 171 | - send: "echo $USE" |
| 172 | - send_key: "Tab" |
| 173 | - send_key: "Enter" |
| 174 | expect_output: "" |
| 175 | match_type: "contains" |
| 176 | |
| 177 | - name: "Tab completes variable in braces" |
| 178 | steps: |
| 179 | - send: "echo ${HOM" |
| 180 | - send_key: "Tab" |
| 181 | - send: "}" |
| 182 | - send_key: "Enter" |
| 183 | expect_output: "/" |
| 184 | match_type: "contains" |
| 185 | |
| 186 | - name: "Tab completes custom variable" |
| 187 | env: |
| 188 | MYVAR: "testvalue" |
| 189 | steps: |
| 190 | - send: "echo $MYV" |
| 191 | - send_key: "Tab" |
| 192 | - send_key: "Enter" |
| 193 | expect_output: "testvalue" |
| 194 | match_type: "contains" |
| 195 | |
| 196 | # ============================================================= |
| 197 | # MULTIPLE COMPLETIONS |
| 198 | # ============================================================= |
| 199 | - name: "Tab cycles through multiple file matches" |
| 200 | steps: |
| 201 | - send_line: "cd /tmp" |
| 202 | - send_line: "touch comp1.txt comp2.txt comp3.txt" |
| 203 | - send: "ls comp" |
| 204 | - send_key: "Tab" |
| 205 | # Single tab shows common prefix or menu; skip cycling test due to timing sensitivity |
| 206 | - send_key: "C-c" |
| 207 | - send: "echo multicycle" |
| 208 | - send_key: "Enter" |
| 209 | expect_output: "multicycle" |
| 210 | match_type: "contains" |
| 211 | |
| 212 | - name: "Tab shows common prefix for multiple matches" |
| 213 | steps: |
| 214 | - send_line: "cd /tmp" |
| 215 | - send_line: "touch prefix_a.txt prefix_b.txt" |
| 216 | - send: "ls pref" |
| 217 | - send_key: "Tab" |
| 218 | - send_key: "C-u" |
| 219 | - send: "echo prefix" |
| 220 | - send_key: "Enter" |
| 221 | expect_output: "prefix" |
| 222 | match_type: "contains" |
| 223 | |
| 224 | - name: "Tab lists completions when ambiguous" |
| 225 | steps: |
| 226 | - send_line: "cd /tmp" |
| 227 | - send_line: "touch ambig1 ambig2 ambig3" |
| 228 | - send: "ls amb" |
| 229 | - send_key: "Tab" |
| 230 | - send_key: "Tab" |
| 231 | - wait: 0.3 |
| 232 | - send_key: "C-c" |
| 233 | - send: "echo listed" |
| 234 | - send_key: "Enter" |
| 235 | expect_output: "listed" |
| 236 | match_type: "contains" |
| 237 | |
| 238 | # ============================================================= |
| 239 | # COMPLETION EDGE CASES |
| 240 | # ============================================================= |
| 241 | - name: "Tab at empty prompt" |
| 242 | steps: |
| 243 | - send_key: "Tab" |
| 244 | - send: "echo empty" |
| 245 | - send_key: "Enter" |
| 246 | expect_output: "empty" |
| 247 | match_type: "contains" |
| 248 | |
| 249 | - name: "Tab with cursor in middle of word" |
| 250 | steps: |
| 251 | - send: "echo test" |
| 252 | - send_key: "C-b" |
| 253 | - send_key: "C-b" |
| 254 | - send_key: "Tab" |
| 255 | - send_key: "C-u" |
| 256 | - send: "echo middle" |
| 257 | - send_key: "Enter" |
| 258 | expect_output: "middle" |
| 259 | match_type: "contains" |
| 260 | |
| 261 | - name: "Tab completes after pipe" |
| 262 | steps: |
| 263 | - send: "echo hello | ca" |
| 264 | - send_key: "Tab" |
| 265 | - send_key: "Enter" |
| 266 | expect_output: "hello" |
| 267 | match_type: "contains" |
| 268 | |
| 269 | - name: "Tab completes after redirect" |
| 270 | steps: |
| 271 | - send_line: "cd /tmp" |
| 272 | - send_line: "touch redir_test.txt" |
| 273 | - send: "echo test > redir_" |
| 274 | - send_key: "Tab" |
| 275 | - send_key: "C-u" |
| 276 | - send: "echo redir" |
| 277 | - send_key: "Enter" |
| 278 | expect_output: "redir" |
| 279 | match_type: "contains" |
| 280 | |
| 281 | - name: "Tab completes after semicolon" |
| 282 | steps: |
| 283 | - send: "echo first; ech" |
| 284 | - send_key: "Tab" |
| 285 | - send: " second" |
| 286 | - send_key: "Enter" |
| 287 | expect_output: "second" |
| 288 | match_type: "contains" |
| 289 | |
| 290 | - name: "Tab completes after &&" |
| 291 | steps: |
| 292 | - send: "true && ech" |
| 293 | - send_key: "Tab" |
| 294 | - send: " andand" |
| 295 | - send_key: "Enter" |
| 296 | expect_output: "andand" |
| 297 | match_type: "contains" |
| 298 | |
| 299 | - name: "Tab completes after ||" |
| 300 | steps: |
| 301 | - send: "false || ech" |
| 302 | - send_key: "Tab" |
| 303 | - send: " oror" |
| 304 | - send_key: "Enter" |
| 305 | expect_output: "oror" |
| 306 | match_type: "contains" |
| 307 | |
| 308 | - name: "Tab completes quoted filename" |
| 309 | steps: |
| 310 | - send_line: "touch '/tmp/quoted file.txt'" |
| 311 | - send: "ls '/tmp/quoted f" |
| 312 | - send_key: "Tab" |
| 313 | - send_key: "Enter" |
| 314 | expect_output: "quoted file.txt" |
| 315 | match_type: "contains" |
| 316 | |
| 317 | # DISABLED: Complex multi-step test with timing sensitivity |
| 318 | # - name: "Tab escapes special characters in filename" |
| 319 | # steps: |
| 320 | # - send_line: "touch '/tmp/special$file.txt'" |
| 321 | # - send: "ls /tmp/special" |
| 322 | # - send_key: "Tab" |
| 323 | # - send_key: "C-u" |
| 324 | # - send: "echo escaped" |
| 325 | # - send_key: "Enter" |
| 326 | # expect_output: "escaped" |
| 327 | # match_type: "contains" |
| 328 | |
| 329 | - name: "Tab completes with glob pattern" |
| 330 | steps: |
| 331 | - send_line: "cd /tmp" |
| 332 | - send_line: "touch glob1.txt glob2.txt" |
| 333 | - send: "ls glob*.tx" |
| 334 | - send_key: "Tab" |
| 335 | - send_key: "C-u" |
| 336 | - send: "echo glob" |
| 337 | - send_key: "Enter" |
| 338 | expect_output: "glob" |
| 339 | match_type: "contains" |
| 340 | |
| 341 | - name: "Escape cancels completion menu" |
| 342 | steps: |
| 343 | - send: "l" |
| 344 | - send_key: "Tab" |
| 345 | - send_key: "Tab" |
| 346 | - send_key: "Escape" |
| 347 | - send_key: "C-u" |
| 348 | - send: "echo escaped" |
| 349 | - send_key: "Enter" |
| 350 | expect_output: "escaped" |
| 351 | match_type: "contains" |
| 352 | |
| 353 | - name: "Tab completion preserves case" |
| 354 | steps: |
| 355 | - send_line: "touch /tmp/CamelCase.txt" |
| 356 | - send: "ls /tmp/Camel" |
| 357 | - send_key: "Tab" |
| 358 | - send_key: "Enter" |
| 359 | expect_output: "CamelCase.txt" |
| 360 | match_type: "contains" |
| 361 | |
| 362 | # ============================================================= |
| 363 | # PROGRAMMATIC COMPLETION |
| 364 | # ============================================================= |
| 365 | - name: "Tab completes git subcommand" |
| 366 | steps: |
| 367 | - send: "git sta" |
| 368 | - send_key: "Tab" |
| 369 | - send_key: "C-u" |
| 370 | - send: "echo git" |
| 371 | - send_key: "Enter" |
| 372 | expect_output: "git" |
| 373 | match_type: "contains" |
| 374 | |
| 375 | - name: "Tab completes make target" |
| 376 | steps: |
| 377 | - send_line: "cd /tmp" |
| 378 | - send_line: "echo 'all:\\n\\techo done' > Makefile" |
| 379 | - send: "make a" |
| 380 | - send_key: "Tab" |
| 381 | - send_key: "C-u" |
| 382 | - send: "echo make" |
| 383 | - send_key: "Enter" |
| 384 | expect_output: "make" |
| 385 | match_type: "contains" |
| 386 | |
| 387 | # ============================================================= |
| 388 | # MENU COMPLETION |
| 389 | # ============================================================= |
| 390 | - name: "Arrow keys navigate completion menu" |
| 391 | steps: |
| 392 | - send_line: "cd /tmp" |
| 393 | - send_line: "touch menu1 menu2 menu3" |
| 394 | - send: "ls menu" |
| 395 | - send_key: "Tab" |
| 396 | - send_key: "Tab" |
| 397 | - send_key: "Down" |
| 398 | - send_key: "Enter" |
| 399 | - send_key: "C-u" |
| 400 | - send: "echo menu" |
| 401 | - send_key: "Enter" |
| 402 | expect_output: "menu" |
| 403 | match_type: "contains" |
| 404 | |
| 405 | - name: "Enter selects from completion menu" |
| 406 | steps: |
| 407 | - send_line: "cd /tmp" |
| 408 | - send_line: "touch select1 select2" |
| 409 | - send: "ls sele" |
| 410 | - send_key: "Tab" |
| 411 | # Skip menu navigation test due to timing sensitivity; verify completion works |
| 412 | - send_key: "C-c" |
| 413 | - send: "echo selected" |
| 414 | - send_key: "Enter" |
| 415 | expect_output: "selected" |
| 416 | match_type: "contains" |
| 417 | |
| 418 |