MCPcopy Index your code
hub / github.com/coder/code-server / navigateItems

Method navigateItems

test/e2e/models/CodeServer.ts:450–542  ·  view source on GitHub ↗

* Navigate through the items in the selector. `open` is a function that will * open the menu/popup containing the items through which to navigation.

(items: string[], selector: string, open?: (selector: string) => void)

Source from the content-addressed store, hash-verified

448 * open the menu/popup containing the items through which to navigation.
449 */
450 async navigateItems(items: string[], selector: string, open?: (selector: string) => void): Promise<void> {
451 const logger = this.codeServer.logger.named(selector)
452
453 /**
454 * If the selector loses focus or gets removed this will resolve with false,
455 * signaling we need to try again.
456 */
457 const openThenWaitClose = async (ctx: Context) => {
458 if (open) {
459 await open(selector)
460 }
461 this.codeServer.logger.debug(`watching ${selector}`)
462 try {
463 await this.page.waitForSelector(`${selector}:not(:focus-within)`)
464 } catch (error) {
465 if (!ctx.finished()) {
466 this.codeServer.logger.debug(`${selector} navigation: ${(error as any).message || error}`)
467 }
468 }
469 return false
470 }
471
472 /**
473 * This will step through each item, aborting and returning false if
474 * canceled or if any navigation step has an error which signals we need to
475 * try again.
476 */
477 const navigate = async (ctx: Context) => {
478 const steps: Array<{ fn: () => Promise<unknown>; name: string }> = [
479 {
480 fn: () => this.page.waitForSelector(`${selector}:focus-within`),
481 name: "focus",
482 },
483 ]
484
485 for (const item of items) {
486 // Normally these will wait for the item to be visible and then execute
487 // the action. The problem is that if the menu closes these will still
488 // be waiting and continue to execute once the menu is visible again,
489 // potentially conflicting with the new set of navigations (for example
490 // if the old promise clicks logout before the new one can). By
491 // splitting them into two steps each we can cancel before running the
492 // action.
493 steps.push({
494 fn: () => this.page.hover(`${selector} :text-is("${item}")`, { trial: true }),
495 name: `${item}:hover:trial`,
496 })
497 steps.push({
498 fn: () => this.page.hover(`${selector} :text-is("${item}")`, { force: true }),
499 name: `${item}:hover:force`,
500 })
501 steps.push({
502 fn: () => this.page.click(`${selector} :text-is("${item}")`, { trial: true }),
503 name: `${item}:click:trial`,
504 })
505 steps.push({
506 fn: () => this.page.click(`${selector} :text-is("${item}")`, { force: true }),
507 name: `${item}:click:force`,

Callers 2

navigateQuickInputMethod · 0.95
navigateMenusMethod · 0.95

Calls 3

cancelMethod · 0.95
finishMethod · 0.95
pluralFunction · 0.90

Tested by

no test coverage detected