Skip to content
Snippets Groups Projects
Unverified Commit a078a4c1 authored by Paul Rosenzweig's avatar Paul Rosenzweig Committed by GitHub
Browse files

fix bug with null remapping, add cypress snapshot with sqlite db (#13037)

parent b8e9d9db
No related branches found
No related tags found
No related merge requests found
......@@ -355,6 +355,8 @@ export class ValueRemappings extends React.Component {
const mappedString =
mappedOrUndefined !== undefined
? mappedOrUndefined.toString()
: original === null
? "null"
: original.toString();
return [original, mappedString];
......
......@@ -109,21 +109,25 @@ export function typeAndBlurUsingLabel(label, value) {
Cypress.on("uncaught:exception", (err, runnable) => false);
export function withSampleDataset(f) {
cy.request("GET", "/api/database/1/metadata").then(({ body }) => {
const SAMPLE_DATASET = {};
export function withDatabase(databaseId, f) {
cy.request("GET", `/api/database/${databaseId}/metadata`).then(({ body }) => {
const database = {};
for (const table of body.tables) {
const fields = {};
for (const field of table.fields) {
fields[field.name] = field.id;
}
SAMPLE_DATASET[table.name] = fields;
SAMPLE_DATASET[table.name + "_ID"] = table.id;
database[table.name] = fields;
database[table.name + "_ID"] = table.id;
}
f(SAMPLE_DATASET);
f(database);
});
}
export function withSampleDataset(f) {
return withDatabase(1, f);
}
export function visitAlias(alias) {
cy.get(alias).then(url => {
cy.visit(url);
......
......@@ -2,7 +2,9 @@ import {
signInAsAdmin,
restore,
withSampleDataset,
withDatabase,
visitAlias,
popover,
} from "__support__/cypress";
describe("scenarios > admin > datamodel > field", () => {
......@@ -159,5 +161,38 @@ describe("scenarios > admin > datamodel > field", () => {
cy.contains("Custom mapping");
cy.get('input[value="foo"]');
});
it("allows 'Custom mapping' null values", () => {
restore("withSqlite");
signInAsAdmin();
const dbId = 2;
withDatabase(
dbId,
({ number_with_nulls: { num }, number_with_nulls_ID }) =>
cy.visit(
`/admin/datamodel/database/${dbId}/table/${number_with_nulls_ID}/${num}/general`,
),
);
// change to custom mapping
cy.findByText("Use original value").click();
popover()
.findByText("Custom mapping")
.click();
// update text for nulls from "null" to "nothin"
cy.get("input[value=null]")
.clear()
.type("nothin");
cy.findByText("Save").click();
cy.findByText("Saved!");
// check that it appears in QB
cy.visit("/question/new");
cy.findByText("Simple question").click();
cy.findByText("sqlite").click();
cy.findByText("Number With Nulls").click();
cy.findByText("nothin");
});
});
});
......@@ -3,156 +3,198 @@ import {
restore,
USERS,
withSampleDataset,
signInAsAdmin,
} from "__support__/cypress";
describe("default", () => {
it("default", () => {
snapshot("blank");
setup();
updateSettings();
addUsersAndGroups();
withSampleDataset(SAMPLE_DATASET => {
createQuestionAndDashboard(SAMPLE_DATASET);
describe("snapshots", () => {
describe("default", () => {
it("default", () => {
snapshot("blank");
setup();
updateSettings();
addUsersAndGroups();
withSampleDataset(SAMPLE_DATASET => {
createQuestionAndDashboard(SAMPLE_DATASET);
});
snapshot("default");
restore("blank");
});
snapshot("default");
restore("blank");
});
});
function makeUserObject(name, groupIds) {
return {
first_name: USERS[name].first_name,
last_name: USERS[name].last_name,
email: USERS[name].username,
password: USERS[name].password,
group_ids: groupIds,
};
}
function setup() {
cy.request("GET", "/api/session/properties").then(({ body: properties }) => {
cy.request("POST", "/api/setup", {
token: properties["setup-token"],
user: makeUserObject("admin"),
prefs: {
site_name: "Epic Team",
allow_tracking: false,
function makeUserObject(name, groupIds) {
return {
first_name: USERS[name].first_name,
last_name: USERS[name].last_name,
email: USERS[name].username,
password: USERS[name].password,
group_ids: groupIds,
};
}
function setup() {
cy.request("GET", "/api/session/properties").then(
({ body: properties }) => {
cy.request("POST", "/api/setup", {
token: properties["setup-token"],
user: makeUserObject("admin"),
prefs: {
site_name: "Epic Team",
allow_tracking: false,
},
database: null,
});
},
database: null,
);
}
function updateSettings() {
cy.request("PUT", "/api/setting/enable-public-sharing", { value: true });
cy.request("PUT", "/api/setting/enable-embedding", { value: true });
cy.request("PUT", "/api/setting/embedding-secret-key", {
value: "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
});
});
}
function updateSettings() {
cy.request("PUT", "/api/setting/enable-public-sharing", { value: true });
cy.request("PUT", "/api/setting/enable-embedding", { value: true });
cy.request("PUT", "/api/setting/embedding-secret-key", {
value: "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
});
// update the Sample db connection string so it is valid in both CI and locally
cy.request("GET", "/api/database/1").then(response => {
response.body.details.db =
"./resources/sample-dataset.db;USER=GUEST;PASSWORD=guest";
cy.request("PUT", "/api/database/1", response.body);
});
}
// update the Sample db connection string so it is valid in both CI and locally
cy.request("GET", "/api/database/1").then(response => {
response.body.details.db =
"./resources/sample-dataset.db;USER=GUEST;PASSWORD=guest";
cy.request("PUT", "/api/database/1", response.body);
});
}
const ALL_USERS_GROUP = 1;
const COLLECTION_GROUP = 4;
const DATA_GROUP = 5;
function addUsersAndGroups() {
// groups
cy.request("POST", "/api/permissions/group", { name: "collection" }); // 4
cy.request("POST", "/api/permissions/group", { name: "data" }); // 5
// additional users
cy.request(
"POST",
"/api/user",
makeUserObject("normal", [ALL_USERS_GROUP, COLLECTION_GROUP, DATA_GROUP]),
);
cy.request(
"POST",
"/api/user",
makeUserObject("nodata", [ALL_USERS_GROUP, COLLECTION_GROUP]),
);
cy.request(
"POST",
"/api/user",
makeUserObject("nocollection", [ALL_USERS_GROUP, DATA_GROUP]),
);
cy.request("POST", "/api/user", makeUserObject("none", [ALL_USERS_GROUP]));
// Make a call to `/api/user` because some things (personal collections) get created there
cy.request("GET", "/api/user");
// permissions
cy.request("PUT", "/api/permissions/graph", {
revision: 0,
groups: {
[ALL_USERS_GROUP]: { "1": { schemas: "none", native: "none" } },
[DATA_GROUP]: { "1": { schemas: "all", native: "write" } },
[COLLECTION_GROUP]: { "1": { schemas: "none", native: "none" } },
},
});
cy.request("PUT", "/api/collection/graph", {
revision: 0,
groups: {
[ALL_USERS_GROUP]: { root: "none" },
[DATA_GROUP]: { root: "none" },
[COLLECTION_GROUP]: { root: "write" },
},
});
}
function createQuestionAndDashboard({ ORDERS, ORDERS_ID }) {
// question 1: Orders
cy.request("POST", "/api/card", {
name: "Orders",
display: "table",
visualization_settings: {},
dataset_query: {
database: 1,
query: { "source-table": ORDERS_ID },
type: "query",
},
});
const ALL_USERS_GROUP = 1;
const COLLECTION_GROUP = 4;
const DATA_GROUP = 5;
// question 2: Orders, Count
cy.request("POST", "/api/card", {
name: "Orders, Count",
display: "table",
visualization_settings: {},
dataset_query: {
database: 1,
query: { "source-table": ORDERS_ID, aggregation: [["count"]] },
type: "query",
},
});
function addUsersAndGroups() {
// groups
cy.request("POST", "/api/permissions/group", { name: "collection" }); // 4
cy.request("POST", "/api/permissions/group", { name: "data" }); // 5
// additional users
cy.request(
"POST",
"/api/user",
makeUserObject("normal", [ALL_USERS_GROUP, COLLECTION_GROUP, DATA_GROUP]),
);
cy.request(
"POST",
"/api/user",
makeUserObject("nodata", [ALL_USERS_GROUP, COLLECTION_GROUP]),
);
cy.request(
"POST",
"/api/user",
makeUserObject("nocollection", [ALL_USERS_GROUP, DATA_GROUP]),
);
cy.request("POST", "/api/user", makeUserObject("none", [ALL_USERS_GROUP]));
cy.request("POST", "/api/card", {
name: "Orders, Count, Grouped by Created At (year)",
dataset_query: {
type: "query",
query: {
"source-table": ORDERS_ID,
aggregation: [["count"]],
breakout: [["datetime-field", ["field-id", ORDERS.CREATED_AT], "year"]],
// Make a call to `/api/user` because some things (personal collections) get created there
cy.request("GET", "/api/user");
// permissions
cy.request("PUT", "/api/permissions/graph", {
revision: 0,
groups: {
[ALL_USERS_GROUP]: { "1": { schemas: "none", native: "none" } },
[DATA_GROUP]: { "1": { schemas: "all", native: "write" } },
[COLLECTION_GROUP]: { "1": { schemas: "none", native: "none" } },
},
database: 1,
},
display: "line",
visualization_settings: {},
});
});
cy.request("PUT", "/api/collection/graph", {
revision: 0,
groups: {
[ALL_USERS_GROUP]: { root: "none" },
[DATA_GROUP]: { root: "none" },
[COLLECTION_GROUP]: { root: "write" },
},
});
}
function createQuestionAndDashboard({ ORDERS, ORDERS_ID }) {
// question 1: Orders
cy.request("POST", "/api/card", {
name: "Orders",
display: "table",
visualization_settings: {},
dataset_query: {
database: 1,
query: { "source-table": ORDERS_ID },
type: "query",
},
});
// dashboard 1: Orders in a dashboard
cy.request("POST", "/api/dashboard", { name: "Orders in a dashboard" });
cy.request("POST", `/api/dashboard/1/cards`, { cardId: 1 });
// question 2: Orders, Count
cy.request("POST", "/api/card", {
name: "Orders, Count",
display: "table",
visualization_settings: {},
dataset_query: {
database: 1,
query: { "source-table": ORDERS_ID, aggregation: [["count"]] },
type: "query",
},
});
// dismiss the "it's ok to play around" modal
Object.values(USERS).map((_, index) =>
cy.request("PUT", `/api/user/${index + 1}/qbnewb`, {}),
);
}
cy.request("POST", "/api/card", {
name: "Orders, Count, Grouped by Created At (year)",
dataset_query: {
type: "query",
query: {
"source-table": ORDERS_ID,
aggregation: [["count"]],
breakout: [
["datetime-field", ["field-id", ORDERS.CREATED_AT], "year"],
],
},
database: 1,
},
display: "line",
visualization_settings: {},
});
// dashboard 1: Orders in a dashboard
cy.request("POST", "/api/dashboard", { name: "Orders in a dashboard" });
cy.request("POST", `/api/dashboard/1/cards`, { cardId: 1 });
// dismiss the "it's ok to play around" modal
Object.values(USERS).map((_, index) =>
cy.request("PUT", `/api/user/${index + 1}/qbnewb`, {}),
);
}
// TODO: It'd be nice to have one file per snapshot.
// To do that we need to enforce execution order among them.
describe("withSqlite", () => {
it("withSqlite", () => {
restore("default");
signInAsAdmin();
cy.request("POST", "/api/database", {
engine: "sqlite",
name: "sqlite",
details: { db: "./resources/sqlite-fixture.db" },
auto_run_queries: true,
is_full_sync: true,
schedules: {
cache_field_values: {
schedule_day: null,
schedule_frame: null,
schedule_hour: 0,
schedule_type: "daily",
},
metadata_sync: {
schedule_day: null,
schedule_frame: null,
schedule_hour: null,
schedule_type: "hourly",
},
},
});
cy.request("POST", "/api/database/2/sync_schema");
cy.request("POST", "/api/database/2/rescan_values");
cy.wait(1000); // wait for sync
snapshot("withSqlite");
restore("blank");
});
});
});
File added
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