Browse Source

Added PortsPom / E2E ui tests

Tim Jones 1 month ago
parent
commit
613142b0da

+ 12 - 2
Shared.Rcl/Connections/PortConnectionModal.razor

@@ -12,8 +12,10 @@
 
 
         <div class="absolute inset-0 bg-black/70" @onclick="Cancel"></div>
         <div class="absolute inset-0 bg-black/70" @onclick="Cancel"></div>
 
 
-        <div class="relative bg-zinc-900 border border-zinc-800 rounded w-full max-w-3xl p-4">
-
+        <div
+            class="relative bg-zinc-900 border border-zinc-800 rounded w-full max-w-3xl p-4"
+            data-testid="@($"{BaseTestId}-container")">
+            
             <div class="flex justify-between mb-4">
             <div class="flex justify-between mb-4">
                 <div class="text-zinc-100 text-sm font-medium">
                 <div class="text-zinc-100 text-sm font-medium">
                     Create Connection
                     Create Connection
@@ -33,6 +35,7 @@
                     <div class="text-zinc-400">Side A</div>
                     <div class="text-zinc-400">Side A</div>
 
 
                     <select class="w-full bg-zinc-800 border border-zinc-700 rounded px-2 py-1 text-zinc-100"
                     <select class="w-full bg-zinc-800 border border-zinc-700 rounded px-2 py-1 text-zinc-100"
+                            data-testid="@($"{BaseTestId}-resource-a")"
                             @bind="_resourceAIndex">
                             @bind="_resourceAIndex">
 
 
                         <option value="">Select resource</option>
                         <option value="">Select resource</option>
@@ -48,6 +51,7 @@
                     @if (_resourceA?.Ports?.Any() == true)
                     @if (_resourceA?.Ports?.Any() == true)
                     {
                     {
                         <select class="w-full bg-zinc-800 border border-zinc-700 rounded px-2 py-1 text-zinc-100"
                         <select class="w-full bg-zinc-800 border border-zinc-700 rounded px-2 py-1 text-zinc-100"
+                                data-testid="@($"{BaseTestId}-group-a")"
                                 @bind="_groupAIndex">
                                 @bind="_groupAIndex">
 
 
                             <option value="">Select group</option>
                             <option value="">Select group</option>
@@ -64,6 +68,7 @@
                     @if (_groupA is not null)
                     @if (_groupA is not null)
                     {
                     {
                         <select class="w-full bg-zinc-800 border border-zinc-700 rounded px-2 py-1 text-zinc-100"
                         <select class="w-full bg-zinc-800 border border-zinc-700 rounded px-2 py-1 text-zinc-100"
+                                data-testid="@($"{BaseTestId}-port-a")"
                                 @bind="_portAIndex">
                                 @bind="_portAIndex">
 
 
                             <option value="">Select port</option>
                             <option value="">Select port</option>
@@ -92,6 +97,7 @@
                     <div class="text-zinc-400">Side B</div>
                     <div class="text-zinc-400">Side B</div>
 
 
                     <select class="w-full bg-zinc-800 border border-zinc-700 rounded px-2 py-1 text-zinc-100"
                     <select class="w-full bg-zinc-800 border border-zinc-700 rounded px-2 py-1 text-zinc-100"
+                            data-testid="@($"{BaseTestId}-resource-b")"
                             @bind="_resourceBIndex">
                             @bind="_resourceBIndex">
 
 
                         <option value="">Select resource</option>
                         <option value="">Select resource</option>
@@ -107,6 +113,7 @@
                     @if (_resourceB?.Ports?.Any() == true)
                     @if (_resourceB?.Ports?.Any() == true)
                     {
                     {
                         <select class="w-full bg-zinc-800 border border-zinc-700 rounded px-2 py-1 text-zinc-100"
                         <select class="w-full bg-zinc-800 border border-zinc-700 rounded px-2 py-1 text-zinc-100"
+                                data-testid="@($"{BaseTestId}-group-b")"
                                 @bind="_groupBIndex">
                                 @bind="_groupBIndex">
 
 
                             <option value="">Select group</option>
                             <option value="">Select group</option>
@@ -123,6 +130,7 @@
                     @if (_groupB is not null)
                     @if (_groupB is not null)
                     {
                     {
                         <select class="w-full bg-zinc-800 border border-zinc-700 rounded px-2 py-1 text-zinc-100"
                         <select class="w-full bg-zinc-800 border border-zinc-700 rounded px-2 py-1 text-zinc-100"
+                                data-testid="@($"{BaseTestId}-port-b")"
                                 @bind="_portBIndex">
                                 @bind="_portBIndex">
 
 
                             <option value="">Select port</option>
                             <option value="">Select port</option>
@@ -149,12 +157,14 @@
             <div class="flex justify-end gap-2 mt-6">
             <div class="flex justify-end gap-2 mt-6">
 
 
                 <button class="px-3 py-1 border border-zinc-700 rounded text-zinc-300"
                 <button class="px-3 py-1 border border-zinc-700 rounded text-zinc-300"
+                        data-testid="@($"{BaseTestId}-cancel")"
                         @onclick="Cancel">
                         @onclick="Cancel">
                     Cancel
                     Cancel
                 </button>
                 </button>
 
 
                 <button class="px-3 py-1 rounded bg-emerald-600 text-black"
                 <button class="px-3 py-1 rounded bg-emerald-600 text-black"
                         disabled="@(!CanSubmit)"
                         disabled="@(!CanSubmit)"
+                        data-testid="@($"{BaseTestId}-submit")"
                         @onclick="HandleSubmit">
                         @onclick="HandleSubmit">
                     Add Connection
                     Add Connection
                 </button>
                 </button>

+ 17 - 11
Shared.Rcl/Connections/PortGroupVisualizer.razor

@@ -20,28 +20,29 @@
 
 
             var conn = GetConnection(port);
             var conn = GetConnection(port);
             var selected = SelectedPortIndex == index;
             var selected = SelectedPortIndex == index;
-
+            
             <button type="button"
             <button type="button"
+                    data-testid="@($"{BaseTestId}-port-{index}")"
                     title="@GetTooltip(conn, port)"
                     title="@GetTooltip(conn, port)"
                     class="group flex flex-col items-center w-6 leading-none"
                     class="group flex flex-col items-center w-6 leading-none"
                     @onclick="() => SelectPort(index, port)">
                     @onclick="() => SelectPort(index, port)">
-
+                
                 <div class="w-6 h-3 flex items-center justify-center
                 <div class="w-6 h-3 flex items-center justify-center
                             shadow-inner
                             shadow-inner
                             border-t border-b border-r
                             border-t border-b border-r
                             @(index == 0 ? "border-l" : "")
                             @(index == 0 ? "border-l" : "")
                             @(selected
                             @(selected
-                                                                                                                       ? "bg-emerald-500 border-emerald-400"
-                                                                                                                       : conn != null
-                                                                                                                           ? "bg-blue-600 border-blue-500"
-                                                                                                                           : "bg-zinc-800 border-zinc-700 group-hover:bg-zinc-700")">
+                                ? "bg-emerald-500 border-emerald-400"
+                                : conn != null
+                                    ? "bg-blue-600 border-blue-500"
+                                    : "bg-zinc-800 border-zinc-700 group-hover:bg-zinc-700")">
 
 
                     <div class="w-2 h-[1.5px]
                     <div class="w-2 h-[1.5px]
                                 @(selected
                                 @(selected
-                                                                    ? "bg-black"
-                                                                    : conn != null
-                                                                        ? "bg-blue-200"
-                                                                        : "bg-zinc-600")">
+                                    ? "bg-black"
+                                    : conn != null
+                                        ? "bg-blue-200"
+                                        : "bg-zinc-600")">
                     </div>
                     </div>
 
 
                 </div>
                 </div>
@@ -61,6 +62,7 @@
     [Parameter] public string ResourceName { get; set; } = "";
     [Parameter] public string ResourceName { get; set; } = "";
     [Parameter] public int PortGroupIndex { get; set; }
     [Parameter] public int PortGroupIndex { get; set; }
     [Parameter] public Port? PortGroup { get; set; }
     [Parameter] public Port? PortGroup { get; set; }
+    [Parameter] public string? TestIdPrefix { get; set; }
 
 
     [Parameter] public int? SelectedPortIndex { get; set; }
     [Parameter] public int? SelectedPortIndex { get; set; }
     [Parameter] public EventCallback<int?> SelectedPortIndexChanged { get; set; }
     [Parameter] public EventCallback<int?> SelectedPortIndexChanged { get; set; }
@@ -68,7 +70,11 @@
     [Parameter] public EventCallback<PortReference> OnPortClicked { get; set; }
     [Parameter] public EventCallback<PortReference> OnPortClicked { get; set; }
 
 
     private List<Connection> _connections = new();
     private List<Connection> _connections = new();
-
+    private string BaseTestId =>
+        string.IsNullOrWhiteSpace(TestIdPrefix)
+            ? "port-visualizer"
+            : TestIdPrefix;
+    
     protected override async Task OnParametersSetAsync()
     protected override async Task OnParametersSetAsync()
     {
     {
         _connections = (await Repository.GetConnectionsAsync()).ToList();
         _connections = (await Repository.GetConnectionsAsync()).ToList();

+ 9 - 9
Shared.Rcl/Hardware/PortGroupEditor.razor

@@ -14,8 +14,9 @@
     <div class="flex items-center justify-between mb-1 group">
     <div class="flex items-center justify-between mb-1 group">
         <div class="text-zinc-400">
         <div class="text-zinc-400">
             Ports
             Ports
+
             <button
             <button
-                data-testid="@($"{BaseTestId}-add-button")"
+                data-testid="@($"{BaseTestId}-add")"
                 class="hover:text-emerald-400 group-hover:opacity-100 transition"
                 class="hover:text-emerald-400 group-hover:opacity-100 transition"
                 title="Add Port"
                 title="Add Port"
                 @onclick="OpenAddNic">
                 @onclick="OpenAddNic">
@@ -38,20 +39,22 @@
                     <button
                     <button
                         data-testid="@($"{BaseTestId}-edit-{idx}")"
                         data-testid="@($"{BaseTestId}-edit-{idx}")"
                         class="hover:text-emerald-400 text-sm"
                         class="hover:text-emerald-400 text-sm"
-                        title="Edit NIC"
+                        title="Edit Port Group"
                         @onclick="() => OpenEditNic(nic)">
                         @onclick="() => OpenEditNic(nic)">
                         @nic.Type — @nic.Speed Gbps (@nic.Count ports)
                         @nic.Type — @nic.Speed Gbps (@nic.Count ports)
                     </button>
                     </button>
 
 
                 </div>
                 </div>
 
 
-                <div class="pl-1"
-                     data-testid="@($"{BaseTestId}-ports-{idx}")">
+                <div
+                    class="pl-1"
+                    data-testid="@($"{BaseTestId}-ports-{idx}")">
 
 
                     <PortGroupVisualizer
                     <PortGroupVisualizer
                         ResourceName="@Resource.Name"
                         ResourceName="@Resource.Name"
                         PortGroupIndex="@idx"
                         PortGroupIndex="@idx"
                         PortGroup="@nic"
                         PortGroup="@nic"
+                        TestIdPrefix="@($"{BaseTestId}-visualizer-{idx}")"
                         OnPortClicked="HandlePortClicked"/>
                         OnPortClicked="HandlePortClicked"/>
 
 
                 </div>
                 </div>
@@ -62,22 +65,19 @@
 
 
 </div>
 </div>
 
 
-
 <PortModal
 <PortModal
     IsOpen="@_nicModalOpen"
     IsOpen="@_nicModalOpen"
     IsOpenChanged="v => _nicModalOpen = v"
     IsOpenChanged="v => _nicModalOpen = v"
     Value="@_editingNic"
     Value="@_editingNic"
     OnSubmit="HandleNicSubmit"
     OnSubmit="HandleNicSubmit"
     OnDelete="HandleNicDelete"
     OnDelete="HandleNicDelete"
-    TestIdPrefix="@($"{BaseTestId}-modal")"/>
-
+    TestIdPrefix="@($"{BaseTestId}")"/>
 
 
 <PortConnectionModal
 <PortConnectionModal
     IsOpen="@_connectionModalOpen"
     IsOpen="@_connectionModalOpen"
     IsOpenChanged="v => _connectionModalOpen = v"
     IsOpenChanged="v => _connectionModalOpen = v"
     SeedPort="@_selectedPort"
     SeedPort="@_selectedPort"
-    TestIdPrefix="@($"{BaseTestId}-connection")"/>
-
+    TestIdPrefix="@($"{BaseTestId}")"/>
 
 
 @code {
 @code {
 
 

+ 98 - 0
Tests.E2e/AccessPointCardTests.cs

@@ -295,4 +295,102 @@ public class AccessPointCardTests(
             await context.CloseAsync();
             await context.CloseAsync();
         }
         }
     }
     }
+
+    [Fact]
+    public async Task User_Can_Add_Ports_To_Two_AccessPoints_And_Connect_Them() {
+        (IBrowserContext context, IPage page) = await CreatePageAsync();
+
+        var ap1 = $"e2e-ap-{Guid.NewGuid():N}"[..16];
+        var ap2 = $"e2e-ap-{Guid.NewGuid():N}"[..16];
+
+        try {
+            await page.GotoAsync(_fixture.BaseUrl);
+
+            var layout = new MainLayoutPom(page);
+            await layout.AssertLoadedAsync();
+            await layout.GotoHardwareAsync();
+
+            var hardwareTree = new HardwareTreePom(page);
+            await hardwareTree.AssertLoadedAsync();
+            await hardwareTree.GotoAccessPointsListAsync();
+
+            var list = new AccessPointsListPom(page);
+            await list.AssertLoadedAsync();
+
+            // -------------------------------------------------
+            // Create first AP
+            // -------------------------------------------------
+
+            await list.AddAccessPointAsync(ap1);
+            await page.WaitForURLAsync($"**/resources/hardware/{ap1}");
+
+            var card = new AccessPointCardPom(page);
+            await card.AssertCardVisibleAsync(ap1);
+
+            // Add port group to AP1
+            await card.AddPortGroupAsync(
+                "rj45",
+                "1",
+                2);
+
+            // -------------------------------------------------
+            // Create second AP
+            // -------------------------------------------------
+
+            await layout.GotoHardwareAsync();
+            await hardwareTree.AssertLoadedAsync();
+            await hardwareTree.GotoAccessPointsListAsync();
+            await list.AssertLoadedAsync();
+
+            await list.AddAccessPointAsync(ap2);
+            await page.WaitForURLAsync($"**/resources/hardware/{ap2}");
+
+            await card.AssertCardVisibleAsync(ap2);
+
+            // Add port group to AP2
+            await card.AddPortGroupAsync(
+                "sfp+",
+                "2.5",
+                2);
+            // -------------------------------------------------
+            // Go back to AP1 to create connection
+            // -------------------------------------------------
+
+            await layout.GotoHardwareAsync();
+            await hardwareTree.GotoAccessPointsListAsync();
+            await list.AssertLoadedAsync();
+            await list.OpenAccessPointAsync(ap1);
+
+            await card.AssertCardVisibleAsync(ap1);
+
+            // -------------------------------------------------
+            // Open connection modal from port
+            // -------------------------------------------------
+
+            await card.OpenConnectionFromPortAsync(0, 0);
+
+            // -------------------------------------------------
+            // Create connection
+            // -------------------------------------------------
+
+            await card.CreateConnectionAsync(
+                ap1,
+                "rj45 — 1 Gbps (2)", // example label — adjust if needed
+                "Port 1",
+                ap2,
+                "sfp+ — 2.5 Gbps (2)",
+                "Port 1");
+
+            // -------------------------------------------------
+            // Verify connection indicator appears
+            // -------------------------------------------------
+
+            await card.Ports.AssertPortVisibleAsync("accesspoint-ports", 0, 0);
+
+            await context.CloseAsync();
+        }
+        finally {
+            await context.CloseAsync();
+        }
+    }
 }
 }

+ 2 - 1
Tests.E2e/Infra/PlaywrightFixture.cs

@@ -34,8 +34,9 @@ public class PlaywrightFixture : IAsyncLifetime {
 
 
         Browser = await _playwright.Chromium.LaunchAsync(new BrowserTypeLaunchOptions {
         Browser = await _playwright.Chromium.LaunchAsync(new BrowserTypeLaunchOptions {
             Headless = true,
             Headless = true,
+            SlowMo = 400,
             //Headless = false,
             //Headless = false,
-            SlowMo = 500,
+            //SlowMo = 1500,
             Args = new[]
             Args = new[]
             {
             {
                 "--disable-dev-shm-usage",
                 "--disable-dev-shm-usage",

+ 35 - 0
Tests.E2e/PageObjectModels/AccessPointCardPom.cs

@@ -6,7 +6,9 @@ namespace Tests.E2e.PageObjectModels;
 public class AccessPointCardPom(IPage page) {
 public class AccessPointCardPom(IPage page) {
     public TagsPom Tags => new(page);
     public TagsPom Tags => new(page);
     public LabelsPom Labels => new(page);
     public LabelsPom Labels => new(page);
+    public PortsPom Ports => new(page);
 
 
+    private const string _portsPrefix = "accesspoint-ports";
     // Modals
     // Modals
     public ILocator DeleteConfirmModal => page.GetByTestId("AccessPoint-confirm-modal");
     public ILocator DeleteConfirmModal => page.GetByTestId("AccessPoint-confirm-modal");
     public ILocator DeleteConfirmButton => page.GetByTestId("AccessPoint-confirm-modal-confirm");
     public ILocator DeleteConfirmButton => page.GetByTestId("AccessPoint-confirm-modal-confirm");
@@ -153,4 +155,37 @@ public class AccessPointCardPom(IPage page) {
 
 
     private static string Sanitize(string value)
     private static string Sanitize(string value)
         => value.Replace(" ", "-");
         => value.Replace(" ", "-");
+
+    // -------------------------------------------------
+    // Ports
+    // -------------------------------------------------
+
+    public async Task AddPortGroupAsync(
+        string type,
+        string speed,
+        int count) {
+        await Ports.AddPortGroupAsync(
+            "accesspoint-ports",
+            type,
+            speed,
+            count);
+    }
+    public async Task OpenConnectionFromPortAsync(int groupIndex, int portIndex) => await Ports.OpenConnectionFromPortAsync(_portsPrefix, groupIndex, portIndex);
+
+    public async Task CreateConnectionAsync(
+        string resourceA,
+        string groupA,
+        string portA,
+        string resourceB,
+        string groupB,
+        string portB) {
+        await Ports.CreateConnectionAsync(
+            _portsPrefix,
+            resourceA,
+            groupA,
+            portA,
+            resourceB,
+            groupB,
+            portB);
+    }
 }
 }

+ 166 - 0
Tests.E2e/PageObjectModels/PortsPom.cs

@@ -0,0 +1,166 @@
+namespace Tests.E2e.PageObjectModels;
+
+using Microsoft.Playwright;
+
+public class PortsPom(IPage page) {
+    public TagsPom Tags => new(page);
+    public LabelsPom Labels => new(page);
+    public PortsPom Ports => new(page);
+
+    private const string _portsPrefix = "accesspoint-ports";
+
+    // -------------------------------------------------
+    // Root
+    // -------------------------------------------------
+
+    public ILocator Root(string testIdPrefix)
+        => page.GetByTestId($"{testIdPrefix}-port-group-section");
+
+    public ILocator AddButton(string testIdPrefix)
+        => page.GetByTestId($"{testIdPrefix}-port-group-add");
+
+    // -------------------------------------------------
+    // Port Groups
+    // -------------------------------------------------
+
+    public ILocator PortGroup(string testIdPrefix, int index)
+        => page.GetByTestId($"{testIdPrefix}-port-group-item-{index}");
+
+    public ILocator EditPortGroupButton(string testIdPrefix, int index)
+        => page.GetByTestId($"{testIdPrefix}-port-group-edit-{index}");
+
+    public ILocator PortsContainer(string testIdPrefix, int index)
+        => page.GetByTestId($"{testIdPrefix}-port-group-ports-{index}");
+
+    // -------------------------------------------------
+    // Individual Ports
+    // -------------------------------------------------
+
+    public ILocator Port(string testIdPrefix, int groupIndex, int portIndex)
+        => page.GetByTestId($"{testIdPrefix}-port-group-visualizer-{groupIndex}-port-{portIndex}");
+
+    // -------------------------------------------------
+    // Port Modal
+    // -------------------------------------------------
+
+    public ILocator PortModal(string testIdPrefix)
+        => page.GetByTestId($"{testIdPrefix}-port-group-port-modal");
+
+    // -------------------------------------------------
+    // Connection Modal
+    // -------------------------------------------------
+
+    public ILocator ConnectionModal(string testIdPrefix)
+        => page.GetByTestId($"{testIdPrefix}-port-group-connection-modal-container");
+
+    public ILocator ResourceASelect(string testIdPrefix)
+        => page.GetByTestId($"{testIdPrefix}-port-group-connection-modal-resource-a");
+
+    public ILocator GroupASelect(string testIdPrefix)
+        => page.GetByTestId($"{testIdPrefix}-port-group-connection-modal-group-a");
+
+    public ILocator PortASelect(string testIdPrefix)
+        => page.GetByTestId($"{testIdPrefix}-port-group-connection-modal-port-a");
+
+    public ILocator ResourceBSelect(string testIdPrefix)
+        => page.GetByTestId($"{testIdPrefix}-port-group-connection-modal-resource-b");
+
+    public ILocator GroupBSelect(string testIdPrefix)
+        => page.GetByTestId($"{testIdPrefix}-port-group-connection-modal-group-b");
+
+    public ILocator PortBSelect(string testIdPrefix)
+        => page.GetByTestId($"{testIdPrefix}-port-group-connection-modal-port-b");
+
+    public ILocator SubmitConnection(string testIdPrefix)
+        => page.GetByTestId($"{testIdPrefix}-port-group-connection-modal-submit");
+
+    // -------------------------------------------------
+    // Assertions
+    // -------------------------------------------------
+
+    public async Task AssertPortGroupVisibleAsync(string prefix, int index)
+        => await Assertions.Expect(PortGroup(prefix, index)).ToBeVisibleAsync();
+
+    public async Task AssertPortVisibleAsync(string prefix, int groupIndex, int portIndex)
+        => await Assertions.Expect(Port(prefix, groupIndex, portIndex)).ToBeVisibleAsync();
+
+    // -------------------------------------------------
+    // Actions
+    // -------------------------------------------------
+
+    public async Task AddPortGroupAsync(string prefix) {
+        await AddButton(prefix).ClickAsync();
+        await Assertions.Expect(PortModal(prefix)).ToBeVisibleAsync();
+    }
+
+    public async Task OpenConnectionFromPortAsync(string prefix, int groupIndex, int portIndex) {
+        await Port(prefix, groupIndex, portIndex).ClickAsync();
+        await Assertions.Expect(ConnectionModal(prefix)).ToBeVisibleAsync();
+    }
+
+    public async Task CreateConnectionAsync(
+        string prefix,
+        string resourceA,
+        string groupA,
+        string portA,
+        string resourceB,
+        string groupB,
+        string portB) {
+        await ResourceASelect(prefix).SelectOptionAsync(
+            new SelectOptionValue { Label = resourceA });
+
+        await GroupASelect(prefix).SelectOptionAsync(
+            new SelectOptionValue { Label = groupA });
+
+        await PortASelect(prefix).SelectOptionAsync(
+            new SelectOptionValue { Label = portA });
+
+        await ResourceBSelect(prefix).SelectOptionAsync(
+            new SelectOptionValue { Label = resourceB });
+
+        await GroupBSelect(prefix).SelectOptionAsync(
+            new SelectOptionValue { Label = groupB });
+
+        await PortBSelect(prefix).SelectOptionAsync(
+            new SelectOptionValue { Label = portB });
+
+        await SubmitConnection(prefix).ClickAsync();
+    }
+
+    // -------------------------------------------------
+    // Port Modal Fields
+    // -------------------------------------------------
+
+    public ILocator PortTypeSelect(string prefix)
+        => page.GetByTestId($"{prefix}-port-group-port-modal-type-input");
+
+    public ILocator PortSpeedSelect(string prefix)
+        => page.GetByTestId($"{prefix}-port-group-port-modal-speed-input");
+
+    public ILocator PortCountInput(string prefix)
+        => page.GetByTestId($"{prefix}-port-group-port-modal-count-input");
+    public ILocator PortSubmit(string prefix)
+        => page.GetByTestId($"{prefix}-port-group-port-modal-submit");
+
+    public ILocator PortCancel(string prefix)
+        => page.GetByTestId($"{prefix}-port-group-port-modal-cancel");
+
+    public async Task AddPortGroupAsync(
+        string prefix,
+        string type,
+        string speed,
+        int count) {
+        await AddButton(prefix).ClickAsync();
+
+        await Assertions.Expect(PortModal(prefix)).ToBeVisibleAsync();
+
+        await PortTypeSelect(prefix).SelectOptionAsync(
+            new SelectOptionValue { Label = type });
+
+        await PortSpeedSelect(prefix).FillAsync(speed.ToString());
+
+        await PortCountInput(prefix).FillAsync(count.ToString());
+
+        await PortSubmit(prefix).ClickAsync();
+    }
+}