it("should let you favorite and unfavorite dashboards", async () => {
    const store = await createTestStore();
    store.pushPath("/dashboards");
    const app = mount(store.getAppContainer());
    await store.waitForActions([FETCH_DASHBOARDS]);

    click(
      app
        .find(DashboardListItem)
        .first()
        .find(".Icon-staroutline"),
    );
    await store.waitForActions([SET_FAVORITED]);
    click(app.find(ListFilterWidget));

    click(app.find(".TestPopover").find('h4[children="Favorites"]'));

    click(
      app
        .find(DashboardListItem)
        .first()
        .find(".Icon-star")
        .first(),
    );
    await store.waitForActions([SET_FAVORITED]);
    expect(app.find(EmptyState).length).toBe(1);
  });
        it("forces you to choose the FK field manually if there is no field with Field Name special type", async () => {
            const { store, fieldApp } = await initFieldApp({ fieldId: USER_ID_FK_ID });

            // Set FK id to `Reviews -> ID`  with a direct metadata update call
            const field = getMetadata(store.getState()).fields[USER_ID_FK_ID]
            await store.dispatch(updateField({
                ...field.getPlainObject(),
                fk_target_field_id: 31
            }));

            const section = fieldApp.find(FieldRemapping)
            const mappingTypePicker = section.find(Select);
            expect(mappingTypePicker.text()).toBe('Use original value')
            click(mappingTypePicker);
            const pickerOptions = mappingTypePicker.find(TestPopover).find("li");
            expect(pickerOptions.length).toBe(2);

            const useFKButton = pickerOptions.at(1).children().first()
            click(useFKButton);
            store.waitForActions([UPDATE_FIELD_DIMENSION, FETCH_TABLE_METADATA])
            // TODO: Figure out a way to avoid using delay – the use of delays may lead to occasional CI failures
            await delay(500);

            expect(section.find(RemappingNamingTip).length).toBe(1)

            dispatchBrowserEvent('mousedown', { e: { target: document.documentElement }})
            await delay(300); // delay needed because of setState in FieldApp; app.update() does not work for whatever reason
            expect(section.find(".text-danger").length).toBe(1) // warning that you should choose a column
        })
    it("lets you open and close the revisions screen", async () => {
      if (!dashboardId)
        throw new Error(
          "Test fails because previous tests failed to create a dashboard",
        );

      const store = await createTestStore();
      const dashboardUrl = Urls.dashboard(dashboardId);
      store.pushPath(dashboardUrl);
      const app = mount(store.getAppContainer());
      await store.waitForActions([FETCH_DASHBOARD]);

      click(app.find(".Icon.Icon-pencil"));
      await store.waitForActions([SET_EDITING_DASHBOARD]);

      click(app.find(".Icon.Icon-history"));

      await store.waitForActions([FETCH_REVISIONS]);
      const modal = app.find(DashboardHistoryModal);
      expect(modal.length).toBe(1);
      expect(store.getPath()).toBe(`${dashboardUrl}/history`);

      click(modal.find(".Icon.Icon-close"));
      await store.waitForActions([BROWSER_HISTORY_PUSH]);
      expect(store.getPath()).toBe(`/dashboard/${dashboardId}`);
    });
    it("should show you scheduling step if you select \"Let me choose when Metabase syncs and scans\"", async () => {
        // we can conveniently test returning to database settings now as well
        const connectionStep = app.find(DatabaseConnectionStep)
        click(connectionStep.find("h3"))
        expect(connectionStep.find('.SetupStep--active').length).toBe(1)

        const letUserControlSchedulingToggle = connectionStep
            .find(FormField)
            .filterWhere((f) => f.props().fieldName === "let-user-control-scheduling")
            .find(Toggle);

        expect(letUserControlSchedulingToggle.length).toBe(1);
        expect(letUserControlSchedulingToggle.prop('value')).toBe(false);
        click(letUserControlSchedulingToggle);
        expect(letUserControlSchedulingToggle.prop('value')).toBe(true);

        const nextButton = connectionStep.find('button[children="Next"]')
        clickButton(nextButton);
        await store.waitForActions([SET_DATABASE_DETAILS])

        const schedulingStep = app.find(DatabaseSchedulingStep);
        expect(schedulingStep.find('.SetupStep--active').length).toBe(1)

        // disable the deep analysis
        const syncOptions = schedulingStep.find(SyncOption);
        const syncOptionsNever = syncOptions.at(1);
        click(syncOptionsNever)

        // proceed to tracking preferences step again
        const nextButton2 = schedulingStep.find('button[children="Next"]')
        clickButton(nextButton2);
        await store.waitForActions([SET_DATABASE_DETAILS])
    })
        it("lets you change to 'Use foreign key' and change the target for field with fk", async () => {
            const { store, fieldApp } = await initFieldApp({ fieldId: USER_ID_FK_ID });
            const section = fieldApp.find(FieldRemapping)
            const mappingTypePicker = section.find(Select);
            expect(mappingTypePicker.text()).toBe('Use original value')

            click(mappingTypePicker);
            const pickerOptions = mappingTypePicker.find(TestPopover).find("li");
            expect(pickerOptions.length).toBe(2);

            const useFKButton = pickerOptions.at(1).children().first()
            click(useFKButton);
            store.waitForActions([UPDATE_FIELD_DIMENSION, FETCH_TABLE_METADATA])
            // TODO: Figure out a way to avoid using delay – the use of delays may lead to occasional CI failures
            await delay(500);

            const fkFieldSelect = section.find(SelectButton);

            expect(fkFieldSelect.text()).toBe("Name");
            click(fkFieldSelect);

            const sourceField = fkFieldSelect.parent().find(TestPopover)
                .find(".List-item")
                .filterWhere(li => /Source/.test(li.text()))
                .first().children().first();

            click(sourceField)
            store.waitForActions([FETCH_TABLE_METADATA])
            // TODO: Figure out a way to avoid using delay – the use of delays may lead to occasional CI failures
            await delay(500);
            expect(fkFieldSelect.text()).toBe("Source");
        })
  it("it should render the proper configuration form", async () => {
    const store = await createTestStore();

    store.pushPath("/admin/settings");

    const app = mount(store.getAppContainer());
    await store.waitForActions([INITIALIZE_SETTINGS]);
    const settingsWrapper = app.find(SettingsEditorApp);
    const authListItem = settingsWrapper.find(
      'span[children="Authentication"]',
    );

    click(authListItem);

    expect(settingsWrapper.find(SettingsAuthenticationOptions).length).toBe(1);

    // test google
    const googleConfigButton = settingsWrapper.find(".Button").first();
    click(googleConfigButton);

    expect(settingsWrapper.find(SettingsSingleSignOnForm).length).toBe(1);

    store.goBack();

    // test ldap
    const ldapConfigButton = settingsWrapper.find(".Button").last();
    click(ldapConfigButton);
    expect(settingsWrapper.find(SettingsLdapForm).length).toBe(1);
  });
        it("lets you start a question from a metric", async () => {
            useSharedNormalLogin()
            const store = await createTestStore()

            store.pushPath(Urls.newQuestion());
            const app = mount(store.getAppContainer());
            await store.waitForActions([DETERMINE_OPTIONS]);

            click(app.find(NewQueryOption).filterWhere((c) => c.prop('title') === "Metrics"))
            await store.waitForActions(FETCH_DATABASES);
            await store.waitForActions([SET_REQUEST_STATE]);
            expect(store.getPath()).toBe("/question/new/metric")

            const entitySearch = app.find(EntitySearch)
            const viewByCreator = entitySearch.find(SearchGroupingOption).last()
            expect(viewByCreator.text()).toBe("Creator");
            click(viewByCreator)
            expect(store.getPath()).toBe("/question/new/metric?grouping=creator")

            const group = entitySearch.find(SearchResultsGroup)
            expect(group.prop('groupName')).toBe("Bobby Tables")

            const metricSearchResult = group.find(SearchResultListItem)
                .filterWhere((item) => /A Metric/.test(item.text()))
            click(metricSearchResult.childAt(0))

            await store.waitForActions([INITIALIZE_QB, QUERY_COMPLETED]);
            await delay(100); // Trying to address random CI failures with a small delay

            expect(
                app.find(AggregationWidget).find(".View-section-aggregation").text()
            ).toBe("A Metric")
        })
            async function runSharedQuestionTests(store, questionUrl, apiRegex) {
                store.pushPath(questionUrl);
                const app = mount(store.getAppContainer())

                await store.waitForActions([ADD_PARAM_VALUES]);

                // Loading the query results is done in PublicQuestion itself so we have to listen to API request instead of Redux action
                await waitForRequestToComplete("GET", apiRegex)
                // use `update()` because of setState
                expect(app.update().find(Scalar).text()).toBe(COUNT_ALL + "sql parametrized");

                // manually click parameter (sadly the query results loading happens inline again)
                click(app.find(Parameters).find("a").first());
                click(app.find(CategoryWidget).find('li[children="Doohickey"]'));

                await waitForRequestToComplete("GET", apiRegex)
                expect(app.update().find(Scalar).text()).toBe(COUNT_DOOHICKEY + "sql parametrized");

                // set parameter via url
                store.pushPath("/"); // simulate a page reload by visiting other page
                store.pushPath(questionUrl + "?category=Gadget");
                await waitForRequestToComplete("GET", apiRegex)
                // use `update()` because of setState
                expect(app.update().find(Scalar).text()).toBe(COUNT_GADGET + "sql parametrized");
            }
    it("should show validation error if you enable scheduling toggle and enter invalid db connection info", async () => {
      MetabaseApi.db_create = async db => {
        await delay(10);
        return { ...db, id: 10 };
      };

      const store = await createTestStore();
      store.pushPath("/admin/databases");

      const app = mount(store.getAppContainer());
      await store.waitForActions([FETCH_DATABASES]);

      const listAppBeforeAdd = app.find(DatabaseListApp);

      const addDbButton = listAppBeforeAdd
        .find(".Button.Button--primary")
        .first();
      click(addDbButton);

      const dbDetailsForm = app.find(DatabaseEditApp);
      expect(dbDetailsForm.length).toBe(1);

      await store.waitForActions([INITIALIZE_DATABASE]);

      expect(
        dbDetailsForm.find('button[children="Save"]').props().disabled,
      ).toBe(true);

      const updateInputValue = (name, value) =>
        setInputValue(dbDetailsForm.find(`input[name="${name}"]`), value);

      updateInputValue("name", "Test db name");
      updateInputValue("dbname", "test_postgres_db");
      updateInputValue("user", "uberadmin");

      const letUserControlSchedulingField = dbDetailsForm
        .find(FormField)
        .filterWhere(
          f => f.props().fieldName === "let-user-control-scheduling",
        );
      expect(letUserControlSchedulingField.length).toBe(1);
      expect(letUserControlSchedulingField.find(Toggle).props().value).toBe(
        false,
      );
      click(letUserControlSchedulingField.find(Toggle));

      const nextStepButton = dbDetailsForm.find('button[children="Next"]');
      expect(nextStepButton.props().disabled).toBe(false);
      clickButton(nextStepButton);

      await store.waitForActions([
        VALIDATE_DATABASE_STARTED,
        VALIDATE_DATABASE_FAILED,
      ]);
      expect(app.find(FormMessage).text()).toMatch(
        /Couldn't connect to the database./,
      );
    });
        it("lets you change field visibility", async () => {
            const { store, fieldApp } = await initFieldApp({ fieldId: CREATED_AT_ID });

            const visibilitySelect = fieldApp.find(FieldVisibilityPicker);
            click(visibilitySelect);
            click(visibilitySelect.find(TestPopover).find("li").at(1).children().first());

            await store.waitForActions([UPDATE_FIELD])
        })
Example #11
0
  it("should load create pulse", async () => {
    store.pushPath("/pulse/create");
    const app = mount(store.connectContainer(<PulseEditApp />));
    await store.waitForActions([SET_EDITING_PULSE,FETCH_CARDS]);

    // no previews yet
    expect(app.find(PulseCardPreview).length).toBe(0)

    // set name to 'foo'
    setInputValue(app.find("input").first(), "foo")

    // email channel should be enabled
    expect(app.find(Toggle).first().props().value).toBe(true);

    // add count card
    app.find(CardPicker).first().props().onChange(questionCount.id())
    await store.waitForActions([FETCH_PULSE_CARD_PREVIEW]);

    // add raw card
    app.find(CardPicker).first().props().onChange(questionRaw.id())
    await store.waitForActions([FETCH_PULSE_CARD_PREVIEW]);

    let previews = app.find(PulseCardPreview);
    expect(previews.length).toBe(2)

    // NOTE: check text content since enzyme doesn't doesn't seem to work well with dangerouslySetInnerHTML
    expect(previews.at(0).text()).toBe("count12,805")
    expect(previews.at(0).find(".Icon-attachment").length).toBe(1)
    expect(previews.at(1).text()).toBe("tableThis question will be added as a file attachment")
    expect(previews.at(1).find(".Icon-attachment").length).toBe(0)

    // toggle email channel off
    click(app.find(Toggle).first())

    previews = app.find(PulseCardPreview);
    expect(previews.at(0).text()).toBe("count12,805")
    expect(previews.at(0).find(".Icon-attachment").length).toBe(0)
    expect(previews.at(1).text()).toBe("tableThis question won't be included in your Pulse")
    expect(previews.at(1).find(".Icon-attachment").length).toBe(0)

    // toggle email channel on
    click(app.find(Toggle).first())

    // save
    const saveButton = app.find(".PulseEdit-footer .Button").first();
    expect(saveButton.hasClass("Button--primary")).toBe(true)
    click(saveButton)

    await store.waitForActions([SAVE_EDITING_PULSE]);

    const [pulse] = await PulseApi.list();
    expect(pulse.name).toBe("foo");
    expect(pulse.cards[0].id).toBe(questionCount.id());
    expect(pulse.cards[1].id).toBe(questionRaw.id());
    expect(pulse.channels[0].channel_type).toBe("email");
    expect(pulse.channels[0].enabled).toBe(true);
  })
        it("lets you disable the binning", async () => {
            const breakoutWidget = qb.find(BreakoutWidget).first();
            click(breakoutWidget.find(FieldName).children().first())
            const breakoutPopover = qb.find("#BreakoutPopover")

            const subtotalFieldButton = breakoutPopover.find(FieldList).find('.List-item--selected h4[children="100 bins"]')
            expect(subtotalFieldButton.length).toBe(1);
            click(subtotalFieldButton);

            click(qb.find(DimensionPicker).find('a[children="Don\'t bin"]'));
        });
        it("lets you add ID field as a filter", async () => {
            const filterSection = qb.find('.GuiBuilder-filtered-by');
            const addFilterButton = filterSection.find('.AddButton');
            click(addFilterButton);

            const filterPopover = filterSection.find(FilterPopover);

            const ratingFieldButton = filterPopover.find(FieldList).find('h4[children="ID"]')
            expect(ratingFieldButton.length).toBe(1);
            click(ratingFieldButton)
        })
        it("lets you change the type to 'No special type'", async () => {
            const { store, fieldApp } = await initFieldApp({ fieldId: CREATED_AT_ID });
            const picker = fieldApp.find(SpecialTypeAndTargetPicker)
            const typeSelect = picker.find(Select).at(0)
            click(typeSelect);

            const noSpecialTypeButton = typeSelect.find(TestPopover).find("li").last().children().first()
            click(noSpecialTypeButton);

            await store.waitForActions([UPDATE_FIELD])
            expect(picker.text()).toMatch(/Select a special type/);
        })
Example #15
0
    it("should properly increment and decrement object deteail", async () => {
      const store = await createTestStore();
      const newQuestion = Question.create({
        databaseId: 1,
        tableId: 1,
        metadata: getMetadata(store.getState()),
      })
        .query()
        .addFilter(["=", ["field-id", 2], 2])
        .question()
        .setDisplayName("Object Detail");

      const savedQuestion = await createSavedQuestion(newQuestion);

      store.pushPath(savedQuestion.getUrl());

      const app = mount(store.getAppContainer());

      await store.waitForActions([INITIALIZE_QB, QUERY_COMPLETED]);
      await delay(100); // Trying to address random CI failures with a small delay

      expect(app.find(".ObjectDetail h1").text()).toEqual("2");

      const previousObjectTrigger = app.find(".Icon.Icon-backArrow");
      click(previousObjectTrigger);

      await store.waitForActions([QUERY_COMPLETED]);
      await delay(100); // Trying to address random CI failures with a small delay

      expect(app.find(".ObjectDetail h1").text()).toEqual("1");
      const nextObjectTrigger = app.find(".Icon.Icon-forwardArrow");
      click(nextObjectTrigger);

      await store.waitForActions([QUERY_COMPLETED]);
      await delay(100); // Trying to address random CI failures with a small delay

      expect(app.find(".ObjectDetail h1").text()).toEqual("2");

      // test keyboard shortcuts

      // left arrow
      dispatchBrowserEvent("keydown", { key: "ArrowLeft" });
      await store.waitForActions([QUERY_COMPLETED]);
      await delay(100); // Trying to address random CI failures with a small delay
      expect(app.find(".ObjectDetail h1").text()).toEqual("1");

      // left arrow
      dispatchBrowserEvent("keydown", { key: "ArrowRight" });
      await store.waitForActions([QUERY_COMPLETED]);
      await delay(100); // Trying to address random CI failures with a small delay
      expect(app.find(".ObjectDetail h1").text()).toEqual("2");
    });
        it("lets you switch back to Use original value after changing to some other value", async () => {
            const { store, fieldApp } = await initFieldApp({ fieldId: USER_ID_FK_ID });
            const section = fieldApp.find(FieldRemapping)
            const mappingTypePicker = section.find(Select);
            expect(mappingTypePicker.text()).toBe('Use foreign key')

            click(mappingTypePicker);
            const pickerOptions = mappingTypePicker.find(TestPopover).find("li");
            const useOriginalValue = pickerOptions.first().children().first()
            click(useOriginalValue);

            store.waitForActions([DELETE_FIELD_DIMENSION, FETCH_TABLE_METADATA]);
        })
        it("lets you add Rating field as a filter", async () => {
            // TODO Atte Keinänen 7/13/17: Extracting GuiQueryEditor's contents to smaller React components
            // would make testing with selectors more natural
            const filterSection = qb.find('.GuiBuilder-filtered-by');
            const addFilterButton = filterSection.find('.AddButton');
            click(addFilterButton);

            const filterPopover = filterSection.find(FilterPopover);

            const ratingFieldButton = filterPopover.find(FieldList).find('h4[children="Rating"]')
            expect(ratingFieldButton.length).toBe(1);
            click(ratingFieldButton);
        })
    it("should let you archive and unarchive dashboards", async () => {
        const store = await createTestStore();
        store.pushPath("/dashboards")
        const app = mount(store.getAppContainer());
        await store.waitForActions([FETCH_DASHBOARDS])

        click(app.find(DashboardListItem).first().find(".Icon-archive"));
        await store.waitForActions([SET_ARCHIVED])

        click(app.find(".Icon-viewArchive"))
        await store.waitForActions([FETCH_ARCHIVE])
        expect(app.find(ArchivedItem).length).toBeGreaterThan(0)
    });
        it("lets you change the binning strategy to 100 bins", async () => {
            const breakoutWidget = qb.find(BreakoutWidget).first();
            click(breakoutWidget.find(FieldName).children().first())
            const breakoutPopover = qb.find("#BreakoutPopover")

            const subtotalFieldButton = breakoutPopover.find(FieldList).find('.List-item--selected h4[children="Auto binned"]')
            expect(subtotalFieldButton.length).toBe(1);
            click(subtotalFieldButton)

            click(qb.find(DimensionPicker).find('a[children="100 bins"]'));

            await store.waitForActions([SET_DATASET_QUERY])
            expect(breakoutWidget.text()).toBe("Total: 100 bins");
        });
        it("lets you group by Latitude with the 'Bin every 1 degree'", async () => {
            const breakoutWidget = qb.find(BreakoutWidget).first();
            click(breakoutWidget.find(FieldName).children().first())
            const breakoutPopover = qb.find("#BreakoutPopover")

            const subtotalFieldButton = breakoutPopover.find(FieldList).find('.List-item--selected h4[children="Auto binned"]')
            expect(subtotalFieldButton.length).toBe(1);
            click(subtotalFieldButton);

            click(qb.find(DimensionPicker).find('a[children="Bin every 1 degree"]'));

            await store.waitForActions([SET_DATASET_QUERY])
            expect(breakoutWidget.text()).toBe("Latitude: 1°");
        });
        it("lets you group by Total with the default binning option", async () => {
            const breakoutSection = qb.find('.GuiBuilder-groupedBy');
            const addBreakoutButton = breakoutSection.find('.AddButton');
            click(addBreakoutButton);

            const breakoutPopover = breakoutSection.find("#BreakoutPopover")
            const subtotalFieldButton = breakoutPopover.find(FieldList).find('h4[children="Total"]')
            expect(subtotalFieldButton.length).toBe(1);
            click(subtotalFieldButton);

            await store.waitForActions([SET_DATASET_QUERY])

            const breakoutWidget = qb.find(BreakoutWidget).first();
            expect(breakoutWidget.text()).toBe("Total: Auto binned");
        });
    it("lets you change title and description", async () => {
      const name = "Customer Feedback Analysis";
      const description =
        "For seeing the usual response times, feedback topics, our response rate, how often customers are directed to our knowledge base instead of providing a customized response";

      // Create a dashboard programmatically
      const dashboard = await DashboardApi.create({ name, description });
      dashboardId = dashboard.id;

      const store = await createTestStore();
      store.pushPath(Urls.dashboard(dashboardId));
      const app = mount(store.getAppContainer());

      await store.waitForActions([FETCH_DASHBOARD]);

      // Test dashboard renaming
      click(app.find(".Icon.Icon-pencil"));
      await store.waitForActions([SET_EDITING_DASHBOARD]);

      const headerInputs = app.find(".Header-title input");
      setInputValue(headerInputs.first(), "Customer Analysis Paralysis");
      setInputValue(headerInputs.at(1), "");

      clickButton(app.find(EditBar).find(".Button--primary.Button"));
      await store.waitForActions([SAVE_DASHBOARD_AND_CARDS, FETCH_DASHBOARD]);

      await delay(500);

      expect(app.find(DashboardHeader).text()).toMatch(
        /Customer Analysis Paralysis/,
      );
    });
    it("should not block deletes", async () => {
      MetabaseApi.db_delete = async () => await delay(10);

      const store = await createTestStore();
      store.pushPath("/admin/databases");

      const app = mount(store.getAppContainer());
      await store.waitForActions([FETCH_DATABASES]);

      const wrapper = app.find(DatabaseListApp);
      const dbCount = wrapper.find("tr").length;

      const deleteButton = wrapper.find(".Button.Button--danger").first();

      click(deleteButton);

      const deleteModal = wrapper.find(".test-modal");
      setInputValue(deleteModal.find(".Form-input"), "DELETE");
      clickButton(deleteModal.find(".Button.Button--danger"));

      // test that the modal is gone
      expect(wrapper.find(".test-modal").length).toEqual(0);

      // we should now have a disabled db row during delete
      expect(wrapper.find("tr.disabled").length).toEqual(1);

      // db delete finishes
      await store.waitForActions([DELETE_DATABASE]);

      // there should be no disabled db rows now
      expect(wrapper.find("tr.disabled").length).toEqual(0);

      // we should now have one database less in the list
      expect(wrapper.find("tr").length).toEqual(dbCount - 1);
    });
        it("lets you remove the added filter", async () => {
            const filterWidget = qb.find(FilterWidget);
            click(filterWidget.find(".Icon-close"))
            await store.waitForActions([SET_DATASET_QUERY])

            expect(qb.find(FilterWidget).length).toBe(0);
        })
        it("lets you update the filter to 'ID is between 1 or 100'", async () => {
            const filterWidget = qb.find(FilterWidget);
            click(filterWidget.find(FieldName))

            const filterPopover = qb.find(FilterPopover);
            const operatorSelector = filterPopover.find(OperatorSelector);
            clickButton(operatorSelector.find('button[children="Between"]'));

            const betweenInputs = filterPopover.find("textarea");
            expect(betweenInputs.length).toBe(2);

            expect(betweenInputs.at(0).props().value).toBe("10, 11");

            setInputValue(betweenInputs.at(1), "asdasd")
            const updateFilterButton = filterPopover.find('button[children="Update filter"]')
            expect(updateFilterButton.props().className).toMatch(/disabled/);

            setInputValue(betweenInputs.at(0), "1")
            setInputValue(betweenInputs.at(1), "100")

            clickButton(updateFilterButton);

            await store.waitForActions([SET_DATASET_QUERY])
            expect(qb.find(FilterPopover).length).toBe(0);
            expect(filterWidget.text()).toBe("ID between1100");
        });
Example #26
0
    it("shows metrics for the current table, excluding the retired ones", async () => {
      const url = Question.create({
        databaseId: DATABASE_ID,
        tableId: ORDERS_TABLE_ID,
        metadata,
      })
        .query()
        .question()
        .getUrl();

      const store = await createTestStore();
      store.pushPath(url);
      const app = mount(store.getAppContainer());

      await store.waitForActions([
        INITIALIZE_QB,
        QUERY_COMPLETED,
        LOAD_TABLE_METADATA,
      ]);

      const actionsWidget = app.find(ActionsWidget);
      click(actionsWidget.childAt(0));

      expect(actionsWidget.find('strong[children="A Metric"]').length).toBe(1);
    });
    it("should change the user's password to random password", async () => {
      expect.assertions(3);

      let newPassword;

      mock.get("/api/user/42", (req, res) =>
        res.json({ id: 42, ...MOCK_USER }),
      );
      mock.put("/api/user/42/password", (req, res) => {
        expect(Object.keys(req.json())).toEqual(["password"]);
        newPassword = req.json().password;
        return res.json({ id: 42, ...MOCK_USER });
      });

      const { wrapper } = mountWithStore(
        <UserPasswordResetModal params={{ userId: 42 }} />,
      );

      const resetButton = await wrapper.async.find(".Button--danger");
      expect(resetButton.length).toBe(1);

      clickButton(resetButton);

      const showPasswordLink = await wrapper.async.find(".link");
      click(showPasswordLink);

      const passwordReveal = await wrapper.async.find("input");
      expect(passwordReveal.props().value).toBe(newPassword);
    });
  it("should let you create a dashboard when there are no existing dashboards", async () => {
    const store = await createTestStore();
    store.pushPath("/dashboards");
    const app = mount(store.getAppContainer());

    await store.waitForActions([FETCH_DASHBOARDS]);

    // // Create a new dashboard in the empty state (EmptyState react component)
    click(app.find(".Button.Button--primary"));
    // click(app.find(".Icon.Icon-add"))

    const modal = app.find(CreateDashboardModal);

    setInputValue(
      modal.find('input[name="name"]'),
      "Customer Feedback Analysis",
    );
    setInputValue(
      modal.find('input[name="description"]'),
      "For seeing the usual response times, feedback topics, our response rate, how often customers are directed to our knowledge base instead of providing a customized response",
    );
    clickButton(modal.find(".Button--primary"));

    // should navigate to dashboard page
    await store.waitForActions(FETCH_DASHBOARD);
    expect(app.find(Dashboard).length).toBe(1);
  });
    it("should advance through steps properly", () => {
      const wrapper = shallow(<NewUserOnboardingModal />);
      const nextButton = wrapper.find("a");

      expect(wrapper.state().step).toEqual(1);
      click(nextButton);
      expect(wrapper.state().step).toEqual(2);
    });
Example #30
0
      it("lets you add 'Rating is Perfecto' filter", async () => {
        const { store, qb } = await initQBWithReviewsTable();

        // open filter popover
        const filterSection = qb.find(".GuiBuilder-filtered-by");
        const newFilterButton = filterSection.find(".AddButton");
        click(newFilterButton);

        // choose the field to be filtered
        const filterPopover = filterSection.find(FilterPopover);
        const ratingFieldButton = filterPopover
          .find(FieldList)
          .find('h4[children="Rating Description"]');
        expect(ratingFieldButton.length).toBe(1);
        click(ratingFieldButton);

        // check that field values seem correct
        const fieldItems = filterPopover.find("li");
        expect(fieldItems.length).toBe(5);
        expect(fieldItems.first().text()).toBe("Awful");
        expect(fieldItems.last().text()).toBe("Perfecto");

        // select the last item (Perfecto)
        const widgetFieldItem = fieldItems.last();
        const widgetCheckbox = widgetFieldItem.find(CheckBox);
        expect(widgetCheckbox.props().checked).toBe(false);
        click(widgetFieldItem.children().first());
        expect(widgetCheckbox.props().checked).toBe(true);

        // add the filter
        const addFilterButton = filterPopover.find(
          'button[children="Add filter"]',
        );
        clickButton(addFilterButton);

        await store.waitForActions([SET_DATASET_QUERY]);

        // validate the filter text value
        expect(qb.find(FilterPopover).length).toBe(0);
        const filterWidget = qb.find(FilterWidget);
        expect(filterWidget.length).toBe(1);
        expect(filterWidget.text()).toBe(
          "Rating Description is equal toPerfecto",
        );
      });