(null);
+
+ return (
+
+ {
+ const value = inputRef.current?.value;
+ if (value !== undefined) {
+ onChange(value);
+ }
+ }}
+ placeholder={placeholder}
+ data-testid={dataTestId}
+ defaultValue=""
+ style={{
+ width: "100%",
+ fontSize: "inherit",
+ padding: "8px 16px",
+ borderRadius: "50px",
+ height: "50px",
+ border: "1px solid",
+ borderColor: fieldState.error?.message ? "red" : "#6F99FF",
+ backgroundColor: fieldState.error?.message ? "#FAEAEB" : "white",
+ boxSizing: "border-box",
+ margin: 0,
+ display: "block",
+ minWidth: 0,
+ lineHeight: "1.4375em",
+ WebkitTapHighlightColor: "transparent",
+ animationDuration: "10ms",
+ WebkitAnimationDuration: "10ms",
+ animationName: "mui-auto-fill-cancel",
+ WebkitAnimationName: "mui-auto-fill-cancel",
+ outline: "none",
+ }}
+ />
+ {fieldState.error && (
+
+ )}
+
+ );
+};
diff --git a/govtool/frontend/src/components/organisms/ValidatedGovernanceActionCard.tsx b/govtool/frontend/src/components/organisms/ValidatedGovernanceActionCard.tsx
new file mode 100644
index 000000000..df6a8991a
--- /dev/null
+++ b/govtool/frontend/src/components/organisms/ValidatedGovernanceActionCard.tsx
@@ -0,0 +1,54 @@
+import { useState, useRef, useEffect } from "react";
+
+import { useValidateMutation } from "@/hooks/mutations";
+import { MetadataStandard, ProposalData } from "@/models";
+import { GovernanceActionCard } from "../molecules";
+
+type ActionTypeProps = Omit<
+ ProposalData,
+ | "yesVotes"
+ | "noVotes"
+ | "abstainVotes"
+ | "id"
+ | "details"
+ | "rationale"
+ | "motivation"
+> & {
+ onClick?: () => void;
+ inProgress?: boolean;
+};
+export const ValidatedGovernanceActionCard = ({
+ url,
+ metadataHash,
+ ...props
+}: ActionTypeProps) => {
+ const [isValidating, setIsValidating] = useState(false);
+ const metadataStatus = useRef();
+ const { validateMetadata } = useValidateMutation();
+
+ useEffect(() => {
+ const validate = async () => {
+ setIsValidating(true);
+
+ const { status } = await validateMetadata({
+ standard: MetadataStandard.CIP108,
+ url: url ?? "",
+ hash: metadataHash ?? "",
+ });
+
+ metadataStatus.current = status;
+ setIsValidating(false);
+ };
+ validate();
+ }, []);
+
+ return (
+
+ );
+};
diff --git a/govtool/frontend/src/components/organisms/ValidatedGovernanceVotedOnCard.tsx b/govtool/frontend/src/components/organisms/ValidatedGovernanceVotedOnCard.tsx
new file mode 100644
index 000000000..ec551d4c7
--- /dev/null
+++ b/govtool/frontend/src/components/organisms/ValidatedGovernanceVotedOnCard.tsx
@@ -0,0 +1,43 @@
+import { useState, useRef, useEffect } from "react";
+
+import { useValidateMutation } from "@/hooks/mutations";
+import { MetadataStandard, VotedProposal } from "@/models";
+import { GovernanceVotedOnCard } from "../molecules";
+
+type Props = {
+ votedProposal: VotedProposal;
+ inProgress?: boolean;
+};
+export const ValidatedGovernanceVotedOnCard = ({
+ votedProposal,
+ inProgress,
+}: Props) => {
+ const [isValidating, setIsValidating] = useState(false);
+ const metadataStatus = useRef();
+ const { validateMetadata } = useValidateMutation();
+
+ useEffect(() => {
+ const validate = async () => {
+ setIsValidating(true);
+
+ const { status } = await validateMetadata({
+ standard: MetadataStandard.CIP108,
+ url: votedProposal.proposal.url,
+ hash: votedProposal.proposal.metadataHash,
+ });
+
+ metadataStatus.current = status;
+ setIsValidating(false);
+ };
+ validate();
+ }, []);
+
+ return (
+
+ );
+};
diff --git a/govtool/frontend/src/components/organisms/index.ts b/govtool/frontend/src/components/organisms/index.ts
index 4e4df0284..f1c136904 100644
--- a/govtool/frontend/src/components/organisms/index.ts
+++ b/govtool/frontend/src/components/organisms/index.ts
@@ -2,6 +2,8 @@ export * from "./AutomatedVotingOptions";
export * from "./ChooseStakeKeyPanel";
export * from "./ControlledField";
export * from "./CreateGovernanceActionSteps";
+export * from "./DRepCard";
+export * from "./DRepDetailsCard";
export * from "./DashboardCards";
export * from "./DashboardCards";
export * from "./DashboardDrawerMobile";
@@ -11,18 +13,19 @@ export * from "./DashboardGovernanceActionsVotedOn";
export * from "./DashboardTopNav";
export * from "./Drawer";
export * from "./DrawerMobile";
-export * from "./DRepCard";
-export * from "./DRepDetailsCard";
export * from "./EditDRepInfoSteps";
-export * from "./Modal";
export * from "./Footer";
export * from "./GovernanceActionDetailsCard";
export * from "./GovernanceActionDetailsCardData";
export * from "./GovernanceActionsToVote";
export * from "./Hero";
export * from "./HomeCards";
+export * from "./Modal";
export * from "./RegisterAsDRepSteps";
export * from "./Slider";
export * from "./TopNav";
+export * from "./UncontrolledImageInput";
+export * from "./ValidatedGovernanceActionCard";
+export * from "./ValidatedGovernanceVotedOnCard";
export * from "./VoteContext";
export * from "./WrongRouteInfo";
diff --git a/govtool/frontend/src/consts/dRepActions/fields.ts b/govtool/frontend/src/consts/dRepActions/fields.ts
index e8273cdb1..367ef4468 100644
--- a/govtool/frontend/src/consts/dRepActions/fields.ts
+++ b/govtool/frontend/src/consts/dRepActions/fields.ts
@@ -3,6 +3,7 @@ import {
IMAGE_REGEX,
URL_REGEX,
isReceivingAddress,
+ isValidImageUrl,
isValidURLLength,
} from "@/utils";
@@ -76,5 +77,6 @@ export const Rules = {
value: IMAGE_REGEX,
message: i18n.t("registration.fields.validations.image"),
},
+ validate: isValidImageUrl,
},
};
diff --git a/govtool/frontend/src/context/governanceAction.test.tsx b/govtool/frontend/src/context/governanceAction.test.tsx
index 3eb4e06b4..0ecfd2cb2 100644
--- a/govtool/frontend/src/context/governanceAction.test.tsx
+++ b/govtool/frontend/src/context/governanceAction.test.tsx
@@ -80,7 +80,7 @@ describe("GovernanceActionProvider", () => {
const hash = await createHash(jsonld!);
expect(hash).toBeDefined();
expect(hash).toBe(
- "816b63124f5c5d5bdfc016ad0aea238baf374fecbdadd389eab2dab94bc2383c",
+ "9f7b2f83113e003d36231bd815cafbcc677c3a9513281d751a241720893cc877",
);
};
test();
diff --git a/govtool/frontend/src/hooks/mutations/metadataValidation/useValidateMutation.ts b/govtool/frontend/src/hooks/mutations/metadataValidation/useValidateMutation.ts
index d9fc1a1ec..74f5f0b06 100644
--- a/govtool/frontend/src/hooks/mutations/metadataValidation/useValidateMutation.ts
+++ b/govtool/frontend/src/hooks/mutations/metadataValidation/useValidateMutation.ts
@@ -1,17 +1,27 @@
-import { useMutation } from "react-query";
+import { useMutation, useQueryClient } from "react-query";
import { postValidate } from "@services";
import { MUTATION_KEYS } from "@consts";
import { MetadataValidationDTO } from "@models";
export const useValidateMutation = () => {
- const { data, isLoading, mutateAsync } = useMutation({
- mutationFn: (body: MetadataValidationDTO) => postValidate(body),
+ const queryClient = useQueryClient();
+
+ const { data, isLoading } = useMutation({
+ mutationFn: (body: MetadataValidationDTO) =>
+ postValidate(body),
mutationKey: [MUTATION_KEYS.postValidateKey],
});
+ const validateMetadata = async (body: MetadataValidationDTO) =>
+ queryClient.fetchQuery({
+ queryKey: [MUTATION_KEYS.postValidateKey, body.hash, body.url],
+ queryFn: () => postValidate(body),
+ cacheTime: 20 * 1000, // 20 seconds
+ });
+
return {
- validateMetadata: mutateAsync,
+ validateMetadata,
validationStatus: data,
isValidating: isLoading,
};
diff --git a/govtool/frontend/src/i18n/locales/en.json b/govtool/frontend/src/i18n/locales/en.json
index 78ba4d111..7f25ca853 100644
--- a/govtool/frontend/src/i18n/locales/en.json
+++ b/govtool/frontend/src/i18n/locales/en.json
@@ -388,7 +388,8 @@
"errors": {
"tooLongUrl": "Url must be less than 128 bytes",
"mustBeStakeAddress": "It must be reward address in bech32 format",
- "mustBeReceivingAddress": "Invalid payment address"
+ "mustBeReceivingAddress": "Invalid payment address",
+ "couldNotGenerateImageSha": "Could not generate image sha"
}
},
"proposalDiscussion": {
diff --git a/govtool/frontend/src/models/api.ts b/govtool/frontend/src/models/api.ts
index f298b41f0..bc374ccad 100644
--- a/govtool/frontend/src/models/api.ts
+++ b/govtool/frontend/src/models/api.ts
@@ -1,4 +1,3 @@
-import { MetadataValidationStatus } from "@models";
import { GovernanceActionType } from "@/types/governanceAction";
export type EpochParams = {
@@ -176,8 +175,6 @@ export type DRepData = DrepDataDTO & {
qualifications: string | null;
references: Reference[];
doNotList: boolean;
- metadataStatus: MetadataValidationStatus | null;
- metadataValid: boolean;
imageUrl: string | null;
// either base64 for IPFS image or URL for regular image
image: string | null;
@@ -210,7 +207,7 @@ export type SubmittedVotesData = {
protocolParams: EpochParams | null;
};
-export type ProposalDataDTO = {
+export type ProposalData = {
createdDate: string;
createdEpochNo: number;
details?: ActionDetailsType;
@@ -232,21 +229,11 @@ export type ProposalDataDTO = {
protocolParams: EpochParams | null;
} & SubmittedVotesData;
-export type ProposalData = ProposalDataDTO & {
- metadataStatus: MetadataValidationStatus | null;
- metadataValid: boolean;
-};
-
export type NewConstitutionAnchor = {
dataHash: string;
url: string;
};
-export type VotedProposalDTO = {
- vote: ProposalVote | null;
- proposal: ProposalDataDTO;
-};
-
export type VotedProposal = {
vote: ProposalVote | null;
proposal: ProposalData;
diff --git a/govtool/frontend/src/pages/DashboardGovernanceActionsCategory.tsx b/govtool/frontend/src/pages/DashboardGovernanceActionsCategory.tsx
index 9084bf070..fb366fc67 100644
--- a/govtool/frontend/src/pages/DashboardGovernanceActionsCategory.tsx
+++ b/govtool/frontend/src/pages/DashboardGovernanceActionsCategory.tsx
@@ -8,7 +8,6 @@ import { useCardano, useDataActionsBar } from "@context";
import {
DataActionsBar,
EmptyStateGovernanceActionsCategory,
- GovernanceActionCard,
} from "@molecules";
import {
useFetchNextPageDetector,
@@ -23,6 +22,7 @@ import {
getProposalTypeLabel,
removeDuplicatedProposals,
} from "@utils";
+import { ValidatedGovernanceActionCard } from "@/components/organisms";
export const DashboardGovernanceActionsCategory = () => {
const { category } = useParams();
@@ -133,7 +133,7 @@ export const DashboardGovernanceActionsCategory = () => {
>
{mappedData.map((item) => (
- {
);
const proposal = (data ?? state)?.proposal;
+ const metadataStatus = useRef();
+ const { validateMetadata } = useValidateMutation();
+
+ useEffect(() => {
+ const validate = async () => {
+ const { status } = await validateMetadata({
+ standard: MetadataStandard.CIP108,
+ url: proposal?.url ?? "",
+ hash: proposal?.metadataHash ?? "",
+ });
+
+ metadataStatus.current = status;
+ };
+ validate();
+ }, [proposal?.url, proposal?.metadataHash]);
+
useEffect(() => {
const isProposalNotFound =
(error as AxiosError)?.response?.data ===
@@ -105,7 +122,7 @@ export const GovernanceActionDetails = () => {
elementOne={t("govActions.title")}
elementOnePath={PATHS.governanceActions}
elementTwo={proposal?.title ?? ""}
- isDataMissing={proposal?.metadataStatus ?? null}
+ isDataMissing={metadataStatus?.current ?? null}
/>
{
}}
onClick={() =>
navigate(
- state && state.openedFromCategoryPage
+ state?.openedFromCategoryPage
? generatePath(PATHS.governanceActionsCategory, {
category: state?.proposal?.type,
})
@@ -144,7 +161,7 @@ export const GovernanceActionDetails = () => {
) : proposal ? (
diff --git a/govtool/frontend/src/pages/GovernanceActionsCategory.tsx b/govtool/frontend/src/pages/GovernanceActionsCategory.tsx
index 51d982f79..7eda23034 100644
--- a/govtool/frontend/src/pages/GovernanceActionsCategory.tsx
+++ b/govtool/frontend/src/pages/GovernanceActionsCategory.tsx
@@ -8,9 +8,8 @@ import { useCardano, useDataActionsBar } from "@context";
import {
DataActionsBar,
EmptyStateGovernanceActionsCategory,
- GovernanceActionCard,
} from "@molecules";
-import { Footer, TopNav } from "@organisms";
+import { Footer, TopNav, ValidatedGovernanceActionCard } from "@organisms";
import {
useGetProposalsInfiniteQuery,
useFetchNextPageDetector,
@@ -139,7 +138,7 @@ export const GovernanceActionsCategory = () => {
>
{mappedData.map((item) => (
- {
saveScrollPosition();
diff --git a/govtool/frontend/src/pages/ProposalDiscussion.tsx b/govtool/frontend/src/pages/ProposalDiscussion.tsx
index b69836df9..396b6eee8 100644
--- a/govtool/frontend/src/pages/ProposalDiscussion.tsx
+++ b/govtool/frontend/src/pages/ProposalDiscussion.tsx
@@ -6,6 +6,7 @@ import {
useCardano,
useGovernanceActions,
useProposalDiscussion,
+ useSnackbar,
} from "@/context";
import { useValidateMutation } from "@/hooks/mutations";
import { useScreenDimension } from "@/hooks/useScreenDimension";
@@ -30,6 +31,7 @@ export const ProposalDiscussionPillar = () => {
const { fetchDRepVotingPowerList } = useGetDRepVotingPowerList();
const { username, setUsername } = useProposalDiscussion();
const { votingPower } = useGetAdaHolderVotingPowerQuery(context.stakeKey);
+ const snackbarContext = useSnackbar();
return (
{
setUsername={setUsername}
epochParams={epochParams}
votingPower={votingPower}
+ {...snackbarContext}
/>
diff --git a/govtool/frontend/src/services/requests/getDRepList.ts b/govtool/frontend/src/services/requests/getDRepList.ts
index b61707411..12270b7ea 100644
--- a/govtool/frontend/src/services/requests/getDRepList.ts
+++ b/govtool/frontend/src/services/requests/getDRepList.ts
@@ -3,7 +3,6 @@ import {
type DRepStatus,
type DRepListSort,
DRepData,
- DrepDataDTO,
} from "@models";
import { API } from "../API";
import { dRepSearchPhraseProcessor, mapDtoToDrep } from "@/utils";
@@ -27,7 +26,7 @@ export const getDRepList = async ({
}: GetDRepListArguments): Promise> => {
const searchPhrase = await dRepSearchPhraseProcessor(rawSearchPhrase);
- const response = await API.get>("/drep/list", {
+ const response = await API.get>("/drep/list", {
params: {
page,
pageSize,
diff --git a/govtool/frontend/src/services/requests/getDRepVotes.ts b/govtool/frontend/src/services/requests/getDRepVotes.ts
index 1b2bbf1e6..008e720bf 100644
--- a/govtool/frontend/src/services/requests/getDRepVotes.ts
+++ b/govtool/frontend/src/services/requests/getDRepVotes.ts
@@ -1,6 +1,5 @@
-import { VotedProposal, VotedProposalDTO } from "@models";
+import { VotedProposal } from "@models";
import { API } from "../API";
-import { mapDtoToProposal } from "@/utils";
type GetDRepVotesParams = {
type?: string[];
@@ -17,14 +16,7 @@ export const getDRepVotes = async ({
}): Promise => {
const urlBase = `/drep/getVotes/${dRepID}`;
- const { data } = await API.get(urlBase, { params });
+ const { data } = await API.get(urlBase, { params });
- const validatedData = await Promise.all(
- data.map(async (votedProposal) => ({
- ...votedProposal,
- proposal: await mapDtoToProposal(votedProposal.proposal),
- }))
- );
-
- return validatedData;
+ return data;
};
diff --git a/govtool/frontend/src/services/requests/getProposal.ts b/govtool/frontend/src/services/requests/getProposal.ts
index c82aa6199..65744d6d0 100644
--- a/govtool/frontend/src/services/requests/getProposal.ts
+++ b/govtool/frontend/src/services/requests/getProposal.ts
@@ -1,5 +1,5 @@
-import { VotedProposal, VotedProposalDTO } from "@/models";
-import { decodeCIP129Identifier, mapDtoToProposal } from "@/utils";
+import { VotedProposal } from "@/models";
+import { decodeCIP129Identifier } from "@/utils";
import { API } from "../API";
@@ -15,12 +15,9 @@ export const getProposal = async (
const encodedHash = encodeURIComponent(proposalId);
- const { data } = await API.get(
+ const { data } = await API.get(
`/proposal/get/${encodedHash}?drepId=${drepId}`,
);
- return {
- ...data,
- proposal: await mapDtoToProposal(data.proposal),
- };
+ return data;
};
diff --git a/govtool/frontend/src/services/requests/getProposals.ts b/govtool/frontend/src/services/requests/getProposals.ts
index 9d09751be..765fd211c 100644
--- a/govtool/frontend/src/services/requests/getProposals.ts
+++ b/govtool/frontend/src/services/requests/getProposals.ts
@@ -1,11 +1,7 @@
-import { Infinite, ProposalData, ProposalDataDTO } from "@models";
+import { Infinite, ProposalData } from "@models";
import { API } from "../API";
-import {
- decodeCIP129Identifier,
- getFullGovActionId,
- mapDtoToProposal,
-} from "@/utils";
+import { decodeCIP129Identifier, getFullGovActionId } from "@/utils";
export type GetProposalsArguments = {
dRepID?: string;
@@ -34,7 +30,7 @@ export const getProposals = async ({
return rawSearchPhrase;
})();
- const response = await API.get>("/proposal/list", {
+ const response = await API.get>("/proposal/list", {
params: {
page,
pageSize,
@@ -47,14 +43,5 @@ export const getProposals = async ({
},
});
- const validatedResponse = {
- ...response.data,
- elements: await Promise.all(
- response.data.elements.map((proposalDTO) =>
- mapDtoToProposal(proposalDTO),
- ),
- ),
- };
-
- return validatedResponse;
+ return response.data;
};
diff --git a/govtool/frontend/src/stories/DRepDetailsCard.stories.ts b/govtool/frontend/src/stories/DRepDetailsCard.stories.ts
index c91b396d3..17754f8c9 100644
--- a/govtool/frontend/src/stories/DRepDetailsCard.stories.ts
+++ b/govtool/frontend/src/stories/DRepDetailsCard.stories.ts
@@ -1,6 +1,6 @@
import { ComponentProps } from "react";
import type { Meta, StoryObj } from "@storybook/react";
-import { DRepData, DRepStatus, MetadataValidationStatus } from "@models";
+import { DRepData, DRepStatus } from "@models";
import { DRepDetailsCard } from "@organisms";
const meta = {
@@ -22,33 +22,40 @@ const meta = {
votingPower: 1000000,
paymentAddress: "examplePaymentAddress",
givenName: "John Smith",
- objectives: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum ornare pellentesque hendrerit. Pellentesque et placerat ex. Curabitur vitae pharetra ligula. Nullam euismod, odio sit amet suscipit facilisis, neque erat ultricies velit, sed rutrum neque nisi ac dui. Donec lobortis metus pulvinar varius gravida. Duis blandit, tortor non placerat commodo, metus lorem aliquam augue, eget ultricies nunc massa eu arcu. Etiam pellentesque urna nisl, facilisis placerat elit congue quis. Nulla quis dolor ac eros ullamcorper convallis ac ut enim. Proin faucibus urna at mi blandit, ut gravida sapien lacinia. Sed pretium, magna non tempor sollicitudin, tellus odio efficitur enim, ut feugiat nisi ligula non dolor. Fusce volutpat condimentum arcu, eu tempus neque convallis non. Suspendisse mattis sit amet libero et fringilla. Suspendisse eget erat eu nisl feugiat varius. Interdum et malesuada fames ac ante ipsum primis in faucibus. Curabitur vehicula eleifend lectus, vel eleifend felis vestibulum.",
- motivations: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras semper tortor ullamcorper volutpat vehicula. Duis varius orci a elit luctus, in fringilla nisl fringilla. Fusce pellentesque convallis dapibus. In hac habitasse platea dictumst. Nunc efficitur ipsum at ipsum blandit, ac eleifend purus pulvinar. Pellentesque orci quam, interdum eget massa id, sollicitudin lacinia turpis. Nullam lectus quam, congue commodo sollicitudin in, pretium sit amet metus. Integer pretium, odio eu dictum posuere.",
- qualifications: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc porta iaculis sodales. Praesent non nisi fermentum, porta sem in, porta arcu. In dignissim pulvinar est eu dignissim. Duis vitae vehicula dui. Praesent posuere egestas lacus, at pulvinar elit tempus ut. Etiam vulputate, lorem in accumsan.",
- references: [{
- "@type": "Link",
- label: "Link Reference",
- uri: "https://example.com/",
- }, {
- "@type": "Link",
- label: "Another Link Reference",
- uri: "https://example.com/",
- }, {
- "@type": "Identity",
- label: "Identity Reference",
- uri: "https://example.com/",
- }, {
- "@type": "GovernanceMetadata",
- label: "GovernanceMetadata Reference",
- uri: "https://example.com/",
- }, {
- "@type": "Other",
- label: "Other Reference",
- uri: "https://example.com/",
- }],
+ objectives:
+ "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum ornare pellentesque hendrerit. Pellentesque et placerat ex. Curabitur vitae pharetra ligula. Nullam euismod, odio sit amet suscipit facilisis, neque erat ultricies velit, sed rutrum neque nisi ac dui. Donec lobortis metus pulvinar varius gravida. Duis blandit, tortor non placerat commodo, metus lorem aliquam augue, eget ultricies nunc massa eu arcu. Etiam pellentesque urna nisl, facilisis placerat elit congue quis. Nulla quis dolor ac eros ullamcorper convallis ac ut enim. Proin faucibus urna at mi blandit, ut gravida sapien lacinia. Sed pretium, magna non tempor sollicitudin, tellus odio efficitur enim, ut feugiat nisi ligula non dolor. Fusce volutpat condimentum arcu, eu tempus neque convallis non. Suspendisse mattis sit amet libero et fringilla. Suspendisse eget erat eu nisl feugiat varius. Interdum et malesuada fames ac ante ipsum primis in faucibus. Curabitur vehicula eleifend lectus, vel eleifend felis vestibulum.",
+ motivations:
+ "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras semper tortor ullamcorper volutpat vehicula. Duis varius orci a elit luctus, in fringilla nisl fringilla. Fusce pellentesque convallis dapibus. In hac habitasse platea dictumst. Nunc efficitur ipsum at ipsum blandit, ac eleifend purus pulvinar. Pellentesque orci quam, interdum eget massa id, sollicitudin lacinia turpis. Nullam lectus quam, congue commodo sollicitudin in, pretium sit amet metus. Integer pretium, odio eu dictum posuere.",
+ qualifications:
+ "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc porta iaculis sodales. Praesent non nisi fermentum, porta sem in, porta arcu. In dignissim pulvinar est eu dignissim. Duis vitae vehicula dui. Praesent posuere egestas lacus, at pulvinar elit tempus ut. Etiam vulputate, lorem in accumsan.",
+ references: [
+ {
+ "@type": "Link",
+ label: "Link Reference",
+ uri: "https://example.com/",
+ },
+ {
+ "@type": "Link",
+ label: "Another Link Reference",
+ uri: "https://example.com/",
+ },
+ {
+ "@type": "Identity",
+ label: "Identity Reference",
+ uri: "https://example.com/",
+ },
+ {
+ "@type": "GovernanceMetadata",
+ label: "GovernanceMetadata Reference",
+ uri: "https://example.com/",
+ },
+ {
+ "@type": "Other",
+ label: "Other Reference",
+ uri: "https://example.com/",
+ },
+ ],
doNotList: false,
- metadataStatus: null,
- metadataValid: true,
} as DRepData,
},
tags: ["autodocs"],
@@ -93,12 +100,3 @@ export const UserNotConnected: Story = {
isConnected: false,
},
};
-
-export const InvalidData: Story = {
- args: {
- dRepData: {
- ...meta.args.dRepData,
- metadataStatus: MetadataValidationStatus.INCORRECT_FORMAT,
- },
- },
-};
diff --git a/govtool/frontend/src/stories/GovernanceAction.stories.ts b/govtool/frontend/src/stories/GovernanceAction.stories.ts
index 3119c83c5..085e69df4 100644
--- a/govtool/frontend/src/stories/GovernanceAction.stories.ts
+++ b/govtool/frontend/src/stories/GovernanceAction.stories.ts
@@ -1,4 +1,3 @@
-import { MetadataValidationStatus } from "@models";
import {
expect,
screen,
@@ -16,6 +15,7 @@ import {
} from "@utils";
import { GovernanceActionCard } from "@/components/molecules";
import { GovernanceActionType } from "@/types/governanceAction";
+import { MetadataValidationStatus } from "@/models";
const meta = {
title: "Example/GovernanceActionCard",
@@ -30,8 +30,8 @@ export default meta;
type Story = StoryObj;
-const commonArgs = {
- about: "About this Governance Action",
+const commonArgs: Story["args"] = {
+ abstract: "About this Governance Action",
createdDate: "1970-01-01T00:00:00Z",
createdEpochNo: 302,
expiryDate: "1970-02-01T00:00:00Z",
@@ -42,8 +42,6 @@ const commonArgs = {
title: "Example title",
txHash: "sad78afdsf7jasd98d",
type: GovernanceActionType.InfoAction,
- metadataValid: true,
- metadataStatus: null,
dRepYesVotes: 1,
dRepNoVotes: 0,
dRepAbstainVotes: 0,
@@ -56,6 +54,8 @@ const commonArgs = {
protocolParams: null,
prevGovActionIndex: null,
prevGovActionTxHash: null,
+ metadataHash: "exampleMetadataHash",
+ url: "https://exampleMetadataUrl.com",
};
const cip129GovActionId = encodeCIP129Identifier({
@@ -102,10 +102,7 @@ export const GovernanceActionCardComponent: Story = {
};
export const GovernanceActionCardIsLoading: Story = {
- args: {
- ...commonArgs,
- inProgress: true,
- },
+ args: { ...commonArgs, inProgress: true },
play: async ({ canvasElement }) => {
const canvas = within(canvasElement);
await expect(canvas.getByText(/in progress/i)).toBeVisible();
@@ -116,7 +113,6 @@ export const GovernanceActionCardDataMissing: Story = {
args: {
...commonArgs,
metadataStatus: MetadataValidationStatus.URL_NOT_FOUND,
- metadataValid: false,
},
play: async ({ canvasElement }) => {
const canvas = within(canvasElement);
@@ -135,8 +131,7 @@ export const GovernanceActionCardDataMissing: Story = {
export const GovernanceActionCardIncorectFormat: Story = {
args: {
...commonArgs,
- metadataStatus: MetadataValidationStatus.INVALID_JSONLD,
- metadataValid: false,
+ metadataStatus: MetadataValidationStatus.INCORRECT_FORMAT,
},
play: async ({ canvasElement }) => {
const canvas = within(canvasElement);
@@ -158,7 +153,6 @@ export const GovernanceActionCardNotVerifiable: Story = {
args: {
...commonArgs,
metadataStatus: MetadataValidationStatus.INVALID_HASH,
- metadataValid: false,
},
play: async ({ canvasElement }) => {
const canvas = within(canvasElement);
diff --git a/govtool/frontend/src/stories/GovernanceActionDetailsCard.stories.ts b/govtool/frontend/src/stories/GovernanceActionDetailsCard.stories.ts
index 9d62c35f9..67e6001f7 100644
--- a/govtool/frontend/src/stories/GovernanceActionDetailsCard.stories.ts
+++ b/govtool/frontend/src/stories/GovernanceActionDetailsCard.stories.ts
@@ -57,8 +57,6 @@ const commonArgs = {
prevGovActionIndex: null,
prevGovActionTxHash: null,
metadataHash: "exampleMetadataHash",
- metadataStatus: null,
- metadataValid: true,
references: [
{
"@type": "Reference",
@@ -118,6 +116,7 @@ async function assertGovActionDetails(
export const GovernanceActionDetailsCardComponent: Story = {
args: {
...commonArgs,
+ isDataMissing: undefined,
proposal: {
...commonArgs.proposal,
abstract: "Example about section",
@@ -159,6 +158,7 @@ export const GovernanceActionDetailsDrep: Story = {
...commonArgs,
isDashboard: true,
isVoter: true,
+ isDataMissing: undefined,
proposal: {
...commonArgs.proposal,
abstract: "Example about section",
diff --git a/govtool/frontend/src/stories/GovernanceActionVoted.stories.ts b/govtool/frontend/src/stories/GovernanceActionVoted.stories.ts
index 6b43f2452..d5eb8de53 100644
--- a/govtool/frontend/src/stories/GovernanceActionVoted.stories.ts
+++ b/govtool/frontend/src/stories/GovernanceActionVoted.stories.ts
@@ -4,6 +4,7 @@ import { expect, userEvent, waitFor, within, screen } from "@storybook/test";
import { GovernanceVotedOnCard } from "@molecules";
import { formatDisplayDate, getProposalTypeNoEmptySpaces } from "@/utils";
import { GovernanceActionType } from "@/types/governanceAction";
+import { MetadataValidationStatus } from "@/models/metadataValidation";
const meta = {
title: "Example/GovernanceVotedOnCard",
@@ -68,8 +69,6 @@ export const GovernanceVotedOnCardComponent: Story = {
proposal: {
createdEpochNo: 232,
expiryEpochNo: 323,
- metadataStatus: null,
- metadataValid: true,
createdDate: "1970-01-01T00:00:00Z",
expiryDate: "1970-02-01T00:00:00Z",
id: "exampleId",
@@ -115,8 +114,6 @@ export const GovernanceVotedOnCardAbstain: Story = {
proposal: {
createdEpochNo: 232,
expiryEpochNo: 323,
- metadataStatus: null,
- metadataValid: true,
createdDate: "1970-01-01T00:00:00Z",
expiryDate: "1970-02-01T00:00:00Z",
id: "exampleId",
@@ -163,8 +160,6 @@ export const GovernanceVotedOnCardYes: Story = {
proposal: {
createdEpochNo: 232,
expiryEpochNo: 323,
- metadataStatus: null,
- metadataValid: true,
createdDate: "1970-01-01T00:00:00Z",
expiryDate: "1970-02-01T00:00:00Z",
id: "exampleId",
@@ -211,8 +206,6 @@ export const GovernanceVotedOnCardNo: Story = {
proposal: {
createdEpochNo: 232,
expiryEpochNo: 323,
- metadataStatus: null,
- metadataValid: true,
createdDate: "1970-01-01T00:00:00Z",
expiryDate: "1970-02-01T00:00:00Z",
id: "exampleId",
@@ -242,3 +235,91 @@ export const GovernanceVotedOnCardNo: Story = {
expect(canvas.getByText(/no/i)).toBeInTheDocument();
},
};
+
+export const GovernanceVotedOnCardDataFormattedIncorrectly: Story = {
+ args: {
+ votedProposal: {
+ vote: {
+ date: new Date().toLocaleDateString(),
+ drepId: "drep1_exampledrepid1231231",
+ epochNo: 222,
+ metadataHash: "ababa1ababab1abababa1ababab1ababa1aba1",
+ proposalId: "exampleproposalid12dsadasdasda",
+ url: "https://exampleurl.com",
+ vote: "no",
+ txHash: "dwq78dqw78qwd78wdq78dqw78dqw",
+ },
+ proposal: {
+ createdEpochNo: 232,
+ expiryEpochNo: 323,
+ createdDate: "1970-01-01T00:00:00Z",
+ expiryDate: "1970-02-01T00:00:00Z",
+ id: "exampleId",
+ type: GovernanceActionType.InfoAction,
+ index: 1,
+ txHash: "exampleHash",
+ url: "https://example.com",
+ metadataHash: "exampleHash",
+ dRepYesVotes: 1,
+ dRepNoVotes: 0,
+ dRepAbstainVotes: 2,
+ poolYesVotes: 1,
+ poolNoVotes: 0,
+ poolAbstainVotes: 2,
+ ccYesVotes: 1,
+ ccNoVotes: 0,
+ ccAbstainVotes: 2,
+ protocolParams: null,
+ prevGovActionIndex: null,
+ prevGovActionTxHash: null,
+ },
+ },
+ metadataStatus: MetadataValidationStatus.INCORRECT_FORMAT,
+ },
+ play: async ({ canvasElement }) => {
+ const canvas = within(canvasElement);
+ expect(canvas.getByText(/Data Formatted Incorrectly/i)).toBeInTheDocument();
+ },
+};
+
+export const GovernanceVotedOnCardValidating: Story = {
+ args: {
+ votedProposal: {
+ vote: {
+ date: new Date().toLocaleDateString(),
+ drepId: "drep1_exampledrepid1231231",
+ epochNo: 222,
+ metadataHash: "ababa1ababab1abababa1ababab1ababa1aba1",
+ proposalId: "exampleproposalid12dsadasdasda",
+ url: "https://exampleurl.com",
+ vote: "no",
+ txHash: "dwq78dqw78qwd78wdq78dqw78dqw",
+ },
+ proposal: {
+ createdEpochNo: 232,
+ expiryEpochNo: 323,
+ createdDate: "1970-01-01T00:00:00Z",
+ expiryDate: "1970-02-01T00:00:00Z",
+ id: "exampleId",
+ type: GovernanceActionType.InfoAction,
+ index: 1,
+ txHash: "exampleHash",
+ url: "https://example.com",
+ metadataHash: "exampleHash",
+ dRepYesVotes: 1,
+ dRepNoVotes: 0,
+ dRepAbstainVotes: 2,
+ poolYesVotes: 1,
+ poolNoVotes: 0,
+ poolAbstainVotes: 2,
+ ccYesVotes: 1,
+ ccNoVotes: 0,
+ ccAbstainVotes: 2,
+ protocolParams: null,
+ prevGovActionIndex: null,
+ prevGovActionTxHash: null,
+ },
+ },
+ isValidating: true,
+ },
+};
diff --git a/govtool/frontend/src/utils/generateJsonld.ts b/govtool/frontend/src/utils/generateJsonld.ts
index b2481c762..1ed0700ba 100644
--- a/govtool/frontend/src/utils/generateJsonld.ts
+++ b/govtool/frontend/src/utils/generateJsonld.ts
@@ -19,6 +19,7 @@ export const generateJsonld = async <
const doc = {
"@context": context,
hashAlgorithm: "blake2b-256",
+ authors: [],
body,
};
diff --git a/govtool/frontend/src/utils/generateMetadataBody.ts b/govtool/frontend/src/utils/generateMetadataBody.ts
index 03ef7a68a..bc35bcbd0 100644
--- a/govtool/frontend/src/utils/generateMetadataBody.ts
+++ b/govtool/frontend/src/utils/generateMetadataBody.ts
@@ -17,47 +17,51 @@ export const generateMetadataBody = async ({
data,
acceptedKeys,
}: MetadataConfig) => {
- const filteredData = Object.entries(data)
- .filter(([key, value]) => value && acceptedKeys.includes(key))
- .map(([key, value]) => [key, value]);
-
- const references = data?.references
- ? // uri should not be optional. It is just not yet supported on govtool
- (data.references as Array>)
- .filter((link) => link.uri)
- .map((link) => ({
- "@type": link["@type"] ?? "Other",
- label: link.label ?? "Label",
- uri: link.uri,
- }))
- : undefined;
-
- const isUrl = (url?: unknown) => URL_REGEX.test(url as string);
- let image;
-
- if (isUrl(data?.image)) {
- image = {
- "@type": "ImageObject",
- contentUrl: data.image,
- sha256: await getImageSha(data.image as string),
- };
- } else {
- image = data?.image
- ? {
- "@type": "ImageObject",
- contentUrl: data.image,
- }
+ try {
+ const filteredData = Object.entries(data)
+ .filter(([key, value]) => value && acceptedKeys.includes(key))
+ .map(([key, value]) => [key, value]);
+
+ const references = data?.references
+ ? // uri should not be optional. It is just not yet supported on govtool
+ (data.references as Array>)
+ .filter((link) => link.uri)
+ .map((link) => ({
+ "@type": link["@type"] ?? "Other",
+ label: link.label ?? "Label",
+ uri: link.uri,
+ }))
: undefined;
- }
- const body = Object.fromEntries(filteredData);
- if (references?.length) {
- body.references = references;
- }
+ const isUrl = (url?: unknown) => URL_REGEX.test(url as string);
+ let image;
- if (image) {
- body.image = image;
- }
+ if (isUrl(data?.image)) {
+ image = {
+ "@type": "ImageObject",
+ contentUrl: data.image,
+ sha256: await getImageSha(data.image as string),
+ };
+ } else {
+ image = data?.image
+ ? {
+ "@type": "ImageObject",
+ contentUrl: data.image,
+ }
+ : undefined;
+ }
- return body;
+ const body = Object.fromEntries(filteredData);
+ if (references?.length) {
+ body.references = references;
+ }
+
+ if (image) {
+ body.image = image;
+ }
+
+ return body;
+ } catch (error) {
+ console.error({ error });
+ }
};
diff --git a/govtool/frontend/src/utils/index.ts b/govtool/frontend/src/utils/index.ts
index dfeaca81f..38c403872 100644
--- a/govtool/frontend/src/utils/index.ts
+++ b/govtool/frontend/src/utils/index.ts
@@ -27,7 +27,6 @@ export * from "./jsonUtils";
export * from "./localStorage";
export * from "./mapArrayToObjectByKeys";
export * from "./mapDtoToDrep";
-export * from "./mapDtoToProposal";
export * from "./numberValidation";
export * from "./openInNewTab";
export * from "./removeDuplicatedProposals";
diff --git a/govtool/frontend/src/utils/isValidFormat.ts b/govtool/frontend/src/utils/isValidFormat.ts
index b203fcee7..dbb5a1c84 100644
--- a/govtool/frontend/src/utils/isValidFormat.ts
+++ b/govtool/frontend/src/utils/isValidFormat.ts
@@ -5,6 +5,7 @@ import {
} from "@emurgo/cardano-serialization-lib-asmjs";
import i18n from "@/i18n";
import { adaHandleService } from "@/services/AdaHandle";
+import { getImageSha } from "./getImageSha";
export const URL_REGEX =
/^(?:(?:https?:\/\/)?(?:\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}|(?:[a-zA-Z0-9-]+\.)+[a-zA-Z]{2,})(?:\/[^\s]*)?)|(?:ipfs:\/\/(?:[a-zA-Z0-9]+(?:\/[a-zA-Z0-9._-]+)*))$|^$/;
@@ -76,3 +77,15 @@ export async function isDRepView(view?: string) {
}
return i18n.t("forms.errors.mustBeDRepView");
}
+
+export async function isValidImageUrl(url: string) {
+ if (!url.length) return false;
+ try {
+ if (URL_REGEX.test(url)) {
+ await getImageSha(url);
+ }
+ return true;
+ } catch (error) {
+ return i18n.t("forms.errors.couldNotGenerateImageSha");
+ }
+}
diff --git a/govtool/frontend/src/utils/mapDtoToDrep.ts b/govtool/frontend/src/utils/mapDtoToDrep.ts
index b0f1e4b1f..985bd67b9 100644
--- a/govtool/frontend/src/utils/mapDtoToDrep.ts
+++ b/govtool/frontend/src/utils/mapDtoToDrep.ts
@@ -1,30 +1,11 @@
-import {
- DRepData,
- DRepMetadata,
- DrepDataDTO,
- MetadataStandard,
-} from "@/models";
-import { postValidate } from "@/services";
+import { DRepData } from "@/models";
import { fixViewForScriptBasedDRep } from "./dRep";
const imageFetchDefaultOptions: RequestInit = {
mode: "no-cors",
};
-export const mapDtoToDrep = async (dto: DrepDataDTO): Promise => {
- const emptyMetadata = {
- paymentAddress: null,
- givenName: "",
- imageUrl: null,
- objectives: null,
- motivations: null,
- qualifications: null,
- references: [],
- doNotList: false,
- metadataStatus: null,
- metadataValid: true,
- };
-
+export const mapDtoToDrep = async (dto: DRepData): Promise => {
// DBSync contains wrong representation of DRep view for script based DReps
const view = fixViewForScriptBasedDRep(dto.view, dto.isScriptBased);
@@ -62,27 +43,8 @@ export const mapDtoToDrep = async (dto: DrepDataDTO): Promise => {
}
});
}
-
- if (dto.metadataHash && dto.url) {
- const validationResponse = await postValidate({
- url: dto.url,
- hash: dto.metadataHash,
- standard: MetadataStandard.CIP119,
- });
- return {
- ...dto,
- ...emptyMetadata,
- ...validationResponse.metadata,
- metadataStatus: validationResponse.status || null,
- metadataValid: validationResponse.valid,
- image: isIPFSImage ? base64Image : dto.imageUrl,
- view,
- };
- }
-
return {
...dto,
- ...emptyMetadata,
view,
image: isIPFSImage ? base64Image : dto.imageUrl,
};
diff --git a/govtool/frontend/src/utils/mapDtoToProposal.ts b/govtool/frontend/src/utils/mapDtoToProposal.ts
deleted file mode 100644
index 9f3635350..000000000
--- a/govtool/frontend/src/utils/mapDtoToProposal.ts
+++ /dev/null
@@ -1,36 +0,0 @@
-import {
- MetadataStandard,
- ProposalData,
- ProposalDataDTO,
- ProposalMetadata,
-} from "@/models";
-import { postValidate } from "@/services";
-
-export const mapDtoToProposal = async (
- dto: ProposalDataDTO,
-): Promise => {
- if (dto.url && dto.metadataHash) {
- const validationResponse = await postValidate({
- url: dto.url,
- hash: dto.metadataHash,
- standard: MetadataStandard.CIP108,
- });
-
- return {
- ...dto,
- title: dto.title || validationResponse.metadata?.title,
- abstract: dto.abstract || validationResponse.metadata?.abstract,
- motivation: dto.motivation || validationResponse.metadata?.motivation,
- rationale: dto.rationale || validationResponse.metadata?.rationale,
- references: validationResponse.metadata?.references || [],
- metadataStatus: validationResponse.status || null,
- metadataValid: validationResponse.valid,
- };
- }
-
- return {
- ...dto,
- metadataStatus: null,
- metadataValid: true,
- };
-};
diff --git a/govtool/frontend/src/utils/tests/dRep.test.ts b/govtool/frontend/src/utils/tests/dRep.test.ts
index 66f41fe63..00a06a4f2 100644
--- a/govtool/frontend/src/utils/tests/dRep.test.ts
+++ b/govtool/frontend/src/utils/tests/dRep.test.ts
@@ -15,8 +15,6 @@ const EXAMPLE_DREP: DRepData = {
type: "DRep" as TDRepType,
givenName: "name",
references: [],
- metadataStatus: null,
- metadataValid: true,
latestRegistrationDate: "2024-07-10",
paymentAddress: null,
objectives: null,
diff --git a/govtool/frontend/src/utils/tests/removeDuplicatedProposals.test.ts b/govtool/frontend/src/utils/tests/removeDuplicatedProposals.test.ts
index 29260ed57..aa9adee76 100644
--- a/govtool/frontend/src/utils/tests/removeDuplicatedProposals.test.ts
+++ b/govtool/frontend/src/utils/tests/removeDuplicatedProposals.test.ts
@@ -30,8 +30,6 @@ const uniqueProposals: ProposalData[] = [
ccAbstainVotes: 4324,
title: "Proposal 1322 Title",
abstract: "This is about Proposal 1322",
- metadataStatus: null,
- metadataValid: false,
motivation: "Motivation behind Proposal 1322",
rationale: "Rationale for Proposal 1322",
protocolParams: null,
@@ -65,8 +63,6 @@ const uniqueProposals: ProposalData[] = [
ccAbstainVotes: 4324,
title: "Proposal 1338 Title",
abstract: "This is about Proposal 1338",
- metadataStatus: null,
- metadataValid: false,
motivation: "Motivation behind Proposal 1338",
rationale: "Rationale for Proposal 1338",
protocolParams: null,
@@ -100,8 +96,6 @@ const uniqueProposals: ProposalData[] = [
ccAbstainVotes: 4324,
title: "Proposal 1335 Title",
abstract: "This is about Proposal 1335",
- metadataStatus: null,
- metadataValid: false,
motivation: "Motivation behind Proposal 1335",
rationale: "Rationale for Proposal 1335",
protocolParams: null,
diff --git a/govtool/frontend/yarn.lock b/govtool/frontend/yarn.lock
index f22212f21..dc1af3026 100644
--- a/govtool/frontend/yarn.lock
+++ b/govtool/frontend/yarn.lock
@@ -1377,10 +1377,10 @@
resolved "https://registry.npmjs.org/@emurgo/cardano-serialization-lib-asmjs/-/cardano-serialization-lib-asmjs-14.1.1.tgz"
integrity sha512-Q2HVpPRt417Quxv3qagGWbkJQU8SiQCl1K/344ZtQMwsLoqTfRlCNzmSWMBN7jyBxbtKoh+vdbSiLqwG1NAjYg==
-"@esbuild/linux-x64@0.25.0":
+"@esbuild/darwin-arm64@0.25.0":
version "0.25.0"
- resolved "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.0.tgz"
- integrity sha512-9yl91rHw/cpwMCNytUDxwj2XjFpxML0y9HAOH9pNVQDpQrBxHy01Dx+vaMu0N1CKa/RzBD2hB4u//nfc+Sd3Cw==
+ resolved "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.0.tgz"
+ integrity sha512-mVwdUb5SRkPayVadIOI78K7aAnPamoeFR2bT5nszFUZ9P8UpK4ratOdYbZZXYSqPKMHfS1wdHCJk1P1EZpRdvw==
"@eslint-community/eslint-utils@^4.2.0", "@eslint-community/eslint-utils@^4.4.0":
version "4.4.1"
@@ -1492,10 +1492,10 @@
resolved "https://registry.npmjs.org/@inquirer/type/-/type-3.0.4.tgz"
integrity sha512-2MNFrDY8jkFYc9Il9DgLsHhMzuHnOYM1+CUYVWbzu9oT0hC7V7EcYvdCKeoll/Fcci04A+ERZ9wcc7cQ8lTkIA==
-"@intersect.mbo/govtool-outcomes-pillar-ui@1.3.0":
- version "1.3.0"
- resolved "https://registry.npmjs.org/@intersect.mbo/govtool-outcomes-pillar-ui/-/govtool-outcomes-pillar-ui-1.3.0.tgz"
- integrity sha512-6+H+QG8kyM2UUEycNsjrF1K5+UGUw6+wy7gRxlyOtFjIrZ9CUdTfwwyD1hrh+g55awZ4t+EmQgYB00An0iXOag==
+"@intersect.mbo/govtool-outcomes-pillar-ui@1.4.0":
+ version "1.4.0"
+ resolved "https://registry.npmjs.org/@intersect.mbo/govtool-outcomes-pillar-ui/-/govtool-outcomes-pillar-ui-1.4.0.tgz"
+ integrity sha512-iSg6FzeUW4F3KSQDcHCytggCG68Q4OKUzQa8yNMSPVAuM6w5I6LhaqEYRO8x02G8WPyE+8W+Q9m3SCFea59osg==
dependencies:
"@fontsource/poppins" "^5.0.14"
"@intersect.mbo/intersectmbo.org-icons-set" "^1.0.8"
@@ -1512,10 +1512,10 @@
resolved "https://registry.npmjs.org/@intersect.mbo/intersectmbo.org-icons-set/-/intersectmbo.org-icons-set-1.1.0.tgz"
integrity sha512-sjKEtnK9eLYH/8kCD0YRQCms3byFA/tnSsei9NHTZbBYX9sBpeX6ErfR0sKYjOSxQOxl4FumX9D0X+vHIqxo8g==
-"@intersect.mbo/pdf-ui@0.7.0-beta-16":
- version "0.7.0-beta-16"
- resolved "https://registry.npmjs.org/@intersect.mbo/pdf-ui/-/pdf-ui-0.7.0-beta-16.tgz"
- integrity sha512-2I7BSg+5FDGhlvwLdZk0teVhtPMRQ1uDWKQiwobIF41cM0b+iT2CJMDL5MJk6tsM2/2JBbOEev9VrsHSanrCVA==
+"@intersect.mbo/pdf-ui@0.7.0-beta-19":
+ version "0.7.0-beta-19"
+ resolved "https://registry.npmjs.org/@intersect.mbo/pdf-ui/-/pdf-ui-0.7.0-beta-19.tgz"
+ integrity sha512-7VxTZos1biINze2eijXX1qJ5zSlAEIbtbCbH12+9NPSfkRFHty4pZphgCka0/res/mI/wU6TNcweHnomjyJ2vQ==
dependencies:
"@emurgo/cardano-serialization-lib-asmjs" "^12.0.0-beta.2"
"@fontsource/poppins" "^5.0.14"
@@ -2173,15 +2173,10 @@
resolved "https://registry.npmjs.org/@open-draft/until/-/until-2.1.0.tgz"
integrity sha512-U69T3ItWHvLwGg5eJ0n3I62nWuE6ilHlmz7zM0npLBRvPRd7e6NYmg54vvRtP5mZG7kZqZCFVdsTWo7BPtBujg==
-"@parcel/watcher-linux-x64-glibc@2.5.0":
- version "2.5.0"
- resolved "https://registry.npmjs.org/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.5.0.tgz"
- integrity sha512-d9AOkusyXARkFD66S6zlGXyzx5RvY+chTP9Jp0ypSTC9d4lzyRs9ovGf/80VCxjKddcUvnsGwCHWuF2EoPgWjw==
-
-"@parcel/watcher-linux-x64-musl@2.5.0":
+"@parcel/watcher-darwin-arm64@2.5.0":
version "2.5.0"
- resolved "https://registry.npmjs.org/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.5.0.tgz"
- integrity sha512-iqOC+GoTDoFyk/VYSFHwjHhYrk8bljW6zOhPuhi5t9ulqiYq1togGJB5e3PwYVFFfeVgc6pbz3JdQyDoBszVaA==
+ resolved "https://registry.npmjs.org/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.5.0.tgz"
+ integrity sha512-hyZ3TANnzGfLpRA2s/4U1kbw2ZI4qGxaRJbBH2DCSREFfubMswheh8TeiC1sGZ3z2jUf3s37P0BBlrD3sjVTUw==
"@parcel/watcher@^2.4.1":
version "2.5.0"
@@ -2294,15 +2289,10 @@
estree-walker "^2.0.2"
picomatch "^4.0.2"
-"@rollup/rollup-linux-x64-gnu@4.34.9":
+"@rollup/rollup-darwin-arm64@4.34.9":
version "4.34.9"
- resolved "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.34.9.tgz"
- integrity sha512-FwBHNSOjUTQLP4MG7y6rR6qbGw4MFeQnIBrMe161QGaQoBQLqSUEKlHIiVgF3g/mb3lxlxzJOpIBhaP+C+KP2A==
-
-"@rollup/rollup-linux-x64-musl@4.34.9":
- version "4.34.9"
- resolved "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.34.9.tgz"
- integrity sha512-cYRpV4650z2I3/s6+5/LONkjIz8MBeqrk+vPXV10ORBnshpn8S32bPqQ2Utv39jCiDcO2eJTuSlPXpnvmaIgRA==
+ resolved "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.34.9.tgz"
+ integrity sha512-0CY3/K54slrzLDjOA7TOjN1NuLKERBgk9nY5V34mhmuu673YNb+7ghaDUs6N0ujXR7fz5XaS5Aa6d2TNxZd0OQ==
"@rtsao/scc@^1.1.0":
version "1.1.0"
@@ -2905,15 +2895,10 @@
"@svgr/plugin-svgo" "^5.5.0"
loader-utils "^2.0.0"
-"@swc/core-linux-x64-gnu@1.9.3":
- version "1.9.3"
- resolved "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.9.3.tgz"
- integrity sha512-ivXXBRDXDc9k4cdv10R21ccBmGebVOwKXT/UdH1PhxUn9m/h8erAWjz5pcELwjiMf27WokqPgaWVfaclDbgE+w==
-
-"@swc/core-linux-x64-musl@1.9.3":
+"@swc/core-darwin-arm64@1.9.3":
version "1.9.3"
- resolved "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.9.3.tgz"
- integrity sha512-ILsGMgfnOz1HwdDz+ZgEuomIwkP1PHT6maigZxaCIuC6OPEhKE8uYna22uU63XvYcLQvZYDzpR3ms47WQPuNEg==
+ resolved "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.9.3.tgz"
+ integrity sha512-hGfl/KTic/QY4tB9DkTbNuxy5cV4IeejpPD4zo+Lzt4iLlDWIeANL4Fkg67FiVceNJboqg48CUX+APhDHO5G1w==
"@swc/core@*", "@swc/core@^1.5.22", "@swc/core@^1.7.26":
version "1.9.3"
@@ -6401,6 +6386,11 @@ escape-string-regexp@^4.0.0:
resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz"
integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==
+escape-string-regexp@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz"
+ integrity sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==
+
escodegen@^1.8.1:
version "1.14.3"
resolved "https://registry.npmjs.org/escodegen/-/escodegen-1.14.3.tgz"
@@ -7216,6 +7206,16 @@ fs@^0.0.1-security:
resolved "https://registry.npmjs.org/fs/-/fs-0.0.1-security.tgz"
integrity sha512-3XY9e1pP0CVEUCdj5BmfIZxRBTSDycnbqhIOGec9QYtmVH2fbLpj86CFWkrNOkt/Fvty4KZG5lTglL9j/gJ87w==
+fsevents@^2.3.2, fsevents@~2.3.2, fsevents@~2.3.3:
+ version "2.3.3"
+ resolved "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz"
+ integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==
+
+fsevents@2.3.2:
+ version "2.3.2"
+ resolved "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz"
+ integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==
+
function-bind@^1.1.2:
version "1.1.2"
resolved "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz"
@@ -9924,6 +9924,16 @@ mdast-util-definitions@^5.0.0:
"@types/unist" "^2.0.0"
unist-util-visit "^4.0.0"
+mdast-util-find-and-replace@^3.0.0:
+ version "3.0.2"
+ resolved "https://registry.npmjs.org/mdast-util-find-and-replace/-/mdast-util-find-and-replace-3.0.2.tgz"
+ integrity sha512-Tmd1Vg/m3Xz43afeNxDIhWRtFZgM2VLyaf4vSTYwudTyeuTneoL3qtWMA5jeLyz/O1vDJmmV4QuScFCA2tBPwg==
+ dependencies:
+ "@types/mdast" "^4.0.0"
+ escape-string-regexp "^5.0.0"
+ unist-util-is "^6.0.0"
+ unist-util-visit-parents "^6.0.0"
+
mdast-util-from-markdown@^1.0.0:
version "1.3.1"
resolved "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-1.3.1.tgz"
@@ -10015,6 +10025,14 @@ mdast-util-mdxjs-esm@^2.0.0:
mdast-util-from-markdown "^2.0.0"
mdast-util-to-markdown "^2.0.0"
+mdast-util-newline-to-break@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.npmjs.org/mdast-util-newline-to-break/-/mdast-util-newline-to-break-2.0.0.tgz"
+ integrity sha512-MbgeFca0hLYIEx/2zGsszCSEJJ1JSCdiY5xQxRcLDDGa8EPvlLPupJ4DSajbMPAnC0je8jfb9TiUATnxxrHUog==
+ dependencies:
+ "@types/mdast" "^4.0.0"
+ mdast-util-find-and-replace "^3.0.0"
+
mdast-util-phrasing@^4.0.0:
version "4.1.0"
resolved "https://registry.npmjs.org/mdast-util-phrasing/-/mdast-util-phrasing-4.1.0.tgz"
@@ -12619,6 +12637,15 @@ release-zalgo@^1.0.0:
dependencies:
es6-error "^4.0.1"
+remark-breaks@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.npmjs.org/remark-breaks/-/remark-breaks-4.0.0.tgz"
+ integrity sha512-IjEjJOkH4FuJvHZVIW0QCDWxcG96kCq7An/KVH2NfJe6rKZU2AsHeB3OEjPNRxi4QC34Xdx7I2KGYn6IpT7gxQ==
+ dependencies:
+ "@types/mdast" "^4.0.0"
+ mdast-util-newline-to-break "^2.0.0"
+ unified "^11.0.0"
+
remark-math@^6.0.0:
version "6.0.0"
resolved "https://registry.npmjs.org/remark-math/-/remark-math-6.0.0.tgz"
diff --git a/govtool/metadata-validation/package-lock.json b/govtool/metadata-validation/package-lock.json
index 83e662ff1..f35ffe507 100644
--- a/govtool/metadata-validation/package-lock.json
+++ b/govtool/metadata-validation/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "@govtool/metadata-validation",
- "version": "2.0.19",
+ "version": "2.0.20",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "@govtool/metadata-validation",
- "version": "2.0.19",
+ "version": "2.0.20",
"license": "UNLICENSED",
"dependencies": {
"@nestjs/axios": "^3.0.2",
diff --git a/govtool/metadata-validation/package.json b/govtool/metadata-validation/package.json
index c3b69cd67..6601acc07 100644
--- a/govtool/metadata-validation/package.json
+++ b/govtool/metadata-validation/package.json
@@ -1,6 +1,6 @@
{
"name": "@govtool/metadata-validation",
- "version": "2.0.19",
+ "version": "2.0.20",
"description": "",
"author": "",
"private": true,
diff --git a/govtool/metadata-validation/src/app.service.ts b/govtool/metadata-validation/src/app.service.ts
index a44669a89..82f0bb1af 100644
--- a/govtool/metadata-validation/src/app.service.ts
+++ b/govtool/metadata-validation/src/app.service.ts
@@ -7,7 +7,7 @@ import * as jsonld from 'jsonld';
import { ValidateMetadataDTO } from '@dto';
import { LoggerMessage, MetadataValidationStatus } from '@enums';
import { validateMetadataStandard, parseMetadata, getStandard } from '@utils';
-import { ValidateMetadataResult } from '@types';
+import { MetadataStandard, ValidateMetadataResult } from '@types';
@Injectable()
export class AppService {
@@ -57,6 +57,13 @@ export class AppService {
throw MetadataValidationStatus.INCORRECT_FORMAT;
}
+ if (
+ standard === MetadataStandard.CIP108 &&
+ !Array.isArray(parsedData.authors)
+ ) {
+ throw MetadataValidationStatus.INCORRECT_FORMAT;
+ }
+
if (!parsedData?.body) {
throw MetadataValidationStatus.INCORRECT_FORMAT;
}
diff --git a/govtool/metadata-validation/src/main.ts b/govtool/metadata-validation/src/main.ts
index 627d3af87..f1c7a0dd2 100644
--- a/govtool/metadata-validation/src/main.ts
+++ b/govtool/metadata-validation/src/main.ts
@@ -13,7 +13,7 @@ async function bootstrap() {
const config = new DocumentBuilder()
.setTitle('Metadata Validation Tool')
.setDescription('The Metadata Validation Tool API description')
- .setVersion("2.0.19")
+ .setVersion("2.0.20")
.build();
const document = SwaggerModule.createDocument(app, config);
diff --git a/tests/govtool-frontend/playwright/lib/pages/budgetDiscussionDetailsPage.ts b/tests/govtool-frontend/playwright/lib/pages/budgetDiscussionDetailsPage.ts
index 9ac2efb25..44a50c317 100644
--- a/tests/govtool-frontend/playwright/lib/pages/budgetDiscussionDetailsPage.ts
+++ b/tests/govtool-frontend/playwright/lib/pages/budgetDiscussionDetailsPage.ts
@@ -144,9 +144,6 @@ export default class BudgetDiscussionDetailsPage {
await this.readMoreBtn.click();
// proposal ownership validation
- await expect(this.publicProposalChampionContent).toHaveText(
- budgetProposal.proposalOwnership.publicChampion
- );
await expect(this.socialHandlesContent).toHaveText(
budgetProposal.proposalOwnership.contactDetails
);
diff --git a/tests/govtool-frontend/playwright/lib/pages/budgetDiscussionSubmissionPage.ts b/tests/govtool-frontend/playwright/lib/pages/budgetDiscussionSubmissionPage.ts
index 9d2ff5197..3376c2b7c 100644
--- a/tests/govtool-frontend/playwright/lib/pages/budgetDiscussionSubmissionPage.ts
+++ b/tests/govtool-frontend/playwright/lib/pages/budgetDiscussionSubmissionPage.ts
@@ -1,5 +1,5 @@
import environments from "@constants/environments";
-import { fa, faker } from "@faker-js/faker";
+import { faker } from "@faker-js/faker";
import { extractProposalIdFromUrl } from "@helpers/string";
import { Page, expect } from "@playwright/test";
import {
@@ -11,11 +11,11 @@ import {
BudgetProposalOwnershipProps,
BudgetProposalProblemStatementAndBenefitProps,
BudgetProposalProps,
+ BudgetProposalStageEnum,
CommitteeAlignmentEnum,
CompanyEnum,
LocationEnum,
PreferredCurrencyEnum,
- ProposalChampionEnum,
ProposalContractingEnum,
ProposalLink,
RoadmapNameEnum,
@@ -163,7 +163,7 @@ export default class BudgetDiscussionSubmissionPage {
this.page.getByTestId("preferred-currency");
readonly intersectNamedAdministratorSelect = this.page.getByTestId(
- "itersect-named-administrator"
+ "intersect-named-administrator"
);
// content
@@ -310,11 +310,6 @@ export default class BudgetDiscussionSubmissionPage {
.getByRole("option", { name: proposalOwnership.companyType })
.click(); //BUG missing testId
- await this.publicChampionSelect.click();
- await this.page
- .getByRole("option", { name: proposalOwnership.publicChampion })
- .click(); //BUG missing testId
-
await this.contactDetailsInput.fill(proposalOwnership.contactDetails);
if (proposalOwnership.companyType === "Group") {
@@ -446,29 +441,28 @@ export default class BudgetDiscussionSubmissionPage {
await this.continueBtn.click();
}
- async fillupForm(budgetProposal: BudgetProposalProps, stage = 8) {
- await this.fillupContactInformationForm(budgetProposal.contactInformation);
-
- if (stage > 2) {
- await this.fillupProposalOwnershipForm(budgetProposal.proposalOwnership);
- }
+ async fillupForm(
+ budgetProposal: BudgetProposalProps,
+ stage: BudgetProposalStageEnum = BudgetProposalStageEnum.AdministrationAndAuditing
+ ) {
+ await this.fillupProposalOwnershipForm(budgetProposal.proposalOwnership);
- if (stage > 3) {
+ if (stage > BudgetProposalStageEnum.ProposalOwnership) {
await this.fillupProblemStatementAndBenefitsForm(
budgetProposal.problemStatementAndBenefits
);
}
- if (stage > 4) {
+ if (stage > BudgetProposalStageEnum.ProblemStatementAndBenefits) {
await this.fillupProposalDetailsForm(budgetProposal.proposalDetails);
}
- if (stage > 5) {
+ if (stage > BudgetProposalStageEnum.ProposalDetails) {
await this.fillupCostingForm(budgetProposal.costing);
}
- if (stage > 6) {
+ if (stage > BudgetProposalStageEnum.Costing) {
await this.fillupFurtherInformation(budgetProposal.furtherInformation);
}
- if (stage > 7) {
+ if (stage > BudgetProposalStageEnum.FurtherInformation) {
await this.intersectNamedAdministratorSelect.click();
await this.page
@@ -558,9 +552,6 @@ export default class BudgetDiscussionSubmissionPage {
generateValidProposalOwnerShip(): BudgetProposalOwnershipProps {
return {
companyType: faker.helpers.arrayElement(Object.values(CompanyEnum)),
- publicChampion: faker.helpers.arrayElement(
- Object.values(ProposalChampionEnum)
- ),
contactDetails: faker.internet.email(),
groupName: faker.company.name(),
groupType: faker.company.buzzVerb(),
@@ -623,7 +614,6 @@ export default class BudgetDiscussionSubmissionPage {
generateValidBudgetProposalInformation(): BudgetProposalProps {
return {
- contactInformation: this.generateValidBudgetProposalContactInformation(),
proposalOwnership: this.generateValidProposalOwnerShip(),
problemStatementAndBenefits:
this.generateValidBudgetProposalProblemStatementAndBenefits(),
@@ -640,9 +630,7 @@ export default class BudgetDiscussionSubmissionPage {
if (fillAllDetails) {
await this.fillupForm(budgetProposal);
} else {
- await this.fillupContactInformationForm(
- budgetProposal.contactInformation
- );
+ await this.fillupProposalOwnershipForm(budgetProposal.proposalOwnership);
}
await this.saveDraftBtn.click();
@@ -650,7 +638,7 @@ export default class BudgetDiscussionSubmissionPage {
await this.cancelBtn.click();
await this.createBudgetProposalBtn.click();
- return fillAllDetails ? budgetProposal : budgetProposal.contactInformation;
+ return fillAllDetails ? budgetProposal : budgetProposal.proposalOwnership;
}
async createBudgetProposal(): Promise<{
@@ -678,42 +666,10 @@ export default class BudgetDiscussionSubmissionPage {
async validateReviewBudgetProposal(
proposalInformations: BudgetProposalProps
) {
- // contact information
- await expect(this.beneficiaryFullNameContent).toHaveText(
- proposalInformations.contactInformation.beneficiaryFullName
- );
- await expect(this.beneficiaryCountryOfResidenceContent).toHaveText(
- proposalInformations.contactInformation.beneficiaryCountry
- );
- //BUG missing testId
- await expect(
- this.currentPage.getByText(
- proposalInformations.contactInformation.beneficiaryNationality,
- { exact: true }
- )
- ).toBeVisible();
- //BUG missing testId
- await expect(
- this.currentPage.getByText(
- proposalInformations.contactInformation.submissionLeadEmail,
- { exact: true }
- )
- ).toBeVisible();
- //BUG missing testId
- await expect(
- this.currentPage.getByText(
- proposalInformations.contactInformation.submissionLeadFullName,
- { exact: true }
- )
- ).toBeVisible();
-
// proposal ownership
await expect(this.companyTypeContent).toHaveText(
proposalInformations.proposalOwnership.companyType
);
- await expect(this.providePreferredContent).toHaveText(
- proposalInformations.proposalOwnership.publicChampion
- );
await expect(this.socialHandlesContent).toHaveText(
proposalInformations.proposalOwnership.contactDetails
);
diff --git a/tests/govtool-frontend/playwright/lib/pages/loginPage.ts b/tests/govtool-frontend/playwright/lib/pages/loginPage.ts
index 21dc76fe5..13c95ecab 100644
--- a/tests/govtool-frontend/playwright/lib/pages/loginPage.ts
+++ b/tests/govtool-frontend/playwright/lib/pages/loginPage.ts
@@ -47,7 +47,9 @@ export default class LoginPage {
// Handle multiple stake keys
if (stakeKeys.length > 1) {
await this.page
- .getByTestId(`${rewardAddresses[0]}-radio`).locator('div').first()
+ .getByTestId(`${rewardAddresses[0]}-radio`)
+ .locator("div")
+ .first()
.click({ force: true });
await this.page.getByTestId("select-button").click();
}
diff --git a/tests/govtool-frontend/playwright/lib/types.ts b/tests/govtool-frontend/playwright/lib/types.ts
index 4efb623d6..eafc59ca8 100644
--- a/tests/govtool-frontend/playwright/lib/types.ts
+++ b/tests/govtool-frontend/playwright/lib/types.ts
@@ -352,17 +352,8 @@ export enum CompanyEnum {
Group = "Group",
}
-export type ProposalChampionType =
- | "Beneficiary listed above"
- | "Submission lead listed above";
-export enum ProposalChampionEnum {
- BeneficiaryListedAbove = "Beneficiary listed above",
- SubmissionLeadListedAbove = "Submission lead listed above",
-}
-
export interface BudgetProposalOwnershipProps {
companyType: CompanyType;
- publicChampion: ProposalChampionType;
contactDetails: string;
groupName?: string;
groupType?: string;
@@ -510,7 +501,6 @@ export interface AdministrationAndAuditingProps {
}
export interface BudgetProposalProps {
- contactInformation: BudgetProposalContactInformationProps;
proposalOwnership: BudgetProposalOwnershipProps;
problemStatementAndBenefits: BudgetProposalProblemStatementAndBenefitProps;
proposalDetails: BudgetProposalDetailsProps;
@@ -518,3 +508,13 @@ export interface BudgetProposalProps {
furtherInformation: Array;
administrationAndAuditing: AdministrationAndAuditingProps;
}
+
+export enum BudgetProposalStageEnum {
+ ProposalOwnership = 1,
+ ProblemStatementAndBenefits = 2,
+ ProposalDetails = 3,
+ Costing = 4,
+ FurtherInformation = 5,
+ AdministrationAndAuditing = 6,
+ Review = 7,
+}
diff --git a/tests/govtool-frontend/playwright/package-lock.json b/tests/govtool-frontend/playwright/package-lock.json
index 74d2b854d..a186f77ce 100644
--- a/tests/govtool-frontend/playwright/package-lock.json
+++ b/tests/govtool-frontend/playwright/package-lock.json
@@ -9,7 +9,7 @@
"version": "1.0.0",
"license": "MIT",
"dependencies": {
- "@cardanoapi/cardano-test-wallet": "^3.0.0",
+ "@cardanoapi/cardano-test-wallet": "^3.2.0",
"@faker-js/faker": "^8.4.1",
"@noble/curves": "^1.3.0",
"@noble/ed25519": "^2.0.0",
@@ -43,9 +43,9 @@
}
},
"node_modules/@cardanoapi/cardano-test-wallet": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/@cardanoapi/cardano-test-wallet/-/cardano-test-wallet-3.0.0.tgz",
- "integrity": "sha512-5cQPQPrsco8eeDBIQI74jiAVl48hI0E3u2JSmya9PvRL/D18LUPqanmhpDScD8fpWRzS7MKSAhqoqsxTlgWYOw==",
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/@cardanoapi/cardano-test-wallet/-/cardano-test-wallet-3.2.0.tgz",
+ "integrity": "sha512-tstRrWlfxatJ12Ra4Y3u4sMLwTyGWl7AYw8ix8H8pdxWToU2of8PWNQrRQ2fE40j2RJ0Ul5XLlMFOSLFrkybxA==",
"license": "MIT"
},
"node_modules/@cbor-extract/cbor-extract-darwin-arm64": {
@@ -1008,9 +1008,9 @@
}
},
"node_modules/browserslist": {
- "version": "4.23.3",
- "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.3.tgz",
- "integrity": "sha512-btwCFJVjI4YWDNfau8RhZ+B1Q/VLoUITrm3RlP6y1tYGWIOa+InuYiRGXUBXo8nA1qKmHMyLB/iVQg5TT4eFoA==",
+ "version": "4.24.4",
+ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.4.tgz",
+ "integrity": "sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A==",
"dev": true,
"funding": [
{
@@ -1028,10 +1028,10 @@
],
"license": "MIT",
"dependencies": {
- "caniuse-lite": "^1.0.30001646",
- "electron-to-chromium": "^1.5.4",
- "node-releases": "^2.0.18",
- "update-browserslist-db": "^1.1.0"
+ "caniuse-lite": "^1.0.30001688",
+ "electron-to-chromium": "^1.5.73",
+ "node-releases": "^2.0.19",
+ "update-browserslist-db": "^1.1.1"
},
"bin": {
"browserslist": "cli.js"
@@ -1082,9 +1082,9 @@
}
},
"node_modules/caniuse-lite": {
- "version": "1.0.30001658",
- "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001658.tgz",
- "integrity": "sha512-N2YVqWbJELVdrnsW5p+apoQyYt51aBMSsBZki1XZEfeBCexcM/sf4xiAHcXQBkuOwJBXtWF7aW1sYX6tKebPHw==",
+ "version": "1.0.30001713",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001713.tgz",
+ "integrity": "sha512-wCIWIg+A4Xr7NfhTuHdX+/FKh3+Op3LBbSp2N5Pfx6T/LhdQy3GTyoTg48BReaW/MyMNZAkTadsBtai3ldWK0Q==",
"dev": true,
"funding": [
{
@@ -1377,9 +1377,9 @@
}
},
"node_modules/electron-to-chromium": {
- "version": "1.5.16",
- "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.16.tgz",
- "integrity": "sha512-2gQpi2WYobXmz2q23FrOBYTLcI1O/P4heW3eqX+ldmPVDQELRqhiebV380EhlGG12NtnX1qbK/FHpN0ba+7bLA==",
+ "version": "1.5.137",
+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.137.tgz",
+ "integrity": "sha512-/QSJaU2JyIuTbbABAo/crOs+SuAZLS+fVVS10PVrIT9hrRkmZl8Hb0xPSkKRUUWHQtYzXHpQUW3Dy5hwMzGZkA==",
"dev": true,
"license": "ISC"
},
@@ -2477,9 +2477,9 @@
}
},
"node_modules/node-releases": {
- "version": "2.0.18",
- "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.18.tgz",
- "integrity": "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==",
+ "version": "2.0.19",
+ "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz",
+ "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==",
"dev": true,
"license": "MIT"
},
@@ -2637,9 +2637,9 @@
}
},
"node_modules/picocolors": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.0.tgz",
- "integrity": "sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==",
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
+ "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
"dev": true,
"license": "ISC"
},
@@ -3516,9 +3516,9 @@
}
},
"node_modules/update-browserslist-db": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz",
- "integrity": "sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ==",
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz",
+ "integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==",
"dev": true,
"funding": [
{
@@ -3536,8 +3536,8 @@
],
"license": "MIT",
"dependencies": {
- "escalade": "^3.1.2",
- "picocolors": "^1.0.1"
+ "escalade": "^3.2.0",
+ "picocolors": "^1.1.1"
},
"bin": {
"update-browserslist-db": "cli.js"
diff --git a/tests/govtool-frontend/playwright/package.json b/tests/govtool-frontend/playwright/package.json
index a57cd1b79..03997d2e4 100644
--- a/tests/govtool-frontend/playwright/package.json
+++ b/tests/govtool-frontend/playwright/package.json
@@ -29,7 +29,7 @@
"generate-wallets": "ts-node ./generate_wallets.ts 24"
},
"dependencies": {
- "@cardanoapi/cardano-test-wallet": "^3.0.0",
+ "@cardanoapi/cardano-test-wallet": "^3.2.0",
"@faker-js/faker": "^8.4.1",
"@noble/curves": "^1.3.0",
"@noble/ed25519": "^2.0.0",
diff --git a/tests/govtool-frontend/playwright/tests/12-proposal-budget-submission/proposalBudgetSubmission.loggedin.spec.ts b/tests/govtool-frontend/playwright/tests/12-proposal-budget-submission/proposalBudgetSubmission.loggedin.spec.ts
index 181b37138..698106567 100644
--- a/tests/govtool-frontend/playwright/tests/12-proposal-budget-submission/proposalBudgetSubmission.loggedin.spec.ts
+++ b/tests/govtool-frontend/playwright/tests/12-proposal-budget-submission/proposalBudgetSubmission.loggedin.spec.ts
@@ -11,8 +11,9 @@ import BudgetDiscussionDetailsPage from "@pages/budgetDiscussionDetailsPage";
import BudgetDiscussionSubmissionPage from "@pages/budgetDiscussionSubmissionPage";
import { expect } from "@playwright/test";
import {
- BudgetProposalContactInformationProps,
+ BudgetProposalOwnershipProps,
BudgetProposalProps,
+ BudgetProposalStageEnum,
CompanyEnum,
} from "@types";
import { allure } from "allure-playwright";
@@ -47,38 +48,12 @@ test.describe("Budget proposal 01 wallet", () => {
});
test.describe("Budget proposal field verification", () => {
- test("12D_1. Should verify all field of “contact information” section", async () => {
- await expect(
- budgetProposalSubmissionPage.beneficiaryFullNameInput
- ).toBeVisible();
- await expect(
- budgetProposalSubmissionPage.beneficiaryEmailInput
- ).toBeVisible();
- await expect(
- budgetProposalSubmissionPage.beneficiaryCountrySelect
- ).toBeVisible();
- await expect(
- budgetProposalSubmissionPage.beneficiaryNationalitySelect
- ).toBeVisible();
- await expect(
- budgetProposalSubmissionPage.submissionLeadFullNameInput
- ).toBeVisible();
- });
-
- test("12D_2. Should verify all field of “proposal ownership” section", async () => {
- const proposalContactInformationContent =
- budgetProposalSubmissionPage.generateValidBudgetProposalContactInformation();
- await budgetProposalSubmissionPage.fillupContactInformationForm(
- proposalContactInformationContent
- );
-
+ test("12D_1. Should verify all field of “proposal ownership” section", async () => {
// default field
await expect(
budgetProposalSubmissionPage.companyTypeSelect
).toBeVisible();
- await expect(
- budgetProposalSubmissionPage.publicChampionSelect
- ).toBeVisible();
+
await expect(
budgetProposalSubmissionPage.contactDetailsInput
).toBeVisible();
@@ -111,10 +86,12 @@ test.describe("Budget proposal 01 wallet", () => {
).toBeVisible();
});
- test("12D_3. Should verify all field of “problem statements and proposal benefits” section", async () => {
- const proposalInformation =
- budgetProposalSubmissionPage.generateValidBudgetProposalInformation();
- await budgetProposalSubmissionPage.fillupForm(proposalInformation, 3);
+ test("12D_2. Should verify all field of “problem statements and proposal benefits” section", async () => {
+ const proposalOwnership =
+ budgetProposalSubmissionPage.generateValidProposalOwnerShip();
+ await budgetProposalSubmissionPage.fillupProposalOwnershipForm(
+ proposalOwnership
+ );
await expect(
budgetProposalSubmissionPage.problemStatementInput
@@ -136,10 +113,13 @@ test.describe("Budget proposal 01 wallet", () => {
).toBeVisible();
});
- test("12D_4. Should verify all field of “proposal details” section", async () => {
+ test("12D_3. Should verify all field of “proposal details” section", async () => {
const proposalInformation =
budgetProposalSubmissionPage.generateValidBudgetProposalInformation();
- await budgetProposalSubmissionPage.fillupForm(proposalInformation, 4);
+ await budgetProposalSubmissionPage.fillupForm(
+ proposalInformation,
+ BudgetProposalStageEnum.ProblemStatementAndBenefits
+ );
await expect(
budgetProposalSubmissionPage.proposalNameInput
@@ -164,10 +144,13 @@ test.describe("Budget proposal 01 wallet", () => {
).toBeVisible();
});
- test("12D_5. Should verify all field of “costing” section", async () => {
+ test("12D_4. Should verify all field of “costing” section", async () => {
const proposalInformation =
budgetProposalSubmissionPage.generateValidBudgetProposalInformation();
- await budgetProposalSubmissionPage.fillupForm(proposalInformation, 5);
+ await budgetProposalSubmissionPage.fillupForm(
+ proposalInformation,
+ BudgetProposalStageEnum.ProposalDetails
+ );
await expect(budgetProposalSubmissionPage.adaAmountInput).toBeVisible();
await expect(
@@ -184,20 +167,26 @@ test.describe("Budget proposal 01 wallet", () => {
).toBeVisible();
});
- test("12D_6. Should verify all field of “further information” section", async () => {
+ test("12D_5. Should verify all field of “further information” section", async () => {
const proposalInformation =
budgetProposalSubmissionPage.generateValidBudgetProposalInformation();
- await budgetProposalSubmissionPage.fillupForm(proposalInformation, 6);
+ await budgetProposalSubmissionPage.fillupForm(
+ proposalInformation,
+ BudgetProposalStageEnum.Costing
+ );
await expect(budgetProposalSubmissionPage.linkTextInput).toBeVisible();
await expect(budgetProposalSubmissionPage.linkUrlInput).toBeVisible();
await expect(budgetProposalSubmissionPage.addLinkBtn).toBeVisible();
});
- test("12D_7. Should verify all field of “administration and auditing” section", async () => {
+ test("12D_6. Should verify all field of “administration and auditing” section", async () => {
const proposalInformation =
budgetProposalSubmissionPage.generateValidBudgetProposalInformation();
- await budgetProposalSubmissionPage.fillupForm(proposalInformation, 7);
+ await budgetProposalSubmissionPage.fillupForm(
+ proposalInformation,
+ BudgetProposalStageEnum.FurtherInformation
+ );
await expect(
budgetProposalSubmissionPage.intersectNamedAdministratorSelect
@@ -247,32 +236,44 @@ test("12C. Should save and view draft proposal", async ({ browser }) => {
const budgetSubmissionPage = new BudgetDiscussionSubmissionPage(page);
await budgetSubmissionPage.goto();
- const draftContactInformationContent =
- (await budgetSubmissionPage.createDraftBudgetProposal()) as BudgetProposalContactInformationProps;
+ const draftProposalOwnership =
+ (await budgetSubmissionPage.createDraftBudgetProposal()) as BudgetProposalOwnershipProps;
const getAddDrafts = await budgetSubmissionPage.getAllDrafts();
expect(getAddDrafts.length).toBeGreaterThan(0);
await budgetSubmissionPage.viewLastDraft();
- await expect(budgetSubmissionPage.beneficiaryFullNameInput).toHaveValue(
- draftContactInformationContent.beneficiaryFullName
+ await expect(budgetSubmissionPage.companyTypeSelect).toHaveText(
+ draftProposalOwnership.companyType
);
- await expect(budgetSubmissionPage.beneficiaryEmailInput).toHaveValue(
- draftContactInformationContent.beneficiaryEmail
- );
- await expect(budgetSubmissionPage.beneficiaryCountrySelect).toHaveText(
- draftContactInformationContent.beneficiaryCountry
- );
- await expect(budgetSubmissionPage.beneficiaryNationalitySelect).toHaveText(
- draftContactInformationContent.beneficiaryNationality
- );
- await expect(budgetSubmissionPage.submissionLeadFullNameInput).toHaveValue(
- draftContactInformationContent.submissionLeadFullName
- );
- await expect(budgetSubmissionPage.submissionLeadEmailInput).toHaveValue(
- draftContactInformationContent.submissionLeadEmail
+
+ await expect(budgetSubmissionPage.contactDetailsInput).toHaveValue(
+ draftProposalOwnership.contactDetails
);
+
+ if (draftProposalOwnership.companyType === "Group") {
+ await expect(budgetSubmissionPage.groupNameInput).toHaveValue(
+ draftProposalOwnership.groupName
+ );
+ await expect(budgetSubmissionPage.groupTypeInput).toHaveValue(
+ draftProposalOwnership.groupType
+ );
+ await expect(budgetSubmissionPage.keyInformationOfGroupInput).toHaveValue(
+ draftProposalOwnership.groupKeyIdentity
+ );
+ }
+ if (draftProposalOwnership.companyType === "Company") {
+ await expect(budgetSubmissionPage.companyNameInput).toHaveValue(
+ draftProposalOwnership.companyName
+ );
+ await expect(budgetSubmissionPage.companyDomainNameInput).toHaveValue(
+ draftProposalOwnership.companyDomainName
+ );
+ await expect(budgetSubmissionPage.countryOfIncorporationBtn).toHaveText(
+ draftProposalOwnership.countryOfIncorportation
+ );
+ }
});
test("12H. Should submit a valid budget proposal", async ({ browser }) => {
@@ -310,7 +311,7 @@ test("12I. Should submit a valid draft budget proposal", async ({
await budgetSubmissionPage.viewLastDraft();
- for (let i = 0; i < 8; i++) {
+ for (let i = 0; i < 7; i++) {
await budgetSubmissionPage.continueBtn.click();
}
await budgetSubmissionPage.submitBtn.click();