Skip to main content
net6.0net8.0.NETStandard2.0

Π‘ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ° для взаимодСйствия с ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Π°ΠΌΠΈ @skbkontur/react-ui ΠΏΡ€ΠΈ тСстировании с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ Playwright"

Published
Jan 20, 2026
9mo ago
Total Downloads
23.3K
23,306

Install

dotnet add package SkbKontur.Playwright.ReactUI.Controls --version 4.0.0-betac761fd74
ProductVersions
.NET
net6.0net8.0
.NET Standard
netstandard2.0

README

Playwright.ReactUI.Controls

Π‘ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ° ΠΏΡ€Π΅Π΄Π½Π°Π·Π½Π°Ρ‡Π΅Π½Π° для взаимодСйствия с ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Π°ΠΌΠΈ @skbkontur/react-ui ΠΏΡ€ΠΈ тСстировании с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ Playwright.NET

Как ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ

Π’ качСствС ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π° взят ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ Input:
<Input data-tid="InputId" />

Π˜Π½ΠΈΡ†ΠΈΠ°Π»ΠΈΠ·Π°Ρ†ΠΈΡ
var input = new Input(page.GetByTestId("InputId"));

ВзаимодСйствиС
await input.FillAsync("newValue").ConfigureAwait(false);

ΠŸΡ€ΠΎΠ²Π΅Ρ€ΠΊΠ°
await input.ExpectV2().ToHaveValueAsync("newValue").ConfigureAwait(false);

Π‘ΠΎΠ·Π΄Π°Π½ΠΈΠ΅ своСго ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Π°

public class Header : ControlBase
{
    public Header(ILocator rootLocator)
        : base(rootLocator)
    {
        SomeInput = new Input(rootLocator.GetByTestId("InputId"));
    }
    
    public Input SomeInput { get; }
}

Π‘ΠΎΠ·Π΄Π°Π½ΠΈΠ΅ Π½Π°Π±ΠΎΡ€Π° ассСртов ΠΊ своСму ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Ρƒ

public class HeaderAssertions : ControlBaseAssertionsV2
{
    private readonly Header header;
    
    public HeaderAssertions(Header header)
        : base(header)
    {
        this.header = header;
    }
    
    public async Task ToBeVisibleAsync()
        => await header.RootLocator.Expect().ToBeVisibleAsync().ConfigureAwait(false);
}

Для "ΠΏΠΎΠ΄ΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΡ" Π½Π°Π±ΠΎΡ€Π° достаточно Π΄ΠΎΠ±Π°Π²ΠΈΡ‚ΡŒ ΠΊ своСму ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Ρƒ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΡƒΡŽ строчку:

public new HeaderAssertions ExpectV2() => new(this);

Π Π°ΡΡˆΠΈΡ€Π΅Π½ΠΈΡ SkbKontur.Playwright.ReactUI.Controls.Extensions

ΠŸΡ€Π΅Π΄ΠΎΡΡ‚Π°Π²Π»ΡΠ΅Ρ‚ΡΡ Π½Π°Π±ΠΎΡ€ Ρ€Π°ΡΡˆΠΈΡ€Π΅Π½ΠΈΠΉ, Π° Ρ‚Π°ΠΊΠΆΠ΅ Π°Ρ‚Ρ€ΠΈΠ±ΡƒΡ‚Ρ‹ для автозаполнСния ΠΊΠΎΠ½Ρ‚Ρ€ΠΎΠ»ΠΎΠ² Π² PageObjects ΠΈ PageElements

Как ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ

ΠŸΡ€ΠΈΠΌΠ΅Ρ€Ρ‹ Ρ€Π°ΡΡˆΠΈΡ€Π΅Π½ΠΈΠΉ для ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Π° Input:

  • await input.AppendTextAsync("newValue").ConfigureAwait(false); - Π΄ΠΎΠ±Π°Π²Π»Π΅Π½ΠΈΠ΅ значСния newValue ΠΊ ΡƒΠΆΠ΅ ΡΡƒΡ‰Π΅ΡΡ‚Π²ΡƒΡŽΡ‰Π΅ΠΌΡƒ Π² Input
  • await input.WaitToBeVisibleAsync().ConfigureAwait(false); - ΠΎΠΆΠΈΠ΄Π°Π½ΠΈΠ΅ видимости ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Π° Π½Π° страницС
  • await input.WaitToHaveValueAsync("TODO").ConfigureAwait(false); - ΠΎΠΆΠΈΠ΄Π°Π½ΠΈΠ΅ значСния TODO Π² Input'e

AutoFillControlsAttribute

Π§Ρ‚ΠΎΠ±Ρ‹ Π²ΠΎΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒΡΡ Π°Ρ‚Ρ€ΠΈΠ±ΡƒΡ‚ΠΎΠΌ AutoFillControls Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰Π΅Π΅:

  • Π‘Ρ‚Ρ€Π°Π½ΠΈΡ†Π° (PageObject) Π΄ΠΎΠ»ΠΆΠ½Π° Π½Π°ΡΠ»Π΅Π΄ΠΎΠ²Π°Ρ‚ΡŒΡΡ ΠΎΡ‚ PageBase. Если Ρƒ вас Π΅ΡΡ‚ΡŒ свой Π±Π°Π·ΠΎΠ²Ρ‹ΠΉ класс страницы, Ρ‚ΠΎ ΠΎΠ½ Π΄ΠΎΠ»ΠΆΠ΅Π½ Π½Π°ΡΠ»Π΅Π΄ΠΎΠ²Π°Ρ‚ΡŒ PageBase
  • Боставной / слоТный ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ (PageElement), Ρ‚.Π΅. ΠΊΠΎΠ½Ρ‚Ρ€ΠΎΠ», ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ состоит ΠΈΠ· Π½Π΅ΡΠΊΠΎΠ»ΡŒΠΊΠΈΡ… ΠΊΠΎΠ½Ρ‚Ρ€ΠΎΠ»ΠΎΠ² (см. ΠΏΡ€ΠΈΠΌΠ΅Ρ€ Π½ΠΈΠΆΠ΅), Π΄ΠΎΠ»ΠΆΠ΅Π½ Π½Π°ΡΠ»Π΅Π΄ΠΎΠ²Π°Ρ‚ΡŒΡΡ ΠΎΡ‚ CompoundControlBase, Π° Π½Π΅ ControlBase
  • На PageObject / PageElement Π½Π°Π²Π΅ΡΠΈΡ‚ΡŒ Π°Ρ‚Ρ€ΠΈΠ±ΡƒΡ‚ [AutoFillControls]

Для заполнСния самих ΠΊΠΎΠ½Ρ‚Ρ€ΠΎΠ»ΠΎΠ² сущСствуСт нСсколько Π°Ρ‚Ρ€ΠΈΠ±ΡƒΡ‚ΠΎΠ²:

  • RootByTid - ΠΈΡ‰Π΅Ρ‚ ΠΊΠΎΠ½Ρ‚Ρ€ΠΎΠ» ΠΏΠΎ ΠΏΠ΅Ρ€Π΅Π΄Π°Π½Π½ΠΎΠΌΡƒ data-tid'Ρƒ
  • RootByLocator - ΠΈΡ‰Π΅Ρ‚ ΠΊΠΎΠ½Ρ‚Ρ€ΠΎΠ» ΠΏΠΎ ΠΏΠ΅Ρ€Π΅Π΄Π°Π½Π½ΠΎΠΌΡƒ сСлСктору (css / xpath)
  • ChildByTid - ΠΈΡ‰Π΅Ρ‚ элСмСнт списка ΠΏΠΎ ΠΏΠ΅Ρ€Π΅Π΄Π°Π½Π½ΠΎΠΌΡƒ data-tid'Ρƒ; ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ для ΠΈΠ½ΠΈΡ†ΠΈΠ°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ ControlList совмСстно с RootByTid / RootByLocator
  • ChildByLocator - ΠΈΡ‰Π΅Ρ‚ элСмСнт списка ΠΏΠΎ ΠΏΠ΅Ρ€Π΅Π΄Π°Π½Π½ΠΎΠΌΡƒ сСлСктору (css / xpath); ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ для ΠΈΠ½ΠΈΡ†ΠΈΠ°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ ControlList совмСстно с RootByTid / RootByLocator
  • SkipAutoFillControl - Ссли ΠΏΠΎ ΠΊΠ°ΠΊΠΈΠΌ-Ρ‚ΠΎ ΠΏΡ€ΠΈΡ‡ΠΈΠ½Π°ΠΌ ΠΊΠΎΠ½Ρ‚Ρ€ΠΎΠ» нСльзя Π°Π²Ρ‚ΠΎΠ·Π°ΠΏΠΎΠ»Π½ΠΈΡ‚ΡŒ, Ρ‚ΠΎ Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ Π½Π°Π²Π΅ΡΠΈΡ‚ΡŒ Π½Π° Π½Π΅Π³ΠΎ Π°Ρ‚Ρ€ΠΈΠ±ΡƒΡ‚ SkipAutoFillControl ΠΈ ΠΈΠ½ΠΈΡ†ΠΈΠ°Π»ΠΈΠ·ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ Π² конструкторС

Π‘ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ° прСдоставляСт Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ‚ΡŒ ΡΠΎΠ·Π΄Π°Ρ‚ΡŒ свой Π°Ρ‚Ρ€ΠΈΠ±ΡƒΡ‚ для заполнСния ΠΊΠΎΠ½Ρ‚Ρ€ΠΎΠ»ΠΎΠ². Для этого Π½Π°Π΄ΠΎ Ρ€Π΅Π°Π»ΠΈΠ·ΠΎΠ²Π°Ρ‚ΡŒ IRootLocatorAttribute ΠΈ(ΠΈΠ»ΠΈ) IChildLocatorAttribute (см. ΠΏΡ€ΠΈΠΌΠ΅Ρ€ Π½ΠΈΠΆΠ΅)
Если появится ΠΆΠ΅Π»Π°Π½ΠΈΠ΅ Ρ€Π΅Π°Π»ΠΈΠ·ΠΎΠ²Π°Ρ‚ΡŒ свой Π°Ρ‚Ρ€ΠΈΠ±ΡƒΡ‚, Ρ‚ΠΎ Π»ΡƒΡ‡ΡˆΠ΅ сначало ΠΏΡ€ΠΈΠΉΡ‚ΠΈ Π² мСня. Π’ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎ ваш Π°Ρ‚Ρ€ΠΈΠ±ΡƒΡ‚ Π»ΡƒΡ‡ΡˆΠ΅ ΠΏΠΎΠΌΠ΅ΡΡ‚ΠΈΡ‚ΡŒ Π² Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΡƒ

Если Π½ΠΈΠΊΠ°ΠΊΠΎΠΉ Π°Ρ‚Ρ€ΠΈΠ±ΡƒΡ‚ заполнСния ΠΊΠΎΠ½Ρ‚Ρ€ΠΎΠ»Π° Π½Π΅ ΡƒΠΊΠ°Π·Π°Π½, Ρ‚ΠΎ AutoFillControls Π±ΡƒΠ΄Π΅Ρ‚ ΠΈΡΠΊΠ°Ρ‚ΡŒ ΠΊΠΎΠ½Ρ‚Ρ€ΠΎΠ» ΠΏΠΎ data-tid'Ρƒ ΠΈΠΌΠ΅Π½ΠΈ свойства

ΠŸΡ€ΠΈΠΌΠ΅Ρ€Ρ‹ использования AutoFillControlsAttribute

// PageObject
[AutoFillControls]
public class TestPage : PageBase
{
    public TestPage(IPage page)
        : base(page)
    {
    }

    // ΠšΠΎΠ½Ρ‚Ρ€ΠΎΠ» инициализируСтся с data-tid'ΠΎΠΌ Compound
    public Compound Compound { get; init; }

    // ΠšΠΎΠ½Ρ‚Ρ€ΠΎΠ» инициализируСтся с data-tid'ΠΎΠΌ LinkId
    [RootByTid("LinkId")]
    public Link Link { get; init; }

    // ΠšΠΎΠ½Ρ‚Ρ€ΠΎΠ» инициализируСтся с Π»ΠΎΠΊΠ°Ρ‚ΠΎΡ€ΠΎΠΌ LocatorId (здСсь ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ css / xpath)
    [RootByLocator("LocatorId")]
    public Input Input { get; init; }
}

// PageElement
[AutoFillControls]
public class Compound : CompoundControlBase
{
    public Compound(ILocator rootLocator)
        : base(rootLocator)
    {
        Button = new Button(rootLocator.GetByText("ButtonId"));
    }

    // ΠšΠΎΠ½Ρ‚Ρ€ΠΎΠ» инициализируСтся Π² конструкторС ΠΈ Π½Π΅ Π±ΡƒΠ΄Π΅Ρ‚ Π°Π²Ρ‚ΠΎΠ·Π°ΠΏΠΎΠ»Π½ΡΡ‚ΡŒΡΡ
    [SkipAutoFillControl]
    public Button Button { get; init; }

    // Для создания списка Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ ΡƒΠΊΠ°Π·Π°Ρ‚ΡŒ Root* ΠΈ Child* Π°Ρ‚Ρ€ΠΈΠ±ΡƒΡ‚Ρ‹. Child Π°Ρ‚Ρ€ΠΈΠ±ΡƒΡ‚ Π΄ΠΎΠ»ΠΆΠ΅Π½ Π±Ρ‹Ρ‚ΡŒ ΠΎΠ±ΡΠ·Π°Ρ‚Π΅Π»ΡŒΠ½ΠΎ ΡƒΠΊΠ°Π·Π°Π½
    [RootByTid("RootList")]
    [ChildByLocator("ChildItem")]
    public ControlList<Label> List { get; init; }
}

ΠŸΡ€ΠΈΠΌΠ΅Ρ€ Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ IRootLocatorAttribute

// Π˜Ρ‰Π΅Ρ‚ ΠΊΠΎΠ½Ρ‚Ρ€ΠΎΠ» ΠΏΠΎ GetByText
[AttributeUsage(AttributeTargets.Property)]
public class RootByTextAttribute : Attribute, IRootLocatorAttribute
{
    public RootByTextAttribute(string selector) => Selector = selector;
    public string Selector { get; }

    public ILocator Resolve(ILocator locator) => locator.GetByText(Selector);

    public ILocator Resolve(IPage page) => page.GetByText(Selector);
}

ΠœΠΈΠ½ΠΈΠΌΠ°Π»ΡŒΠ½Ρ‹Π΅ трСбования

  • netstandard2.0 / NET6
  • Playwright 1.51.0
  • @skbkontur/react-ui 4.25.2 (рСкомСндуСтся ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ послСдниС вСрсии)

Changes from Previous Version

v4.0.0-betac1918b74v4.0.0-betac761fd74

Adoption Assessment

A verified publisher signal is available. Assess fit from the package's supported frameworks, license and dependency graph rather than popularity alone.

This version is marked prerelease. Validate its API and upgrade path before production use.Compatibility metadata lists 3 target frameworks; confirm the exact target used by your application.

Related Guides & Workflows

Learn how to evaluate, integrate, or audit this package in your .NET project.