diff --git a/e2e/test/scenarios/admin/databases/add-new-database.cy.spec.js b/e2e/test/scenarios/admin/databases/add-new-database.cy.spec.js index c964b3338f2abe7cf27e895c33b982393378916a..53ad65d8296fe9fb80cb5954bf5e27bae2f26875 100644 --- a/e2e/test/scenarios/admin/databases/add-new-database.cy.spec.js +++ b/e2e/test/scenarios/admin/databases/add-new-database.cy.spec.js @@ -27,128 +27,146 @@ describe("admin > database > add", () => { }); describe("external databases", { tags: "@external" }, () => { - it("should add Postgres database and redirect to listing (metabase#12972, metabase#14334, metabase#17450)", () => { - popover().within(() => { - if (isEE) { - // EE should ship with Oracle and Vertica as options - cy.findByText("Oracle"); - cy.findByText("Vertica"); - } - }); + describe("postgres", () => { + beforeEach(() => { + popover().within(() => { + if (isEE) { + // EE should ship with Oracle and Vertica as options + cy.findByText("Oracle"); + cy.findByText("Vertica"); + } + }); - popover().contains("PostgreSQL").click({ force: true }); + popover().contains("PostgreSQL").click({ force: true }); - cy.findByTestId("database-form").within(() => { - cy.findByText("Show advanced options").click(); - cy.findByLabelText("Rerun queries for simple explorations").should( - "have.attr", - "aria-checked", - "true", - ); - // Reproduces (metabase#14334) - cy.findByText("Additional JDBC connection string options"); - // Reproduces (metabase#17450) - cy.findByLabelText("Choose when syncs and scans happen") - .click() - .should("have.attr", "aria-checked", "true"); - cy.findByLabelText("Never, I'll do this manually if I need to").should( - "have.attr", - "aria-selected", - "true", + cy.findByTestId("database-form").within(() => { + cy.findByText("Show advanced options").click(); + cy.findByLabelText("Rerun queries for simple explorations").should( + "have.attr", + "aria-checked", + "true", + ); + // Reproduces (metabase#14334) + cy.findByText("Additional JDBC connection string options"); + // Reproduces (metabase#17450) + cy.findByLabelText("Choose when syncs and scans happen") + .click() + .should("have.attr", "aria-checked", "true"); + cy.findByLabelText( + "Never, I'll do this manually if I need to", + ).should("have.attr", "aria-selected", "true"); + + // make sure fields needed to connect to the database are properly trimmed (metabase#12972) + typeAndBlurUsingLabel("Display name", "QA Postgres12"); + typeAndBlurUsingLabel("Host", "localhost"); + typeAndBlurUsingLabel("Port", QA_POSTGRES_PORT); + typeAndBlurUsingLabel("Database name", "sample"); + typeAndBlurUsingLabel("Username", "metabase"); + typeAndBlurUsingLabel("Password", "metasample123"); + }); + + const confirmSSLFields = (visible, hidden) => { + visible.forEach(field => cy.findByText(field)); + hidden.forEach(field => cy.findByText(field).should("not.exist")); + }; + + const ssl = "Use a secure connection (SSL)", + sslMode = "SSL Mode", + useClientCert = "Authenticate client certificate?", + clientPemCert = "SSL Client Certificate (PEM)", + clientPkcsCert = "SSL Client Key (PKCS-8/DER)", + sslRootCert = "SSL Root Certificate (PEM)"; + + // initially, all SSL sub-properties should be hidden + confirmSSLFields( + [ssl], + [sslMode, useClientCert, clientPemCert, clientPkcsCert, sslRootCert], ); - // make sure fields needed to connect to the database are properly trimmed (metabase#12972) - typeAndBlurUsingLabel("Display name", "QA Postgres12"); - typeAndBlurUsingLabel("Host", "localhost"); - typeAndBlurUsingLabel("Port", QA_POSTGRES_PORT); - typeAndBlurUsingLabel("Database name", "sample"); - typeAndBlurUsingLabel("Username", "metabase"); - typeAndBlurUsingLabel("Password", "metasample123"); - }); + toggleFieldWithDisplayName(ssl); + // when ssl is enabled, the mode and "enable client cert" options should be shown + confirmSSLFields( + [ssl, sslMode, useClientCert], + [clientPemCert, clientPkcsCert, sslRootCert], + ); - const confirmSSLFields = (visible, hidden) => { - visible.forEach(field => cy.findByText(field)); - hidden.forEach(field => cy.findByText(field).should("not.exist")); - }; - - const ssl = "Use a secure connection (SSL)", - sslMode = "SSL Mode", - useClientCert = "Authenticate client certificate?", - clientPemCert = "SSL Client Certificate (PEM)", - clientPkcsCert = "SSL Client Key (PKCS-8/DER)", - sslRootCert = "SSL Root Certificate (PEM)"; - - // initially, all SSL sub-properties should be hidden - confirmSSLFields( - [ssl], - [sslMode, useClientCert, clientPemCert, clientPkcsCert, sslRootCert], - ); + toggleFieldWithDisplayName(useClientCert); + // when the "enable client cert" option is enabled, its sub-properties should be shown + confirmSSLFields( + [ssl, sslMode, useClientCert, clientPemCert, clientPkcsCert], + [sslRootCert], + ); - toggleFieldWithDisplayName(ssl); - // when ssl is enabled, the mode and "enable client cert" options should be shown - confirmSSLFields( - [ssl, sslMode, useClientCert], - [clientPemCert, clientPkcsCert, sslRootCert], - ); + selectFieldOption(sslMode, "verify-ca"); + // when the ssl mode is set to "verify-ca", then the root cert option should be shown + confirmSSLFields( + [ + ssl, + sslMode, + useClientCert, + clientPemCert, + clientPkcsCert, + sslRootCert, + ], + [], + ); + toggleFieldWithDisplayName(ssl); - toggleFieldWithDisplayName(useClientCert); - // when the "enable client cert" option is enabled, its sub-properties should be shown - confirmSSLFields( - [ssl, sslMode, useClientCert, clientPemCert, clientPkcsCert], - [sslRootCert], - ); + cy.button("Save").should("not.be.disabled").click(); - selectFieldOption(sslMode, "verify-ca"); - // when the ssl mode is set to "verify-ca", then the root cert option should be shown - confirmSSLFields( - [ - ssl, - sslMode, - useClientCert, - clientPemCert, - clientPkcsCert, - sslRootCert, - ], - [], - ); - toggleFieldWithDisplayName(ssl); + cy.wait("@createDatabase").then(({ request }) => { + expect(request.body.details.host).to.equal("localhost"); + expect(request.body.details.dbname).to.equal("sample"); + expect(request.body.details.user).to.equal("metabase"); + }); - cy.button("Save").should("not.be.disabled").click(); + cy.url().should( + "match", + /\/admin\/databases\?created=true&createdDbId=\d$/, + ); - cy.wait("@createDatabase").then(({ request }) => { - expect(request.body.details.host).to.equal("localhost"); - expect(request.body.details.dbname).to.equal("sample"); - expect(request.body.details.user).to.equal("metabase"); + waitForDbSync(); }); - cy.url().should("match", /\/admin\/databases\?created=true$/); + it("should add Postgres database and redirect to listing (metabase#12972, metabase#14334, metabase#17450)", () => { + cy.findByRole("dialog").within(() => { + cy.findByText( + "Your database was added! Want to configure permissions?", + ).should("exist"); + cy.button("Maybe later").click(); + }); - waitForDbSync(); + cy.findByRole("status").within(() => { + cy.findByText("Done!"); + }); - cy.findByRole("dialog").within(() => { - cy.findByText("We're taking a look at your database!"); - cy.icon("close").click(); - }); + cy.findByRole("table").within(() => { + cy.findByText("QA Postgres12").click(); + }); - cy.findByRole("status").within(() => { - cy.findByText("Done!"); - }); + cy.findByLabelText("Choose when syncs and scans happen").should( + "have.attr", + "aria-checked", + "true", + ); - cy.findByRole("table").within(() => { - cy.findByText("QA Postgres12").click(); + cy.findByLabelText("Never, I'll do this manually if I need to").should( + "have.attr", + "aria-selected", + "true", + ); }); - cy.findByLabelText("Choose when syncs and scans happen").should( - "have.attr", - "aria-checked", - "true", - ); + it("should show a modal allowing you to redirect to the permissions page", () => { + cy.findByRole("dialog").within(() => { + cy.findByText( + "Your database was added! Want to configure permissions?", + ).should("exist"); + cy.findByRole("link", { name: "Configure permissions" }).click(); + }); - cy.findByLabelText("Never, I'll do this manually if I need to").should( - "have.attr", - "aria-selected", - "true", - ); + cy.findByTestId("permissions-editor").findByText(/QA Postgres12/); + }); }); it( @@ -175,11 +193,16 @@ describe("admin > database > add", () => { cy.wait("@createDatabase"); - cy.url().should("match", /\/admin\/databases\?created=true$/); + cy.url().should( + "match", + /\/admin\/databases\?created=true&createdDbId=\d$/, + ); cy.findByRole("dialog").within(() => { - cy.findByText("We're taking a look at your database!"); - cy.findByLabelText("close icon").click(); + cy.findByText( + "Your database was added! Want to configure permissions?", + ).should("exist"); + cy.button("Maybe later").click(); }); cy.findByRole("table").within(() => { @@ -236,11 +259,16 @@ describe("admin > database > add", () => { cy.wait("@createDatabase"); - cy.url().should("match", /\/admin\/databases\?created=true$/); + cy.url().should( + "match", + /\/admin\/databases\?created=true&createdDbId=\d$/, + ); cy.findByRole("dialog").within(() => { - cy.findByText("We're taking a look at your database!"); - cy.findByLabelText("close icon").click(); + cy.findByText( + "Your database was added! Want to configure permissions?", + ).should("exist"); + cy.button("Maybe later").click(); }); cy.findByRole("table").within(() => { @@ -281,11 +309,16 @@ describe("admin > database > add", () => { cy.wait("@createDatabase"); - cy.url().should("match", /\/admin\/databases\?created=true$/); + cy.url().should( + "match", + /\/admin\/databases\?created=true&createdDbId=\d$/, + ); cy.findByRole("dialog").within(() => { - cy.findByText("We're taking a look at your database!"); - cy.findByLabelText("close icon").click(); + cy.findByText( + "Your database was added! Want to configure permissions?", + ).should("exist"); + cy.button("Maybe later").click(); }); cy.findByRole("table").within(() => { diff --git a/frontend/src/metabase/admin/databases/components/DatabaseList/DatabaseList.jsx b/frontend/src/metabase/admin/databases/components/DatabaseList/DatabaseList.jsx index 56d8df57c5ffa4f0d62b9d5b9c7019779e897d15..bb62be68bae484edd68da21cddafd6cf242304fe 100644 --- a/frontend/src/metabase/admin/databases/components/DatabaseList/DatabaseList.jsx +++ b/frontend/src/metabase/admin/databases/components/DatabaseList/DatabaseList.jsx @@ -6,14 +6,13 @@ import { Link } from "react-router"; import { t } from "ttag"; import LoadingSpinner from "metabase/components/LoadingSpinner"; -import Modal from "metabase/components/Modal"; import AdminS from "metabase/css/admin.module.css"; import ButtonsS from "metabase/css/components/buttons.module.css"; import CS from "metabase/css/core/index.css"; -import { DatabaseSyncModal } from "metabase/databases/components/DatabaseSyncModal"; import { FormMessage } from "metabase/forms"; import { isSyncCompleted } from "metabase/lib/syncing"; import { PLUGIN_FEATURE_LEVEL_PERMISSIONS } from "metabase/plugins"; +import { Button, Flex, Modal, Text } from "metabase/ui"; import { TableCellContent, @@ -34,18 +33,12 @@ export default class DatabaseList extends Component { }); this.state = { - isSyncingModalOpened: (props.created && props.showSyncingModal) || false, + isPermissionModalOpened: (props.created && props.createdDbId) || false, }; } - componentDidMount() { - if (this.state.isSyncingModalOpened) { - this.props.closeSyncingModal(); - } - } - - onSyncingModalClose = () => { - this.setState({ isSyncingModalOpened: false }); + onPermissionModalClose = () => { + this.setState({ isPermissionModalOpened: false }); }; static propTypes = { @@ -55,6 +48,7 @@ export default class DatabaseList extends Component { deletes: PropTypes.array, deletionError: PropTypes.object, created: PropTypes.string, + createdDbId: PropTypes.string, showSyncingModal: PropTypes.bool, closeSyncingModal: PropTypes.func, isAdmin: PropTypes.bool, @@ -69,8 +63,9 @@ export default class DatabaseList extends Component { engines, deletionError, isAdmin, + createdDbId, } = this.props; - const { isSyncingModalOpened } = this.state; + const { isPermissionModalOpened } = this.state; const error = deletionError || addSampleDatabaseError; @@ -167,13 +162,38 @@ export default class DatabaseList extends Component { </div> ) : null} </section> - <Modal - small - isOpen={isSyncingModalOpened} - onClose={this.onSyncingModalClose} + + {/* Needed to make this a composed modal to get the padding we wanted. + Not sure why the padding prop didn't work */} + <Modal.Root + opened={isPermissionModalOpened} + size={620} + withCloseButton={false} > - <DatabaseSyncModal onClose={this.onSyncingModalClose} /> - </Modal> + <Modal.Overlay /> + <Modal.Content p="1rem"> + <Modal.Header> + <Modal.Title fz="1.25rem">{t`Your database was added! Want to configure permissions?`}</Modal.Title> + </Modal.Header> + <Modal.Body> + <Text + mb="1.5rem" + mt="1rem" + >{t`You can change these settings later in the Permissions tab. Do you want to configure it?`}</Text> + <Flex justify="end"> + <Button + mr="0.5rem" + onClick={this.onPermissionModalClose} + >{t`Maybe later`}</Button> + <Button + component={Link} + variant="filled" + to={`/admin/permissions/data/database/${createdDbId}`} + >{t`Configure permissions`}</Button> + </Flex> + </Modal.Body> + </Modal.Content> + </Modal.Root> </div> ); } diff --git a/frontend/src/metabase/admin/databases/containers/DatabaseEditApp.tsx b/frontend/src/metabase/admin/databases/containers/DatabaseEditApp.tsx index 91532ea3844d05704460fe892ca546996849996c..8b532b28f65e5fc29d04595495e004767437e656 100644 --- a/frontend/src/metabase/admin/databases/containers/DatabaseEditApp.tsx +++ b/frontend/src/metabase/admin/databases/containers/DatabaseEditApp.tsx @@ -58,7 +58,7 @@ interface DatabaseEditAppProps { databaseId: DatabaseId, isDetailView: boolean, ) => Promise<void>; - saveDatabase: (database: DatabaseData) => void; + saveDatabase: (database: DatabaseData) => Database; updateDatabase: ( database: { id: DatabaseId } & Partial<DatabaseType>, ) => Promise<void>; @@ -141,11 +141,12 @@ function DatabaseEditApp(props: DatabaseEditAppProps) { ]; const handleSubmit = async (database: DatabaseData) => { try { - await saveDatabase(database); - + const savedDB = await saveDatabase(database); if (addingNewDatabase) { scheduleCallback(() => { - onChangeLocation("/admin/databases?created=true"); + onChangeLocation( + `/admin/databases?created=true&createdDbId=${savedDB.id}`, + ); }); } } catch (error) { diff --git a/frontend/src/metabase/admin/databases/containers/DatabaseEditApp.unit.spec.tsx b/frontend/src/metabase/admin/databases/containers/DatabaseEditApp.unit.spec.tsx index 1dd8601df5cd91fd18ee62e36537f1c32a242a59..86867d38773127585094c971c957361a4d443e89 100644 --- a/frontend/src/metabase/admin/databases/containers/DatabaseEditApp.unit.spec.tsx +++ b/frontend/src/metabase/admin/databases/containers/DatabaseEditApp.unit.spec.tsx @@ -196,7 +196,8 @@ describe("DatabaseEditApp", () => { ); }); - expect(history.getCurrentLocation().search).toEqual("?created=true"); + expect(history.getCurrentLocation().search).toContain("created=true"); + expect(history.getCurrentLocation().search).toContain("createdDbId"); //Enpoint doesn't return an ID expect( screen.queryByTestId("leave-confirmation"), diff --git a/frontend/src/metabase/admin/databases/containers/DatabaseListApp.jsx b/frontend/src/metabase/admin/databases/containers/DatabaseListApp.jsx index 45aac844a3403e661a172e95c46a8c4192344d8c..323ed1366056fbbb8355bca18e9570cca4ea66f4 100644 --- a/frontend/src/metabase/admin/databases/containers/DatabaseListApp.jsx +++ b/frontend/src/metabase/admin/databases/containers/DatabaseListApp.jsx @@ -40,6 +40,7 @@ const mapStateToProps = (state, props) => ({ addSampleDatabaseError: getAddSampleDatabaseError(state), created: props.location.query.created, + createdDbId: props.location.query.createdDbId, engines: MetabaseSettings.get("engines"), showSyncingModal: MetabaseSettings.get("show-database-syncing-modal"), diff --git a/frontend/src/metabase/admin/databases/database.js b/frontend/src/metabase/admin/databases/database.js index 43d1466a86a56c148ba10142e3cb7f4efde06465..f22051955f0ec5bcb6c7586ceacf9cc0b8066a6e 100644 --- a/frontend/src/metabase/admin/databases/database.js +++ b/frontend/src/metabase/admin/databases/database.js @@ -156,7 +156,8 @@ export const createDatabase = function (database) { return async function (dispatch, getState) { try { dispatch({ type: CREATE_DATABASE_STARTED }); - await dispatch(Databases.actions.create(database)); + const action = await dispatch(Databases.actions.create(database)); + const savedDatabase = Databases.HACK_getObjectFromAction(action); MetabaseAnalytics.trackStructEvent( "Databases", "Create", @@ -164,6 +165,8 @@ export const createDatabase = function (database) { ); dispatch({ type: CREATE_DATABASE }); + + return savedDatabase; } catch (error) { console.error("error creating a database", error); MetabaseAnalytics.trackStructEvent( @@ -189,6 +192,7 @@ export const updateDatabase = function (database) { ); dispatch({ type: UPDATE_DATABASE, payload: { database: savedDatabase } }); + return savedDatabase; } catch (error) { MetabaseAnalytics.trackStructEvent( "Databases", @@ -207,9 +211,9 @@ export const saveDatabase = function (database) { return async function (dispatch, getState) { const isUnsavedDatabase = !database.id; if (isUnsavedDatabase) { - await dispatch(createDatabase(database)); + return await dispatch(createDatabase(database)); } else { - await dispatch(updateDatabase(database)); + return await dispatch(updateDatabase(database)); } }; }; diff --git a/frontend/src/metabase/databases/components/DatabaseSyncModal/DatabaseSyncModal.styled.tsx b/frontend/src/metabase/databases/components/DatabaseSyncModal/DatabaseSyncModal.styled.tsx deleted file mode 100644 index b66bf21a7e149fca8cd31f0e6ddf31f64985c3b6..0000000000000000000000000000000000000000 --- a/frontend/src/metabase/databases/components/DatabaseSyncModal/DatabaseSyncModal.styled.tsx +++ /dev/null @@ -1,50 +0,0 @@ -import styled from "@emotion/styled"; - -import { color } from "metabase/lib/colors"; -import { Icon } from "metabase/ui"; - -export const ModalRoot = styled.div` - position: relative; -`; - -export const ModalBody = styled.div` - display: flex; - flex-direction: column; - align-items: center; - padding: 2.5rem 3rem; -`; - -export const ModalTitle = styled.div` - color: ${color("text-dark")}; - font-size: 1.25rem; - font-weight: 700; - line-height: 1.5rem; - margin-bottom: 0.75rem; - text-align: center; -`; - -export const ModalMessage = styled.div` - color: ${color("text-dark")}; - line-height: 1.5rem; - margin-bottom: 3rem; - text-align: center; -`; - -export const ModalIllustration = styled.img` - margin-top: 1.5rem; - margin-bottom: 3rem; -`; - -export const ModalCloseIcon = styled(Icon)` - position: absolute; - top: 1rem; - right: 1rem; - width: 1rem; - height: 1rem; - color: ${color("text-light")}; - cursor: pointer; - - &:hover { - color: ${color("text-medium")}; - } -`; diff --git a/frontend/src/metabase/databases/components/DatabaseSyncModal/DatabaseSyncModal.tsx b/frontend/src/metabase/databases/components/DatabaseSyncModal/DatabaseSyncModal.tsx deleted file mode 100644 index 76dbca8f2c8de827fe173f72ead56e95e8421eed..0000000000000000000000000000000000000000 --- a/frontend/src/metabase/databases/components/DatabaseSyncModal/DatabaseSyncModal.tsx +++ /dev/null @@ -1,93 +0,0 @@ -import cx from "classnames"; -import { jt, t } from "ttag"; - -import { useListDatabaseCandidatesQuery, skipToken } from "metabase/api"; -import { useDatabaseListQuery } from "metabase/common/hooks"; -import { useSetting } from "metabase/common/hooks/use-setting"; -import Button from "metabase/core/components/Button"; -import Link from "metabase/core/components/Link"; -import ButtonsS from "metabase/css/components/buttons.module.css"; -import type { DatabaseCandidate, TableCandidate } from "metabase-types/api"; - -import { - ModalMessage, - ModalIllustration, - ModalRoot, - ModalTitle, - ModalBody, - ModalCloseIcon, -} from "./DatabaseSyncModal.styled"; - -const getSampleUrl = (candidates: DatabaseCandidate[]) => { - const tables = candidates.flatMap(d => d.tables); - const table = - tables.find((t: TableCandidate) => t.title.includes("Orders")) ?? tables[0]; - return table?.url; -}; - -const useSampleDatabaseLink = () => { - const { data: databases } = useDatabaseListQuery(); - const xraysEnabled = useSetting("enable-xrays"); - const sampleDatabase = databases?.find(d => d.is_sample); - - const { data: databaseCandidates } = useListDatabaseCandidatesQuery( - sampleDatabase?.id && xraysEnabled ? sampleDatabase.id : skipToken, - ); - - const sampleUrl = databaseCandidates - ? getSampleUrl(databaseCandidates) - : undefined; - - return sampleUrl; -}; - -export interface DatabaseSyncModalProps { - sampleUrl?: string; - onClose?: () => void; -} - -export const DatabaseSyncModalView = ({ - sampleUrl, - onClose, -}: DatabaseSyncModalProps) => { - return ( - <ModalRoot> - <ModalBody> - <ModalIllustration - src="app/img/syncing-illustration.svg" - width={148} - height={109} - /> - <ModalTitle>{t`We're taking a look at your database!`}</ModalTitle> - <ModalMessage> - {t`You’ll be able to use individual tables as they finish syncing.`}{" "} - {sampleUrl - ? jt`In the meantime, you can take a look at the ${( - <strong key="name">{t`Sample Database`}</strong> - )} if you want to get a head start. Want to explore?` - : // eslint-disable-next-line no-literal-metabase-strings -- Metabase settings - t`Have a look around your Metabase in the meantime if you want to get a head start.`} - </ModalMessage> - {sampleUrl ? ( - <Link - className={cx(ButtonsS.Button, ButtonsS.ButtonPrimary)} - to={sampleUrl} - > - {t`Explore sample data`} - </Link> - ) : ( - <Button primary onClick={onClose}> - {t`Got it`} - </Button> - )} - </ModalBody> - {onClose && <ModalCloseIcon name="close" onClick={onClose} />} - </ModalRoot> - ); -}; - -export const DatabaseSyncModal = ({ onClose }: { onClose: () => void }) => { - const sampleUrl = useSampleDatabaseLink(); - - return <DatabaseSyncModalView sampleUrl={sampleUrl} onClose={onClose} />; -}; diff --git a/frontend/src/metabase/databases/components/DatabaseSyncModal/DatabaseSyncModal.unit.spec.tsx b/frontend/src/metabase/databases/components/DatabaseSyncModal/DatabaseSyncModal.unit.spec.tsx deleted file mode 100644 index 216c0194735dae3befde9b711fb2f1d1130abff7..0000000000000000000000000000000000000000 --- a/frontend/src/metabase/databases/components/DatabaseSyncModal/DatabaseSyncModal.unit.spec.tsx +++ /dev/null @@ -1,21 +0,0 @@ -import { render, screen } from "@testing-library/react"; -import userEvent from "@testing-library/user-event"; - -import { DatabaseSyncModalView } from "./DatabaseSyncModal"; - -describe("DatabaseSyncModal", () => { - it("should render with a table from the sample database", () => { - render(<DatabaseSyncModalView sampleUrl={"/auto/table/1"} />); - - expect(screen.getByText("Explore sample data")).toBeInTheDocument(); - }); - - it("should render with no sample database", async () => { - const onClose = jest.fn(); - - render(<DatabaseSyncModalView onClose={onClose} />); - await userEvent.click(screen.getByText("Got it")); - - expect(onClose).toHaveBeenCalled(); - }); -}); diff --git a/frontend/src/metabase/databases/components/DatabaseSyncModal/index.ts b/frontend/src/metabase/databases/components/DatabaseSyncModal/index.ts deleted file mode 100644 index c17a9ef0d871c9221c410157e3281da70bb64205..0000000000000000000000000000000000000000 --- a/frontend/src/metabase/databases/components/DatabaseSyncModal/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from "./DatabaseSyncModal";