Skip to content

Commit

Permalink
Added basic e2e test setup (#44)
Browse files Browse the repository at this point in the history
* Added basic e2e test setup
  • Loading branch information
snakex64 authored Sep 20, 2024
1 parent 52216cc commit fe0badf
Show file tree
Hide file tree
Showing 13 changed files with 487 additions and 97 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,5 @@
/src/NodeDev.Core.Types.Tests/bin
/src/NodeDev.Core.Types.Tests/obj
/src/NodeDev.Core.Types/bin
/src/NodeDev.EndToEndTests/bin/Debug/net8.0
/src/NodeDev.EndToEndTests/obj
8 changes: 4 additions & 4 deletions src/NodeDev.Blazor/Components/ClassExplorer.razor
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
@inject IDialogService DialogService

<MudStack Row="false" Class="wh100">
<MudStack Row="false" Class="wh100" data-test-id="classExplorer">
<MudText>@Class.Name</MudText>

<MudTreeView T="TreeItem" Items="Items" SelectedValueChanged="OnSelectedItemChanged" Dense="true" Class="w100">
Expand All @@ -19,7 +19,7 @@
{
<MudTreeViewItem @bind-Expanded="@context.Expanded" Items="@context.Children" Value="@context.Value" Text="@context.Value!.Name" EndTextTypo="@Typo.caption">
<BodyContent Context="Item">
<div style="display: grid; grid-template-columns: 1fr auto; align-items: center; width: 100%" @onmouseover="() => Hovered = Item.Value" @onmouseout="() => Hovered = null">
<div style="display: grid; grid-template-columns: 1fr auto; align-items: center; width: 100%" @onmouseover="() => Hovered = Item.Value" @onmouseout="() => Hovered = null" data-test-id="@context.Value.Type">
<MudText Style="justify-self: start;">@Item.Text</MudText>
<div style="@($"justify-self: end; visibility: {(Hovered == Item.Value ? "visible" : "hidden")}")">
<MudIconButton Icon="@Icons.Material.Filled.Add" Size="Size.Medium" Color="Color.Inherit" OnClick="context.Value.Type == TreeItemType.MethodsFolder ? ShowAddMethodMenu : ShowNewProperty" />
Expand All @@ -32,7 +32,7 @@
{
<MudTreeViewItem @bind-Expanded="@context.Expanded" Value="@context.Value" Text="@context.Value!.Name" EndTextTypo="@Typo.caption">
<BodyContent Context="Item">
<div style="display: grid; grid-template-columns: 1fr auto; align-items: center; width: 100%" @onmouseover="() => Hovered = Item.Value" @onmouseout="() => Hovered = null">
<div style="display: grid; grid-template-columns: 1fr auto; align-items: center; width: 100%" @onmouseover="() => Hovered = Item.Value" @onmouseout="() => Hovered = null" data-test-id="Method" data-test-method="@Item.Text">
<MudText Typo="Typo.caption" Style="justify-self: start;">@Item.Value!.Method!.ReturnType.FriendlyName @Item.Text (@string.Join(',', Item.Value.Method!.Parameters.Select(x => $"{x.ParameterType.FriendlyName} {x.Name}")))</MudText>
<div style="@($"justify-self: end; visibility: {(Hovered == Item.Value ? "visible" : "hidden")}")">
<MudIconButton Icon="@Icons.Material.Filled.Edit" Size="Size.Medium" Color="Color.Inherit" OnClick="() => ShowMethodEdit(Item.Value!)" />
Expand All @@ -46,7 +46,7 @@
{
<MudTreeViewItem @bind-Expanded="@context.Expanded" Value="@context.Value" Text="@context.Value.Name" EndTextTypo="@Typo.caption">
<BodyContent Context="Item">
<div style="display: grid; grid-template-columns: 1fr auto; align-items: center; width: 100%" @onmouseover="() => Hovered = Item.Value" @onmouseout="() => Hovered = null">
<div style="display: grid; grid-template-columns: 1fr auto; align-items: center; width: 100%" @onmouseover="() => Hovered = Item.Value" @onmouseout="() => Hovered = null" data-test-id="Property">
<MudText Typo="Typo.caption" Style="justify-self: start;">@Item.Value!.Property!.PropertyType.FriendlyName @Item.Value!.Name</MudText>
<div style="@($"justify-self: end; visibility: {(Hovered == Item.Value ? "visible" : "hidden")}")">
<MudIconButton Icon="@Icons.Material.Filled.ShapeLine" Size="Size.Medium" Color="Color.Inherit" OnClick="() => ShowPropertyTypeEdit(Item.Value!)" />
Expand Down
181 changes: 91 additions & 90 deletions src/NodeDev.Blazor/Components/ProjectExplorer.razor
Original file line number Diff line number Diff line change
@@ -1,98 +1,99 @@

<MudStack Row="false" Class="wh100">
<MudText>Project</MudText>

<MudTreeView T="TreeItem" Items="Items" @bind-SelectedValue="Selected" @bind-SelectedValue:after="OnSelectedItemChanged" Class="flex-1">
<ItemTemplate>
@if (context.Value == null)
{ }
else if (context.Value.Type == TreeItemType.Folder)
{
<MudTreeViewItem @bind-Expanded="@context.Expanded" Items="@context.Children" Value="@context.Value" Text="@context.Value.Name" EndTextTypo="@Typo.caption" />
}
else if (context.Value.Type == TreeItemType.Class)
{
<MudTreeViewItem @bind-Expanded="@context.Expanded" Value="@context.Value" Text="@context.Value.Name" EndTextTypo="@Typo.caption" />
}
</ItemTemplate>
</MudTreeView>
<MudText>Project</MudText>

<MudTreeView T="TreeItem" Items="Items" @bind-SelectedValue="Selected" @bind-SelectedValue:after="OnSelectedItemChanged" Class="flex-1" data-test-id="projectExplorer">
<ItemTemplate>
@if (context.Value == null)
{ }
else if (context.Value.Type == TreeItemType.Folder)
{
<MudTreeViewItem @bind-Expanded="@context.Expanded" Items="@context.Children" Value="@context.Value" Text="@context.Value.Name" EndTextTypo="@Typo.caption" data-test-id="projectExplorerMethod" />
}
else if (context.Value.Type == TreeItemType.Class)
{
<MudTreeViewItem @bind-Expanded="@context.Expanded" Value="@context.Value" Text="@context.Value.Name" EndTextTypo="@Typo.caption" data-test-id="projectExplorerClass" />
}
</ItemTemplate>
</MudTreeView>
</MudStack>

@code {

private enum TreeItemType
{
Folder,
Class
}

private record class TreeItem(string Name, TreeItemType Type, NodeDev.Core.Class.NodeClass? Class)
{
public bool IsExpanded { get; set; } = true;
}

[Parameter]
public NodeDev.Core.Project Project { get; set; } = null!;

[Parameter]
public NodeDev.Core.Class.NodeClass? SelectedClass { get; set; }

[Parameter]
public EventCallback<NodeDev.Core.Class.NodeClass?> SelectedClassChanged { get; set; }

private TreeItem? Selected = null;

private List<TreeItemData<TreeItem>> Items { get; } = new();

private void OnSelectedItemChanged()
{
if (Selected?.Type == TreeItemType.Class)
{
SelectedClass = Selected.Class;
_ = SelectedClassChanged.InvokeAsync(SelectedClass);
}
else
{
SelectedClass = null;
_ = SelectedClassChanged.InvokeAsync(SelectedClass);
}
}

protected override void OnInitialized()
{
base.OnInitialized();

foreach (var nodeClass in Project.Classes)
AddClass(nodeClass);
}

private void AddClass(NodeDev.Core.Class.NodeClass nodeClass)
{
// find the folder that already exists in the tree
var folders = nodeClass.Namespace.Split('.');
TreeItemData<TreeItem>? folder = null;
for (int i = 0; i < folders.Length; ++i)
{
var parent = folder?.Children ?? Items;
folder = parent.FirstOrDefault(x => x.Value?.Name == folders[i] && x.Value?.Type == TreeItemType.Folder);
if (folder == null)
{
folder = new TreeItemData<TreeItem>()
{
Value = new(folders[i], TreeItemType.Folder, null),
Children = []
};
parent.Add(folder);
}
}

if (folder?.Children == null)
throw new Exception("Call cannot have no namespace ??");

folder.Children.Add(new()
{
Value = new(nodeClass.Name, TreeItemType.Class, nodeClass)
});
}
private enum TreeItemType
{
Folder,
Class
}

private record class TreeItem(string Name, TreeItemType Type, NodeDev.Core.Class.NodeClass? Class)
{
public bool IsExpanded { get; set; } = true;
}

[Parameter]
public NodeDev.Core.Project Project { get; set; } = null!;

[Parameter]
public NodeDev.Core.Class.NodeClass? SelectedClass { get; set; }

[Parameter]
public EventCallback<NodeDev.Core.Class.NodeClass?> SelectedClassChanged { get; set; }

private TreeItem? Selected = null;

private List<TreeItemData<TreeItem>> Items { get; } = new();

private void OnSelectedItemChanged()
{
if (Selected?.Type == TreeItemType.Class)
{
SelectedClass = Selected.Class;
_ = SelectedClassChanged.InvokeAsync(SelectedClass);
}
else
{
SelectedClass = null;
_ = SelectedClassChanged.InvokeAsync(SelectedClass);
}
}

protected override void OnInitialized()
{
base.OnInitialized();

foreach (var nodeClass in Project.Classes)
AddClass(nodeClass);
}

private void AddClass(NodeDev.Core.Class.NodeClass nodeClass)
{
// find the folder that already exists in the tree
var folders = nodeClass.Namespace.Split('.');
TreeItemData<TreeItem>? folder = null;
for (int i = 0; i < folders.Length; ++i)
{
var parent = folder?.Children ?? Items;
folder = parent.FirstOrDefault(x => x.Value?.Name == folders[i] && x.Value?.Type == TreeItemType.Folder);
if (folder == null)
{
folder = new TreeItemData<TreeItem>()
{
Value = new(folders[i], TreeItemType.Folder, null),
Children = [],
Expanded = true
};
parent.Add(folder);
}
}

if (folder?.Children == null)
throw new Exception("Call cannot have no namespace ??");

folder.Children.Add(new()
{
Value = new(nodeClass.Name, TreeItemType.Class, nodeClass)
});
}

}
20 changes: 17 additions & 3 deletions src/NodeDev.Blazor/Index.razor
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
@inject Services.DebuggedPathService DebuggedPathService
@inject NavigationManager NavigationManager
@inject ISnackbar Snackbar

<MudThemeProvider />
<MudPopoverProvider />
<MudDialogProvider />
<MudSnackbarProvider />

<MudLayout Style="height: 100vh; width: 100%; overflow: hidden">
<MudAppBar Elevation="1">
<MudButton OnClick="Save" Class="ml-3">Save</MudButton>
<MudAppBar Elevation="1" data-test-id="appBar">
<MudButton OnClick="NewProject" Class="ml-3" data-test-id="newProject">New Project</MudButton>
<MudButton OnClick="Save" Class="ml-3" data-test-id="Save">Save</MudButton>
<MudButton OnClick="Add" Class="ml-3">Add node</MudButton>
<MudButton OnClick="Run" Class="ml-3">Run</MudButton>
<MudButton OnClick="SwitchLiveDebugging">@(Project.IsLiveDebuggingEnabled ? "Stop Live Debugging" : "Start Live Debugging")</MudButton>
Expand All @@ -18,7 +21,7 @@

<MudExtensions.MudSplitter EnableSlide="true" Sensitivity="0.01" @bind-Dimension="ProjectExplorerGraphPercentage" Class="wh100 overflow-hidden relative">
<StartContent>
<MudTabs Elevation="2" Rounded="true" ApplyEffectsToContainer="true" PanelClass="pa-2 wh100" KeepPanelsAlive="true" Class="wh100">
<MudTabs Elevation="2" Rounded="true" ApplyEffectsToContainer="true" PanelClass="pa-2 wh100" KeepPanelsAlive="true" Class="wh100" data-test-id="ProjectExplorerSection">
<MudTabPanel Text="Project">
<ProjectExplorer Project="Project" @bind-SelectedClass="SelectedClass"></ProjectExplorer>
</MudTabPanel>
Expand Down Expand Up @@ -164,6 +167,17 @@
{
var content = Project.Serialize();
File.WriteAllText("project.json", content);

Snackbar.Add("Project saved", Severity.Success);
}

private void NewProject()
{
if (File.Exists("project.json"))
File.Move("project.json", "project_backup.json", true);


NavigationManager.Refresh(true);
}

private void Add()
Expand Down
8 changes: 8 additions & 0 deletions src/NodeDev.EndToEndTests/Features/SaveProject.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
Feature: Save a project to file system

Scenario: Save empty project
Given I load the default project
Then The 'Main' method in the 'Program' class should exist

Given I save the current project
Then Snackbar should contain 'Project saved'
112 changes: 112 additions & 0 deletions src/NodeDev.EndToEndTests/Features/SaveProject.feature.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit fe0badf

Please sign in to comment.