From 5f4f4074e02adbb607df69fb9c0bc363998d199f Mon Sep 17 00:00:00 2001
From: Thomas Walker <thomas.e.walker88@gmail.com>
Date: Tue, 21 Jan 2025 12:29:18 -0500
Subject: [PATCH 1/4] feat(test) post submission form snapshots (#1042)

* feat(test) post submission form snapshots

* Additional test
---
 .../__snapshots__/index.test.tsx.snap         | 851 +++++++++++++++++
 .../toggle-withdraw-rai/index.test.tsx        |  30 +
 .../__snapshots__/indext.test.tsx.snap        | 876 ++++++++++++++++++
 .../withdraw-package/indext.test.tsx          |  16 +
 react-app/vitest.setup.ts                     |   5 +-
 5 files changed, 1777 insertions(+), 1 deletion(-)
 create mode 100644 react-app/src/features/forms/post-submission/toggle-withdraw-rai/__snapshots__/index.test.tsx.snap
 create mode 100644 react-app/src/features/forms/post-submission/toggle-withdraw-rai/index.test.tsx
 create mode 100644 react-app/src/features/forms/post-submission/withdraw-package/__snapshots__/indext.test.tsx.snap
 create mode 100644 react-app/src/features/forms/post-submission/withdraw-package/indext.test.tsx

diff --git a/react-app/src/features/forms/post-submission/toggle-withdraw-rai/__snapshots__/index.test.tsx.snap b/react-app/src/features/forms/post-submission/toggle-withdraw-rai/__snapshots__/index.test.tsx.snap
new file mode 100644
index 0000000000..914c34bc0b
--- /dev/null
+++ b/react-app/src/features/forms/post-submission/toggle-withdraw-rai/__snapshots__/index.test.tsx.snap
@@ -0,0 +1,851 @@
+// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
+
+exports[`Toggle Withdraw Rai components > renders disable withdraw rai correctly 1`] = `
+{
+  "asFragment": [Function],
+  "baseElement": <body>
+    <div>
+      <div
+        class="max-w-screen-xl mx-auto px-4 lg:px-8"
+      >
+        <nav
+          aria-label="breadcrumbs for spa or waiver choices"
+          class="my-4"
+          role="navigation"
+        >
+          <ul
+            class="flex flex-wrap gap-1"
+          >
+            <li
+              class="flex items-center text-sm"
+            >
+              <a
+                class="underline text-sky-700 hover:text-sky-800"
+                data-discover="true"
+                href="/dashboard?tab=waivers"
+              >
+                Dashboard
+              </a>
+            </li>
+            <li
+              class="flex items-center text-sm"
+            >
+              <span>
+                <svg
+                  class="w-5 h-5"
+                  fill="none"
+                  height="24"
+                  stroke="currentColor"
+                  stroke-linecap="round"
+                  stroke-linejoin="round"
+                  stroke-width="2"
+                  viewBox="0 0 24 24"
+                  width="24"
+                  xmlns="http://www.w3.org/2000/svg"
+                >
+                  <path
+                    d="m9 18 6-6-6-6"
+                  />
+                </svg>
+              </span>
+              <a
+                class="underline text-sky-700 hover:text-sky-800"
+                data-discover="true"
+                href="/details/1915(b)/VA-2234.R11.02"
+              >
+                VA-2234.R11.02
+              </a>
+            </li>
+            <li
+              class="flex items-center text-sm"
+            >
+              <span>
+                <svg
+                  class="w-5 h-5"
+                  fill="none"
+                  height="24"
+                  stroke="currentColor"
+                  stroke-linecap="round"
+                  stroke-linejoin="round"
+                  stroke-width="2"
+                  viewBox="0 0 24 24"
+                  width="24"
+                  xmlns="http://www.w3.org/2000/svg"
+                >
+                  <path
+                    d="m9 18 6-6-6-6"
+                  />
+                </svg>
+              </span>
+              <span
+                aria-disabled="true"
+                class="whitespace-nowrap"
+              >
+                Enable Formal RAI Response Withdraw
+              </span>
+            </li>
+          </ul>
+        </nav>
+        <form
+          class="my-6 space-y-8 mx-auto justify-center flex flex-col"
+        >
+          <section
+            class="p-4 border rounded-sm border-cardBorder"
+            data-testid="detail-section"
+          >
+            <h1
+              class="text-3xl font-semibold mb-2"
+              data-testid="detail-section-title"
+            >
+              Enable Formal RAI Response Withdraw Details
+            </h1>
+            <hr
+              class="my-6 bg-slate-200"
+            />
+            <div
+              class="gap-8 flex flex-col"
+              data-testid="detail-section-child"
+            >
+              <div>
+                <div
+                  class="mt-4"
+                >
+                  Once you submit this form, the most recent Formal RAI Response for this package will be able to be withdrawn by the state
+                </div>
+              </div>
+              <section
+                class="flex flex-col mb-8 space-y-8"
+              >
+                <div>
+                  <p
+                    class="font-bold"
+                  >
+                    Waiver Number
+                  </p>
+                  <p
+                    class="text-xl"
+                  >
+                    VA-2234.R11.02
+                  </p>
+                </div>
+                <div>
+                  <p
+                    class="font-bold"
+                  >
+                    Authority
+                  </p>
+                  <p
+                    class="text-xl"
+                  >
+                    1915(b) Waiver
+                  </p>
+                </div>
+              </section>
+            </div>
+          </section>
+          <section
+            class="flex justify-end gap-2 p-4 ml-auto"
+          >
+            <button
+              class="inline-flex items-center justify-center rounded-md text-[16px] font-bold ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 bg-primary text-slate-50 hover:bg-primary-dark h-10 py-2 px-12"
+              data-testid="submit-action-form"
+              disabled=""
+              type="submit"
+            >
+              Submit
+            </button>
+            <button
+              class="inline-flex items-center justify-center rounded-md text-[16px] ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 border border-primary text-primary font-bold hover:bg-primary/10 h-10 py-2 px-12"
+              data-testid="cancel-action-form"
+              type="reset"
+            >
+              Cancel
+            </button>
+          </section>
+        </form>
+        <div
+          class="relative w-full border p-4 [&>svg~*]:pl-7 [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 [&>svg]:text-foreground border-l-[6px] border-y-0 border-r-0 border-cyan-500 bg-cyan-300/10 rounded-none mb-8 items-center flex py-8 px-14 flex-row text-sm justify-center gap-24"
+          role="alert"
+        >
+          <p
+            class="text-lg"
+          >
+            Do you have questions or need support?
+          </p>
+          <a
+            data-discover="true"
+            href="/faq"
+            target="_blank"
+          >
+            <button
+              class="inline-flex items-center justify-center text-[16px] font-bold ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 bg-primary text-slate-50 hover:bg-primary-dark h-11 rounded-md px-8 mx-4"
+            >
+              View FAQ
+            </button>
+          </a>
+        </div>
+      </div>
+      ,
+    </div>
+  </body>,
+  "container": <div>
+    <div
+      class="max-w-screen-xl mx-auto px-4 lg:px-8"
+    >
+      <nav
+        aria-label="breadcrumbs for spa or waiver choices"
+        class="my-4"
+        role="navigation"
+      >
+        <ul
+          class="flex flex-wrap gap-1"
+        >
+          <li
+            class="flex items-center text-sm"
+          >
+            <a
+              class="underline text-sky-700 hover:text-sky-800"
+              data-discover="true"
+              href="/dashboard?tab=waivers"
+            >
+              Dashboard
+            </a>
+          </li>
+          <li
+            class="flex items-center text-sm"
+          >
+            <span>
+              <svg
+                class="w-5 h-5"
+                fill="none"
+                height="24"
+                stroke="currentColor"
+                stroke-linecap="round"
+                stroke-linejoin="round"
+                stroke-width="2"
+                viewBox="0 0 24 24"
+                width="24"
+                xmlns="http://www.w3.org/2000/svg"
+              >
+                <path
+                  d="m9 18 6-6-6-6"
+                />
+              </svg>
+            </span>
+            <a
+              class="underline text-sky-700 hover:text-sky-800"
+              data-discover="true"
+              href="/details/1915(b)/VA-2234.R11.02"
+            >
+              VA-2234.R11.02
+            </a>
+          </li>
+          <li
+            class="flex items-center text-sm"
+          >
+            <span>
+              <svg
+                class="w-5 h-5"
+                fill="none"
+                height="24"
+                stroke="currentColor"
+                stroke-linecap="round"
+                stroke-linejoin="round"
+                stroke-width="2"
+                viewBox="0 0 24 24"
+                width="24"
+                xmlns="http://www.w3.org/2000/svg"
+              >
+                <path
+                  d="m9 18 6-6-6-6"
+                />
+              </svg>
+            </span>
+            <span
+              aria-disabled="true"
+              class="whitespace-nowrap"
+            >
+              Enable Formal RAI Response Withdraw
+            </span>
+          </li>
+        </ul>
+      </nav>
+      <form
+        class="my-6 space-y-8 mx-auto justify-center flex flex-col"
+      >
+        <section
+          class="p-4 border rounded-sm border-cardBorder"
+          data-testid="detail-section"
+        >
+          <h1
+            class="text-3xl font-semibold mb-2"
+            data-testid="detail-section-title"
+          >
+            Enable Formal RAI Response Withdraw Details
+          </h1>
+          <hr
+            class="my-6 bg-slate-200"
+          />
+          <div
+            class="gap-8 flex flex-col"
+            data-testid="detail-section-child"
+          >
+            <div>
+              <div
+                class="mt-4"
+              >
+                Once you submit this form, the most recent Formal RAI Response for this package will be able to be withdrawn by the state
+              </div>
+            </div>
+            <section
+              class="flex flex-col mb-8 space-y-8"
+            >
+              <div>
+                <p
+                  class="font-bold"
+                >
+                  Waiver Number
+                </p>
+                <p
+                  class="text-xl"
+                >
+                  VA-2234.R11.02
+                </p>
+              </div>
+              <div>
+                <p
+                  class="font-bold"
+                >
+                  Authority
+                </p>
+                <p
+                  class="text-xl"
+                >
+                  1915(b) Waiver
+                </p>
+              </div>
+            </section>
+          </div>
+        </section>
+        <section
+          class="flex justify-end gap-2 p-4 ml-auto"
+        >
+          <button
+            class="inline-flex items-center justify-center rounded-md text-[16px] font-bold ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 bg-primary text-slate-50 hover:bg-primary-dark h-10 py-2 px-12"
+            data-testid="submit-action-form"
+            disabled=""
+            type="submit"
+          >
+            Submit
+          </button>
+          <button
+            class="inline-flex items-center justify-center rounded-md text-[16px] ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 border border-primary text-primary font-bold hover:bg-primary/10 h-10 py-2 px-12"
+            data-testid="cancel-action-form"
+            type="reset"
+          >
+            Cancel
+          </button>
+        </section>
+      </form>
+      <div
+        class="relative w-full border p-4 [&>svg~*]:pl-7 [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 [&>svg]:text-foreground border-l-[6px] border-y-0 border-r-0 border-cyan-500 bg-cyan-300/10 rounded-none mb-8 items-center flex py-8 px-14 flex-row text-sm justify-center gap-24"
+        role="alert"
+      >
+        <p
+          class="text-lg"
+        >
+          Do you have questions or need support?
+        </p>
+        <a
+          data-discover="true"
+          href="/faq"
+          target="_blank"
+        >
+          <button
+            class="inline-flex items-center justify-center text-[16px] font-bold ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 bg-primary text-slate-50 hover:bg-primary-dark h-11 rounded-md px-8 mx-4"
+          >
+            View FAQ
+          </button>
+        </a>
+      </div>
+    </div>
+    ,
+  </div>,
+  "debug": [Function],
+  "findAllByAltText": [Function],
+  "findAllByDisplayValue": [Function],
+  "findAllByLabelText": [Function],
+  "findAllByPlaceholderText": [Function],
+  "findAllByRole": [Function],
+  "findAllByTestId": [Function],
+  "findAllByText": [Function],
+  "findAllByTitle": [Function],
+  "findByAltText": [Function],
+  "findByDisplayValue": [Function],
+  "findByLabelText": [Function],
+  "findByPlaceholderText": [Function],
+  "findByRole": [Function],
+  "findByTestId": [Function],
+  "findByText": [Function],
+  "findByTitle": [Function],
+  "getAllByAltText": [Function],
+  "getAllByDisplayValue": [Function],
+  "getAllByLabelText": [Function],
+  "getAllByPlaceholderText": [Function],
+  "getAllByRole": [Function],
+  "getAllByTestId": [Function],
+  "getAllByText": [Function],
+  "getAllByTitle": [Function],
+  "getByAltText": [Function],
+  "getByDisplayValue": [Function],
+  "getByLabelText": [Function],
+  "getByPlaceholderText": [Function],
+  "getByRole": [Function],
+  "getByTestId": [Function],
+  "getByText": [Function],
+  "getByTitle": [Function],
+  "queryAllByAltText": [Function],
+  "queryAllByDisplayValue": [Function],
+  "queryAllByLabelText": [Function],
+  "queryAllByPlaceholderText": [Function],
+  "queryAllByRole": [Function],
+  "queryAllByTestId": [Function],
+  "queryAllByText": [Function],
+  "queryAllByTitle": [Function],
+  "queryByAltText": [Function],
+  "queryByDisplayValue": [Function],
+  "queryByLabelText": [Function],
+  "queryByPlaceholderText": [Function],
+  "queryByRole": [Function],
+  "queryByTestId": [Function],
+  "queryByText": [Function],
+  "queryByTitle": [Function],
+  "rerender": [Function],
+  "unmount": [Function],
+}
+`;
+
+exports[`Toggle Withdraw Rai components > renders disable withdraw rai correctly 2`] = `
+{
+  "asFragment": [Function],
+  "baseElement": <body>
+    <div>
+      <div
+        class="max-w-screen-xl mx-auto px-4 lg:px-8"
+      >
+        <nav
+          aria-label="breadcrumbs for spa or waiver choices"
+          class="my-4"
+          role="navigation"
+        >
+          <ul
+            class="flex flex-wrap gap-1"
+          >
+            <li
+              class="flex items-center text-sm"
+            >
+              <a
+                class="underline text-sky-700 hover:text-sky-800"
+                data-discover="true"
+                href="/dashboard?tab=waivers"
+              >
+                Dashboard
+              </a>
+            </li>
+            <li
+              class="flex items-center text-sm"
+            >
+              <span>
+                <svg
+                  class="w-5 h-5"
+                  fill="none"
+                  height="24"
+                  stroke="currentColor"
+                  stroke-linecap="round"
+                  stroke-linejoin="round"
+                  stroke-width="2"
+                  viewBox="0 0 24 24"
+                  width="24"
+                  xmlns="http://www.w3.org/2000/svg"
+                >
+                  <path
+                    d="m9 18 6-6-6-6"
+                  />
+                </svg>
+              </span>
+              <a
+                class="underline text-sky-700 hover:text-sky-800"
+                data-discover="true"
+                href="/details/1915(b)/VA-2234.R11.02"
+              >
+                VA-2234.R11.02
+              </a>
+            </li>
+            <li
+              class="flex items-center text-sm"
+            >
+              <span>
+                <svg
+                  class="w-5 h-5"
+                  fill="none"
+                  height="24"
+                  stroke="currentColor"
+                  stroke-linecap="round"
+                  stroke-linejoin="round"
+                  stroke-width="2"
+                  viewBox="0 0 24 24"
+                  width="24"
+                  xmlns="http://www.w3.org/2000/svg"
+                >
+                  <path
+                    d="m9 18 6-6-6-6"
+                  />
+                </svg>
+              </span>
+              <span
+                aria-disabled="true"
+                class="whitespace-nowrap"
+              >
+                Disable Formal RAI Response Withdraw
+              </span>
+            </li>
+          </ul>
+        </nav>
+        <form
+          class="my-6 space-y-8 mx-auto justify-center flex flex-col"
+        >
+          <section
+            class="p-4 border rounded-sm border-cardBorder"
+            data-testid="detail-section"
+          >
+            <h1
+              class="text-3xl font-semibold mb-2"
+              data-testid="detail-section-title"
+            >
+              Disable Formal RAI Response Withdraw Details
+            </h1>
+            <hr
+              class="my-6 bg-slate-200"
+            />
+            <div
+              class="gap-8 flex flex-col"
+              data-testid="detail-section-child"
+            >
+              <div>
+                <div
+                  class="mt-4"
+                >
+                  The state will not be able to withdraw its RAI response. It may take up to a minute for this change to be applied.
+                </div>
+              </div>
+              <section
+                class="flex flex-col mb-8 space-y-8"
+              >
+                <div>
+                  <p
+                    class="font-bold"
+                  >
+                    Waiver Number
+                  </p>
+                  <p
+                    class="text-xl"
+                  >
+                    VA-2234.R11.02
+                  </p>
+                </div>
+                <div>
+                  <p
+                    class="font-bold"
+                  >
+                    Authority
+                  </p>
+                  <p
+                    class="text-xl"
+                  >
+                    1915(b) Waiver
+                  </p>
+                </div>
+              </section>
+            </div>
+          </section>
+          <section
+            class="flex justify-end gap-2 p-4 ml-auto"
+          >
+            <button
+              class="inline-flex items-center justify-center rounded-md text-[16px] font-bold ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 bg-primary text-slate-50 hover:bg-primary-dark h-10 py-2 px-12"
+              data-testid="submit-action-form"
+              disabled=""
+              type="submit"
+            >
+              Submit
+            </button>
+            <button
+              class="inline-flex items-center justify-center rounded-md text-[16px] ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 border border-primary text-primary font-bold hover:bg-primary/10 h-10 py-2 px-12"
+              data-testid="cancel-action-form"
+              type="reset"
+            >
+              Cancel
+            </button>
+          </section>
+        </form>
+        <div
+          class="relative w-full border p-4 [&>svg~*]:pl-7 [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 [&>svg]:text-foreground border-l-[6px] border-y-0 border-r-0 border-cyan-500 bg-cyan-300/10 rounded-none mb-8 items-center flex py-8 px-14 flex-row text-sm justify-center gap-24"
+          role="alert"
+        >
+          <p
+            class="text-lg"
+          >
+            Do you have questions or need support?
+          </p>
+          <a
+            data-discover="true"
+            href="/faq"
+            target="_blank"
+          >
+            <button
+              class="inline-flex items-center justify-center text-[16px] font-bold ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 bg-primary text-slate-50 hover:bg-primary-dark h-11 rounded-md px-8 mx-4"
+            >
+              View FAQ
+            </button>
+          </a>
+        </div>
+      </div>
+      ,
+    </div>
+  </body>,
+  "container": <div>
+    <div
+      class="max-w-screen-xl mx-auto px-4 lg:px-8"
+    >
+      <nav
+        aria-label="breadcrumbs for spa or waiver choices"
+        class="my-4"
+        role="navigation"
+      >
+        <ul
+          class="flex flex-wrap gap-1"
+        >
+          <li
+            class="flex items-center text-sm"
+          >
+            <a
+              class="underline text-sky-700 hover:text-sky-800"
+              data-discover="true"
+              href="/dashboard?tab=waivers"
+            >
+              Dashboard
+            </a>
+          </li>
+          <li
+            class="flex items-center text-sm"
+          >
+            <span>
+              <svg
+                class="w-5 h-5"
+                fill="none"
+                height="24"
+                stroke="currentColor"
+                stroke-linecap="round"
+                stroke-linejoin="round"
+                stroke-width="2"
+                viewBox="0 0 24 24"
+                width="24"
+                xmlns="http://www.w3.org/2000/svg"
+              >
+                <path
+                  d="m9 18 6-6-6-6"
+                />
+              </svg>
+            </span>
+            <a
+              class="underline text-sky-700 hover:text-sky-800"
+              data-discover="true"
+              href="/details/1915(b)/VA-2234.R11.02"
+            >
+              VA-2234.R11.02
+            </a>
+          </li>
+          <li
+            class="flex items-center text-sm"
+          >
+            <span>
+              <svg
+                class="w-5 h-5"
+                fill="none"
+                height="24"
+                stroke="currentColor"
+                stroke-linecap="round"
+                stroke-linejoin="round"
+                stroke-width="2"
+                viewBox="0 0 24 24"
+                width="24"
+                xmlns="http://www.w3.org/2000/svg"
+              >
+                <path
+                  d="m9 18 6-6-6-6"
+                />
+              </svg>
+            </span>
+            <span
+              aria-disabled="true"
+              class="whitespace-nowrap"
+            >
+              Disable Formal RAI Response Withdraw
+            </span>
+          </li>
+        </ul>
+      </nav>
+      <form
+        class="my-6 space-y-8 mx-auto justify-center flex flex-col"
+      >
+        <section
+          class="p-4 border rounded-sm border-cardBorder"
+          data-testid="detail-section"
+        >
+          <h1
+            class="text-3xl font-semibold mb-2"
+            data-testid="detail-section-title"
+          >
+            Disable Formal RAI Response Withdraw Details
+          </h1>
+          <hr
+            class="my-6 bg-slate-200"
+          />
+          <div
+            class="gap-8 flex flex-col"
+            data-testid="detail-section-child"
+          >
+            <div>
+              <div
+                class="mt-4"
+              >
+                The state will not be able to withdraw its RAI response. It may take up to a minute for this change to be applied.
+              </div>
+            </div>
+            <section
+              class="flex flex-col mb-8 space-y-8"
+            >
+              <div>
+                <p
+                  class="font-bold"
+                >
+                  Waiver Number
+                </p>
+                <p
+                  class="text-xl"
+                >
+                  VA-2234.R11.02
+                </p>
+              </div>
+              <div>
+                <p
+                  class="font-bold"
+                >
+                  Authority
+                </p>
+                <p
+                  class="text-xl"
+                >
+                  1915(b) Waiver
+                </p>
+              </div>
+            </section>
+          </div>
+        </section>
+        <section
+          class="flex justify-end gap-2 p-4 ml-auto"
+        >
+          <button
+            class="inline-flex items-center justify-center rounded-md text-[16px] font-bold ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 bg-primary text-slate-50 hover:bg-primary-dark h-10 py-2 px-12"
+            data-testid="submit-action-form"
+            disabled=""
+            type="submit"
+          >
+            Submit
+          </button>
+          <button
+            class="inline-flex items-center justify-center rounded-md text-[16px] ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 border border-primary text-primary font-bold hover:bg-primary/10 h-10 py-2 px-12"
+            data-testid="cancel-action-form"
+            type="reset"
+          >
+            Cancel
+          </button>
+        </section>
+      </form>
+      <div
+        class="relative w-full border p-4 [&>svg~*]:pl-7 [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 [&>svg]:text-foreground border-l-[6px] border-y-0 border-r-0 border-cyan-500 bg-cyan-300/10 rounded-none mb-8 items-center flex py-8 px-14 flex-row text-sm justify-center gap-24"
+        role="alert"
+      >
+        <p
+          class="text-lg"
+        >
+          Do you have questions or need support?
+        </p>
+        <a
+          data-discover="true"
+          href="/faq"
+          target="_blank"
+        >
+          <button
+            class="inline-flex items-center justify-center text-[16px] font-bold ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 bg-primary text-slate-50 hover:bg-primary-dark h-11 rounded-md px-8 mx-4"
+          >
+            View FAQ
+          </button>
+        </a>
+      </div>
+    </div>
+    ,
+  </div>,
+  "debug": [Function],
+  "findAllByAltText": [Function],
+  "findAllByDisplayValue": [Function],
+  "findAllByLabelText": [Function],
+  "findAllByPlaceholderText": [Function],
+  "findAllByRole": [Function],
+  "findAllByTestId": [Function],
+  "findAllByText": [Function],
+  "findAllByTitle": [Function],
+  "findByAltText": [Function],
+  "findByDisplayValue": [Function],
+  "findByLabelText": [Function],
+  "findByPlaceholderText": [Function],
+  "findByRole": [Function],
+  "findByTestId": [Function],
+  "findByText": [Function],
+  "findByTitle": [Function],
+  "getAllByAltText": [Function],
+  "getAllByDisplayValue": [Function],
+  "getAllByLabelText": [Function],
+  "getAllByPlaceholderText": [Function],
+  "getAllByRole": [Function],
+  "getAllByTestId": [Function],
+  "getAllByText": [Function],
+  "getAllByTitle": [Function],
+  "getByAltText": [Function],
+  "getByDisplayValue": [Function],
+  "getByLabelText": [Function],
+  "getByPlaceholderText": [Function],
+  "getByRole": [Function],
+  "getByTestId": [Function],
+  "getByText": [Function],
+  "getByTitle": [Function],
+  "queryAllByAltText": [Function],
+  "queryAllByDisplayValue": [Function],
+  "queryAllByLabelText": [Function],
+  "queryAllByPlaceholderText": [Function],
+  "queryAllByRole": [Function],
+  "queryAllByTestId": [Function],
+  "queryAllByText": [Function],
+  "queryAllByTitle": [Function],
+  "queryByAltText": [Function],
+  "queryByDisplayValue": [Function],
+  "queryByLabelText": [Function],
+  "queryByPlaceholderText": [Function],
+  "queryByRole": [Function],
+  "queryByTestId": [Function],
+  "queryByText": [Function],
+  "queryByTitle": [Function],
+  "rerender": [Function],
+  "unmount": [Function],
+}
+`;
diff --git a/react-app/src/features/forms/post-submission/toggle-withdraw-rai/index.test.tsx b/react-app/src/features/forms/post-submission/toggle-withdraw-rai/index.test.tsx
new file mode 100644
index 0000000000..552afa0845
--- /dev/null
+++ b/react-app/src/features/forms/post-submission/toggle-withdraw-rai/index.test.tsx
@@ -0,0 +1,30 @@
+import { describe, expect, it, vi } from "vitest";
+
+import { WITHDRAW_RAI_ITEM_B } from "mocks";
+import { EnableWithdrawRaiForm, DisableWithdrawRaiForm } from ".";
+import { renderFormAsync } from "@/utils/test-helpers/renderForm";
+
+vi.mock("react-router", async () => ({
+  ...(await vi.importActual<Record<string, unknown>>("react-router")),
+  useParams: vi.fn().mockReturnValue({ authority: "1915(b)", id: WITHDRAW_RAI_ITEM_B }),
+}));
+vi.mock("shared-utils", async (importOriginal) => {
+  const actual = await importOriginal();
+  return {
+    ...(typeof actual === "object" && actual !== null ? actual : {}),
+    isCmsUser: vi.fn().mockReturnValue(true),
+  };
+});
+
+describe("Toggle Withdraw Rai components", () => {
+  it("renders disable withdraw rai correctly", async () => {
+    const container = renderFormAsync(<EnableWithdrawRaiForm />);
+
+    expect(await container).toMatchSnapshot();
+  });
+  it("renders disable withdraw rai correctly", async () => {
+    const container = renderFormAsync(<DisableWithdrawRaiForm />);
+
+    expect(await container).toMatchSnapshot();
+  });
+});
diff --git a/react-app/src/features/forms/post-submission/withdraw-package/__snapshots__/indext.test.tsx.snap b/react-app/src/features/forms/post-submission/withdraw-package/__snapshots__/indext.test.tsx.snap
new file mode 100644
index 0000000000..2fc5fae390
--- /dev/null
+++ b/react-app/src/features/forms/post-submission/withdraw-package/__snapshots__/indext.test.tsx.snap
@@ -0,0 +1,876 @@
+// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
+
+exports[`WithdrawPackageAction components > renders WithdrawPackageActionWaiver correctly 1`] = `
+{
+  "asFragment": [Function],
+  "baseElement": <body>
+    <div>
+      <div
+        class="max-w-screen-xl mx-auto px-4 lg:px-8"
+      >
+        <nav
+          aria-label="breadcrumbs for spa or waiver choices"
+          class="my-4"
+          role="navigation"
+        >
+          <ul
+            class="flex flex-wrap gap-1"
+          >
+            <li
+              class="flex items-center text-sm"
+            >
+              <a
+                class="underline text-sky-700 hover:text-sky-800"
+                data-discover="true"
+                href="/dashboard?tab=waivers"
+              >
+                Dashboard
+              </a>
+            </li>
+            <li
+              class="flex items-center text-sm"
+            >
+              <span>
+                <svg
+                  class="w-5 h-5"
+                  fill="none"
+                  height="24"
+                  stroke="currentColor"
+                  stroke-linecap="round"
+                  stroke-linejoin="round"
+                  stroke-width="2"
+                  viewBox="0 0 24 24"
+                  width="24"
+                  xmlns="http://www.w3.org/2000/svg"
+                >
+                  <path
+                    d="m9 18 6-6-6-6"
+                  />
+                </svg>
+              </span>
+              <a
+                class="underline text-sky-700 hover:text-sky-800"
+                data-discover="true"
+                href="/details/1915(c)/VA-2234.R11.01"
+              >
+                VA-2234.R11.01
+              </a>
+            </li>
+            <li
+              class="flex items-center text-sm"
+            >
+              <span>
+                <svg
+                  class="w-5 h-5"
+                  fill="none"
+                  height="24"
+                  stroke="currentColor"
+                  stroke-linecap="round"
+                  stroke-linejoin="round"
+                  stroke-width="2"
+                  viewBox="0 0 24 24"
+                  width="24"
+                  xmlns="http://www.w3.org/2000/svg"
+                >
+                  <path
+                    d="m9 18 6-6-6-6"
+                  />
+                </svg>
+              </span>
+              <span
+                aria-disabled="true"
+                class="whitespace-nowrap"
+              >
+                Withdraw Package
+              </span>
+            </li>
+          </ul>
+        </nav>
+        <form
+          class="my-6 space-y-8 mx-auto justify-center flex flex-col"
+        >
+          <section
+            class="p-4 border rounded-sm border-cardBorder"
+            data-testid="detail-section"
+          >
+            <h1
+              class="text-3xl font-semibold mb-2"
+              data-testid="detail-section-title"
+            >
+              Withdraw 1915(c) Appendix K
+            </h1>
+            <hr
+              class="my-6 bg-slate-200"
+            />
+            <div
+              class="gap-8 flex flex-col"
+              data-testid="detail-section-child"
+            >
+              <div>
+                <span
+                  class="text-red-600"
+                >
+                  *
+                </span>
+                 
+                <em
+                  class="text-neutral-500"
+                >
+                  Indicates a required field.
+                </em>
+                <div
+                  class="mt-4"
+                >
+                  Complete this form to withdraw this 1915(c) Appendix K package. Once complete, you will not be able to resubmit this package. CMS will be notified and will use this content to review your request. If CMS needs any additional information, they will follow up by email.
+                  <p
+                    class="font-bold"
+                  >
+                    If you leave this page, you will lose your progress on this form.
+                  </p>
+                </div>
+              </div>
+              <section
+                class="flex flex-col mb-8 space-y-8"
+              >
+                <div>
+                  <p
+                    class="font-bold"
+                  >
+                    Waiver Number
+                  </p>
+                  <p
+                    class="text-xl"
+                  >
+                    VA-2234.R11.01
+                  </p>
+                </div>
+                <div>
+                  <p
+                    class="font-bold"
+                  >
+                    Authority
+                  </p>
+                  <p
+                    class="text-xl"
+                  >
+                    1915(c) Waiver
+                  </p>
+                </div>
+              </section>
+            </div>
+          </section>
+          <section
+            class="p-4 border rounded-sm border-cardBorder"
+            data-testid="attachment-section"
+          >
+            <h1
+              class="text-3xl font-semibold mb-2"
+              data-testid="attachment-section-title"
+            >
+              Attachments
+               
+            </h1>
+            <hr
+              class="my-6 bg-slate-200"
+            />
+            <div
+              class="gap-8 flex flex-col"
+              data-testid="attachment-section-child"
+            >
+              <div>
+                <p
+                  class="font-medium"
+                >
+                  Upload your supporting documentation for withdrawal or explain your need for withdrawal in the Additional Information section.
+                </p>
+                <br />
+                <p
+                  data-testid="attachments-instructions"
+                >
+                  Maximum file size of 80 MB per attachment.
+                   
+                  <span
+                    class="font-bold"
+                  >
+                    You can add multiple files per attachment type.
+                  </span>
+                   Read the description for each of the attachment types on the
+                   
+                  <a
+                    class="text-blue-900 underline"
+                    data-discover="true"
+                    href="/faq/withdraw-package-waiver"
+                    rel="noopener noreferrer"
+                    target="faq-tab"
+                  >
+                    FAQ Page
+                  </a>
+                  .
+                </p>
+                <br />
+                <p
+                  data-testid="accepted-files"
+                >
+                  We accept the following file formats:
+                   
+                  <span
+                    class="font-bold"
+                  >
+                    .doc, .docx, .pdf, .jpg, .xlsx, and more. 
+                  </span>
+                   
+                  <a
+                    class="text-blue-900 underline"
+                    data-discover="true"
+                    href="/faq/acceptable-file-formats"
+                    rel="noopener noreferrer"
+                    target="faq-tab"
+                  >
+                    See the full list
+                  </a>
+                  .
+                </p>
+              </div>
+              <section
+                class="space-y-8"
+                data-testid="attachments-section"
+              >
+                <div>
+                  <label
+                    class="text-base leading-normal peer-disabled:cursor-not-allowed peer-disabled:opacity-70 font-bold"
+                    data-testid="supportingDocumentation-label"
+                    for="attachments.supportingDocumentation.files"
+                  >
+                    Supporting Documentation
+                     
+                  </label>
+                  <div
+                    class="w-full flex items-center justify-center border border-dashed border-[#71767a] py-6 rounded-sm"
+                    role="presentation"
+                    tabindex="0"
+                  >
+                    <p>
+                      Drag file here or
+                       
+                      <span
+                        class="text-sky-700 underline hover:cursor-pointer"
+                      >
+                        choose from folder
+                      </span>
+                    </p>
+                    <label
+                      class="sr-only"
+                      for="upload-mocked-uuid-1234"
+                    >
+                      Drag file here or choose from folder
+                    </label>
+                    <input
+                      accept="image/bmp,.bmp,text/csv,.csv,application/msword,.doc,application/vnd.openxmlformats-officedocument.wordprocessingml.document,.docx,image/gif,.gif,image/jpeg,.jpeg,application/vnd.oasis.opendocument.presentation,.odp,application/vnd.oasis.opendocument.spreadsheet,.ods,application/vnd.oasis.opendocument.text,.odt,image/png,.png,application/pdf,.pdf,application/vnd.ms-powerpoint,.ppt,application/vnd.openxmlformats-officedocument.presentationml.presentation,.pptx,application/rtf,.rtf,image/tiff,.tif,text/plain,.txt,application/vnd.ms-excel,.xls,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,.xlsx"
+                      data-testid="supportingDocumentation-upload"
+                      id="upload-mocked-uuid-1234"
+                      multiple=""
+                      style="display: none;"
+                      tabindex="-1"
+                      type="file"
+                    />
+                  </div>
+                </div>
+              </section>
+            </div>
+          </section>
+          <section
+            class="p-4 border rounded-sm border-cardBorder"
+            data-testid="additional-info"
+          >
+            <h1
+              class="text-3xl font-semibold mb-2"
+              data-testid="additional-info-title"
+            >
+              Additional Information
+               
+            </h1>
+            <hr
+              class="my-6 bg-slate-200"
+            />
+            <div
+              class="gap-8 flex flex-col"
+              data-testid="additional-info-child"
+            >
+              <div>
+                <label
+                  class="text-base leading-normal peer-disabled:cursor-not-allowed peer-disabled:opacity-70 font-normal"
+                  data-testid="addl-info-label"
+                  for="additional-info"
+                >
+                  Explain your need for withdrawal, or upload supporting documentation.
+                </label>
+                <textarea
+                  aria-describedby="character-count"
+                  aria-live="off"
+                  aria-multiline="true"
+                  class="flex min-h-[76px] w-full rounded-sm border border-black bg-transparent px-3 py-2 text-sm shadow-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 h-[200px] resize-none"
+                  id="additional-info"
+                  maxlength="4000"
+                  name="additionalInformation"
+                />
+                <p
+                  id=":r1:-form-item-description"
+                >
+                  <span
+                    aria-label="character-count"
+                    aria-live="polite"
+                    class="text-neutral-500"
+                    id="character-count"
+                    tabindex="0"
+                  >
+                    4000 characters remaining
+                  </span>
+                </p>
+              </div>
+            </div>
+          </section>
+          <div
+            class="relative w-full border p-4 [&>svg~*]:pl-7 [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 [&>svg]:text-foreground border-l-[6px] border-y-0 border-r-0 border-cyan-500 bg-cyan-300/10 rounded-none my-2 flex-row text-sm"
+            role="alert"
+          >
+            <svg
+              class="lucide lucide-info"
+              fill="none"
+              height="24"
+              stroke="currentColor"
+              stroke-linecap="round"
+              stroke-linejoin="round"
+              stroke-width="2"
+              viewBox="0 0 24 24"
+              width="24"
+              xmlns="http://www.w3.org/2000/svg"
+            >
+              <circle
+                cx="12"
+                cy="12"
+                r="10"
+              />
+              <path
+                d="M12 16v-4"
+              />
+              <path
+                d="M12 8h.01"
+              />
+            </svg>
+            <p
+              class="ml-2"
+            >
+              Once complete, you will not be able to resubmit this package. CMS will be notified and will use this content to review your request. If CMS needs any additional information, they will follow up by email.
+            </p>
+            <p
+              class="font-bold ml-2"
+            >
+              If you leave this page, you will lose your progress on this form.
+            </p>
+          </div>
+          <section
+            class="flex justify-end gap-2 p-4 ml-auto"
+          >
+            <button
+              class="inline-flex items-center justify-center rounded-md text-[16px] font-bold ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 bg-primary text-slate-50 hover:bg-primary-dark h-10 py-2 px-12"
+              data-testid="submit-action-form"
+              disabled=""
+              type="button"
+            >
+              Submit
+            </button>
+            <button
+              class="inline-flex items-center justify-center rounded-md text-[16px] ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 border border-primary text-primary font-bold hover:bg-primary/10 h-10 py-2 px-12"
+              data-testid="cancel-action-form"
+              type="reset"
+            >
+              Cancel
+            </button>
+          </section>
+        </form>
+        <div
+          class="relative w-full border p-4 [&>svg~*]:pl-7 [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 [&>svg]:text-foreground border-l-[6px] border-y-0 border-r-0 border-cyan-500 bg-cyan-300/10 rounded-none mb-8 items-center flex py-8 px-14 flex-row text-sm justify-center gap-24"
+          role="alert"
+        >
+          <p
+            class="text-lg"
+          >
+            Do you have questions or need support?
+          </p>
+          <a
+            data-discover="true"
+            href="/faq"
+            target="_blank"
+          >
+            <button
+              class="inline-flex items-center justify-center text-[16px] font-bold ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 bg-primary text-slate-50 hover:bg-primary-dark h-11 rounded-md px-8 mx-4"
+            >
+              View FAQ
+            </button>
+          </a>
+        </div>
+      </div>
+      ,
+    </div>
+  </body>,
+  "container": <div>
+    <div
+      class="max-w-screen-xl mx-auto px-4 lg:px-8"
+    >
+      <nav
+        aria-label="breadcrumbs for spa or waiver choices"
+        class="my-4"
+        role="navigation"
+      >
+        <ul
+          class="flex flex-wrap gap-1"
+        >
+          <li
+            class="flex items-center text-sm"
+          >
+            <a
+              class="underline text-sky-700 hover:text-sky-800"
+              data-discover="true"
+              href="/dashboard?tab=waivers"
+            >
+              Dashboard
+            </a>
+          </li>
+          <li
+            class="flex items-center text-sm"
+          >
+            <span>
+              <svg
+                class="w-5 h-5"
+                fill="none"
+                height="24"
+                stroke="currentColor"
+                stroke-linecap="round"
+                stroke-linejoin="round"
+                stroke-width="2"
+                viewBox="0 0 24 24"
+                width="24"
+                xmlns="http://www.w3.org/2000/svg"
+              >
+                <path
+                  d="m9 18 6-6-6-6"
+                />
+              </svg>
+            </span>
+            <a
+              class="underline text-sky-700 hover:text-sky-800"
+              data-discover="true"
+              href="/details/1915(c)/VA-2234.R11.01"
+            >
+              VA-2234.R11.01
+            </a>
+          </li>
+          <li
+            class="flex items-center text-sm"
+          >
+            <span>
+              <svg
+                class="w-5 h-5"
+                fill="none"
+                height="24"
+                stroke="currentColor"
+                stroke-linecap="round"
+                stroke-linejoin="round"
+                stroke-width="2"
+                viewBox="0 0 24 24"
+                width="24"
+                xmlns="http://www.w3.org/2000/svg"
+              >
+                <path
+                  d="m9 18 6-6-6-6"
+                />
+              </svg>
+            </span>
+            <span
+              aria-disabled="true"
+              class="whitespace-nowrap"
+            >
+              Withdraw Package
+            </span>
+          </li>
+        </ul>
+      </nav>
+      <form
+        class="my-6 space-y-8 mx-auto justify-center flex flex-col"
+      >
+        <section
+          class="p-4 border rounded-sm border-cardBorder"
+          data-testid="detail-section"
+        >
+          <h1
+            class="text-3xl font-semibold mb-2"
+            data-testid="detail-section-title"
+          >
+            Withdraw 1915(c) Appendix K
+          </h1>
+          <hr
+            class="my-6 bg-slate-200"
+          />
+          <div
+            class="gap-8 flex flex-col"
+            data-testid="detail-section-child"
+          >
+            <div>
+              <span
+                class="text-red-600"
+              >
+                *
+              </span>
+               
+              <em
+                class="text-neutral-500"
+              >
+                Indicates a required field.
+              </em>
+              <div
+                class="mt-4"
+              >
+                Complete this form to withdraw this 1915(c) Appendix K package. Once complete, you will not be able to resubmit this package. CMS will be notified and will use this content to review your request. If CMS needs any additional information, they will follow up by email.
+                <p
+                  class="font-bold"
+                >
+                  If you leave this page, you will lose your progress on this form.
+                </p>
+              </div>
+            </div>
+            <section
+              class="flex flex-col mb-8 space-y-8"
+            >
+              <div>
+                <p
+                  class="font-bold"
+                >
+                  Waiver Number
+                </p>
+                <p
+                  class="text-xl"
+                >
+                  VA-2234.R11.01
+                </p>
+              </div>
+              <div>
+                <p
+                  class="font-bold"
+                >
+                  Authority
+                </p>
+                <p
+                  class="text-xl"
+                >
+                  1915(c) Waiver
+                </p>
+              </div>
+            </section>
+          </div>
+        </section>
+        <section
+          class="p-4 border rounded-sm border-cardBorder"
+          data-testid="attachment-section"
+        >
+          <h1
+            class="text-3xl font-semibold mb-2"
+            data-testid="attachment-section-title"
+          >
+            Attachments
+             
+          </h1>
+          <hr
+            class="my-6 bg-slate-200"
+          />
+          <div
+            class="gap-8 flex flex-col"
+            data-testid="attachment-section-child"
+          >
+            <div>
+              <p
+                class="font-medium"
+              >
+                Upload your supporting documentation for withdrawal or explain your need for withdrawal in the Additional Information section.
+              </p>
+              <br />
+              <p
+                data-testid="attachments-instructions"
+              >
+                Maximum file size of 80 MB per attachment.
+                 
+                <span
+                  class="font-bold"
+                >
+                  You can add multiple files per attachment type.
+                </span>
+                 Read the description for each of the attachment types on the
+                 
+                <a
+                  class="text-blue-900 underline"
+                  data-discover="true"
+                  href="/faq/withdraw-package-waiver"
+                  rel="noopener noreferrer"
+                  target="faq-tab"
+                >
+                  FAQ Page
+                </a>
+                .
+              </p>
+              <br />
+              <p
+                data-testid="accepted-files"
+              >
+                We accept the following file formats:
+                 
+                <span
+                  class="font-bold"
+                >
+                  .doc, .docx, .pdf, .jpg, .xlsx, and more. 
+                </span>
+                 
+                <a
+                  class="text-blue-900 underline"
+                  data-discover="true"
+                  href="/faq/acceptable-file-formats"
+                  rel="noopener noreferrer"
+                  target="faq-tab"
+                >
+                  See the full list
+                </a>
+                .
+              </p>
+            </div>
+            <section
+              class="space-y-8"
+              data-testid="attachments-section"
+            >
+              <div>
+                <label
+                  class="text-base leading-normal peer-disabled:cursor-not-allowed peer-disabled:opacity-70 font-bold"
+                  data-testid="supportingDocumentation-label"
+                  for="attachments.supportingDocumentation.files"
+                >
+                  Supporting Documentation
+                   
+                </label>
+                <div
+                  class="w-full flex items-center justify-center border border-dashed border-[#71767a] py-6 rounded-sm"
+                  role="presentation"
+                  tabindex="0"
+                >
+                  <p>
+                    Drag file here or
+                     
+                    <span
+                      class="text-sky-700 underline hover:cursor-pointer"
+                    >
+                      choose from folder
+                    </span>
+                  </p>
+                  <label
+                    class="sr-only"
+                    for="upload-mocked-uuid-1234"
+                  >
+                    Drag file here or choose from folder
+                  </label>
+                  <input
+                    accept="image/bmp,.bmp,text/csv,.csv,application/msword,.doc,application/vnd.openxmlformats-officedocument.wordprocessingml.document,.docx,image/gif,.gif,image/jpeg,.jpeg,application/vnd.oasis.opendocument.presentation,.odp,application/vnd.oasis.opendocument.spreadsheet,.ods,application/vnd.oasis.opendocument.text,.odt,image/png,.png,application/pdf,.pdf,application/vnd.ms-powerpoint,.ppt,application/vnd.openxmlformats-officedocument.presentationml.presentation,.pptx,application/rtf,.rtf,image/tiff,.tif,text/plain,.txt,application/vnd.ms-excel,.xls,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,.xlsx"
+                    data-testid="supportingDocumentation-upload"
+                    id="upload-mocked-uuid-1234"
+                    multiple=""
+                    style="display: none;"
+                    tabindex="-1"
+                    type="file"
+                  />
+                </div>
+              </div>
+            </section>
+          </div>
+        </section>
+        <section
+          class="p-4 border rounded-sm border-cardBorder"
+          data-testid="additional-info"
+        >
+          <h1
+            class="text-3xl font-semibold mb-2"
+            data-testid="additional-info-title"
+          >
+            Additional Information
+             
+          </h1>
+          <hr
+            class="my-6 bg-slate-200"
+          />
+          <div
+            class="gap-8 flex flex-col"
+            data-testid="additional-info-child"
+          >
+            <div>
+              <label
+                class="text-base leading-normal peer-disabled:cursor-not-allowed peer-disabled:opacity-70 font-normal"
+                data-testid="addl-info-label"
+                for="additional-info"
+              >
+                Explain your need for withdrawal, or upload supporting documentation.
+              </label>
+              <textarea
+                aria-describedby="character-count"
+                aria-live="off"
+                aria-multiline="true"
+                class="flex min-h-[76px] w-full rounded-sm border border-black bg-transparent px-3 py-2 text-sm shadow-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 h-[200px] resize-none"
+                id="additional-info"
+                maxlength="4000"
+                name="additionalInformation"
+              />
+              <p
+                id=":r1:-form-item-description"
+              >
+                <span
+                  aria-label="character-count"
+                  aria-live="polite"
+                  class="text-neutral-500"
+                  id="character-count"
+                  tabindex="0"
+                >
+                  4000 characters remaining
+                </span>
+              </p>
+            </div>
+          </div>
+        </section>
+        <div
+          class="relative w-full border p-4 [&>svg~*]:pl-7 [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 [&>svg]:text-foreground border-l-[6px] border-y-0 border-r-0 border-cyan-500 bg-cyan-300/10 rounded-none my-2 flex-row text-sm"
+          role="alert"
+        >
+          <svg
+            class="lucide lucide-info"
+            fill="none"
+            height="24"
+            stroke="currentColor"
+            stroke-linecap="round"
+            stroke-linejoin="round"
+            stroke-width="2"
+            viewBox="0 0 24 24"
+            width="24"
+            xmlns="http://www.w3.org/2000/svg"
+          >
+            <circle
+              cx="12"
+              cy="12"
+              r="10"
+            />
+            <path
+              d="M12 16v-4"
+            />
+            <path
+              d="M12 8h.01"
+            />
+          </svg>
+          <p
+            class="ml-2"
+          >
+            Once complete, you will not be able to resubmit this package. CMS will be notified and will use this content to review your request. If CMS needs any additional information, they will follow up by email.
+          </p>
+          <p
+            class="font-bold ml-2"
+          >
+            If you leave this page, you will lose your progress on this form.
+          </p>
+        </div>
+        <section
+          class="flex justify-end gap-2 p-4 ml-auto"
+        >
+          <button
+            class="inline-flex items-center justify-center rounded-md text-[16px] font-bold ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 bg-primary text-slate-50 hover:bg-primary-dark h-10 py-2 px-12"
+            data-testid="submit-action-form"
+            disabled=""
+            type="button"
+          >
+            Submit
+          </button>
+          <button
+            class="inline-flex items-center justify-center rounded-md text-[16px] ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 border border-primary text-primary font-bold hover:bg-primary/10 h-10 py-2 px-12"
+            data-testid="cancel-action-form"
+            type="reset"
+          >
+            Cancel
+          </button>
+        </section>
+      </form>
+      <div
+        class="relative w-full border p-4 [&>svg~*]:pl-7 [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 [&>svg]:text-foreground border-l-[6px] border-y-0 border-r-0 border-cyan-500 bg-cyan-300/10 rounded-none mb-8 items-center flex py-8 px-14 flex-row text-sm justify-center gap-24"
+        role="alert"
+      >
+        <p
+          class="text-lg"
+        >
+          Do you have questions or need support?
+        </p>
+        <a
+          data-discover="true"
+          href="/faq"
+          target="_blank"
+        >
+          <button
+            class="inline-flex items-center justify-center text-[16px] font-bold ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 bg-primary text-slate-50 hover:bg-primary-dark h-11 rounded-md px-8 mx-4"
+          >
+            View FAQ
+          </button>
+        </a>
+      </div>
+    </div>
+    ,
+  </div>,
+  "debug": [Function],
+  "findAllByAltText": [Function],
+  "findAllByDisplayValue": [Function],
+  "findAllByLabelText": [Function],
+  "findAllByPlaceholderText": [Function],
+  "findAllByRole": [Function],
+  "findAllByTestId": [Function],
+  "findAllByText": [Function],
+  "findAllByTitle": [Function],
+  "findByAltText": [Function],
+  "findByDisplayValue": [Function],
+  "findByLabelText": [Function],
+  "findByPlaceholderText": [Function],
+  "findByRole": [Function],
+  "findByTestId": [Function],
+  "findByText": [Function],
+  "findByTitle": [Function],
+  "getAllByAltText": [Function],
+  "getAllByDisplayValue": [Function],
+  "getAllByLabelText": [Function],
+  "getAllByPlaceholderText": [Function],
+  "getAllByRole": [Function],
+  "getAllByTestId": [Function],
+  "getAllByText": [Function],
+  "getAllByTitle": [Function],
+  "getByAltText": [Function],
+  "getByDisplayValue": [Function],
+  "getByLabelText": [Function],
+  "getByPlaceholderText": [Function],
+  "getByRole": [Function],
+  "getByTestId": [Function],
+  "getByText": [Function],
+  "getByTitle": [Function],
+  "queryAllByAltText": [Function],
+  "queryAllByDisplayValue": [Function],
+  "queryAllByLabelText": [Function],
+  "queryAllByPlaceholderText": [Function],
+  "queryAllByRole": [Function],
+  "queryAllByTestId": [Function],
+  "queryAllByText": [Function],
+  "queryAllByTitle": [Function],
+  "queryByAltText": [Function],
+  "queryByDisplayValue": [Function],
+  "queryByLabelText": [Function],
+  "queryByPlaceholderText": [Function],
+  "queryByRole": [Function],
+  "queryByTestId": [Function],
+  "queryByText": [Function],
+  "queryByTitle": [Function],
+  "rerender": [Function],
+  "unmount": [Function],
+}
+`;
diff --git a/react-app/src/features/forms/post-submission/withdraw-package/indext.test.tsx b/react-app/src/features/forms/post-submission/withdraw-package/indext.test.tsx
new file mode 100644
index 0000000000..42190f8f98
--- /dev/null
+++ b/react-app/src/features/forms/post-submission/withdraw-package/indext.test.tsx
@@ -0,0 +1,16 @@
+import { describe, expect, it, vi } from "vitest";
+import { CAPITATED_AMEND_ITEM_ID } from "mocks";
+import { WithdrawPackageActionWaiver } from ".";
+import { renderFormAsync } from "@/utils/test-helpers/renderForm";
+
+vi.mock("react-router", async () => ({
+  ...(await vi.importActual<Record<string, unknown>>("react-router")),
+  useParams: vi.fn().mockReturnValue({ authority: "1915(c)", id: CAPITATED_AMEND_ITEM_ID }),
+}));
+describe("WithdrawPackageAction components", () => {
+  it("renders WithdrawPackageActionWaiver correctly", async () => {
+    const container = renderFormAsync(<WithdrawPackageActionWaiver />);
+
+    expect(await container).toMatchSnapshot();
+  });
+});
diff --git a/react-app/vitest.setup.ts b/react-app/vitest.setup.ts
index fb52fdd2ce..accc404e50 100644
--- a/react-app/vitest.setup.ts
+++ b/react-app/vitest.setup.ts
@@ -9,6 +9,7 @@ import {
   setDefaultStateSubmitter,
   setMockUsername,
 } from "mocks";
+
 import { mockedApiServer as mockedServer } from "mocks/server";
 import { afterAll, afterEach, beforeAll, expect, vi } from "vitest";
 
@@ -63,7 +64,9 @@ beforeAll(() => {
   mockedServer.listen({
     onUnhandledRequest: "warn",
   });
-
+  vi.mock("uuid", () => ({
+    v4: vi.fn(() => "mocked-uuid-1234"),
+  }));
   if (process.env.MOCK_API_REFINES) {
     vi.mock("@/components/Inputs/upload.utilities", () => ({
       getPresignedUrl: vi.fn(async () => "hello world"),

From 8fccfdab7b3af6cede658828e0e29166086b82b8 Mon Sep 17 00:00:00 2001
From: Tiffany Forkner <thetif@gmail.com>
Date: Tue, 21 Jan 2025 12:37:33 -0500
Subject: [PATCH 2/4] feat(tests): tests for opensearch utils (#1041)

* added tests for opensearch utils
* additional useSearch tests
---
 mocks/data/items.ts                           |  14 +
 mocks/handlers/api/search.ts                  |  23 +-
 mocks/handlers/search.utils.ts                |  32 +
 react-app/src/api/useSearch.test.ts           |  34 +-
 .../src/components/Opensearch/utils.test.ts   | 688 ++++++++++++++++++
 react-app/src/components/Opensearch/utils.ts  |  51 +-
 6 files changed, 801 insertions(+), 41 deletions(-)
 create mode 100644 react-app/src/components/Opensearch/utils.test.ts

diff --git a/mocks/data/items.ts b/mocks/data/items.ts
index 78756ace8b..cd377c82f9 100644
--- a/mocks/data/items.ts
+++ b/mocks/data/items.ts
@@ -515,4 +515,18 @@ export const TEST_TEMP_EXT_ITEM = items[
   EXISTING_ITEM_TEMPORARY_EXTENSION_ID
 ] as opensearch.main.ItemResult;
 
+export const itemList = Object.values(items);
+
+export const getFilteredItemList = (filters: string[]) => {
+  return itemList.filter((item) => filters.includes(item?._source?.authority || ""));
+};
+
+export const docList = Object.values(items).map(
+  (item) => (item?._source || {}) as opensearch.main.Document,
+);
+
+export const getFilteredDocList = (filters: string[]) => {
+  return docList.filter((item) => filters.includes(item?.authority || ""));
+};
+
 export default items;
diff --git a/mocks/handlers/api/search.ts b/mocks/handlers/api/search.ts
index d1a51c0767..cbc80f5f72 100644
--- a/mocks/handlers/api/search.ts
+++ b/mocks/handlers/api/search.ts
@@ -1,12 +1,23 @@
-import { http, HttpResponse } from "msw";
-import { cpocsList } from "../../data/cpocs";
+import { http, HttpResponse, PathParams } from "msw";
+import { getFilteredItemList } from "../../data/items";
+import { getFilterValueAsStringArray } from "../search.utils";
+import { SearchQueryBody } from "../../index.d";
 
-const defaultApiSearchHandler = http.post(
+const defaultApiSearchHandler = http.post<PathParams, SearchQueryBody>(
   "https://test-domain.execute-api.us-east-1.amazonaws.com/mocked-tests/search/:index",
-  ({ params }) => {
+  async ({ params, request }) => {
     const { index } = params;
+    const { query } = await request.json();
+
+    const must = query?.bool?.must;
+
+    if (index === "main") {
+      const authorityValues =
+        getFilterValueAsStringArray(must, "terms", "authority.keyword") ||
+        getFilterValueAsStringArray(must, "terms", "authority") ||
+        [];
+      const itemList = getFilteredItemList(authorityValues);
 
-    if (index === "cpocs") {
       return HttpResponse.json({
         took: 3,
         timed_out: false,
@@ -22,7 +33,7 @@ const defaultApiSearchHandler = http.post(
             relation: "eq",
           },
           max_score: 1,
-          hits: cpocsList,
+          hits: itemList,
         },
       });
     }
diff --git a/mocks/handlers/search.utils.ts b/mocks/handlers/search.utils.ts
index 608a7b2e13..9290c7ea03 100644
--- a/mocks/handlers/search.utils.ts
+++ b/mocks/handlers/search.utils.ts
@@ -109,6 +109,38 @@ const parseValueAsNumberArray = (value: string | string[] | undefined): number[]
   );
 };
 
+export const getFilterValueAsString = (
+  query: QueryContainer | QueryContainer[] | undefined,
+  queryKey: keyof QueryContainer,
+  filterName: string,
+): string | undefined => {
+  const value = getFilterValue(query, queryKey, filterName);
+
+  return parseValueAsStringArray(value).join(",");
+};
+
+export const getFilterValueAsStringArray = (
+  query: QueryContainer | QueryContainer[] | undefined,
+  queryKey: keyof QueryContainer,
+  filterName: string,
+): string[] => {
+  const value = getFilterValue(query, queryKey, filterName);
+
+  return parseValueAsStringArray(value);
+};
+
+const parseValueAsStringArray = (value: string | string[] | undefined): string[] => {
+  if (value == undefined) {
+    return [];
+  }
+
+  if (typeof value === "string") {
+    return value.split(",").map((val) => val.trim());
+  }
+
+  return value.filter((val) => val && typeof val === "string").map((val) => val.trim()) || [];
+};
+
 export const getTermValues = (
   query: QueryContainer | QueryContainer[] | undefined,
   filterName: string,
diff --git a/react-app/src/api/useSearch.test.ts b/react-app/src/api/useSearch.test.ts
index c412d53ea7..fa4a2d4216 100644
--- a/react-app/src/api/useSearch.test.ts
+++ b/react-app/src/api/useSearch.test.ts
@@ -1,21 +1,21 @@
 import { describe, expect, it } from "vitest";
-import { getOsData } from "./useSearch";
-import { cpocsList } from "mocks/data/cpocs";
+import { getMainExportData } from "./useSearch";
+import { DEFAULT_FILTERS } from "@/components/Opensearch/main/useOpensearch";
+import { getFilteredDocList } from "mocks/data/items";
 
-describe("getOsData tests", () => {
-  it("should return cpocs", async () => {
-    const results = await getOsData({
-      index: "cpocs",
-      sort: {
-        field: "lastName",
-        order: "asc",
-      },
-      pagination: {
-        number: 0,
-        size: 20,
-      },
-      filters: [],
-    });
-    expect(results.hits.hits).toEqual(cpocsList);
+describe("getMainExportData tests", () => {
+  it("should return spa items", async () => {
+    const results = await getMainExportData(DEFAULT_FILTERS.spas.filters);
+    expect(results).toEqual(getFilteredDocList(["Medicaid SPA", "CHIP SPA"]));
+  });
+
+  it("should return waiver items", async () => {
+    const results = await getMainExportData(DEFAULT_FILTERS.waivers.filters);
+    expect(results).toEqual(getFilteredDocList(["1915(b)", "1915(c)"]));
+  });
+
+  it("should return an empty array if there are no filters", async () => {
+    const results = await getMainExportData();
+    expect(results).toEqual([]);
   });
 });
diff --git a/react-app/src/components/Opensearch/utils.test.ts b/react-app/src/components/Opensearch/utils.test.ts
new file mode 100644
index 0000000000..f6b701fa68
--- /dev/null
+++ b/react-app/src/components/Opensearch/utils.test.ts
@@ -0,0 +1,688 @@
+import { describe, expect, it } from "vitest";
+import {
+  filterQueryBuilder,
+  paginationQueryBuilder,
+  sortQueryBuilder,
+  aggQueryBuilder,
+  createSearchFilterable,
+  checkMultiFilter,
+} from "./utils";
+
+describe("Opensearch utils tests", () => {
+  describe("filterQueryBuilder tests", () => {
+    it("should handle undefined filters", () => {
+      const results = filterQueryBuilder(undefined);
+      expect(results).toEqual({});
+    });
+    it("should handle null filters", () => {
+      const results = filterQueryBuilder(null);
+      expect(results).toEqual({});
+    });
+    it("should handle empty filters", () => {
+      const results = filterQueryBuilder([]);
+      expect(results).toEqual({});
+    });
+    it("should handle exists filter without a value", () => {
+      const results = filterQueryBuilder([
+        // @ts-expect-error
+        {
+          type: "exists",
+          prefix: "must",
+          field: "origin",
+        },
+      ]);
+      expect(results).toEqual({
+        query: {
+          bool: {
+            must: [{ exists: { field: "origin" } }],
+            must_not: [],
+            should: [],
+            filter: [],
+          },
+        },
+      });
+    });
+    it("should handle an invalid prefix", () => {
+      const result = filterQueryBuilder([
+        {
+          // @ts-expect-error
+          type: "mismatch",
+          prefix: "must",
+          field: "authority.keyword",
+          value: ["Medicaid SPA", "CHIP SPA"],
+        },
+      ]);
+      expect(result).toEqual({
+        query: {
+          bool: {
+            must: [],
+            must_not: [],
+            should: [],
+            filter: [],
+          },
+        },
+      });
+    });
+    it.each([["terms"], ["term"], ["range"], ["global_search"]])(
+      "should handle %s filter without a value",
+      (type) => {
+        const results = filterQueryBuilder([
+          {
+            // @ts-expect-error
+            type,
+            prefix: "must",
+            field: "authority.keyword",
+          },
+        ]);
+        expect(results).toEqual({
+          query: {
+            bool: {
+              must: [],
+              must_not: [],
+              should: [],
+              filter: [],
+            },
+          },
+        });
+      },
+    );
+    it("should handle match filter with a false value", () => {
+      const results = filterQueryBuilder([
+        {
+          type: "match",
+          prefix: "must",
+          field: "authority.keyword",
+          value: false,
+        },
+      ]);
+      expect(results).toEqual({
+        query: {
+          bool: {
+            must: [{ match: { "authority.keyword": false } }],
+            must_not: [],
+            should: [],
+            filter: [],
+          },
+        },
+      });
+    });
+    it.each([
+      [
+        "terms",
+        "authority.keyword",
+        ["Medicaid SPA", "CHIP SPA"],
+        [{ terms: { "authority.keyword": ["Medicaid SPA", "CHIP SPA"] } }],
+      ],
+      ["term", "state", "MD", [{ term: { state: "MD" } }]],
+      ["exists", "origin", "OneMAC", [{ exists: { field: "origin" } }]],
+      [
+        "range",
+        "timestamp",
+        ["1677715190000", "1677715210000"],
+        [{ range: { timestamp: ["1677715190000", "1677715210000"] } }],
+      ],
+    ])("should handle must %s filters", (type, field, value, expected) => {
+      const results = filterQueryBuilder([
+        {
+          // @ts-expect-error
+          type,
+          prefix: "must",
+          field,
+          value,
+        },
+      ]);
+      expect(results).toEqual({
+        query: {
+          bool: {
+            must: expected,
+            must_not: [],
+            should: [],
+            filter: [],
+          },
+        },
+      });
+    });
+    it("should handle a global_search filter", () => {
+      const results = filterQueryBuilder([
+        {
+          type: "global_search",
+          prefix: "must",
+          field: "authority",
+          value: "   CHIP SPA   ",
+        },
+      ]);
+      expect(results).toEqual({
+        query: {
+          bool: {
+            must: [
+              {
+                dis_max: {
+                  tie_breaker: 0.7,
+                  boost: 1.2,
+                  queries: [
+                    {
+                      wildcard: {
+                        "id.keyword": {
+                          value: "*CHIP SPA*",
+                          case_insensitive: true,
+                        },
+                      },
+                    },
+                    {
+                      wildcard: {
+                        "submitterName.keyword": {
+                          value: "*CHIP SPA*",
+                          case_insensitive: true,
+                        },
+                      },
+                    },
+                    {
+                      wildcard: {
+                        "leadAnalystName.keyword": {
+                          value: "*CHIP SPA*",
+                          case_insensitive: true,
+                        },
+                      },
+                    },
+                  ],
+                },
+              },
+            ],
+            must_not: [],
+            should: [],
+            filter: [],
+          },
+        },
+      });
+    });
+    it("should handle multiple filters", () => {
+      const results = filterQueryBuilder([
+        {
+          type: "terms",
+          prefix: "must",
+          field: "authority.keyword",
+          value: ["Medicaid SPA", "CHIP SPA"],
+        },
+        {
+          type: "term",
+          prefix: "must_not",
+          field: "state",
+          value: "MD",
+        },
+        // @ts-expect-error
+        {
+          type: "exists",
+          prefix: "should",
+          field: "origin",
+        },
+        {
+          type: "range",
+          prefix: "filter",
+          field: "timestamp",
+          value: ["1677715190000", "1677715210000"],
+        },
+        {
+          type: "global_search",
+          prefix: "must",
+          field: "authority",
+          value: "   CHIP SPA   ",
+        },
+      ]);
+      expect(results).toEqual({
+        query: {
+          bool: {
+            must: [
+              { terms: { "authority.keyword": ["Medicaid SPA", "CHIP SPA"] } },
+              {
+                dis_max: {
+                  tie_breaker: 0.7,
+                  boost: 1.2,
+                  queries: [
+                    {
+                      wildcard: {
+                        "id.keyword": {
+                          value: "*CHIP SPA*",
+                          case_insensitive: true,
+                        },
+                      },
+                    },
+                    {
+                      wildcard: {
+                        "submitterName.keyword": {
+                          value: "*CHIP SPA*",
+                          case_insensitive: true,
+                        },
+                      },
+                    },
+                    {
+                      wildcard: {
+                        "leadAnalystName.keyword": {
+                          value: "*CHIP SPA*",
+                          case_insensitive: true,
+                        },
+                      },
+                    },
+                  ],
+                },
+              },
+            ],
+            must_not: [{ term: { state: "MD" } }],
+            should: [{ exists: { field: "origin" } }],
+            filter: [{ range: { timestamp: ["1677715190000", "1677715210000"] } }],
+          },
+        },
+      });
+    });
+  });
+
+  describe("paginationQueryBuilder tests", () => {
+    it("should handle an undefined pagination", () => {
+      const result = paginationQueryBuilder(undefined);
+      expect(result).toEqual({});
+    });
+    it("should handle a null pagination", () => {
+      const result = paginationQueryBuilder(null);
+      expect(result).toEqual({});
+    });
+    it("should handle an empty pagination", () => {
+      // @ts-expect-error
+      const result = paginationQueryBuilder({});
+      expect(result).toEqual({
+        from: 0,
+        size: 25,
+      });
+    });
+    it("should handle an undefined number", () => {
+      // @ts-expect-error
+      const result = paginationQueryBuilder({ size: 20 });
+      expect(result).toEqual({
+        from: 0,
+        size: 20,
+      });
+    });
+    it("should handle 0 number", () => {
+      const result = paginationQueryBuilder({ number: 0, size: 20 });
+      expect(result).toEqual({
+        from: 0,
+        size: 20,
+      });
+    });
+    it("should handle a negative number", () => {
+      const result = paginationQueryBuilder({ number: -3, size: 20 });
+      expect(result).toEqual({
+        from: 0,
+        size: 20,
+      });
+    });
+    it("should handle an undefined size", () => {
+      // @ts-expect-error
+      const result = paginationQueryBuilder({ number: 1 });
+      expect(result).toEqual({
+        from: 0,
+        size: 25,
+      });
+    });
+    it("should handle 0 size", () => {
+      const result = paginationQueryBuilder({ number: 1, size: 0 });
+      expect(result).toEqual({
+        from: 0,
+        size: 25,
+      });
+    });
+    it("should handle a negative size", () => {
+      const result = paginationQueryBuilder({ number: 1, size: -3 });
+      expect(result).toEqual({
+        from: 0,
+        size: 25,
+      });
+    });
+    it("should handle a valid number and size", () => {
+      const result = paginationQueryBuilder({ number: 2, size: 20 });
+      expect(result).toEqual({
+        from: 40,
+        size: 20,
+      });
+    });
+  });
+
+  describe("sortQueryBuilder tests", () => {
+    it("should handle an undefined sort", () => {
+      const result = sortQueryBuilder(undefined);
+      expect(result).toEqual({});
+    });
+    it("should handle a null sort", () => {
+      const result = sortQueryBuilder(null);
+      expect(result).toEqual({});
+    });
+    it("should handle an empty sort", () => {
+      // @ts-expect-error
+      const result = sortQueryBuilder({});
+      expect(result).toEqual({});
+    });
+    it("should handle an undefined field", () => {
+      // @ts-expect-error
+      const result = sortQueryBuilder({ order: "asc" });
+      expect(result).toEqual({});
+    });
+    it("should handle a null field", () => {
+      const result = sortQueryBuilder({ field: null, order: "asc" });
+      expect(result).toEqual({});
+    });
+    it("should handle an undefined order", () => {
+      // @ts-expect-error
+      const result = sortQueryBuilder({ field: "test" });
+      expect(result).toEqual({ sort: [{ test: "asc" }] });
+    });
+    it("should handle a null field", () => {
+      const result = sortQueryBuilder({ field: "test", order: null });
+      expect(result).toEqual({ sort: [{ test: "asc" }] });
+    });
+    it("should handle a valid sort", () => {
+      const result = sortQueryBuilder({ field: "test", order: "desc" });
+      expect(result).toEqual({ sort: [{ test: "desc" }] });
+    });
+  });
+
+  describe("aggQueryBuilder tests", () => {
+    it("should handle an undefined aggregation", () => {
+      const result = aggQueryBuilder(undefined);
+      expect(result).toEqual({});
+    });
+    it("should handle a null aggregation", () => {
+      const result = aggQueryBuilder(null);
+      expect(result).toEqual({});
+    });
+    it("should handle an empty aggregation", () => {
+      const result = aggQueryBuilder([]);
+      expect(result).toEqual({});
+    });
+    it("should handle an aggregation with an undefined name", () => {
+      const result = aggQueryBuilder([
+        // @ts-expect-error
+        {
+          type: "term",
+          field: "authority.keyword",
+          size: 25,
+        },
+      ]);
+      expect(result).toEqual({
+        aggs: {},
+      });
+    });
+    it("should handle an aggregation with an undefined type", () => {
+      const result = aggQueryBuilder([
+        // @ts-expect-error
+        {
+          name: "must",
+          field: "authority.keyword",
+          size: 25,
+        },
+      ]);
+      expect(result).toEqual({
+        aggs: {},
+      });
+    });
+    it("should handle an aggregation with an undefined field", () => {
+      const result = aggQueryBuilder([
+        // @ts-expect-error
+        {
+          name: "must",
+          type: "term",
+          size: 25,
+        },
+      ]);
+      expect(result).toEqual({
+        aggs: {},
+      });
+    });
+    it("should handle an aggregation with an undefined size", () => {
+      const result = aggQueryBuilder([
+        // @ts-expect-error
+        {
+          name: "must",
+          type: "term",
+          field: "authority.keyword",
+        },
+      ]);
+      expect(result).toEqual({
+        aggs: {
+          must: {
+            term: {
+              field: "authority.keyword",
+              order: { _term: "asc" },
+            },
+          },
+        },
+      });
+    });
+    it("should handle an aggregation with one definition", () => {
+      const result = aggQueryBuilder([
+        {
+          name: "must",
+          type: "term",
+          field: "authority.keyword",
+          size: 50,
+        },
+      ]);
+      expect(result).toEqual({
+        aggs: {
+          must: {
+            term: {
+              field: "authority.keyword",
+              order: { _term: "asc" },
+              size: 50,
+            },
+          },
+        },
+      });
+    });
+    it("should handle an aggregation with multiple definitions", () => {
+      const result = aggQueryBuilder([
+        // @ts-expect-error
+        {
+          name: "must",
+          type: "terms",
+          field: "state",
+        },
+        {
+          name: "must_not",
+          type: "match",
+          field: "origin",
+          size: 40,
+        },
+      ]);
+      expect(result).toEqual({
+        aggs: {
+          must: {
+            terms: {
+              field: "state",
+              order: { _term: "asc" },
+            },
+          },
+          must_not: {
+            match: {
+              field: "origin",
+              order: { _term: "asc" },
+              size: 40,
+            },
+          },
+        },
+      });
+    });
+    it("should overwrite aggregations with the same name and type", () => {
+      const result = aggQueryBuilder([
+        // @ts-expect-error
+        {
+          name: "must",
+          type: "terms",
+          field: "state",
+        },
+        {
+          name: "must",
+          type: "terms",
+          field: "origin",
+          size: 40,
+        },
+      ]);
+      expect(result).toEqual({
+        aggs: {
+          must: {
+            terms: {
+              field: "origin",
+              order: { _term: "asc" },
+              size: 40,
+            },
+          },
+        },
+      });
+    });
+    it("should over aggregations with the same name and different types", () => {
+      const result = aggQueryBuilder([
+        // @ts-expect-error
+        {
+          name: "must",
+          type: "terms",
+          field: "state",
+        },
+        {
+          name: "must",
+          type: "match",
+          field: "origin",
+          size: 40,
+        },
+      ]);
+      expect(result).toEqual({
+        aggs: {
+          must: {
+            match: {
+              field: "origin",
+              order: { _term: "asc" },
+              size: 40,
+            },
+          },
+        },
+      });
+    });
+  });
+
+  describe("createSearchFilterable tests", () => {
+    it("should handle an undefined value", () => {
+      const result = createSearchFilterable(undefined);
+      expect(result).toEqual([]);
+    });
+    it("should handle a null value", () => {
+      const result = createSearchFilterable(null);
+      expect(result).toEqual([]);
+    });
+    it("should handle an empty value", () => {
+      const result = createSearchFilterable("");
+      expect(result).toEqual([]);
+    });
+    it("should handle a value", () => {
+      const result = createSearchFilterable("test");
+      expect(result).toEqual([
+        {
+          type: "global_search",
+          field: "",
+          value: "test",
+          prefix: "must",
+        },
+      ]);
+    });
+  });
+
+  describe("checkMultiFilter tests", () => {
+    it("should return true undefined filters and undefined val", () => {
+      const result = checkMultiFilter(undefined, undefined);
+      expect(result).toBe(true);
+    });
+    it("should return true for equal filters and val", () => {
+      const result = checkMultiFilter(
+        [
+          {
+            prefix: "must",
+            type: "terms",
+            field: "authority.keyword",
+            value: ["Medicaid SPA", "CHIP SPA"],
+          },
+        ],
+        1,
+      );
+      expect(result).toBe(true);
+    });
+    it("should return true for more filters than val", () => {
+      const result = checkMultiFilter(
+        [
+          {
+            prefix: "must",
+            type: "terms",
+            field: "authority.keyword",
+            value: ["Medicaid SPA", "CHIP SPA"],
+          },
+          {
+            prefix: "must",
+            type: "exists",
+            field: "origin",
+            value: true,
+          },
+        ],
+        1,
+      );
+      expect(result).toBe(true);
+    });
+    it("should return true for more filter values than val", () => {
+      const result = checkMultiFilter(
+        [
+          {
+            prefix: "must",
+            type: "terms",
+            field: "authority.keyword",
+            value: ["Medicaid SPA", "CHIP SPA", "1915(b)", "1915(c)"],
+          },
+          {
+            prefix: "must",
+            type: "exists",
+            field: "origin",
+            value: true,
+          },
+        ],
+        3,
+      );
+      expect(result).toBe(true);
+    });
+    it("should return false for less filters than val", () => {
+      const result = checkMultiFilter(
+        [
+          {
+            prefix: "must",
+            type: "terms",
+            field: "authority.keyword",
+            value: ["Medicaid SPA", "CHIP SPA"],
+          },
+          {
+            prefix: "must",
+            type: "exists",
+            field: "origin",
+            value: true,
+          },
+        ],
+        4,
+      );
+      expect(result).toBe(false);
+    });
+    it("should return false for filter values less than val", () => {
+      const result = checkMultiFilter(
+        [
+          {
+            prefix: "must",
+            type: "terms",
+            field: "authority.keyword",
+            value: ["Medicaid SPA"],
+          },
+        ],
+        2,
+      );
+      expect(result).toBe(false);
+    });
+  });
+});
diff --git a/react-app/src/components/Opensearch/utils.ts b/react-app/src/components/Opensearch/utils.ts
index bc73ea90c3..d0e20443e6 100644
--- a/react-app/src/components/Opensearch/utils.ts
+++ b/react-app/src/components/Opensearch/utils.ts
@@ -4,6 +4,14 @@ const filterMapQueryReducer = (
   state: Record<opensearch.Filterable<any>["prefix"], any[]>,
   filter: opensearch.Filterable<any>,
 ) => {
+  if (filter.type === "exists") {
+    state[filter.prefix].push({
+      exists: { field: filter.field },
+    });
+  }
+
+  if (filter.value === undefined || filter.value == null) return state;
+
   // this was hoisted up since false is a valid "match" value
   if (filter.type === "match") {
     state[filter.prefix].push({
@@ -25,12 +33,6 @@ const filterMapQueryReducer = (
     });
   }
 
-  if (filter.type === "exists") {
-    state[filter.prefix].push({
-      exists: { field: filter.field },
-    });
-  }
-
   if (filter.type === "range") {
     state[filter.prefix].push({
       range: { [filter.field]: filter.value },
@@ -38,7 +40,6 @@ const filterMapQueryReducer = (
   }
 
   if (filter.type === "global_search") {
-    if (!filter.value) return state;
     state[filter.prefix].push({
       dis_max: {
         tie_breaker: 0.7,
@@ -74,31 +75,45 @@ export const filterQueryBuilder = (filters: opensearch.Filterable<any>[]) => {
 };
 
 export const paginationQueryBuilder = (pagination: opensearch.QueryState<any>["pagination"]) => {
+  if (!pagination) return {};
+
   const from = (() => {
-    if (!pagination.number) return 0;
+    if (
+      !pagination?.number ||
+      !pagination?.size ||
+      pagination?.number < 1 ||
+      pagination?.size < 1
+    ) {
+      return 0;
+    }
     return pagination.number * pagination.size;
   })();
 
   return {
-    size: pagination.size,
+    size: pagination?.size && pagination?.size > 0 ? pagination?.size : 25,
     from,
   };
 };
 
 export const sortQueryBuilder = (sort: opensearch.QueryState<any>["sort"]) => {
-  return { sort: [{ [sort.field]: sort.order }] };
+  if (!sort?.field) return {};
+  return { sort: [{ [sort.field]: sort.order || "asc" }] };
 };
 
 export const aggQueryBuilder = (aggs: opensearch.AggQuery<any>[]) => {
+  if (!aggs?.length) return {};
+
   return {
     aggs: aggs.reduce((STATE, AGG) => {
-      STATE[AGG.name] = {
-        [AGG.type]: {
-          field: AGG.field,
-          order: { _term: "asc" },
-          ...(AGG.size && { size: AGG.size }),
-        },
-      };
+      if (AGG?.name && AGG?.type && AGG?.field) {
+        STATE[AGG.name] = {
+          [AGG.type]: {
+            field: AGG.field,
+            order: { _term: "asc" },
+            ...(AGG.size && { size: AGG.size }),
+          },
+        };
+      }
       return STATE;
     }, {} as any),
   };
@@ -116,7 +131,7 @@ export const createSearchFilterable = (value?: string) => {
   ];
 };
 
-export const checkMultiFilter = (filters: opensearch.Filterable<any>[], val: number) => {
+export const checkMultiFilter = (filters: opensearch.Filterable<any>[] = [], val: number = 0) => {
   return (
     filters.length >= val ||
     filters.some((filter) => Array.isArray(filter.value) && filter.value.length >= val)

From 891ebb6e5e442f97c1510e2a4df3626a9d4af028 Mon Sep 17 00:00:00 2001
From: Thomas Walker <thomas.e.walker88@gmail.com>
Date: Wed, 22 Jan 2025 08:28:10 -0500
Subject: [PATCH 3/4] feat(test)Test cov cleanup (#1045)

* feat(test)-test coverage cleanup

* remove sroll to top
---
 vitest.config.ts | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/vitest.config.ts b/vitest.config.ts
index 18ce87308e..be11903341 100644
--- a/vitest.config.ts
+++ b/vitest.config.ts
@@ -20,6 +20,9 @@ export default defineConfig({
         "lib/libs/webforms/**",
         "lib/libs/email/mock-data/**",
         "react-app/src/features/webforms/**",
+        "react-app/src/components/ScrollToTop/**",
+        "**/*.test.ts",
+        "**/*.test.tsx",
         "TestWrapper.tsx",
         "lib/stacks/**",
         "lib/packages/eslint-config-custom/**",

From 64d83393f5a95638439a674a6157e44750681826 Mon Sep 17 00:00:00 2001
From: Benjamin Paige <benjamin.paige@gmail.com>
Date: Wed, 22 Jan 2025 07:52:19 -0700
Subject: [PATCH 4/4] feat(te/appk): Adding initial temp extension emails and
 appk for b's and c's (#1049)

* Update with tempExt and appks

* Addd 1915b appks

* Update

* Update

* Update
---
 lib/lambda/processEmailsHandler.test.ts       | 17 +++++++---
 .../newSubmission/emailTemplates/AppKCMS.tsx  |  2 +-
 .../emailTemplates/AppKState.tsx              |  2 +-
 .../email/content/newSubmission/index.tsx     | 33 +++++++++++++++----
 .../emailTemplates/TempExtCMS.tsx             |  6 ++--
 .../emailTemplates/TempExtState.tsx           |  6 ++--
 .../email/content/tempExtension/index.tsx     |  4 +--
 lib/libs/email/index.ts                       |  6 ++--
 lib/libs/email/mock-data/temp-extension.ts    |  2 --
 .../preview/InitialSubmissions/CMS/AppK.tsx   | 25 ++++++++++++++
 .../InitialSubmissions/CMS/Temp_Extension.tsx |  2 ++
 .../State/Temp_Extension.tsx                  |  3 +-
 .../CMS/Temp_Extension.tsx                    | 14 --------
 lib/libs/email/types.ts                       |  2 +-
 lib/packages/shared-types/events/app-k.ts     |  2 ++
 lib/packages/shared-types/events/index.ts     |  4 +--
 16 files changed, 87 insertions(+), 43 deletions(-)
 create mode 100644 lib/libs/email/preview/InitialSubmissions/CMS/AppK.tsx
 delete mode 100644 lib/libs/email/preview/Initial_Submissions/CMS/Temp_Extension.tsx

diff --git a/lib/lambda/processEmailsHandler.test.ts b/lib/lambda/processEmailsHandler.test.ts
index dace4fd428..0eb98d5989 100644
--- a/lib/lambda/processEmailsHandler.test.ts
+++ b/lib/lambda/processEmailsHandler.test.ts
@@ -7,12 +7,13 @@ import { Authority } from "shared-types";
 import { SIMPLE_ID, WITHDRAW_RAI_ITEM_B, WITHDRAW_RAI_ITEM_C } from "mocks";
 const nms = "new-medicaid-submission";
 const ncs = "new-chip-submission";
-const tempExtension = "temp-extension";
+const tempExtension = "temporary-extension";
 const withdrawPackage = "withdraw-package";
 const contractingInitial = "contracting-initial";
 const capitatedInitial = "capitated-initial";
 const withdrawRai = "withdraw-rai";
 const respondToRai = "respond-to-rai";
+const appk = "app-k";
 
 describe("process emails  Handler", () => {
   it.each([
@@ -131,9 +132,9 @@ describe("process emails  Handler", () => {
       SIMPLE_ID,
     ],
     [
-      `should send an email for ${withdrawPackage} with ${Authority["1915c"]}`,
+      `should send an email for ${appk} with ${Authority["1915c"]}`,
       Authority["1915c"],
-      withdrawPackage,
+      appk,
       SIMPLE_ID,
     ],
     [
@@ -179,9 +180,15 @@ describe("process emails  Handler", () => {
       SIMPLE_ID,
     ],
     [
-      `should send an email for ${capitatedInitial} with ${Authority["1915c"]}`,
+      `should send an email for ${appk} with ${Authority["1915c"]}`,
       Authority["1915c"],
-      capitatedInitial,
+      appk,
+      SIMPLE_ID,
+    ],
+    [
+      `should send an email for ${appk} with ${Authority["1915b"]}`,
+      Authority["1915b"],
+      appk,
       SIMPLE_ID,
     ],
     [
diff --git a/lib/libs/email/content/newSubmission/emailTemplates/AppKCMS.tsx b/lib/libs/email/content/newSubmission/emailTemplates/AppKCMS.tsx
index 0abdffe531..5bb1c55d7d 100644
--- a/lib/libs/email/content/newSubmission/emailTemplates/AppKCMS.tsx
+++ b/lib/libs/email/content/newSubmission/emailTemplates/AppKCMS.tsx
@@ -9,7 +9,7 @@ import {
 import { BaseEmailTemplate } from "../../email-templates";
 import { formatDate } from "shared-utils";
 
-type AppKEmailProps = Events["NewAppKSubmission"] & CommonEmailVariables;
+type AppKEmailProps = Events["AppKSubmission"] & CommonEmailVariables;
 
 // 1915c - app K
 export const AppKCMSEmail = ({ variables }: { variables: AppKEmailProps }) => {
diff --git a/lib/libs/email/content/newSubmission/emailTemplates/AppKState.tsx b/lib/libs/email/content/newSubmission/emailTemplates/AppKState.tsx
index 2d8d2b44be..441314d632 100644
--- a/lib/libs/email/content/newSubmission/emailTemplates/AppKState.tsx
+++ b/lib/libs/email/content/newSubmission/emailTemplates/AppKState.tsx
@@ -12,7 +12,7 @@ import { BaseEmailTemplate } from "../../email-templates";
 import { styles } from "../../email-styles";
 
 export const AppKStateEmail = (props: {
-  variables: Events["NewAppKSubmission"] & CommonEmailVariables;
+  variables: Events["AppKSubmission"] & CommonEmailVariables;
 }) => {
   const variables = props.variables;
   const previewText = `Appendix K Amendment Submitted`;
diff --git a/lib/libs/email/content/newSubmission/index.tsx b/lib/libs/email/content/newSubmission/index.tsx
index a7a967f2f3..6f16ded38c 100644
--- a/lib/libs/email/content/newSubmission/index.tsx
+++ b/lib/libs/email/content/newSubmission/index.tsx
@@ -61,31 +61,50 @@ export const newSubmission: AuthoritiesWithUserTypesTemplate = {
       variables:
         | (Events["CapitatedInitial"] & CommonEmailVariables & { emails: EmailAddresses })
         | (Events["ContractingInitial"] & CommonEmailVariables & { emails: EmailAddresses })
-        | (Events["CapitatedRenewal"] & CommonEmailVariables & { emails: EmailAddresses }),
+        | (Events["CapitatedRenewal"] & CommonEmailVariables & { emails: EmailAddresses })
+        | (Events["ContractingRenewal"] & CommonEmailVariables & { emails: EmailAddresses })
+        | (Events["CapitatedAmendment"] & CommonEmailVariables & { emails: EmailAddresses })
+        | (Events["ContractingAmendment"] & CommonEmailVariables & { emails: EmailAddresses })
+        | (Events["AppKSubmission"] & CommonEmailVariables & { emails: EmailAddresses }),
     ) => {
       return {
         to: variables.emails.osgEmail,
         subject: `${variables.authority} ${variables.id} Submitted`,
-        body: await render(<Waiver1915bCMSEmail variables={variables} />),
+        body: await render(
+          variables.event === "app-k" ? (
+            <AppKCMSEmail variables={variables} />
+          ) : (
+            <Waiver1915bCMSEmail variables={variables} />
+          ),
+        ),
       };
     },
     state: async (
       variables:
         | (Events["CapitatedInitial"] & CommonEmailVariables & { emails: EmailAddresses })
         | (Events["ContractingInitial"] & CommonEmailVariables & { emails: EmailAddresses })
-        | (Events["CapitatedRenewal"] & CommonEmailVariables & { emails: EmailAddresses }),
+        | (Events["CapitatedRenewal"] & CommonEmailVariables & { emails: EmailAddresses })
+        | (Events["ContractingRenewal"] & CommonEmailVariables & { emails: EmailAddresses })
+        | (Events["CapitatedAmendment"] & CommonEmailVariables & { emails: EmailAddresses })
+        | (Events["ContractingAmendment"] & CommonEmailVariables & { emails: EmailAddresses })
+        | (Events["AppKSubmission"] & CommonEmailVariables & { emails: EmailAddresses }),
     ) => {
       return {
         to: [`${variables.submitterName} <${variables.submitterEmail}>`],
         subject: `Your ${variables.authority} ${variables.id} has been submitted to CMS`,
-        body: await render(<Waiver1915bStateEmail variables={variables} />),
+        body: await render(
+          variables.event === "app-k" ? (
+            <AppKCMSEmail variables={variables} />
+          ) : (
+            <Waiver1915bStateEmail variables={variables} />
+          ),
+        ),
       };
     },
   },
-
   [Authority["1915c"]]: {
     cms: async (
-      variables: Events["NewAppKSubmission"] & CommonEmailVariables & { emails: EmailAddresses },
+      variables: Events["AppKSubmission"] & CommonEmailVariables & { emails: EmailAddresses },
     ) => {
       return {
         to: variables.emails.osgEmail,
@@ -94,7 +113,7 @@ export const newSubmission: AuthoritiesWithUserTypesTemplate = {
       };
     },
     state: async (
-      variables: Events["NewAppKSubmission"] & CommonEmailVariables & { emails: EmailAddresses },
+      variables: Events["AppKSubmission"] & CommonEmailVariables & { emails: EmailAddresses },
     ) => {
       return {
         to: [`${variables.submitterName} <${variables.submitterEmail}>`],
diff --git a/lib/libs/email/content/tempExtension/emailTemplates/TempExtCMS.tsx b/lib/libs/email/content/tempExtension/emailTemplates/TempExtCMS.tsx
index 9a7e3a0767..72978c26f1 100644
--- a/lib/libs/email/content/tempExtension/emailTemplates/TempExtCMS.tsx
+++ b/lib/libs/email/content/tempExtension/emailTemplates/TempExtCMS.tsx
@@ -8,9 +8,9 @@ import {
 import { BaseEmailTemplate } from "../../email-templates";
 import { formatNinetyDaysDate } from "shared-utils";
 
-export const TempExtCMSEmail = (props: {
-  variables: Events["TempExtension"] & CommonEmailVariables;
-}) => {
+type TempExtCMSEmailProps = Events["TemporaryExtension"] & CommonEmailVariables;
+
+export const TempExtCMSEmail = (props: { variables: TempExtCMSEmailProps }) => {
   const variables = props.variables;
   const previewText = `Temporary Extension ${variables.id} Submitted`;
   const heading = `The Submission Portal received a ${variables.authority} Temporary Extension Submission:`;
diff --git a/lib/libs/email/content/tempExtension/emailTemplates/TempExtState.tsx b/lib/libs/email/content/tempExtension/emailTemplates/TempExtState.tsx
index 8ea90ded58..96cb13c896 100644
--- a/lib/libs/email/content/tempExtension/emailTemplates/TempExtState.tsx
+++ b/lib/libs/email/content/tempExtension/emailTemplates/TempExtState.tsx
@@ -1,10 +1,12 @@
 import { formatNinetyDaysDate } from "shared-utils";
-import { CommonEmailVariables } from "shared-types";
+import { CommonEmailVariables, Events } from "shared-types";
 import { PackageDetails, MailboxNotice, FollowUpNotice, Attachments } from "../../email-components";
 
 import { BaseEmailTemplate } from "../../email-templates";
 
-export const TempExtStateEmail = (props: { variables: any & CommonEmailVariables }) => {
+type TempExtStateEmailProps = Events["TemporaryExtension"] & CommonEmailVariables;
+
+export const TempExtStateEmail = (props: { variables: TempExtStateEmailProps }) => {
   const variables = props.variables;
   const previewText = `Temporary Extension ${variables.id} Submitted`;
   const heading =
diff --git a/lib/libs/email/content/tempExtension/index.tsx b/lib/libs/email/content/tempExtension/index.tsx
index b3d4f3f011..9b34859b2f 100644
--- a/lib/libs/email/content/tempExtension/index.tsx
+++ b/lib/libs/email/content/tempExtension/index.tsx
@@ -6,7 +6,7 @@ import { TempExtCMSEmail, TempExtStateEmail } from "./emailTemplates";
 
 export const tempExtention: UserTypeOnlyTemplate = {
   cms: async (
-    variables: Events["TempExtension"] & CommonEmailVariables & { emails: EmailAddresses },
+    variables: Events["TemporaryExtension"] & CommonEmailVariables & { emails: EmailAddresses },
   ) => {
     return {
       to: variables.emails.osgEmail,
@@ -15,7 +15,7 @@ export const tempExtention: UserTypeOnlyTemplate = {
     };
   },
   state: async (
-    variables: Events["TempExtension"] & CommonEmailVariables & { emails: EmailAddresses },
+    variables: Events["TemporaryExtension"] & CommonEmailVariables & { emails: EmailAddresses },
   ) => {
     return {
       to: [`${variables.submitterName} <${variables.submitterEmail}>`],
diff --git a/lib/libs/email/index.ts b/lib/libs/email/index.ts
index ca21f9e4dd..57f4d78244 100644
--- a/lib/libs/email/index.ts
+++ b/lib/libs/email/index.ts
@@ -23,7 +23,7 @@ export type AuthoritiesWithUserTypesTemplate = {
 export type EmailTemplates = {
   "new-medicaid-submission": AuthoritiesWithUserTypesTemplate;
   "new-chip-submission": AuthoritiesWithUserTypesTemplate;
-  "temp-extension": UserTypeOnlyTemplate;
+  "temporary-extension": UserTypeOnlyTemplate;
   "withdraw-package": AuthoritiesWithUserTypesTemplate;
   "withdraw-rai": AuthoritiesWithUserTypesTemplate;
   "contracting-initial": AuthoritiesWithUserTypesTemplate;
@@ -37,13 +37,14 @@ export type EmailTemplates = {
   "contracting-renewal-state": AuthoritiesWithUserTypesTemplate;
   "capitated-renewal-state": AuthoritiesWithUserTypesTemplate;
   "respond-to-rai": AuthoritiesWithUserTypesTemplate;
+  "app-k": AuthoritiesWithUserTypesTemplate;
 };
 
 // Create a type-safe mapping of email templates
 const emailTemplates: EmailTemplates = {
   "new-medicaid-submission": EmailContent.newSubmission,
   "new-chip-submission": EmailContent.newSubmission,
-  "temp-extension": EmailContent.tempExtention,
+  "temporary-extension": EmailContent.tempExtention,
   "withdraw-package": EmailContent.withdrawPackage,
   "withdraw-rai": EmailContent.withdrawRai,
   "contracting-initial": EmailContent.newSubmission,
@@ -57,6 +58,7 @@ const emailTemplates: EmailTemplates = {
   "contracting-renewal-state": EmailContent.newSubmission,
   "capitated-renewal-state": EmailContent.newSubmission,
   "respond-to-rai": EmailContent.respondToRai,
+  "app-k": EmailContent.newSubmission,
 };
 
 // Create a type-safe lookup function
diff --git a/lib/libs/email/mock-data/temp-extension.ts b/lib/libs/email/mock-data/temp-extension.ts
index 7faf0506e5..da3a18a70a 100644
--- a/lib/libs/email/mock-data/temp-extension.ts
+++ b/lib/libs/email/mock-data/temp-extension.ts
@@ -3,8 +3,6 @@ export const emailTemplateValue = {
   territory: "MD",
   id: "MD-2343.R00.TE09",
   waiverNumber: "MD-2343.R00.TE00",
-  authority: "1915(b)",
-  actionType: "Extend",
   applicationEndpointUrl: "https://mako-dev.cms.gov/",
   get timestamp() {
     return Date.now() + 5184000000;
diff --git a/lib/libs/email/preview/InitialSubmissions/CMS/AppK.tsx b/lib/libs/email/preview/InitialSubmissions/CMS/AppK.tsx
new file mode 100644
index 0000000000..06b09119ec
--- /dev/null
+++ b/lib/libs/email/preview/InitialSubmissions/CMS/AppK.tsx
@@ -0,0 +1,25 @@
+import { AppKCMSEmail } from "../../../content/newSubmission/emailTemplates";
+import { emailTemplateValue } from "../../../mock-data/new-submission";
+import * as attachments from "../../../mock-data/attachments";
+
+const AppKCMSEmailPreview = () => {
+  return (
+    <AppKCMSEmail
+      variables={{
+        ...emailTemplateValue,
+        event: "app-k",
+        id: "CO-1234.R21.00",
+        authority: "1915(c)",
+        actionType: "Amend",
+        territory: "CO",
+        title: "A Perfect Appendix K Amendment Title",
+        attachments: {
+          appk: attachments.appk,
+          other: attachments.other,
+        },
+      }}
+    />
+  );
+};
+
+export default AppKCMSEmailPreview;
diff --git a/lib/libs/email/preview/InitialSubmissions/CMS/Temp_Extension.tsx b/lib/libs/email/preview/InitialSubmissions/CMS/Temp_Extension.tsx
index 3cafcc4b2e..90cb98cdc6 100644
--- a/lib/libs/email/preview/InitialSubmissions/CMS/Temp_Extension.tsx
+++ b/lib/libs/email/preview/InitialSubmissions/CMS/Temp_Extension.tsx
@@ -6,6 +6,8 @@ const TempExtCMSPreview = () => {
     <TempExtCMSEmail
       variables={{
         ...emailTemplateValue,
+        authority: "1915(b)",
+        actionType: "Extend",
       }}
     />
   );
diff --git a/lib/libs/email/preview/InitialSubmissions/State/Temp_Extension.tsx b/lib/libs/email/preview/InitialSubmissions/State/Temp_Extension.tsx
index 3a56000dcd..8713633494 100644
--- a/lib/libs/email/preview/InitialSubmissions/State/Temp_Extension.tsx
+++ b/lib/libs/email/preview/InitialSubmissions/State/Temp_Extension.tsx
@@ -1,5 +1,4 @@
 import { emailTemplateValue } from "../../../mock-data/temp-extension";
-
 import { TempExtStateEmail } from "../../../content/tempExtension/emailTemplates/TempExtState";
 
 const TempExtStatePreview = () => {
@@ -7,6 +6,8 @@ const TempExtStatePreview = () => {
     <TempExtStateEmail
       variables={{
         ...emailTemplateValue,
+        authority: "1915(b)",
+        actionType: "Extend",
       }}
     />
   );
diff --git a/lib/libs/email/preview/Initial_Submissions/CMS/Temp_Extension.tsx b/lib/libs/email/preview/Initial_Submissions/CMS/Temp_Extension.tsx
deleted file mode 100644
index 44c222ebf1..0000000000
--- a/lib/libs/email/preview/Initial_Submissions/CMS/Temp_Extension.tsx
+++ /dev/null
@@ -1,14 +0,0 @@
-import { TempExtCMSEmail } from "../../../content/tempExtension/emailTemplates";
-import { emailTemplateValue } from "../../../mock-data/temp-extension";
-
-const TempExtCMSPreview = () => {
-  return (
-    <TempExtCMSEmail
-      variables={{
-        ...emailTemplateValue,
-      }}
-    />
-  );
-};
-
-export default TempExtCMSPreview;
diff --git a/lib/libs/email/types.ts b/lib/libs/email/types.ts
index 011dd7f514..1472916014 100644
--- a/lib/libs/email/types.ts
+++ b/lib/libs/email/types.ts
@@ -37,5 +37,5 @@ export interface NewSubmissionTemplateProps<T extends keyof Events> {
 }
 
 export interface TempExtensionTemplateProps {
-  variables: Events["TempExtension"] & CommonEmailVariables;
+  variables: Events["TemporaryExtension"] & CommonEmailVariables;
 }
diff --git a/lib/packages/shared-types/events/app-k.ts b/lib/packages/shared-types/events/app-k.ts
index cf258c5589..f8cd316bf5 100644
--- a/lib/packages/shared-types/events/app-k.ts
+++ b/lib/packages/shared-types/events/app-k.ts
@@ -33,3 +33,5 @@ export const schema = baseSchema.extend({
   submitterEmail: z.string().email(),
   timestamp: z.number(),
 });
+
+export type AppKSubmission = z.infer<typeof schema>;
diff --git a/lib/packages/shared-types/events/index.ts b/lib/packages/shared-types/events/index.ts
index 6a61d3a879..c4bc12533a 100644
--- a/lib/packages/shared-types/events/index.ts
+++ b/lib/packages/shared-types/events/index.ts
@@ -45,6 +45,7 @@ export const events = {
 export type BaseSchemas = z.infer<typeof newMedicaidSubmission.baseSchema>;
 
 export type Events = {
+  AppKSubmission: z.infer<typeof appk.schema>;
   CapitatedInitial: z.infer<typeof capitatedIntial.schema>;
   CapitatedRenewal: z.infer<typeof capitatedRenewal.schema>;
   CapitatedAmendment: z.infer<typeof capitatedAmendment.schema>;
@@ -53,8 +54,7 @@ export type Events = {
   ContractingAmendment: z.infer<typeof contractingAmendment.schema>;
   NewChipSubmission: z.infer<typeof newChipSubmission.schema>;
   NewMedicaidSubmission: z.infer<typeof newMedicaidSubmission.schema>;
-  TempExtension: z.infer<typeof temporaryExtension.schema>;
-  NewAppKSubmission: z.infer<typeof appk.schema>;
+  TemporaryExtension: z.infer<typeof temporaryExtension.schema>;
   RespondToRai: z.infer<typeof respondToRai.schema>;
   UploadSubsequentDocuments: z.infer<typeof uploadSubsequentDocuments.schema>;
   WithdrawPackage: z.infer<typeof withdrawPackage.schema>;