diff --git a/src/AzureOpenAIProxy.PlaygroundApp/Components/Pages/Home.razor b/src/AzureOpenAIProxy.PlaygroundApp/Components/Pages/Home.razor index ec9c95ef..51c675bf 100644 --- a/src/AzureOpenAIProxy.PlaygroundApp/Components/Pages/Home.razor +++ b/src/AzureOpenAIProxy.PlaygroundApp/Components/Pages/Home.razor @@ -1,5 +1,4 @@ @page "/" -@using AzureOpenAIProxy.PlaygroundApp.Components.UI Home diff --git a/src/AzureOpenAIProxy.PlaygroundApp/Components/Pages/Playground.razor b/src/AzureOpenAIProxy.PlaygroundApp/Components/Pages/Playground.razor index ac7463cb..4ade2e46 100644 --- a/src/AzureOpenAIProxy.PlaygroundApp/Components/Pages/Playground.razor +++ b/src/AzureOpenAIProxy.PlaygroundApp/Components/Pages/Playground.razor @@ -8,6 +8,7 @@ + diff --git a/src/AzureOpenAIProxy.PlaygroundApp/Components/Pages/Tests.razor b/src/AzureOpenAIProxy.PlaygroundApp/Components/Pages/Tests.razor index 40ebae28..42bbe51b 100644 --- a/src/AzureOpenAIProxy.PlaygroundApp/Components/Pages/Tests.razor +++ b/src/AzureOpenAIProxy.PlaygroundApp/Components/Pages/Tests.razor @@ -1,29 +1,38 @@ -@page "/tests" -@rendermode InteractiveServer - -

Component Tests

- -

Debug Button

- - - -

Deployment Models

- - - -@code { - private object? targetValue; - private string? selectedModel; - - private async Task SetInput(int value) - { - targetValue = value; - await Task.CompletedTask; - } - - private async Task SetDeploymentModel(string value) - { - selectedModel = value; - await Task.CompletedTask; - } -} +@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 new file mode 100644 index 00000000..d81073fc --- /dev/null +++ b/src/AzureOpenAIProxy.PlaygroundApp/Components/UI/ApiKeyInputComponent.razor @@ -0,0 +1,22 @@ +API key input + +@code { + private string? apiKeyValue { get; set; } + + [Parameter] + public string? Id { get; set; } + + [Parameter] + public EventCallback OnKeyInput { get; set; } + + private async Task SetApiKey(ChangeEventArgs e) + { + apiKeyValue = e.Value!.ToString(); + if (string.IsNullOrWhiteSpace(apiKeyValue) == true) + { + return; + } + + await OnKeyInput.InvokeAsync(apiKeyValue); + } +} diff --git a/test/AzureOpenAIProxy.PlaygroundApp.Tests/Pages/PlaygroundPageTests.cs b/test/AzureOpenAIProxy.PlaygroundApp.Tests/Pages/PlaygroundPageTests.cs index 88d80724..6692fde3 100644 --- a/test/AzureOpenAIProxy.PlaygroundApp.Tests/Pages/PlaygroundPageTests.cs +++ b/test/AzureOpenAIProxy.PlaygroundApp.Tests/Pages/PlaygroundPageTests.cs @@ -1,293 +1,332 @@ -using FluentAssertions; - -using Microsoft.Playwright; -using Microsoft.Playwright.NUnit; - -namespace AzureOpenAIProxy.PlaygroundApp.Tests.Pages; - -[Parallelizable(ParallelScope.Self)] -[TestFixture] -[Property("Category", "Integration")] -public class PlaygroundPageTests : PageTest -{ - public override BrowserNewContextOptions ContextOptions() => new() { IgnoreHTTPSErrors = true, }; - - [SetUp] - public async Task Init() - { - await Page.GotoAsync("https://localhost:5001/playground/"); - await Page.WaitForLoadStateAsync(LoadState.NetworkIdle); - } - - [Test] - public async Task Given_Page_When_Endpoint_Invoked_Then_It_Should_Show_Header() - { - // Arrange - var header = Page.Locator("div.layout") - .Locator("header.header") - .Locator("div.header-gutters") - .Locator("h1"); - - // Act - var headerText = await header.TextContentAsync(); - - // Assert - headerText.Should().Be("Azure OpenAI Proxy Playground"); - } - - [Test] - [TestCase("config-grid")] - [TestCase("chat-grid")] - public async Task Given_Page_When_Endpoint_Invoked_Then_It_Should_Show_Panels(string id) - { - // Act - var panel = Page.Locator($"div.{id}"); - - // Assert - 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(); - } - - [TearDown] - public async Task CleanUp() - { - await Page.CloseAsync(); - } -} \ No newline at end of file +using FluentAssertions; + +using Microsoft.Playwright; +using Microsoft.Playwright.NUnit; + +namespace AzureOpenAIProxy.PlaygroundApp.Tests.Pages; + +[Parallelizable(ParallelScope.Self)] +[TestFixture] +[Property("Category", "Integration")] +public class PlaygroundPageTests : PageTest +{ + public override BrowserNewContextOptions ContextOptions() => new() { IgnoreHTTPSErrors = true, }; + + [SetUp] + public async Task Init() + { + await Page.GotoAsync("https://localhost:5001/playground/"); + await Page.WaitForLoadStateAsync(LoadState.NetworkIdle); + } + + [Test] + public async Task Given_Page_When_Endpoint_Invoked_Then_It_Should_Show_Header() + { + // Arrange + var header = Page.Locator("div.layout") + .Locator("header.header") + .Locator("div.header-gutters") + .Locator("h1"); + + // Act + var headerText = await header.TextContentAsync(); + + // Assert + headerText.Should().Be("Azure OpenAI Proxy Playground"); + } + + [Test] + [TestCase("config-grid")] + [TestCase("chat-grid")] + public async Task Given_Page_When_Endpoint_Invoked_Then_It_Should_Show_Panels(string id) + { + // Act + var panel = Page.Locator($"div.{id}"); + + // Assert + 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 index 0d4ca2f1..f6be2968 100644 --- a/test/AzureOpenAIProxy.PlaygroundApp.Tests/Pages/TestsPageTests.cs +++ b/test/AzureOpenAIProxy.PlaygroundApp.Tests/Pages/TestsPageTests.cs @@ -1,128 +1,149 @@ -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("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(); - } +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