diff --git a/frontend/test/metabase/scenarios/binning/correctness/time-series.cy.spec.js b/frontend/test/metabase/scenarios/binning/correctness/time-series.cy.spec.js new file mode 100644 index 0000000000000000000000000000000000000000..7b836c36c1285d688d9025bed4a0eee0f06c142c --- /dev/null +++ b/frontend/test/metabase/scenarios/binning/correctness/time-series.cy.spec.js @@ -0,0 +1,200 @@ +import { restore, popover, openOrdersTable } from "__support__/e2e/cypress"; + +const TIME_OPTIONS = { + Minute: { + selected: "by minute", + representativeValues: [ + "January 1, 2017, 12:00 AM", + "January 1, 2018, 12:00 AM", + ], + type: "basic", + }, + Hour: { + selected: "by hour", + representativeValues: [ + "January 1, 2017, 12:00 AM", + "January 1, 2018, 12:00 AM", + "January 1, 2019, 12:00 AM", + ], + type: "basic", + }, + Day: { + selected: "by day", + representativeValues: [ + "January 1, 2017", + "January 1, 2018", + "January 1, 2019", + "January 1, 2020", + ], + type: "basic", + }, + Week: { + selected: "by week", + representativeValues: [ + "January, 2017", + "January, 2018", + "January, 2019", + "January, 2020", + ], + type: "basic", + }, + Month: { + selected: "by month", + representativeValues: [ + "January, 2017", + "January, 2018", + "January, 2019", + "January, 2020", + ], + type: "basic", + }, + Quarter: { + selected: "by quarter", + representativeValues: ["Q1 - 2017", "Q1 - 2018", "Q1 - 2019", "Q1 - 2020"], + type: "basic", + }, + Year: { + selected: "by year", + representativeValues: ["2016", "2017", "2018", "2019", "2020"], + type: "basic", + }, + "Minute of Hour": { + selected: "by minute of hour", + representativeValues: ["0", "5", "25", "55"], + type: "extended", + }, + "Hour of Day": { + selected: "by hour of day", + representativeValues: ["12:00 AM", "2:00 AM", "12:00 PM", "8:00 PM"], + type: "extended", + }, + "Day of Week": { + selected: "by day of week", + representativeValues: ["Saturday", "Tuesday", "Friday", "Sunday"], + type: "extended", + }, + "Day of Month": { + selected: "by day of month", + representativeValues: ["5", "10", "15", "30"], + type: "extended", + }, + "Day of Year": { + selected: "by day of year", + representativeValues: ["50", "100", "150", "300"], + type: "extended", + }, + "Week of Year": { + selected: "by week of year", + representativeValues: ["5th", "10th", "50th"], + type: "extended", + }, + "Month of Year": { + selected: "by month of year", + representativeValues: ["January", "June", "December"], + type: "extended", + }, + "Quarter of Year": { + selected: "by quarter of year", + representativeValues: ["Q1", "Q2", "Q3", "Q4"], + type: "extended", + }, +}; + +describe("scenarios > binning > correctness > time series", () => { + beforeEach(() => { + restore(); + cy.signInAsAdmin(); + + openOrdersTable(); + cy.findByText("Summarize").click(); + openPopoverFromDefaultBucketSize("Created At", "by month"); + }); + + Object.entries(TIME_OPTIONS).forEach( + ([bucketSize, { selected, representativeValues, type }]) => { + // We are forced to ignore the case here because we construct titles like so: + // "Day of Month" (bucket) -> "Day of month" (title) + // This feels weird and is probably worth investigating it further. + const titleRegex = new RegExp(`Count by Created At: ${bucketSize}`, "i"); + const bucketRegex = new RegExp(bucketSize, "i"); + + it(`should return correct values for ${bucketSize}`, () => { + popover().within(() => { + cy.findByText(bucketSize).click(); + }); + + cy.get(".List-item--selected") + .should("contain", "Created At") + .and("contain", selected); + + cy.findByText("Done").click(); + cy.findByTestId("sidebar-right").should("not.be.visible"); + + getTitle(titleRegex); + getVisualization(type); + + assertOnXYAxisLabels(); + assertOnXAxisTicks(representativeValues); + + assertOnTimeSeriesFooter(bucketRegex); + }); + }, + ); +}); + +function openPopoverFromDefaultBucketSize(column, bucket) { + cy.findByTestId("sidebar-right") + .contains(column) + .first() + .closest(".List-item") + .should("be.visible") + .as("targetListItem"); + + cy.get("@targetListItem") + .find(".Field-extra") + .as("listItemSelectedBinning") + .should("contain", bucket) + .click(); +} + +function getTitle(title) { + cy.findByText(title); +} + +function getVisualization(binningType) { + const selector = binningType === "basic" ? "circle" : ".bar"; + + cy.get(selector); +} + +function assertOnXYAxisLabels() { + cy.get(".y-axis-label") + .invoke("text") + .should("eq", "Count"); + cy.get(".x-axis-label") + .invoke("text") + .should("eq", "Created At"); +} + +function assertOnXAxisTicks(values) { + if (values) { + cy.get(".axis.x").within(() => { + values.forEach(value => { + cy.findByText(value); + }); + }); + } else { + cy.get(".axis.x").should("not.exist"); + } +} + +function assertOnTimeSeriesFooter(regex) { + cy.get(".AdminSelect-content") + .first() + .invoke("text") + .should("eq", "All Time"); + cy.get(".AdminSelect-content") + .last() + .invoke("text") + .should("match", regex); +}