sorcha-ui

Sorcha UI Development Skill

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "sorcha-ui" with this command: npx skills add stuartf303/sorcha/stuartf303-sorcha-sorcha-ui

Sorcha UI Development Skill

Test-driven UI development for Sorcha.UI. Every page change is paired with Playwright E2E tests that run against the Docker environment (docker-compose up -d ). Tests automatically validate console errors, network failures, MudBlazor CSS health, and take screenshots on failure.

Prerequisites

Docker must be running with all services:

docker-compose up -d

UI at http://localhost:5400 | API Gateway at http://localhost:80

Login: admin@sorcha.local / Dev_Pass_2025!

Workflow: Building a Page

For every page you build or modify, follow these steps in order:

Step 1: Create the Page Object

Create tests/Sorcha.UI.E2E.Tests/PageObjects/{PageName}Page.cs :

using Microsoft.Playwright; using Sorcha.UI.E2E.Tests.Infrastructure; using Sorcha.UI.E2E.Tests.PageObjects.Shared;

namespace Sorcha.UI.E2E.Tests.PageObjects;

public class WalletListPage { private readonly IPage _page; public WalletListPage(IPage page) => _page = page;

// Use data-testid as primary selector strategy
public ILocator WalletCards => MudBlazorHelpers.TestIdPrefix(_page, "wallet-card-");
public ILocator CreateButton => MudBlazorHelpers.TestId(_page, "create-wallet-btn");
public ILocator EmptyState => MudBlazorHelpers.TestId(_page, "wallet-empty-state");
public ILocator SearchInput => _page.Locator("input[placeholder*='Search']");

// Fallback to MudBlazor class selectors
public ILocator Table => MudBlazorHelpers.Table(_page);
public ILocator LoadingSpinner => MudBlazorHelpers.CircularProgress(_page);

public async Task NavigateAsync()
{
    await _page.GotoAsync($"{TestConstants.UiWebUrl}{TestConstants.AuthenticatedRoutes.Wallets}");
    await _page.WaitForLoadStateAsync(LoadState.NetworkIdle);
    await MudBlazorHelpers.WaitForBlazorAsync(_page);
}

public async Task<int> GetWalletCountAsync() => await WalletCards.CountAsync();
public async Task<bool> IsEmptyStateVisibleAsync() =>
    await EmptyState.CountAsync() > 0 && await EmptyState.IsVisibleAsync();

}

Step 2: Write the Playwright Tests (Test-First)

Create tests/Sorcha.UI.E2E.Tests/Docker/{Feature}Tests.cs :

using Sorcha.UI.E2E.Tests.Infrastructure; using Sorcha.UI.E2E.Tests.PageObjects;

namespace Sorcha.UI.E2E.Tests.Docker;

[Parallelizable(ParallelScope.Self)] [TestFixture] [Category("Docker")] [Category("Wallets")] [Category("Authenticated")] public class WalletListTests : AuthenticatedDockerTestBase { private WalletListPage _walletList = null!;

[SetUp]
public override async Task BaseSetUp()
{
    await base.BaseSetUp();
    _walletList = new WalletListPage(Page);
}

[Test]
[Retry(2)]
public async Task WalletList_LoadsWithoutErrors()
{
    await NavigateAuthenticatedAsync(TestConstants.AuthenticatedRoutes.Wallets);
    // Base class automatically checks console errors, network 5xx, CSS health
}

[Test]
public async Task WalletList_ShowsEmptyStateOrWallets()
{
    await _walletList.NavigateAsync();
    var count = await _walletList.GetWalletCountAsync();
    if (count == 0)
    {
        Assert.That(await _walletList.IsEmptyStateVisibleAsync(), Is.True,
            "Empty system should show empty state message");
    }
    else
    {
        Assert.That(count, Is.GreaterThan(0));
    }
}

}

Step 3: Build the Blazor Page

Edit src/Apps/Sorcha.UI/Sorcha.UI.Web.Client/Pages/{Page}.razor :

@page "/wallets" @layout MainLayout @rendermode @(new InteractiveWebAssemblyRenderMode(prerender: false)) @attribute [Authorize] @inject HttpClient Http

<PageTitle>Wallets - Sorcha</PageTitle>

@if (_isLoading) { <MudProgressCircular Indeterminate="true" data-testid="wallet-loading" /> } else if (_wallets.Count == 0) { <MudAlert Severity="Severity.Info" data-testid="wallet-empty-state"> No wallets found. Create your first wallet to get started. </MudAlert> } else { @foreach (var wallet in _wallets) { <MudCard data-testid="wallet-card-@wallet.Id" Class="mb-3"> <MudCardContent> <MudText Typo="Typo.h6">@wallet.Name</MudText> </MudCardContent> </MudCard> } }

<MudButton data-testid="create-wallet-btn" Variant="Variant.Filled" Color="Color.Primary" Href="wallets/create"> Create Wallet </MudButton>

Step 4: Run Tests

Run tests for the feature you just built

dotnet test tests/Sorcha.UI.E2E.Tests --filter "Category=Wallets"

Run all smoke tests (fast CI gate)

dotnet test tests/Sorcha.UI.E2E.Tests --filter "Category=Smoke"

Run all Docker tests

dotnet test tests/Sorcha.UI.E2E.Tests --filter "Category=Docker"

Step 5: Check Artifacts on Failure

Screenshots are saved to tests/Sorcha.UI.E2E.Tests/bin/Debug/net10.0/screenshots/ on any test failure. Console errors and network failures are reported in the test output.

Key Concepts

Concept Usage Location

DockerTestBase

Unauthenticated tests with auto error capture Infrastructure/DockerTestBase.cs

AuthenticatedDockerTestBase

Login once, reuse auth state across tests Infrastructure/AuthenticatedDockerTestBase.cs

TestConstants

URLs, credentials, routes, timeouts Infrastructure/TestConstants.cs

Page Objects Encapsulate selectors and actions per page PageObjects/*.cs

MudBlazorHelpers

Shared MudBlazor locators and layout validation PageObjects/Shared/MudBlazorHelpers.cs

data-testid

Primary selector strategy for resilient tests Added to Razor components

Categories Filter tests by feature or concern [Category("Wallets")] on test classes

Test Inheritance

PageTest (Playwright NUnit) └── DockerTestBase (console errors, network failures, screenshots) ├── ComponentHealthTests, LoginTests (unauthenticated) └── AuthenticatedDockerTestBase (login once, reuse state, layout health) ├── DashboardTests ├── NavigationTests ├── WalletTests └── ... (one per feature area)

Test Categories

Category Scope Use

Smoke

All pages load, no JS errors CI gate

Docker

All tests targeting Docker Full Docker suite

Auth

Login, logout, redirects Authentication features

Authenticated

All tests needing login Post-login features

Dashboard

Dashboard page Dashboard development

Navigation

Drawer, app bar, routing Layout changes

Components

CSS, MudBlazor, responsive Style/component changes

Wallets

Wallet pages Wallet features

Blueprints

Blueprint pages Blueprint features

Registers

Register pages Register features

Schemas

Schema library Schema features

Admin

Administration pages Admin features

File Locations

What Where

Blazor pages src/Apps/Sorcha.UI/Sorcha.UI.Web.Client/Pages/

Shared components src/Apps/Sorcha.UI/Sorcha.UI.Core/

Layout src/Apps/Sorcha.UI/Sorcha.UI.Web.Client/Components/Layout/

Test infrastructure tests/Sorcha.UI.E2E.Tests/Infrastructure/

Page objects tests/Sorcha.UI.E2E.Tests/PageObjects/

Docker tests tests/Sorcha.UI.E2E.Tests/Docker/

MudBlazor helpers tests/Sorcha.UI.E2E.Tests/PageObjects/Shared/MudBlazorHelpers.cs

See Also

  • patterns - Page implementation and test patterns

  • workflows - Development workflow and checklist

Related Skills

  • See the blazor skill for Blazor WASM component architecture

  • See the playwright skill for Playwright API reference

  • See the frontend-design skill for MudBlazor styling

  • See the minimal-apis skill for backend API endpoints the pages call

  • See the jwt skill for authentication token handling

Documentation Resources

Fetch latest Playwright .NET and MudBlazor documentation with Context7.

Library IDs:

  • /websites/playwright_dev_dotnet (Playwright .NET)

  • /websites/mudblazor (MudBlazor component library)

Recommended Queries:

  • "Locators selectors data-testid"

  • "NUnit test fixtures parallel"

  • "MudBlazor card table dialog"

  • "MudBlazor form validation"

  • "Browser storage state authentication"

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

Coding

sorcha-cli

No summary provided by upstream source.

Repository SourceNeeds Review
General

entity-framework

No summary provided by upstream source.

Repository SourceNeeds Review
General

signalr

No summary provided by upstream source.

Repository SourceNeeds Review