Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/Controls.Extensions/ControlListExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,23 +32,23 @@
public static async Task ClickFirstItemAsync<T>(
this ControlList<T> controlList,
LocatorClickOptions? options = default) where T : ControlBase
=> await controlList.ClickItemAsync(0, options).ConfigureAwait(false);

Check warning on line 35 in src/Controls.Extensions/ControlListExtensions.cs

View workflow job for this annotation

GitHub Actions / build-test

'ControlList<T>.ClickItemAsync(int, LocatorClickOptions?)' is obsolete: 'В будущих версиях метод будет перемещен в Controls.Extensions. Если вы его используете, то убедитесь, что Controls.Extensions у вас добавлен'

Check warning on line 35 in src/Controls.Extensions/ControlListExtensions.cs

View workflow job for this annotation

GitHub Actions / build-test

'ControlList<T>.ClickItemAsync(int, LocatorClickOptions?)' is obsolete: 'В будущих версиях метод будет перемещен в Controls.Extensions. Если вы его используете, то убедитесь, что Controls.Extensions у вас добавлен'

Check warning on line 35 in src/Controls.Extensions/ControlListExtensions.cs

View workflow job for this annotation

GitHub Actions / build-test

'ControlList<T>.ClickItemAsync(int, LocatorClickOptions?)' is obsolete: 'В будущих версиях метод будет перемещен в Controls.Extensions. Если вы его используете, то убедитесь, что Controls.Extensions у вас добавлен'

Check warning on line 35 in src/Controls.Extensions/ControlListExtensions.cs

View workflow job for this annotation

GitHub Actions / build-test

'ControlList<T>.ClickItemAsync(int, LocatorClickOptions?)' is obsolete: 'В будущих версиях метод будет перемещен в Controls.Extensions. Если вы его используете, то убедитесь, что Controls.Extensions у вас добавлен'

public static async Task ClickLastItemAsync<T>(
this ControlList<T> controlList,
LocatorClickOptions? options = default) where T : ControlBase
{
var itemsCount = await controlList.CountAsync().ConfigureAwait(false);
await controlList.ClickItemAsync(itemsCount - 1, options).ConfigureAwait(false);

Check warning on line 42 in src/Controls.Extensions/ControlListExtensions.cs

View workflow job for this annotation

GitHub Actions / build-test

'ControlList<T>.ClickItemAsync(int, LocatorClickOptions?)' is obsolete: 'В будущих версиях метод будет перемещен в Controls.Extensions. Если вы его используете, то убедитесь, что Controls.Extensions у вас добавлен'

Check warning on line 42 in src/Controls.Extensions/ControlListExtensions.cs

View workflow job for this annotation

GitHub Actions / build-test

'ControlList<T>.ClickItemAsync(int, LocatorClickOptions?)' is obsolete: 'В будущих версиях метод будет перемещен в Controls.Extensions. Если вы его используете, то убедитесь, что Controls.Extensions у вас добавлен'

Check warning on line 42 in src/Controls.Extensions/ControlListExtensions.cs

View workflow job for this annotation

GitHub Actions / build-test

'ControlList<T>.ClickItemAsync(int, LocatorClickOptions?)' is obsolete: 'В будущих версиях метод будет перемещен в Controls.Extensions. Если вы его используете, то убедитесь, что Controls.Extensions у вас добавлен'

Check warning on line 42 in src/Controls.Extensions/ControlListExtensions.cs

View workflow job for this annotation

GitHub Actions / build-test

'ControlList<T>.ClickItemAsync(int, LocatorClickOptions?)' is obsolete: 'В будущих версиях метод будет перемещен в Controls.Extensions. Если вы его используете, то убедитесь, что Controls.Extensions у вас добавлен'
}

public static async Task<T> GetSingleItemAsync<T>(this ControlList<T> controlList) where T : ControlBase
{
await controlList.ExpectV2().ToHaveCountAsync(1).ConfigureAwait(false);
return await controlList.GetFirstItemAsync().ConfigureAwait(false);
return controlList.GetFirstItem();
}

[Obsolete("Используй GetItemAsync из ControlList")]
[Obsolete("Используй GetItem из ControlList")]
public static async Task<T> GetSingleItemAsync<T>(
this ControlList<T> controlList,
Func<T, Task<bool>> predicate,
Expand Down
2 changes: 1 addition & 1 deletion src/Controls.Extensions/Controls.Extensions.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
<Title>Playwright.ReactUI.Controls.Extensions</Title>
<AssemblyVersion>1.0.0.0</AssemblyVersion>
<FileVersion>1.0.0</FileVersion>
<Version>3.2.0</Version>
<Version>3.3.0</Version>
<Authors>Evgeniy Ivanov</Authors>
<Product>Playwright.ReactUI.Controls.Extensions</Product>
<PackageReadmeFile>README-Controls.Extensions.md</PackageReadmeFile>
Expand Down
4 changes: 2 additions & 2 deletions src/Controls/Assertions/RadioGroupAssertionsV2.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public async Task ToBeCheckedByValueAsync(string value, LocatorAssertionsToBeChe

public async Task ToBeCheckedByIndexAsync(int index, LocatorAssertionsToBeCheckedOptions? options = default)
{
var radio = await radioGroup.GetByIndexAsync(index).ConfigureAwait(false);
var radio = radioGroup.GetByIndex(index);
await radio.ExpectV2().ToBeCheckedAsync(options).ConfigureAwait(false);
}

Expand All @@ -48,7 +48,7 @@ public async Task ToBeUncheckedByValueAsync(string value, LocatorAssertionsToBeC

public async Task ToBeUncheckedByIndexAsync(int index, LocatorAssertionsToBeCheckedOptions? options = default)
{
var radio = await radioGroup.GetByIndexAsync(index).ConfigureAwait(false);
var radio = radioGroup.GetByIndex(index);
await radio.ExpectV2().ToBeUncheckedAsync(options).ConfigureAwait(false);
}

Expand Down
18 changes: 10 additions & 8 deletions src/Controls/Autocomplete.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ public async Task<string> GetValueAsync(LocatorInputValueOptions? options = defa

public async Task FillAsync(string value, LocatorFillOptions? options = default)
{
await FocusAsync().ConfigureAwait(false);
await ClearAsync().ConfigureAwait(false);
await FocusAsync(new LocatorFocusOptions { Timeout = options?.Timeout }).ConfigureAwait(false);
await ClearAsync(new LocatorClearOptions { Timeout = options?.Timeout }).ConfigureAwait(false);
await InputLocator.FillAsync(value, options).ConfigureAwait(false);
}

Expand All @@ -44,10 +44,12 @@ public async Task PressSequentiallyAsync(string value, LocatorPressSequentiallyO
public async Task ClearAsync(LocatorClearOptions? options = default)
=> await InputLocator.ClearAsync(options).ConfigureAwait(false);

public async Task FocusAsync()
public async Task FocusAsync(LocatorFocusOptions? options = default)
{
await InputLocator.Expect().ToBeEnabledAsync().ConfigureAwait(false);
await InputLocator.FocusAsync().ConfigureAwait(false);
await ExpectV2()
.ToBeEnabledAsync(new LocatorAssertionsToBeEnabledOptions { Timeout = options?.Timeout })
.ConfigureAwait(false);
await InputLocator.FocusAsync(options).ConfigureAwait(false);
}

public async Task BlurAsync(LocatorBlurOptions? options = default)
Expand All @@ -56,9 +58,6 @@ public async Task BlurAsync(LocatorBlurOptions? options = default)
public override async Task ClickAsync(LocatorClickOptions? options = default)
=> await InputLocator.ClickAsync(options).ConfigureAwait(false);

public async Task<Tooltip> GetTooltipAsync(TooltipType type)
=> await TooltipProvider.GetTooltipAsync(type, this).ConfigureAwait(false);

public async Task SelectFirstSuggestionAsync(LocatorClickOptions? options = default)
{
var suggestions = await GetSuggestionsAsync().ConfigureAwait(false);
Expand All @@ -83,6 +82,9 @@ public async Task SelectSuggestionAsync(Regex regex, LocatorClickOptions? option
await suggestions.GetByText(regex).ClickAsync(options).ConfigureAwait(false);
}

public async Task<Tooltip> GetTooltipAsync(TooltipType type)
=> await TooltipProvider.GetTooltipAsync(type, this).ConfigureAwait(false);

[Obsolete("Используй ExpectV2. В будущих версиях этот метод будет удален")]
public override ILocatorAssertions Expect() => new InputAssertions(RootLocator.Expect(), InputLocator.Expect());

Expand Down
8 changes: 5 additions & 3 deletions src/Controls/Button.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,12 @@ public async Task<string> GetTextAsync(LocatorInnerTextOptions? options = defaul
public override async Task ClickAsync(LocatorClickOptions? options = default)
=> await ButtonLocator.ClickAsync(options).ConfigureAwait(false);

public async Task FocusAsync()
public async Task FocusAsync(LocatorFocusOptions? options = default)
{
await ButtonLocator.Expect().ToBeEnabledAsync().ConfigureAwait(false);
await ButtonLocator.FocusAsync().ConfigureAwait(false);
await ButtonLocator.Expect()
.ToBeEnabledAsync(new LocatorAssertionsToBeEnabledOptions { Timeout = options?.Timeout })
.ConfigureAwait(false);
await ButtonLocator.FocusAsync(options).ConfigureAwait(false);
}

public async Task BlurAsync(LocatorBlurOptions? options = default)
Expand Down
8 changes: 5 additions & 3 deletions src/Controls/Checkbox.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,12 @@ public async Task CheckAsync(LocatorCheckOptions? options = default)
public async Task UncheckAsync(LocatorUncheckOptions? options = default)
=> await RootLocator.UncheckAsync(options).ConfigureAwait(false);

public async Task FocusAsync()
public async Task FocusAsync(LocatorFocusOptions? options = default)
{
await InputLocator.Expect().ToBeEnabledAsync().ConfigureAwait(false);
await InputLocator.FocusAsync().ConfigureAwait(false);
await ExpectV2()
.ToBeEnabledAsync(new LocatorAssertionsToBeEnabledOptions { Timeout = options?.Timeout })
.ConfigureAwait(false);
await InputLocator.FocusAsync(options).ConfigureAwait(false);
}

public async Task BlurAsync(LocatorBlurOptions? options = default)
Expand Down
59 changes: 40 additions & 19 deletions src/Controls/Combobox.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,77 +44,98 @@ public async Task<string> GetSelectedValueAsync()
/// Используй этот метод, когда в меню существует несколько элементов с одинаковым названием
/// В остальных случаях лучше использовать `SelectAsync`
/// </summary>
public async Task SelectFirstAsync(string value)
public async Task SelectFirstAsync(string value, LocatorClickOptions? options = default)
{
var items = await GetComboboxMenuItemsLocatorAsync(value).ConfigureAwait(false);
await items.First.ClickAsync().ConfigureAwait(false);
await items.First.ClickAsync(options).ConfigureAwait(false);
}

/// <summary>
/// Используй этот метод, когда в меню существует несколько элементов с одинаковым названием
/// В остальных случаях лучше использовать `SelectAsync`
/// </summary>
public async Task SelectFirstAsync(Regex value)
public async Task SelectFirstAsync(Regex value, LocatorClickOptions? options = default)
{
var items = await GetComboboxMenuItemsLocatorAsync(value).ConfigureAwait(false);
await items.First.ClickAsync().ConfigureAwait(false);
await items.First.ClickAsync(options).ConfigureAwait(false);
}

public async Task SelectAsync(string value)
public async Task SelectAsync(string value, LocatorClickOptions? options = default)
{
var items = await GetComboboxMenuItemsLocatorAsync(value).ConfigureAwait(false);
await items.Expect().ToHaveCountAsync(1).ConfigureAwait(false);
await items.ClickAsync().ConfigureAwait(false);
await items.Expect()
.ToHaveCountAsync(1, new LocatorAssertionsToHaveCountOptions { Timeout = options?.Timeout })
.ConfigureAwait(false);
await items.ClickAsync(options).ConfigureAwait(false);
}

public async Task SelectAsync(Regex value)
public async Task SelectAsync(Regex value, LocatorClickOptions? options = default)
{
var items = await GetComboboxMenuItemsLocatorAsync(value).ConfigureAwait(false);
await items.Expect().ToHaveCountAsync(1).ConfigureAwait(false);
await items.ClickAsync().ConfigureAwait(false);
await items.Expect()
.ToHaveCountAsync(1, new LocatorAssertionsToHaveCountOptions { Timeout = options?.Timeout })
.ConfigureAwait(false);
await items.ClickAsync(options).ConfigureAwait(false);
}

public async Task FillAsync(string value, LocatorFillOptions? options = default)
{
await FocusAsync().ConfigureAwait(false);
await FocusAsync(new LocatorFocusOptions { Timeout = options?.Timeout }).ConfigureAwait(false);
await NativeInputLocator.FillAsync(value, options).ConfigureAwait(false);
}

public async Task ClearAsync(LocatorClearOptions? options = default)
{
await FocusAsync().ConfigureAwait(false);
await FocusAsync(new LocatorFocusOptions { Timeout = options?.Timeout }).ConfigureAwait(false);
await NativeInputLocator.ClearAsync(options).ConfigureAwait(false);
}

public async Task FocusAsync()
public async Task FocusAsync(LocatorFocusOptions? options = default)
{
await NativeInputLocator.Expect().ToBeEnabledAsync().ConfigureAwait(false);
await NativeInputLocator.Expect()
.ToBeEnabledAsync(new LocatorAssertionsToBeEnabledOptions { Timeout = options?.Timeout })
.ConfigureAwait(false);
await RootLocator
.Locator("input[type='text']")
.Or(RootLocator.Locator("[data-tid='InputLikeText__root']"))
.FocusAsync()
.FocusAsync(options)
.ConfigureAwait(false);
}

public async Task BlurAsync()
=> await NativeInputLocator.PressAsync("Tab").ConfigureAwait(false);
public async Task BlurAsync(LocatorBlurOptions? options = default)
=> await NativeInputLocator.PressAsync(
"Tab",
new LocatorPressOptions { Timeout = options?.Timeout }
).ConfigureAwait(false);

public override async Task ClickAsync(LocatorClickOptions? options = default)
{
// NOTE: rootLocator всегда в состоянии enabled, даже если ComboBox disabled
await NativeInputLocator.Expect().ToBeEnabledAsync().ConfigureAwait(false);
await ExpectV2()
.ToBeEnabledAsync(new LocatorAssertionsToBeEnabledOptions { Timeout = options?.Timeout })
.ConfigureAwait(false);
await base.ClickAsync(options).ConfigureAwait(false);
}

public async Task<Tooltip> GetTooltipAsync(TooltipType type)
=> await TooltipProvider.GetTooltipAsync(type, this).ConfigureAwait(false);

/// <summary>
/// Возвращает список меню по data-tid из react-ui:
/// - MenuItem__root
/// - MenuMessage__root
/// - ComboBoxMenu__item
/// - ComboBoxMenu__notFound
/// - MenuHeader__root
/// - MenuFooter__root
/// </summary>
public async Task<ControlList<MenuItem>> GetMenuItemsAsync()
{
await FocusAsync().ConfigureAwait(false);
var container = await portal.GetContainerAsync().ConfigureAwait(false);
await container.Locator("[data-tid='Spinner__root']")
.WaitForAsync(new LocatorWaitForOptions { State = WaitForSelectorState.Hidden }).ConfigureAwait(false);
.WaitForAsync(new LocatorWaitForOptions { State = WaitForSelectorState.Hidden })
.ConfigureAwait(false);

return new ControlList<MenuItem>(
container,
Expand Down
18 changes: 9 additions & 9 deletions src/Controls/ControlBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,16 @@ protected ControlBase(ILocator rootLocator)
public virtual async Task<bool> IsVisibleAsync(LocatorIsVisibleOptions? options = default)
=> await RootLocator.IsVisibleAsync(options).ConfigureAwait(false);

public async Task<bool> HasErrorAsync()
public async Task<bool> HasErrorAsync(LocatorGetAttributeOptions? options = default)
{
await WaitForAsync().ConfigureAwait(false);
return await HasAttributeAsync(DataVisualState.Error).ConfigureAwait(false);
await WaitForAsync(new LocatorWaitForOptions { Timeout = options?.Timeout }).ConfigureAwait(false);
return await HasAttributeAsync(DataVisualState.Error, options).ConfigureAwait(false);
}

public async Task<bool> HasWarningAsync()
public async Task<bool> HasWarningAsync(LocatorGetAttributeOptions? options = default)
{
await WaitForAsync().ConfigureAwait(false);
return await HasAttributeAsync(DataVisualState.Warning).ConfigureAwait(false);
await WaitForAsync(new LocatorWaitForOptions { Timeout = options?.Timeout }).ConfigureAwait(false);
return await HasAttributeAsync(DataVisualState.Warning, options).ConfigureAwait(false);
}

public virtual async Task ClickAsync(LocatorClickOptions? options = default)
Expand All @@ -45,10 +45,10 @@ public async Task ScrollIntoViewIfNeededAsync(LocatorScrollIntoViewIfNeededOptio
public async Task WaitForAsync(LocatorWaitForOptions? options = default)
=> await RootLocator.WaitForAsync(options).ConfigureAwait(false);

public async Task<bool> HasAttributeAsync(string name)
public async Task<bool> HasAttributeAsync(string name, LocatorGetAttributeOptions? options = default)
{
await WaitForAsync().ConfigureAwait(false);
return await GetAttributeValueAsync(name).ConfigureAwait(false) != null;
await WaitForAsync(new LocatorWaitForOptions { Timeout = options?.Timeout }).ConfigureAwait(false);
return await GetAttributeValueAsync(name, options).ConfigureAwait(false) != null;
}

public async Task<string?> GetAttributeValueAsync(
Expand Down
29 changes: 20 additions & 9 deletions src/Controls/ControlList.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,26 +31,37 @@ Func<ILocator, TItem> itemFactory
public override async Task<bool> IsVisibleAsync(LocatorIsVisibleOptions? options = default)
=> await ItemsLocator.First.IsVisibleAsync(options).ConfigureAwait(false);

/// <summary>
/// Поведение метода идентично вызову Locator.All()
///
/// getItems не ждет появления элементов, соответствующих локатору, а сразу возвращает всё, что есть на странице в данный момент.
/// Когда список элементов меняется динамически, использование getItems приведёт к непредсказуемым и нестабильным результатам.
/// Когда список элементов стабилен, но загружается динамически, необходимо дождаться полной загрузки списка перед вызовом getItems
/// </summary>
public async Task<IReadOnlyList<TItem>> GetItemsAsync()
{
var itemLocators = await GetItemLocatorsAsync().ConfigureAwait(false);
return itemLocators.Select(x => itemFactory(x)).ToList();
}

public async Task<TItem> GetFirstItemAsync()
=> await GetItemAsync(0).ConfigureAwait(false);
/// <summary>
/// Поведение метода идентично вызову Locator.Nth(0)
/// </summary>
public TItem GetFirstItem() => GetItem(0);

/// <summary>
/// Поведение метода идентично вызову Locator.Nth(-1)
/// </summary>
public async Task<TItem> GetLastItemAsync()
{
var itemsCount = await CountAsync().ConfigureAwait(false);
return await GetItemAsync(itemsCount - 1).ConfigureAwait(false);
return GetItem(itemsCount - 1);
}

public async Task<TItem> GetItemAsync(int index)
{
var itemLocators = await GetItemLocatorsAsync().ConfigureAwait(false);
return itemFactory(itemLocators[index]);
}
/// <summary>
/// Поведение метода идентично вызову Locator.Nth(index)
/// </summary>
public TItem GetItem(int index) => itemFactory(ItemsLocator.Nth(index));

public async Task<TItem> GetFirstItemAsync(
Func<TItem, Task<bool>> predicate,
Expand Down Expand Up @@ -125,7 +136,7 @@ public async Task<TItem> GetItemAsync(Func<TItem, Task<bool>> predicate, int tim
"Если вы его используете, то убедитесь, что Controls.Extensions у вас добавлен")]
public async Task ClickItemAsync(int index, LocatorClickOptions? options = default)
{
var item = await GetItemAsync(index).ConfigureAwait(false);
var item = GetItem(index);
await item.ClickAsync(options).ConfigureAwait(false);
}

Expand Down
2 changes: 1 addition & 1 deletion src/Controls/Controls.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
<Title>Playwright.ReactUI.Controls</Title>
<AssemblyVersion>1.0.0.0</AssemblyVersion>
<FileVersion>1.0.0</FileVersion>
<Version>3.1.1</Version>
<Version>3.2.0</Version>
<Authors>Evgeniy Ivanov</Authors>
<Product>Playwright.ReactUI.Controls</Product>
<PackageReadmeFile>README-Controls.md</PackageReadmeFile>
Expand Down
Loading
Loading