Repository: GoogleChromeLabs/ps-analysis-tool
Pull request #125 (2023-08-24 15:37:37)

Debounce the toggling functionality of table sorting
## Description
This PR contains code to debounce enable and disabling of table sorting. When user moves his cursor inside the header, the sorting enables and as he leaves the sorting gets disabled with debounce to both actions.
<!-- What do we want to achieve with this PR? -->

## Relevant Technical Choices

<!-- Please describe your changes. -->

## Testing Instructions

<!--
How can the changes in this PR be verified?
Please provide step-by-step instructions to test the changes.
-->

## Additional Information:

<!-- Any other information. -->

## Screenshot/Screencast

<!-- Please provide Screenshot/Screencast, if applicable -->

---

<!--
Example:

Fixes #123
Partially addresses #22
See #834
-->

Fixes #



Patch:
diff --git a/package-lock.json b/package-lock.json
index 6320ac6b..e1b404bc 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
 {
 	"name": "cookie-analysis-tool",
-	"version": "0.1.0",
+	"version": "0.0.2",
 	"lockfileVersion": 2,
 	"requires": true,
 	"packages": {
 		"": {
 			"name": "cookie-analysis-tool",
-			"version": "0.1.0",
+			"version": "0.0.2",
 			"license": "Apache-2.0",
 			"workspaces": [
 				"packages/*"
@@ -23186,7 +23186,7 @@
 		},
 		"packages/cli": {
 			"name": "@cookie-analysis-tool/cli",
-			"version": "0.1.0",
+			"version": "0.0.2",
 			"license": "Apache-2.0"
 		},
 		"packages/extension": {
diff --git a/packages/extension/src/view/design-system/components/circlePieChart/index.tsx b/packages/extension/src/view/design-system/components/circlePieChart/index.tsx
index 071d7ad8..c288383c 100644
--- a/packages/extension/src/view/design-system/components/circlePieChart/index.tsx
+++ b/packages/extension/src/view/design-system/components/circlePieChart/index.tsx
@@ -76,7 +76,7 @@ const CirclePieChart = ({
           <p className="text-xs text-center font-semibold leading-relaxed dark:text-bright-gray">
             {title}
           </p>
-          {title === '3rd Party Cookies' && (
+          {title.toLocaleLowerCase() === '3rd party cookies' && (
             <p
               className={infoIconClassName}
               title="An active ad-blocker or other cookie extensions may affect the results."
diff --git a/packages/extension/src/view/devtools/components/tabContent/cookies/cookiesLanding/cookiesMatrix/index.tsx b/packages/extension/src/view/devtools/components/tabContent/cookies/cookiesLanding/cookiesMatrix/index.tsx
index 0907e56c..80804df0 100644
--- a/packages/extension/src/view/devtools/components/tabContent/cookies/cookiesLanding/cookiesMatrix/index.tsx
+++ b/packages/extension/src/view/devtools/components/tabContent/cookies/cookiesLanding/cookiesMatrix/index.tsx
@@ -32,7 +32,6 @@ import type {
   TabFrames,
   CookieStatsComponents,
 } from '../../../../../cookies.types';
-import { InfoIcon } from '../../../../../../../icons';
 
 interface CookiesMatrixProps {
   tabCookies: TabCookies | null;
@@ -113,11 +112,8 @@ const CookiesMatrix = ({
     <div className="w-full" data-testid="cookies-matrix">
       <div>
         <div className="flex gap-x-5 justify-between">
-          <h4 className="flex items-center gap-1 pb-3 flex-1 grow border-b border-bright-gray dark:border-quartz text-xs font-bold text-darkest-gray dark:text-bright-gray uppercase">
-            <span>Cookies Insights</span>
-            <span title="An active ad-blocker or other cookie extensions may affect the results.">
-              <InfoIcon />
-            </span>
+          <h4 className="pb-3 flex-1 grow border-b border-bright-gray dark:border-quartz text-xs font-bold text-darkest-gray dark:text-bright-gray uppercase">
+            Cookies Insights
           </h4>
           <h4 className="pb-3 flex-1 grow border-b border-bright-gray dark:border-quartz text-xs font-bold text-darkest-gray dark:text-bright-gray text-right">
             <button onClick={() => setIsExpanded((state) => !state)}>
diff --git a/packages/extension/src/view/devtools/components/tabContent/cookies/cookiesListing/cookieTable/index.tsx b/packages/extension/src/view/devtools/components/tabContent/cookies/cookiesListing/cookieTable/index.tsx
index 9acbadb3..2ff4ecb0 100644
--- a/packages/extension/src/view/devtools/components/tabContent/cookies/cookiesListing/cookieTable/index.tsx
+++ b/packages/extension/src/view/devtools/components/tabContent/cookies/cookiesListing/cookieTable/index.tsx
@@ -24,6 +24,7 @@ import {
   type ColumnDef,
   getSortedRowModel,
 } from '@tanstack/react-table';
+import { useDebouncedCallback } from 'use-debounce';
 
 /**
  * Internal dependencies.
@@ -35,8 +36,6 @@ import type { CookieTableData } from '../../../../../cookies.types';
 export interface CookieTableProps {
   cookies: CookieTableData[];
   selectedFrame: string | null;
-  isMouseInsideHeader: boolean;
-  setIsMouseInsideHeader: React.Dispatch<React.SetStateAction<boolean>>;
 }
 
 const tableColumns: ColumnDef<CookieTableData>[] = [
@@ -137,12 +136,7 @@ const tableColumns: ColumnDef<CookieTableData>[] = [
   },
 ];
 
-const CookieTable = ({
-  cookies,
-  selectedFrame,
-  isMouseInsideHeader,
-  setIsMouseInsideHeader,
-}: CookieTableProps) => {
+const CookieTable = ({ cookies, selectedFrame }: CookieTableProps) => {
   const {
     selectedFrameCookie,
     setSelectedFrameCookie,
@@ -156,12 +150,21 @@ const CookieTable = ({
   }));
 
   const [data, setData] = useState<CookieTableData[]>(cookies);
+  const [isMouseInsideHeader, setIsMouseInsideHeader] =
+    useState<boolean>(false);
+  const [enableSorting, setEnableSorting] = useState<boolean>(false);
+  const setDebouncedEnableSorting = useDebouncedCallback((value) => {
+    setEnableSorting(value);
+  }, 10);
 
   useEffect(() => {
-    if (!isMouseInsideHeader) {
+    if (isMouseInsideHeader) {
+      setDebouncedEnableSorting(true);
+    } else {
       setData(cookies);
+      setDebouncedEnableSorting(false);
     }
-  }, [cookies, isMouseInsideHeader]);
+  }, [cookies, isMouseInsideHeader, setDebouncedEnableSorting]);
 
   useEffect(() => {
     if (selectedFrame && selectedFrameCookie) {
@@ -188,6 +191,7 @@ const CookieTable = ({
     data,
     columns,
     enableColumnResizing: true,
+    enableSorting,
     columnResizeMode: 'onChange',
     getCoreRowModel: getCoreRowModel(),
     getSortedRowModel: getSortedRowModel(),
diff --git a/packages/extension/src/view/devtools/components/tabContent/cookies/cookiesListing/index.tsx b/packages/extension/src/view/devtools/components/tabContent/cookies/cookiesListing/index.tsx
index 8039ed42..a27f9b11 100644
--- a/packages/extension/src/view/devtools/components/tabContent/cookies/cookiesListing/index.tsx
+++ b/packages/extension/src/view/devtools/components/tabContent/cookies/cookiesListing/index.tsx
@@ -31,12 +31,9 @@ import CookieTopBar from '../cookieTopBar';
 import FiltersList from '../cookieFilter';
 
 const CookiesListing = () => {
-  const { selectedFrame, isMouseInsideHeader, setIsMouseInsideHeader } =
-    useCookieStore(({ state, actions }) => ({
-      selectedFrame: state.selectedFrame,
-      isMouseInsideHeader: state.isMouseInsideHeader,
-      setIsMouseInsideHeader: actions.setIsMouseInsideHeader,
-    }));
+  const { selectedFrame } = useCookieStore(({ state }) => ({
+    selectedFrame: state.selectedFrame,
+  }));
 
   const { filteredCookies, cookiesAvailable } = useFilterManagementStore(
     ({ state }) => ({
@@ -98,8 +95,6 @@ const CookiesListing = () => {
                 <CookieTable
                   cookies={filteredCookies}
                   selectedFrame={selectedFrame}
-                  isMouseInsideHeader={isMouseInsideHeader}
-                  setIsMouseInsideHeader={setIsMouseInsideHeader}
                 />
               </div>
             </div>
diff --git a/packages/extension/src/view/devtools/stateProviders/syncCookieStore/index.tsx b/packages/extension/src/view/devtools/stateProviders/syncCookieStore/index.tsx
index 9167466d..5bf43b24 100644
--- a/packages/extension/src/view/devtools/stateProviders/syncCookieStore/index.tsx
+++ b/packages/extension/src/view/devtools/stateProviders/syncCookieStore/index.tsx
@@ -36,11 +36,9 @@ export interface CookieStoreContext {
     tabUrl: string | null;
     tabFrames: TabFrames | null;
     selectedFrame: string | null;
-    isMouseInsideHeader: boolean;
   };
   actions: {
     setSelectedFrame: React.Dispatch<React.SetStateAction<string | null>>;
-    setIsMouseInsideHeader: React.Dispatch<React.SetStateAction<boolean>>;
   };
 }
 
@@ -50,11 +48,9 @@ const initialState: CookieStoreContext = {
     tabUrl: null,
     tabFrames: null,
     selectedFrame: null,
-    isMouseInsideHeader: false,
   },
   actions: {
     setSelectedFrame: () => undefined,
-    setIsMouseInsideHeader: () => undefined,
   },
 };
 
@@ -74,9 +70,6 @@ export const Provider = ({ children }: PropsWithChildren) => {
   const [tabFrames, setTabFrames] =
     useState<CookieStoreContext['state']['tabFrames']>(null);
 
-  const [isMouseInsideHeader, setIsMouseInsideHeader] =
-    useState<boolean>(false);
-
   const getAllFramesForCurrentTab = useCallback(
     async (_tabId: number | null) => {
       if (!_tabId) {
@@ -216,9 +209,8 @@ export const Provider = ({ children }: PropsWithChildren) => {
           tabUrl,
           tabFrames,
           selectedFrame,
-          isMouseInsideHeader,
         },
-        actions: { setSelectedFrame, setIsMouseInsideHeader },
+        actions: { setSelectedFrame },
       }}
     >
       {children}


Test patch:
diff --git a/packages/extension/src/view/devtools/components/tabContent/cookies/tests/cookieTab.tsx b/packages/extension/src/view/devtools/components/tabContent/cookies/tests/cookieTab.tsx
index 12f5cb4a..55e56344 100644
--- a/packages/extension/src/view/devtools/components/tabContent/cookies/tests/cookieTab.tsx
+++ b/packages/extension/src/view/devtools/components/tabContent/cookies/tests/cookieTab.tsx
@@ -17,7 +17,13 @@
  * External dependencies.
  */
 import React from 'react';
-import { fireEvent, render, screen, within } from '@testing-library/react';
+import {
+  fireEvent,
+  render,
+  screen,
+  waitFor,
+  within,
+} from '@testing-library/react';
 import '@testing-library/jest-dom';
 import SinonChrome from 'sinon-chrome';
 
@@ -76,6 +82,7 @@ mockFilterManagementStore.mockImplementation((selector) => {
 describe('CookieTab', () => {
   beforeAll(() => {
     globalThis.chrome = SinonChrome as unknown as typeof chrome;
+    globalThis.Promise = Promise;
   });
 
   it('should render a list of cookies with analytics', async () => {
@@ -91,28 +98,56 @@ describe('CookieTab', () => {
     render(<CookieTab />);
 
     const headerCell = (await screen.findAllByTestId('header-cell'))[0];
+    fireEvent.mouseEnter(headerCell);
+    waitFor(
+      async () => {
+        await new Promise((r) => setTimeout(r, 100));
+      },
+      { timeout: 1000 }
+    );
     fireEvent.click(headerCell);
 
     const firstRow = (await screen.findAllByTestId('body-row'))[0];
-
-    expect(
-      await within(firstRow).findByText('KRTBCOOKIE_290')
-    ).toBeInTheDocument();
+    waitFor(
+      async () => {
+        expect(
+          await within(firstRow).findByText('KRTBCOOKIE_290')
+        ).toBeInTheDocument();
+      },
+      { interval: 1000 }
+    );
 
     const lastRow = (await screen.findAllByTestId('body-row'))[3];
-    expect(await within(lastRow).findByText('pubsyncexp')).toBeInTheDocument();
+    waitFor(
+      async () => {
+        expect(
+          await within(lastRow).findByText('pubsyncexp')
+        ).toBeInTheDocument();
+      },
+      { interval: 1000 }
+    );
 
     fireEvent.click(headerCell);
 
     const firstRowAfterReverse = (await screen.findAllByTestId('body-row'))[0];
-    expect(
-      await within(firstRowAfterReverse).findByText('pubsyncexp')
-    ).toBeInTheDocument();
+    waitFor(
+      async () => {
+        expect(
+          await within(firstRowAfterReverse).findByText('pubsyncexp')
+        ).toBeInTheDocument();
+      },
+      { interval: 1000 }
+    );
 
     const lastRowAfterReverse = (await screen.findAllByTestId('body-row'))[3];
-    expect(
-      await within(lastRowAfterReverse).findByText('KRTBCOOKIE_290')
-    ).toBeInTheDocument();
+    waitFor(
+      async () => {
+        expect(
+          await within(lastRowAfterReverse).findByText('KRTBCOOKIE_290')
+        ).toBeInTheDocument();
+      },
+      { interval: 1000 }
+    );
   });
 
   it('should open column menu when right click on header cell', async () => {