From 7c10149ff353e6fec164d6249efbc9b05f00c866 Mon Sep 17 00:00:00 2001 From: Jonathan McCaffrey Date: Mon, 25 Apr 2022 16:43:45 -0400 Subject: [PATCH] feat(TestAutomation) Harass Calculator tests and Search box style fix --- Components/Form/FormNumberComponent.razor | 4 + IGP/Database.db | Bin 278528 -> 278528 bytes IGP/Dialog/SearchDialogComponent.razor | 7 +- IGP/IGP.sln | 6 + IGP/Pages/HarassCalculatorPage.razor | 214 ++++++++++++------- IGP/Portals/SearchPortal.razor | 23 +- IGP/wwwroot/generated/AgileTaskModels.json | 2 +- Model/TravelTime.cs | 4 +- TestAutomation/Pages/BasePage.cs | 13 ++ TestAutomation/Pages/HarassCalculatorPage.cs | 70 ++++++ TestAutomation/TestAutomation.csproj | 24 +++ TestAutomation/UnitTest1.cs | 120 +++++++++++ TestAutomation/Usings.cs | 9 + TestAutomation/Website.cs | 51 +++++ 14 files changed, 447 insertions(+), 100 deletions(-) create mode 100644 TestAutomation/Pages/BasePage.cs create mode 100644 TestAutomation/Pages/HarassCalculatorPage.cs create mode 100644 TestAutomation/TestAutomation.csproj create mode 100644 TestAutomation/UnitTest1.cs create mode 100644 TestAutomation/Usings.cs create mode 100644 TestAutomation/Website.cs diff --git a/Components/Form/FormNumberComponent.razor b/Components/Form/FormNumberComponent.razor index db68e1b..00abf5a 100644 --- a/Components/Form/FormNumberComponent.razor +++ b/Components/Form/FormNumberComponent.razor @@ -5,6 +5,7 @@ }
#lXPe0>lnLEIm=foY87yLZ&~X=jK!XRtdh z+$?nAK0hmvukNw=+kHL(W=}q!$?OLvZx$5T#5?&zJpjbiI&_E$SO`#;eBr#|Dh6jw&>_($-uzi0>lnLEHhEVoY8V)LZ&~X$L3T1Rtcd zZx*_6pP$vh$VkC(^SAqa0?ZzKL6g}JOx!Feu#0!{hkBOguz%ab{xQByoGc{Z*FG_U iY5T+k=KT0=4vdTn+Zi7)vk9 Harass Calculator @@ -12,21 +12,21 @@ Credit to Zard for deriving the formula. - + - @costOfWorker + @CostOfWorker - @alloyMinedPerSecondByWorker + @AlloyMinedPerSecondByWorker - @timeToProduceWorker + @TimeToProduceWorker @@ -34,40 +34,45 @@ + Id="numberOfWorkersLostToHarass" + Value="@((int)NumberOfWorkersLostToHarass)" + OnChange="@(e => { NumberOfWorkersLostToHarass = int.Parse(e.Value!.ToString()!); Calculate();})"> Number of workers lost to harass Number of townhalls you have - +
@{ var index = 0; } - @foreach (var travelTime in TravelTimes) - { + @foreach (var travelTime in TravelTimes) { index++; - if (index == 1) - { + if (index == 1) { continue; } - + var id = $"numberOfTownHallsExisting_{index}"; Worker travel time from other base @(travelTime.Index + 1) } +
+
- @totalAlloyHarassment + + @TotalAlloyHarassment +
@@ -77,19 +82,16 @@
- (Worker replacement costs: @WorkerReplacementCost()) + (Worker replacement costs: @WorkerReplacementCost())
- (Delayed mining time: @DelayedMiningCost()) + (Delayed mining time: @DelayedMiningCost())
- (Average travel time: @GetAverageTravelTime()) + (Average travel time: @GetAverageTravelTime())
- - +
- -
@@ -101,7 +103,10 @@ What is this tool? - The Harass Calculator allows you to calculate damage done to an enemy alloy line. For example, if you were to attack with Ichors, and kill 6 enemy workers, you can set the Number of workers lost to harass to 6. This would determine a loss of 741 alloy. Quite the large number. + The Harass Calculator allows you to calculate damage done to an enemy alloy line. For example, if you + were to attack with Ichors, and kill 6 enemy workers, you can set the Number of workers lost to + harass to 6. This would determine a loss of @ExampleTotalAlloyLoss alloy. Quite + the large number. @@ -110,12 +115,21 @@ What can I learn from this? - Well, let's assume you lost a full alloy line of workers, and have to take that 741 alloy cost (300 to rebuy the workers, and 441 in lost mining time.) + Well, let's assume you lost a full alloy line of workers, and have to take that + @ExampleTotalAlloyLoss alloy cost (@ExampleWorkerCost + to rebuy the workers, and @ExampleMiningTimeCost in lost mining + time.)

- If you were to set the Number of townhalls you have to 2, the calculator will consider worker transfer micro. Allowing you to cut the total cost by roughly 315 alloy. However, that number isn't entirely accurate, you are also going to have to bump up the Worker travel time to alloy to account for the time it takes the transferred workers to arrive at the decimated alloy line. + If you were to set the Number of townhalls you have to 2, the calculator will consider worker + transfer micro. Allowing you to cut the total cost by roughly + @ExampleTotalAlloyLossDifference alloy. However, that number isn't + entirely accurate, you are also going to have to bump up the Worker travel time to alloy to account for the time it takes the transferred workers to arrive at the decimated alloy line.

- Let's say it takes 10 seconds for workers to transfer from your second base. We can divide that number by 2, to represent our bases, and add those 5 additional seconds to Worker travel time to alloy, for the more accurate loss of 456 alloy (saving you 285 alloy.) Which is much better than not transferring workers! - + Let's say it takes 10 seconds for workers to transfer from your second base. Let's enter that for the + second base travel time for the more accurate loss of @ExampleTotalAlloyLossAccurate alloy + (saving you @ExampleTotalAlloyLossAccurateDifference alloy.) Which is + much better than not transferring workers!
@@ -194,101 +208,137 @@ @code { - float totalAlloyHarassment = 0; - - readonly float costOfWorker = 50; - readonly float alloyMinedPerSecondByWorker = 1; - readonly float timeToProduceWorker = 20; - float numberOfWorkersLostToHarass = 1; - float numberOfTownHallsExisting = 1; - - float GetAverageTravelTime() - { - if (TravelTimes.Count == 0) - { + // Example calcs + float ExampleTotalAlloyLoss => Calculate( + WorkerReplacementCost(6), + SimultaneousProductionFloor(1,6), + 6, + new List { 0 }); + + float ExampleWorkerCost => WorkerReplacementCost(6); + + float ExampleMiningTimeCost => ExampleTotalAlloyLoss - ExampleWorkerCost; + + float ExampleTotalAlloyLossDifference => ExampleTotalAlloyLoss - Calculate( + WorkerReplacementCost(6), + SimultaneousProductionFloor(2,6), + 6, + new List { 0, 0 }); + + float ExampleTotalAlloyLossAccurate => Calculate( + WorkerReplacementCost(6), + SimultaneousProductionFloor(2,6), + 6, + new List { 0, 10 }); + + float ExampleTotalAlloyLossAccurateDifference => ExampleTotalAlloyLoss - ExampleTotalAlloyLossAccurate; + + float TotalAlloyHarassment = 0; + + readonly float CostOfWorker = 50; + readonly float AlloyMinedPerSecondByWorker = 1; + readonly float TimeToProduceWorker = 20; + float NumberOfWorkersLostToHarass = 1; + float NumberOfTownHallsExisting = 1; + + float GetAverageTravelTime() { + if (TravelTimes.Count == 0) { return 0; } - var sum = 0; + float sum = 0; - foreach (var travelTime in TravelTimes) - { + foreach (var travelTime in TravelTimes) { sum += travelTime.Value; } - return sum / numberOfTownHallsExisting; + return sum / NumberOfTownHallsExisting; } - float SimultaneousProductionFloor() - { - if (numberOfTownHallsExisting <= 0 || numberOfWorkersLostToHarass <= 0) - { + float SimultaneousProductionFloor() { + if (NumberOfTownHallsExisting <= 0 || NumberOfWorkersLostToHarass <= 0) { return 0; } - return numberOfWorkersLostToHarass / Math.Min(numberOfTownHallsExisting, numberOfWorkersLostToHarass); + return NumberOfWorkersLostToHarass / Math.Min(NumberOfTownHallsExisting, NumberOfWorkersLostToHarass); } + + float SimultaneousProductionFloor(float existingTownHalls, float numberOfWorkersLost) { + if (existingTownHalls <= 0 || numberOfWorkersLost <= 0) { + return 0; + } - float WorkerReplacementCost() - { - return costOfWorker * numberOfWorkersLostToHarass; + return numberOfWorkersLost / Math.Min(existingTownHalls, numberOfWorkersLost); } - float DelayedMiningCost() - { - return totalAlloyHarassment - WorkerReplacementCost(); + float WorkerReplacementCost() { + return CostOfWorker * NumberOfWorkersLostToHarass; + } + + float WorkerReplacementCost(int numberOfWorkersLostToHarass) { + return CostOfWorker * numberOfWorkersLostToHarass; } - void Calculate() - { - totalAlloyHarassment = WorkerReplacementCost(); + float DelayedMiningCost() { + return TotalAlloyHarassment - WorkerReplacementCost(); + } - for (var workerProductionIndex = 0; workerProductionIndex < SimultaneousProductionFloor(); workerProductionIndex++) - { + void Calculate() { + TotalAlloyHarassment = Calculate(WorkerReplacementCost(), + SimultaneousProductionFloor(), + NumberOfWorkersLostToHarass, + TravelTimes.Select(x => x.Value).ToList(), + TimeToProduceWorker, + AlloyMinedPerSecondByWorker); + } + + float Calculate(float workerReplacementCost, + float simultaneousProductionFloor, + float numberOfWorkersLostToHarass, + IList travelTimes, + float timeToProduceWorker = 20, + float alloyMinedPerSecondByWorker = 1) { + + float totalAlloyHarassment = workerReplacementCost; + + for (var workerProductionIndex = 0; workerProductionIndex < simultaneousProductionFloor; workerProductionIndex++) { totalAlloyHarassment += alloyMinedPerSecondByWorker * timeToProduceWorker * (workerProductionIndex + 1); } - var remainder = (int)(numberOfWorkersLostToHarass % SimultaneousProductionFloor()); - for (var remainderIndex = 0; remainderIndex < remainder; remainderIndex++) - { - totalAlloyHarassment += alloyMinedPerSecondByWorker * timeToProduceWorker * (SimultaneousProductionFloor() + 1); + var remainder = (int)(numberOfWorkersLostToHarass % simultaneousProductionFloor); + for (var remainderIndex = 0; remainderIndex < remainder; remainderIndex++) { + totalAlloyHarassment += alloyMinedPerSecondByWorker * timeToProduceWorker * (simultaneousProductionFloor + 1); } - for (var travelTimeIndex = 0; travelTimeIndex < numberOfWorkersLostToHarass; travelTimeIndex++) - { - var townHallIndex = travelTimeIndex % TravelTimes.Count; - totalAlloyHarassment += alloyMinedPerSecondByWorker * TravelTimes[townHallIndex].Value; + for (var travelTimeIndex = 0; travelTimeIndex < numberOfWorkersLostToHarass; travelTimeIndex++) { + var townHallIndex = travelTimeIndex % travelTimes.Count; + totalAlloyHarassment += alloyMinedPerSecondByWorker * travelTimes[townHallIndex]; } + + return totalAlloyHarassment; } - protected override void OnInitialized() - { + protected override void OnInitialized() { base.OnInitialized(); Calculate(); } - void ValueChanged(float test) - { - Calculate(); - } public List TravelTimes { get; set; } = new() { new TravelTime(0, 0) }; - private void OnTownHallsChanged(ChangeEventArgs obj) - { - numberOfTownHallsExisting = int.Parse(obj.Value!.ToString()!); + private void OnTownHallsChanged(ChangeEventArgs obj) { + NumberOfTownHallsExisting = int.Parse(obj.Value!.ToString()!); - while (TravelTimes.Count > numberOfTownHallsExisting) + while (TravelTimes.Count > NumberOfTownHallsExisting) TravelTimes.Remove(TravelTimes.Last()); - while (TravelTimes.Count < numberOfTownHallsExisting) - TravelTimes.Add(new TravelTime(TravelTimes.Count, 0)); + while (TravelTimes.Count < NumberOfTownHallsExisting) + TravelTimes.Add(new TravelTime(TravelTimes.Count, 10 * (TravelTimes.Count))); Calculate(); } - private void OnTownHallTravelTimeChanged(ChangeEventArgs obj, TravelTime travelTime) - { + private void OnTownHallTravelTimeChanged(ChangeEventArgs obj, TravelTime travelTime) { travelTime.Value = (int)obj.Value!; Calculate(); diff --git a/IGP/Portals/SearchPortal.razor b/IGP/Portals/SearchPortal.razor index e9a969d..2d35fe7 100644 --- a/IGP/Portals/SearchPortal.razor +++ b/IGP/Portals/SearchPortal.razor @@ -1,28 +1,29 @@ @implements IDisposable; -@inject ISearchService SearchService -@inject IJSRuntime JsRuntime +@inject ISearchService searchService +@inject IJSRuntime jsRuntime @code { + private string test = "Q"; + protected override void OnInitialized() { - base.OnInitialized(); - SearchService.Subscribe(OnUpdate); + searchService.Subscribe(OnUpdate); } protected override async Task OnInitializedAsync() { - await SearchService.Load(); - await JsRuntime.InvokeVoidAsync("SetDotnetReference", DotNetObjectReference.Create(this)); + await searchService.Load(); + await jsRuntime.InvokeVoidAsync("SetDotnetReference", DotNetObjectReference.Create(this)); } - void IDisposable.Dispose() + public void Dispose() { - SearchService.Unsubscribe(OnUpdate); + searchService.Unsubscribe(OnUpdate); } void OnUpdate() @@ -35,13 +36,13 @@ { if (code.ToLower().Equals("k") && (ctrlKey || shiftKey || altKey || metaKey)) { - if (SearchService.IsVisible) + if (searchService.IsVisible) { - SearchService.Hide(); + searchService.Hide(); } else { - SearchService.Show(); + searchService.Show(); } } } diff --git a/IGP/wwwroot/generated/AgileTaskModels.json b/IGP/wwwroot/generated/AgileTaskModels.json index 66a9b0a..4bab940 100644 --- a/IGP/wwwroot/generated/AgileTaskModels.json +++ b/IGP/wwwroot/generated/AgileTaskModels.json @@ -1 +1 @@ -[{"Id":1,"AgileSprintModelId":null,"Name":"Support Safari","Description":"Consider other web browsers.","Notes":"Added","Status":"Todo","Priority":"Low","Task":"Feature","OrderPriority":2,"Created":"2022-02-20T00:00:00","Finished":"2022-02-20T00:00:00"},{"Id":2,"AgileSprintModelId":2,"Name":"Filter Patch Notes","Description":"You should be showing people what they really want to see in the patch notes.","Notes":"Added","Status":"Done","Priority":"Blocker","Task":"Feature","OrderPriority":3,"Created":"2022-02-20T00:00:00","Finished":"2022-02-20T00:00:00"},{"Id":3,"AgileSprintModelId":5,"Name":"Consider Pyre","Description":"Add Pyre Income. Make it so you can take Pyre Camps and Pyre Miners","Notes":"Add notes...","Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-02-20T00:00:00","Finished":"2022-04-18T00:00:00"},{"Id":4,"AgileSprintModelId":5,"Name":"Optimizations","Description":"Build Calculator should be usable.","Notes":"Add notes...","Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-02-20T00:00:00","Finished":"2022-04-13T00:00:00"},{"Id":5,"AgileSprintModelId":5,"Name":"Change Attack Timing Interval","Description":"Be able to set attack timing.","Notes":"Add notes...","Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-02-20T00:00:00","Finished":"2022-04-15T00:00:00"},{"Id":6,"AgileSprintModelId":5,"Name":"Add Pyre Spells","Description":"Make Pyre Spells castable and consume Pyre on build order","Notes":"Add notes...","Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-02-20T00:00:00","Finished":"2022-04-18T00:00:00"},{"Id":7,"AgileSprintModelId":null,"Name":"Default builds (Rush Thrones)","Description":"Add a dropdown list of default builds.","Notes":"Add notes...","Status":"Todo","Priority":"Medium","Task":"Feature","OrderPriority":2,"Created":"2022-02-20T00:00:00","Finished":null},{"Id":8,"AgileSprintModelId":null,"Name":"Load older builds","Description":"Be able to load older builds. How are you going to handle auto correct to current patch?","Notes":"Add notes...","Status":"Todo","Priority":"Medium","Task":"Feature","OrderPriority":2,"Created":"2022-02-20T00:00:00","Finished":null},{"Id":9,"AgileSprintModelId":null,"Name":"How to use Build Calculator step by step","Description":"Need docs","Notes":"Add notes...","Status":"Todo","Priority":"Medium","Task":"Feature","OrderPriority":2,"Created":"2022-02-20T00:00:00","Finished":null},{"Id":10,"AgileSprintModelId":null,"Name":"Compare Health and Damage","Description":"Refer to community example spreadsheet.","Notes":"Add notes...","Status":"Todo","Priority":"Medium","Task":"Feature","OrderPriority":2,"Created":"2022-02-20T00:00:00","Finished":null},{"Id":11,"AgileSprintModelId":null,"Name":"Compare Unit\u0027s Damage with it\u0027s own costs","Description":"Refer to community example spreadsheet.","Notes":"Add notes...","Status":"Todo","Priority":"Medium","Task":"Feature","OrderPriority":2,"Created":"2022-02-20T00:00:00","Finished":null},{"Id":12,"AgileSprintModelId":4,"Name":"View one unit stats from a link. Make YAML copy and paste","Description":"Design so people can easily copy and paste data into discord","Notes":"Ended up not using exact Yaml. Button in Database controls Detailed vs Plain display ","Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-02-20T00:00:00","Finished":"2022-04-03T00:00:00"},{"Id":13,"AgileSprintModelId":2,"Name":"Look into SQL","Description":"You really should be using SQL.","Notes":"Agile and Change log pages now use SQL","Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-02-20T00:00:00","Finished":null},{"Id":14,"AgileSprintModelId":1,"Name":"Mobile Menu","Description":"You need a real mobile menu. Viewers don\u0027t scroll below the fold, so no one is going to know what happens when you click a button on phones.","Notes":"Added smaller menus for tablets and phones.","Status":"Done","Priority":"High","Task":"Feature","OrderPriority":3,"Created":"2022-02-18T00:00:00","Finished":"2022-02-19T00:00:00"},{"Id":15,"AgileSprintModelId":2,"Name":"Acropolis Consume Mote","Description":"The Mote is suppose to be consumed when making a Town Hall.","Notes":"Fixed","Status":"Done","Priority":"High","Task":"Bug","OrderPriority":3,"Created":"2022-02-18T00:00:00","Finished":"2022-02-20T00:00:00"},{"Id":16,"AgileSprintModelId":5,"Name":"Multiple Travel Time in Harass Calculator","Description":"Travel time should be based on the amount of bases used. 3 bases is 3 travel times.","Notes":"Add notes...","Status":"Done","Priority":"Low","Task":"Feature","OrderPriority":3,"Created":"2022-02-18T00:00:00","Finished":"2022-04-18T00:00:00"},{"Id":17,"AgileSprintModelId":1,"Name":"Update Database to 0.0.6.8375a","Description":"Xacal tech change, and Hallower damage change. Update Godhead text.","Notes":"Done","Status":"Done","Priority":"None","Task":"Feature","OrderPriority":3,"Created":"2022-02-18T00:00:00","Finished":"2022-02-18T00:00:00"},{"Id":18,"AgileSprintModelId":null,"Name":"Patch History Viewer","Description":"Add an ability to compare patches, to see all nerfs and buffs made between them.","Notes":"Inspired by Zkay\u0027s post on discord, where he details a possible \u0027patch history viewer\u0027 implementation.","Status":"Fun_Idea","Priority":"None","Task":"Feature","OrderPriority":5,"Created":"2022-02-16T00:00:00","Finished":null},{"Id":19,"AgileSprintModelId":1,"Name":"Twitch Page","Description":"Did a ~3 hour test stream, and was personal quite happy with the quality. Make Twitch page, and stream patch, sprint planning and development on Sunday.","Notes":"Page added under General, and named \u0022Streams\u0022.","Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-02-16T00:00:00","Finished":"2022-02-16T00:00:00"},{"Id":20,"AgileSprintModelId":1,"Name":"Finish the database","Description":"Add more descriptions for everything. Reduce any data duplication with ids. Add upgrade connections. Add ability connections. Add passives and passives connections.","Notes":"Good enough for now","Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-02-11T00:00:00","Finished":"2022-02-19T00:00:00"},{"Id":21,"AgileSprintModelId":1,"Name":"Change Log View","Description":"Add a log to view last changes.","Notes":"Added changelog page. Shows Today, X Days Ago, or exact date if patch is over a week old.","Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-02-14T00:00:00","Finished":"2022-02-14T00:00:00"},{"Id":22,"AgileSprintModelId":1,"Name":"Agile View","Description":"Add the agile view.","Notes":"Finished.","Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-02-11T00:00:00","Finished":"2022-02-17T00:00:00"},{"Id":23,"AgileSprintModelId":1,"Name":"GUID for Ids","Description":"Stop using enums for ids, and start using guids. Enums are just too limited, I lose out on component and inheritance design with them. Replace all your enums with guids, rip off the bandaid.","Notes":"Add notes...","Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-02-11T00:00:00","Finished":"2022-02-18T00:00:00"},{"Id":24,"AgileSprintModelId":1,"Name":"Co-op overview","Description":"Write some sort of blog on co-op gameplay so you have something the feels very content-ish. Maybe make it a video.","Notes":"Finished and released early.","Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-02-11T00:00:00","Finished":"2022-02-12T00:00:00"},{"Id":25,"AgileSprintModelId":1,"Name":"Mobile UI","Description":"Make website work on mobile.","Notes":"Should be good. Will test on phone later.","Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-02-15T00:00:00","Finished":"2022-02-18T00:00:00"},{"Id":26,"AgileSprintModelId":1,"Name":"Add Making Of View","Description":"View to reference UI designs. Nicely encourages the pratice of making the UI code a lot cleaner.","Notes":"Good enough for now","Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-02-11T00:00:00","Finished":"2022-02-19T00:00:00"},{"Id":27,"AgileSprintModelId":3,"Name":"Close Nav Menu on Navigation","Description":"Close Nav Menu on Navigation","Notes":null,"Status":"Done","Priority":"High","Task":"Bug","OrderPriority":3,"Created":"2022-03-27T00:00:00","Finished":"2022-03-27T00:00:00"},{"Id":28,"AgileSprintModelId":3,"Name":"Add Passive Descriptions and Passive","Description":"Have to guess on a bunch of passives","Notes":null,"Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-03-27T00:00:00","Finished":"2022-03-31T00:00:00"},{"Id":29,"AgileSprintModelId":3,"Name":"Tooltips that show referenced units","Description":"I should see any referenced unit by hovering over it","Notes":"Links can now go to links which can go to links.","Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-03-27T00:00:00","Finished":"2022-04-01T00:00:00"},{"Id":30,"AgileSprintModelId":null,"Name":"Update Logo for Website","Description":"After color scheme is picked","Notes":null,"Status":"Todo","Priority":"Low","Task":"Feature","OrderPriority":2,"Created":"2022-03-27T00:00:00","Finished":null},{"Id":31,"AgileSprintModelId":3,"Name":"Documentation page","Description":"Add documents on how to maintain website","Notes":"Added start of documents","Status":"Done","Priority":"Low","Task":"Feature","OrderPriority":3,"Created":"2022-03-27T00:00:00","Finished":"2022-04-03T00:00:00"},{"Id":32,"AgileSprintModelId":6,"Name":"Test Automation","Description":"Selenium Tests","Notes":"Start adding IDs to everything","Status":"Todo","Priority":"Low","Task":"Feature","OrderPriority":2,"Created":"2022-03-27T00:00:00","Finished":null},{"Id":33,"AgileSprintModelId":6,"Name":"Unit Test","Description":"Add some unit tests","Notes":null,"Status":"Todo","Priority":"Low","Task":"Feature","OrderPriority":2,"Created":"2022-03-27T00:00:00","Finished":null},{"Id":34,"AgileSprintModelId":4,"Name":"Fully Transfer everything to SQL","Description":"Need to regenerate the database once everthing is fully transfered","Notes":null,"Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-03-27T00:00:00","Finished":"2022-04-09T00:00:00"},{"Id":35,"AgileSprintModelId":3,"Name":"Adding a loading Component","Description":"For JSON loading","Notes":"Added loading component to Agile and Changelog screens","Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-03-27T00:00:00","Finished":"2022-03-27T00:00:00"},{"Id":36,"AgileSprintModelId":3,"Name":"Optimize Loading of Data","Description":"Currently loading non Agile stuff on Agile page","Notes":"Moved SQL database injection to app root","Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-03-27T00:00:00","Finished":"2022-03-27T00:00:00"},{"Id":37,"AgileSprintModelId":3,"Name":"Convert Notes to Markdown","Description":"Using Markdown and generating the Note pages seems like a better solution to SQL or hardcoding data","Notes":null,"Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-03-27T00:00:00","Finished":"2022-04-01T00:00:00"},{"Id":38,"AgileSprintModelId":3,"Name":"Improve Entity Filter Options","Description":"The options I give you is strange, given it filers on Faction type","Notes":null,"Status":"Done","Priority":"High","Task":"Bug","OrderPriority":3,"Created":"2022-04-01T00:00:00","Finished":"2022-04-03T00:00:00"},{"Id":39,"AgileSprintModelId":4,"Name":"Refresh Database Bug","Description":"Database dialog UI isn\u0027t refreshing enough","Notes":null,"Status":"Done","Priority":"High","Task":"Bug","OrderPriority":3,"Created":"2022-04-03T00:00:00","Finished":"2022-04-03T00:00:00"},{"Id":40,"AgileSprintModelId":4,"Name":"Branding Stuff","Description":"Add a schedule, improving branding, etc, ","Notes":"Only improved Twitch overlays","Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-04-03T00:00:00","Finished":"2022-04-10T00:00:00"},{"Id":41,"AgileSprintModelId":4,"Name":"Improve Documents/Notes UI","Description":"Should have a left navigation menu. And prev/next buttons","Notes":"Updated UI. Will added prev/next and breadcrumbs later","Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-04-05T00:00:00","Finished":"2022-04-10T00:00:00"},{"Id":42,"AgileSprintModelId":5,"Name":"Add GitHub links instead of showing code","Description":"For all code examples","Notes":"Add notes...","Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-04-10T00:00:00","Finished":"2022-04-14T00:00:00"},{"Id":43,"AgileSprintModelId":5,"Name":"Research More used RTS calculations","Description":"What other calculators like the Harass Page can be added","Notes":"Do amount of hits to kill, between two units. Maybe time to regen spell uses","Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-04-10T00:00:00","Finished":"2022-04-14T00:00:00"},{"Id":44,"AgileSprintModelId":5,"Name":"Add Error Toasts to Calculator","Description":"Not enough \u0022Ether\u0022","Notes":"Add notes...","Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-04-10T00:00:00","Finished":"2022-04-12T00:00:00"},{"Id":45,"AgileSprintModelId":5,"Name":"Handle Divide by Zero in Harass Calculator","Description":"addDescription","Notes":"addNotes","Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-04-10T00:00:00","Finished":"2022-04-18T00:00:00"},{"Id":46,"AgileSprintModelId":null,"Name":"Harass Calculator first client experience","Description":"Navigate player though the harass calculator steps","Notes":"addNotes","Status":"Todo","Priority":"Medium","Task":"Feature","OrderPriority":2,"Created":"2022-04-10T00:00:00","Finished":null},{"Id":47,"AgileSprintModelId":5,"Name":"Training Queue","Description":"Add training queue times to the build calculator","Notes":"addNotes","Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-04-10T00:00:00","Finished":"2022-04-24T00:00:00"},{"Id":48,"AgileSprintModelId":5,"Name":"Refresh Button for Build Calculator","Description":"Refresh to regenerate timeline and charts","Notes":"Adding a loading screen for charts. Remove redundant renders","Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-04-10T00:00:00","Finished":"2022-04-13T00:00:00"},{"Id":49,"AgileSprintModelId":null,"Name":"Gameplay Warning State Toasts","Description":"\u0022You should upgrade your economy.\u0022 \u0022Your using too much ether, spend alloy\u0022","Notes":"addNotes","Status":"Todo","Priority":"Medium","Task":"Feature","OrderPriority":2,"Created":"2022-04-10T00:00:00","Finished":null},{"Id":50,"AgileSprintModelId":5,"Name":"Make desktop navigation buttons","Description":"It popping up all the time is a tad tedious","Notes":"addNotes","Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-04-10T00:00:00","Finished":"2022-04-12T00:00:00"},{"Id":51,"AgileSprintModelId":5,"Name":"Working Timers","Description":"Toast dismiss timers not making sense. Look into proper Timers","Notes":"addNotes","Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-04-10T00:00:00","Finished":"2022-04-13T00:00:00"},{"Id":52,"AgileSprintModelId":5,"Name":"Clean up Build Calculator code","Description":"Code needs to be easily readable so it can be updated, maintained, and optimized","Notes":"addNotes","Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-04-12T00:00:00","Finished":null},{"Id":53,"AgileSprintModelId":0,"Name":"Armor Types","Description":"Explain Light, Medium and Heavy armor types, and damage works","Notes":"addNotes","Status":"Todo","Priority":"Medium","Task":"Document","OrderPriority":2,"Created":"2022-04-13T00:00:00","Finished":null},{"Id":54,"AgileSprintModelId":0,"Name":"Economy Overview","Description":"How long it takes bases to mine out. How good natruals area","Notes":"addNotes","Status":"Todo","Priority":"Medium","Task":"Document","OrderPriority":2,"Created":"2022-04-13T00:00:00","Finished":null},{"Id":55,"AgileSprintModelId":0,"Name":"Timing and Scouting","Description":"Attacking and reacting to what the enemy is doing","Notes":"addNotes","Status":"Todo","Priority":"Medium","Task":"Document","OrderPriority":2,"Created":"2022-04-13T00:00:00","Finished":null},{"Id":56,"AgileSprintModelId":0,"Name":"Families, Factions, and Immortal Vanguards","Description":"How factions could be viewed.","Notes":"addNotes","Status":"Todo","Priority":"Medium","Task":"Document","OrderPriority":2,"Created":"2022-04-13T00:00:00","Finished":null},{"Id":57,"AgileSprintModelId":0,"Name":"Immortals Spells and Pyre","Description":"Using your Immortal","Notes":"addNotes","Status":"Todo","Priority":"Medium","Task":"Document","OrderPriority":2,"Created":"2022-04-13T00:00:00","Finished":null},{"Id":58,"AgileSprintModelId":6,"Name":"Organize Sprint Order","Description":"Sprints should be ordered as, current sprint, previous sprint, backlog, easy tasks, future sprints, old sprints","Notes":"addNotes","Status":"Todo","Priority":"Medium","Task":"Feature","OrderPriority":2,"Created":"2022-04-13T00:00:00","Finished":null},{"Id":59,"AgileSprintModelId":null,"Name":"Better Sorting Algorithms ","Description":"Be smarted with searching through and sorting lists","Notes":"addNotes","Status":"Todo","Priority":"Medium","Task":"Feature","OrderPriority":2,"Created":"2022-04-13T00:00:00","Finished":null},{"Id":60,"AgileSprintModelId":6,"Name":"Settings Section","Description":"Add a settings area, for permission and cookie related content","Notes":"addNotes","Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-04-14T00:00:00","Finished":"2022-04-24T00:00:00"},{"Id":61,"AgileSprintModelId":6,"Name":"Analytics","Description":"Track client going to each page.","Notes":"addNotes","Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-04-14T00:00:00","Finished":"2022-04-25T00:00:00"},{"Id":62,"AgileSprintModelId":6,"Name":"Cookies","Description":"Cookies to remember a the client permission options ","Notes":"Using local storage instead of cookies.","Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-04-14T00:00:00","Finished":"2022-04-24T00:00:00"},{"Id":63,"AgileSprintModelId":6,"Name":"Permission Controls Page","Description":"Allow clients to enable cookies, analytics, and perhaps make things more granular. ","Notes":"addNotes","Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-04-14T00:00:00","Finished":"2022-04-24T00:00:00"},{"Id":64,"AgileSprintModelId":6,"Name":"Defaults Page","Description":"Let clients set a cookie for Plain/Detailed view. Perhaps default Immortal. Etc.","Notes":"Calling it Storage Page","Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-04-14T00:00:00","Finished":"2022-04-24T00:00:00"},{"Id":65,"AgileSprintModelId":null,"Name":"Analytics Page","Description":"Let\u0027s have a page that shows the analytics collected during a client\u0027s session","Notes":"addNotes","Status":"Todo","Priority":"Medium","Task":"Feature","OrderPriority":2,"Created":"2022-04-14T00:00:00","Finished":null},{"Id":66,"AgileSprintModelId":5,"Name":"Economy Comparison","Description":"Compare different economies. Make this a page under resources","Notes":"addNotes","Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-04-15T00:00:00","Finished":"2022-04-17T00:00:00"},{"Id":67,"AgileSprintModelId":5,"Name":"[Ctrl \u002B K] Search feature","Description":"WIP. Needs polish","Notes":"addNotes","Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-04-16T00:00:00","Finished":"2022-04-16T00:00:00"},{"Id":68,"AgileSprintModelId":6,"Name":"Lighthouse Score","Description":"Lighthouse score is awful. Try to get to the green","Notes":"addNotes","Status":"Todo","Priority":"Medium","Task":"Feature","OrderPriority":2,"Created":"2022-04-16T00:00:00","Finished":null},{"Id":69,"AgileSprintModelId":6,"Name":"SEO","Description":"People might be trying to google this website instead of bookmarking it. Make sure its googleable","Notes":"addNotes","Status":"Todo","Priority":"Medium","Task":"Feature","OrderPriority":2,"Created":"2022-04-17T00:00:00","Finished":null},{"Id":70,"AgileSprintModelId":6,"Name":"AttacksPerSecond Format Setting","Description":"Make SunSpear\u0027s DPS formatting the default, and allow people to turn it off in settings, for people that don\u0027t like the SBA/APS swapping","Notes":"addNotes","Status":"Todo","Priority":"Medium","Task":"Feature","OrderPriority":2,"Created":"2022-04-17T00:00:00","Finished":null},{"Id":71,"AgileSprintModelId":5,"Name":"Fix Cancel Button Giving Money","Description":"Things can be built faster if you cancel","Notes":"addNotes","Status":"Done","Priority":"High","Task":"Bug","OrderPriority":3,"Created":"2022-04-17T00:00:00","Finished":"2022-04-18T00:00:00"},{"Id":72,"AgileSprintModelId":5,"Name":"Calculations Change Answers Over Time","Description":"Obviously a bug in the calculation logic","Notes":"addNotes","Status":"Done","Priority":"High","Task":"Bug","OrderPriority":3,"Created":"2022-04-17T00:00:00","Finished":"2022-04-18T00:00:00"}] \ No newline at end of file +[{"Id":1,"AgileSprintModelId":null,"Name":"Support Safari","Description":"Consider other web browsers.","Notes":"Added","Status":"Todo","Priority":"Low","Task":"Feature","OrderPriority":2,"Created":"2022-02-20T00:00:00","Finished":"2022-02-20T00:00:00"},{"Id":2,"AgileSprintModelId":2,"Name":"Filter Patch Notes","Description":"You should be showing people what they really want to see in the patch notes.","Notes":"Added","Status":"Done","Priority":"Blocker","Task":"Feature","OrderPriority":3,"Created":"2022-02-20T00:00:00","Finished":"2022-02-20T00:00:00"},{"Id":3,"AgileSprintModelId":5,"Name":"Consider Pyre","Description":"Add Pyre Income. Make it so you can take Pyre Camps and Pyre Miners","Notes":"Add notes...","Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-02-20T00:00:00","Finished":"2022-04-18T00:00:00"},{"Id":4,"AgileSprintModelId":5,"Name":"Optimizations","Description":"Build Calculator should be usable.","Notes":"Add notes...","Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-02-20T00:00:00","Finished":"2022-04-13T00:00:00"},{"Id":5,"AgileSprintModelId":5,"Name":"Change Attack Timing Interval","Description":"Be able to set attack timing.","Notes":"Add notes...","Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-02-20T00:00:00","Finished":"2022-04-15T00:00:00"},{"Id":6,"AgileSprintModelId":5,"Name":"Add Pyre Spells","Description":"Make Pyre Spells castable and consume Pyre on build order","Notes":"Add notes...","Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-02-20T00:00:00","Finished":"2022-04-18T00:00:00"},{"Id":7,"AgileSprintModelId":null,"Name":"Default builds (Rush Thrones)","Description":"Add a dropdown list of default builds.","Notes":"Add notes...","Status":"Todo","Priority":"Medium","Task":"Feature","OrderPriority":2,"Created":"2022-02-20T00:00:00","Finished":null},{"Id":8,"AgileSprintModelId":null,"Name":"Load older builds","Description":"Be able to load older builds. How are you going to handle auto correct to current patch?","Notes":"Add notes...","Status":"Todo","Priority":"Medium","Task":"Feature","OrderPriority":2,"Created":"2022-02-20T00:00:00","Finished":null},{"Id":9,"AgileSprintModelId":null,"Name":"How to use Build Calculator step by step","Description":"Need docs","Notes":"Add notes...","Status":"Todo","Priority":"Medium","Task":"Feature","OrderPriority":2,"Created":"2022-02-20T00:00:00","Finished":null},{"Id":10,"AgileSprintModelId":null,"Name":"Compare Health and Damage","Description":"Refer to community example spreadsheet.","Notes":"Add notes...","Status":"Todo","Priority":"Medium","Task":"Feature","OrderPriority":2,"Created":"2022-02-20T00:00:00","Finished":null},{"Id":11,"AgileSprintModelId":null,"Name":"Compare Unit\u0027s Damage with it\u0027s own costs","Description":"Refer to community example spreadsheet.","Notes":"Add notes...","Status":"Todo","Priority":"Medium","Task":"Feature","OrderPriority":2,"Created":"2022-02-20T00:00:00","Finished":null},{"Id":12,"AgileSprintModelId":4,"Name":"View one unit stats from a link. Make YAML copy and paste","Description":"Design so people can easily copy and paste data into discord","Notes":"Ended up not using exact Yaml. Button in Database controls Detailed vs Plain display ","Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-02-20T00:00:00","Finished":"2022-04-03T00:00:00"},{"Id":13,"AgileSprintModelId":2,"Name":"Look into SQL","Description":"You really should be using SQL.","Notes":"Agile and Change log pages now use SQL","Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-02-20T00:00:00","Finished":null},{"Id":14,"AgileSprintModelId":1,"Name":"Mobile Menu","Description":"You need a real mobile menu. Viewers don\u0027t scroll below the fold, so no one is going to know what happens when you click a button on phones.","Notes":"Added smaller menus for tablets and phones.","Status":"Done","Priority":"High","Task":"Feature","OrderPriority":3,"Created":"2022-02-18T00:00:00","Finished":"2022-02-19T00:00:00"},{"Id":15,"AgileSprintModelId":2,"Name":"Acropolis Consume Mote","Description":"The Mote is suppose to be consumed when making a Town Hall.","Notes":"Fixed","Status":"Done","Priority":"High","Task":"Bug","OrderPriority":3,"Created":"2022-02-18T00:00:00","Finished":"2022-02-20T00:00:00"},{"Id":16,"AgileSprintModelId":5,"Name":"Multiple Travel Time in Harass Calculator","Description":"Travel time should be based on the amount of bases used. 3 bases is 3 travel times.","Notes":"Add notes...","Status":"Done","Priority":"Low","Task":"Feature","OrderPriority":3,"Created":"2022-02-18T00:00:00","Finished":"2022-04-18T00:00:00"},{"Id":17,"AgileSprintModelId":1,"Name":"Update Database to 0.0.6.8375a","Description":"Xacal tech change, and Hallower damage change. Update Godhead text.","Notes":"Done","Status":"Done","Priority":"None","Task":"Feature","OrderPriority":3,"Created":"2022-02-18T00:00:00","Finished":"2022-02-18T00:00:00"},{"Id":18,"AgileSprintModelId":null,"Name":"Patch History Viewer","Description":"Add an ability to compare patches, to see all nerfs and buffs made between them.","Notes":"Inspired by Zkay\u0027s post on discord, where he details a possible \u0027patch history viewer\u0027 implementation.","Status":"Fun_Idea","Priority":"None","Task":"Feature","OrderPriority":5,"Created":"2022-02-16T00:00:00","Finished":null},{"Id":19,"AgileSprintModelId":1,"Name":"Twitch Page","Description":"Did a ~3 hour test stream, and was personal quite happy with the quality. Make Twitch page, and stream patch, sprint planning and development on Sunday.","Notes":"Page added under General, and named \u0022Streams\u0022.","Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-02-16T00:00:00","Finished":"2022-02-16T00:00:00"},{"Id":20,"AgileSprintModelId":1,"Name":"Finish the database","Description":"Add more descriptions for everything. Reduce any data duplication with ids. Add upgrade connections. Add ability connections. Add passives and passives connections.","Notes":"Good enough for now","Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-02-11T00:00:00","Finished":"2022-02-19T00:00:00"},{"Id":21,"AgileSprintModelId":1,"Name":"Change Log View","Description":"Add a log to view last changes.","Notes":"Added changelog page. Shows Today, X Days Ago, or exact date if patch is over a week old.","Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-02-14T00:00:00","Finished":"2022-02-14T00:00:00"},{"Id":22,"AgileSprintModelId":1,"Name":"Agile View","Description":"Add the agile view.","Notes":"Finished.","Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-02-11T00:00:00","Finished":"2022-02-17T00:00:00"},{"Id":23,"AgileSprintModelId":1,"Name":"GUID for Ids","Description":"Stop using enums for ids, and start using guids. Enums are just too limited, I lose out on component and inheritance design with them. Replace all your enums with guids, rip off the bandaid.","Notes":"Add notes...","Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-02-11T00:00:00","Finished":"2022-02-18T00:00:00"},{"Id":24,"AgileSprintModelId":1,"Name":"Co-op overview","Description":"Write some sort of blog on co-op gameplay so you have something the feels very content-ish. Maybe make it a video.","Notes":"Finished and released early.","Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-02-11T00:00:00","Finished":"2022-02-12T00:00:00"},{"Id":25,"AgileSprintModelId":1,"Name":"Mobile UI","Description":"Make website work on mobile.","Notes":"Should be good. Will test on phone later.","Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-02-15T00:00:00","Finished":"2022-02-18T00:00:00"},{"Id":26,"AgileSprintModelId":1,"Name":"Add Making Of View","Description":"View to reference UI designs. Nicely encourages the pratice of making the UI code a lot cleaner.","Notes":"Good enough for now","Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-02-11T00:00:00","Finished":"2022-02-19T00:00:00"},{"Id":27,"AgileSprintModelId":3,"Name":"Close Nav Menu on Navigation","Description":"Close Nav Menu on Navigation","Notes":null,"Status":"Done","Priority":"High","Task":"Bug","OrderPriority":3,"Created":"2022-03-27T00:00:00","Finished":"2022-03-27T00:00:00"},{"Id":28,"AgileSprintModelId":3,"Name":"Add Passive Descriptions and Passive","Description":"Have to guess on a bunch of passives","Notes":null,"Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-03-27T00:00:00","Finished":"2022-03-31T00:00:00"},{"Id":29,"AgileSprintModelId":3,"Name":"Tooltips that show referenced units","Description":"I should see any referenced unit by hovering over it","Notes":"Links can now go to links which can go to links.","Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-03-27T00:00:00","Finished":"2022-04-01T00:00:00"},{"Id":30,"AgileSprintModelId":null,"Name":"Update Logo for Website","Description":"After color scheme is picked","Notes":null,"Status":"Todo","Priority":"Low","Task":"Feature","OrderPriority":2,"Created":"2022-03-27T00:00:00","Finished":null},{"Id":31,"AgileSprintModelId":3,"Name":"Documentation page","Description":"Add documents on how to maintain website","Notes":"Added start of documents","Status":"Done","Priority":"Low","Task":"Feature","OrderPriority":3,"Created":"2022-03-27T00:00:00","Finished":"2022-04-03T00:00:00"},{"Id":32,"AgileSprintModelId":6,"Name":"Test Automation","Description":"Selenium Tests","Notes":"Start adding IDs to everything","Status":"Todo","Priority":"Low","Task":"Feature","OrderPriority":2,"Created":"2022-03-27T00:00:00","Finished":null},{"Id":33,"AgileSprintModelId":6,"Name":"Unit Test","Description":"Add some unit tests","Notes":null,"Status":"Todo","Priority":"Low","Task":"Feature","OrderPriority":2,"Created":"2022-03-27T00:00:00","Finished":null},{"Id":34,"AgileSprintModelId":4,"Name":"Fully Transfer everything to SQL","Description":"Need to regenerate the database once everthing is fully transfered","Notes":null,"Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-03-27T00:00:00","Finished":"2022-04-09T00:00:00"},{"Id":35,"AgileSprintModelId":3,"Name":"Adding a loading Component","Description":"For JSON loading","Notes":"Added loading component to Agile and Changelog screens","Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-03-27T00:00:00","Finished":"2022-03-27T00:00:00"},{"Id":36,"AgileSprintModelId":3,"Name":"Optimize Loading of Data","Description":"Currently loading non Agile stuff on Agile page","Notes":"Moved SQL database injection to app root","Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-03-27T00:00:00","Finished":"2022-03-27T00:00:00"},{"Id":37,"AgileSprintModelId":3,"Name":"Convert Notes to Markdown","Description":"Using Markdown and generating the Note pages seems like a better solution to SQL or hardcoding data","Notes":null,"Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-03-27T00:00:00","Finished":"2022-04-01T00:00:00"},{"Id":38,"AgileSprintModelId":3,"Name":"Improve Entity Filter Options","Description":"The options I give you is strange, given it filers on Faction type","Notes":null,"Status":"Done","Priority":"High","Task":"Bug","OrderPriority":3,"Created":"2022-04-01T00:00:00","Finished":"2022-04-03T00:00:00"},{"Id":39,"AgileSprintModelId":4,"Name":"Refresh Database Bug","Description":"Database dialog UI isn\u0027t refreshing enough","Notes":null,"Status":"Done","Priority":"High","Task":"Bug","OrderPriority":3,"Created":"2022-04-03T00:00:00","Finished":"2022-04-03T00:00:00"},{"Id":40,"AgileSprintModelId":4,"Name":"Branding Stuff","Description":"Add a schedule, improving branding, etc, ","Notes":"Only improved Twitch overlays","Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-04-03T00:00:00","Finished":"2022-04-10T00:00:00"},{"Id":41,"AgileSprintModelId":4,"Name":"Improve Documents/Notes UI","Description":"Should have a left navigation menu. And prev/next buttons","Notes":"Updated UI. Will added prev/next and breadcrumbs later","Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-04-05T00:00:00","Finished":"2022-04-10T00:00:00"},{"Id":42,"AgileSprintModelId":5,"Name":"Add GitHub links instead of showing code","Description":"For all code examples","Notes":"Add notes...","Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-04-10T00:00:00","Finished":"2022-04-14T00:00:00"},{"Id":43,"AgileSprintModelId":5,"Name":"Research More used RTS calculations","Description":"What other calculators like the Harass Page can be added","Notes":"Do amount of hits to kill, between two units. Maybe time to regen spell uses","Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-04-10T00:00:00","Finished":"2022-04-14T00:00:00"},{"Id":44,"AgileSprintModelId":5,"Name":"Add Error Toasts to Calculator","Description":"Not enough \u0022Ether\u0022","Notes":"Add notes...","Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-04-10T00:00:00","Finished":"2022-04-12T00:00:00"},{"Id":45,"AgileSprintModelId":5,"Name":"Handle Divide by Zero in Harass Calculator","Description":"addDescription","Notes":"addNotes","Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-04-10T00:00:00","Finished":"2022-04-18T00:00:00"},{"Id":46,"AgileSprintModelId":null,"Name":"Harass Calculator first client experience","Description":"Navigate player though the harass calculator steps","Notes":"addNotes","Status":"Todo","Priority":"Medium","Task":"Feature","OrderPriority":2,"Created":"2022-04-10T00:00:00","Finished":null},{"Id":47,"AgileSprintModelId":5,"Name":"Training Queue","Description":"Add training queue times to the build calculator","Notes":"addNotes","Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-04-10T00:00:00","Finished":"2022-04-24T00:00:00"},{"Id":48,"AgileSprintModelId":5,"Name":"Refresh Button for Build Calculator","Description":"Refresh to regenerate timeline and charts","Notes":"Adding a loading screen for charts. Remove redundant renders","Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-04-10T00:00:00","Finished":"2022-04-13T00:00:00"},{"Id":49,"AgileSprintModelId":null,"Name":"Gameplay Warning State Toasts","Description":"\u0022You should upgrade your economy.\u0022 \u0022Your using too much ether, spend alloy\u0022","Notes":"addNotes","Status":"Todo","Priority":"Medium","Task":"Feature","OrderPriority":2,"Created":"2022-04-10T00:00:00","Finished":null},{"Id":50,"AgileSprintModelId":5,"Name":"Make desktop navigation buttons","Description":"It popping up all the time is a tad tedious","Notes":"addNotes","Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-04-10T00:00:00","Finished":"2022-04-12T00:00:00"},{"Id":51,"AgileSprintModelId":5,"Name":"Working Timers","Description":"Toast dismiss timers not making sense. Look into proper Timers","Notes":"addNotes","Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-04-10T00:00:00","Finished":"2022-04-13T00:00:00"},{"Id":52,"AgileSprintModelId":5,"Name":"Clean up Build Calculator code","Description":"Code needs to be easily readable so it can be updated, maintained, and optimized","Notes":"addNotes","Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-04-12T00:00:00","Finished":null},{"Id":53,"AgileSprintModelId":0,"Name":"Armor Types","Description":"Explain Light, Medium and Heavy armor types, and damage works","Notes":"addNotes","Status":"Todo","Priority":"Medium","Task":"Document","OrderPriority":2,"Created":"2022-04-13T00:00:00","Finished":null},{"Id":54,"AgileSprintModelId":0,"Name":"Economy Overview","Description":"How long it takes bases to mine out. How good natruals area","Notes":"addNotes","Status":"Todo","Priority":"Medium","Task":"Document","OrderPriority":2,"Created":"2022-04-13T00:00:00","Finished":null},{"Id":55,"AgileSprintModelId":0,"Name":"Timing and Scouting","Description":"Attacking and reacting to what the enemy is doing","Notes":"addNotes","Status":"Todo","Priority":"Medium","Task":"Document","OrderPriority":2,"Created":"2022-04-13T00:00:00","Finished":null},{"Id":56,"AgileSprintModelId":0,"Name":"Families, Factions, and Immortal Vanguards","Description":"How factions could be viewed.","Notes":"addNotes","Status":"Todo","Priority":"Medium","Task":"Document","OrderPriority":2,"Created":"2022-04-13T00:00:00","Finished":null},{"Id":57,"AgileSprintModelId":0,"Name":"Immortals Spells and Pyre","Description":"Using your Immortal","Notes":"addNotes","Status":"Todo","Priority":"Medium","Task":"Document","OrderPriority":2,"Created":"2022-04-13T00:00:00","Finished":null},{"Id":58,"AgileSprintModelId":6,"Name":"Organize Sprint Order","Description":"Sprints should be ordered as, current sprint, previous sprint, backlog, easy tasks, future sprints, old sprints","Notes":"addNotes","Status":"Todo","Priority":"Medium","Task":"Feature","OrderPriority":2,"Created":"2022-04-13T00:00:00","Finished":null},{"Id":59,"AgileSprintModelId":null,"Name":"Better Sorting Algorithms ","Description":"Be smarted with searching through and sorting lists","Notes":"addNotes","Status":"Todo","Priority":"Medium","Task":"Feature","OrderPriority":2,"Created":"2022-04-13T00:00:00","Finished":null},{"Id":60,"AgileSprintModelId":6,"Name":"Settings Section","Description":"Add a settings area, for permission and cookie related content","Notes":"addNotes","Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-04-14T00:00:00","Finished":"2022-04-24T00:00:00"},{"Id":61,"AgileSprintModelId":6,"Name":"Analytics","Description":"Track client going to each page.","Notes":"addNotes","Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-04-14T00:00:00","Finished":"2022-04-25T00:00:00"},{"Id":62,"AgileSprintModelId":6,"Name":"Cookies","Description":"Cookies to remember a the client permission options ","Notes":"Using local storage instead of cookies.","Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-04-14T00:00:00","Finished":"2022-04-24T00:00:00"},{"Id":63,"AgileSprintModelId":6,"Name":"Permission Controls Page","Description":"Allow clients to enable cookies, analytics, and perhaps make things more granular. ","Notes":"addNotes","Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-04-14T00:00:00","Finished":"2022-04-24T00:00:00"},{"Id":64,"AgileSprintModelId":6,"Name":"Defaults Page","Description":"Let clients set a cookie for Plain/Detailed view. Perhaps default Immortal. Etc.","Notes":"Calling it Storage Page","Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-04-14T00:00:00","Finished":"2022-04-24T00:00:00"},{"Id":65,"AgileSprintModelId":null,"Name":"Analytics Page","Description":"Let\u0027s have a page that shows the analytics collected during a client\u0027s session","Notes":"addNotes","Status":"Todo","Priority":"Medium","Task":"Feature","OrderPriority":2,"Created":"2022-04-14T00:00:00","Finished":null},{"Id":66,"AgileSprintModelId":5,"Name":"Economy Comparison","Description":"Compare different economies. Make this a page under resources","Notes":"addNotes","Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-04-15T00:00:00","Finished":"2022-04-17T00:00:00"},{"Id":67,"AgileSprintModelId":5,"Name":"[Ctrl \u002B K] Search feature","Description":"WIP. Needs polish","Notes":"addNotes","Status":"Done","Priority":"Medium","Task":"Feature","OrderPriority":3,"Created":"2022-04-16T00:00:00","Finished":"2022-04-16T00:00:00"},{"Id":68,"AgileSprintModelId":6,"Name":"Lighthouse Score","Description":"Lighthouse score is awful. Try to get to the green","Notes":"addNotes","Status":"Todo","Priority":"Medium","Task":"Feature","OrderPriority":2,"Created":"2022-04-16T00:00:00","Finished":null},{"Id":69,"AgileSprintModelId":6,"Name":"SEO","Description":"People might be trying to google this website instead of bookmarking it. Make sure its googleable","Notes":"addNotes","Status":"Todo","Priority":"Medium","Task":"Feature","OrderPriority":2,"Created":"2022-04-17T00:00:00","Finished":null},{"Id":70,"AgileSprintModelId":6,"Name":"AttacksPerSecond Format Setting","Description":"Make SunSpear\u0027s DPS formatting the default, and allow people to turn it off in settings, for people that don\u0027t like the SBA/APS swapping","Notes":"addNotes","Status":"Todo","Priority":"Medium","Task":"Feature","OrderPriority":2,"Created":"2022-04-17T00:00:00","Finished":null},{"Id":71,"AgileSprintModelId":5,"Name":"Fix Cancel Button Giving Money","Description":"Things can be built faster if you cancel","Notes":"addNotes","Status":"Done","Priority":"High","Task":"Bug","OrderPriority":3,"Created":"2022-04-17T00:00:00","Finished":"2022-04-18T00:00:00"},{"Id":72,"AgileSprintModelId":5,"Name":"Calculations Change Answers Over Time","Description":"Obviously a bug in the calculation logic","Notes":"addNotes","Status":"Done","Priority":"High","Task":"Bug","OrderPriority":3,"Created":"2022-04-17T00:00:00","Finished":"2022-04-18T00:00:00"},{"Id":73,"AgileSprintModelId":6,"Name":"Draft Mode","Description":"Add in the Draft cost changes. For example Zephyr costs -10 of total","Notes":"addNotes","Status":"Todo","Priority":"Medium","Task":"Feature","OrderPriority":2,"Created":"2022-04-25T00:00:00","Finished":null}] \ No newline at end of file diff --git a/Model/TravelTime.cs b/Model/TravelTime.cs index ceea696..f10e6ca 100644 --- a/Model/TravelTime.cs +++ b/Model/TravelTime.cs @@ -2,12 +2,12 @@ public class TravelTime { - public TravelTime(int index, int value) + public TravelTime(int index, float value) { Index = index; Value = value; } public int Index { get; set; } - public int Value { get; set; } + public float Value { get; set; } } \ No newline at end of file diff --git a/TestAutomation/Pages/BasePage.cs b/TestAutomation/Pages/BasePage.cs new file mode 100644 index 0000000..5f60e8f --- /dev/null +++ b/TestAutomation/Pages/BasePage.cs @@ -0,0 +1,13 @@ +using OpenQA.Selenium; + +namespace TestAutomation.Pages; + +public class BasePage { + + public Website website; + + public BasePage(Website website) { + this.website = website; + } + +} \ No newline at end of file diff --git a/TestAutomation/Pages/HarassCalculatorPage.cs b/TestAutomation/Pages/HarassCalculatorPage.cs new file mode 100644 index 0000000..9284558 --- /dev/null +++ b/TestAutomation/Pages/HarassCalculatorPage.cs @@ -0,0 +1,70 @@ +namespace TestAutomation.Pages; + +public class HarassCalculatorPage : BasePage { + private IWebElement NumberOfWorkersLostToHarass => website.Find("numberOfWorkersLostToHarass"); + private IWebElement NumberOfTownHallsExisting => website.Find("numberOfTownHallsExisting"); + private IList OnTownHallTravelTimes => website.FindChildren("numberOfTownHallTravelTimes", "input"); + private int TotalAlloyHarassment => website.FindInt("totalAlloyHarassment"); + private int WorkerReplacementCost => website.FindInt("workerReplacementCost"); + private int DelayedMiningCost => website.FindInt("delayedMiningCost"); + private int AverageTravelTime => website.FindInt("getAverageTravelTime"); + + private int ExampleTotalAlloyLoss => website.FindInt("exampleTotalAlloyLoss"); + private int ExampleWorkerCost => website.FindInt("exampleWorkerCost"); + private int ExampleMiningTimeCost => website.FindInt("exampleMiningTimeCost"); + private int ExampleTotalAlloyLossDifference => website.FindInt("exampleTotalAlloyLossDifference"); + private int ExampleTotalAlloyLossAccurate => website.FindInt("exampleTotalAlloyLossAccurate"); + private int ExampleTotalAlloyLossAccurateDifference => website.FindInt("exampleTotalAlloyLossAccurateDifference"); + + public HarassCalculatorPage(Website website) : base(website) { } + + public HarassCalculatorPage SetWorkersLostToHarass(int number) { + website.EnterInput(NumberOfWorkersLostToHarass, number); + return this; + } + + public HarassCalculatorPage SetNumberOfTownHallsExisting(int number) { + website.EnterInput(NumberOfTownHallsExisting, number); + return this; + } + + public HarassCalculatorPage SetTownHallTravelTime(int forTownHall, int number) { + website.EnterInput(OnTownHallTravelTimes[forTownHall], number); + return this; + } + + public HarassCalculatorPage GetTotalAlloyHarassment(out int result) { + result = TotalAlloyHarassment; + return this; + } + + + public HarassCalculatorPage GetExampleTotalAlloyLoss(out int result) { + result = ExampleTotalAlloyLoss; + return this; + } + + public HarassCalculatorPage GetExampleWorkerCost(out int result) { + result = ExampleWorkerCost; + return this; + } + + public HarassCalculatorPage GetExampleMiningTimeCost(out int result) { + result = ExampleMiningTimeCost; + return this; + } + public HarassCalculatorPage GetExampleTotalAlloyLossAccurate(out int result) { + result = ExampleTotalAlloyLossAccurate; + return this; + } + public HarassCalculatorPage GetExampleTotalAlloyLossDifference(out int result) { + result = ExampleTotalAlloyLossDifference; + return this; + } + + public HarassCalculatorPage GetExampleTotalAlloyLossAccurateDifference(out int result) { + result = ExampleTotalAlloyLossAccurateDifference; + return this; + } + +} \ No newline at end of file diff --git a/TestAutomation/TestAutomation.csproj b/TestAutomation/TestAutomation.csproj new file mode 100644 index 0000000..6565be7 --- /dev/null +++ b/TestAutomation/TestAutomation.csproj @@ -0,0 +1,24 @@ + + + + net7.0 + enable + enable + + false + + + + + + + + + + + + + + + + diff --git a/TestAutomation/UnitTest1.cs b/TestAutomation/UnitTest1.cs new file mode 100644 index 0000000..45c8c98 --- /dev/null +++ b/TestAutomation/UnitTest1.cs @@ -0,0 +1,120 @@ + +namespace TestAutomation; + +public class Tests +{ + private IWebDriver _webDriver = default!; + + + private readonly string localhost = "https://localhost:7234"; + private readonly string develop = "https://calm-mud-04916b210.1.azurestaticapps.net/"; + + + private Website Website { get; } + + public Tests() { + //var options = new FirefoxOptions(); + var options = new ChromeOptions(); + + options.AcceptInsecureCertificates = true; + +#if !DEBUG + options.AddArgument("--headless"); +#endif + + options.AddArgument("--start-maximized"); + + //_webDriver = new FirefoxDriver(options); + _webDriver = new ChromeDriver(options); + + Website = new Website(_webDriver); + } + + [OneTimeSetUp] + public void Setup() + { + _webDriver.Navigate().GoToUrl(localhost); + _webDriver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(15); + } + + [OneTimeTearDown] + public void TearDown() + { + _webDriver.Quit(); + } + + [Test] + public void HarassCalculator() + { + _webDriver.Navigate().GoToUrl(localhost + "/harass-calculator"); + + int expectedTotalAlloyHarassment = 240; + + Website.HarassCalculatorPage + .SetWorkersLostToHarass(3) + .SetNumberOfTownHallsExisting(2) + .SetTownHallTravelTime(0, 30) + .GetTotalAlloyHarassment(out var foundTotalAlloyHarassment); + + Assert.True(expectedTotalAlloyHarassment.Equals(foundTotalAlloyHarassment), + $"expectTotalAlloyHarassment of {expectedTotalAlloyHarassment} " + + "does not equal " + + $"foundTotalAlloyHarassment of {foundTotalAlloyHarassment} "); + + } + + [Test] + public void HarassCalculatorInformation() + { + _webDriver.Navigate().GoToUrl(localhost + "/harass-calculator"); + + int expectedExampleTotalAlloyLoss = 720; + int expectedExampleWorkerCost = 300; + int expectedExampleMiningTimeCost = 420; + int expectedExampleTotalAlloyLossDifference = 300; + int expectedExampleTotalAlloyLossAccurate = 450; + int expectedExampleTotalAlloyLossAccurateDifference = 270; + + Website.HarassCalculatorPage + .GetExampleTotalAlloyLoss(out var foundTotalAlloyLoss) + .GetExampleWorkerCost(out var foundExampleWorkerCost) + .GetExampleMiningTimeCost(out var foundExampleMiningTimeCost) + .GetExampleTotalAlloyLossAccurate(out var foundExampleTotalAlloyLossAccurate) + .GetExampleTotalAlloyLossDifference(out var foundGetExampleTotalAlloyLossDifference) + .GetExampleTotalAlloyLossAccurateDifference(out var foundExampleTotalAlloyLossAccurateDifference); + + Assert.True(expectedExampleTotalAlloyLoss.Equals(foundTotalAlloyLoss), + $"expectedExampleTotalAlloyLoss of {expectedExampleTotalAlloyLoss} " + + "does not equal " + + $"foundTotalAlloyLoss of {foundTotalAlloyLoss} "); + + Assert.True(expectedExampleWorkerCost.Equals(foundExampleWorkerCost), + $"expectedExampleWorkerCost of {expectedExampleWorkerCost} " + + "does not equal " + + $"foundExampleWorkerCost of {foundExampleWorkerCost} "); + + + Assert.True(expectedExampleMiningTimeCost.Equals(foundExampleMiningTimeCost), + $"expectedExampleMiningTimeCost of {expectedExampleMiningTimeCost} " + + "does not equal " + + $"foundExampleMiningTimeCost of {foundExampleMiningTimeCost} "); + + + Assert.True(expectedExampleTotalAlloyLossAccurate.Equals(foundExampleTotalAlloyLossAccurate), + $"expectedExampleTotalAlloyLossAccurate of {expectedExampleTotalAlloyLossAccurate} " + + "does not equal " + + $"foundExampleTotalAlloyLossAccurate of {foundExampleTotalAlloyLossAccurate} "); + + + Assert.True(expectedExampleTotalAlloyLossDifference.Equals(foundGetExampleTotalAlloyLossDifference), + $"expectedExampleTotalAlloyLossDifference of {expectedExampleTotalAlloyLossDifference} " + + "does not equal " + + $"foundGetExampleTotalAlloyLossDifference of {foundGetExampleTotalAlloyLossDifference} "); + + + Assert.True(expectedExampleTotalAlloyLossAccurateDifference.Equals(foundExampleTotalAlloyLossAccurateDifference), + $"expectedExampleTotalAlloyLossAccurateDifference of {expectedExampleTotalAlloyLossAccurateDifference} " + + "does not equal " + + $"foundExampleTotalAlloyLossAccurateDifference of {foundExampleTotalAlloyLossAccurateDifference} "); + } +} \ No newline at end of file diff --git a/TestAutomation/Usings.cs b/TestAutomation/Usings.cs new file mode 100644 index 0000000..661f6bd --- /dev/null +++ b/TestAutomation/Usings.cs @@ -0,0 +1,9 @@ +global using NUnit.Framework; + +global using OpenQA.Selenium; +global using OpenQA.Selenium.Firefox; +global using OpenQA.Selenium.Chrome; +global using TestAutomation.Pages; +global using OpenQA.Selenium.Support.UI; +global using OpenQA.Selenium.Support; + diff --git a/TestAutomation/Website.cs b/TestAutomation/Website.cs new file mode 100644 index 0000000..1a7983f --- /dev/null +++ b/TestAutomation/Website.cs @@ -0,0 +1,51 @@ +namespace TestAutomation; + +public class Website { + public IWebDriver WebDriver { get; } + + public HarassCalculatorPage HarassCalculatorPage { get; } + + public Website(IWebDriver webDriver) { + WebDriver = webDriver; + + HarassCalculatorPage = new HarassCalculatorPage(this); + } + + public IWebElement Find(string byId) { + return WebDriver.FindElement(By.Id(byId)); + } + + public IList FindChildren(string ofId, string tagname) { + return WebDriver.FindElements(By.CssSelector($"#{ofId} {tagname}")); + } + + public string FindText(string byId) { + return WebDriver.FindElement(By.Id(byId)).Text; + } + + + public int FindInt(string byId) { + return int.Parse(WebDriver.FindElement(By.Id(byId)).Text); + } + + + public IWebElement EnterInput(IWebElement element, T input) { + element.Clear(); + element.SendKeys(input!.ToString()); + element.SendKeys(Keys.Enter); + return element; + } + + + public IWebElement EnterInput(string byId, T input) { + var element = Find(byId); + element.Clear(); + element.SendKeys(input!.ToString()); + element.SendKeys(Keys.Enter); + return element; + } + + public string GetLabel(string byId) { + return Find(byId).Text; + } +} \ No newline at end of file