Skip to content
Snippets Groups Projects
Unverified Commit 792c8711 authored by Aleksandr Lesnenko's avatar Aleksandr Lesnenko Committed by GitHub
Browse files

fix broken audit (#32212)

parent 3dccdd27
No related branches found
No related tags found
No related merge requests found
......@@ -88,6 +88,7 @@ jobs:
java-version: [11]
edition: [ee]
folder:
- "auditing"
- "actions"
- "admin"
- "binning"
......@@ -256,6 +257,7 @@ jobs:
java-version: [11]
edition: [ee]
folder:
- "auditing"
- "actions"
- "admin"
- "binning"
......
......@@ -54,7 +54,6 @@ describeEE("audit > ad-hoc", () => {
cy.signInAsNormalUser();
openOrdersTable();
cy.button("Visualize").click();
cy.wait("@dataset");
// Sign in as admin to be able to access audit logs in tests
......@@ -77,7 +76,11 @@ describeEE("audit > ad-hoc", () => {
cy.get(".PageTitle").contains("Query");
// eslint-disable-next-line no-unscoped-text-selectors -- deprecated usage
cy.findByText("Open in Metabase").should("be.visible");
cy.findByText("Open in Metabase")
.should("have.attr", "href")
.then(href => {
expect(href.startsWith("/question#")).to.be.true;
});
cy.findByTestId("read-only-notebook").within(() => {
cy.findByTestId("data-step-cell").within(() => {
......
......@@ -50,9 +50,9 @@ describeEE(
it("should validate approved email domains for a dashboard subscription in the audit app", () => {
visitDashboard(1);
cy.icon("share").click();
cy.icon("subscription").click();
// eslint-disable-next-line no-unscoped-text-selectors -- deprecated usage
cy.findByText("Dashboard subscriptions").click();
cy.findByText("Create a dashboard subscription").click();
// eslint-disable-next-line no-unscoped-text-selectors -- deprecated usage
cy.findByText("Email it").click();
......
......@@ -89,7 +89,7 @@ describeEE("audit > auditing", () => {
beforeEach(cy.signInAsAdmin);
describe("See expected info on team member pages", () => {
it("should load the Overview tab", () => {
it.skip(`should load the Overview tab (metabase#32244)`, () => {
cy.visit("/admin/audit/members/overview");
// We haven't created any new members yet so this should be empty
......@@ -204,7 +204,7 @@ describeEE("audit > auditing", () => {
// All tables tab
cy.visit("/admin/audit/tables/all");
cy.findByPlaceholderText("Table name");
cy.findAllByText("PUBLIC").should("have.length", 4);
cy.findAllByText("PUBLIC").should("have.length", 8);
// eslint-disable-next-line no-unscoped-text-selectors -- deprecated usage
cy.findByText("REVIEWS"); // Table name in DB
// eslint-disable-next-line no-unscoped-text-selectors -- deprecated usage
......@@ -226,7 +226,7 @@ describeEE("audit > auditing", () => {
// eslint-disable-next-line no-unscoped-text-selectors -- deprecated usage
cy.findByText("Query views and speed per day");
cy.findAllByText("No results!").should("not.exist");
cy.get(".LineAreaBarChart").should("have.length", 3);
cy.get(".LineAreaBarChart").should("have.length", 1);
cy.get("rect");
cy.get(".voronoi");
......
......@@ -22,9 +22,24 @@ describeEE("audit > auditing > questions", () => {
const QUERY_RUNS_ASC_ORDER = [...QUERY_RUNS_DESC_ORDER].reverse();
_.times(1, () => visitQuestion(ORDERS_QUESTION_ID));
_.times(2, () => visitQuestion(ORDERS_COUNT_QUESTION_ID));
_.times(3, () => visitQuestion(ORDERS_BY_YEAR_QUESTION_ID));
_.times(1, () =>
visitQuestionAndVerifyTitle(
ORDERS_QUESTION_ID,
QUERY_RUNS_DESC_ORDER[2],
),
);
_.times(2, () =>
visitQuestionAndVerifyTitle(
ORDERS_COUNT_QUESTION_ID,
QUERY_RUNS_DESC_ORDER[1],
),
);
_.times(3, () =>
visitQuestionAndVerifyTitle(
ORDERS_BY_YEAR_QUESTION_ID,
QUERY_RUNS_DESC_ORDER[0],
),
);
cy.visit("/admin/audit/questions/all");
......@@ -51,7 +66,7 @@ describeEE("audit > auditing > questions", () => {
});
it("should support filtering by collection name", () => {
const FIRST_COLLECTION_ID = 9;
const FIRST_COLLECTION_ID = 10;
cy.createNativeQuestion({
name: "My question",
......@@ -90,3 +105,8 @@ const assertRowsOrder = names => {
cy.wrap(nameColumn).should("have.text", names[index]);
});
};
const visitQuestionAndVerifyTitle = (id, title) => {
visitQuestion(id);
cy.findByTestId("saved-question-header-title").should("have.value", title);
};
......@@ -6,6 +6,9 @@ import {
visualize,
startNewQuestion,
main,
addOrUpdateDashboardCard,
visitDashboardAndCreateTab,
popover,
} from "e2e/support/helpers";
import { SAMPLE_DB_ID } from "e2e/support/cypress_data";
......@@ -226,4 +229,33 @@ describe("scenarios > x-rays", () => {
// eslint-disable-next-line no-unscoped-text-selectors -- deprecated usage
cy.findByText("463");
});
it("should be able to open x-ray on a dashcard from a dashboard with multiple tabs", () => {
cy.intercept("POST", "/api/dataset").as("dataset");
return cy.createDashboard(name).then(({ body: { id: dashboard_id } }) => {
addOrUpdateDashboardCard({
card_id: 3,
dashboard_id,
card: {
row: 0,
col: 0,
size_x: 24,
size_y: 10,
visualization_settings: {},
},
});
visitDashboardAndCreateTab({ dashboardId: dashboard_id });
cy.findByRole("tab", { name: "Tab 1" }).click();
cy.get("circle").eq(0).click({ force: true });
popover().findByText("Automatic insights…").click();
popover().findByText("X-ray").click();
cy.wait("@dataset", { timeout: 30000 });
// Ensure charts actually got rendered
cy.get("text.x-axis-label").contains("Created At");
});
});
});
......@@ -44,6 +44,7 @@ import {
getDashboardType,
fetchDataOrError,
getDatasetQueryParams,
getCurrentTabDashboardCards,
} from "../utils";
import { DASHBOARD_SLOW_TIMEOUT } from "../constants";
import { loadMetadataForDashboard } from "./metadata";
......@@ -424,23 +425,14 @@ export const fetchDashboardCardData = createThunkAction(
const dashboard = getDashboardComplete(getState());
const selectedTabId = getSelectedTabId(getState());
const dashcardIds = [];
const promises = getAllDashboardCards(dashboard)
const promises = getCurrentTabDashboardCards(dashboard, selectedTabId)
.filter(({ dashcard }) => !isVirtualDashCard(dashcard))
.map(({ card, dashcard }) => {
if (
isVirtualDashCard(dashcard) ||
(selectedTabId !== undefined &&
dashcard.dashboard_tab_id !== selectedTabId)
) {
return;
}
dashcardIds.push(dashcard.id);
return dispatch(fetchCardData(card, dashcard, options)).then(() => {
return dispatch(updateLoadingTitle());
});
})
.filter(p => !!p);
});
dispatch(setDocumentTitle(t`0/${promises.length} loaded`));
......
......@@ -11,6 +11,7 @@ import {
DashboardTabId,
} from "metabase-types/api";
import { DashboardState, TabDeletionId } from "metabase-types/store";
import { INITIALIZE } from "metabase/dashboard/actions/core";
import { INITIAL_DASHBOARD_STATE } from "../constants";
......@@ -307,6 +308,16 @@ export const tabsReducer = createReducer<DashboardState>(
},
);
builder.addCase<
string,
{ type: string; payload?: { clearCache: boolean } }
>(INITIALIZE, (state, { payload: { clearCache = true } = {} }) => {
if (clearCache) {
state.selectedTabId = INITIAL_DASHBOARD_STATE.selectedTabId;
state.tabDeletions = INITIAL_DASHBOARD_STATE.tabDeletions;
}
});
builder.addCase(initTabs, (state, { payload: { slug } }) => {
const { prevTabs } = getPrevDashAndTabs({ state });
......
......@@ -7,7 +7,7 @@ import {
getPermissionErrorMessage,
} from "metabase/visualizations/lib/errors";
import { IS_EMBED_PREVIEW } from "metabase/lib/embed";
import {
import type {
Card,
CardId,
DashCardId,
......@@ -20,6 +20,7 @@ import {
StructuredDatasetQuery,
ActionDashboardCard,
} from "metabase-types/api";
import type { SelectedTabId } from "metabase-types/store";
import Question from "metabase-lib/Question";
import {
isDateParameter,
......@@ -127,6 +128,17 @@ export function getAllDashboardCards(dashboard: Dashboard) {
return results;
}
export function getCurrentTabDashboardCards(
dashboard: Dashboard,
selectedTabId: SelectedTabId,
) {
return getAllDashboardCards(dashboard).filter(
({ dashcard }) =>
(dashcard.dashboard_tab_id == null && selectedTabId == null) ||
dashcard.dashboard_tab_id === selectedTabId,
);
}
export function hasDatabaseActionsEnabled(database: Database) {
return database.settings?.["database-enable-actions"] ?? false;
}
......
import {
fetchDataOrError,
getCurrentTabDashboardCards,
getDashcardResultsError,
getVisibleCardIds,
hasDatabaseActionsEnabled,
......@@ -7,6 +8,7 @@ import {
syncParametersAndEmbeddingParams,
} from "metabase/dashboard/utils";
import {
createMockDashboard,
createMockDashboardCardWithVirtualCard,
createMockDashboardOrderedCard,
createMockDatabase,
......@@ -284,4 +286,48 @@ describe("Dashboard utils", () => {
);
});
});
describe("getCurrentTabDashboardCards", () => {
it("when selectedTabId=null returns cards with dashboard_tab_id=undefined", () => {
const selectedTabId = null;
const dashcard = createMockDashboardOrderedCard({
dashboard_tab_id: undefined,
});
const dashboard = createMockDashboard({
ordered_cards: [dashcard],
});
expect(
getCurrentTabDashboardCards(dashboard, selectedTabId),
).toStrictEqual([
{
card: dashcard.card,
dashcard,
},
]);
});
it("returns cards from selected tab only", () => {
const selectedTabId = 1;
const visibleDashcard = createMockDashboardOrderedCard({
dashboard_tab_id: 1,
});
const hiddenDashcard = createMockDashboardOrderedCard({
dashboard_tab_id: 2,
});
const dashboard = createMockDashboard({
ordered_cards: [visibleDashcard, hiddenDashcard],
});
expect(
getCurrentTabDashboardCards(dashboard, selectedTabId),
).toStrictEqual([
{
card: visibleDashcard.card,
dashcard: visibleDashcard,
},
]);
});
});
});
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment