ecosystems.spec.ts
1 import { test as base, expect } from '@playwright/test'; 2 import createEcosystemPayload from './create-ecosystem-payload.json' with { type: 'json' }; 3 import { ConnectedSession, TEST_ADDRESSES } from './fixtures/ConnectedSession'; 4 import workerUniqueString from './utils/worker-unique-string'; 5 6 const test = base.extend<{ 7 connectedSession: ConnectedSession; 8 }>({ 9 connectedSession: async ({ page }, use) => { 10 const connectedSession = new ConnectedSession(page, TEST_ADDRESSES[0]); 11 await connectedSession.goto(); 12 await connectedSession.connect(); 13 14 await use(connectedSession); 15 }, 16 }); 17 18 test('ecosystems donation flow', async ({ connectedSession, request }, testInfo) => { 19 const { page } = connectedSession; 20 test.setTimeout(240_000); 21 22 const ecosystemName = workerUniqueString(testInfo, 'Test Ecosystem'); 23 24 // create the ecosystem 25 const ecosystemCreatedResponse = await request.post('http://localhost:5173/api/ecosystems', { 26 data: { 27 ...createEcosystemPayload, 28 name: ecosystemName, 29 }, 30 }); 31 expect(ecosystemCreatedResponse.ok()).toBeTruthy(); 32 33 // wait for ecosystem to be in the correct state for deployment 34 await page.waitForTimeout(5_000); 35 36 // deploy the ecosystem 37 const { id } = await ecosystemCreatedResponse.json(); 38 const ecosystemDeployedResponse = await request.post( 39 `http://localhost:5173/api/ecosystems/${id}/deploy`, 40 ); 41 expect(ecosystemDeployedResponse.ok()).toBeTruthy(); 42 43 await page.getByTestId('sidenav-item-Ecosystems').click(); 44 await expect(page.getByRole('heading', { name: 'Ecosystems' })).toBeVisible(); 45 46 // wait for the api to return an ecosystem that we can support 47 // by checking for the appearance of funds donated 48 49 let fundsDisplaying = false; 50 51 while (!fundsDisplaying) { 52 await page.reload(); 53 await page.getByRole('button', { name: 'Connect', exact: true }).click(); 54 await page.getByTestId('sidenav-item-Ecosystems').click(); 55 // NOTE: strategically placed timeout! 56 await page.waitForTimeout(1_000); 57 const fundsCount = await page.getByTestId(`ecosystem-card-${id}`).getByText('Funds').count(); 58 59 fundsDisplaying = fundsCount > 0; 60 } 61 62 // navigate to the created ecosystem 63 await page.locator(`text=${ecosystemName}`).nth(0).click(); 64 65 // verify that the distribution details are correct 66 await page.waitForTimeout(1_000); 67 expect(await page.getByText('50%').count()).toBe(2); 68 69 // perform a one-time donation 70 await page.getByRole('button', { name: 'Support' }).nth(0).click(); 71 await page.getByRole('button', { name: 'One-time donation' }).first().click(); 72 await page.getByText('Test Token').click(); 73 74 // Wait for token balance to load completely before interacting with amount input 75 // The token balance fetch is async, and while loading, the input value gets reset to '0' 76 // This can cause a race condition where Playwright's fill() conflicts with the reactive reset 77 await expect(page.getByText('TEST', { exact: true }).last()).toBeVisible({ timeout: 10000 }); 78 79 // Additional safety: wait a brief moment for all reactive statements to settle 80 await page.waitForTimeout(500); 81 82 await page.getByRole('spinbutton', { name: 'TEST Amount' }).click(); 83 await page.getByRole('spinbutton', { name: 'TEST Amount' }).fill('10'); 84 await page.getByRole('button', { name: 'Confirm in your wallet' }).click(); 85 await page.getByRole('button', { name: 'Continue' }).click(); 86 await page.getByRole('button', { name: 'Got it' }).click(); 87 88 // verify that support shows the donation 89 await expect(page.getByText('10 TEST').nth(0)).toBeVisible(); 90 91 // verify that the ecosystem support has propagated to the relevant projects. 92 const page1Promise = page.waitForEvent('popup'); 93 // skip root node 94 await page.getByRole('link', { name: createEcosystemPayload.graph.nodes[1].projectName }).click(); 95 const page1 = await page1Promise; 96 await expect(page1.locator(`text=${ecosystemName}`).nth(0)).toBeVisible(); 97 await expect(page1.getByText('50%').first()).toBeVisible(); 98 });