tastejs/todomvc · error · Error
Cannot determine what kind of selectors this app uses. Add i
Error message
Cannot determine what kind of selectors this app uses. Add it to usesIDSelectors.
What it means
Thrown at cypress/e2e/spec.cy.js:501 during selector-style auto-detection in the setup hook. The spec decides whether to drive the app with ID selectors (`input#new-todo`) or class selectors (`input.new-todo`) by probing the live document (including shadow roots, via findDeep at line 487). Frameworks listed in the `usesIDSelectors` map (line 132, currently only `polymer: false`) bypass detection; for every other framework it inspects the DOM. If BOTH `input#new-todo` AND `input.new-todo` are present the choice is ambiguous, so it throws and asks you to register the framework explicitly rather than guess.
Source
Thrown at cypress/e2e/spec.cy.js:501
// Walk the document INCLUDING shadow roots — web-component apps
// (lit, polymer) keep their UI inside a shadow tree, so a plain
// doc.querySelector misses them. Returns the first element that
// matches `selector` anywhere in the light or shadow DOM.
const findDeep = (root, selector) => {
if (!root) return false
if (root.querySelector?.(selector)) return true
const candidates = root.querySelectorAll?.('*') || []
for (const el of candidates) {
if (el.shadowRoot && findDeep(el.shadowRoot, selector)) return true
}
return false
}
cy.document().then(doc => {
if (framework in usesIDSelectors) {
setSelectors(usesIDSelectors[framework])
createTodoCommands(usesIDSelectors[framework])
} else if (findDeep(doc, 'input#new-todo') && findDeep(doc, 'input.new-todo')) {
throw new Error(
'Cannot determine what kind of selectors this app uses. Add it to usesIDSelectors.'
)
} else if (findDeep(doc, 'input#new-todo')) {
cy.log('app uses ID selectors')
setSelectors(true)
createTodoCommands(true)
} else if (findDeep(doc, 'input.new-todo')) {
cy.log('app uses class selectors')
setSelectors(false)
createTodoCommands(false)
} else {
throw new Error(
'Cannot determine what kind of selectors this app uses.'
)
}
})
})
View on GitHub (pinned to ff43b02e59)
Solutions
- Register the framework in the `usesIDSelectors` map at line 132, e.g. `yourframework: true` if the app uses IDs or `yourframework: false` if it uses classes — this short-circuits detection at line 497.
- Inspect the rendered DOM (`cy.document().then(d => cy.log(d.querySelector('input#new-todo'), d.querySelector('input.new-todo')))`) to decide which value (true/false) to register.
- If the dual-selector is unintentional, fix the app template so it exposes only one of the two conventions.
Example fix
// before (cypress/e2e/spec.cy.js:132)
const usesIDSelectors = {
polymer: false
}
// after
const usesIDSelectors = {
polymer: false,
myframework: true // app renders <input id="new-todo"> Defensive patterns
Strategy: fallback
Validate before calling
// Before adding a framework to the suite, snapshot which selectors its DOM exposes.
// Run once in `cypress open --env framework=NEWFW` after commenting out the throw, then:
cy.document().then(doc => {
const hasId = !!doc.querySelector('input#new-todo')
const hasClass = !!doc.querySelector('input.new-todo')
cy.log(`id=${hasId} class=${hasClass}`)
// If both true -> add to usesIDSelectors with the value you intend to drive the app with.
}) Try / catch
// Wrap the detection so an ambiguous framework is reported, not fatal, during onboarding.
cy.document().then(doc => {
const fw = Cypress.env('framework')
if (!(fw in usesIDSelectors)) {
const hasId = findDeep(doc, 'input#new-todo')
const hasClass = findDeep(doc, 'input.new-todo')
if (hasId && hasClass) {
cy.log(`WARNING: ${fw} exposes both selector styles; defaulting to IDs. Add it to usesIDSelectors.`)
setSelectors(true); createTodoCommands(true); return
}
}
// ... existing branches
}) Prevention
- Register every supported framework in `usesIDSelectors` (line 132) rather than relying on runtime detection — detection is a fallback, not the primary path.
- When porting a new TodoMVC example, decide its selector style up front and add the entry in the same PR.
- Keep the map commented with the rendered markup shape so future contributors know why each value was chosen.
- Treat the both-selectors-present throw as a CI signal: a new framework passing detection means the map needs an entry.
When it happens
Trigger: Running against a framework that is NOT a key in `usesIDSelectors` (anything other than `polymer`) whose rendered DOM contains both an element matching `input#new-todo` and an element matching `input.new-todo`. This commonly happens when a single input carries both id="new-todo" and class="new-todo", or when the app renders two inputs.
Common situations: Adding a new TodoMVC example whose template assigns both the id and the class to the new-todo input; a framework upgrade that changes the markup to include both; a shadow-DOM web-component app (lit/polyderivative) whose shadow tree exposes both selectors. The map at line 132 only whitelists `polymer`, so most real apps fall through to runtime detection.
Related errors
- Cannot determine what kind of selectors this app uses.
- Please specify the framework name to test. See fold
- Invalid number of tests ${N} from env "${Cypress.env('times'
AI-assisted analysis of tastejs/todomvc@ff43b02e59 (2026-08-13).
Data as JSON: /api/errors/8e7cb363006ec341.
Report an issue: GitHub.