diff --git a/src/AzureOpenAIProxy.PlaygroundApp/Components/Pages/Playground.razor b/src/AzureOpenAIProxy.PlaygroundApp/Components/Pages/Playground.razor index 4ade2e46..ceb2684f 100644 --- a/src/AzureOpenAIProxy.PlaygroundApp/Components/Pages/Playground.razor +++ b/src/AzureOpenAIProxy.PlaygroundApp/Components/Pages/Playground.razor @@ -8,8 +8,7 @@ - - + diff --git a/src/AzureOpenAIProxy.PlaygroundApp/Components/Pages/Tests.razor b/src/AzureOpenAIProxy.PlaygroundApp/Components/Pages/Tests.razor deleted file mode 100644 index 42bbe51b..00000000 --- a/src/AzureOpenAIProxy.PlaygroundApp/Components/Pages/Tests.razor +++ /dev/null @@ -1,38 +0,0 @@ -@page "/tests" -@rendermode InteractiveServer - -

Component Tests

- -

Debug Button

- - - - - - -

Deployment Models

- - - -@code { - private object? targetValue; - private string? apiKey; - private string? selectedModel; - - private async Task SetInput(int value) - { - targetValue = value; - await Task.CompletedTask; - } - - private void HandleApiKeyInput(string apiKeyValue) - { - apiKey = apiKeyValue; - } - - private async Task SetDeploymentModel(string value) - { - selectedModel = value; - await Task.CompletedTask; - } -} diff --git a/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ApiKeyInputComponent.razor b/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ApiKeyInputComponent.razor index d81073fc..d6b3f660 100644 --- a/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ApiKeyInputComponent.razor +++ b/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ApiKeyInputComponent.razor @@ -1,4 +1,10 @@ -API key input + + + @code { private string? apiKeyValue { get; set; } diff --git a/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ConfigTabComponent.razor b/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ConfigTabComponent.razor index 33d9589a..3895e562 100644 --- a/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ConfigTabComponent.razor +++ b/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ConfigTabComponent.razor @@ -1,20 +1,23 @@ - - - This is "System message" tab. - - - This is "Parameters" tab. - - - -

[TEST] Active tab changed to: @SelectedTab?.Id

+ + + + This is "System message" tab. + + + This is "Parameters" tab. + + + @code { - FluentTab? SelectedTab; + private FluentTab? selectedTab { get; set; } + + [Parameter] + public string? Id { get; set; } private async Task ChangeTab(FluentTab tab) { - SelectedTab = tab; + this.selectedTab = tab; await Task.CompletedTask; } } \ No newline at end of file diff --git a/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ConfigWindowComponent.razor b/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ConfigWindowComponent.razor new file mode 100644 index 00000000..e63e28df --- /dev/null +++ b/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ConfigWindowComponent.razor @@ -0,0 +1,31 @@ +@using AzureOpenAIProxy.PlaygroundApp.Models + + + Setup + + + + + + +@code { + private string? apiKey; + private string? deploymentModel; + + [Parameter] + public string? Id { get; set; } + + private async Task SetApiKey(string apiKey) + { + this.apiKey = apiKey; + + await Task.CompletedTask; + } + + private async Task SetDeploymentModel(string deploymentModel) + { + this.deploymentModel = deploymentModel; + + await Task.CompletedTask; + } +} \ No newline at end of file diff --git a/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/DebugButtonComponent.razor b/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/DebugButtonComponent.razor deleted file mode 100644 index 8335d49e..00000000 --- a/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/DebugButtonComponent.razor +++ /dev/null @@ -1,25 +0,0 @@ -@inject IToastService ToastService - - -Debug - -@code { - [Parameter] - public string? Id { get; set; } - - [Parameter] - public object? Input { get; set; } - - private async Task ShowToast() - { - if (Input is null) - { - ToastService.ShowToast(ToastIntent.Warning, "Input is null."); - await Task.CompletedTask; - return; - } - - ToastService.ShowToast(ToastIntent.Success, $"{Input} (Type: {Input.GetType()})"); - await Task.CompletedTask; - } -} \ No newline at end of file diff --git a/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/DebugTargetComponent.razor b/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/DebugTargetComponent.razor deleted file mode 100644 index bfb54641..00000000 --- a/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/DebugTargetComponent.razor +++ /dev/null @@ -1,18 +0,0 @@ - - 123 - 456 - 789 - - -@code { - [Parameter] - public string? Id { get; set; } - - [Parameter] - public EventCallback OnValueChanged { get; set; } - - private async Task SetValue(int value) - { - await OnValueChanged.InvokeAsync(value); - } -} \ No newline at end of file diff --git a/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/DeploymentModelListComponent.razor b/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/DeploymentModelListComponent.razor index ac39ba4c..463ed83f 100644 --- a/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/DeploymentModelListComponent.razor +++ b/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/DeploymentModelListComponent.razor @@ -1,74 +1,39 @@ - -
- - * -
- - - -
+ + + @code { - private Option? selectedOption { get; set; } = new(); + private List>? deploymentModels; + private Option? selectedOption { get; set; } [Parameter] public string? Id { get; set; } [Parameter] public EventCallback OnUserOptionSelected { get; set; } - - private async Task OnValueChanged() + + protected override async Task OnInitializedAsync() { - string? selectedValue = selectedOption?.Value?.ToString(); - await OnUserOptionSelected.InvokeAsync(selectedValue); + this.deploymentModels = new() + { + new Option { Value = "model-gpt35turbo16k-0613", Text = "model-gpt35turbo16k-0613" }, + new Option { Value = "model-gpt4o-20240513", Text = "model-gpt4o-20240513" }, + }; + + await Task.CompletedTask; } - static List> deploymentModelOptions = new() + private async Task SetDeploymentModel() { - new Option { Value = "AL", Text = "Alabama" }, - new Option { Value = "AK", Text = "Alaska" }, - new Option { Value = "AZ", Text = "Arizona" }, - new Option { Value = "AR", Text = "Arkansas" }, - new Option { Value = "CA", Text = "California" }, - new Option { Value = "CO", Text = "Colorado" }, - new Option { Value = "CT", Text = "Connecticut" }, - new Option { Value = "DE", Text = "Delaware" }, - new Option { Value = "FL", Text = "Florida" }, - new Option { Value = "GA", Text = "Georgia" }, - new Option { Value = "HI", Text = "Hawaii" }, - new Option { Value = "ID", Text = "Idaho" }, - new Option { Value = "IL", Text = "Illinois" }, - new Option { Value = "IN", Text = "Indiana" }, - new Option { Value = "IA", Text = "Iowa" }, - new Option { Value = "KS", Text = "Kansas" }, - new Option { Value = "KY", Text = "Kentucky" }, - new Option { Value = "LA", Text = "Louisiana" }, - new Option { Value = "ME", Text = "Maine" }, - new Option { Value = "MD", Text = "Maryland" }, - new Option { Value = "MA", Text = "Massachussets" }, - new Option { Value = "MI", Text = "Michigain" }, - new Option { Value = "MN", Text = "Minnesota" }, - new Option { Value = "MS", Text = "Mississippi" }, - new Option { Value = "MO", Text = "Missouri" }, - new Option { Value = "MT", Text = "Montana" }, - new Option { Value = "NE", Text = "Nebraska" }, - new Option { Value = "NV", Text = "Nevada" }, - new Option { Value = "NH", Text = "New Hampshire" }, - new Option { Value = "NJ", Text = "New Jersey" }, - new Option { Value = "NM", Text = "New Mexico" }, - new Option { Value = "NY", Text = "New York" }, - new Option { Value = "NC", Text = "North Carolina" }, - new Option { Value = "ND", Text = "North Dakota" }, - new Option { Value = "OH", Text = "Ohio" }, - new Option { Value = "OK", Text = "Oklahoma" }, - new Option { Value = "OR", Text = "Oregon" }, - new Option { Value = "PA", Text = "Pennsylvania" } - }; + var selectedValue = selectedOption?.Value!; + + await OnUserOptionSelected.InvokeAsync(selectedValue); + } } \ No newline at end of file diff --git a/test/AzureOpenAIProxy.PlaygroundApp.Tests/Pages/PlaygroundPageChatWindowTests.cs b/test/AzureOpenAIProxy.PlaygroundApp.Tests/Pages/PlaygroundPageChatWindowTests.cs new file mode 100644 index 00000000..52cff76d --- /dev/null +++ b/test/AzureOpenAIProxy.PlaygroundApp.Tests/Pages/PlaygroundPageChatWindowTests.cs @@ -0,0 +1,183 @@ +using FluentAssertions; + +namespace AzureOpenAIProxy.PlaygroundApp.Tests.Pages; + +[TestFixture] +[Property("Category", "Integration")] +public partial class PlaygroundPageTests +{ + [Test] + public async Task Given_ChatGrid_When_Endpoint_Invoked_Then_ChatWindow_Should_Be_Displayed() + { + // Act + var element = Page.Locator("div.chat-grid") + .Locator("div#chat-window"); + + // Assert + await Expect(element).ToBeVisibleAsync(); + } + + [Test] + public async Task Given_ChatGrid_When_Endpoint_Invoked_Then_ChatHistory_Should_Be_Empty() + { + // Act + var element = Page.Locator("div.chat-grid") + .Locator("div#chat-window") + .Locator("div#chat-history"); + + var text = await element.TextContentAsync(); + + // Assert + text.Should().BeNullOrEmpty(); + } + + [Test] + public async Task Given_ChatGrid_When_Endpoint_Invoked_Then_ChatPrompt_Should_Be_Displayed() + { + // Act + var element = Page.Locator("div.chat-grid") + .Locator("div#chat-window") + .Locator("div#chat-prompt"); + + // Assert + await Expect(element).ToBeVisibleAsync(); + } + + [Test] + public async Task Given_ChatGrid_When_Endpoint_Invoked_Then_ChatPromptArea_Should_Be_Displayed() + { + // Act + var element = Page.Locator("div.chat-grid") + .Locator("div#chat-window") + .Locator("div#chat-prompt") + .Locator("fluent-text-area#prompt"); + + // Assert + await Expect(element).ToBeVisibleAsync(); + } + + [Test] + [TestCase("button-clear")] + [TestCase("button-send")] + public async Task Given_ChatGrid_When_Endpoint_Invoked_Then_ChatPromptButton_Should_Be_Displayed(string id) + { + // Act + var element = Page.Locator("div.chat-grid") + .Locator("div#chat-window") + .Locator("div#chat-prompt") + .Locator($"div > fluent-button#{id}"); + + // Assert + await Expect(element).ToBeVisibleAsync(); + } + + [Test] + [TestCase("abcde")] + public async Task Given_ChatPrompt_When_Send_Clicked_Then_ChatHistoryMessage_Should_Be_Displayed_OnTheRight(string text) + { + // Arrange + var history = Page.Locator("div.chat-grid") + .Locator("div#chat-window") + .Locator("div#chat-history"); + var prompt = Page.Locator("div.chat-grid") + .Locator("div#chat-window") + .Locator("div#chat-prompt") + .Locator("fluent-text-area#prompt"); + var send = Page.Locator("div.chat-grid") + .Locator("div#chat-window") + .Locator("div#chat-prompt") + .Locator("div > fluent-button#button-send"); + + // Act + await prompt.Locator("textarea").FillAsync(text); + await send.ClickAsync(); + + var style = await history.Locator("div#message-00").GetAttributeAsync("style"); + + // Assert + style.Should().ContainAll("justify-content:", "end"); + } + + [Test] + [TestCase("abcde")] + public async Task Given_ChatPrompt_When_Send_Clicked_Then_ChatHistoryMessage_Should_Be_Displayed(string text) + { + // Arrange + var history = Page.Locator("div.chat-grid") + .Locator("div#chat-window") + .Locator("div#chat-history"); + var prompt = Page.Locator("div.chat-grid") + .Locator("div#chat-window") + .Locator("div#chat-prompt") + .Locator("fluent-text-area#prompt"); + var send = Page.Locator("div.chat-grid") + .Locator("div#chat-window") + .Locator("div#chat-prompt") + .Locator("div > fluent-button#button-send"); + + // Act + await prompt.Locator("textarea").FillAsync(text); + await send.ClickAsync(); + + var item = await history.Locator("div#message-00 p").TextContentAsync(); + + // Assert + item.Should().Be(text); + } + + [Test] + [TestCase("abcde")] + public async Task Given_ChatPrompt_When_Send_Clicked_Then_ChatPromptArea_Should_Be_Empty(string text) + { + // Arrange + var prompt = Page.Locator("div.chat-grid") + .Locator("div#chat-window") + .Locator("div#chat-prompt") + .Locator("fluent-text-area#prompt"); + var send = Page.Locator("div.chat-grid") + .Locator("div#chat-window") + .Locator("div#chat-prompt") + .Locator("div > fluent-button#button-send"); + + // Act + await prompt.Locator("textarea").FillAsync(text); + await send.ClickAsync(); + + var item = await prompt.Locator("textarea").TextContentAsync(); + + // Assert + item.Should().BeNullOrEmpty(); + } + + [Test] + [TestCase("abcde")] + public async Task Given_ChatPrompt_When_Clear_Clicked_Then_ChatHistoryMessage_Should_Be_Cleared(string text) + { + // Arrange + var history = Page.Locator("div.chat-grid") + .Locator("div#chat-window") + .Locator("div#chat-history"); + var prompt = Page.Locator("div.chat-grid") + .Locator("div#chat-window") + .Locator("div#chat-prompt") + .Locator("fluent-text-area#prompt"); + var send = Page.Locator("div.chat-grid") + .Locator("div#chat-window") + .Locator("div#chat-prompt") + .Locator("div > fluent-button#button-send"); + var clear = Page.Locator("div.chat-grid") + .Locator("div#chat-window") + .Locator("div#chat-prompt") + .Locator("div > fluent-button#button-clear"); + + // Act + await prompt.Locator("textarea").FillAsync(text); + await send.ClickAsync(); + await clear.ClickAsync(); + + var result = await history.TextContentAsync(); + + // Assert + result.Should().BeNullOrEmpty(); + } +} diff --git a/test/AzureOpenAIProxy.PlaygroundApp.Tests/Pages/PlaygroundPageConfigWindowTests.cs b/test/AzureOpenAIProxy.PlaygroundApp.Tests/Pages/PlaygroundPageConfigWindowTests.cs new file mode 100644 index 00000000..0fa7827c --- /dev/null +++ b/test/AzureOpenAIProxy.PlaygroundApp.Tests/Pages/PlaygroundPageConfigWindowTests.cs @@ -0,0 +1,212 @@ +using FluentAssertions; + +namespace AzureOpenAIProxy.PlaygroundApp.Tests.Pages; + +[TestFixture] +[Property("Category", "Integration")] +public partial class PlaygroundPageTests +{ + [Test] + public async Task Given_ConfigTab_When_Endpoint_Invoked_Then_Header_Should_Be_Displayed() + { + // Act + var element = Page.Locator("div.config-grid") + .Locator("div#config-window") + .Locator("h2"); + + // Assert + await Expect(element).ToBeVisibleAsync(); + } + + [Test] + [TestCase("api-key", "API key")] + public async Task Given_ApiKeynputField_When_Endpoint_Invoked_Then_Label_Should_Be_Visible(string id, string label) + { + // Arrange + var element = Page.Locator("div.config-grid") + .Locator("div#config-window") + .Locator($"div#{id}") + .Locator("label[for='api-key-field']"); + + // Act + var result = await element.TextContentAsync(); + + // Assert + result.Should().StartWith(label); + } + + [Test] + [TestCase("api-key")] + public async Task Given_ApiKeynputField_When_Endpoint_Invoked_Then_It_Should_Be_Visible(string id) + { + // Act + var element = Page.Locator("div.config-grid") + .Locator("div#config-window") + .Locator($"div#{id}") + .Locator("fluent-text-field#api-key-field"); + + // Assert + await Expect(element).ToBeVisibleAsync(); + } + + [Test] + [TestCase("api-key")] + public async Task Given_ApiKeyInputField_When_Endpoint_Invoked_Then_It_Should_Be_Password_Type(string id) + { + // Arrange + var element = Page.Locator("div.config-grid") + .Locator("div#config-window") + .Locator($"div#{id}") + .Locator("fluent-text-field#api-key-field") + .Locator("input"); + + // Act + var inputType = await element.GetAttributeAsync("type"); + + // Assert + inputType.Should().Be("password"); + } + + [Test] + [TestCase("api-key", "test-api-key-1")] + [TestCase("api-key", "example-key-123")] + public async Task Given_ApiKeyInputField_When_Changed_Then_It_Should_Be_Updated(string id, string apiKey) + { + // Arrange + var element = Page.Locator("div.config-grid") + .Locator("div#config-window") + .Locator($"div#{id}") + .Locator("fluent-text-field#api-key-field") + .Locator("input"); + + // Act + await element.FillAsync(apiKey); + + // Assert + await Expect(element).ToHaveValueAsync(apiKey); + } + + [Test] + [TestCase("deployment-model-list", "Deployment")] + public async Task Given_Label_When_Page_Loaded_Then_Label_Should_Be_Visible(string id, string label) + { + // Arrange + var element = Page.Locator("div.config-grid") + .Locator("div#config-window") + .Locator($"div#{id}") + .Locator("label[for='deployment-model-list-options']"); + + // Act + var result = await element.TextContentAsync(); + + // Assert + result.Should().StartWith(label); + } + + [Test] + [TestCase("deployment-model-list")] + public async Task Given_DropdownList_When_Page_Loaded_Then_DropdownList_Should_Be_Visible(string id) + { + // Act + var element = Page.Locator("div.config-grid") + .Locator("div#config-window") + .Locator($"div#{id}") + .Locator("fluent-select#deployment-model-list-options"); + + // Assert + await Expect(element).ToBeVisibleAsync(); + } + + [Test] + [TestCase("deployment-model-list")] + public async Task Given_DropdownList_When_DropdownList_Clicked_And_DropdownOptions_Appeared_Then_All_DropdownOptions_Should_Be_Visible(string id) + { + // Arrange + var element = Page.Locator("div.config-grid") + .Locator("div#config-window") + .Locator($"div#{id}") + .Locator("fluent-select#deployment-model-list-options"); + + // Act + await element.ClickAsync(); + var options = element.Locator("fluent-option"); + + // Assert + await Expect(options.Nth(0)).Not.ToBeVisibleAsync(); + for (int i = 1; i < await options.CountAsync(); i++) + { + await Expect(options.Nth(i)).ToBeVisibleAsync(); + } + } + + [Test] + [TestCase("config-tab")] + public async Task Given_ConfigTab_When_Endpoint_Invoked_Then_ConfigTab_Should_Be_Displayed(string id) + { + // Act + var element = Page.Locator("div.config-grid") + .Locator("div#config-window") + .Locator($"div#{id}") + .Locator("fluent-tabs#config-tabs"); + + // Assert + await Expect(element).ToBeVisibleAsync(); + } + + [Test] + [TestCase("config-tab")] + public async Task Given_ConfigTab_When_Endpoint_Invoked_Then_Id_Should_Be_System_Message_Tab(string id) + { + // Act + var systemMessagePanel = Page.Locator("div.config-grid") + .Locator("div#config-window") + .Locator($"div#{id}") + .Locator("fluent-tabs#config-tabs") + .Locator("fluent-tab-panel#system-message-tab-panel"); + var parameterPanel = Page.Locator("div.config-grid") + .Locator("div#config-window") + .Locator($"div#{id}") + .Locator("fluent-tabs#config-tabs") + .Locator("fluent-tab-panel#parameters-tab-panel"); + + // Assert + await Expect(systemMessagePanel).ToBeVisibleAsync(); + await Expect(parameterPanel).ToBeHiddenAsync(); + } + + [Test] + [TestCase( + "fluent-tab#parameters-tab", + "fluent-tab-panel#parameters-tab-panel", + "fluent-tab-panel#system-message-tab-panel" + )] + [TestCase( + "fluent-tab#system-message-tab", + "fluent-tab-panel#system-message-tab-panel", + "fluent-tab-panel#parameters-tab-panel" + )] + public async Task Given_ConfigTab_When_Changed_Then_Tab_Should_Be_Updated( + string selectedTabSelector, + string selectedPanelSelector, + string hiddenPanelSelector + ) + { + // Arrange + var selectedTab = Page.Locator("div.config-grid") + .Locator("fluent-tabs#config-tabs") + .Locator(selectedTabSelector); + var selectedPanel = Page.Locator("div.config-grid") + .Locator("fluent-tabs#config-tabs") + .Locator(selectedPanelSelector); + var hiddenPanel = Page.Locator("div.config-grid") + .Locator("fluent-tabs#config-tabs") + .Locator(hiddenPanelSelector); + + // Act + await selectedTab.ClickAsync(); + + // Assert + await Expect(selectedPanel).ToBeVisibleAsync(); + await Expect(hiddenPanel).ToBeHiddenAsync(); + } +} diff --git a/test/AzureOpenAIProxy.PlaygroundApp.Tests/Pages/PlaygroundPageTests.cs b/test/AzureOpenAIProxy.PlaygroundApp.Tests/Pages/PlaygroundPageTests.cs index 6692fde3..6772ba03 100644 --- a/test/AzureOpenAIProxy.PlaygroundApp.Tests/Pages/PlaygroundPageTests.cs +++ b/test/AzureOpenAIProxy.PlaygroundApp.Tests/Pages/PlaygroundPageTests.cs @@ -8,7 +8,7 @@ namespace AzureOpenAIProxy.PlaygroundApp.Tests.Pages; [Parallelizable(ParallelScope.Self)] [TestFixture] [Property("Category", "Integration")] -public class PlaygroundPageTests : PageTest +public partial class PlaygroundPageTests : PageTest { public override BrowserNewContextOptions ContextOptions() => new() { IgnoreHTTPSErrors = true, }; @@ -47,286 +47,9 @@ public async Task Given_Page_When_Endpoint_Invoked_Then_It_Should_Show_Panels(st await Expect(panel).ToBeVisibleAsync(); } - [Test] - public async Task Given_ConfigTab_When_Endpoint_Invoked_Then_ConfigTab_Should_Be_Displayed() - { - // Act - var configTab = Page.Locator("div.config-grid") - .Locator("fluent-tabs#config-tab"); - - // Assert - await Expect(configTab).ToBeVisibleAsync(); - } - - [Test] - public async Task Given_ConfigTab_When_Endpoint_Invoked_Then_Id_Should_Be_System_Message_Tab() - { - // Act - var systemMessagePanel = Page.Locator("div.config-grid") - .Locator("fluent-tabs#config-tab") - .Locator("fluent-tab-panel#system-message-tab-panel"); - var parameterPanel = Page.Locator("div.config-grid") - .Locator("fluent-tabs#config-tab") - .Locator("fluent-tab-panel#parameters-tab-panel"); - - // Assert - await Expect(systemMessagePanel).ToBeVisibleAsync(); - await Expect(parameterPanel).ToBeHiddenAsync(); - } - - [Test] - [TestCase( - "fluent-tab#parameters-tab", - "fluent-tab-panel#parameters-tab-panel", - "fluent-tab-panel#system-message-tab-panel" - )] - [TestCase( - "fluent-tab#system-message-tab", - "fluent-tab-panel#system-message-tab-panel", - "fluent-tab-panel#parameters-tab-panel" - )] - public async Task Given_ConfigTab_When_Changed_Then_Tab_Should_Be_Updated( - string selectedTabSelector, - string selectedPanelSelector, - string hiddenPanelSelector - ) - { - // Arrange - var selectedTab = Page.Locator("div.config-grid") - .Locator("fluent-tabs#config-tab") - .Locator(selectedTabSelector); - var selectedPanel = Page.Locator("div.config-grid") - .Locator("fluent-tabs#config-tab") - .Locator(selectedPanelSelector); - var hiddenPanel = Page.Locator("div.config-grid") - .Locator("fluent-tabs#config-tab") - .Locator(hiddenPanelSelector); - - // Act - await selectedTab.ClickAsync(); - - // Assert - await Expect(selectedPanel).ToBeVisibleAsync(); - await Expect(hiddenPanel).ToBeHiddenAsync(); - } - - [Test] - public async Task Given_ChatGrid_When_Endpoint_Invoked_Then_ChatWindow_Should_Be_Displayed() - { - // Act - var element = Page.Locator("div.chat-grid") - .Locator("div#chat-window"); - - // Assert - await Expect(element).ToBeVisibleAsync(); - } - - [Test] - public async Task Given_ChatGrid_When_Endpoint_Invoked_Then_ChatHistory_Should_Be_Empty() - { - // Act - var element = Page.Locator("div.chat-grid") - .Locator("div#chat-window") - .Locator("div#chat-history"); - - var text = await element.TextContentAsync(); - - // Assert - text.Should().BeNullOrEmpty(); - } - - [Test] - public async Task Given_ChatGrid_When_Endpoint_Invoked_Then_ChatPrompt_Should_Be_Displayed() - { - // Act - var element = Page.Locator("div.chat-grid") - .Locator("div#chat-window") - .Locator("div#chat-prompt"); - - // Assert - await Expect(element).ToBeVisibleAsync(); - } - - [Test] - public async Task Given_ChatGrid_When_Endpoint_Invoked_Then_ChatPromptArea_Should_Be_Displayed() - { - // Act - var element = Page.Locator("div.chat-grid") - .Locator("div#chat-window") - .Locator("div#chat-prompt") - .Locator("fluent-text-area#prompt"); - - // Assert - await Expect(element).ToBeVisibleAsync(); - } - - [Test] - [TestCase("button-clear")] - [TestCase("button-send")] - public async Task Given_ChatGrid_When_Endpoint_Invoked_Then_ChatPromptButton_Should_Be_Displayed(string id) - { - // Act - var element = Page.Locator("div.chat-grid") - .Locator("div#chat-window") - .Locator("div#chat-prompt") - .Locator($"div > fluent-button#{id}"); - - // Assert - await Expect(element).ToBeVisibleAsync(); - } - - [Test] - [TestCase("abcde")] - public async Task Given_ChatPrompt_When_Send_Clicked_Then_ChatHistoryMessage_Should_Be_Displayed_OnTheRight(string text) - { - // Arrange - var history = Page.Locator("div.chat-grid") - .Locator("div#chat-window") - .Locator("div#chat-history"); - var prompt = Page.Locator("div.chat-grid") - .Locator("div#chat-window") - .Locator("div#chat-prompt") - .Locator("fluent-text-area#prompt"); - var send = Page.Locator("div.chat-grid") - .Locator("div#chat-window") - .Locator("div#chat-prompt") - .Locator("div > fluent-button#button-send"); - - // Act - await prompt.Locator("textarea").FillAsync(text); - await send.ClickAsync(); - - var style = await history.Locator("div#message-00").GetAttributeAsync("style"); - - // Assert - style.Should().ContainAll("justify-content:", "end"); - } - - [Test] - [TestCase("abcde")] - public async Task Given_ChatPrompt_When_Send_Clicked_Then_ChatHistoryMessage_Should_Be_Displayed(string text) - { - // Arrange - var history = Page.Locator("div.chat-grid") - .Locator("div#chat-window") - .Locator("div#chat-history"); - var prompt = Page.Locator("div.chat-grid") - .Locator("div#chat-window") - .Locator("div#chat-prompt") - .Locator("fluent-text-area#prompt"); - var send = Page.Locator("div.chat-grid") - .Locator("div#chat-window") - .Locator("div#chat-prompt") - .Locator("div > fluent-button#button-send"); - - // Act - await prompt.Locator("textarea").FillAsync(text); - await send.ClickAsync(); - - var item = await history.Locator("div#message-00 p").TextContentAsync(); - - // Assert - item.Should().Be(text); - } - - [Test] - [TestCase("abcde")] - public async Task Given_ChatPrompt_When_Send_Clicked_Then_ChatPromptArea_Should_Be_Empty(string text) - { - // Arrange - var prompt = Page.Locator("div.chat-grid") - .Locator("div#chat-window") - .Locator("div#chat-prompt") - .Locator("fluent-text-area#prompt"); - var send = Page.Locator("div.chat-grid") - .Locator("div#chat-window") - .Locator("div#chat-prompt") - .Locator("div > fluent-button#button-send"); - - // Act - await prompt.Locator("textarea").FillAsync(text); - await send.ClickAsync(); - - var item = await prompt.Locator("textarea").TextContentAsync(); - - // Assert - item.Should().BeNullOrEmpty(); - } - - [Test] - [TestCase("abcde")] - public async Task Given_ChatPrompt_When_Clear_Clicked_Then_ChatHistoryMessage_Should_Be_Cleared(string text) - { - // Arrange - var history = Page.Locator("div.chat-grid") - .Locator("div#chat-window") - .Locator("div#chat-history"); - var prompt = Page.Locator("div.chat-grid") - .Locator("div#chat-window") - .Locator("div#chat-prompt") - .Locator("fluent-text-area#prompt"); - var send = Page.Locator("div.chat-grid") - .Locator("div#chat-window") - .Locator("div#chat-prompt") - .Locator("div > fluent-button#button-send"); - var clear = Page.Locator("div.chat-grid") - .Locator("div#chat-window") - .Locator("div#chat-prompt") - .Locator("div > fluent-button#button-clear"); - - // Act - await prompt.Locator("textarea").FillAsync(text); - await send.ClickAsync(); - await clear.ClickAsync(); - - var result = await history.TextContentAsync(); - - // Assert - result.Should().BeNullOrEmpty(); - } - - [Test] - public async Task Given_ApiKeynputField_When_Endpoint_Invoked_Then_It_Should_Be_Visible() - { - // Arrange - var apiKeyInput = Page.Locator("fluent-text-field#api-key").Locator("input"); - - // Act & Assert - await Expect(apiKeyInput).ToBeVisibleAsync(); - } - - [Test] - public async Task Given_ApiKeyInputField_When_Endpoint_Invoked_Then_It_Should_Be_Password_Type() - { - // Arrange - var apiKeyInput = Page.Locator("fluent-text-field#api-key").Locator("input"); - - // Act - var inputType = await apiKeyInput.GetAttributeAsync("type"); - - // Assert - inputType.Should().Be("password"); - } - - [Test] - [TestCase("test-api-key-1")] - [TestCase("example-key-123")] - public async Task Given_ApiKeyInputField_When_Changed_Then_It_Should_Be_Updated(string apiKey) - { - // Arrange - var apiKeyInput = Page.Locator("fluent-text-field#api-key").Locator("input"); - - // Act - await apiKeyInput.FillAsync(apiKey); - - // Assert - await Expect(apiKeyInput).ToHaveValueAsync(apiKey); - } - [TearDown] public async Task CleanUp() { await Page.CloseAsync(); } } - diff --git a/test/AzureOpenAIProxy.PlaygroundApp.Tests/Pages/TestsPageTests.cs b/test/AzureOpenAIProxy.PlaygroundApp.Tests/Pages/TestsPageTests.cs deleted file mode 100644 index f6be2968..00000000 --- a/test/AzureOpenAIProxy.PlaygroundApp.Tests/Pages/TestsPageTests.cs +++ /dev/null @@ -1,149 +0,0 @@ -using FluentAssertions; - -using Microsoft.Playwright; -using Microsoft.Playwright.NUnit; - -namespace AzureOpenAIProxy.PlaygroundApp.Tests.Pages; - -[Parallelizable(ParallelScope.Self)] -[TestFixture] -[Property("Category", "Integration")] -public class TestsPageTests : PageTest -{ - public override BrowserNewContextOptions ContextOptions() => new() - { - IgnoreHTTPSErrors = true, - }; - - [SetUp] - public async Task Setup() - { - // Arrange - await Page.GotoAsync("https://localhost:5001/tests"); - await Page.WaitForLoadStateAsync(LoadState.NetworkIdle); - } - - [Test] - public async Task Given_No_Input_On_DebugTarget_When_DebugButton_Clicked_Then_Toast_Should_Show_NullMessage() - { - // Arrange - var button = Page.Locator("fluent-button#debug-button"); - - // Act - await button.ClickAsync(); - - // Assert - await Expect(Page.Locator(".fluent-toast-title")).ToHaveTextAsync("Input is null."); - } - - [Test] - [TestCase(123, typeof(int))] - [TestCase(456, typeof(int))] - [TestCase(789, typeof(int))] - public async Task Given_Input_On_DebugTarget_When_DebugButton_Clicked_Then_Toast_Should_Show_Input(int inputValue, Type expectedType) - { - // Arrange - var radio = Page.Locator("fluent-radio-group#debug-target") - .Locator($"fluent-radio[current-value='{inputValue}']"); - var button = Page.Locator("fluent-button#debug-button"); - - // Act - await radio.ClickAsync(); - await button.ClickAsync(); - - // Assert - await Expect(Page.Locator(".fluent-toast-title")).ToHaveTextAsync($"{inputValue} (Type: {expectedType})"); - } - - [Test] - [TestCase("3F2504E0-4F89-11D3-9A0C-0305E82C3301", typeof(string))] - [TestCase("b9f6741c-2f44-4d9b-bd63-c0e6b97cc83f", typeof(string))] - - public async Task Given_Input_On_ApiKeyField_When_DebugButton_Clicked_Then_Toast_Should_Show_Input(string apiKey, Type expectedType) - { - // Arrange - var apiKeyInput = Page.Locator("fluent-text-field#api-key-input").Locator("input"); - var debugButton = Page.Locator("fluent-button#debug-api-key"); - - // Act - await apiKeyInput.FillAsync(apiKey); - await debugButton.ClickAsync(); - - // Assert - await Expect(Page.Locator(".fluent-toast-title")).ToHaveTextAsync($"{apiKey} (Type: {expectedType})"); - } - - [Test] - [TestCase("deployment-model-label", "Deployment")] - public async Task Given_Label_When_Page_Loaded_Then_Label_Should_Be_Visible(string id, string expected) - { - // Arrange - var label = Page.Locator($"label#{id}"); - - // Act - var result = await label.TextContentAsync(); - - // Assert - result.Should().Be(expected); - } - - [Test] - [TestCase("deployment-model-list-options")] - public async Task Given_DropdownList_When_Page_Loaded_Then_DropdownList_Should_Be_Visible(string id) - { - // Act - var select = Page.Locator($"fluent-select#{id}"); - - // Assert - await Expect(select).ToBeVisibleAsync(); - } - - [Test] - [TestCase("deployment-model-list-options")] - public async Task Given_DropdownList_When_DropdownList_Clicked_And_DropdownOptions_Appeared_Then_All_DropdownOptions_Should_Be_Visible(string id) - { - // Arrange - var fluentSelect = Page.Locator($"fluent-select#{id}"); - - // Act - await fluentSelect.ClickAsync(); - var fluentOptions = fluentSelect.Locator("fluent-option"); - - // Assert - for (int i = 0; i < await fluentOptions.CountAsync(); i++) - { - await Expect(fluentOptions.Nth(i)).ToBeVisibleAsync(); - } - } - - [Test] - [TestCase(2, "AZ", typeof(string))] - [TestCase(4, "CA", typeof(string))] - [TestCase(6, "CT", typeof(string))] - [TestCase(8, "FL", typeof(string))] - public async Task Given_DropdownOptions_And_ExpectedValue_When_Third_DropdownOption_Selected_And_DropdownValue_Updated_Then_DropdownValue_Should_Match_ExpectedValue(int index, string expectedValue, Type expectedType) - { - // Arrange - var fluentSelect = Page.Locator("fluent-select#deployment-model-list-options"); - await fluentSelect.ClickAsync(); - var fluentOptions = fluentSelect.Locator("fluent-option"); - var button = Page.Locator("fluent-button#debug-button-deployment-model-list"); - - // Act - await fluentOptions.Nth(index).ScrollIntoViewIfNeededAsync(); - await fluentOptions.Nth(index).ClickAsync(); - await button.ClickAsync(); - - // Assert - await Expect(Page.Locator(".fluent-toast-title")).ToHaveTextAsync($"{expectedValue} (Type: {expectedType})"); - } - - - [TearDown] - public async Task CleanUp() - { - await Page.CloseAsync(); - } - - -} \ No newline at end of file