Merge branch 'module_config' into 'master'

Module config page + tests

See merge request murphg62/2023-ca400-murphg62-byrnm257!10
This commit is contained in:
Malachy Byrne 2023-05-02 18:56:12 +00:00
commit 73f37bc501
158 changed files with 34316 additions and 35 deletions

View File

@ -12,16 +12,23 @@ variables:
POSTGRES_HOST_AUTH_METHOD: trust
# Define the job for building the Go backend application
build:
backend:
stage: build
image: golang:1.17.4-alpine3.14
script:
- cd src/backend/cmd
- go mod download
- go build -o app
frontend:
stage: build
image: mcr.microsoft.com/dotnet/sdk:6.0
script:
- cd src/PanoptesFrontend
- dotnet build
# Define the job for running the tests
test:
backend-test:
stage: test
image: golang:1.17.4-alpine3.14
services:
@ -44,3 +51,13 @@ test:
- export DB_NAME=$POSTGRES_DB
script:
- go test -v ./...
frontend-test:
stage: test
image: mcr.microsoft.com/dotnet/sdk:6.0
before_script:
- cd src/PanoptesTest
- dotnet restore
- dotnet build
script:
- dotnet test

View File

@ -0,0 +1,5 @@
public class ModuleConfig {
public string ImageName {get; set;}
public Dictionary<string, string> Environment {get; set;} = new Dictionary<string, string>();
public Dictionary<string, string> Volumes {get; set;} = new Dictionary<string, string>();
}

View File

@ -1,15 +0,0 @@
public class Post {
public int userId {get; set;}
public int id {get; set;}
public string title {get; set;}
public string body {get; set;}
public Post(int userId, int id, string title, string body){
userId = userId;
id = id;
title = title;
body = body;
}
}

View File

@ -1,18 +0,0 @@
@page "/counter"
<PageTitle>Counter</PageTitle>
<h1>Counter</h1>
<p role="status">Current count: @currentCount</p>
<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
@code {
private int currentCount = 0;
private void IncrementCount()
{
currentCount++;
}
}

View File

@ -0,0 +1,135 @@
@page "/module-config"
@using System.Text.Json
@using Microsoft.AspNetCore.Components.Web
@using Microsoft.JSInterop
@using System.Net;
@using PanoptesFrontend.Data
@using PanoptesFrontend.Services
@inject IHttpService httpService
<h1>Module Configuration</h1>
<div class="row">
<div class="col-12">
<div class="form-group">
<label for="imageName">Image Name</label>
<input type="text" class="form-control" id="imageName" name="ImageName" @bind="ModuleConfig.ImageName" />
</div>
</div>
</div>
<br>
<div class="row">
<div class="col-md-6">
<div class="card">
<div class="card-header">
<h2>Environment</h2>
</div>
<div class="card-body">
<div class="form-group">
<label for="key1">Key</label>
<input type="text" class="form-control" name="env_key" @bind="Key1" />
</div>
<div class="form-group">
<label for="value1">Value</label>
<input type="text" class="form-control" name="env_val" @bind="Value1" />
</div>
<button class="btn btn-primary" @onclick="AddKeyValuePair1">Add</button>
<table class="table mt-2" name="env_table">
<thead>
<tr>
<th>Key</th>
<th>Value</th>
</tr>
</thead>
<tbody>
@foreach (var kvp in ModuleConfig.Environment)
{
<tr>
<td>@kvp.Key</td>
<td>@kvp.Value</td>
</tr>
}
</tbody>
</table>
</div>
</div>
</div>
<div class="col-md-6">
<div class="card">
<div class="card-header">
<h2>Volumes</h2>
</div>
<div class="card-body">
<div class="form-group">
<label for="key2">Key</label>
<input type="text" class="form-control" name="vol_key" @bind="Key2" />
</div>
<div class="form-group">
<label for="value2">Value</label>
<input type="text" class="form-control" name="vol_val" @bind="Value2" />
</div>
<button class="btn btn-primary" @onclick="AddKeyValuePair2">Add</button>
<table class="table mt-2" name="vol_table">
<thead>
<tr>
<th>Key</th>
<th>Value</th>
</tr>
</thead>
<tbody>
@foreach (var kvp in ModuleConfig.Volumes)
{
<tr>
<td>@kvp.Key</td>
<td>@kvp.Value</td>
</tr>
}
</tbody>
</table>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-12 mt-3">
<button class="btn btn-success" @onclick="SubmitForm">Submit</button>
</div>
</div>
@code
{
@code {
private string Key1 { get; set; }
private string Value1 { get; set; }
private string Key2 { get; set; }
private string Value2 { get; set; }
public ModuleConfig ModuleConfig { get; set; } = new ModuleConfig();
private void AddKeyValuePair1()
{
ModuleConfig.Environment.Add(Key1, Value1);
Key1 = "";
Value1 = "";
}
private void AddKeyValuePair2()
{
ModuleConfig.Volumes.Add(Key2, Value2);
Key2 = "";
Value2 = "";
}
private async void SubmitForm()
{
// Log ModuleConfig object to console and send to backend
var config = JsonSerializer.Serialize(ModuleConfig);
Console.WriteLine(config);
await httpService.PostAsync("http://localhost:8080/config_module", config);
}
}
}

View File

@ -8,6 +8,9 @@
<ItemGroup>
<PackageReference Include="Blazor-ApexCharts" Version="0.9.20-beta" />
<PackageReference Include="Bunit" Version="1.19.14" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.5.0" />
<PackageReference Include="Moq" Version="4.18.4" />
<PackageReference Include="xunit" Version="2.4.2" />
</ItemGroup>

View File

@ -0,0 +1,60 @@
using PanoptesFrontend.Data;
using PanoptesFrontend.Pages;
using PanoptesFrontend.Services;
using System.Net;
using System.Net.Http;
public class ModuleConfigTests : TestContext
{
[Fact]
public void ImageNameInputFieldIsPresent()
{
Services.AddSingleton<IHttpService, HttpService>();
// Arrange
using var ctx = new TestContext();
ctx.Services.AddSingleton<IHttpService, HttpService>();
var cut = ctx.RenderComponent<ModConfig>();
// Act
var input = cut.Find("input[name='ImageName']");
// Assert
Assert.NotNull(input);
}
[Fact]
public void EnvironmentVariableFormIsPresent()
{
Services.AddSingleton<IHttpService, HttpService>();
// Arrange
using var ctx = new TestContext();
ctx.Services.AddSingleton<IHttpService, HttpService>();
var cut = ctx.RenderComponent<ModConfig>();
// Act
var envKey= cut.Find("input[name='env_key']");
var envVal = cut.Find("input[name='env_val']");
// Assert
Assert.NotNull(envKey);
Assert.NotNull(envVal);
}
[Fact]
public void VolumeFormIsPresent()
{
Services.AddSingleton<IHttpService, HttpService>();
// Arrange
using var ctx = new TestContext();
ctx.Services.AddSingleton<IHttpService, HttpService>();
var cut = ctx.RenderComponent<ModConfig>();
// Act
var volKey= cut.Find("input[name='vol_key']");
var volVal = cut.Find("input[name='vol_val']");
// Assert
Assert.NotNull(volKey);
Assert.NotNull(volVal);
}
}

View File

@ -0,0 +1,16 @@
<h1>Counter</h1>
<p>
Current count: @currentCount
</p>
<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
@code {
int currentCount = 0;
void IncrementCount()
{
currentCount++;
}
}

View File

@ -0,0 +1,31 @@
namespace PanoptesTest;
/// <summary>
/// These tests are written entirely in C#.
/// Learn more at https://bunit.dev/docs/getting-started/writing-tests.html#creating-basic-tests-in-cs-files
/// </summary>
public class CounterCSharpTests : TestContext
{
[Fact]
public void CounterStartsAtZero()
{
// Arrange
var cut = RenderComponent<Counter>();
// Assert that content of the paragraph shows counter at zero
cut.Find("p").MarkupMatches("<p>Current count: 0</p>");
}
[Fact]
public void ClickingButtonIncrementsCounter()
{
// Arrange
var cut = RenderComponent<Counter>();
// Act - click button to increment counter
cut.Find("button").Click();
// Assert that the counter was incremented
cut.Find("p").MarkupMatches("<p>Current count: 1</p>");
}
}

View File

@ -0,0 +1,29 @@
@inherits TestContext
These tests are written entirely in razor and C# syntax.
Learn more at https://bunit.dev/docs/getting-started/writing-tests.html#creating-basic-tests-in-razor-files
@code {
[Fact]
public void CounterStartsAtZero()
{
// Arrange
var cut = Render(@<Counter />);
// Assert that content of the paragraph shows counter at zero
cut.Find("p").MarkupMatches(@<p>Current count: 0</p>);
}
[Fact]
public void ClickingButtonIncrementsCounter()
{
// Arrange
var cut = Render(@<Counter />);
// Act - click button to increment counter
cut.Find("button").Click();
// Assert that the counter was incremented
cut.Find("p").MarkupMatches(@<p>Current count: 1</p>);
}
}

View File

@ -0,0 +1,40 @@
<Project Sdk="Microsoft.NET.Sdk.Razor">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<Nullable>enable</Nullable>
<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>
<Using Include="Bunit" />
<Using Include="Bunit.TestDoubles" />
<Using Include="Microsoft.Extensions.DependencyInjection" />
<Using Include="Xunit" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="bunit" Version="1.19.14" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.5.0" />
<PackageReference Include="coverlet.collector" Version="3.1.0">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="RichardSzalay.MockHttp" Version="6.0.0" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="xunit" Version="2.4.2" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.5">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\PanoptesFrontend\PanoptesFrontend.csproj" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,9 @@
@using Microsoft.AspNetCore.Components.Web
@using Microsoft.JSInterop
@using Microsoft.Extensions.DependencyInjection
@using Bunit
@using Bunit.TestDoubles
@using Xunit
@using System.Net;
@using System.Net.Http;
@using System.Threading.Tasks;

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,19 @@
{
"runtimeOptions": {
"tfm": "net6.0",
"frameworks": [
{
"name": "Microsoft.NETCore.App",
"version": "6.0.0"
},
{
"name": "Microsoft.AspNetCore.App",
"version": "6.0.0"
}
],
"configProperties": {
"System.GC.Server": true,
"System.Runtime.Serialization.EnableUnsafeBinaryFormatterSerialization": false
}
}
}

View File

@ -0,0 +1 @@
{"ContentRoots":["C:\\Users\\user\\Documents\\Panoptes\\2023-ca400-murphg62-byrnm257\\src\\PanoptesFrontend\\wwwroot\\","C:\\Users\\user\\.nuget\\packages\\microsoft.aspnetcore.components.webassembly.authentication\\6.0.0\\staticwebassets\\","C:\\Users\\user\\.nuget\\packages\\blazor-apexcharts\\0.9.20-beta\\staticwebassets\\","C:\\Users\\user\\Documents\\Panoptes\\2023-ca400-murphg62-byrnm257\\src\\PanoptesFrontend\\obj\\Debug\\net6.0\\scopedcss\\bundle\\"],"Root":{"Children":{"css":{"Children":{"bootstrap":{"Children":{"bootstrap.min.css":{"Children":null,"Asset":{"ContentRootIndex":0,"SubPath":"css/bootstrap/bootstrap.min.css"},"Patterns":null},"bootstrap.min.css.map":{"Children":null,"Asset":{"ContentRootIndex":0,"SubPath":"css/bootstrap/bootstrap.min.css.map"},"Patterns":null}},"Asset":null,"Patterns":null},"open-iconic":{"Children":{"FONT-LICENSE":{"Children":null,"Asset":{"ContentRootIndex":0,"SubPath":"css/open-iconic/FONT-LICENSE"},"Patterns":null},"font":{"Children":{"css":{"Children":{"open-iconic-bootstrap.min.css":{"Children":null,"Asset":{"ContentRootIndex":0,"SubPath":"css/open-iconic/font/css/open-iconic-bootstrap.min.css"},"Patterns":null}},"Asset":null,"Patterns":null},"fonts":{"Children":{"open-iconic.eot":{"Children":null,"Asset":{"ContentRootIndex":0,"SubPath":"css/open-iconic/font/fonts/open-iconic.eot"},"Patterns":null},"open-iconic.otf":{"Children":null,"Asset":{"ContentRootIndex":0,"SubPath":"css/open-iconic/font/fonts/open-iconic.otf"},"Patterns":null},"open-iconic.svg":{"Children":null,"Asset":{"ContentRootIndex":0,"SubPath":"css/open-iconic/font/fonts/open-iconic.svg"},"Patterns":null},"open-iconic.ttf":{"Children":null,"Asset":{"ContentRootIndex":0,"SubPath":"css/open-iconic/font/fonts/open-iconic.ttf"},"Patterns":null},"open-iconic.woff":{"Children":null,"Asset":{"ContentRootIndex":0,"SubPath":"css/open-iconic/font/fonts/open-iconic.woff"},"Patterns":null}},"Asset":null,"Patterns":null}},"Asset":null,"Patterns":null},"ICON-LICENSE":{"Children":null,"Asset":{"ContentRootIndex":0,"SubPath":"css/open-iconic/ICON-LICENSE"},"Patterns":null},"README.md":{"Children":null,"Asset":{"ContentRootIndex":0,"SubPath":"css/open-iconic/README.md"},"Patterns":null}},"Asset":null,"Patterns":null},"site.css":{"Children":null,"Asset":{"ContentRootIndex":0,"SubPath":"css/site.css"},"Patterns":null}},"Asset":null,"Patterns":null},"favicon.ico":{"Children":null,"Asset":{"ContentRootIndex":0,"SubPath":"favicon.ico"},"Patterns":null},"_content":{"Children":{"Microsoft.AspNetCore.Components.WebAssembly.Authentication":{"Children":{"AuthenticationService.js":{"Children":null,"Asset":{"ContentRootIndex":1,"SubPath":"AuthenticationService.js"},"Patterns":null}},"Asset":null,"Patterns":null},"Blazor-ApexCharts":{"Children":{"css":{"Children":{"apexcharts.css":{"Children":null,"Asset":{"ContentRootIndex":2,"SubPath":"css/apexcharts.css"},"Patterns":null}},"Asset":null,"Patterns":null},"js":{"Children":{"apex-charts.min.js":{"Children":null,"Asset":{"ContentRootIndex":2,"SubPath":"js/apex-charts.min.js"},"Patterns":null},"blazor-apex-charts.js":{"Children":null,"Asset":{"ContentRootIndex":2,"SubPath":"js/blazor-apex-charts.js"},"Patterns":null}},"Asset":null,"Patterns":null}},"Asset":null,"Patterns":null}},"Asset":null,"Patterns":null},"PanoptesFrontend.styles.css":{"Children":null,"Asset":{"ContentRootIndex":3,"SubPath":"PanoptesFrontend.styles.css"},"Patterns":null}},"Asset":null,"Patterns":[{"ContentRootIndex":0,"Pattern":"**","Depth":0}]}}

File diff suppressed because it is too large Load Diff

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,15 @@
{
"runtimeOptions": {
"tfm": "net6.0",
"frameworks": [
{
"name": "Microsoft.NETCore.App",
"version": "6.0.0"
},
{
"name": "Microsoft.AspNetCore.App",
"version": "6.0.0"
}
]
}
}

View File

@ -0,0 +1 @@
{"ContentRoots":["C:\\Users\\user\\.nuget\\packages\\microsoft.aspnetcore.components.webassembly.authentication\\6.0.0\\staticwebassets\\","C:\\Users\\user\\.nuget\\packages\\blazor-apexcharts\\0.9.20-beta\\staticwebassets\\","C:\\Users\\user\\Documents\\Panoptes\\2023-ca400-murphg62-byrnm257\\src\\PanoptesFrontend\\obj\\Debug\\net6.0\\scopedcss\\projectbundle\\","C:\\Users\\user\\Documents\\Panoptes\\2023-ca400-murphg62-byrnm257\\src\\PanoptesFrontend\\wwwroot\\","C:\\Users\\user\\Documents\\Panoptes\\2023-ca400-murphg62-byrnm257\\src\\PanoptesTest\\obj\\Debug\\net6.0\\scopedcss\\bundle\\"],"Root":{"Children":{"_content":{"Children":{"Microsoft.AspNetCore.Components.WebAssembly.Authentication":{"Children":{"AuthenticationService.js":{"Children":null,"Asset":{"ContentRootIndex":0,"SubPath":"AuthenticationService.js"},"Patterns":null}},"Asset":null,"Patterns":null},"Blazor-ApexCharts":{"Children":{"css":{"Children":{"apexcharts.css":{"Children":null,"Asset":{"ContentRootIndex":1,"SubPath":"css/apexcharts.css"},"Patterns":null}},"Asset":null,"Patterns":null},"js":{"Children":{"apex-charts.min.js":{"Children":null,"Asset":{"ContentRootIndex":1,"SubPath":"js/apex-charts.min.js"},"Patterns":null},"blazor-apex-charts.js":{"Children":null,"Asset":{"ContentRootIndex":1,"SubPath":"js/blazor-apex-charts.js"},"Patterns":null}},"Asset":null,"Patterns":null}},"Asset":null,"Patterns":null},"PanoptesFrontend":{"Children":{"PanoptesFrontend.bundle.scp.css":{"Children":null,"Asset":{"ContentRootIndex":2,"SubPath":"PanoptesFrontend.bundle.scp.css"},"Patterns":null},"css":{"Children":{"bootstrap":{"Children":{"bootstrap.min.css":{"Children":null,"Asset":{"ContentRootIndex":3,"SubPath":"css/bootstrap/bootstrap.min.css"},"Patterns":null},"bootstrap.min.css.map":{"Children":null,"Asset":{"ContentRootIndex":3,"SubPath":"css/bootstrap/bootstrap.min.css.map"},"Patterns":null}},"Asset":null,"Patterns":null},"open-iconic":{"Children":{"FONT-LICENSE":{"Children":null,"Asset":{"ContentRootIndex":3,"SubPath":"css/open-iconic/FONT-LICENSE"},"Patterns":null},"font":{"Children":{"css":{"Children":{"open-iconic-bootstrap.min.css":{"Children":null,"Asset":{"ContentRootIndex":3,"SubPath":"css/open-iconic/font/css/open-iconic-bootstrap.min.css"},"Patterns":null}},"Asset":null,"Patterns":null},"fonts":{"Children":{"open-iconic.eot":{"Children":null,"Asset":{"ContentRootIndex":3,"SubPath":"css/open-iconic/font/fonts/open-iconic.eot"},"Patterns":null},"open-iconic.otf":{"Children":null,"Asset":{"ContentRootIndex":3,"SubPath":"css/open-iconic/font/fonts/open-iconic.otf"},"Patterns":null},"open-iconic.svg":{"Children":null,"Asset":{"ContentRootIndex":3,"SubPath":"css/open-iconic/font/fonts/open-iconic.svg"},"Patterns":null},"open-iconic.ttf":{"Children":null,"Asset":{"ContentRootIndex":3,"SubPath":"css/open-iconic/font/fonts/open-iconic.ttf"},"Patterns":null},"open-iconic.woff":{"Children":null,"Asset":{"ContentRootIndex":3,"SubPath":"css/open-iconic/font/fonts/open-iconic.woff"},"Patterns":null}},"Asset":null,"Patterns":null}},"Asset":null,"Patterns":null},"ICON-LICENSE":{"Children":null,"Asset":{"ContentRootIndex":3,"SubPath":"css/open-iconic/ICON-LICENSE"},"Patterns":null},"README.md":{"Children":null,"Asset":{"ContentRootIndex":3,"SubPath":"css/open-iconic/README.md"},"Patterns":null}},"Asset":null,"Patterns":null},"site.css":{"Children":null,"Asset":{"ContentRootIndex":3,"SubPath":"css/site.css"},"Patterns":null}},"Asset":null,"Patterns":null},"favicon.ico":{"Children":null,"Asset":{"ContentRootIndex":3,"SubPath":"favicon.ico"},"Patterns":null}},"Asset":null,"Patterns":[{"ContentRootIndex":3,"Pattern":"**","Depth":2}]}},"Asset":null,"Patterns":null},"PanoptesTest.styles.css":{"Children":null,"Asset":{"ContentRootIndex":4,"SubPath":"PanoptesTest.styles.css"},"Patterns":null}},"Asset":null,"Patterns":null}}

View File

@ -0,0 +1,9 @@
{
"DetailedErrors": true,
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
}
}

View File

@ -0,0 +1,9 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*"
}

Some files were not shown because too many files have changed in this diff Show More