diff --git a/dapp/tests/management/management.spec.ts b/dapp/tests/management/management.spec.ts index 51c160821..bd6bd0b41 100644 --- a/dapp/tests/management/management.spec.ts +++ b/dapp/tests/management/management.spec.ts @@ -10,13 +10,16 @@ import { formatDate } from '@/lib/utils/format/formatDate'; import { expect, test } from '../helpers/fixtures'; import { iotaNamesClient } from '../setup/utils'; import { + connectName, connectWallet, createWallet, generateRandomName, purchaseName, requestFaucetTokens, + setDisplayName, } from '../utils'; +test.setTimeout(60_000); test.describe.parallel('Name Management Tests', () => { test.beforeAll(async ({ appPage, context, extensionPage, extensionName, sharedState }) => { const { address, mnemonic } = await createWallet(extensionPage); @@ -38,7 +41,7 @@ test.describe.parallel('Name Management Tests', () => { const keypair = Ed25519Keypair.deriveKeypair(sharedState.wallet.mnemonic ?? ''); const name = generateRandomName('display'); - const response = await purchaseName(name, sharedState.wallet.address ?? '', keypair); + const response = await purchaseName(name, keypair); expect(response.effects?.status.status).toBe('success'); await page.goto('/my-names'); @@ -88,10 +91,11 @@ test.describe.parallel('Name Management Tests', () => { await page.close(); }); + test('Create subname', async ({ appPage: page, context, sharedState }) => { const keypair = Ed25519Keypair.deriveKeypair(sharedState.wallet.mnemonic ?? ''); const name = generateRandomName('display'); - const response = await purchaseName(name, sharedState.wallet.address ?? '', keypair); + const response = await purchaseName(name, keypair); expect(response.effects?.status.status).toBe('success'); await page.goto('/my-names'); @@ -125,4 +129,50 @@ test.describe.parallel('Name Management Tests', () => { await page.close(); }); + + test('Unset Display', async ({ appPage: page, context, sharedState }) => { + const keypair = Ed25519Keypair.deriveKeypair(sharedState.wallet.mnemonic ?? ''); + const name = generateRandomName('display'); + + const responsePurchase = await purchaseName(name, keypair); + expect(responsePurchase.effects?.status.status).toBe('success'); + + const record = await iotaNamesClient.getNameRecord(name); + if (!record) throw new Error('Name record not found'); + + const responseConnect = await connectName(name, record.nftId, keypair); + expect(responseConnect.effects?.status.status).toBe('success'); + + const responseSetDisplay = await setDisplayName(name, keypair); + expect(responseSetDisplay.effects?.status.status).toBe('success'); + + await page.goto('/my-names'); + await expect( + page.getByTestId('name-card').filter({ hasText: normalizeIotaName(name, 'at') }), + ).toBeVisible({ timeout: 10_000 }); + + const nameCard = page + .getByTestId('name-card') + .filter({ hasText: normalizeIotaName(name, 'at') }); + await nameCard.getByTestId('name-card-avatar').hover(); + const menuButtonLocator = nameCard.getByTestId('menu-button'); + await expect(menuButtonLocator).toBeVisible(); + await menuButtonLocator.click(); + + await page.getByText('Connect to Address', { exact: true }).click(); + const dialog = page.getByRole('dialog'); + await expect(dialog.getByText('Connect to Address')).toBeVisible(); + + const displayLabel = dialog.getByText('Set as Display name', { exact: true }); + await expect(displayLabel).toBeVisible(); + const displayCheckbox = dialog.getByRole('checkbox'); + await expect(displayCheckbox).toBeChecked({ timeout: 10_000 }); + await displayCheckbox.click(); + await dialog.getByRole('button', { name: 'Apply' }).click(); + (await context.waitForEvent('page')).getByRole('button', { name: 'Approve' }).click(); + await page.bringToFront(); + + await dialog.getByRole('button', { name: 'Finish' }).click(); + await page.close(); + }); }); diff --git a/dapp/tests/utils.ts b/dapp/tests/utils.ts index 4fd4e9c9c..f4a541cd7 100644 --- a/dapp/tests/utils.ts +++ b/dapp/tests/utils.ts @@ -107,7 +107,8 @@ export async function requestFaucetTokens(recipient: string) { } } -export async function purchaseName(name: string, address: string, signer: Signer) { +export async function purchaseName(name: string, signer: Signer) { + const address = signer.toIotaAddress(); const tx = new Transaction(); const iotaNamesTx = new IotaNamesTransaction(iotaNamesClient, tx); const [coin] = iotaNamesTx.transaction.splitCoins(tx.gas, [50_000_000_000]); @@ -140,6 +141,67 @@ export async function purchaseName(name: string, address: string, signer: Signer return responsePurchase; } +export async function connectName(name: string, nft: string, signer: Signer) { + const address = signer.toIotaAddress(); + const tx = new Transaction(); + const iotaNamesTx = new IotaNamesTransaction(iotaNamesClient, tx); + iotaNamesTx.setTargetAddress({ + nft, + address, + isSubname: false, + }); + iotaNamesTx.transaction.setSender(address); + const txBytes = await iotaNamesTx.transaction.build({ + client: iotaClient, + }); + + const txDryRun = await iotaClient.dryRunTransactionBlock({ + transactionBlock: txBytes, + }); + + if (txDryRun.effects.status.status !== 'success') { + throw new Error(txDryRun.effects.status.error || 'Transaction dry run failed'); + } + console.log(`Connected name: ${name} to address: ${address}`); + const responseConnect = await iotaClient.signAndExecuteTransaction({ + transaction: txBytes, + signer, + options: { + showEffects: true, + }, + }); + return responseConnect; +} + +export async function setDisplayName(name: string, signer: Signer) { + const address = signer.toIotaAddress(); + const tx = new Transaction(); + const iotaNamesTx = new IotaNamesTransaction(iotaNamesClient, tx); + iotaNamesTx.setDefault(name); + iotaNamesTx.transaction.setSender(address); + const txBytes = await iotaNamesTx.transaction.build({ + client: iotaClient, + }); + + const txDryRun = await iotaClient.dryRunTransactionBlock({ + transactionBlock: txBytes, + }); + + if (txDryRun.effects.status.status !== 'success') { + throw new Error(txDryRun.effects.status.error || 'Transaction dry run failed'); + } + + console.log(`Set name: ${name} as display name for address: ${address}`); + const responseSetDisplay = await iotaClient.signAndExecuteTransaction({ + transaction: txBytes, + signer, + options: { + showEffects: true, + }, + }); + return responseSetDisplay; +} + export function deriveAddressFromMnemonic(mnemonic: string, path?: string) { const keypair = Ed25519Keypair.deriveKeypair(mnemonic, path); const address = keypair.getPublicKey().toIotaAddress();