Skip to content

Commit

Permalink
2532 allow list (passportxyz#2576)
Browse files Browse the repository at this point in the history
* feat: allow list stamp

* feat: verify allow list from scorer

* app: wip dynamic provider

* feat(app): normalize custom provider at global level

* feat: update to address list and build provider config within app from weights

* feat: verifying allow list

* chore: rename back to allowList

* feat: update remaining functionality to match custom providers

* feat: hide allow list if you don't have points

* chore: remove unneeded updates

* chore(platforms): fix allowlist test

* fix: non custom dashboard bugs

* feat: test allow list providers

* chore: use is_member

* feat: show allow list within cardlist

* chore: provide errors for allowList stamp

* fix: non error handling
  • Loading branch information
tim-schultz authored Jun 14, 2024
1 parent 1812b01 commit ec2d21b
Show file tree
Hide file tree
Showing 32 changed files with 666 additions and 241 deletions.
5 changes: 3 additions & 2 deletions app/__test-fixtures__/contextTestHelpers.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -221,13 +221,14 @@ const datastoreConnectionContext = {
export const renderWithContext = (
ceramicContext: CeramicContextState,
ui: React.ReactElement<any, string | React.JSXElementConstructor<any>>,
datastoreContextOverride: Partial<DatastoreConnectionContextState> = {}
datastoreContextOverride: Partial<DatastoreConnectionContextState> = {},
scorerContextOverride: Partial<ScorerContextState> = {}
) => {
const queryClient = new QueryClient();
return render(
<QueryClientProvider client={queryClient}>
<DatastoreConnectionContext.Provider value={{ ...datastoreConnectionContext, ...datastoreContextOverride }}>
<ScorerContext.Provider value={scorerContext}>
<ScorerContext.Provider value={{ ...scorerContext, ...scorerContextOverride }}>
<CeramicContext.Provider value={ceramicContext}>{ui}</CeramicContext.Provider>
</ScorerContext.Provider>
</DatastoreConnectionContext.Provider>
Expand Down
27 changes: 24 additions & 3 deletions app/__tests__/components/CardList.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ import {
} from "../../__test-fixtures__/contextTestHelpers";
import { CeramicContext, CeramicContextState } from "../../context/ceramicContext";
import { Category, CategoryProps } from "../../components/Category";
import { PROVIDER_ID } from "@gitcoin/passport-types";
import { PlatformCard, SelectedProviders } from "../../components/PlatformCard";
import { PlatformCard } from "../../components/PlatformCard";
import { PlatformScoreSpec } from "../../context/scorerContext";

jest.mock("@didtools/cacao", () => ({
Cacao: {
Expand Down Expand Up @@ -133,7 +133,6 @@ describe("<CardList />", () => {
possiblePoints: 10,
earnedPoints: 7,
}}
selectedProviders={{ ETH: [] as PROVIDER_ID[] } as SelectedProviders}
onOpen={mockOnOpen}
setCurrentPlatform={mockSetCurrentPlatform}
/>
Expand Down Expand Up @@ -161,6 +160,28 @@ describe("<CardList />", () => {
//the verified stamp no longer shows the score of availablepoints
expect(availablePnts).toEqual(["12.93", "7.44", "0.69"]);
});
it("renders allowList if stamp is present", () => {
const scorerContext = {
scoredPlatforms: [
{
icon: "./assets/star-light.svg",
platform: "AllowList",
name: "Guest List",
description: "Verify you are part of a community",
connectMessage: "Verify",
isEVM: true,
possiblePoints: 100,
earnedPoints: 100,
},
] as PlatformScoreSpec[],
};
renderWithContext(mockCeramicContext, <CardList {...cardListProps} />, {}, scorerContext);
expect(screen.getByText("Guest List")).toBeInTheDocument();
});
it("should not render allow list", () => {
renderWithContext(mockCeramicContext, <CardList {...cardListProps} />);
expect(screen.queryByText("Guest List")).not.toBeInTheDocument();
});
});

test("renders Category component", () => {
Expand Down
122 changes: 54 additions & 68 deletions app/__tests__/components/GenericPlatform.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -71,15 +71,13 @@ describe("when user has not verified with EnsProvider", () => {
});
it("should display a verification button", () => {
const drawer = () => (
<Drawer isOpen={true} placement="right" size="sm" onClose={() => {}}>
<DrawerOverlay />
<GenericPlatform
platform={new Ens.EnsPlatform()}
platFormGroupSpec={Ens.ProviderConfig}
platformScoreSpec={EnsScoreSpec}
onClose={() => {}}
/>
</Drawer>
<GenericPlatform
isOpen={true}
platform={new Ens.EnsPlatform()}
platFormGroupSpec={Ens.ProviderConfig}
platformScoreSpec={EnsScoreSpec}
onClose={() => {}}
/>
);

renderWithContext(mockCeramicContext, drawer());
Expand All @@ -88,15 +86,13 @@ describe("when user has not verified with EnsProvider", () => {
});
it("should attempt to fetch a verifiable credential when the button is clicked", async () => {
const drawer = () => (
<Drawer isOpen={true} placement="right" size="sm" onClose={() => {}}>
<DrawerOverlay />
<GenericPlatform
platform={new Ens.EnsPlatform()}
platFormGroupSpec={Ens.ProviderConfig}
platformScoreSpec={EnsScoreSpec}
onClose={() => {}}
/>
</Drawer>
<GenericPlatform
isOpen={true}
platform={new Ens.EnsPlatform()}
platFormGroupSpec={Ens.ProviderConfig}
platformScoreSpec={EnsScoreSpec}
onClose={() => {}}
/>
);
renderWithContext(mockCeramicContext, drawer());

Expand All @@ -111,15 +107,13 @@ describe("when user has not verified with EnsProvider", () => {
it("should show success toast when credential is fetched", async () => {
const drawer = () => (
<ChakraProvider>
<Drawer isOpen={true} placement="right" size="sm" onClose={() => {}}>
<DrawerOverlay />
<GenericPlatform
platform={new Ens.EnsPlatform()}
platFormGroupSpec={Ens.ProviderConfig}
platformScoreSpec={EnsScoreSpec}
onClose={() => {}}
/>
</Drawer>
<GenericPlatform
platform={new Ens.EnsPlatform()}
isOpen={true}
platFormGroupSpec={Ens.ProviderConfig}
platformScoreSpec={EnsScoreSpec}
onClose={() => {}}
/>
</ChakraProvider>
);
renderWithContext(mockCeramicContext, drawer());
Expand All @@ -136,15 +130,13 @@ describe("when user has not verified with EnsProvider", () => {
it("should prompt user to refresh when session expired", async () => {
const drawer = () => (
<ChakraProvider>
<Drawer isOpen={true} placement="right" size="sm" onClose={() => {}}>
<DrawerOverlay />
<GenericPlatform
platform={new Ens.EnsPlatform()}
platFormGroupSpec={Ens.ProviderConfig}
platformScoreSpec={EnsScoreSpec}
onClose={() => {}}
/>
</Drawer>
<GenericPlatform
isOpen={true}
platform={new Ens.EnsPlatform()}
platFormGroupSpec={Ens.ProviderConfig}
platformScoreSpec={EnsScoreSpec}
onClose={() => {}}
/>
</ChakraProvider>
);
renderWithContext(mockCeramicContext, drawer(), {
Expand Down Expand Up @@ -173,20 +165,18 @@ describe("when user has previously verified with EnsProvider", () => {
const extraProvider = "FakeExtraProviderRequiredForCanSubmitLogic" as PROVIDER_ID;
const drawer = () => (
<ChakraProvider>
<Drawer isOpen={true} placement="right" size="sm" onClose={() => {}}>
<DrawerOverlay />
<GenericPlatform
platform={new Ens.EnsPlatform()}
platFormGroupSpec={[
{
...Ens.ProviderConfig[0],
providers: [...Ens.ProviderConfig[0].providers, { title: "Extra", name: extraProvider }],
},
]}
platformScoreSpec={EnsScoreSpec}
onClose={() => {}}
/>
</Drawer>
<GenericPlatform
isOpen={true}
platform={new Ens.EnsPlatform()}
platFormGroupSpec={[
{
...Ens.ProviderConfig[0],
providers: [...Ens.ProviderConfig[0].providers, { title: "Extra", name: extraProvider }],
},
]}
platformScoreSpec={EnsScoreSpec}
onClose={() => {}}
/>
</ChakraProvider>
);

Expand Down Expand Up @@ -219,15 +209,13 @@ describe("Mulitple EVM plaftorms", () => {
credentials: [UN_SUCCESSFUL_ENS_RESULT],
});
const drawer = () => (
<Drawer isOpen={true} placement="right" size="sm" onClose={() => {}}>
<DrawerOverlay />
<GenericPlatform
platform={new Ens.EnsPlatform()}
platFormGroupSpec={Ens.ProviderConfig}
platformScoreSpec={EnsScoreSpec}
onClose={() => {}}
/>
</Drawer>
<GenericPlatform
isOpen={true}
platform={new Ens.EnsPlatform()}
platFormGroupSpec={Ens.ProviderConfig}
platformScoreSpec={EnsScoreSpec}
onClose={() => {}}
/>
);
renderWithContext(mockCeramicContext, drawer());

Expand All @@ -244,15 +232,13 @@ describe("Mulitple EVM plaftorms", () => {
it("should indicate that there was an error issuing the credential", async () => {
const drawer = () => (
<ChakraProvider>
<Drawer isOpen={true} placement="right" size="sm" onClose={() => {}}>
<DrawerOverlay />
<GenericPlatform
platform={new Ens.EnsPlatform()}
platFormGroupSpec={Ens.ProviderConfig}
platformScoreSpec={EnsScoreSpec}
onClose={() => {}}
/>
</Drawer>
<GenericPlatform
isOpen={true}
platform={new Ens.EnsPlatform()}
platFormGroupSpec={Ens.ProviderConfig}
platformScoreSpec={EnsScoreSpec}
onClose={() => {}}
/>
</ChakraProvider>
);
renderWithContext({ ...mockCeramicContext, handlePatchStamps: jest.fn().mockRejectedValue(500) }, drawer());
Expand Down
38 changes: 37 additions & 1 deletion app/__tests__/components/PlatformCard.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ import { PROVIDER_ID } from "@gitcoin/passport-types";
import { useCustomization } from "../../hooks/useCustomization";

// mock useCustomization
jest.mock("../../hooks/useCustomization");
jest.mock("../../hooks/useCustomization", () => ({
useCustomization: jest.fn(),
}));

describe("<PlatformCard />", () => {
beforeEach(() => {
Expand Down Expand Up @@ -68,5 +70,39 @@ describe("<PlatformCard />", () => {
renderTestComponent({});
expect(screen.queryByTestId("platform-name")).toBeInTheDocument();
});
it("should show allow list stamp if user has points", () => {
(useCustomization as jest.Mock).mockReturnValue({
scorer: {
wieghts: {
"AllowList#test": 10,
},
},
});
const AllowListPlatform = getPlatformSpec("AllowList") as PlatformSpec;
const platformScoreSpec = {
...AllowListPlatform,
possiblePoints: 6,
earnedPoints: 1,
};
render(<PlatformCard i={0} platform={platformScoreSpec} onOpen={() => {}} setCurrentPlatform={() => {}} />);
expect(screen.getByTestId("platform-name")).toBeInTheDocument();
});
it("should hide allow list if no points are earned", () => {
(useCustomization as jest.Mock).mockReturnValue({
scorer: {
wieghts: {
"AllowList#test": 10,
},
},
});
const AllowListPlatform = getPlatformSpec("AllowList") as PlatformSpec;
const platformScoreSpec = {
...AllowListPlatform,
possiblePoints: 6,
earnedPoints: 0,
};
render(<PlatformCard i={0} platform={platformScoreSpec} onOpen={() => {}} setCurrentPlatform={() => {}} />);
expect(screen.queryByTestId("platform-name")).not.toBeInTheDocument();
});
});
});
67 changes: 67 additions & 0 deletions app/__tests__/config/providers.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import { PLATFORM_ID } from "@gitcoin/passport-types";
import { Providers, customStampProviders, getStampProviderIds } from "../../config/providers";
import { DynamicCustomization } from "../../utils/customizationUtils";
import { Provider } from "ethers";

jest.mock("@gitcoin/passport-platforms", () => ({
platforms: [],
}));

const STAMP_PROVIDERS = {
Signer: [
{
platformGroup: "Account Name",
providers: [{ title: "Encrypted", name: "Signer" }],
},
],
};

const CUSTOM_PROVIDERS = {
AllowList: [{ providers: [{ name: "AllowList#test" }] }],
};

describe("customStampProviders", () => {
it("returns default providers if customization is undefined", () => {
const result = customStampProviders();
expect(result).toMatchObject(STAMP_PROVIDERS);
});

it("returns default providers if customization does not have allowListProviders", () => {
const customization = { otherField: "value" } as unknown as DynamicCustomization;
const result = customStampProviders(customization);
expect(result).toEqual(STAMP_PROVIDERS);
});

it("returns custom providers if customization contains allowListProviders", () => {
const customization = { allowListProviders: CUSTOM_PROVIDERS.AllowList } as unknown as DynamicCustomization;
const result = customStampProviders(customization);
expect(result.AllowList).toEqual(CUSTOM_PROVIDERS.AllowList);
});
});

describe("getStampProviderIds", () => {
it("returns an empty array if no providers are available for the given platform", () => {
const providers = { Signer: [] } as unknown as Providers;
const result = getStampProviderIds("E" as PLATFORM_ID, providers);
expect(result).toEqual([]);
});

it("returns an array of provider IDs for the given platform", () => {
const providers = {
Default: [{ providers: [{ name: "ProviderOne" }, { name: "ProviderTwo" }] }],
} as unknown as Providers;
const result = getStampProviderIds("Default" as PLATFORM_ID, providers);
expect(result).toEqual(["ProviderOne", "ProviderTwo"]);
});

it("handles platforms with multiple provider groups", () => {
const providers = {
ComplexPlatform: [
{ providers: [{ name: "FirstGroupProvider" }] },
{ providers: [{ name: "SecondGroupProvider" }] },
],
} as unknown as Providers;
const result = getStampProviderIds("ComplexPlatform" as PLATFORM_ID, providers);
expect(result).toEqual(["FirstGroupProvider", "SecondGroupProvider"]);
});
});
4 changes: 2 additions & 2 deletions app/__tests__/hooks/useOneClickVerification.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ import { render, waitFor, screen } from "@testing-library/react";
import { useOneClickVerification } from "../../hooks/useOneClickVerification";
import { useEffect } from "react";
import { useAtom } from "jotai";
import { mutableUserVerificationAtom, userVerificationAtom } from "../../context/userState";
import { mutableUserVerificationAtom } from "../../context/userState";
import { makeTestCeramicContext, renderWithContext } from "../../__test-fixtures__/contextTestHelpers";
import { CeramicContext, CeramicContextState } from "../../context/ceramicContext";
import { CeramicContextState } from "../../context/ceramicContext";
import { DID } from "dids";
import { DatastoreConnectionContext } from "../../context/datastoreConnectionContext";
import { fetchVerifiableCredential } from "@gitcoin/passport-identity";
Expand Down
Loading

0 comments on commit ec2d21b

Please sign in to comment.