mirror of
https://github.com/prowler-cloud/prowler.git
synced 2026-05-06 08:47:18 +00:00
fix(ui): polish shared table pagination and provider spacing (#10891)
This commit is contained in:
@@ -17,6 +17,7 @@ All notable changes to the **Prowler UI** are documented in this file.
|
||||
- Mutelist improvements: table now supports name/reason search and visual count badges for finding targets [(#10846)](https://github.com/prowler-cloud/prowler/pull/10846)
|
||||
- Resources now use batch-applied filters, render metadata JSON with syntax highlighting, and more [(#10861)](https://github.com/prowler-cloud/prowler/pull/10861)
|
||||
- Added knip for dead code detection with `lint:knip` and `lint:knip:fix` scripts [(#10654)](https://github.com/prowler-cloud/prowler/pull/10654)
|
||||
- Table pagination controls now keep their arrows visible on hover in light theme, and more UI improvements [(#10862)](https://github.com/prowler-cloud/prowler/pull/10862)
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
import { render, screen } from "@testing-library/react";
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
|
||||
import type { FilterOption, MetaDataProps, ProviderProps } from "@/types";
|
||||
import type { ProvidersTableRow } from "@/types/providers-table";
|
||||
|
||||
vi.mock("@/components/providers/add-provider-button", () => ({
|
||||
AddProviderButton: () => <button type="button">Add provider</button>,
|
||||
}));
|
||||
|
||||
vi.mock("@/components/providers/muted-findings-config-button", () => ({
|
||||
MutedFindingsConfigButton: () => (
|
||||
<button type="button">Muted findings config</button>
|
||||
),
|
||||
}));
|
||||
|
||||
vi.mock("@/components/providers/providers-filters", () => ({
|
||||
ProvidersFilters: () => <div data-testid="providers-filters">Filters</div>,
|
||||
}));
|
||||
|
||||
vi.mock("@/components/providers/providers-accounts-table", () => ({
|
||||
ProvidersAccountsTable: () => <div data-testid="providers-table">Table</div>,
|
||||
}));
|
||||
|
||||
vi.mock("@/components/providers/wizard", () => ({
|
||||
ProviderWizardModal: () => <div data-testid="provider-wizard-modal" />,
|
||||
}));
|
||||
|
||||
import { ProvidersAccountsView } from "./providers-accounts-view";
|
||||
|
||||
const filters: FilterOption[] = [];
|
||||
const providers: ProviderProps[] = [];
|
||||
const rows: ProvidersTableRow[] = [];
|
||||
const metadata: MetaDataProps = {
|
||||
pagination: { page: 1, pages: 1, count: 0, itemsPerPage: [10] },
|
||||
version: "latest",
|
||||
};
|
||||
|
||||
describe("ProvidersAccountsView", () => {
|
||||
it("keeps the same vertical spacing between filters and table as other views", () => {
|
||||
render(
|
||||
<ProvidersAccountsView
|
||||
isCloud={false}
|
||||
filters={filters}
|
||||
metadata={metadata}
|
||||
providers={providers}
|
||||
rows={rows}
|
||||
/>,
|
||||
);
|
||||
|
||||
expect(screen.getByTestId("providers-filters").parentElement).toHaveClass(
|
||||
"flex",
|
||||
"flex-col",
|
||||
"gap-6",
|
||||
);
|
||||
expect(screen.getByTestId("providers-table")).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
@@ -60,23 +60,25 @@ export function ProvidersAccountsView({
|
||||
|
||||
return (
|
||||
<>
|
||||
<ProvidersFilters
|
||||
filters={filters}
|
||||
providers={providers}
|
||||
actions={
|
||||
<>
|
||||
<MutedFindingsConfigButton />
|
||||
<AddProviderButton onOpenWizard={() => openProviderWizard()} />
|
||||
</>
|
||||
}
|
||||
/>
|
||||
<ProvidersAccountsTable
|
||||
isCloud={isCloud}
|
||||
metadata={metadata}
|
||||
rows={rows}
|
||||
onOpenProviderWizard={openProviderWizard}
|
||||
onOpenOrganizationWizard={openOrganizationWizard}
|
||||
/>
|
||||
<div className="flex flex-col gap-6">
|
||||
<ProvidersFilters
|
||||
filters={filters}
|
||||
providers={providers}
|
||||
actions={
|
||||
<>
|
||||
<MutedFindingsConfigButton />
|
||||
<AddProviderButton onOpenWizard={() => openProviderWizard()} />
|
||||
</>
|
||||
}
|
||||
/>
|
||||
<ProvidersAccountsTable
|
||||
isCloud={isCloud}
|
||||
metadata={metadata}
|
||||
rows={rows}
|
||||
onOpenProviderWizard={openProviderWizard}
|
||||
onOpenOrganizationWizard={openOrganizationWizard}
|
||||
/>
|
||||
</div>
|
||||
<ProviderWizardModal
|
||||
open={isProviderWizardOpen}
|
||||
onOpenChange={handleWizardOpenChange}
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
import { render, screen } from "@testing-library/react";
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
|
||||
import type { MetaDataProps } from "@/types";
|
||||
|
||||
vi.mock("next/navigation", () => ({
|
||||
usePathname: () => "/providers",
|
||||
useRouter: () => ({ push: vi.fn() }),
|
||||
useSearchParams: () => new URLSearchParams(),
|
||||
}));
|
||||
|
||||
vi.mock("@/lib", () => ({
|
||||
getPaginationInfo: () => ({
|
||||
currentPage: 2,
|
||||
totalPages: 4,
|
||||
totalEntries: 40,
|
||||
itemsPerPageOptions: [10, 20, 50],
|
||||
}),
|
||||
}));
|
||||
|
||||
vi.mock("@/components/shadcn/select/select", () => ({
|
||||
Select: ({ children }: { children: React.ReactNode }) => (
|
||||
<div>{children}</div>
|
||||
),
|
||||
SelectContent: ({ children }: { children: React.ReactNode }) => (
|
||||
<div>{children}</div>
|
||||
),
|
||||
SelectItem: ({
|
||||
children,
|
||||
value,
|
||||
}: {
|
||||
children: React.ReactNode;
|
||||
value: string;
|
||||
}) => <option value={value}>{children}</option>,
|
||||
SelectTrigger: ({ children }: { children: React.ReactNode }) => (
|
||||
<button type="button">{children}</button>
|
||||
),
|
||||
SelectValue: () => <span>10</span>,
|
||||
}));
|
||||
|
||||
import { DataTablePagination } from "./data-table-pagination";
|
||||
|
||||
const metadata: MetaDataProps = {
|
||||
pagination: {
|
||||
page: 2,
|
||||
pages: 4,
|
||||
count: 40,
|
||||
itemsPerPage: [10, 20, 50],
|
||||
},
|
||||
version: "latest",
|
||||
};
|
||||
|
||||
describe("DataTablePagination", () => {
|
||||
it("keeps navigation arrows visible on hover in light theme", () => {
|
||||
render(<DataTablePagination metadata={metadata} />);
|
||||
|
||||
expect(screen.getByLabelText("Go to first page")).toHaveClass(
|
||||
"hover:text-text-neutral-primary",
|
||||
);
|
||||
expect(screen.getByLabelText("Go to first page")).toHaveClass(
|
||||
"hover:bg-bg-neutral-tertiary",
|
||||
);
|
||||
expect(screen.getByLabelText("Go to next page")).toHaveClass(
|
||||
"hover:text-text-neutral-primary",
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -40,7 +40,8 @@ interface DataTablePaginationProps {
|
||||
|
||||
const NAV_BUTTON_STYLES = {
|
||||
base: "flex items-center justify-center rounded-full p-3 transition-colors",
|
||||
enabled: "text-text-neutral-secondary hover:text-white",
|
||||
enabled:
|
||||
"text-text-neutral-secondary hover:bg-bg-neutral-tertiary hover:text-text-neutral-primary",
|
||||
disabled: "text-text-neutral-tertiary cursor-not-allowed pointer-events-none",
|
||||
} as const;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user