All files / react-app/src/features/package hooks.tsx

100% Statements 23/23
92.3% Branches 12/13
100% Functions 9/9
100% Lines 22/22

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79                5x                         5x           5x 6x         5x       6x       11x             5x 4x             5x 6x   6x 4x 4x 6x 6x 6x       4x   4x 4x   4x     6x    
import { useLayoutEffect, useState } from "react";
 
export type DetailsSidebarLink = {
  id: string;
  href: string;
  displayName: string;
};
 
const BASE_SIDEBAR_LINKS: DetailsSidebarLink[] = [
  {
    id: "package_details",
    href: "#package_details",
    displayName: "Package Details",
  },
  {
    id: "package_activity",
    href: "#package_activity",
    displayName: "Package Activity",
  },
];
 
const ADMIN_CHANGES_LINK: DetailsSidebarLink = {
  id: "administrative_package_changes",
  href: "#administrative_package_changes",
  displayName: "Administrative Package Changes",
};
 
const getSidebarLinks = (root: ParentNode = document) => {
  return root.querySelector(`#${ADMIN_CHANGES_LINK.id}`)
    ? [...BASE_SIDEBAR_LINKS, ADMIN_CHANGES_LINK]
    : BASE_SIDEBAR_LINKS;
};
 
const areSidebarLinksEqual = (
  current: DetailsSidebarLink[],
  next: DetailsSidebarLink[],
): boolean => {
  return (
    current.length === next.length &&
    current.every(
      (link, index) =>
        link.id === next[index]?.id &&
        link.href === next[index]?.href &&
        link.displayName === next[index]?.displayName,
    )
  );
};
 
const getSidebarObserverRoot = (): HTMLElement => {
  return (
    document.getElementById("package_details_page") ??
    document.getElementById("package_details")?.parentElement ??
    document.body
  );
};
 
export const useDetailsSidebarLinks = (): DetailsSidebarLink[] => {
  const [sideBarLinks, setSideBarLinks] = useState<DetailsSidebarLink[]>(BASE_SIDEBAR_LINKS);
 
  useLayoutEffect(() => {
    const observerRoot = getSidebarObserverRoot();
    const updateLinks = () => {
      setSideBarLinks((current) => {
        const next = getSidebarLinks(observerRoot);
        return areSidebarLinksEqual(current, next) ? current : next;
      });
    };
 
    updateLinks();
 
    const observer = new MutationObserver(updateLinks);
    observer.observe(observerRoot, { childList: true, subtree: true });
 
    return () => observer.disconnect();
  }, []);
 
  return sideBarLinks;
};