Compare commits

...

7 Commits

Author SHA1 Message Date
ChrisVandoo
ddac059dd4 Fix titles and comments in search e2e tests
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-01 13:22:37 -07:00
ChrisVandoo
b0e0df2544 Drop unused setup from search e2e tests
- the last_edited_at label hydration tests only read the filter chip, so
  they no longer run the hook that edits a question through the UI
- the second entity picker recents test never used the home page load
- remove a repeated restore, repeated admin sign-ins and an intercept
  that was never awaited

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-01 13:22:37 -07:00
ChrisVandoo
3a150d9259 Merge the search result description e2e tests
Both tests created one question with a description, loaded the same page
as the same user and typed the same search text. They now share one page
load, with each assertion scoped to its own result.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-01 13:22:37 -07:00
ChrisVandoo
2a1439a16b Strengthen weak assertions in search e2e tests
- the page reset test now proves page 2 was reached, then checks the
  page param is gone and only tables are listed after filtering
- the persist filters test now checks every filter chip and URL param
  after the text query changes, since the results alone only showed
  that at least one filter survived
- the non-admin personal collection test now checks a sibling filter is
  rendered before asserting the personal filter is absent

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-01 13:22:37 -07:00
ChrisVandoo
245f9fdfa5 Repair search e2e tests that could not fail
- snowplow type filter removal expected content_type [], which the
  matcher accepts for any array, so the page load event satisfied it
- expectSearchResultContent passed a callback to .first(), so collection
  names were never checked
- issue 28788 measured an element that is never a scroll container
- the empty string test ended before any search could fire and its
  intercept did not match search requests
- the entity picker recents tests never opened recent items
- the trash filter test asserted zero results while the list was loading
- the Today date filter tests only asserted results that were already
  shown before the filter was applied
- the search page results after Enter were asserted unscoped, so the
  dropdown results satisfied them

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-01 13:22:37 -07:00
ChrisVandoo
c254e78610 Fold search filter hydration tests into the tests that share their URL
Each folded test loaded the same URL as its target and only asserted the
hydrated state, so its assertions now run at the start of the target:
- plain search hydration into the persist filters test
- created_by hydration into the remove a user test
- verified hydration into the turn the toggle off test
- native query hydration into the turn the toggle off test
- type filter removal into the type hydration tests

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-01 13:22:36 -07:00
ChrisVandoo
da19a78b89 Remove duplicate search e2e tests
Each removed test is a prefix of another test in the same spec:
- snowplow "filter used in the URL" tests repeat the first half of the
  "removed from the UI" tests
- created_at/last_edited_at=thisday hydration is asserted by the tests
  that remove those filters
- the recently viewed list is asserted by the up-to-date list test

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-01 12:58:13 -07:00
6 changed files with 277 additions and 362 deletions

View File

@@ -43,9 +43,9 @@ export function expectSearchResultContent({
}
if (expectedSearchResult.collection) {
cy.findAllByTestId("result-link-wrapper").first(() => {
cy.findByText(expectedSearchResult.collection).should("exist");
});
cy.findAllByTestId("result-link-wrapper")
.first()
.should("contain.text", expectedSearchResult.collection);
}
if (expectedSearchResult.timestamp) {
cy.findByTestId("revision-history-text").findByText(

View File

@@ -40,12 +40,6 @@ describe("search > recently viewed", () => {
cy.findByTestId("loading-indicator").should("not.exist");
});
it("shows list of recently viewed items", () => {
assertRecentlyViewedItem(0, "Orders in a dashboard", "Dashboard");
assertRecentlyViewedItem(1, "Orders", "Question");
assertRecentlyViewedItem(2, "People", "Table");
});
it("allows to select an item from keyboard", () => {
cy.findByTestId("recents-list-container").findByText("Recently viewed");
cy.get("body").trigger("keydown", { key: "ArrowDown" });
@@ -55,7 +49,7 @@ describe("search > recently viewed", () => {
cy.url().should("match", /\/question\/\d+-orders$/);
});
it("shows up-to-date list of recently viewed items after another page is visited (metabase#36868)", () => {
it("shows list of recently viewed items and keeps it up to date after another page is visited (metabase#36868)", () => {
cy.findByPlaceholderText("Search…").click();
cy.wait("@recent");
cy.findByTestId("loading-indicator").should("not.exist");
@@ -81,10 +75,10 @@ describe("Recently Viewed > Entity Picker", () => {
beforeEach(() => {
H.restore();
cy.signInAsAdmin();
cy.visit("/");
});
it("shows recently created collection in entity picker", () => {
cy.visit("/");
H.createCollection({
name: "My Fresh Collection",
});
@@ -94,28 +88,42 @@ describe("Recently Viewed > Entity Picker", () => {
cy.findByTestId("collection-picker-button").click();
H.entityPickerModal().within(() => {
cy.findByText("Select a collection").click();
cy.findByText("My Fresh Collection");
cy.findByText("Select a collection").should("be.visible");
cy.findByText("Recent items").click();
cy.findAllByTestId("result-item").should(
"contain.text",
"My Fresh Collection",
);
});
});
it("shows recently visited dashboard in entity picker", () => {
H.visitDashboard(ORDERS_DASHBOARD_ID);
H.visitQuestion(ORDERS_QUESTION_ID);
H.createDashboard({ name: "My Fresh Dashboard" }).then(
({ body: { id: dashboardId } }) => {
H.visitDashboard(dashboardId);
H.visitQuestion(ORDERS_QUESTION_ID);
cy.findByTestId("qb-header").icon("ellipsis").click();
H.popover().findByText("Add to dashboard").click();
cy.findByTestId("qb-header").icon("ellipsis").click();
H.popover().findByText("Add to dashboard").click();
H.entityPickerModal().within(() => {
cy.findByText("Add this question to a dashboard").click();
cy.findByText("Our analytics").click();
cy.findByText("Orders in a dashboard").click();
cy.button("Select").click();
});
H.entityPickerModal().within(() => {
cy.findByText("Add this question to a dashboard").should(
"be.visible",
);
cy.button("Select").should("be.enabled");
cy.findByText("Recent items").click();
cy.contains(
"[data-testid=result-item]",
"My Fresh Dashboard",
).click();
cy.button("Select").click();
});
cy.url().should("contain", `/dashboard/${ORDERS_DASHBOARD_ID}-`);
cy.findByTestId("dashboard-header-container").findByText(
/You're editing this dashboard/,
cy.url().should("contain", `/dashboard/${dashboardId}-`);
cy.findByTestId("dashboard-header-container").findByText(
/You're editing this dashboard/,
);
},
);
});
});

View File

@@ -73,7 +73,6 @@ const REVIEWS_TABLE_NAME = "Reviews";
const TEST_NATIVE_QUESTION_NAME = "GithubUptimeisMagnificentlyHigh";
const TEST_CREATED_AT_FILTERS = [
["Today", "thisday"],
["Yesterday", "past1days"],
["Previous week", "past1weeks"],
["Previous 7 days", "past7days"],
@@ -92,14 +91,6 @@ describe("scenarios > search", () => {
describe("applying search filters", () => {
describe("no filters", () => {
it("hydrating search from URL", () => {
cy.visit("/search?q=orders");
cy.wait("@search");
cy.findByTestId("search-app").within(() => {
cy.findByText('Results for "orders"').should("exist");
});
});
it("hydrates the command palette search from the URL (#71248)", () => {
cy.visit("/search?q=products");
cy.wait("@search");
@@ -178,7 +169,7 @@ describe("scenarios > search", () => {
});
typeFilters.forEach(({ label, type }) => {
it(`should hydrate search with search text and ${label} filter`, () => {
it(`should hydrate search with search text and ${label} filter and remove it when \`X\` is clicked`, () => {
cy.visit(`/search?q=e&type=${type}`);
cy.wait("@search");
@@ -195,7 +186,21 @@ describe("scenarios > search", () => {
cy.findByTestId("type-search-filter").within(() => {
cy.findByText(label).should("exist");
cy.findByLabelText("close icon").should("exist");
cy.findByLabelText("close icon").click();
cy.findByText(label).should("not.exist");
cy.findByText("Content type").should("exist");
});
cy.url().should("not.contain", "type");
cy.findAllByTestId("search-result-item").then(($results) => {
const uniqueResults = new Set(
$results.toArray().map((el) => {
const ariaLabel = el.getAttribute("aria-label");
return ariaLabel.split(" ").slice(-1)[0];
}),
);
expect(uniqueResults.size).to.be.greaterThan(1);
});
});
@@ -219,36 +224,10 @@ describe("scenarios > search", () => {
});
});
});
it("should remove type filter when `X` is clicked on search filter", () => {
const { label, type } = typeFilters[0];
cy.visit(`/search?q=e&type=${type}`);
cy.wait("@search");
cy.findByTestId("type-search-filter").within(() => {
cy.findByText(label).should("exist");
cy.findByLabelText("close icon").click();
cy.findByText(label).should("not.exist");
cy.findByText("Content type").should("exist");
});
cy.url().should("not.contain", "type");
cy.findAllByTestId("search-result-item").then(($results) => {
const uniqueResults = new Set(
$results.toArray().map((el) => {
const label = el.getAttribute("aria-label");
return label.split(" ").slice(-1)[0];
}),
);
expect(uniqueResults.size).to.be.greaterThan(1);
});
});
});
describe("created_by filter", () => {
beforeEach(() => {
H.restore();
// create a question from a normal and admin user, then we can query the question
// created by that user as an admin
cy.signInAsNormalUser();
@@ -259,34 +238,6 @@ describe("scenarios > search", () => {
H.createQuestion(ADMIN_TEST_QUESTION);
});
it("should hydrate created_by filter", () => {
cy.visit(
`/search?created_by=${ADMIN_USER_ID}&created_by=${NORMAL_USER_ID}&q=reviews`,
);
cy.wait("@search");
cy.findByTestId("created_by-search-filter").within(() => {
cy.findByText("2 users selected").should("exist");
cy.findByLabelText("close icon").should("exist");
});
H.expectSearchResultContent({
expectedSearchResults: [
{
name: NORMAL_USER_TEST_QUESTION.name,
timestamp: "Created a few seconds ago by Robert Tableton",
collection: "Our analytics",
},
{
name: ADMIN_TEST_QUESTION.name,
timestamp: "Created a few seconds ago by you",
collection: "Our analytics",
},
],
});
});
it("should filter results by one user", () => {
cy.visit("/");
@@ -359,13 +310,18 @@ describe("scenarios > search", () => {
});
});
it("should be able to remove a user from the `created_by` filter", () => {
it("should hydrate created_by filter and be able to remove a user from it", () => {
cy.visit(
`/search?q=reviews&created_by=${NORMAL_USER_ID}&created_by=${ADMIN_USER_ID}`,
`/search?created_by=${ADMIN_USER_ID}&created_by=${NORMAL_USER_ID}&q=reviews`,
);
cy.wait("@search");
cy.findByTestId("created_by-search-filter").within(() => {
cy.findByText("2 users selected").should("exist");
cy.findByLabelText("close icon").should("exist");
});
H.expectSearchResultContent({
expectedSearchResults: [
{
@@ -463,8 +419,7 @@ describe("scenarios > search", () => {
describe("last_edited_by filter", () => {
beforeEach(() => {
cy.signInAsAdmin();
// We'll create a question as a normal user, then edit it as an admin user
// We'll create a question as an admin user, then edit it as a normal user
H.createQuestion(LAST_EDITED_BY_NORMAL_USER_QUESTION).then(
({ body: { id: questionId } }) => {
cy.signOut();
@@ -481,7 +436,7 @@ describe("scenarios > search", () => {
},
);
// We'll create a question as an admin user, then edit it as a normal user
// We'll create a question as a normal user, then edit it as an admin user
H.createQuestion(LAST_EDITED_BY_ADMIN_QUESTION).then(
({ body: { id: questionId } }) => {
cy.signInAsAdmin();
@@ -499,8 +454,6 @@ describe("scenarios > search", () => {
});
it("should hydrate last_edited_by filter", () => {
cy.intercept("GET", "/api/user").as("getUsers");
cy.visit(`/search?q=reviews&last_edited_by=${NORMAL_USER_ID}`);
cy.wait("@search");
@@ -554,7 +507,7 @@ describe("scenarios > search", () => {
});
});
it("should filter last_edited results by more than user", () => {
it("should filter last_edited results by more than one user", () => {
cy.visit("/");
H.commandPaletteSearch("reviews");
@@ -746,6 +699,12 @@ describe("scenarios > search", () => {
cy.findByText("Today").click();
});
cy.location("search").should("include", "created_at=thisday");
cy.findByTestId("created_at-search-filter").within(() => {
cy.findByText("Today").should("exist");
cy.findByLabelText("close icon").should("exist");
});
H.expectSearchResultContent({
expectedSearchResults: [
{
@@ -758,7 +717,7 @@ describe("scenarios > search", () => {
});
});
it("should remove created_at filter when `X` is clicked on search filter", () => {
it("should hydrate created_at=thisday and remove the filter when `X` is clicked", () => {
cy.visit("/search?q=Reviews&created_at=thisday");
cy.wait("@search");
@@ -794,28 +753,6 @@ describe("scenarios > search", () => {
});
describe("last_edited_at filter", () => {
beforeEach(() => {
cy.signInAsAdmin();
// We'll create a question as a normal user, then edit it as an admin user
H.createQuestion(LAST_EDITED_BY_NORMAL_USER_QUESTION).then(
({ body: { id: questionId } }) => {
cy.signOut();
cy.signInAsNormalUser();
cy.visit(`/question/${questionId}`);
H.summarize();
cy.findByTestId("sidebar-right").findByText("Done").click();
cy.findByTestId("qb-header-action-panel")
.findByText("Save")
.click();
cy.findByTestId("save-question-modal").within((modal) => {
cy.findByText("Save").click();
});
cy.signOut();
cy.signInAsAdmin();
},
);
});
TEST_CREATED_AT_FILTERS.forEach(([label, filter]) => {
it(`should hydrate last_edited_at=${filter}`, () => {
cy.visit(`/search?q=reviews&last_edited_at=${filter}`);
@@ -829,66 +766,96 @@ describe("scenarios > search", () => {
});
});
// we can only test the 'today' filter since we currently
// can't edit the last_edited_at column of a question in our database
it("should filter results by Today (last_edited_at=thisday)", () => {
cy.visit("/search?q=Reviews");
expectSearchResultItemNameContent({
itemNames: [
REVIEWS_TABLE_NAME,
LAST_EDITED_BY_NORMAL_USER_QUESTION.name,
],
});
cy.findByTestId("last_edited_at-search-filter").click();
H.popover().within(() => {
cy.findByText("Today").click();
});
H.expectSearchResultContent({
expectedSearchResults: [
{
name: LAST_EDITED_BY_NORMAL_USER_QUESTION.name,
collection: "Our analytics",
timestamp: "Updated a few seconds ago by Robert Tableton",
describe("with an edited question", () => {
beforeEach(() => {
// We'll create a question as an admin user, then edit it as a normal user
H.createQuestion(LAST_EDITED_BY_NORMAL_USER_QUESTION).then(
({ body: { id: questionId } }) => {
cy.signOut();
cy.signInAsNormalUser();
cy.visit(`/question/${questionId}`);
H.summarize();
cy.findByTestId("sidebar-right").findByText("Done").click();
cy.findByTestId("qb-header-action-panel")
.findByText("Save")
.click();
cy.findByTestId("save-question-modal").within((modal) => {
cy.findByText("Save").click();
});
cy.signOut();
cy.signInAsAdmin();
},
],
strict: false,
});
});
it("should remove last_edited_at filter when `X` is clicked on search filter", () => {
cy.visit("/search?q=Reviews&last_edited_at=thisday");
cy.wait("@search");
H.expectSearchResultContent({
expectedSearchResults: [
{
name: LAST_EDITED_BY_NORMAL_USER_QUESTION.name,
collection: "Our analytics",
timestamp: "Updated a few seconds ago by Robert Tableton",
},
],
strict: false,
);
});
cy.findByTestId("last_edited_at-search-filter").within(() => {
cy.findByText("Today").should("exist");
// we can only test the 'today' filter since we currently
// can't edit the last_edited_at column of a question in our database
it("should filter results by Today (last_edited_at=thisday)", () => {
cy.visit("/search?q=Reviews");
cy.findByLabelText("close icon").click();
expectSearchResultItemNameContent({
itemNames: [
REVIEWS_TABLE_NAME,
LAST_EDITED_BY_NORMAL_USER_QUESTION.name,
],
});
cy.findByText("Today").should("not.exist");
cy.findByText("Last edit date").should("exist");
cy.findByTestId("last_edited_at-search-filter").click();
H.popover().within(() => {
cy.findByText("Today").click();
});
cy.location("search").should("include", "last_edited_at=thisday");
cy.findByTestId("last_edited_at-search-filter").within(() => {
cy.findByText("Today").should("exist");
cy.findByLabelText("close icon").should("exist");
});
cy.findAllByTestId("search-result-item").should("have.length", 1);
H.expectSearchResultContent({
expectedSearchResults: [
{
name: LAST_EDITED_BY_NORMAL_USER_QUESTION.name,
collection: "Our analytics",
timestamp: "Updated a few seconds ago by Robert Tableton",
},
],
strict: false,
});
});
cy.url().should("not.contain", "last_edited_at");
it("should hydrate last_edited_at=thisday and remove the filter when `X` is clicked", () => {
cy.visit("/search?q=Reviews&last_edited_at=thisday");
cy.wait("@search");
expectSearchResultItemNameContent({
itemNames: [
REVIEWS_TABLE_NAME,
LAST_EDITED_BY_NORMAL_USER_QUESTION.name,
],
H.expectSearchResultContent({
expectedSearchResults: [
{
name: LAST_EDITED_BY_NORMAL_USER_QUESTION.name,
collection: "Our analytics",
timestamp: "Updated a few seconds ago by Robert Tableton",
},
],
strict: false,
});
cy.findByTestId("last_edited_at-search-filter").within(() => {
cy.findByText("Today").should("exist");
cy.findByLabelText("close icon").click();
cy.findByText("Today").should("not.exist");
cy.findByText("Last edit date").should("exist");
});
cy.url().should("not.contain", "last_edited_at");
expectSearchResultItemNameContent({
itemNames: [
REVIEWS_TABLE_NAME,
LAST_EDITED_BY_NORMAL_USER_QUESTION.name,
],
});
});
});
});
@@ -903,21 +870,6 @@ describe("scenarios > search", () => {
});
});
it("should hydrate search with search text and verified filter", () => {
cy.visit("/search?q=orders&verified=true");
cy.wait("@search");
cy.findByTestId("search-app").within(() => {
cy.findByText('Results for "orders"').should("exist");
});
cy.findAllByTestId("search-result-item").each((result) => {
cy.wrap(result).within(() => {
cy.findByLabelText("verified_filled icon").should("exist");
});
});
});
it("should filter results by verified items", () => {
cy.visit("/");
@@ -937,11 +889,21 @@ describe("scenarios > search", () => {
});
});
it("should not filter results when verified items is off", () => {
it("should hydrate verified filter and not filter results when it is turned off", () => {
cy.visit("/search?q=e&verified=true");
cy.wait("@search");
cy.findByTestId("search-app").within(() => {
cy.findByText('Results for "e"').should("exist");
});
cy.findAllByTestId("search-result-item").each((result) => {
cy.wrap(result).within(() => {
cy.findByLabelText("verified_filled icon").should("exist");
});
});
cy.findByTestId("verified-search-filter")
.findByLabelText("Verified items only")
.click();
@@ -966,7 +928,6 @@ describe("scenarios > search", () => {
describe("native query filter", () => {
beforeEach(() => {
cy.signInAsAdmin();
H.createNativeQuestion({
name: TEST_NATIVE_QUESTION_NAME,
native: {
@@ -982,23 +943,6 @@ describe("scenarios > search", () => {
});
});
it("should hydrate search with search text and native query filter", () => {
cy.visit(
`/search?q=${TEST_NATIVE_QUESTION_NAME}&search_native_query=true`,
);
cy.wait("@search");
cy.findByTestId("search-app").within(() => {
cy.findByText(`Results for "${TEST_NATIVE_QUESTION_NAME}"`).should(
"exist",
);
});
expectSearchResultItemNameContent({
itemNames: [TEST_NATIVE_QUESTION_NAME, "Native Query"],
});
});
it("should include results that contain native query data when the toggle is on", () => {
cy.visit(`/search?q=${TEST_NATIVE_QUESTION_NAME}`);
cy.wait("@search");
@@ -1018,12 +962,18 @@ describe("scenarios > search", () => {
});
});
it("should not include results that contain native query data if the toggle is off", () => {
it("should hydrate native query filter and not include results that contain native query data if the toggle is turned off", () => {
cy.visit(
`/search?q=${TEST_NATIVE_QUESTION_NAME}&search_native_query=true`,
);
cy.wait("@search");
cy.findByTestId("search-app").within(() => {
cy.findByText(`Results for "${TEST_NATIVE_QUESTION_NAME}"`).should(
"exist",
);
});
expectSearchResultItemNameContent({
itemNames: [TEST_NATIVE_QUESTION_NAME, "Native Query"],
});
@@ -1080,6 +1030,7 @@ describe("scenarios > search", () => {
expectSearchResultItemNameContent({
itemNames: ["Normal User Personal Question [keyword]"],
});
cy.findByTestId("archived-search-filter").should("be.visible");
cy.findByTestId(
"filter_items_in_personal_collection-search-filter",
).should("not.exist");
@@ -1126,7 +1077,10 @@ describe("scenarios > search", () => {
cy.findByTestId("archived-search-filter")
.findByLabelText("Search items in trash")
.click();
cy.findAllByTestId("search-result-item").should("have.length", 0);
cy.location("search").should("include", "archived=true");
cy.findByTestId("search-app")
.findByText("Didn't find anything")
.should("be.visible");
H.archiveCollection(FIRST_COLLECTION_ID);
cy.reload();
@@ -1138,8 +1092,12 @@ describe("scenarios > search", () => {
});
});
it("should persist filters when the user changes the text query", () => {
it("should hydrate search from the URL and persist filters when the user changes the text query", () => {
cy.visit("/search?q=orders");
cy.wait("@search");
cy.findByTestId("search-app").within(() => {
cy.findByText('Results for "orders"').should("exist");
});
// add created_by filter
cy.findByTestId("created_by-search-filter").click();
@@ -1173,6 +1131,23 @@ describe("scenarios > search", () => {
//getSearchBar().clear().type("count{enter}");
H.commandPaletteSearch("count");
cy.findByTestId("search-app").within(() => {
cy.findByText('Results for "count"').should("exist");
});
cy.location("search")
.should("include", `created_by=${ADMIN_USER_ID}`)
.and("include", `last_edited_by=${ADMIN_USER_ID}`)
.and("include", "type=card");
cy.findByTestId("created_by-search-filter")
.findByText("Bobby Tables")
.should("exist");
cy.findByTestId("last_edited_by-search-filter")
.findByText("Bobby Tables")
.should("exist");
cy.findByTestId("type-search-filter")
.findByText("Question")
.should("exist");
expectSearchResultItemNameContent({
itemNames: [
"Orders, Count",

View File

@@ -15,14 +15,27 @@ describe("scenarios > search", () => {
});
it("should not search on an empty string", () => {
cy.intercept("/api/search", (req) => {
expect("Unexpected call to /api/search").to.be.false;
});
cy.intercept("GET", "/api/search?q=*").as("search");
H.visitFullAppEmbeddingUrl({
url: "/",
qs: { top_nav: true, search: true },
});
H.getSearchBar().type(" ");
H.getSearchBar().type(" ").should("have.value", " ");
cy.findByTestId("search-results-floating-container")
.findByText("Recently viewed")
.should("be.visible");
H.getSearchBar().clear().type("ord");
cy.wait("@search");
cy.findByTestId("search-bar-results-container").should("be.visible");
H.getSearchBar().clear().type(" ").should("have.value", " ");
cy.findByTestId("search-results-floating-container")
.findByText("Recently viewed")
.should("be.visible");
cy.findByTestId("search-bar-results-container").should("not.exist");
cy.get("@search.all").should("have.length", 1);
});
describe("multiple pages of results", () => {
@@ -69,13 +82,21 @@ describe("scenarios > search", () => {
it("should reset the page when filters change (metabase#65501)", () => {
cy.visit("/search?q=");
cy.findByLabelText("Next page").click();
cy.location("search").should("include", "page=1");
cy.findByLabelText("Previous page").should("be.enabled");
cy.findByTestId("type-search-filter").click();
H.popover().findByText("Table").click();
H.popover().findByText("Apply").click();
cy.findByTestId("search-app")
.findByText("Didn't find anything")
.should("not.exist");
cy.findAllByTestId("search-result-item").should("exist");
cy.location("search")
.should("include", "type=table")
.and("not.include", "page=");
cy.findAllByTestId("search-result-item").should(($items) => {
$items.each((_index, item) => {
expect(item).to.have.attr("data-model-type", "table");
});
});
});
});
});

View File

@@ -162,7 +162,7 @@ describe("scenarios > search > snowplow", () => {
describe("should send snowplow events for each filter when it is applied and removed", () => {
describe("no filters", () => {
it("should send a new_search_query snowplow event", () => {
it("should send search_query and search_click snowplow events", () => {
cy.visit("/search?q=orders");
cy.wait("@search");
H.expectUnstructuredSnowplowEvent({
@@ -192,21 +192,6 @@ describe("scenarios > search > snowplow", () => {
});
describe("type filter", () => {
it("should send a snowplow event when a search filter is used in the URL", () => {
cy.visit("/search?q=orders&type=card");
cy.wait("@search");
H.expectUnstructuredSnowplowEvent(
{
event: NEW_SEARCH_QUERY_EVENT_NAME,
context: "search-app",
content_type: ["card"],
},
1,
);
});
it("should send a snowplow event when a search filter is applied from the UI", () => {
cy.visit("/search?q=orders");
cy.wait("@search");
@@ -239,7 +224,7 @@ describe("scenarios > search > snowplow", () => {
});
});
it("should send a snowplow event when a search filter is removed from the UI", () => {
it("should send snowplow events when a search filter is used in the URL and then removed from the UI", () => {
cy.visit("/search?q=orders&type=card");
cy.wait("@search");
H.expectUnstructuredSnowplowEvent({
@@ -257,23 +242,12 @@ describe("scenarios > search > snowplow", () => {
event: NEW_SEARCH_QUERY_EVENT_NAME,
context: "search-app",
content_type: [],
content_type: null,
});
});
});
describe("created_by filter", () => {
it("should send a snowplow event when a search filter is used in the URL", () => {
cy.visit("/search?q=orders&created_by=1");
cy.wait("@search");
H.expectUnstructuredSnowplowEvent({
event: NEW_SEARCH_QUERY_EVENT_NAME,
context: "search-app",
creator: true,
});
});
it("should send a snowplow event when a search filter is applied from the UI", () => {
cy.visit("/search?q=orders");
cy.wait("@search");
@@ -297,7 +271,7 @@ describe("scenarios > search > snowplow", () => {
});
});
it("should send a snowplow event when a search filter is removed from the UI", () => {
it("should send snowplow events when a search filter is used in the URL and then removed from the UI", () => {
cy.visit("/search?q=orders&created_by=1");
cy.wait("@search");
H.expectUnstructuredSnowplowEvent({
@@ -321,17 +295,6 @@ describe("scenarios > search > snowplow", () => {
});
describe("last_edited_by filter", () => {
it("should send a snowplow event when a search filter is used in the URL", () => {
cy.visit("/search?q=orders&last_edited_by=1");
cy.wait("@search");
H.expectUnstructuredSnowplowEvent({
event: NEW_SEARCH_QUERY_EVENT_NAME,
context: "search-app",
last_editor: true,
});
});
it("should send a snowplow event when a search filter is applied from the UI", () => {
cy.visit("/search?q=orders");
cy.wait("@search");
@@ -356,7 +319,7 @@ describe("scenarios > search > snowplow", () => {
});
});
it("should send a snowplow event when a search filter is removed from the UI", () => {
it("should send snowplow events when a search filter is used in the URL and then removed from the UI", () => {
cy.visit("/search?q=orders&last_edited_by=1");
cy.wait("@search");
H.expectUnstructuredSnowplowEvent({
@@ -380,17 +343,6 @@ describe("scenarios > search > snowplow", () => {
});
describe("created_at filter", () => {
it("should send a snowplow event when a search filter is used in the URL", () => {
cy.visit("/search?q=orders&created_at=thisday");
cy.wait("@search");
H.expectUnstructuredSnowplowEvent({
event: NEW_SEARCH_QUERY_EVENT_NAME,
context: "search-app",
creation_date: true,
});
});
it("should send a snowplow event when a search filter is applied from the UI", () => {
cy.visit("/search?q=orders");
cy.wait("@search");
@@ -414,7 +366,7 @@ describe("scenarios > search > snowplow", () => {
});
});
it("should send a snowplow event when a search filter is removed from the UI", () => {
it("should send snowplow events when a search filter is used in the URL and then removed from the UI", () => {
cy.visit("/search?q=orders&created_at=thisday");
cy.wait("@search");
H.expectUnstructuredSnowplowEvent({
@@ -438,17 +390,6 @@ describe("scenarios > search > snowplow", () => {
});
describe("last_edited_at filter", () => {
it("should send a snowplow event when a search filter is used in the URL", () => {
cy.visit("/search?q=orders&last_edited_at=thisday");
cy.wait("@search");
H.expectUnstructuredSnowplowEvent({
event: NEW_SEARCH_QUERY_EVENT_NAME,
context: "search-app",
last_edit_date: true,
});
});
it("should send a snowplow event when a search filter is applied from the UI", () => {
cy.visit("/search?q=orders");
cy.wait("@search");
@@ -472,7 +413,7 @@ describe("scenarios > search > snowplow", () => {
});
});
it("should send a snowplow event when a search filter is removed from the UI", () => {
it("should send snowplow events when a search filter is used in the URL and then removed from the UI", () => {
cy.visit("/search?q=orders&last_edited_at=thisday");
cy.wait("@search");
H.expectUnstructuredSnowplowEvent({
@@ -500,17 +441,6 @@ describe("scenarios > search > snowplow", () => {
H.activateToken("pro-self-hosted");
});
it("should send a snowplow event when a search filter is used in the URL", () => {
cy.visit("/search?q=orders&verified=true");
cy.wait("@search");
H.expectUnstructuredSnowplowEvent({
event: NEW_SEARCH_QUERY_EVENT_NAME,
context: "search-app",
verified_items: true,
});
});
it("should send a snowplow event when a search filter is applied from the UI", () => {
cy.visit("/search?q=orders");
cy.wait("@search");
@@ -533,7 +463,7 @@ describe("scenarios > search > snowplow", () => {
});
});
it("should send a snowplow event when a search filter is removed from the UI", () => {
it("should send snowplow events when a search filter is used in the URL and then removed from the UI", () => {
cy.visit("/search?q=orders&verified=true");
cy.wait("@search");
H.expectUnstructuredSnowplowEvent({
@@ -557,17 +487,6 @@ describe("scenarios > search > snowplow", () => {
});
describe("search_native_query filter", () => {
it("should send a snowplow event when a search filter is used in the URL", () => {
cy.visit("/search?q=orders&search_native_query=true");
cy.wait("@search");
H.expectUnstructuredSnowplowEvent({
event: NEW_SEARCH_QUERY_EVENT_NAME,
context: "search-app",
search_native_queries: true,
});
});
it("should send a snowplow event when a search filter is applied from the UI", () => {
cy.visit("/search?q=orders");
cy.wait("@search");
@@ -590,7 +509,7 @@ describe("scenarios > search > snowplow", () => {
});
});
it("should send a snowplow event when a search filter is removed from the UI", () => {
it("should send snowplow events when a search filter is used in the URL and then removed from the UI", () => {
cy.visit("/search?q=orders&search_native_query=true");
cy.wait("@search");
H.expectUnstructuredSnowplowEvent({
@@ -614,17 +533,6 @@ describe("scenarios > search > snowplow", () => {
});
describe("archived filter", () => {
it("should send a snowplow event when a search filter is used in the URL", () => {
cy.visit("/search?q=orders&archived=true");
cy.wait("@search");
H.expectUnstructuredSnowplowEvent({
event: NEW_SEARCH_QUERY_EVENT_NAME,
context: "search-app",
search_archived: true,
});
});
it("should send a snowplow event when a search filter is applied from the UI", () => {
cy.visit("/search?q=orders");
cy.wait("@search");
@@ -647,7 +555,7 @@ describe("scenarios > search > snowplow", () => {
});
});
it("should send a snowplow event when a search filter is removed from the UI", () => {
it("should send snowplow events when a search filter is used in the URL and then removed from the UI", () => {
cy.visit("/search?q=orders&archived=true");
cy.wait("@search");
H.expectUnstructuredSnowplowEvent({

View File

@@ -58,15 +58,17 @@ describe("scenarios > search", () => {
cy.get("@searchBox").type("{enter}");
cy.wait("@search");
H.expectSearchResultContent({
expectedSearchResults: [
{
name: "Products",
description:
"Includes a catalog of all the products ever sold by the famed Sample Company.",
},
],
strict: false,
cy.findByTestId("search-app").within(() => {
H.expectSearchResultContent({
expectedSearchResults: [
{
name: "Products",
description:
"Includes a catalog of all the products ever sold by the famed Sample Company.",
},
],
strict: false,
});
});
});
@@ -116,9 +118,9 @@ describe("scenarios > search", () => {
cy.get("@search.all").should("have.length", 1);
});
it("should render a preview of markdown descriptions", () => {
it("should render a preview of markdown descriptions and not overflow the container on large unbroken strings", () => {
H.createQuestion({
name: "Description Test",
name: "Markdown Description Test",
query: { "source-table": ORDERS_ID },
description: `![alt](https://upload.wikimedia.org/wikipedia/commons/a/a2/Cat_outside.jpg)
@@ -131,40 +133,41 @@ describe("scenarios > search", () => {
This is a [link](https://upload.wikimedia.org/wikipedia/commons/a/a2/Cat_outside.jpg).
Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. `,
}).then(() => {
cy.signInAsNormalUser();
visitEmbeddingWithSearch("/");
H.getSearchBar().type("Test");
});
//Enseure that text is ellipsified
cy.findByTestId("result-description")
.findByText(/Lorem ipsum dolor sit amet./)
.then((el) => H.assertIsEllipsified(el[0]));
//Ensure that images are not being rendered in the descriptions
cy.findByTestId("result-description")
.findByRole("img")
.should("not.exist");
});
it("should not overflow container if results contain descriptions with large unbroken strings", () => {
H.createQuestion({
name: "Description Test",
name: "Unbroken Description Test",
query: { "source-table": ORDERS_ID },
description:
"testingtestingtestingtestingtestingtestingtestingtesting testingtestingtestingtestingtestingtestingtestingtestingtestingtestingtestingtestingtestingtestingtestingtestingtestingtestingtestingtestingtesting testingtestingtestingtestingtestingtestingtestingtestingtestingtestingtestingtestingtestingtestingtestingtestingtestingtestingtestingtestingtestingtestingtestingtestingtestingtestingtestingtestingtestingtestingtestingtestingtestingtestingtestingtestingtesting",
}).then(() => {
cy.signInAsNormalUser();
visitEmbeddingWithSearch("/");
H.getSearchBar().type("Test");
});
cy.signInAsNormalUser();
visitEmbeddingWithSearch("/");
H.getSearchBar().type("Test");
cy.contains(
"[data-testid=search-result-item]",
"Markdown Description Test",
).within(() => {
//Enseure that text is ellipsified
cy.findByTestId("result-description")
.findByText(/Lorem ipsum dolor sit amet./)
.then((el) => H.assertIsEllipsified(el[0]));
//Ensure that images are not being rendered in the descriptions
cy.findByTestId("result-description")
.findByRole("img")
.should("not.exist");
});
cy.findByTestId("search-results-floating-container")
.as("parentContainer")
.invoke("outerWidth")
.then((parentWidth) => {
cy.findByTestId("result-description")
cy.contains(
"[data-testid=search-result-item]",
"Unbroken Description Test",
)
.findByTestId("result-description")
.invoke("outerWidth")
.should(
"be.lessThan",
@@ -255,7 +258,6 @@ describe("issue 28788", () => {
beforeEach(() => {
H.restore();
cy.signInAsNormalUser();
cy.intercept("GET", "/api/search*").as("search");
});
it("search results container should not be scrollable horizontally (metabase#28788)", () => {
@@ -282,11 +284,12 @@ describe("issue 28788", () => {
qs: { top_nav: true, search: true },
});
cy.findByPlaceholderText("Search…").type(questionDetails.name);
cy.wait("@search");
cy.icon("hourglass").should("not.exist");
cy.findByTestId("search-bar-results-container").then(($container) => {
expect(H.isScrollableHorizontally($container[0])).to.be.false;
});
cy.findByTestId("search-results-list")
.should("contain.text", questionDetails.name)
.find("ul")
.should(($list) => {
expect(H.isScrollableHorizontally($list[0])).to.be.false;
});
});
});