Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add options to customize name and displayName and message of some builtin commands #15438

Closed
DanaGoyette opened this issue Mar 11, 2021 · 3 comments
Labels
stage: proposal 💡 No work has been done of this issue type: feature New feature that does not currently exist

Comments

@DanaGoyette
Copy link

What would you like?

A way to customize the name and displayName and message attributes of some built-in commands, such as cy.get and .find.

Why is this needed?

This can help unclutter the command log, by moving the "key" of what it's looking for from the message to the displayName.

image

This could also be useful to partially address another feature request, by giving a way to tidy up the logging without disabling it entirely: #8296

I've tried doing it with a custom command, but custom commands that wrap cy commands aren't able to fully replicate the logging:

  • Can't highlight element by setting $el, especially in cases where you expect it not to exist
  • Can't call a callback each time the selector result is checked (.then only happens after element exists, and .should breaks default assertions)
  • Can't call a callback when the chained assertions fail (need something like .onFail: it would be block-scoped, and would allow logging, but not allow canceling the failure)
  • Can't use verifyUpcomingAssertions on the return value of .get (because that mixes synchronous and asynchronous code)
  • Can't use verifyUpcomingAssertions in a .should block (because it causes an infinite loop)

As an experiment, I managed to get something like what I want by copying the code of the .get() method, but that's too messy, and all the shadowDom stuff seemed not to be publicly exposed.

@DanaGoyette
Copy link
Author

A hackish approach I found to work for get is to pass the undocumented _log attribute, but I'd like something more official than that. It also doesn't work for the find method.

if (options._log == null) {

I'm not sure whether it would be better to add the name and message to options directly, or to make it accept a LogConfig object (and have it override consoleProps).

My current approach looks something like this:

export function getByTestId<E extends HTMLElement>(
  testId: string,
  options?: Partial<Existable & Cypress.Loggable & Cypress.Timeoutable & Cypress.Withinable & Cypress.Shadow>
): Cypress.Chainable<JQuery<E>> {
  const selector = `[data-testid=${testId}]`
  const userOptions = options || {}

  let mustExist: boolean = userOptions.exists ?? true
  delete userOptions.exists

  options = Cypress._.defaults({}, userOptions, {
    exists: true,
    log: true,
    timeout: Cypress.config('defaultCommandTimeout'),
  })

  const consoleProps = {
    Selector: selector,
    Yielded: undefined,
    Elements: undefined,
  }

  const logConf: Partial<Cypress.LogConfig> = {
    name: 'Get Element by Data-TestID',
    displayName: 'get(testid)',
    message: testId,
    timeout: options.timeout,
    //consoleProps: () => consoleProps
    // @ts-ignore (undocumented attribute)
    type: 'parent', // no '-' in command log
    // @ts-ignore (undocumented attribute)
    autoEnd: false,
  }

  const log = options?.log ? Cypress.log(logConf) : null
  options['_log'] = log
  return cy
    .get<E>(selector, { ...options })
    .should((currentSubject: JQuery<E>) => {
      log?.set('$el', currentSubject)
      Cypress._.extend(logConf, { $el: currentSubject })
      Cypress._.extend(consoleProps, {
        Selector: selector,
        Yielded: currentSubject ? Cypress.dom.getElements(currentSubject) : '--nothing--',
        Elements: currentSubject ? currentSubject.length : undefined,
      })
      if (mustExist) {
        expect(currentSubject).to.exist
      } else {
        expect(currentSubject).to.not.exist
      }
      log?.snapshot()
      log?.end()
    })
}

@jennifer-shehane jennifer-shehane added the stage: proposal 💡 No work has been done of this issue label Mar 16, 2021
@DanaGoyette
Copy link
Author

DanaGoyette commented Apr 1, 2021

In my own uses I ended up just switching back to native cy.get and relying on quotes around the ID for emphasis. This is enough to satisfy my needs for now, and I'll revisit this eventually.

For reference, I ended up making a far simpler helper method:

const byTestId = (testId: string) => `[data-testid="${testId}"]`

Used as follows:

cy.get(byTestId('some-test-id'))

Cypress command log comparison, showing how quotes help:

get  |  [data-testid=some-test-id]
get  |  [data-testid="some-test-id"]

(I also tried using getByTestId from testing-library/cypress, but that has quirks with logging and chaining.)

@jennifer-shehane jennifer-shehane added the type: feature New feature that does not currently exist label May 5, 2021
@jennifer-shehane
Copy link
Member

Since this hasn’t gotten a lot of interest over the years, we’ll close this issue.

@jennifer-shehane jennifer-shehane closed this as not planned Won't fix, can't repro, duplicate, stale Dec 16, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
stage: proposal 💡 No work has been done of this issue type: feature New feature that does not currently exist
Projects
None yet
Development

No branches or pull requests

2 participants