Run the sample Playwright JS visual test
Step 1: Setup environment
Requirements
- Npm tool
- Playwright framework
- Access key
- You can generate an Access key using the following instruction – Access key
- Billing unit
- The billing unit is your team’s unique identifier, or just the word “personal” in the case of an individual account.
More information can be found here.
- The billing unit is your team’s unique identifier, or just the word “personal” in the case of an individual account.
Step 2: Prepare the test configuration
After setup up the environment, you need to prepare the test configuration
import {defineConfig} from '@playwright/test';
export default defineConfig({
retries: 0,
timeout: 120_000,
testDir: '../tests'
});Step 3: Add the interaction with visual testing API
After setup up the environment, you need to add the interaction with the visual testing API:
const axios = require('axios');
const FormData = require("form-data");
class VisualTestingAPI {
constructor(baseUrl, apiKey) {
this.baseUrl = baseUrl;
this.apiKey = apiKey;
// Initialize an Axios instance
this.http = axios.create({
baseURL: this.baseUrl,
headers: {
Authorization: `Bearer ${this.apiKey}`,
"Content-Type": "application/json",
},
});
}
async createBuild(inputData) {
const response = await this.http.post("/builds", inputData);
if (response.status === 200) {
return response.data; // VisualBuildData object
} else {
console.log(`Unexpected status code: ${response.status}`);
}
}
async finishBuild(buildId) {
const response = await this.http.post(`/builds/${buildId}/finish`);
if (response.status === 200) {
console.log("Build finished successfully!");
} else {
console.log(`Unexpected status code: ${response.status}`);
}
}
async submitSnapshot(driver, buildId, visualBuildInputData) {
const response = await this.http.post(
`/builds/${buildId}/snapshots`,
visualBuildInputData,
{
headers: {
Authorization: `Bearer ${this.apiKey}`,
'Content-Type': 'multipart/form-data'
},
}
);
if (response.status === 201) {
return response.data; // VisualBuildData object
} else {
console.log(`Unexpected status code: ${response.status}`);
}
}
}Step 4: Run sample test
After setup up the environment and integrating the visual testing API, you can run your first web visual test
'use strict';
import {chromium, expect, test} from '@playwright/test';
const playwright = require('playwright-core');
const mobitruHost = "browserhub-us.mobitru.com";
const mobitruTeamCode = "<TEAM_CODE>";
const mobitruAccessToken = "mobitru_ak_....";
const httpCredentials = {
username: mobitruTeamCode,
password: mobitruAccessToken,
};
const mobitruApiAccessToken = btoa(`${httpCredentials.username}:${httpCredentials.password}`);
const mobitruLandingUrl = 'https://mobitru.com/';
const pwVersion = "1.53.2";
const mobitruVisualHost = 'visual.mobitru.com';
const mobitruVisualBaseUrl = `https://${mobitruVisualHost}/billing/unit/${mobitruTeamCode}/api/v1`;
const visualTestingApi = new VisualTestingAPI(mobitruVisualBaseUrl, mobitruAccessToken);
test.describe("Sample test", () => {
const timeZone = "Europe/Istanbul";
const visualTestName = "visual js demo for playwright";
let browser;
let page;
let visualBuildData;
test.beforeAll(async ({browserName}) => {
test.setTimeout(120000);
const browserType = chromium;
const encodedTimezone = encodeURIComponent(timeZone);
let additionalLaunchParams = "&devtools=true&arg=--use-gl&arg=--use-fake-ui-for-media-stream&arg=--start-maximized";
const wsEndpoint = `wss://${mobitruTeamCode}:${mobitruAccessToken}@${mobitruHost}/playwright/${browserName}/playwright-${pwVersion}?headless=false&env=TZ%3D${encodedTimezone}&env=LANG%3Dde_AT.UTF-8&env=LC_ALL%3Dde_AT.UTF-8&env=LANGUAGE%3Dat:de&env=DISPLAY%3D127.0.0.1:0&host=example.com:99.80.6.196${additionalLaunchParams}`;
browser = await browserType.connect({
timeout: 0,
wsEndpoint: wsEndpoint
});
page = await browser.newPage({
ignoreHTTPSErrors: true,
viewport: {width: 1920, height: 1080}
});
const buildInput = {
name: "Build 1",
project: "JS Web Playwright Automation Demo",
branch: "main"
};
visualBuildData = await visualTestingApi.createBuild(buildInput);
console.log("Build Created:", visualBuildData);
});
test.afterEach('submit snapshot after test', async ({browserName}, testInfo) => {
await submitSnapshot(browserName, page, testInfo.title, visualTestName, visualBuildData, visualTestingApi);
});
test.afterAll('Finish visual testing build', async () => {
await browser.close();
await visualTestingApi.finishBuild(visualBuildData.id);
});
test("Check elements in the Header", async ({}) => {
await page.goto(mobitruLandingUrl);
const contactUsLink = page.locator("button[class*='request-demo']");
await expect(contactUsLink, 'check text of contact us link').toContainText("Request a demo");
});
async function submitSnapshot(browserName, page, name, testName, visualBuildData, visualTestingApi) {
//save screenshot
const tmpFile = tmp.fileSync({postfix: '.png'});
const tmpFilePath = tmpFile.name;
await page.screenshot({path: tmpFilePath});
const formData = new FormData();
formData.append("name", name);
formData.append("testName", testName);
formData.append("suiteName", visualBuildData.project);
formData.append("browser", browserName);
formData.append("image", fs.createReadStream(tmpFilePath), {
filename: path.basename(tmpFilePath),
contentType: 'image/png'
});
await visualTestingApi.submitSnapshot(visualBuildData.id, formData);
}
});