I have a Svelte application that interact with Mapbox-gl and Line-Awesome. I'm defining a test suite for that using Playwright. My playwright configuration is:
import { defineConfig } from '@playwright/test';export default defineConfig({ // Dirs testDir: './test', outputDir: './test/out', // Run Setup fullyParallel: true, reporter: [ ['html'], ['json', { outputFile: 'test-results.json' }], ], // Setup Assertions Timeout expect: { timeout: 10000, }, use: { baseURL: 'http://localhost/test/home', headless: true, // Recording Options trace: 'on-first-retry', video: 'on-first-retry', screenshot: 'only-on-failure', // Miscellaneous acceptDownloads: true, ignoreHTTPSErrors: true, bypassCSP: true, },});
Then I defined two tests:
import { test, expect } from '@playwright/test';const users = [ { userId: 'fake.user@randomdomain.com', userRole: 'AdminUser' }, { userId: 'fake.user@randomdomain.com', userRole: 'AuthorizedUser' }, { userId: 'fake.user@randomdomain.com', userRole: 'CompanyUser' },];test.describe.parallel('ShareViewTest', () => { users.forEach(({ userId: generatorId, userRole: generatorRole }) => { users.forEach(({ userId: openerId, userRole: openerRole }) => { /* if (generatorId == openerId && generatorRole == openerRole){ test.skip() }*/ if(generatorId == ''){ return } else{ test(`From (${generatorId}, ${generatorRole}) to (${openerId}, ${openerRole})`, async ({ browser }) => { let generatorContex = await browser.newContext(); let openerContext = await browser.newContext(); let generatorPage = await generatorContex.newPage(); await generatorPage.setExtraHTTPHeaders({'X-Test-User': generatorId,'X-Test-Role': generatorRole, }); await generatorPage.goto(''); await generatorPage.waitForSelector('.mapboxgl-canvas'); await generatorPage.waitForTimeout(5000) // Hack for fly animation await generatorPage.waitForTimeout(1000); await generatorPage.getByTitle('Share View').click(); const linkArea = generatorPage.getByTestId('share-link'); const shareLink = await linkArea.inputValue(); // Step 2: Open link as second user let openerPage = await openerContext.newPage(); await openerPage.setExtraHTTPHeaders({'X-Test-User': openerId,'X-Test-Role': openerRole, }); await openerPage.goto(shareLink); await openerPage.waitForSelector('.mapboxgl-canvas'); await openerPage.waitForTimeout(5000) // Hack for fly animation await openerPage.waitForTimeout(1000); await openerPage.getByTitle('Share View').click(); const newLinkAread = openerPage.getByTestId('share-link'); const newShareLink = await newLinkAread.inputValue(); if (generatorId == openerId || ['AdminUser', 'AuthorizedUser'].includes(openerId)) { expect(newShareLink).toBe(shareLink); } else { expect(newShareLink).not.toBe(shareLink)!; } }); } }); });});
and
import { test, expect } from '@playwright/test';const userRoles = ['AdminUser', 'AuthorizedUser', 'CompanyUser'];const testID = 'AAAAAA-BBBBBB-CCCCCC-DDD';const makeRandomString = () => { let result = ''; const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; const charactersLength = characters.length; let counter = 0; while (counter < 10) { result += characters.charAt(Math.floor(Math.random() * charactersLength)); counter += 1; } return result;};test.describe.parallel('ModifyInfoTest', () => { userRoles.forEach((role) => { test(`As ${role}`, async ({ browser }) => { let context = await browser.newContext(); let userPage = await context.newPage(); await userPage.setExtraHTTPHeaders({'X-Test-Role': role, }); await userPage.goto(''); await userPage.goto(`#/seq/${testID}`); await userPage.waitForLoadState('networkidle') await userPage.waitForTimeout(5000) await userPage.getByTestId(`analysis-${testID}`).isVisible(); const fieldTestId = '[data-testid="seqinfo-user"]'; const isInputField = await userPage.evaluate((selector) => { const element = document.querySelector(selector); return element && element.tagName.toLowerCase() === 'input'; }, fieldTestId); if (role == 'CompanyUser') { expect(isInputField).toBeFalsy(); } else { await userPage.getByTestId('seqinfo-user').click(); await userPage.getByTestId('seqinfo-user').fill(`${makeRandomString()}@companydomain.com`); } // Modifying Location await userPage.getByTestId('seqinfo-location').click(); await userPage.getByTestId('seqinfo-location').fill(makeRandomString()); // Modifying Description await userPage.getByTestId('seqinfo-description').click(); await userPage.getByTestId('seqinfo-description').fill(makeRandomString()); await userPage.waitForLoadState('networkidle') await userPage.waitForTimeout(5000) await expect(userPage.getByTestId('update-button')).toBeVisible(); }); });});
The first is failing because when I initialize the map in my app with:
map = new mapbox.Map({ container: mapContainer, accessToken: config.mapboxAccessToken, style: getStyleURL(queryInitStyle), center: [0, 20], zoom: 2, maxZoom: 26, attributionControl: false, logoPosition: 'bottom-right', preserveDrawingBuffer: true, testMode: isTestingEnv,});
the operation sometimes is slightly delayed and when I get the link through mapContainer.getQueryString()
it may differ. This method simply returns a query for mabox view parameters in order to zoom on the same point (and it works, manually tested multiple times).The second fails because the icon where I should click on is not visible. The icond would be:
<h2 class="info-title__link no-print" title="Update" style="visibility: {toUpdate}" on:click={updateInfo}><i class="las la-sync" data-testid="update-button"/></h2>
and the icons are loaded in index.html
with:
<link rel="stylesheet" href="https://maxst.icons8.com/vue-static/landings/line-awesome/line-awesome/1.3.0/css/line-awesome.min.css"/>
As you can see, in the first tests I tried different wait functions but the test is still flaky. For the second, the icons are never loaded (in general) and so the expect.toBeVisible()
is always false
. How do I solve those?
I tried to test svelte app with playwright but it fails loading icons and map from linew-awesome and mapbox