| /** |
| * 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 fetchMock from 'fetch-mock'; |
| import configureStore from 'redux-mock-store'; |
| import thunk from 'redux-thunk'; |
| import { render, waitFor } from 'spec/helpers/testing-library'; |
| import { |
| CLEAR_INACTIVE_QUERIES, |
| REFRESH_QUERIES, |
| } from 'src/SqlLab/actions/sqlLab'; |
| import QueryAutoRefresh, { |
| isQueryRunning, |
| shouldCheckForQueries, |
| QUERY_UPDATE_FREQ, |
| } from 'src/SqlLab/components/QueryAutoRefresh'; |
| import { successfulQuery, runningQuery } from 'src/SqlLab/fixtures'; |
| import { QueryDictionary } from 'src/SqlLab/types'; |
| |
| const middlewares = [thunk]; |
| const mockStore = configureStore(middlewares); |
| |
| // NOTE: The uses of @ts-ignore in this file is to enable testing of bad inputs to verify the |
| // function / component handles bad data elegantly |
| describe('QueryAutoRefresh', () => { |
| const runningQueries: QueryDictionary = {}; |
| runningQueries[runningQuery.id] = runningQuery; |
| |
| const successfulQueries: QueryDictionary = {}; |
| successfulQueries[successfulQuery.id] = successfulQuery; |
| |
| const queriesLastUpdate = Date.now(); |
| |
| const refreshApi = 'glob:*/api/v1/query/updated_since?*'; |
| |
| afterEach(() => { |
| fetchMock.reset(); |
| }); |
| |
| it('isQueryRunning returns true for valid running query', () => { |
| const running = isQueryRunning(runningQuery); |
| expect(running).toBe(true); |
| }); |
| |
| it('isQueryRunning returns false for valid not-running query', () => { |
| const running = isQueryRunning(successfulQuery); |
| expect(running).toBe(false); |
| }); |
| |
| it('isQueryRunning returns false for invalid query', () => { |
| // @ts-ignore |
| let running = isQueryRunning(null); |
| expect(running).toBe(false); |
| // @ts-ignore |
| running = isQueryRunning(undefined); |
| expect(running).toBe(false); |
| // @ts-ignore |
| running = isQueryRunning('I Should Be An Object'); |
| expect(running).toBe(false); |
| // @ts-ignore |
| running = isQueryRunning({ state: { badFormat: true } }); |
| expect(running).toBe(false); |
| }); |
| |
| it('shouldCheckForQueries is true for valid running query', () => { |
| expect(shouldCheckForQueries(runningQueries)).toBe(true); |
| }); |
| |
| it('shouldCheckForQueries is false for valid completed query', () => { |
| expect(shouldCheckForQueries(successfulQueries)).toBe(false); |
| }); |
| |
| it('shouldCheckForQueries is false for invalid inputs', () => { |
| // @ts-ignore |
| expect(shouldCheckForQueries(null)).toBe(false); |
| // @ts-ignore |
| expect(shouldCheckForQueries(undefined)).toBe(false); |
| expect( |
| // @ts-ignore |
| shouldCheckForQueries({ |
| // @ts-ignore |
| '1234': null, |
| // @ts-ignore |
| '23425': 'hello world', |
| // @ts-ignore |
| '345': [], |
| // @ts-ignore |
| '57346': undefined, |
| }), |
| ).toBe(false); |
| }); |
| |
| it('Attempts to refresh when given pending query', async () => { |
| const store = mockStore(); |
| fetchMock.get(refreshApi, { |
| result: [ |
| { |
| id: runningQuery.id, |
| status: 'success', |
| }, |
| ], |
| }); |
| |
| render( |
| <QueryAutoRefresh |
| queries={runningQueries} |
| queriesLastUpdate={queriesLastUpdate} |
| />, |
| { useRedux: true, store }, |
| ); |
| await waitFor( |
| () => |
| expect(store.getActions()).toContainEqual( |
| expect.objectContaining({ |
| type: REFRESH_QUERIES, |
| }), |
| ), |
| { timeout: QUERY_UPDATE_FREQ + 100 }, |
| ); |
| }); |
| |
| it('Attempts to clear inactive queries when updated queries are empty', async () => { |
| const store = mockStore(); |
| fetchMock.get(refreshApi, { |
| result: [], |
| }); |
| |
| render( |
| <QueryAutoRefresh |
| queries={runningQueries} |
| queriesLastUpdate={queriesLastUpdate} |
| />, |
| { useRedux: true, store }, |
| ); |
| await waitFor( |
| () => |
| expect(store.getActions()).toContainEqual( |
| expect.objectContaining({ |
| type: CLEAR_INACTIVE_QUERIES, |
| }), |
| ), |
| { timeout: QUERY_UPDATE_FREQ + 100 }, |
| ); |
| expect( |
| store.getActions().filter(({ type }) => type === REFRESH_QUERIES), |
| ).toHaveLength(0); |
| expect(fetchMock.calls(refreshApi)).toHaveLength(1); |
| }); |
| |
| it('Does not fail and attempts to refresh when given pending query and invalid query', async () => { |
| const store = mockStore(); |
| fetchMock.get(refreshApi, { |
| result: [ |
| { |
| id: runningQuery.id, |
| status: 'success', |
| }, |
| ], |
| }); |
| |
| render( |
| <QueryAutoRefresh |
| // @ts-ignore |
| queries={{ ...runningQueries, g324t: null }} |
| queriesLastUpdate={queriesLastUpdate} |
| />, |
| { useRedux: true, store }, |
| ); |
| await waitFor( |
| () => |
| expect(store.getActions()).toContainEqual( |
| expect.objectContaining({ |
| type: REFRESH_QUERIES, |
| }), |
| ), |
| { timeout: QUERY_UPDATE_FREQ + 100 }, |
| ); |
| }); |
| |
| it('Does NOT Attempt to refresh when given only completed queries', async () => { |
| const store = mockStore(); |
| fetchMock.get(refreshApi, { |
| result: [ |
| { |
| id: runningQuery.id, |
| status: 'success', |
| }, |
| ], |
| }); |
| render( |
| <QueryAutoRefresh |
| queries={successfulQueries} |
| queriesLastUpdate={queriesLastUpdate} |
| />, |
| { useRedux: true, store }, |
| ); |
| await waitFor( |
| () => |
| expect(store.getActions()).toContainEqual( |
| expect.objectContaining({ |
| type: CLEAR_INACTIVE_QUERIES, |
| }), |
| ), |
| { timeout: QUERY_UPDATE_FREQ + 100 }, |
| ); |
| expect(fetchMock.calls(refreshApi)).toHaveLength(0); |
| }); |
| }); |