Skip to content

Commit

Permalink
chore(rwa): e2e testing for login (#2841)
Browse files Browse the repository at this point in the history
  • Loading branch information
sstraatemans authored Jan 31, 2025
1 parent 824f91e commit b5d9329
Show file tree
Hide file tree
Showing 17 changed files with 375 additions and 51 deletions.
30 changes: 22 additions & 8 deletions packages/apps/rwa-demo/src/app/(app)/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,23 +36,33 @@ const Home = () => {
<SideBarBreadcrumbs />

<Stack width="100%" flexDirection="column" gap="md">
<SectionCard>
<SectionCard data-testid="contractCard">
<SectionCardContentBlock>
<SectionCardHeader
title="Contract details"
description={<>All you need to know about the contract</>}
/>
<SectionCardBody>
<Stack width="100%" className={contractDetailWrapperClass}>
<ContractDetails label="Name" value={asset?.contractName} />
<ContractDetails label="Namespace" value={asset?.namespace} />
<ContractDetails
data-testid="contractName"
label="Name"
value={asset?.contractName}
/>
<ContractDetails
data-testid="namespace"
label="Namespace"
value={asset?.namespace}
/>
<ContractDetails
data-testid="tokenSupply"
label="Total token supply"
value={<SupplyCountContractDetails />}
/>

{isInvestor && (
<ContractDetails
data-testid="balance"
label="Investor balance"
value={
<InvestorBalance
Expand All @@ -67,16 +77,17 @@ const Home = () => {
</SectionCardContentBlock>
</SectionCard>

<SectionCard>
<SectionCard data-testid="assetCard">
<SectionCardContentBlock>
<SectionCardHeader title="Asset" description={<></>} />
<SectionCardBody title="Actions">
<Stack className={actionsWrapperClass}>
<PauseAssetAction />
<PauseAssetAction data-testid="pauseAction" />

<SetComplianceForm
trigger={
<AssetAction
data-testid="complianceAction"
isDisabled={!isSetComplianceAllowed}
icon={<MonoAdd />}
label="Set Compliance"
Expand All @@ -86,16 +97,18 @@ const Home = () => {

<TransferForm
investorAccount={account?.address!}
trigger={<TransferAssetAction />}
trigger={
<TransferAssetAction data-testid="transferassetAction" />
}
/>

<BatchTransferAssetAction />
<BatchTransferAssetAction data-testid="batchTransferAction" />
</Stack>
</SectionCardBody>
</SectionCardContentBlock>
</SectionCard>

<SectionCard>
<SectionCard data-testid="complianceCard">
<SectionCardContentBlock>
<SectionCardHeader
title="Compliance rules"
Expand All @@ -105,6 +118,7 @@ const Home = () => {
<SetComplianceForm
trigger={
<Button
data-testid="editrules"
isCompact
variant="outlined"
isDisabled={!isSetComplianceAllowed}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,20 @@ interface IProps {
label: string;
isDisabled?: boolean;
onPress?: ITileProps['onClick'];
'data-testid'?: string;
}

export const AssetAction: FC<IProps> = ({
icon,
label,
isDisabled,
onPress,
'data-testid': dataTestId,
}) => {
return (
<Stack className={assetActionWrapper}>
<Tile
data-testId={dataTestId}
isDisabled={isDisabled}
as={onPress ? 'button' : 'div'}
onClick={!isDisabled ? onPress : () => {}}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,17 @@ import { AssetAction } from './AssetAction';

interface IProps {
onPress?: ITileProps['onClick'];
'data-testid'?: string;
}

export const TransferAssetAction: FC<IProps> = ({ onPress }) => {
export const TransferAssetAction: FC<IProps> = ({
onPress,
'data-testid': dataTestId,
}) => {
const { isAllowed: isTransferTokensAllowed } = useTransferTokens();
return (
<AssetAction
data-testid={dataTestId}
onPress={onPress}
isDisabled={!isTransferTokensAllowed}
icon={<MonoAdd />}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,12 @@ export const AssetStepperForm: FC<IProps> = ({ handleDone }) => {
required: true,
}}
render={({ field }) => (
<TextField label="Namespace" isDisabled {...field} />
<TextField
data-testid="namespaceField"
label="Namespace"
isDisabled
{...field}
/>
)}
/>

Expand All @@ -145,7 +150,12 @@ export const AssetStepperForm: FC<IProps> = ({ handleDone }) => {
},
}}
render={({ field }) => (
<TextField label="Contract Name" {...field} />
<TextField
data-testid="contractNameField"
id="contractName"
label="Contract Name"
{...field}
/>
)}
/>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,19 @@ import { BatchTransferAssetForm } from './BatchTransferAssetForm';

interface IProps {
onPress?: ITileProps['onClick'];
'data-testid'?: string;
}

export const BatchTransferAssetAction: FC<IProps> = ({ onPress }) => {
export const BatchTransferAssetAction: FC<IProps> = ({
onPress,
'data-testid': dataTestId,
}) => {
const { isAllowed: isTransferTokensAllowed } = useBatchTransferTokens();
return (
<BatchTransferAssetForm
trigger={
<AssetAction
data-testid={dataTestId}
isDisabled={!isTransferTokensAllowed}
icon={
<TransactionTypeSpinner
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,21 @@ import {
interface IProps {
label: string;
value?: ReactElement | string;
['data-testid']?: string;
}

export const ContractDetails: FC<IProps> = ({ label, value }) => {
export const ContractDetails: FC<IProps> = ({
label,
value,
'data-testid': dataTestId,
}) => {
return (
<Stack
className={contractDetailsClass}
flexDirection="column"
alignItems="center"
gap="sm"
data-testid={dataTestId}
>
<Heading as="h6" className={contractDetailsHeaderClass}>
{label}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,17 @@ import { useAsset } from '@/hooks/asset';
import { useTogglePause } from '@/hooks/togglePause';
import { useTransactions } from '@/hooks/transactions';
import { MonoPause, MonoPlayArrow } from '@kadena/kode-icons';
import type { FC } from 'react';
import { useMemo, useState } from 'react';
import { AssetAction } from '../AssetAction/AssetAction';
import { TransactionPendingIcon } from '../TransactionPendingIcon/TransactionPendingIcon';
import { TXTYPES } from '../TransactionsProvider/TransactionsProvider';
import { TransactionTypeSpinner } from '../TransactionTypeSpinner/TransactionTypeSpinner';
import { PauseForm } from './PauseForm';

export const PauseAssetAction = () => {
export const PauseAssetAction: FC<{
'data-testid'?: string;
}> = ({ 'data-testid': dataTestId }) => {
const { paused } = useAsset();
const [loading, setLoading] = useState(false);
const { isAllowed } = useTogglePause();
Expand All @@ -33,6 +36,7 @@ export const PauseAssetAction = () => {
handleSetIsLoading={setLoading}
trigger={
<AssetAction
data-testid={dataTestId}
isDisabled={!isAllowed}
icon={showIcon()}
label={paused ? 'Contract is paused' : 'Contract is active'}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,15 @@ export const TransactionTypeSpinner: FC<IProps> = ({
}, [type, getTransactions]);

return transactions.length > 0 ? (
<Stack title="Someone is updating this value">
<Stack
data-testid="pending-transactionIcon"
title="Someone is updating this value"
>
<TransactionPendingIcon />
</Stack>
) : (
!!fallbackIcon && fallbackIcon
<Stack data-testid="no-pending-transactionIcon" as="span">
{!!fallbackIcon && fallbackIcon}
</Stack>
);
};
17 changes: 8 additions & 9 deletions packages/apps/rwa-demo/src/services/pact/modelcontract.ts
Original file line number Diff line number Diff line change
Expand Up @@ -233,13 +233,13 @@ export const getContract = ({ contractName, namespace }: IAddContractProps) => `
supply
)
(defcap IDENTITY-REGISTERED:bool (investor-address:string investor-guard:guard identity:string)
(defcap IDENTITY-REGISTERED:bool (investor-address:string investor-guard:guard user-identity:string)
@doc "Event emitted when identity is added"
@event
true
)
(defcap IDENTITY-REMOVED:bool (investor-address:string identity:string)
(defcap IDENTITY-REMOVED:bool (investor-address:string user-identity:string)
@doc "Event emitted when identity is removed"
@event
true
Expand Down Expand Up @@ -619,14 +619,14 @@ export const getContract = ({ contractName, namespace }: IAddContractProps) => `
)
)
(defun register-identity-internal:bool (user-address:string user-guard:guard identity:string country:integer)
(defun register-identity-internal:bool (user-address:string user-guard:guard user-identity:string country:integer)
@doc "Register an identity contract corresponding to a user address. \
\ Requires that the user doesn't have an identity contract already registered. \
\ Only a wallet set as agent of the smart contract can call this function. \
\ Emits an \`IDENTITY-REGISTERED\` event."
(require-capability (INTERNAL))
(is-principal user-address)
(write identities user-address { "kadenaID":identity, "country":country, "active":true })
(write identities user-address { "kadenaID":user-identity, "country":country, "active":true })
(with-default-read users user-address
{ "balance": -1.0 }
{ "balance":=balance }
Expand All @@ -635,7 +635,7 @@ export const getContract = ({ contractName, namespace }: IAddContractProps) => `
""
)
)
(emit-event (IDENTITY-REGISTERED user-address user-guard identity))
(emit-event (IDENTITY-REGISTERED user-address user-guard user-identity))
)
;; freeze operations (pause, unpause, set-address-frozen, freeze-partial-tokens, unfreeze-partial-tokens)
Expand Down Expand Up @@ -693,14 +693,14 @@ export const getContract = ({ contractName, namespace }: IAddContractProps) => `
)
;; identity operations (register-identity, delete-identity)
(defun register-identity:bool (user-address:string user-guard:guard identity:string country:integer)
(defun register-identity:bool (user-address:string user-guard:guard user-identity:string country:integer)
@doc "Register a user address. \
\ Requires that the user doesn't have an identity contract already registered. \
\ Only a wallet set as agent of the smart contract can call this function. \
\ Emits an \`IDENTITY-REGISTERED\` event."
(only-owner-or-agent-admin)
(with-capability (INTERNAL)
(register-identity-internal user-address user-guard identity country)
(register-identity-internal user-address user-guard user-identity country)
)
)
Expand Down Expand Up @@ -1320,7 +1320,7 @@ export const getContract = ({ contractName, namespace }: IAddContractProps) => `
(enforce false "GEN-IMPL-001")
)
(defun update-identity:bool (user-address:string identity:string)
(defun update-identity:bool (user-address:string user-identity:string)
@doc "unused"
(enforce false "GEN-IMPL-001")
)
Expand Down Expand Up @@ -1359,6 +1359,5 @@ export const getContract = ({ contractName, namespace }: IAddContractProps) => `
(RWA.token-mapper.add-token-ref TOKEN-ID ${namespace}.${contractName})
(${namespace}.${contractName}.init "${contractName}" "MVP" 0 "kadenaID" [] false (keyset-ref-guard "${namespace}.admin-keyset"))
`;
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { Page } from '@playwright/test';
import type { Locator, Page } from '@playwright/test';
import { expect } from '@playwright/test';
import { WebAuthNHelper } from '../../helpers/chainweaver/webauthn.helper';

Expand All @@ -23,16 +23,8 @@ export class ChainweaverAppIndex {
await expect(newAccountButton).toBeVisible();
await newAccountButton.click();

const unlockButton = actor.getByRole('button', {
name: 'Unlock',
});

await expect(unlockButton).toBeVisible();
const input = actor.getByTestId('passwordField');
await input.fill(this._PASSWORD);

await unlockButton.click();
await expect(unlockButton).toBeHidden();
await this.signPopupWithPassword(actor);
await actor.waitForTimeout(500);

const newListItems = await actor
.getByTestId('assetList')
Expand Down Expand Up @@ -155,10 +147,44 @@ export class ChainweaverAppIndex {
await actor.getByRole('button', { name: 'Settings' }).waitFor();
await actor.getByRole('button', { name: 'Settings' }).click();

await expect(actor).toHaveURL('/networks');
const url = await actor.evaluate(() => window.location.href);

await expect(url).toContain('/networks');

return true;
}

public async signPopupWithPassword(actor: Page): Promise<boolean> {
const unlockButton = actor.getByRole('button', {
name: 'Unlock',
});

const input = actor.getByTestId('passwordField');
await unlockButton.waitFor();
await input.waitFor();
await input.fill(this._PASSWORD);

await unlockButton.click();
await expect(unlockButton).toBeHidden();

return true;
}
public async signWithPassword(
actor: Page,
trigger: Locator,
): Promise<boolean> {
const popupPromise = actor.waitForEvent('popup');
await trigger.click();
const walletPopup = await popupPromise;

const signButton = walletPopup.getByTestId('signTx');
await signButton.click();

await this.signPopupWithPassword(walletPopup);

return true;
}

public async addNetwork(
actor: Page,
network: { networkId: string; title: string; host: string },
Expand All @@ -176,8 +202,8 @@ export class ChainweaverAppIndex {
await expect(
actor.getByRole('heading', { name: 'Add Network' }),
).toBeVisible();
await actor.type('[name="networkId"]', network.networkId);
await actor.type('[name="hosts.0.url"]', network.host);
await actor.type('[name="networkId"]', network.networkId);
await actor.type('[name="name"]', network.title);
await actor.focus('[name="name"]');

Expand Down
Loading

0 comments on commit b5d9329

Please sign in to comment.