Skip to content

Commit 9930bd6

Browse files
committed
refactor(tests): optimize E2E tests for Stellar Fiat Modal with dynamic selectors and enhanced checks
- Updated E2E tests for the Stellar Fiat Modal to utilize dynamic selectors for improved maintainability. - Enhanced visibility checks for wallet information display in the Deposit Modal and Payout Form tests. - Streamlined test structure for scenarios involving disconnected wallets to improve clarity and execution. These changes aim to bolster the reliability and robustness of the E2E testing process for the Stellar Fiat Modal and related components.
1 parent 59b9c32 commit 9930bd6

4 files changed

Lines changed: 94 additions & 16 deletions

File tree

Dechat/dex_with_fiat_frontend/tests/e2e/bank-details-modal.spec.ts

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -88,33 +88,46 @@ test.describe('BankDetailsModal — Step 1: bank selection', () => {
8888
test.beforeEach(async ({ page }) => {
8989
await mockBankApis(page);
9090
await page.goto('/test-bank-details');
91+
await expect(
92+
page.getByRole('dialog', { name: /fiat payout/i }),
93+
).toBeVisible();
94+
await expect(
95+
page.getByRole('dialog', { name: /fiat payout/i }).getByRole('button', {
96+
name: 'Access Bank',
97+
}),
98+
).toBeVisible({ timeout: 10_000 });
9199
});
92100

93101
test('modal opens and shows step 1 with bank list', async ({ page }) => {
94102
const dialog = page.getByRole('dialog', { name: /fiat payout/i });
95103
await expect(dialog).toBeVisible();
96-
await expect(page.getByText('Access Bank')).toBeVisible();
97-
await expect(page.getByText('Zenith Bank')).toBeVisible();
104+
await expect(dialog.getByText('Access Bank')).toBeVisible();
105+
await expect(dialog.getByText('Zenith Bank')).toBeVisible();
98106
});
99107

100108
test('Next button is disabled until a bank is selected', async ({ page }) => {
101-
const nextBtn = page.getByRole('button', { name: /next/i });
109+
const dialog = page.getByRole('dialog', { name: /fiat payout/i });
110+
const nextBtn = dialog.getByRole('button', { name: /^next$/i });
102111
await expect(nextBtn).toBeDisabled();
103-
await page.getByRole('button', { name: 'Access Bank' }).click();
112+
await dialog.getByRole('button', { name: 'Access Bank' }).click();
104113
await expect(nextBtn).toBeEnabled();
105114
});
106115

107116
test('bank search filters the list', async ({ page }) => {
108-
await page.getByPlaceholder(/search banks/i).fill('Zenith');
109-
await expect(page.getByRole('button', { name: 'Zenith Bank' })).toBeVisible();
117+
const dialog = page.getByRole('dialog', { name: /fiat payout/i });
118+
const searchInput = dialog.getByPlaceholder(/search banks/i);
119+
await searchInput.fill('Zenith');
120+
await expect(searchInput).toHaveValue('Zenith');
121+
await expect(dialog.getByRole('button', { name: 'Zenith Bank' })).toBeVisible();
110122
await expect(
111-
page.getByRole('button', { name: 'Access Bank' }),
123+
dialog.getByRole('button', { name: 'Access Bank' }),
112124
).not.toBeVisible();
113125
});
114126

115127
test('shows "No banks found" when search has no match', async ({ page }) => {
116-
await page.getByPlaceholder(/search banks/i).fill('XYZ_NONEXISTENT');
117-
await expect(page.getByText(/no banks found/i)).toBeVisible();
128+
const dialog = page.getByRole('dialog', { name: /fiat payout/i });
129+
await dialog.getByPlaceholder(/search banks/i).fill('XYZ_NONEXISTENT');
130+
await expect(dialog.getByText(/no banks found/i)).toBeVisible();
118131
});
119132

120133
test('shows error state when bank API fails', async ({ page }) => {

Dechat/dex_with_fiat_frontend/tests/e2e/deposit-modal.spec.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,10 @@ test.describe('Deposit Modal Validation and Success State', () => {
55
test.beforeEach(async ({ page }) => {
66
await mockSorobanRpc(page);
77
await page.goto('/test-stellar-fiat-modal');
8-
await page.getByRole('dialog', { name: /deposit to bridge/i }).waitFor({
9-
state: 'visible',
8+
const dialog = page.getByRole('dialog', { name: /deposit to bridge/i });
9+
await dialog.waitFor({ state: 'visible' });
10+
await expect(dialog.locator('input[type="number"]').first()).toBeVisible({
11+
timeout: 15_000,
1012
});
1113
});
1214

Dechat/dex_with_fiat_frontend/tests/e2e/helpers.ts

Lines changed: 61 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { expect, type Page } from '@playwright/test';
2+
import { xdr } from '@stellar/stellar-sdk';
23

34
/** Valid Stellar testnet address used for admin E2E flows. */
45
export const MOCK_ADMIN_ADDRESS =
@@ -8,6 +9,45 @@ export const MOCK_ADMIN_ADDRESS =
89
const MOCK_ADMIN_SCVAL_XDR =
910
'AAAAEgAAAAAAAAAASFXb0ZgW04l/PbSG2DwEj5+TzC+JpDkIYGpAU0HQeXU=';
1011

12+
/** i128 ScVal XDR mocks for read-only bridge contract view calls (stroops). */
13+
const MOCK_BRIDGE_LIMIT_XDR = 'AAAACgAAAAAAAAAAAAAAF0h26AA='; // 10_000 XLM
14+
const MOCK_CONTRACT_BALANCE_XDR = 'AAAACgAAAAAAAAAAAAAAC6Q7dAA='; // 5_000 XLM
15+
const MOCK_TOTAL_DEPOSITED_XDR = 'AAAACgAAAAAAAAAAAAAABdIdugA='; // 2_500 XLM
16+
17+
function getSimulateFunctionName(transactionXdr: string): string | null {
18+
try {
19+
const envelope = xdr.TransactionEnvelope.fromXDR(transactionXdr, 'base64');
20+
const op = envelope.v1().tx().operations()[0];
21+
const body = op.body();
22+
if (body.switch().name !== 'invokeHostFunctionOp') {
23+
return null;
24+
}
25+
return body
26+
.invokeHostFunctionOp()
27+
.hostFunction()
28+
.invokeContract()
29+
.functionName()
30+
.toString();
31+
} catch {
32+
return null;
33+
}
34+
}
35+
36+
function scvalXdrForSimulateFunction(functionName: string | null): string {
37+
switch (functionName) {
38+
case 'get_admin':
39+
return MOCK_ADMIN_SCVAL_XDR;
40+
case 'get_limit':
41+
return MOCK_BRIDGE_LIMIT_XDR;
42+
case 'get_balance':
43+
return MOCK_CONTRACT_BALANCE_XDR;
44+
case 'get_total_deposited':
45+
return MOCK_TOTAL_DEPOSITED_XDR;
46+
default:
47+
return MOCK_BRIDGE_LIMIT_XDR;
48+
}
49+
}
50+
1151
export const MOCK_WALLET_ADDRESS = MOCK_ADMIN_ADDRESS;
1252

1353
/** Connect a mock wallet via the app's E2E hook (must run after navigation). */
@@ -43,6 +83,19 @@ export async function mockSorobanRpc(
4383
): Promise<void> {
4484
const adminAddress = options.adminAddress ?? MOCK_WALLET_ADDRESS;
4585

86+
await page.route('**/horizon-testnet.stellar.org/accounts/**', async (route) => {
87+
await route.fulfill({
88+
status: 200,
89+
contentType: 'application/json',
90+
body: JSON.stringify({
91+
id: adminAddress,
92+
account_id: adminAddress,
93+
sequence: '123456789',
94+
balances: [{ balance: '1000.0000000', asset_type: 'native' }],
95+
}),
96+
});
97+
});
98+
4699
await page.route('**/*stellar.org/**', async (route) => {
47100
if (route.request().method() !== 'POST') {
48101
await route.continue();
@@ -103,6 +156,13 @@ export async function mockSorobanRpc(
103156
}
104157

105158
if (method === 'simulateTransaction') {
159+
const params = (body as { params?: { transaction?: string } } | null)
160+
?.params;
161+
const functionName = params?.transaction
162+
? getSimulateFunctionName(params.transaction)
163+
: null;
164+
const resultXdr = scvalXdrForSimulateFunction(functionName);
165+
106166
await route.fulfill({
107167
status: 200,
108168
contentType: 'application/json',
@@ -111,7 +171,7 @@ export async function mockSorobanRpc(
111171
id,
112172
result: {
113173
transactionData: '',
114-
results: [{ xdr: MOCK_ADMIN_SCVAL_XDR }],
174+
results: [{ xdr: resultXdr }],
115175
cost: { cpuInsns: '0', memBytes: '0' },
116176
latestLedger: 12_345,
117177
minResourceFee: '0',

Dechat/dex_with_fiat_frontend/tests/e2e/stellar-fiat-modal.spec.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,10 @@ test.describe('StellarFiatModal E2E Tests', () => {
55
test.beforeEach(async ({ page }) => {
66
await mockSorobanRpc(page);
77
await page.goto('/test-stellar-fiat-modal');
8-
await page.getByRole('dialog', { name: /deposit to bridge/i }).waitFor({
9-
state: 'visible',
8+
const dialog = page.getByRole('dialog', { name: /deposit to bridge/i });
9+
await dialog.waitFor({ state: 'visible' });
10+
await expect(dialog.locator('input[type="number"]').first()).toBeVisible({
11+
timeout: 15_000,
1012
});
1113
});
1214

@@ -42,8 +44,9 @@ test.describe('StellarFiatModal E2E Tests', () => {
4244
});
4345

4446
test('should update amount with preset buttons', async ({ page }) => {
45-
await page.getByRole('button', { name: '5', exact: true }).first().click();
46-
await expect(page.locator('input[type="number"]').first()).toHaveValue('5');
47+
const dialog = page.getByRole('dialog', { name: /deposit to bridge/i });
48+
await dialog.getByRole('button', { name: '5', exact: true }).click();
49+
await expect(dialog.locator('input[type="number"]').first()).toHaveValue('5');
4750
});
4851
});
4952

0 commit comments

Comments
 (0)