/** * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ import React from 'react'; import { mount } from 'enzyme'; import { Provider } from 'react-redux'; import fetchMock from 'fetch-mock'; import { supersetTheme, SupersetClient, ThemeProvider, } from '@superset-ui/core'; import Modal from 'src/common/components/Modal'; import PropertiesModal from 'src/dashboard/components/PropertiesModal'; import { mockStore } from 'spec/fixtures/mockStore'; const dashboardResult = { json: { result: { dashboard_title: 'New Title', slug: '/new', json_metadata: '{"something":"foo"}', owners: [], }, }, }; fetchMock.restore(); fetchMock.get('glob:*/api/v1/dashboard/related/owners?*', { result: {}, }); fetchMock.get('glob:*/api/v1/dashboard/*', { result: { dashboard_title: 'New Title', slug: '/new', json_metadata: '{"something":"foo"}', owners: [], }, }); describe('PropertiesModal', () => { afterEach(() => { jest.restoreAllMocks(); jest.resetAllMocks(); }); const requiredProps = { dashboardId: 1, show: true, addSuccessToast: () => {}, }; function setup(overrideProps) { return mount( , { wrappingComponent: ThemeProvider, wrappingComponentProps: { theme: supersetTheme }, }, ); } describe('onColorSchemeChange', () => { it('sets up a default state', () => { const wrapper = setup({ colorScheme: 'SUPERSET_DEFAULT' }); expect( wrapper.find('PropertiesModal').instance().state.values.colorScheme, ).toEqual('SUPERSET_DEFAULT'); }); describe('with a valid color scheme as an arg', () => { describe('without metadata', () => { const wrapper = setup({ colorScheme: 'SUPERSET_DEFAULT' }); const modalInstance = wrapper.find('PropertiesModal').instance(); it('does not update the color scheme in the metadata', () => { const spy = jest.spyOn(modalInstance, 'onMetadataChange'); modalInstance.onColorSchemeChange('SUPERSET_DEFAULT'); expect(spy).not.toHaveBeenCalled(); }); }); describe('with metadata', () => { describe('with color_scheme in the metadata', () => { it('will update the metadata', () => { const wrapper = setup(); const modalInstance = wrapper.find('PropertiesModal').instance(); modalInstance.setState({ values: { json_metadata: '{"color_scheme": "foo"}', }, }); const spy = jest.spyOn(modalInstance, 'onMetadataChange'); modalInstance.onColorSchemeChange('SUPERSET_DEFAULT'); expect(spy).toHaveBeenCalledWith( '{"color_scheme": "SUPERSET_DEFAULT"}', ); }); }); describe('without color_scheme in the metadata', () => { const wrapper = setup(); const modalInstance = wrapper.find('PropertiesModal').instance(); modalInstance.setState({ values: { json_metadata: '{"timed_refresh_immune_slices": []}', }, }); it('will not update the metadata', () => { const spy = jest.spyOn(modalInstance, 'onMetadataChange'); modalInstance.onColorSchemeChange('SUPERSET_DEFAULT'); expect(spy).not.toHaveBeenCalled(); }); }); }); }); describe('with an invalid color scheme as an arg', () => { const wrapper = setup(); const modalInstance = wrapper.find('PropertiesModal').instance(); it('will raise an error', () => { const spy = jest.spyOn(Modal, 'error'); expect(() => modalInstance.onColorSchemeChange('THIS_WILL_NOT_WORK'), ).toThrowError('A valid color scheme is required'); expect(spy).toHaveBeenCalled(); }); }); }); describe('onOwnersChange', () => { it('should update the state with the value passed', () => { const wrapper = setup(); const modalInstance = wrapper.find('PropertiesModal').instance(); const spy = jest.spyOn(modalInstance, 'updateFormState'); modalInstance.onOwnersChange('foo'); expect(spy).toHaveBeenCalledWith('owners', 'foo'); }); }); describe('onMetadataChange', () => { it('should update the state with the value passed', () => { const wrapper = setup(); const modalInstance = wrapper.find('PropertiesModal').instance(); const spy = jest.spyOn(modalInstance, 'updateFormState'); modalInstance.onMetadataChange('foo'); expect(spy).toHaveBeenCalledWith('json_metadata', 'foo'); }); }); describe('onChange', () => { it('should update the state with the value passed', () => { const wrapper = setup(); const modalInstance = wrapper.find('PropertiesModal').instance(); const spy = jest.spyOn(modalInstance, 'updateFormState'); modalInstance.onChange({ target: { name: 'test', value: 'foo' } }); expect(spy).toHaveBeenCalledWith('test', 'foo'); }); }); describe('fetchDashboardDetails', () => { it('should make an api call', () => { const spy = jest.spyOn(SupersetClient, 'get'); const wrapper = setup(); const modalInstance = wrapper.find('PropertiesModal').instance(); modalInstance.fetchDashboardDetails(); expect(spy).toHaveBeenCalledWith({ endpoint: '/api/v1/dashboard/1', }); }); it('should update state', async () => { const wrapper = setup(); const modalInstance = wrapper.find('PropertiesModal').instance(); const fetchSpy = jest .spyOn(SupersetClient, 'get') .mockResolvedValue(dashboardResult); modalInstance.fetchDashboardDetails(); await fetchSpy(); expect(modalInstance.state.values.colorScheme).toBeUndefined(); expect(modalInstance.state.values.dashboard_title).toEqual('New Title'); expect(modalInstance.state.values.slug).toEqual('/new'); expect(modalInstance.state.values.json_metadata).toEqual( '{"something": "foo"}', ); }); it('should call onOwnersChange', async () => { const wrapper = setup(); const modalInstance = wrapper.find('PropertiesModal').instance(); const fetchSpy = jest.spyOn(SupersetClient, 'get').mockResolvedValue({ json: { result: { dashboard_title: 'New Title', slug: '/new', json_metadata: '{"something":"foo"}', owners: [{ id: 1, first_name: 'Al', last_name: 'Pacino' }], }, }, }); const onOwnersSpy = jest.spyOn(modalInstance, 'onOwnersChange'); modalInstance.fetchDashboardDetails(); await fetchSpy(); expect(modalInstance.state.values.colorScheme).toBeUndefined(); expect(onOwnersSpy).toHaveBeenCalledWith([ { value: 1, label: 'Al Pacino' }, ]); }); describe('when colorScheme is undefined as a prop', () => { describe('when color_scheme is defined in json_metadata', () => { const wrapper = setup(); const modalInstance = wrapper.find('PropertiesModal').instance(); it('should use the color_scheme from json_metadata in the api response', async () => { const fetchSpy = jest.spyOn(SupersetClient, 'get').mockResolvedValue({ json: { result: { dashboard_title: 'New Title', slug: '/new', json_metadata: '{"color_scheme":"SUPERSET_DEFAULT"}', owners: [], }, }, }); modalInstance.fetchDashboardDetails(); // this below triggers the callback of the api call await fetchSpy(); expect(modalInstance.state.values.colorScheme).toEqual( 'SUPERSET_DEFAULT', ); }); describe('when color_scheme is not defined in json_metadata', () => { const wrapper = setup(); const modalInstance = wrapper.find('PropertiesModal').instance(); it('should be undefined', async () => { const fetchSpy = jest .spyOn(SupersetClient, 'get') .mockResolvedValue(dashboardResult); modalInstance.fetchDashboardDetails(); await fetchSpy(); expect(modalInstance.state.values.colorScheme).toBeUndefined(); }); }); }); }); describe('when colorScheme is defined as a prop', () => { describe('when color_scheme is defined in json_metadata', () => { const wrapper = setup({ colorScheme: 'SUPERSET_DEFAULT' }); const modalInstance = wrapper.find('PropertiesModal').instance(); it('should use the color_scheme from json_metadata in the api response', async () => { const fetchSpy = jest.spyOn(SupersetClient, 'get').mockResolvedValue({ json: { result: { dashboard_title: 'New Title', slug: '/new', json_metadata: '{"color_scheme":"SUPERSET_DEFAULT"}', owners: [], }, }, }); modalInstance.fetchDashboardDetails(); await fetchSpy(); expect(modalInstance.state.values.colorScheme).toEqual( 'SUPERSET_DEFAULT', ); }); }); describe('when color_scheme is not defined in json_metadata', () => { const wrapper = setup({ colorScheme: 'SUPERSET_DEFAULT' }); const modalInstance = wrapper.find('PropertiesModal').instance(); it('should use the colorScheme from the prop', async () => { const fetchSpy = jest .spyOn(SupersetClient, 'get') .mockResolvedValue(dashboardResult); modalInstance.fetchDashboardDetails(); await fetchSpy(); expect(modalInstance.state.values.colorScheme).toBeUndefined(); }); }); }); }); });