Skip to content
Snippets Groups Projects
Unverified Commit 2cd8df58 authored by Alexander Polyankin's avatar Alexander Polyankin Committed by GitHub
Browse files

Make api server mocks use api mocks (#27635)

parent 6c439596
No related branches found
No related tags found
No related merge requests found
......@@ -43,6 +43,7 @@ export interface Database extends DatabaseData {
// Only appears in GET /api/database/:id
"can-manage"?: boolean;
tables?: Table[];
}
export interface DatabaseData {
......
......@@ -8,7 +8,7 @@ import {
waitForElementToBeRemoved,
} from "__support__/ui";
import {
setupCollectionEndpoints,
setupCollectionsEndpoints,
setupCollectionVirtualSchemaEndpoints,
setupDatabasesEndpoints,
} from "__support__/server-mocks";
......@@ -20,12 +20,12 @@ import {
import { ROOT_COLLECTION } from "metabase/entities/collections";
import type { Collection } from "metabase-types/api";
import { Collection } from "metabase-types/api";
import { createMockCard, createMockCollection } from "metabase-types/api/mocks";
import { createMockSettingsState } from "metabase-types/store/mocks";
import type Database from "metabase-lib/metadata/Database";
import Database from "metabase-lib/metadata/Database";
import Table from "metabase-lib/metadata/Table";
import type { DataPickerValue, DataPickerFiltersProp } from "../types";
import useDataPickerValue from "../useDataPickerValue";
......@@ -130,26 +130,26 @@ export async function setup({
const scope = nock(location.origin);
if (hasDataAccess) {
const databases: Database[] = [SAMPLE_DATABASE];
const databases = [getDatabaseObject(SAMPLE_DATABASE)];
if (hasMultiSchemaDatabase) {
databases.push(MULTI_SCHEMA_DATABASE);
databases.push(getDatabaseObject(MULTI_SCHEMA_DATABASE));
}
if (hasEmptyDatabase) {
databases.push(ANOTHER_DATABASE);
databases.push(getDatabaseObject(ANOTHER_DATABASE));
}
setupDatabasesEndpoints(scope, databases);
} else {
scope.get("/api/database").reply(200, []);
setupDatabasesEndpoints(scope, []);
}
scope
.get("/api/search?models=dataset&limit=1")
.reply(200, { data: hasModels ? [SAMPLE_MODEL] : [] });
setupCollectionEndpoints(scope, [SAMPLE_COLLECTION, EMPTY_COLLECTION]);
setupCollectionsEndpoints(scope, [SAMPLE_COLLECTION, EMPTY_COLLECTION]);
setupCollectionVirtualSchemaEndpoints(
scope,
......@@ -194,3 +194,17 @@ export async function setup({
return { onChange };
}
function getDatabaseObject(database: Database) {
return {
...database.getPlainObject(),
tables: database.tables.map(getTableObject),
};
}
function getTableObject(table: Table) {
return {
...table.getPlainObject(),
schema: table.schema_name,
};
}
......@@ -14,10 +14,10 @@ import {
} from "__support__/ui";
import { ORDERS, PRODUCTS, PEOPLE } from "__support__/sample_database_fixture";
import {
setupCardEndpoints,
setupCollectionEndpoints,
setupCardsEndpoints,
setupCollectionsEndpoints,
setupDatabasesEndpoints,
setupTableEndpoints,
setupTablesEndpoints,
} from "__support__/server-mocks";
import Models from "metabase/entities/questions";
......@@ -26,6 +26,8 @@ import type { Card, Collection, Field } from "metabase-types/api";
import { createMockCollection, createMockUser } from "metabase-types/api/mocks";
import type Question from "metabase-lib/Question";
import Database from "metabase-lib/metadata/Database";
import Table from "metabase-lib/metadata/Table";
import {
getStructuredModel as _getStructuredModel,
getNativeModel as _getNativeModel,
......@@ -81,8 +83,8 @@ async function setup({ model, collections = [], usedBy = [] }: SetupOpts) {
const slug = `${card.id}-model-name`;
if (database) {
setupDatabasesEndpoints(scope, [database]);
setupTableEndpoints(scope, tables);
setupDatabasesEndpoints(scope, [getDatabaseObject(database)]);
setupTablesEndpoints(scope, tables.map(getTableObject));
}
scope
......@@ -93,9 +95,9 @@ async function setup({ model, collections = [], usedBy = [] }: SetupOpts) {
usedBy.map(question => question.card()),
);
setupCardEndpoints(scope, [card]);
setupCardsEndpoints(scope, [card]);
setupCollectionEndpoints(scope, collections);
setupCollectionsEndpoints(scope, collections);
renderWithProviders(<ModelDetailPage params={{ slug }} />, {
withSampleDatabase: true,
......@@ -108,6 +110,20 @@ async function setup({ model, collections = [], usedBy = [] }: SetupOpts) {
return { modelUpdateSpy };
}
function getDatabaseObject(database: Database) {
return {
...database.getPlainObject(),
tables: database.tables.map(getTableObject),
};
}
function getTableObject(table: Table) {
return {
...table.getPlainObject(),
schema: table.schema_name,
};
}
describe("ModelDetailPage", () => {
afterEach(() => {
nock.cleanAll();
......
import type { Scope } from "nock";
import type { Card } from "metabase-types/api";
import { Scope } from "nock";
import { Card } from "metabase-types/api";
import { createMockCard } from "metabase-types/api/mocks";
import {
getQuestionVirtualTableId,
convertSavedQuestionToVirtualTable,
} from "metabase-lib/metadata/utils/saved-questions";
function setupForSingleCard(scope: Scope, card: Card) {
export function setupCardEndpoints(scope: Scope, card: Card) {
scope.get(`/api/card/${card.id}`).reply(200, card);
scope
.put(`/api/card/${card.id}`)
......@@ -26,7 +25,7 @@ function setupForSingleCard(scope: Scope, card: Card) {
}
}
export function setupCardEndpoints(scope: Scope, cards: Card[]) {
export function setupCardsEndpoints(scope: Scope, cards: Card[]) {
scope.get("/api/card").reply(200, cards);
cards.forEach(card => setupForSingleCard(scope, card));
cards.forEach(card => setupCardEndpoints(scope, card));
}
import _ from "underscore";
import type { Scope } from "nock";
import _ from "underscore";
import { ROOT_COLLECTION } from "metabase/entities/collections";
import type { Card, Collection } from "metabase-types/api";
import { Card, Collection } from "metabase-types/api";
import {
convertSavedQuestionToVirtualTable,
getCollectionVirtualSchemaName,
SAVED_QUESTIONS_VIRTUAL_DB_ID,
} from "metabase-lib/metadata/utils/saved-questions";
export function setupCollectionEndpoints(
export function setupCollectionsEndpoints(
scope: Scope,
collections: Collection[],
) {
......
import { Scope } from "nock";
import _ from "underscore";
import type { Scope } from "nock";
import type Database from "metabase-lib/metadata/Database";
import { cleanTable } from "./utils";
import { Database } from "metabase-types/api";
function setupForSingleDatabase(scope: Scope, db: Database) {
scope.get(`/api/database/${db.id}`).reply(200, db.getPlainObject());
scope.get(`/api/database/${db.id}/schemas`).reply(200, db.schemaNames());
export function setupDatabaseEndpoints(scope: Scope, db: Database) {
scope.get(`/api/database/${db.id}`).reply(200, db);
db.schemas.forEach(schema => {
const schemas = _.groupBy(db.tables ?? [], table => table.schema);
const schemaNames = Object.keys(schemas);
scope.get(`/api/database/${db.id}/schemas`).reply(200, schemaNames);
schemaNames.forEach(schema => {
scope
.get(`/api/database/${db.id}/schema/${schema.name}`)
.reply(200, schema.tables.map(cleanTable));
.get(`/api/database/${db.id}/schema/${schema}`)
.reply(200, schemas[schema]);
});
}
export function setupDatabasesEndpoints(scope: Scope, dbs: Database[]) {
scope.get("/api/database").reply(
200,
dbs.map(db => db.getPlainObject()),
);
dbs.forEach(db => setupForSingleDatabase(scope, db));
scope.get("/api/database").reply(200, dbs);
dbs.forEach(db => setupDatabaseEndpoints(scope, db));
}
import type { Scope } from "nock";
import type Field from "metabase-lib/metadata/Field";
import { Scope } from "nock";
import { Field } from "metabase-types/api";
export function setupFieldEndpoints(scope: Scope, field: Field) {
scope.get(`/api/field/${field.id}`).reply(200, field.getPlainObject());
scope.get(`/api/field/${field.id}`).reply(200, field);
}
import type { Scope } from "nock";
import type Table from "metabase-lib/metadata/Table";
import { Scope } from "nock";
import { Table } from "metabase-types/api";
import { setupFieldEndpoints } from "./field";
import { cleanTable } from "./utils";
function setupForSingleTable(scope: Scope, table: Table) {
scope.get(`/api/table/${table.id}`).reply(200, cleanTable(table));
scope.get(`/api/table/${table.id}/query_metadata`).reply(200, {
...cleanTable(table),
db: table.database?.getPlainObject?.(),
fields: table.fields.map(field => field.getPlainObject()),
});
export function setupTableEndpoint(scope: Scope, table: Table) {
scope.get(`/api/table/${table.id}`).reply(200, table);
scope.get(`/api/table/${table.id}/query_metadata`).reply(200, table);
scope.get(`/api/table/${table.id}/fks`).reply(200, []);
table.fields.forEach(field => setupFieldEndpoints(scope, field));
table.fields?.forEach(field => setupFieldEndpoints(scope, field));
}
export function setupTableEndpoints(scope: Scope, tables: Table[]) {
scope.get("/api/table").reply(200, tables.map(cleanTable));
tables.forEach(table => setupForSingleTable(scope, table));
export function setupTablesEndpoints(scope: Scope, tables: Table[]) {
scope.get("/api/table").reply(200, tables);
tables.forEach(table => setupTableEndpoint(scope, table));
}
import _ from "underscore";
import type { Table as TableObject } from "metabase-types/api";
import type Table from "metabase-lib/metadata/Table";
const TABLE_IGNORE_PROPERTIES = [
"fields",
"metrics",
"segments",
"schema",
"schema_name",
];
export function cleanTable(table: Table): TableObject {
const plainObject = table.getPlainObject();
const cleanObject = _.omit(plainObject, ...TABLE_IGNORE_PROPERTIES);
return {
dimension_options: {},
...cleanObject,
// After table is built inside the metadata object,
// what is normally called "schema" is renamed to "schema_name"
schema: table.schema_name,
} as TableObject;
}
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