Run the sample Playwright C# visual test

Step 1: Setup environment

Requirements

  • .NET 9.0
  • 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.

Step 2: Add the interaction with visual testing API

After setup up the environment, you need to add the interaction with the visual testing API:

using NUnit.Framework;
using System;
using System.Net.Http;
using System.Net.Http.Headers;
using System.IO;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Drawing;

namespace PlaywrightTests
{

    public class VisualBuildInputData
    {
        [JsonPropertyName("name")]
        public string Name { get; set; }

        [JsonPropertyName("project")]
        public string Project { get; set; }

        [JsonPropertyName("branch")]
        public string Branch { get; set; }
    }

    public class VisualSnapshotInputData
    {
        [JsonPropertyName("name")]
        public string Name { get; set; }

        [JsonPropertyName("buildId")]
        public string BuildId { get; set; }

        [JsonPropertyName("image")]
        public string Image { get; set; } // Path to the image file

        [JsonPropertyName("testName")]
        public string TestName { get; set; }

        [JsonPropertyName("suiteName")]
        public string SuiteName { get; set; }

        [JsonPropertyName("browser")]
        public string Browser { get; set; }
    }

    public class VisualBuildData
    {
        [JsonPropertyName("id")]
        public string Id { get; set; }

        [JsonPropertyName("name")]
        public string Name { get; set; }

        [JsonPropertyName("project")]
        public string Project { get; set; }

        [JsonPropertyName("branch")]
        public string Branch { get; set; }

        [JsonPropertyName("status")]
        public string Status { get; set; }
    }

    public class VisualSnapshotData
    {
        [JsonPropertyName("id")]
        public string Id { get; set; }

        [JsonPropertyName("name")]
        public string Name { get; set; }

        [JsonPropertyName("buildId")]
        public string BuildId { get; set; }

        [JsonPropertyName("testName")]
        public string TestName { get; set; }

        [JsonPropertyName("suiteName")]
        public string SuiteName { get; set; }

        [JsonPropertyName("browser")]
        public string Browser { get; set; }
    }



    public class VisualTestingAPI
    {
        private readonly HttpClient _httpClient;

        public VisualTestingAPI(string baseUrl, string apiKey)
        {
            _httpClient = new HttpClient
            {
                BaseAddress = new Uri(baseUrl)
            };
            _httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", apiKey);;
            _httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
        }

        public VisualBuildData CreateBuild(VisualBuildInputData inputData)
        {
            var jsonContent = JsonSerializer.Serialize(inputData);
            var stringContent = new StringContent(jsonContent, System.Text.Encoding.UTF8, "application/json");

            var response = _httpClient.PostAsync("builds", stringContent).Result; // Wait for response synchronously
            response.EnsureSuccessStatusCode();

            var responseContent = response.Content.ReadAsStringAsync().Result;
            return JsonSerializer.Deserialize<VisualBuildData>(responseContent);

        }

        public void FinishBuild(string buildId)
        {
            var response = _httpClient.PostAsync($"builds/{buildId}/finish", null).Result; // Wait synchronously
            response.EnsureSuccessStatusCode();

            Console.WriteLine("Build finished successfully");
        }

        public VisualSnapshotData SubmitSnapshot(VisualSnapshotInputData inputData)
        {
            // Prepare Multipart/Form-Data content
            var formContent = new MultipartFormDataContent
            {
                { new StringContent(inputData.Name), "name" },
                { new StringContent(inputData.TestName), "testName" },
                { new StringContent(inputData.SuiteName), "suiteName" },
                { new StringContent(inputData.Browser), "browser" }
            };

            // Attach image file
            if (File.Exists(inputData.Image))
            {
                var fileStream = new FileStream(inputData.Image, FileMode.Open, FileAccess.Read);
                var fileContent = new StreamContent(fileStream);
                fileContent.Headers.ContentType = new MediaTypeHeaderValue("image/png");
                formContent.Add(fileContent, "image", Path.GetFileName(inputData.Image));
            }
            else
            {
                throw new FileNotFoundException("Image file not found.", inputData.Image);
            }

            var response = _httpClient.PostAsync($"builds/{inputData.BuildId}/snapshots", formContent).Result; // Wait synchronously
            response.EnsureSuccessStatusCode();

            var responseContent = response.Content.ReadAsStringAsync().Result;
            return JsonSerializer.Deserialize<VisualSnapshotData>(responseContent);

        }
    }
}

Step 3: Run sample test

After setup up the environment and integrating the visual testing API, you can run your first web visual test

using Microsoft.Playwright;
using NUnit.Framework;
using NUnit.Framework.Legacy;
using OpenQA.Selenium;
using OpenQA.Selenium.Appium;
using OpenQA.Selenium.Appium.iOS;
using OpenQA.Selenium.Support.UI;
using System;
using System.Collections.Generic;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;

namespace PlaywrightTests
{
    public class PlaywrightDemoTest
    {

        private const string PROJECT_NAME = "<TEAM_CODE>";
        private const string API_KEY = "mobitru_ak_...";
        private const string BROWSER_HUB = "browserhub-us.mobitru.com";
        private const string BROWSER_NAME = "chrome";
        private const string PW_VERSION = "1.55.0";

        const string VisuaTestingHost = "visual-stage.mobitru.com";
        const string VisualTestingBaseUrl = $"""https://{VisuaTestingHost}/billing/unit/{PROJECT_NAME}/api/v1/""";

        const string VisualTestName = "visual c# demo for playwright";

        private VisualBuildData visualBuildData;
        private readonly VisualTestingAPI visualTestingApi = new VisualTestingAPI(VisualTestingBaseUrl, API_KEY);

        [SetUp]
        public void Setup()
        {
            // Step 1: Create a visual build
            var buildInput = new VisualBuildInputData
            {
                Name = "Build 1",
                Project = "C# Web Playwright Automation Demo",
                Branch = "main"
            };
            visualBuildData = visualTestingApi.CreateBuild(buildInput);
        }


        [Test]
        public void TestPlaywrightDemo()
        {

            string wsEndpoint = $"wss://{PROJECT_NAME}:{API_KEY}@{BROWSER_HUB}/playwright/{BROWSER_NAME}/playwright-{PW_VERSION}?enableVideo=false";

            using var playwright = Microsoft.Playwright.Playwright.CreateAsync().GetAwaiter().GetResult();
            var browser = playwright.Chromium.ConnectAsync(wsEndpoint).GetAwaiter().GetResult();
            var page = browser.NewPageAsync().GetAwaiter().GetResult();
            page.GotoAsync("https://www.mobitru.com/").GetAwaiter().GetResult();

            string httpCredentials = $"{PROJECT_NAME}:{API_KEY}";

            var isButtonVisible = page.Locator("button[class*='request-demo']").IsVisibleAsync().GetAwaiter().GetResult();
            Assert.That(isButtonVisible, Is.True, "The 'Request Demo' button should be visible, but it was not");

            TakeAndSubmitScreenshot(page, "after_login", VisualTestName, visualBuildData, visualTestingApi);

            browser.CloseAsync().GetAwaiter().GetResult();
        }

        [TearDown]
        public void TearDown()
        {
            visualTestingApi.FinishBuild(visualBuildData.Id);
        }

        private void TakeAndSubmitScreenshot(IPage page, String name, String testName, VisualBuildData buildData, VisualTestingAPI visualTestingApi)
        {
            var browserName = page.Context.Browser.BrowserType.Name;
            string fileName = System.IO.Path.GetTempPath() + Guid.NewGuid().ToString() + ".png";
            page.ScreenshotAsync(new() { Path = fileName }).Wait();
            var snapshotInput = new VisualSnapshotInputData
            {
                BuildId = buildData.Id,
                Name = name,
                TestName = testName,
                SuiteName = buildData.Project,
                Browser = browserName,
                Image = fileName
            };

            var snapshotData = visualTestingApi.SubmitSnapshot(snapshotInput);
            Console.WriteLine($"Snapshot Submitted: {snapshotData.Id}");
        }


    }
}

Scroll to Top