diff --git a/cypress/integration/awesome_bar.js b/cypress/integration/awesome_bar.js index 03ef96783a..dff04a5693 100644 --- a/cypress/integration/awesome_bar.js +++ b/cypress/integration/awesome_bar.js @@ -2,7 +2,11 @@ context("Awesome Bar", () => { before(() => { cy.visit("/login"); cy.login(); - cy.visit("/app/website"); + cy.visit("/app/todo"); // Make sure ToDo filters are cleared. + cy.clear_filters(); + cy.visit("/app/blog-post"); // Make sure Blog Post filters are cleared. + cy.clear_filters(); + cy.visit("/app/website"); // Go to some other page. }); beforeEach(() => { @@ -11,36 +15,61 @@ context("Awesome Bar", () => { cy.get("@awesome_bar").type("{selectall}"); }); + after(() => { + cy.visit("/app/todo"); // Make sure we're not bleeding any filters to the next spec. + cy.clear_filters(); + }); + it("navigates to doctype list", () => { cy.get("@awesome_bar").type("todo"); - cy.wait(100); + cy.wait(100); // Wait a bit before hitting enter. cy.get(".awesomplete").findByRole("listbox").should("be.visible"); cy.get("@awesome_bar").type("{enter}"); cy.get(".title-text").should("contain", "To Do"); cy.location("pathname").should("eq", "/app/todo"); }); - it("find text in doctype list", () => { + it("finds text in doctype list", () => { cy.get("@awesome_bar").type("test in todo"); - cy.wait(100); + cy.wait(150); // Wait a bit before hitting enter. cy.get("@awesome_bar").type("{enter}"); cy.get(".title-text").should("contain", "To Do"); - cy.wait(200); - const name_filter = cy.get('[data-original-title="ID"] > input'); - name_filter.should("have.value", "%test%"); - cy.clear_filters(); + cy.wait(200); // Wait a bit longer before checking the filter. + cy.get('[data-original-title="ID"] > input').should("have.value", "%test%"); + }); + + it("filter preserved, now finds something else", () => { + cy.visit("/app/todo"); + cy.get(".title-text").should("contain", "To Do"); + cy.wait(200); // Wait a bit longer before checking the filter. + cy.get('[data-original-title="ID"] > input').as("filter"); + cy.get("@filter").should("have.value", "%test%"); + cy.get("@awesome_bar").type("anothertest in todo"); + cy.wait(200); // Wait a bit longer before hitting enter. + cy.get("@awesome_bar").type("{enter}"); + cy.wait(200); // Wait a bit longer before checking the filter. + cy.get("@filter").should("have.value", "%anothertest%"); + }); + + it("navigates to another doctype, filter not bleeding", () => { + cy.get("@awesome_bar").type("blog post"); + cy.wait(150); // Wait a bit before hitting enter. + cy.get("@awesome_bar").type("{enter}"); + cy.get(".title-text").should("contain", "Blog Post"); + cy.wait(200); // Wait a bit longer before checking the filter. + cy.location("search").should("be.empty"); }); it("navigates to new form", () => { cy.get("@awesome_bar").type("new blog post"); - cy.wait(100); + cy.wait(150); // Wait a bit before hitting enter cy.get("@awesome_bar").type("{enter}"); cy.get(".title-text:visible").should("have.text", "New Blog Post"); }); it("calculates math expressions", () => { cy.get("@awesome_bar").type("55 + 32"); - cy.wait(100); + cy.wait(150); // Wait a bit before hitting enter cy.get("@awesome_bar").type("{downarrow}{enter}"); cy.get(".modal-title").should("contain", "Result"); cy.get(".msgprint").should("contain", "55 + 32 = 87"); diff --git a/frappe/public/js/frappe/router.js b/frappe/public/js/frappe/router.js index 2631c6374e..3b50791aa7 100644 --- a/frappe/public/js/frappe/router.js +++ b/frappe/public/js/frappe/router.js @@ -368,7 +368,11 @@ frappe.router = { window.open(sub_path, "_blank"); frappe.open_in_new_tab = false; } else { - this.push_state(sub_path); + const route_options = frappe.route_options || {}; + const query_params = Object.entries(route_options) + .map(([key, value]) => `${key}=` + encodeURIComponent(JSON.stringify(value))) + .join("&"); + this.push_state(sub_path, query_params ? `?${query_params}` : ""); } setTimeout(() => { frappe.after_ajax && @@ -469,12 +473,19 @@ frappe.router = { return "/app/" + (path_string || default_page); }, - push_state(url) { - // change the URL and call the router - if (window.location.pathname !== url) { + /** + * Changes the URL and calls the router. + * + * @param {string} path - The desired URI path to replace or push, + * without query string. Example: "/app/todo" + * @param {string} query_params - The desired query parameter string. + * @returns {void} + */ + push_state(path, query_params = "") { + if (window.location.pathname !== path || window.location.search !== query_params) { // push/replace state so the browser looks fine const method = frappe.route_flags.replace_route ? "replaceState" : "pushState"; - history[method](null, null, url); + history[method](null, null, path); // now process the route this.route();