This is an automated email from the ASF dual-hosted git repository.

ephraimanierobi pushed a commit to branch v2-3-test
in repository https://gitbox.apache.org/repos/asf/airflow.git

commit 447077904493975159a3b97975a6d615a21c3355
Author: Brent Bovenzi <[email protected]>
AuthorDate: Mon May 2 19:38:57 2022 -0400

    Improve react www tests (#23329)
    
    * Add shared test wrapper & treeData placeholder
    
    * remove console log
    
    * move testUtils to /utils
    
    * change unnamed export
    
    (cherry picked from commit 8f6b8551c325ff64f42080391a0f97b3a5d2e7d5)
---
 airflow/www/static/js/tree/Tree.jsx                |  2 +-
 airflow/www/static/js/tree/api/useTreeData.js      | 23 +++--
 .../www/static/js/tree/api/useTreeData.test.jsx    | 16 +---
 airflow/www/static/js/tree/dagRuns/index.jsx       |  2 +-
 airflow/www/static/js/tree/dagRuns/index.test.jsx  | 99 ++++++----------------
 airflow/www/static/js/tree/details/Header.jsx      |  2 +-
 airflow/www/static/js/tree/details/content/Dag.jsx |  2 +-
 .../js/tree/details/content/dagRun/index.jsx       |  2 +-
 .../js/tree/details/content/taskInstance/index.jsx |  2 +-
 airflow/www/static/js/tree/renderTaskRows.test.jsx | 33 +-------
 airflow/www/static/js/tree/utils/testUtils.jsx     | 67 +++++++++++++++
 11 files changed, 121 insertions(+), 129 deletions(-)

diff --git a/airflow/www/static/js/tree/Tree.jsx 
b/airflow/www/static/js/tree/Tree.jsx
index 1283d14c1b..b2d1c1dfb1 100644
--- a/airflow/www/static/js/tree/Tree.jsx
+++ b/airflow/www/static/js/tree/Tree.jsx
@@ -47,7 +47,7 @@ const sidePanelKey = 'hideSidePanel';
 const Tree = () => {
   const scrollRef = useRef();
   const tableRef = useRef();
-  const { data: { groups = {}, dagRuns = [] } } = useTreeData();
+  const { data: { groups, dagRuns } } = useTreeData();
   const { isRefreshOn, toggleRefresh, isPaused } = useAutoRefresh();
   const isPanelOpen = localStorage.getItem(sidePanelKey) !== 'true';
   const { isOpen, onToggle } = useDisclosure({ defaultIsOpen: isPanelOpen });
diff --git a/airflow/www/static/js/tree/api/useTreeData.js 
b/airflow/www/static/js/tree/api/useTreeData.js
index 9cb9737fd3..2a0468cac3 100644
--- a/airflow/www/static/js/tree/api/useTreeData.js
+++ b/airflow/www/static/js/tree/api/useTreeData.js
@@ -29,24 +29,30 @@ import useErrorToast from '../utils/useErrorToast';
 
 // dagId comes from dag.html
 const dagId = getMetaValue('dag_id');
-const treeDataUrl = getMetaValue('tree_data_url');
+const treeDataUrl = getMetaValue('tree_data_url') || '';
 const numRuns = getMetaValue('num_runs');
 const urlRoot = getMetaValue('root');
 const baseDate = getMetaValue('base_date');
 
+const emptyData = {
+  dagRuns: [],
+  groups: {},
+};
+
 const useTreeData = () => {
-  const emptyData = {
-    dagRuns: [],
-    groups: {},
-  };
   const initialData = formatData(treeData, emptyData);
   const { isRefreshOn, stopRefresh } = useAutoRefresh();
   const errorToast = useErrorToast();
   return useQuery('treeData', async () => {
     try {
-      const root = urlRoot ? `&root=${urlRoot}` : '';
-      const base = baseDate ? `&base_date=${baseDate}` : '';
-      const newData = await 
axios.get(`${treeDataUrl}?dag_id=${dagId}&num_runs=${numRuns}${root}${base}`);
+      const params = new URLSearchParams({
+        dag_id: dagId,
+      });
+      if (numRuns && numRuns !== 25) params.append('num_runs', numRuns);
+      if (urlRoot) params.append('root', urlRoot);
+      if (baseDate) params.append('base_date', baseDate);
+
+      const newData = await axios.get(treeDataUrl, { params });
       // turn off auto refresh if there are no active runs
       if (!areActiveRuns(newData.dagRuns)) stopRefresh();
       return newData;
@@ -62,6 +68,7 @@ const useTreeData = () => {
     // only refetch if the refresh switch is on
     refetchInterval: isRefreshOn && autoRefreshInterval * 1000,
     initialData,
+    placeholderData: emptyData,
   });
 };
 
diff --git a/airflow/www/static/js/tree/api/useTreeData.test.jsx 
b/airflow/www/static/js/tree/api/useTreeData.test.jsx
index 03d99ea7e0..01c59ef346 100644
--- a/airflow/www/static/js/tree/api/useTreeData.test.jsx
+++ b/airflow/www/static/js/tree/api/useTreeData.test.jsx
@@ -16,11 +16,10 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-import React from 'react';
+
 import { renderHook } from '@testing-library/react-hooks';
-import { QueryClient, QueryClientProvider } from 'react-query';
 import useTreeData from './useTreeData';
-import { AutoRefreshProvider } from '../context/autorefresh';
+import { Wrapper } from '../utils/testUtils';
 
 /* global describe, test, expect, beforeAll */
 
@@ -41,17 +40,6 @@ const pendingTreeData = {
   ],
 };
 
-const Wrapper = ({ children }) => {
-  const queryClient = new QueryClient();
-  return (
-    <AutoRefreshProvider>
-      <QueryClientProvider client={queryClient}>
-        {children}
-      </QueryClientProvider>
-    </AutoRefreshProvider>
-  );
-};
-
 describe('Test useTreeData hook', () => {
   beforeAll(() => {
     global.autoRefreshInterval = 5;
diff --git a/airflow/www/static/js/tree/dagRuns/index.jsx 
b/airflow/www/static/js/tree/dagRuns/index.jsx
index c304b18bcf..462fffc8e3 100644
--- a/airflow/www/static/js/tree/dagRuns/index.jsx
+++ b/airflow/www/static/js/tree/dagRuns/index.jsx
@@ -38,7 +38,7 @@ const DurationTick = ({ children, ...rest }) => (
 );
 
 const DagRuns = () => {
-  const { data: { dagRuns = [] } } = useTreeData();
+  const { data: { dagRuns } } = useTreeData();
   const { selected, onSelect } = useSelection();
   const durations = [];
   const runs = dagRuns.map((dagRun) => {
diff --git a/airflow/www/static/js/tree/dagRuns/index.test.jsx 
b/airflow/www/static/js/tree/dagRuns/index.test.jsx
index 15a30ce41a..550504b0fc 100644
--- a/airflow/www/static/js/tree/dagRuns/index.test.jsx
+++ b/airflow/www/static/js/tree/dagRuns/index.test.jsx
@@ -21,75 +21,43 @@
 
 import React from 'react';
 import { render } from '@testing-library/react';
-import { ChakraProvider, Table, Tbody } from '@chakra-ui/react';
 import moment from 'moment-timezone';
-import { QueryClient, QueryClientProvider } from 'react-query';
-import { MemoryRouter } from 'react-router-dom';
 
 import DagRuns from './index';
-import { ContainerRefProvider } from '../context/containerRef';
-import { TimezoneProvider } from '../context/timezone';
-import { AutoRefreshProvider } from '../context/autorefresh';
+import { TableWrapper } from '../utils/testUtils';
 
-global.moment = moment;
-
-const Wrapper = ({ children }) => {
-  const queryClient = new QueryClient();
-  return (
-    <React.StrictMode>
-      <ChakraProvider>
-        <QueryClientProvider client={queryClient}>
-          <ContainerRefProvider value={{}}>
-            <TimezoneProvider value={{ timezone: 'UTC' }}>
-              <AutoRefreshProvider value={{ isRefreshOn: false, stopRefresh: 
() => {} }}>
-                <MemoryRouter>
-                  <Table>
-                    <Tbody>
-                      {children}
-                    </Tbody>
-                  </Table>
-                </MemoryRouter>
-              </AutoRefreshProvider>
-            </TimezoneProvider>
-          </ContainerRefProvider>
-        </QueryClientProvider>
-      </ChakraProvider>
-    </React.StrictMode>
-  );
-};
+const dagRuns = [
+  {
+    dagId: 'dagId',
+    runId: 'run1',
+    dataIntervalStart: new Date(),
+    dataIntervalEnd: new Date(),
+    startDate: '2021-11-08T21:14:19.704433+00:00',
+    endDate: '2021-11-08T21:17:13.206426+00:00',
+    state: 'failed',
+    runType: 'scheduled',
+    executionDate: '2021-11-08T21:14:19.704433+00:00',
+  },
+  {
+    dagId: 'dagId',
+    runId: 'run2',
+    dataIntervalStart: new Date(),
+    dataIntervalEnd: new Date(),
+    state: 'success',
+    runType: 'manual',
+    startDate: '2021-11-09T00:19:43.023200+00:00',
+    endDate: '2021-11-09T00:22:18.607167+00:00',
+  },
+];
 
 describe('Test DagRuns', () => {
-  const dagRuns = [
-    {
-      dagId: 'dagId',
-      runId: 'run1',
-      dataIntervalStart: new Date(),
-      dataIntervalEnd: new Date(),
-      startDate: '2021-11-08T21:14:19.704433+00:00',
-      endDate: '2021-11-08T21:17:13.206426+00:00',
-      state: 'failed',
-      runType: 'scheduled',
-      executionDate: '2021-11-08T21:14:19.704433+00:00',
-    },
-    {
-      dagId: 'dagId',
-      runId: 'run2',
-      dataIntervalStart: new Date(),
-      dataIntervalEnd: new Date(),
-      state: 'success',
-      runType: 'manual',
-      startDate: '2021-11-09T00:19:43.023200+00:00',
-      endDate: '2021-11-09T00:22:18.607167+00:00',
-    },
-  ];
-
   test('Durations and manual run arrow render correctly, but without any date 
ticks', () => {
     global.treeData = JSON.stringify({
       groups: {},
       dagRuns,
     });
     const { queryAllByTestId, getByText, queryByText } = render(
-      <DagRuns />, { wrapper: Wrapper },
+      <DagRuns />, { wrapper: TableWrapper },
     );
     expect(queryAllByTestId('run')).toHaveLength(2);
     expect(queryAllByTestId('manual-run')).toHaveLength(1);
@@ -127,26 +95,15 @@ describe('Test DagRuns', () => {
       ],
     });
     const { getByText } = render(
-      <DagRuns />, { wrapper: Wrapper },
+      <DagRuns />, { wrapper: TableWrapper },
     );
     expect(getByText(moment.utc(dagRuns[0].executionDate).format('MMM DD, 
HH:mm'))).toBeInTheDocument();
   });
 
   test('Handles empty data correctly', () => {
-    global.treeData = {
-      groups: {},
-      dagRuns: [],
-    };
-    const { queryByTestId } = render(
-      <DagRuns />, { wrapper: Wrapper },
-    );
-    expect(queryByTestId('run')).toBeNull();
-  });
-
-  test('Handles no data correctly', () => {
-    global.treeData = {};
+    global.treeData = null;
     const { queryByTestId } = render(
-      <DagRuns />, { wrapper: Wrapper },
+      <DagRuns />, { wrapper: TableWrapper },
     );
     expect(queryByTestId('run')).toBeNull();
   });
diff --git a/airflow/www/static/js/tree/details/Header.jsx 
b/airflow/www/static/js/tree/details/Header.jsx
index 5ce3b0583d..2bdaa47361 100644
--- a/airflow/www/static/js/tree/details/Header.jsx
+++ b/airflow/www/static/js/tree/details/Header.jsx
@@ -43,7 +43,7 @@ const LabelValue = ({ label, value }) => (
 );
 
 const Header = () => {
-  const { data: { dagRuns = [] } } = useTreeData();
+  const { data: { dagRuns } } = useTreeData();
   const { selected: { taskId, runId }, onSelect, clearSelection } = 
useSelection();
   const { data: { tasks } } = useTasks();
   const dagRun = dagRuns.find((r) => r.runId === runId);
diff --git a/airflow/www/static/js/tree/details/content/Dag.jsx 
b/airflow/www/static/js/tree/details/content/Dag.jsx
index 928b4f3f55..511844d72e 100644
--- a/airflow/www/static/js/tree/details/content/Dag.jsx
+++ b/airflow/www/static/js/tree/details/content/Dag.jsx
@@ -42,7 +42,7 @@ const dagDetailsUrl = getMetaValue('dag_details_url');
 
 const Dag = () => {
   const { data: taskData } = useTasks(dagId);
-  const { data: { dagRuns = [] } } = useTreeData();
+  const { data: { dagRuns } } = useTreeData();
   if (!taskData) return null;
   const { tasks = [], totalEntries = '' } = taskData;
 
diff --git a/airflow/www/static/js/tree/details/content/dagRun/index.jsx 
b/airflow/www/static/js/tree/details/content/dagRun/index.jsx
index 1816385c58..bd096f1510 100644
--- a/airflow/www/static/js/tree/details/content/dagRun/index.jsx
+++ b/airflow/www/static/js/tree/details/content/dagRun/index.jsx
@@ -43,7 +43,7 @@ const graphUrl = getMetaValue('graph_url');
 const dagRunDetailsUrl = getMetaValue('dagrun_details_url');
 
 const DagRun = ({ runId }) => {
-  const { data: { dagRuns = [] } } = useTreeData();
+  const { data: { dagRuns } } = useTreeData();
   const run = dagRuns.find((dr) => dr.runId === runId);
   if (!run) return null;
   const {
diff --git a/airflow/www/static/js/tree/details/content/taskInstance/index.jsx 
b/airflow/www/static/js/tree/details/content/taskInstance/index.jsx
index 0e4f441e24..e40471f071 100644
--- a/airflow/www/static/js/tree/details/content/taskInstance/index.jsx
+++ b/airflow/www/static/js/tree/details/content/taskInstance/index.jsx
@@ -56,7 +56,7 @@ const getTask = ({ taskId, runId, task }) => {
 
 const TaskInstance = ({ taskId, runId }) => {
   const [selectedRows, setSelectedRows] = useState([]);
-  const { data: { groups = {}, dagRuns = [] } } = useTreeData();
+  const { data: { groups, dagRuns } } = useTreeData();
   const group = getTask({ taskId, runId, task: groups });
   const run = dagRuns.find((r) => r.runId === runId);
   const { executionDate } = run;
diff --git a/airflow/www/static/js/tree/renderTaskRows.test.jsx 
b/airflow/www/static/js/tree/renderTaskRows.test.jsx
index 88afb4a580..415f18b89d 100644
--- a/airflow/www/static/js/tree/renderTaskRows.test.jsx
+++ b/airflow/www/static/js/tree/renderTaskRows.test.jsx
@@ -21,15 +21,9 @@
 
 import React from 'react';
 import { render, fireEvent } from '@testing-library/react';
-import { ChakraProvider, Table, Tbody } from '@chakra-ui/react';
-import moment from 'moment';
-import { QueryClient, QueryClientProvider } from 'react-query';
-import { MemoryRouter } from 'react-router-dom';
 
 import renderTaskRows from './renderTaskRows';
-import { ContainerRefProvider } from './context/containerRef';
-
-global.moment = moment;
+import { TableWrapper } from './utils/testUtils';
 
 const mockTreeData = {
   groups: {
@@ -94,27 +88,6 @@ const mockTreeData = {
   ],
 };
 
-const Wrapper = ({ children }) => {
-  const queryClient = new QueryClient();
-  return (
-    <React.StrictMode>
-      <ChakraProvider>
-        <QueryClientProvider client={queryClient}>
-          <ContainerRefProvider value={{}}>
-            <MemoryRouter>
-              <Table>
-                <Tbody>
-                  {children}
-                </Tbody>
-              </Table>
-            </MemoryRouter>
-          </ContainerRefProvider>
-        </QueryClientProvider>
-      </ChakraProvider>
-    </React.StrictMode>
-  );
-};
-
 describe('Test renderTaskRows', () => {
   test('Group defaults to closed but clicking on the name will open a group', 
() => {
     global.treeData = mockTreeData;
@@ -123,7 +96,7 @@ describe('Test renderTaskRows', () => {
 
     const { getByTestId, getByText, getAllByTestId } = render(
       <>{renderTaskRows({ task, dagRunIds })}</>,
-      { wrapper: Wrapper },
+      { wrapper: TableWrapper },
     );
 
     const groupName = getByText('group_1');
@@ -168,7 +141,7 @@ describe('Test renderTaskRows', () => {
 
     const { queryByTestId, getByText } = render(
       <>{renderTaskRows({ task, dagRunIds: [] })}</>,
-      { wrapper: Wrapper },
+      { wrapper: TableWrapper },
     );
 
     expect(getByText('group_1')).toBeInTheDocument();
diff --git a/airflow/www/static/js/tree/utils/testUtils.jsx 
b/airflow/www/static/js/tree/utils/testUtils.jsx
new file mode 100644
index 0000000000..946fe0dd88
--- /dev/null
+++ b/airflow/www/static/js/tree/utils/testUtils.jsx
@@ -0,0 +1,67 @@
+/*!
+ * 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 { ChakraProvider, Table, Tbody } from '@chakra-ui/react';
+import { QueryClient, QueryClientProvider } from 'react-query';
+import { MemoryRouter } from 'react-router-dom';
+// eslint-disable-next-line import/no-extraneous-dependencies
+import moment from 'moment-timezone';
+
+import { ContainerRefProvider } from '../context/containerRef';
+import { TimezoneProvider } from '../context/timezone';
+import { AutoRefreshProvider } from '../context/autorefresh';
+
+global.moment = moment;
+
+export const Wrapper = ({ children }) => {
+  const queryClient = new QueryClient({
+    defaultOptions: {
+      queries: {
+        cacheTime: Infinity,
+        staleTime: Infinity,
+      },
+    },
+  });
+  return (
+    <ChakraProvider>
+      <QueryClientProvider client={queryClient}>
+        <ContainerRefProvider>
+          <TimezoneProvider>
+            <AutoRefreshProvider>
+              <MemoryRouter>
+                {children}
+              </MemoryRouter>
+            </AutoRefreshProvider>
+          </TimezoneProvider>
+        </ContainerRefProvider>
+      </QueryClientProvider>
+    </ChakraProvider>
+  );
+};
+
+export const TableWrapper = ({ children }) => (
+  <Wrapper>
+    <Table>
+      <Tbody>
+        {children}
+      </Tbody>
+    </Table>
+  </Wrapper>
+);

Reply via email to