Im using Turbo an a page w a simple select.
= turbo_frame_tag "widget-index", 'data-controller': 'turbo-frame-select' do
.widget-card-header
select
data-test-id="Widget-year-select"
data-action="turbo-frame-select#onChange"
type="select"
name="filter"
- @widget_years.each do |year|
option[selected=("selected" if (year == @search_year)) value="#{widget_index_path(company_id: @company.abbreviation, year: year)}"] #{year}
#widgets_results data-test-id="widgets-results"
= render WidgetCardComponent.with_collection(@widgets)
The AC is:
When the user selects a year, the results for the year should appear.
I've got a super simple stimulus controller I added to try to make sure caching is not an issue:
// turbo_frame_select_controller.js
import { Controller } from "@hotwired/stimulus";
export default class extends Controller {
onChange (event) {
const frame = this.element;
frame.src = event.target.value;
)}
}
Ive written an overwrite for select to work with Turbo events in command.js.
Cypress.Commands.overwrite("select", (originalFn, subject, ...args) => {
// Check if turbo is active for this select event
const turboFrame = subject[0].closest('[data-controller="turbo-frame-select"]');
const isSelect = subject[0].tagName === 'SELECT';
if (isSelect && turboFrame) {
// Wait for turbo to finish loading the page before proceeding with the next Cypress instructions.
// First, get the document
cy.document({ log: false }).then($document => {
console.log('mutating observer last child');
Cypress.log({
$el: subject,
name: 'select',
displayName: 'select',
message: 'select and wait for page to load',
consoleProps: () => ({ subject: subject })
});
// Make Cypress wait for this promise which waits for the turbFrame to cause a mutation
return new Cypress.Promise(resolve => {
// Once we receive the mutuation,
const onTurboFrameMutate = function(mutationList, observer) {
for(const mutation of mutationList) {
const isChild = mutation.type === 'childList';
const lastChild = mutationList.length -1 !== mutationList.indexOf(mutation)
if (isChild && lastChild) {
console.log('A child node has been added or removed.');
turboFrameObserver.disconnect();
// signal to Cypress that we're done
resolve()
}
}
}
// createa new observer
const turboFrameObserver = new MutationObserver(onTurboFrameMutate);
// Options for the observer (which mutations to observe)
const config = { attributes: true, childList: true, subtree: true };
// Add our logic as observer
turboFrameObserver.observe(turboFrame, config);
// Finally, we are ready to perform the actual select operation
originalFn(subject, ...args);
})
});
} else {
// Not a normal select on an <select> tag, turbo will not interfere here
return originalFn(subject, ...args);
}
});
I am calling the select method in this context:
cy.visit(widgetIndexPath, { timeout: 10000 });
// Make sure header is loaded
cy.contains("h1", "Cash management");
// Current year selected
cy.get("@aYearSelector").find("option:selected").contains(currentYear);
// Select last year
cy.get("@aYearSelector")
.find("option")
.its('length')
.then((length) => {
cy.get("@aYearSelector")
.select(length - 1, {force: true})
.then(()=> {
// Triggers after year selector changes
cy.wait('@previousYearRequest').then(({response}) => {
expect(response.statusCode).to.eq(200);
cy.get("[data-test-id='widget-year-select']").as('newYearSelector');
cy.get("[data-test-id='widgets-results']").as('newResults');
cy.get("@newYearSelector").find("option:selected").contains(previousYear);
// Note: We have 13 months of data in the data layer from the factories.
// The months count backwards from the current month which will be spread out
// over 2 years.
cy.get('@newResults')
The test passes 100/100 times locally, but is only sucesful 1/4 - 1/3 runs on Cypress Dashboard...
Giving the following error:
cy.then() timed out after waiting 6000ms.
Your callback function returned a promise that never resolved.
The callback function was:
$document => {
console.log('mutating observer last child');
Ive tried just about everyhting I can think of... This seems like it should work
Does anyone have any ideas why this is timing out?