diff --git a/angular-workspace/projects/example-client-app/src/app/app.module.ts b/angular-workspace/projects/example-client-app/src/app/app.module.ts index ebb6a1467a..fb5eb64535 100644 --- a/angular-workspace/projects/example-client-app/src/app/app.module.ts +++ b/angular-workspace/projects/example-client-app/src/app/app.module.ts @@ -28,6 +28,7 @@ import { NimbleTableColumnDurationTextModule } from '@ni/nimble-angular/table-co import { NimbleRichTextViewerModule } from '@ni/nimble-angular/rich-text/viewer'; import { NimbleRichTextEditorModule } from '@ni/nimble-angular/rich-text/editor'; import { NimbleRichTextMentionUsersModule } from '@ni/nimble-angular/rich-text-mention/users'; +import { SprightRectangleModule } from '@ni/spright-angular/rectangle'; import { AppComponent } from './app.component'; import { CustomAppComponent } from './customapp/customapp.component'; import { HeaderComponent } from './header/header.component'; @@ -100,6 +101,7 @@ import { HeaderComponent } from './header/header.component'; NimbleMappingUserModule, NimbleRichTextMentionUsersModule, NimbleMappingSpinnerModule, + SprightRectangleModule, RouterModule.forRoot( [ { path: '', redirectTo: '/customapp', pathMatch: 'full' }, diff --git a/angular-workspace/projects/example-client-app/src/app/customapp/customapp.component.html b/angular-workspace/projects/example-client-app/src/app/customapp/customapp.component.html index 7f50decebc..a2bc7ee1d5 100644 --- a/angular-workspace/projects/example-client-app/src/app/customapp/customapp.component.html +++ b/angular-workspace/projects/example-client-app/src/app/customapp/customapp.component.html @@ -412,5 +412,9 @@ +
+
Rectangle (Spright)
+ Spright! +
diff --git a/angular-workspace/projects/ni/nimble-angular/CHANGELOG.json b/angular-workspace/projects/ni/nimble-angular/CHANGELOG.json index 5ed4d94ce8..a799378a56 100644 --- a/angular-workspace/projects/ni/nimble-angular/CHANGELOG.json +++ b/angular-workspace/projects/ni/nimble-angular/CHANGELOG.json @@ -1,6 +1,21 @@ { "name": "@ni/nimble-angular", "entries": [ + { + "date": "Wed, 08 May 2024 17:29:00 GMT", + "version": "24.0.4", + "tag": "@ni/nimble-angular_v24.0.4", + "comments": { + "patch": [ + { + "author": "beachball", + "package": "@ni/nimble-angular", + "comment": "Bump @ni/nimble-components to v28.0.4", + "commit": "not available" + } + ] + } + }, { "date": "Tue, 07 May 2024 20:15:55 GMT", "version": "24.0.3", diff --git a/angular-workspace/projects/ni/nimble-angular/CHANGELOG.md b/angular-workspace/projects/ni/nimble-angular/CHANGELOG.md index 81654b7daf..ef9f03de69 100644 --- a/angular-workspace/projects/ni/nimble-angular/CHANGELOG.md +++ b/angular-workspace/projects/ni/nimble-angular/CHANGELOG.md @@ -1,9 +1,17 @@ # Change Log - @ni/nimble-angular -This log was last generated on Tue, 07 May 2024 20:15:55 GMT and should not be manually modified. +This log was last generated on Wed, 08 May 2024 17:29:00 GMT and should not be manually modified. +## 24.0.4 + +Wed, 08 May 2024 17:29:00 GMT + +### Patches + +- Bump @ni/nimble-components to v28.0.4 + ## 24.0.3 Tue, 07 May 2024 20:15:55 GMT diff --git a/angular-workspace/projects/ni/nimble-angular/package.json b/angular-workspace/projects/ni/nimble-angular/package.json index cbef4ac456..10773b634f 100644 --- a/angular-workspace/projects/ni/nimble-angular/package.json +++ b/angular-workspace/projects/ni/nimble-angular/package.json @@ -1,6 +1,6 @@ { "name": "@ni/nimble-angular", - "version": "24.0.3", + "version": "24.0.4", "description": "Angular components for the NI Nimble Design System", "scripts": { "invoke-publish": "npm run invoke-publish:setup && cd ../../../dist/ni/nimble-angular && npm publish", @@ -32,7 +32,7 @@ "@angular/forms": "^16.2.12", "@angular/localize": "^16.2.12", "@angular/router": "^16.2.12", - "@ni/nimble-components": "^28.0.3" + "@ni/nimble-components": "^28.0.4" }, "dependencies": { "tslib": "^2.2.0" diff --git a/angular-workspace/projects/ni/spright-angular/CHANGELOG.json b/angular-workspace/projects/ni/spright-angular/CHANGELOG.json index 0afe51feb2..106160c6d9 100644 --- a/angular-workspace/projects/ni/spright-angular/CHANGELOG.json +++ b/angular-workspace/projects/ni/spright-angular/CHANGELOG.json @@ -1,6 +1,21 @@ { "name": "@ni/spright-angular", "entries": [ + { + "date": "Wed, 08 May 2024 17:29:00 GMT", + "version": "0.1.15", + "tag": "@ni/spright-angular_v0.1.15", + "comments": { + "patch": [ + { + "author": "beachball", + "package": "@ni/spright-angular", + "comment": "Bump @ni/spright-components to v0.0.18", + "commit": "not available" + } + ] + } + }, { "date": "Tue, 07 May 2024 20:15:55 GMT", "version": "0.1.14", diff --git a/angular-workspace/projects/ni/spright-angular/CHANGELOG.md b/angular-workspace/projects/ni/spright-angular/CHANGELOG.md index bbf18260bd..b63b1dae80 100644 --- a/angular-workspace/projects/ni/spright-angular/CHANGELOG.md +++ b/angular-workspace/projects/ni/spright-angular/CHANGELOG.md @@ -1,9 +1,17 @@ # Change Log - @ni/spright-angular -This log was last generated on Tue, 07 May 2024 20:15:55 GMT and should not be manually modified. +This log was last generated on Wed, 08 May 2024 17:29:00 GMT and should not be manually modified. +## 0.1.15 + +Wed, 08 May 2024 17:29:00 GMT + +### Patches + +- Bump @ni/spright-components to v0.0.18 + ## 0.1.14 Tue, 07 May 2024 20:15:55 GMT diff --git a/angular-workspace/projects/ni/spright-angular/package.json b/angular-workspace/projects/ni/spright-angular/package.json index 57dd39c22a..1f394ae7bf 100644 --- a/angular-workspace/projects/ni/spright-angular/package.json +++ b/angular-workspace/projects/ni/spright-angular/package.json @@ -1,6 +1,6 @@ { "name": "@ni/spright-angular", - "version": "0.1.14", + "version": "0.1.15", "description": "Angular components for NI Spright", "scripts": { "invoke-publish": "npm run invoke-publish:setup && cd ../../../dist/ni/spright-angular && npm publish", @@ -24,7 +24,7 @@ "peerDependencies": { "@angular/common": "^16.2.12", "@angular/core": "^16.2.12", - "@ni/spright-components": "^0.0.17" + "@ni/spright-components": "^0.0.18" }, "dependencies": { "tslib": "^2.2.0" diff --git a/package-lock.json b/package-lock.json index 2dd73fa7f9..ad8f64cceb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -82,7 +82,7 @@ }, "angular-workspace/projects/ni/nimble-angular": { "name": "@ni/nimble-angular", - "version": "24.0.3", + "version": "24.0.4", "license": "MIT", "dependencies": { "tslib": "^2.2.0" @@ -93,12 +93,12 @@ "@angular/forms": "^16.2.12", "@angular/localize": "^16.2.12", "@angular/router": "^16.2.12", - "@ni/nimble-components": "^28.0.3" + "@ni/nimble-components": "^28.0.4" } }, "angular-workspace/projects/ni/spright-angular": { "name": "@ni/spright-angular", - "version": "0.1.14", + "version": "0.1.15", "license": "MIT", "dependencies": { "tslib": "^2.2.0" @@ -106,7 +106,7 @@ "peerDependencies": { "@angular/common": "^16.2.12", "@angular/core": "^16.2.12", - "@ni/spright-components": "^0.0.17" + "@ni/spright-components": "^0.0.18" } }, "node_modules/@11ty/dependency-tree": { @@ -32678,7 +32678,7 @@ }, "packages/nimble-components": { "name": "@ni/nimble-components", - "version": "28.0.3", + "version": "28.0.4", "license": "MIT", "dependencies": { "@microsoft/fast-colors": "^5.3.1", @@ -32826,14 +32826,14 @@ }, "packages/spright-components": { "name": "@ni/spright-components", - "version": "0.0.17", + "version": "0.0.18", "license": "MIT", "dependencies": { "@microsoft/fast-colors": "^5.3.1", "@microsoft/fast-element": "^1.12.0", "@microsoft/fast-foundation": "^2.49.6", "@microsoft/fast-web-utilities": "^6.0.0", - "@ni/nimble-components": "28.0.3", + "@ni/nimble-components": "28.0.4", "@ni/nimble-tokens": "^6.13.5", "tslib": "^2.2.0" }, diff --git a/packages/blazor-workspace/BlazorWorkspace.sln b/packages/blazor-workspace/BlazorWorkspace.sln index 312f365a41..dfb3b4027e 100644 --- a/packages/blazor-workspace/BlazorWorkspace.sln +++ b/packages/blazor-workspace/BlazorWorkspace.sln @@ -27,6 +27,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SprightBlazor.Tests", "Test EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SprightBlazor.Tests.Acceptance", "Tests\SprightBlazor.Tests.Acceptance\SprightBlazor.Tests.Acceptance.csproj", "{8E335572-CD8B-4879-8760-73416CF103B1}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BlazorWorkspace.Testing.Acceptance", "Tests\BlazorWorkspace.Testing.Acceptance\BlazorWorkspace.Testing.Acceptance.csproj", "{D94A4535-51B3-4E70-9582-3F3A44C7A798}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -73,6 +75,10 @@ Global {8E335572-CD8B-4879-8760-73416CF103B1}.Debug|Any CPU.Build.0 = Debug|Any CPU {8E335572-CD8B-4879-8760-73416CF103B1}.Release|Any CPU.ActiveCfg = Release|Any CPU {8E335572-CD8B-4879-8760-73416CF103B1}.Release|Any CPU.Build.0 = Release|Any CPU + {D94A4535-51B3-4E70-9582-3F3A44C7A798}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D94A4535-51B3-4E70-9582-3F3A44C7A798}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D94A4535-51B3-4E70-9582-3F3A44C7A798}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D94A4535-51B3-4E70-9582-3F3A44C7A798}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -86,6 +92,7 @@ Global {7C65AEA1-8CA2-48DC-81FE-CE39295BDD4B} = {E5C31FAF-7DEF-494F-A0D2-C9A4875F2132} {CEA7A89F-CF8E-4128-927E-24CBBF2C8C63} = {E5C31FAF-7DEF-494F-A0D2-C9A4875F2132} {8E335572-CD8B-4879-8760-73416CF103B1} = {E5C31FAF-7DEF-494F-A0D2-C9A4875F2132} + {D94A4535-51B3-4E70-9582-3F3A44C7A798} = {E5C31FAF-7DEF-494F-A0D2-C9A4875F2132} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {38E2A588-0714-41E7-9BA3-D89622560FF9} diff --git a/packages/blazor-workspace/CONTRIBUTING.md b/packages/blazor-workspace/CONTRIBUTING.md index 35b9bf13a5..7662468497 100644 --- a/packages/blazor-workspace/CONTRIBUTING.md +++ b/packages/blazor-workspace/CONTRIBUTING.md @@ -107,6 +107,15 @@ Visual Studio Code commands are included to build and run the example projects. - `blazor-wasm-example:build`: Build the `Demo.Client` project - `blazor-wasm-example:watch`: Run the `Demo.Client` project in watch mode (to automatically pick up code changes) +## Creating a New Project + +When creating a new project in the Blazor workspace, ensure it includes the following configuration: + +- .NET version matches other projects in the workspace +- `true` +- `true` +- Package reference to `NI.CSharp.Analyzers` with same version spec as other projects + ## Additional Tips ### Enabling IIS diff --git a/packages/blazor-workspace/Examples/Demo.Client/packages.lock.json b/packages/blazor-workspace/Examples/Demo.Client/packages.lock.json index a4df66bdb9..0a65346a98 100644 --- a/packages/blazor-workspace/Examples/Demo.Client/packages.lock.json +++ b/packages/blazor-workspace/Examples/Demo.Client/packages.lock.json @@ -340,7 +340,8 @@ "dependencies": { "Microsoft.AspNetCore.Components.Web": "[6.*, )", "NI.CSharp.Analyzers": "[2.0.21, 2.0.21]", - "NimbleBlazor": "[1.0.0, )" + "NimbleBlazor": "[1.0.0, )", + "SprightBlazor": "[1.0.0, )" } }, "nimbleblazor": { @@ -348,6 +349,12 @@ "dependencies": { "Microsoft.AspNetCore.Components.Web": "[6.0.29, )" } + }, + "sprightblazor": { + "type": "Project", + "dependencies": { + "Microsoft.AspNetCore.Components.Web": "[6.0.29, )" + } } }, "net6.0/browser-wasm": { diff --git a/packages/blazor-workspace/Examples/Demo.Client/wwwroot/index.html b/packages/blazor-workspace/Examples/Demo.Client/wwwroot/index.html index 7efddcf383..8e912f7278 100644 --- a/packages/blazor-workspace/Examples/Demo.Client/wwwroot/index.html +++ b/packages/blazor-workspace/Examples/Demo.Client/wwwroot/index.html @@ -20,7 +20,7 @@ Reload 🗙 - + diff --git a/packages/blazor-workspace/Examples/Demo.Hybrid/packages.lock.json b/packages/blazor-workspace/Examples/Demo.Hybrid/packages.lock.json index 9e2bdf58c5..e1addd90a6 100644 --- a/packages/blazor-workspace/Examples/Demo.Hybrid/packages.lock.json +++ b/packages/blazor-workspace/Examples/Demo.Hybrid/packages.lock.json @@ -358,7 +358,8 @@ "dependencies": { "Microsoft.AspNetCore.Components.Web": "[6.*, )", "NI.CSharp.Analyzers": "[2.0.21, 2.0.21]", - "NimbleBlazor": "[1.0.0, )" + "NimbleBlazor": "[1.0.0, )", + "SprightBlazor": "[1.0.0, )" } }, "nimbleblazor": { @@ -366,6 +367,12 @@ "dependencies": { "Microsoft.AspNetCore.Components.Web": "[6.0.29, )" } + }, + "sprightblazor": { + "type": "Project", + "dependencies": { + "Microsoft.AspNetCore.Components.Web": "[6.0.29, )" + } } } } diff --git a/packages/blazor-workspace/Examples/Demo.Hybrid/wwwroot/index.html b/packages/blazor-workspace/Examples/Demo.Hybrid/wwwroot/index.html index 964f8f94c1..fc72bdbc71 100644 --- a/packages/blazor-workspace/Examples/Demo.Hybrid/wwwroot/index.html +++ b/packages/blazor-workspace/Examples/Demo.Hybrid/wwwroot/index.html @@ -21,10 +21,11 @@ 🗙 - + + diff --git a/packages/blazor-workspace/Examples/Demo.Server/Pages/_Layout.cshtml b/packages/blazor-workspace/Examples/Demo.Server/Pages/_Layout.cshtml index 9fa4936eb9..8be6999bc3 100644 --- a/packages/blazor-workspace/Examples/Demo.Server/Pages/_Layout.cshtml +++ b/packages/blazor-workspace/Examples/Demo.Server/Pages/_Layout.cshtml @@ -28,6 +28,6 @@ - + \ No newline at end of file diff --git a/packages/blazor-workspace/Examples/Demo.Server/packages.lock.json b/packages/blazor-workspace/Examples/Demo.Server/packages.lock.json index f7b606cf8c..3c380a3b5d 100644 --- a/packages/blazor-workspace/Examples/Demo.Server/packages.lock.json +++ b/packages/blazor-workspace/Examples/Demo.Server/packages.lock.json @@ -204,7 +204,8 @@ "dependencies": { "Microsoft.AspNetCore.Components.Web": "[6.*, )", "NI.CSharp.Analyzers": "[2.0.21, 2.0.21]", - "NimbleBlazor": "[1.0.0, )" + "NimbleBlazor": "[1.0.0, )", + "SprightBlazor": "[1.0.0, )" } }, "nimbleblazor": { @@ -212,6 +213,12 @@ "dependencies": { "Microsoft.AspNetCore.Components.Web": "[6.0.29, )" } + }, + "sprightblazor": { + "type": "Project", + "dependencies": { + "Microsoft.AspNetCore.Components.Web": "[6.0.29, )" + } } } } diff --git a/packages/blazor-workspace/Examples/Demo.Shared/Demo.Shared.csproj b/packages/blazor-workspace/Examples/Demo.Shared/Demo.Shared.csproj index 318c8dafa9..ebcfb12c58 100644 --- a/packages/blazor-workspace/Examples/Demo.Shared/Demo.Shared.csproj +++ b/packages/blazor-workspace/Examples/Demo.Shared/Demo.Shared.csproj @@ -42,6 +42,7 @@ + diff --git a/packages/blazor-workspace/Examples/Demo.Shared/Pages/ComponentsDemo.razor b/packages/blazor-workspace/Examples/Demo.Shared/Pages/ComponentsDemo.razor index 9c892ba7db..d0babc14e5 100644 --- a/packages/blazor-workspace/Examples/Demo.Shared/Pages/ComponentsDemo.razor +++ b/packages/blazor-workspace/Examples/Demo.Shared/Pages/ComponentsDemo.razor @@ -384,5 +384,9 @@ AddDiesToRadius(10))>Increase Die Count RemoveDiesFromRadius(10))>Decrease Die Count +
+
Rectangle (Spright)
+ Spright! +
diff --git a/packages/blazor-workspace/Examples/Demo.Shared/_Imports.razor b/packages/blazor-workspace/Examples/Demo.Shared/_Imports.razor index beb6a1a10d..c3bfbdfcf6 100644 --- a/packages/blazor-workspace/Examples/Demo.Shared/_Imports.razor +++ b/packages/blazor-workspace/Examples/Demo.Shared/_Imports.razor @@ -4,4 +4,5 @@ @using Microsoft.AspNetCore.Components.Web.Virtualization @using Microsoft.JSInterop @using NimbleBlazor +@using SprightBlazor @using Demo.Shared.Pages \ No newline at end of file diff --git a/packages/blazor-workspace/Examples/Demo.Shared/packages.lock.json b/packages/blazor-workspace/Examples/Demo.Shared/packages.lock.json index ef26793a93..3c68fb5bec 100644 --- a/packages/blazor-workspace/Examples/Demo.Shared/packages.lock.json +++ b/packages/blazor-workspace/Examples/Demo.Shared/packages.lock.json @@ -205,6 +205,12 @@ "dependencies": { "Microsoft.AspNetCore.Components.Web": "[6.0.29, )" } + }, + "sprightblazor": { + "type": "Project", + "dependencies": { + "Microsoft.AspNetCore.Components.Web": "[6.0.29, )" + } } } } diff --git a/packages/blazor-workspace/NimbleBlazor/CHANGELOG.json b/packages/blazor-workspace/NimbleBlazor/CHANGELOG.json index 8be40e1ef6..dad16f266c 100644 --- a/packages/blazor-workspace/NimbleBlazor/CHANGELOG.json +++ b/packages/blazor-workspace/NimbleBlazor/CHANGELOG.json @@ -1,6 +1,21 @@ { "name": "@ni/nimble-blazor", "entries": [ + { + "date": "Wed, 08 May 2024 00:06:34 GMT", + "version": "17.0.0", + "tag": "@ni/nimble-blazor_v17.0.0", + "comments": { + "none": [ + { + "author": "7282195+m-akinc@users.noreply.github.com", + "package": "@ni/nimble-blazor", + "commit": "4f3336686f0c26bacbbb2a25232bc70a7e623fcf", + "comment": "Add Spright rectangle component to Blazor example" + } + ] + } + }, { "date": "Mon, 06 May 2024 19:00:05 GMT", "version": "17.0.0", diff --git a/packages/blazor-workspace/NimbleBlazor/NimbleBlazor.csproj b/packages/blazor-workspace/NimbleBlazor/NimbleBlazor.csproj index 552aed5a0a..2440f5fa6e 100644 --- a/packages/blazor-workspace/NimbleBlazor/NimbleBlazor.csproj +++ b/packages/blazor-workspace/NimbleBlazor/NimbleBlazor.csproj @@ -24,9 +24,13 @@ CS8669 + - - + + diff --git a/packages/blazor-workspace/SprightBlazor/CHANGELOG.json b/packages/blazor-workspace/SprightBlazor/CHANGELOG.json index 5276aa9479..80bb352d02 100644 --- a/packages/blazor-workspace/SprightBlazor/CHANGELOG.json +++ b/packages/blazor-workspace/SprightBlazor/CHANGELOG.json @@ -1,6 +1,21 @@ { "name": "@ni/spright-blazor", "entries": [ + { + "date": "Wed, 08 May 2024 00:06:34 GMT", + "version": "0.0.4", + "tag": "@ni/spright-blazor_v0.0.4", + "comments": { + "none": [ + { + "author": "7282195+m-akinc@users.noreply.github.com", + "package": "@ni/spright-blazor", + "commit": "4f3336686f0c26bacbbb2a25232bc70a7e623fcf", + "comment": "Add Spright rectangle component to Blazor example" + } + ] + } + }, { "date": "Thu, 02 May 2024 23:33:54 GMT", "version": "0.0.4", diff --git a/packages/blazor-workspace/SprightBlazor/SprightBlazor.csproj b/packages/blazor-workspace/SprightBlazor/SprightBlazor.csproj index 677c83e90d..c4a796c7f2 100644 --- a/packages/blazor-workspace/SprightBlazor/SprightBlazor.csproj +++ b/packages/blazor-workspace/SprightBlazor/SprightBlazor.csproj @@ -24,9 +24,13 @@ CS8669 + - - + + diff --git a/packages/blazor-workspace/Tests/BlazorWorkspace.Testing.Acceptance/AcceptanceTestsBase.cs b/packages/blazor-workspace/Tests/BlazorWorkspace.Testing.Acceptance/AcceptanceTestsBase.cs new file mode 100644 index 0000000000..6615fd406d --- /dev/null +++ b/packages/blazor-workspace/Tests/BlazorWorkspace.Testing.Acceptance/AcceptanceTestsBase.cs @@ -0,0 +1,52 @@ +using Microsoft.Playwright; +using Xunit; + +namespace BlazorWorkspace.Testing.Acceptance; + +[Collection(nameof(PlaywrightFixture))] +public abstract class AcceptanceTestsBase +{ + private readonly PlaywrightFixture _playwrightFixture; + + protected abstract Uri ServerAddress { get; } + protected abstract string ComponentLibraryInitializationTestJavaScript { get; } + + protected AcceptanceTestsBase(PlaywrightFixture playwrightFixture) + { + _playwrightFixture = playwrightFixture; + } + + protected async Task NewPageForRouteAsync(string route) + { + var page = await _playwrightFixture.BrowserContext!.NewPageAsync(); + await NavigateToPageAsync(page, route); + await WaitForComponentsInitializationAsync(page); + return new AsyncDisposablePage(page); + } + + private async Task NavigateToPageAsync(IPage page, string route) + { + var address = new Uri(ServerAddress!, route).AbsoluteUri; + await page.GotoAsync(address); + } + + private async Task WaitForComponentsInitializationAsync(IPage page) + { + await page.WaitForFunctionAsync(ComponentLibraryInitializationTestJavaScript); + } + + protected sealed class AsyncDisposablePage : IAsyncDisposable + { + public IPage Page { get; private set; } + + public AsyncDisposablePage(IPage page) + { + Page = page; + } + + public async ValueTask DisposeAsync() + { + await Page.CloseAsync(); + } + } +} diff --git a/packages/blazor-workspace/Tests/BlazorWorkspace.Testing.Acceptance/BlazorWorkspace.Testing.Acceptance.csproj b/packages/blazor-workspace/Tests/BlazorWorkspace.Testing.Acceptance/BlazorWorkspace.Testing.Acceptance.csproj new file mode 100644 index 0000000000..20099d0c08 --- /dev/null +++ b/packages/blazor-workspace/Tests/BlazorWorkspace.Testing.Acceptance/BlazorWorkspace.Testing.Acceptance.csproj @@ -0,0 +1,38 @@ + + + net6.0 + enable + enable + true + true + + + + CA1716 + Properties + + + + + + + + + + + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + diff --git a/packages/blazor-workspace/Tests/NimbleBlazor.Tests.Acceptance/Shared/MainLayout.razor b/packages/blazor-workspace/Tests/BlazorWorkspace.Testing.Acceptance/MainLayout.razor similarity index 85% rename from packages/blazor-workspace/Tests/NimbleBlazor.Tests.Acceptance/Shared/MainLayout.razor rename to packages/blazor-workspace/Tests/BlazorWorkspace.Testing.Acceptance/MainLayout.razor index 708f84232b..c1fca87f02 100644 --- a/packages/blazor-workspace/Tests/NimbleBlazor.Tests.Acceptance/Shared/MainLayout.razor +++ b/packages/blazor-workspace/Tests/BlazorWorkspace.Testing.Acceptance/MainLayout.razor @@ -1,6 +1,7 @@ @using Microsoft.AspNetCore.Components +@using Microsoft.AspNetCore.Components.Web @using NimbleBlazor -@namespace NimbleBlazor.Tests.Acceptance.Shared +@namespace BlazorWorkspace.Testing.Acceptance @inherits LayoutComponentBase Nimble Blazor tests diff --git a/packages/blazor-workspace/Tests/SprightBlazor.Tests.Acceptance/Shared/MainLayout.razor.cs b/packages/blazor-workspace/Tests/BlazorWorkspace.Testing.Acceptance/MainLayout.razor.cs similarity index 90% rename from packages/blazor-workspace/Tests/SprightBlazor.Tests.Acceptance/Shared/MainLayout.razor.cs rename to packages/blazor-workspace/Tests/BlazorWorkspace.Testing.Acceptance/MainLayout.razor.cs index 5d7ec2d0e4..d8afda74a0 100644 --- a/packages/blazor-workspace/Tests/SprightBlazor.Tests.Acceptance/Shared/MainLayout.razor.cs +++ b/packages/blazor-workspace/Tests/BlazorWorkspace.Testing.Acceptance/MainLayout.razor.cs @@ -3,7 +3,7 @@ using Microsoft.JSInterop; using NimbleBlazor; -namespace SprightBlazor.Tests.Acceptance.Shared; +namespace BlazorWorkspace.Testing.Acceptance; /// /// The MainLayout Component. diff --git a/packages/blazor-workspace/Tests/NimbleBlazor.Tests.Acceptance/Shared/MainLayout.razor.css b/packages/blazor-workspace/Tests/BlazorWorkspace.Testing.Acceptance/MainLayout.razor.css similarity index 100% rename from packages/blazor-workspace/Tests/NimbleBlazor.Tests.Acceptance/Shared/MainLayout.razor.css rename to packages/blazor-workspace/Tests/BlazorWorkspace.Testing.Acceptance/MainLayout.razor.css diff --git a/packages/blazor-workspace/Tests/NimbleBlazor.Tests.Acceptance/PlaywrightFixture.cs b/packages/blazor-workspace/Tests/BlazorWorkspace.Testing.Acceptance/PlaywrightFixture.cs similarity index 96% rename from packages/blazor-workspace/Tests/NimbleBlazor.Tests.Acceptance/PlaywrightFixture.cs rename to packages/blazor-workspace/Tests/BlazorWorkspace.Testing.Acceptance/PlaywrightFixture.cs index f8706d87e8..5d0751c0fe 100644 --- a/packages/blazor-workspace/Tests/NimbleBlazor.Tests.Acceptance/PlaywrightFixture.cs +++ b/packages/blazor-workspace/Tests/BlazorWorkspace.Testing.Acceptance/PlaywrightFixture.cs @@ -1,7 +1,7 @@ using Microsoft.Playwright; using Xunit; -namespace NimbleBlazor.Tests.Acceptance; +namespace BlazorWorkspace.Testing.Acceptance; /// /// Fixture to handle Playwright initialization for acceptance tests. diff --git a/packages/blazor-workspace/Tests/BlazorWorkspace.Testing.Acceptance/Properties/launchSettings.json b/packages/blazor-workspace/Tests/BlazorWorkspace.Testing.Acceptance/Properties/launchSettings.json new file mode 100644 index 0000000000..22fa40c924 --- /dev/null +++ b/packages/blazor-workspace/Tests/BlazorWorkspace.Testing.Acceptance/Properties/launchSettings.json @@ -0,0 +1,12 @@ +{ + "profiles": { + "BlazorWorkspace.Testing.Acceptance": { + "commandName": "Project", + "launchBrowser": true, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "applicationUrl": "https://localhost:64440;http://localhost:64441" + } + } +} \ No newline at end of file diff --git a/packages/blazor-workspace/Tests/NimbleBlazor.Tests.Acceptance/Startup.cs b/packages/blazor-workspace/Tests/BlazorWorkspace.Testing.Acceptance/Startup.cs similarity index 74% rename from packages/blazor-workspace/Tests/NimbleBlazor.Tests.Acceptance/Startup.cs rename to packages/blazor-workspace/Tests/BlazorWorkspace.Testing.Acceptance/Startup.cs index 7f518500a0..82366cc3c8 100644 --- a/packages/blazor-workspace/Tests/NimbleBlazor.Tests.Acceptance/Startup.cs +++ b/packages/blazor-workspace/Tests/BlazorWorkspace.Testing.Acceptance/Startup.cs @@ -1,17 +1,10 @@ -namespace NimbleBlazor.Tests.Acceptance; +namespace BlazorWorkspace.Testing.Acceptance; /// /// Web server initialization for Blazor Server /// public sealed class Startup { - public Startup(IConfiguration configuration) - { - Configuration = configuration; - } - - public IConfiguration Configuration { get; } - public void ConfigureServices(IServiceCollection services) { services.AddRazorPages(); diff --git a/packages/blazor-workspace/Tests/SprightBlazor.Tests.Acceptance/WebHostServerFixture.cs b/packages/blazor-workspace/Tests/BlazorWorkspace.Testing.Acceptance/WebHostServerFixture.cs similarity index 67% rename from packages/blazor-workspace/Tests/SprightBlazor.Tests.Acceptance/WebHostServerFixture.cs rename to packages/blazor-workspace/Tests/BlazorWorkspace.Testing.Acceptance/WebHostServerFixture.cs index 1e6bb3f290..b71187d819 100644 --- a/packages/blazor-workspace/Tests/SprightBlazor.Tests.Acceptance/WebHostServerFixture.cs +++ b/packages/blazor-workspace/Tests/BlazorWorkspace.Testing.Acceptance/WebHostServerFixture.cs @@ -2,7 +2,7 @@ using Microsoft.AspNetCore.Hosting.Server.Features; using Xunit; -namespace SprightBlazor.Tests.Acceptance; +namespace BlazorWorkspace.Testing.Acceptance; public abstract class WebHostServerFixture : IAsyncLifetime, IDisposable { @@ -20,6 +20,8 @@ public async Task InitializeAsync() ServerAddress = new Uri(addressFeature!.Addresses.First()); } + protected abstract Startup StartupFactory(WebHostBuilderContext context); + public async Task DisposeAsync() { if (_host != null) @@ -42,5 +44,14 @@ protected virtual void Dispose(bool disposing) } } - protected abstract IHost CreateWebHost(); + private IHost CreateWebHost() + { + return new HostBuilder() + .ConfigureWebHost(webHostBuilder => webHostBuilder + .UseKestrel() + .UseStartup(StartupFactory) + .UseStaticWebAssets() + .UseUrls("http://127.0.0.1:0")) // Pick a port dynamically + .Build(); + } } diff --git a/packages/blazor-workspace/Tests/BlazorWorkspace.Testing.Acceptance/packages.lock.json b/packages/blazor-workspace/Tests/BlazorWorkspace.Testing.Acceptance/packages.lock.json new file mode 100644 index 0000000000..fa7e824863 --- /dev/null +++ b/packages/blazor-workspace/Tests/BlazorWorkspace.Testing.Acceptance/packages.lock.json @@ -0,0 +1,1069 @@ +{ + "version": 1, + "dependencies": { + "net6.0": { + "Microsoft.AspNetCore.Mvc.Testing": { + "type": "Direct", + "requested": "[6.0.29, )", + "resolved": "6.0.29", + "contentHash": "SafR+jYhWN61mCy+FJIaU/YUSGy7BtMrdc+vsRQQB5ars5qLB0Z1iNtAiFgDLd9tO5s+EQa88tAmXjzwCnpK0A==", + "dependencies": { + "Microsoft.AspNetCore.TestHost": "6.0.29", + "Microsoft.Extensions.DependencyModel": "6.0.0", + "Microsoft.Extensions.Hosting": "6.0.1" + } + }, + "Microsoft.Extensions.Configuration": { + "type": "Direct", + "requested": "[7.0.0, )", + "resolved": "7.0.0", + "contentHash": "tldQUBWt/xeH2K7/hMPPo5g8zuLc3Ro9I5d4o/XrxvxOCA2EZBtW7bCHHTc49fcBtvB8tLAb/Qsmfrq+2SJ4vA==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "7.0.0", + "Microsoft.Extensions.Primitives": "7.0.0" + } + }, + "Microsoft.NET.Test.Sdk": { + "type": "Direct", + "requested": "[16.11.0, )", + "resolved": "16.11.0", + "contentHash": "f4mbG1SUSkNWF5p7B3Y8ZxMsvKhxCmpZhdl+w6tMtLSUGE7Izi1syU6TkmKOvB2BV66pdbENConFAISOix4ohQ==", + "dependencies": { + "Microsoft.CodeCoverage": "16.11.0", + "Microsoft.TestPlatform.TestHost": "16.11.0" + } + }, + "Microsoft.Playwright": { + "type": "Direct", + "requested": "[1.42.0, 1.42.0]", + "resolved": "1.42.0", + "contentHash": "vH4dIqJFDRB8+qsoy6vWJwemXwTMDo51aYoDTNrlz+mVqbfZaeEReVdHvwbtIBwm4iADpFQf0xWRoR2pHVKbWQ==", + "dependencies": { + "Microsoft.Bcl.AsyncInterfaces": "6.0.0", + "System.ComponentModel.Annotations": "5.0.0", + "System.Text.Json": "6.0.0" + } + }, + "NI.CSharp.Analyzers": { + "type": "Direct", + "requested": "[2.0.21, 2.0.21]", + "resolved": "2.0.21", + "contentHash": "PST6c0bUeoCVmXG7raQmPZPYQlt0I1/2IFNc7KLetoG0CIxa30A21LUMPi2FLy4e5SrdEqGnLtC0D8O9MFxI6A==", + "dependencies": { + "Microsoft.CodeAnalysis.Analyzers": "3.3.3", + "Microsoft.CodeAnalysis.CSharp": "4.2.0", + "Microsoft.CodeAnalysis.NetAnalyzers": "8.0.0", + "Microsoft.VisualStudio.Threading.Analyzers": "17.2.32", + "Roslynator.Analyzers": "4.1.1", + "StyleCop.Analyzers": "1.2.0-beta.435" + } + }, + "System.ComponentModel": { + "type": "Direct", + "requested": "[4.3.0, )", + "resolved": "4.3.0", + "contentHash": "VyGn1jGRZVfxnh8EdvDCi71v3bMXrsu8aYJOwoV7SNDLVhiEqwP86pPMyRGsDsxhXAm2b3o9OIqeETfN5qfezw==", + "dependencies": { + "System.Runtime": "4.3.0" + } + }, + "xunit": { + "type": "Direct", + "requested": "[2.8.0, )", + "resolved": "2.8.0", + "contentHash": "US3a3twJziAif1kFPGdk9fALwILHxV0n1roX5j67bN/d3o4DGNLHnV3tr5ZX+uinVrzfkf0avH3zGX8JPBC0qA==", + "dependencies": { + "xunit.analyzers": "1.13.0", + "xunit.assert": "2.8.0", + "xunit.core": "[2.8.0]" + } + }, + "xunit.extensibility.execution": { + "type": "Direct", + "requested": "[2.8.0, )", + "resolved": "2.8.0", + "contentHash": "TyyrZesHB9ODZMS9c73OqiBz4x0vL944JCkSPBWW5w6PF2LlUfdfXRjjOhoIOuY6lTmEgl07rS4/Jot9mCYnpg==", + "dependencies": { + "xunit.extensibility.core": "[2.8.0]" + } + }, + "xunit.runner.visualstudio": { + "type": "Direct", + "requested": "[2.8.0, )", + "resolved": "2.8.0", + "contentHash": "mqQbS2zr8dfgSWxkNOC6UTzO8JoqpTmM5+FFn2XR/2nVmx2JvEY0YbM5pt2FmXVg9YVe+jKUPHd6KrroyCl67w==" + }, + "Microsoft.AspNetCore.Authorization": { + "type": "Transitive", + "resolved": "6.0.29", + "contentHash": "1GbePh5YLbjNJjluHPiD2Nc3Y6TSPxWIa6zDxq4vsHrFESspXwRlMD73pd/9LYwQra9+4BgWz3qUFYiBHbBKKQ==", + "dependencies": { + "Microsoft.AspNetCore.Metadata": "6.0.29", + "Microsoft.Extensions.Logging.Abstractions": "6.0.4", + "Microsoft.Extensions.Options": "6.0.0" + } + }, + "Microsoft.AspNetCore.Components": { + "type": "Transitive", + "resolved": "6.0.29", + "contentHash": "gKxEKtF2Yo0BxOALqb/C9fKAMWid69bv1wB3Gfq+ZJ+738rEg745aTgH8cYZVE+quEu+srZWJQV9HiLsgu45xA==", + "dependencies": { + "Microsoft.AspNetCore.Authorization": "6.0.29", + "Microsoft.AspNetCore.Components.Analyzers": "6.0.29" + } + }, + "Microsoft.AspNetCore.Components.Analyzers": { + "type": "Transitive", + "resolved": "6.0.29", + "contentHash": "XxaP69TMJojgBNfp0HkQXr1i2ulhxb1Snf8w1Cp2dSFMD0J+77308hNH5QD8HLkasKwTjd/ECTwKyVTO8y9ngg==" + }, + "Microsoft.AspNetCore.Components.Forms": { + "type": "Transitive", + "resolved": "6.0.29", + "contentHash": "HU+wgWqDybHYVo0d0xmj0HnsyQXUjlm5wSDjWy83XD1SxQ6bkHP51uhFOLOA8rEzCon9T5MdbTENwLQAR+j6NQ==", + "dependencies": { + "Microsoft.AspNetCore.Components": "6.0.29" + } + }, + "Microsoft.AspNetCore.Components.Web": { + "type": "Transitive", + "resolved": "6.0.29", + "contentHash": "NjOkG9RIETtEK/oQetPsXEPfONvc8yM8bW/JPWrO7bhX36Klq3U7eodQXfCe2hLhz3R16hopQ7AzfsQal6Fnlw==", + "dependencies": { + "Microsoft.AspNetCore.Components": "6.0.29", + "Microsoft.AspNetCore.Components.Forms": "6.0.29", + "Microsoft.Extensions.DependencyInjection": "6.0.1", + "Microsoft.JSInterop": "6.0.29", + "System.IO.Pipelines": "6.0.3" + } + }, + "Microsoft.AspNetCore.Metadata": { + "type": "Transitive", + "resolved": "6.0.29", + "contentHash": "NKIduYKzggjJPh00AjhTEJ9MWRUf3y67zwRVy08mB/QtctwcYS1i5Nx3u7UurcudH1J0l904IY8SXnJJ/PMszQ==" + }, + "Microsoft.AspNetCore.TestHost": { + "type": "Transitive", + "resolved": "6.0.29", + "contentHash": "5uo89gT+Zt+Dj2qQRNpLl1WwA00GQUcTYio8oGV6j5KaWnawvhqltWQm6Xd6pbfRiVyLeIP7MhqB7/5um06O8Q==", + "dependencies": { + "System.IO.Pipelines": "6.0.3" + } + }, + "Microsoft.Bcl.AsyncInterfaces": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "UcSjPsst+DfAdJGVDsu346FX0ci0ah+lw3WRtn18NUwEqRt70HaOQ7lI72vy3+1LxtqI3T5GWwV39rQSrCzAeg==" + }, + "Microsoft.CodeAnalysis.Analyzers": { + "type": "Transitive", + "resolved": "3.3.3", + "contentHash": "j/rOZtLMVJjrfLRlAMckJLPW/1rze9MT1yfWqSIbUPGRu1m1P0fuo9PmqapwsmePfGB5PJrudQLvmUOAMF0DqQ==" + }, + "Microsoft.CodeAnalysis.Common": { + "type": "Transitive", + "resolved": "4.2.0", + "contentHash": "lbusGcuE7D8FtZawQ4G++UFsRQArPzZN1GGXjPQwu3gvCbw7FXDcBq1zDZrZN1vRzPTVe1qyZMvfGhVUzs1TDg==", + "dependencies": { + "Microsoft.CodeAnalysis.Analyzers": "3.3.3", + "System.Collections.Immutable": "5.0.0", + "System.Memory": "4.5.4", + "System.Reflection.Metadata": "5.0.0", + "System.Runtime.CompilerServices.Unsafe": "6.0.0", + "System.Text.Encoding.CodePages": "6.0.0", + "System.Threading.Tasks.Extensions": "4.5.4" + } + }, + "Microsoft.CodeAnalysis.CSharp": { + "type": "Transitive", + "resolved": "4.2.0", + "contentHash": "5IDwr8zGNBmDpxtzxxZj9IHwoA6HJ1/WWT/JacqPQJ4Vz/oZXaHNlzcBPVCZRGWUw+QvVdAhCKwEyJyuAuH/wg==", + "dependencies": { + "Microsoft.CodeAnalysis.Common": "[4.2.0]" + } + }, + "Microsoft.CodeAnalysis.NetAnalyzers": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "DxiTgkCl3CGq1rYmBX2wjY7XGbxiBdL4J+/AJIAFLKy5z70NxhnVRnPghnicXZ8oF6JKVXlW3xwznRbI3ioEKg==" + }, + "Microsoft.CodeCoverage": { + "type": "Transitive", + "resolved": "16.11.0", + "contentHash": "wf6lpAeCqP0KFfbDVtfL50lr7jY1gq0+0oSphyksfLOEygMDXqnaxHK5LPFtMEhYSEtgXdNyXNnEddOqQQUdlQ==" + }, + "Microsoft.CSharp": { + "type": "Transitive", + "resolved": "4.0.1", + "contentHash": "17h8b5mXa87XYKrrVqdgZ38JefSUqLChUQpXgSnpzsM0nDOhE40FTeNWOJ/YmySGV6tG6T8+hjz6vxbknHJr6A==", + "dependencies": { + "System.Collections": "4.0.11", + "System.Diagnostics.Debug": "4.0.11", + "System.Dynamic.Runtime": "4.0.11", + "System.Globalization": "4.0.11", + "System.Linq": "4.1.0", + "System.Linq.Expressions": "4.1.0", + "System.ObjectModel": "4.0.12", + "System.Reflection": "4.1.0", + "System.Reflection.Extensions": "4.0.1", + "System.Reflection.Primitives": "4.0.1", + "System.Reflection.TypeExtensions": "4.1.0", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Extensions": "4.1.0", + "System.Runtime.InteropServices": "4.1.0", + "System.Threading": "4.0.11" + } + }, + "Microsoft.Extensions.Configuration.Abstractions": { + "type": "Transitive", + "resolved": "7.0.0", + "contentHash": "f34u2eaqIjNO9YLHBz8rozVZ+TcFiFs0F3r7nUJd7FRkVSxk8u4OpoK226mi49MwexHOR2ibP9MFvRUaLilcQQ==", + "dependencies": { + "Microsoft.Extensions.Primitives": "7.0.0" + } + }, + "Microsoft.Extensions.Configuration.Binder": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "b3ErKzND8LIC7o08QAVlKfaEIYEvLJbtmVbFZVBRXeu9YkKfSSzLZfR1SUfQPBIy9mKLhEtJgGYImkcMNaKE0A==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "6.0.0" + } + }, + "Microsoft.Extensions.Configuration.CommandLine": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "3nL1qCkZ1Oxx14ZTzgo4MmlO7tso7F+TtMZAY2jUAtTLyAcDp+EDjk3RqafoKiNaePyPvvlleEcBxh3b2Hzl1g==", + "dependencies": { + "Microsoft.Extensions.Configuration": "6.0.0", + "Microsoft.Extensions.Configuration.Abstractions": "6.0.0" + } + }, + "Microsoft.Extensions.Configuration.EnvironmentVariables": { + "type": "Transitive", + "resolved": "6.0.1", + "contentHash": "pnyXV1LFOsYjGveuC07xp0YHIyGq7jRq5Ncb5zrrIieMLWVwgMyYxcOH0jTnBedDT4Gh1QinSqsjqzcieHk1og==", + "dependencies": { + "Microsoft.Extensions.Configuration": "6.0.0", + "Microsoft.Extensions.Configuration.Abstractions": "6.0.0" + } + }, + "Microsoft.Extensions.Configuration.FileExtensions": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "V4Dth2cYMZpw3HhGw9XUDIijpI6gN+22LDt0AhufIgOppCUfpWX4483OmN+dFXRJkJLc8Tv0Q8QK+1ingT2+KQ==", + "dependencies": { + "Microsoft.Extensions.Configuration": "6.0.0", + "Microsoft.Extensions.Configuration.Abstractions": "6.0.0", + "Microsoft.Extensions.FileProviders.Abstractions": "6.0.0", + "Microsoft.Extensions.FileProviders.Physical": "6.0.0", + "Microsoft.Extensions.Primitives": "6.0.0" + } + }, + "Microsoft.Extensions.Configuration.Json": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "GJGery6QytCzS/BxJ96klgG9in3uH26KcUBbiVG/coNDXCRq6LGVVlUT4vXq34KPuM+R2av+LeYdX9h4IZOCUg==", + "dependencies": { + "Microsoft.Extensions.Configuration": "6.0.0", + "Microsoft.Extensions.Configuration.Abstractions": "6.0.0", + "Microsoft.Extensions.Configuration.FileExtensions": "6.0.0", + "Microsoft.Extensions.FileProviders.Abstractions": "6.0.0", + "System.Text.Json": "6.0.0" + } + }, + "Microsoft.Extensions.Configuration.UserSecrets": { + "type": "Transitive", + "resolved": "6.0.1", + "contentHash": "Fy8yr4V6obi7ZxvKYI1i85jqtwMq8tqyxQVZpRSkgeA8enqy/KvBIMdcuNdznlxQMZa72mvbHqb7vbg4Pyx95w==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "6.0.0", + "Microsoft.Extensions.Configuration.Json": "6.0.0", + "Microsoft.Extensions.FileProviders.Abstractions": "6.0.0", + "Microsoft.Extensions.FileProviders.Physical": "6.0.0" + } + }, + "Microsoft.Extensions.DependencyInjection": { + "type": "Transitive", + "resolved": "6.0.1", + "contentHash": "vWXPg3HJQIpZkENn1KWq8SfbqVujVD7S7vIAyFXXqK5xkf1Vho+vG0bLBCHxU36lD1cLLtmGpfYf0B3MYFi9tQ==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0", + "System.Runtime.CompilerServices.Unsafe": "6.0.0" + } + }, + "Microsoft.Extensions.DependencyInjection.Abstractions": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "xlzi2IYREJH3/m6+lUrQlujzX8wDitm4QGnUu6kUXTQAWPuZY8i+ticFJbzfqaetLA6KR/rO6Ew/HuYD+bxifg==" + }, + "Microsoft.Extensions.DependencyModel": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "TD5QHg98m3+QhgEV1YVoNMl5KtBw/4rjfxLHO0e/YV9bPUBDKntApP4xdrVtGgCeQZHVfC2EXIGsdpRNrr87Pg==", + "dependencies": { + "System.Buffers": "4.5.1", + "System.Memory": "4.5.4", + "System.Runtime.CompilerServices.Unsafe": "6.0.0", + "System.Text.Encodings.Web": "6.0.0", + "System.Text.Json": "6.0.0" + } + }, + "Microsoft.Extensions.FileProviders.Abstractions": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "0pd4/fho0gC12rQswaGQxbU34jOS1TPS8lZPpkFCH68ppQjHNHYle9iRuHeev1LhrJ94YPvzcRd8UmIuFk23Qw==", + "dependencies": { + "Microsoft.Extensions.Primitives": "6.0.0" + } + }, + "Microsoft.Extensions.FileProviders.Physical": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "QvkL7l0nM8udt3gfyu0Vw8bbCXblxaKOl7c2oBfgGy4LCURRaL9XWZX1FWJrQc43oMokVneVxH38iz+bY1sbhg==", + "dependencies": { + "Microsoft.Extensions.FileProviders.Abstractions": "6.0.0", + "Microsoft.Extensions.FileSystemGlobbing": "6.0.0", + "Microsoft.Extensions.Primitives": "6.0.0" + } + }, + "Microsoft.Extensions.FileSystemGlobbing": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "ip8jnL1aPiaPeKINCqaTEbvBFDmVx9dXQEBZ2HOBRXPD1eabGNqP/bKlsIcp7U2lGxiXd5xIhoFcmY8nM4Hdiw==" + }, + "Microsoft.Extensions.Hosting": { + "type": "Transitive", + "resolved": "6.0.1", + "contentHash": "hbmizc9KPWOacLU8Z8YMaBG6KWdZFppczYV/KwnPGU/8xebWxQxdDeJmLOgg968prb7g2oQgnp6JVLX6lgby8g==", + "dependencies": { + "Microsoft.Extensions.Configuration": "6.0.0", + "Microsoft.Extensions.Configuration.Abstractions": "6.0.0", + "Microsoft.Extensions.Configuration.Binder": "6.0.0", + "Microsoft.Extensions.Configuration.CommandLine": "6.0.0", + "Microsoft.Extensions.Configuration.EnvironmentVariables": "6.0.1", + "Microsoft.Extensions.Configuration.FileExtensions": "6.0.0", + "Microsoft.Extensions.Configuration.Json": "6.0.0", + "Microsoft.Extensions.Configuration.UserSecrets": "6.0.1", + "Microsoft.Extensions.DependencyInjection": "6.0.0", + "Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0", + "Microsoft.Extensions.FileProviders.Abstractions": "6.0.0", + "Microsoft.Extensions.FileProviders.Physical": "6.0.0", + "Microsoft.Extensions.Hosting.Abstractions": "6.0.0", + "Microsoft.Extensions.Logging": "6.0.0", + "Microsoft.Extensions.Logging.Abstractions": "6.0.0", + "Microsoft.Extensions.Logging.Configuration": "6.0.0", + "Microsoft.Extensions.Logging.Console": "6.0.0", + "Microsoft.Extensions.Logging.Debug": "6.0.0", + "Microsoft.Extensions.Logging.EventLog": "6.0.0", + "Microsoft.Extensions.Logging.EventSource": "6.0.0", + "Microsoft.Extensions.Options": "6.0.0" + } + }, + "Microsoft.Extensions.Hosting.Abstractions": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "GcT5l2CYXL6Sa27KCSh0TixsRfADUgth+ojQSD5EkzisZxmGFh7CwzkcYuGwvmXLjr27uWRNrJ2vuuEjMhU05Q==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "6.0.0", + "Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0", + "Microsoft.Extensions.FileProviders.Abstractions": "6.0.0" + } + }, + "Microsoft.Extensions.Logging": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "eIbyj40QDg1NDz0HBW0S5f3wrLVnKWnDJ/JtZ+yJDFnDj90VoPuoPmFkeaXrtu+0cKm5GRAwoDf+dBWXK0TUdg==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection": "6.0.0", + "Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0", + "Microsoft.Extensions.Logging.Abstractions": "6.0.0", + "Microsoft.Extensions.Options": "6.0.0", + "System.Diagnostics.DiagnosticSource": "6.0.0" + } + }, + "Microsoft.Extensions.Logging.Abstractions": { + "type": "Transitive", + "resolved": "6.0.4", + "contentHash": "K14wYgwOfKVELrUh5eBqlC8Wvo9vvhS3ZhIvcswV2uS/ubkTRPSQsN557EZiYUSSoZNxizG+alN4wjtdyLdcyw==" + }, + "Microsoft.Extensions.Logging.Configuration": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "ZDskjagmBAbv+K8rYW9VhjPplhbOE63xUD0DiuydZJwt15dRyoqicYklLd86zzeintUc7AptDkHn+YhhYkYo8A==", + "dependencies": { + "Microsoft.Extensions.Configuration": "6.0.0", + "Microsoft.Extensions.Configuration.Abstractions": "6.0.0", + "Microsoft.Extensions.Configuration.Binder": "6.0.0", + "Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0", + "Microsoft.Extensions.Logging": "6.0.0", + "Microsoft.Extensions.Logging.Abstractions": "6.0.0", + "Microsoft.Extensions.Options": "6.0.0", + "Microsoft.Extensions.Options.ConfigurationExtensions": "6.0.0" + } + }, + "Microsoft.Extensions.Logging.Console": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "gsqKzOEdsvq28QiXFxagmn1oRB9GeI5GgYCkoybZtQA0IUb7QPwf1WmN3AwJeNIsadTvIFQCiVK0OVIgKfOBGg==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0", + "Microsoft.Extensions.Logging": "6.0.0", + "Microsoft.Extensions.Logging.Abstractions": "6.0.0", + "Microsoft.Extensions.Logging.Configuration": "6.0.0", + "Microsoft.Extensions.Options": "6.0.0", + "System.Text.Json": "6.0.0" + } + }, + "Microsoft.Extensions.Logging.Debug": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "M9g/JixseSZATJE9tcMn9uzoD4+DbSglivFqVx8YkRJ7VVPmnvCEbOZ0AAaxsL1EKyI4cz07DXOOJExxNsUOHw==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0", + "Microsoft.Extensions.Logging": "6.0.0", + "Microsoft.Extensions.Logging.Abstractions": "6.0.0" + } + }, + "Microsoft.Extensions.Logging.EventLog": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "rlo0RxlMd0WtLG3CHI0qOTp6fFn7MvQjlrCjucA31RqmiMFCZkF8CHNbe8O7tbBIyyoLGWB1he9CbaA5iyHthg==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0", + "Microsoft.Extensions.Logging": "6.0.0", + "Microsoft.Extensions.Logging.Abstractions": "6.0.0", + "Microsoft.Extensions.Options": "6.0.0", + "System.Diagnostics.EventLog": "6.0.0" + } + }, + "Microsoft.Extensions.Logging.EventSource": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "BeDyyqt7nkm/nr+Gdk+L8n1tUT/u33VkbXAOesgYSNsxDM9hJ1NOBGoZfj9rCbeD2+9myElI6JOVVFmnzgeWQA==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0", + "Microsoft.Extensions.Logging": "6.0.0", + "Microsoft.Extensions.Logging.Abstractions": "6.0.0", + "Microsoft.Extensions.Options": "6.0.0", + "Microsoft.Extensions.Primitives": "6.0.0", + "System.Runtime.CompilerServices.Unsafe": "6.0.0", + "System.Text.Json": "6.0.0" + } + }, + "Microsoft.Extensions.Options": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "dzXN0+V1AyjOe2xcJ86Qbo233KHuLEY0njf/P2Kw8SfJU+d45HNS2ctJdnEnrWbM9Ye2eFgaC5Mj9otRMU6IsQ==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0", + "Microsoft.Extensions.Primitives": "6.0.0" + } + }, + "Microsoft.Extensions.Options.ConfigurationExtensions": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "bXWINbTn0vC0FYc9GaQTISbxhQLAMrvtbuvD9N6JelEaIS/Pr62wUCinrq5bf1WRBGczt1v4wDhxFtVFNcMdUQ==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "6.0.0", + "Microsoft.Extensions.Configuration.Binder": "6.0.0", + "Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0", + "Microsoft.Extensions.Options": "6.0.0", + "Microsoft.Extensions.Primitives": "6.0.0" + } + }, + "Microsoft.Extensions.Primitives": { + "type": "Transitive", + "resolved": "7.0.0", + "contentHash": "um1KU5kxcRp3CNuI8o/GrZtD4AIOXDk+RLsytjZ9QPok3ttLUelLKpilVPuaFT3TFjOhSibUAso0odbOaCDj3Q==", + "dependencies": { + "System.Runtime.CompilerServices.Unsafe": "6.0.0" + } + }, + "Microsoft.JSInterop": { + "type": "Transitive", + "resolved": "6.0.29", + "contentHash": "SOGezowQCY3bxL4lMFk18EbC1OlZ8ea8XJ2e+/eCKapLrarI47XqoGN9WVfAeB0QiT+dynOhAxrMWpTi2fpZPg==" + }, + "Microsoft.NETCore.Platforms": { + "type": "Transitive", + "resolved": "1.1.0", + "contentHash": "kz0PEW2lhqygehI/d6XsPCQzD7ff7gUJaVGPVETX611eadGsA3A877GdSlU0LRVMCTH/+P3o2iDTak+S08V2+A==" + }, + "Microsoft.NETCore.Targets": { + "type": "Transitive", + "resolved": "1.1.0", + "contentHash": "aOZA3BWfz9RXjpzt0sRJJMjAscAUm3Hoa4UWAfceV9UTYxgwZ1lZt5nO2myFf+/jetYQo4uTP7zS8sJY67BBxg==" + }, + "Microsoft.TestPlatform.ObjectModel": { + "type": "Transitive", + "resolved": "16.11.0", + "contentHash": "EiknJx9N9Z30gs7R+HHhki7fA8EiiM3pwD1vkw3bFsBC8kdVq/O7mHf1hrg5aJp+ASO6BoOzQueD2ysfTOy/Bg==", + "dependencies": { + "NuGet.Frameworks": "5.0.0", + "System.Reflection.Metadata": "1.6.0" + } + }, + "Microsoft.TestPlatform.TestHost": { + "type": "Transitive", + "resolved": "16.11.0", + "contentHash": "/Q+R0EcCJE8JaYCk+bGReicw/xrB0HhecrYrUcLbn95BnAlaTJrZhoLkUhvtKTAVtqX/AIKWXYtutiU/Q6QUgg==", + "dependencies": { + "Microsoft.TestPlatform.ObjectModel": "16.11.0", + "Newtonsoft.Json": "9.0.1" + } + }, + "Microsoft.VisualStudio.Threading.Analyzers": { + "type": "Transitive", + "resolved": "17.2.32", + "contentHash": "izJIEScEIBe8m96gMkox9vZE6r/Unk6giifbfRroqYJR3yESJqTkaQ707pE+jkJMqxHNT/lqBensuex90vPfPw==" + }, + "Newtonsoft.Json": { + "type": "Transitive", + "resolved": "9.0.1", + "contentHash": "U82mHQSKaIk+lpSVCbWYKNavmNH1i5xrExDEquU1i6I5pV6UMOqRnJRSlKO3cMPfcpp0RgDY+8jUXHdQ4IfXvw==", + "dependencies": { + "Microsoft.CSharp": "4.0.1", + "System.Collections": "4.0.11", + "System.Diagnostics.Debug": "4.0.11", + "System.Dynamic.Runtime": "4.0.11", + "System.Globalization": "4.0.11", + "System.IO": "4.1.0", + "System.Linq": "4.1.0", + "System.Linq.Expressions": "4.1.0", + "System.ObjectModel": "4.0.12", + "System.Reflection": "4.1.0", + "System.Reflection.Extensions": "4.0.1", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Extensions": "4.1.0", + "System.Runtime.Serialization.Primitives": "4.1.1", + "System.Text.Encoding": "4.0.11", + "System.Text.Encoding.Extensions": "4.0.11", + "System.Text.RegularExpressions": "4.1.0", + "System.Threading": "4.0.11", + "System.Threading.Tasks": "4.0.11", + "System.Xml.ReaderWriter": "4.0.11", + "System.Xml.XDocument": "4.0.11" + } + }, + "NuGet.Frameworks": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "c5JVjuVAm4f7E9Vj+v09Z9s2ZsqFDjBpcsyS3M9xRo0bEdm/LVZSzLxxNvfvAwRiiE8nwe1h2G4OwiwlzFKXlA==" + }, + "Roslynator.Analyzers": { + "type": "Transitive", + "resolved": "4.1.1", + "contentHash": "3cPVlrB1PytlO1ztZZBOExDKQWpMZgI15ZDa0BqLu0l6xv+xIRfEpqjNRcpvUy3aLxWTkPgSKZbbaO+VoFEJ1g==" + }, + "StyleCop.Analyzers": { + "type": "Transitive", + "resolved": "1.2.0-beta.435", + "contentHash": "TADk7vdGXtfTnYCV7GyleaaRTQjfoSfZXprQrVMm7cSJtJbFc1QIbWPyLvrgrfGdfHbGmUPvaN4ODKNxg2jgPQ==", + "dependencies": { + "StyleCop.Analyzers.Unstable": "1.2.0.435" + } + }, + "StyleCop.Analyzers.Unstable": { + "type": "Transitive", + "resolved": "1.2.0.435", + "contentHash": "ouwPWZxbOV3SmCZxIRqHvljkSzkCyi1tDoMzQtDb/bRP8ctASV/iRJr+A2Gdj0QLaLmWnqTWDrH82/iP+X80Lg==" + }, + "System.Buffers": { + "type": "Transitive", + "resolved": "4.5.1", + "contentHash": "Rw7ijyl1qqRS0YQD/WycNst8hUUMgrMH4FCn1nNm27M4VxchZ1js3fVjQaANHO5f3sN4isvP4a+Met9Y4YomAg==" + }, + "System.Collections": { + "type": "Transitive", + "resolved": "4.0.11", + "contentHash": "YUJGz6eFKqS0V//mLt25vFGrrCvOnsXjlvFQs+KimpwNxug9x0Pzy4PlFMU3Q2IzqAa9G2L4LsK3+9vCBK7oTg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.0.1", + "Microsoft.NETCore.Targets": "1.0.1", + "System.Runtime": "4.1.0" + } + }, + "System.Collections.Immutable": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "FXkLXiK0sVVewcso0imKQoOxjoPAj42R8HtjjbSjVPAzwDfzoyoznWxgA3c38LDbN9SJux1xXoXYAhz98j7r2g==" + }, + "System.ComponentModel.Annotations": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "dMkqfy2el8A8/I76n2Hi1oBFEbG1SfxD2l5nhwXV3XjlnOmwxJlQbYpJH4W51odnU9sARCSAgv7S3CyAFMkpYg==" + }, + "System.Diagnostics.Debug": { + "type": "Transitive", + "resolved": "4.0.11", + "contentHash": "w5U95fVKHY4G8ASs/K5iK3J5LY+/dLFd4vKejsnI/ZhBsWS9hQakfx3Zr7lRWKg4tAw9r4iktyvsTagWkqYCiw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.0.1", + "Microsoft.NETCore.Targets": "1.0.1", + "System.Runtime": "4.1.0" + } + }, + "System.Diagnostics.DiagnosticSource": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "frQDfv0rl209cKm1lnwTgFPzNigy2EKk1BS3uAvHvlBVKe5cymGyHO+Sj+NLv5VF/AhHsqPIUUwya5oV4CHMUw==", + "dependencies": { + "System.Runtime.CompilerServices.Unsafe": "6.0.0" + } + }, + "System.Diagnostics.EventLog": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "lcyUiXTsETK2ALsZrX+nWuHSIQeazhqPphLfaRxzdGaG93+0kELqpgEHtwWOlQe7+jSFnKwaCAgL4kjeZCQJnw==" + }, + "System.Diagnostics.Tools": { + "type": "Transitive", + "resolved": "4.0.1", + "contentHash": "xBfJ8pnd4C17dWaC9FM6aShzbJcRNMChUMD42I6772KGGrqaFdumwhn9OdM68erj1ueNo3xdQ1EwiFjK5k8p0g==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.0.1", + "Microsoft.NETCore.Targets": "1.0.1", + "System.Runtime": "4.1.0" + } + }, + "System.Dynamic.Runtime": { + "type": "Transitive", + "resolved": "4.0.11", + "contentHash": "db34f6LHYM0U0JpE+sOmjar27BnqTVkbLJhgfwMpTdgTigG/Hna3m2MYVwnFzGGKnEJk2UXFuoVTr8WUbU91/A==", + "dependencies": { + "System.Collections": "4.0.11", + "System.Diagnostics.Debug": "4.0.11", + "System.Globalization": "4.0.11", + "System.Linq": "4.1.0", + "System.Linq.Expressions": "4.1.0", + "System.ObjectModel": "4.0.12", + "System.Reflection": "4.1.0", + "System.Reflection.Emit": "4.0.1", + "System.Reflection.Emit.ILGeneration": "4.0.1", + "System.Reflection.Primitives": "4.0.1", + "System.Reflection.TypeExtensions": "4.1.0", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Extensions": "4.1.0", + "System.Threading": "4.0.11" + } + }, + "System.Globalization": { + "type": "Transitive", + "resolved": "4.0.11", + "contentHash": "B95h0YLEL2oSnwF/XjqSWKnwKOy/01VWkNlsCeMTFJLLabflpGV26nK164eRs5GiaRSBGpOxQ3pKoSnnyZN5pg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.0.1", + "Microsoft.NETCore.Targets": "1.0.1", + "System.Runtime": "4.1.0" + } + }, + "System.IO": { + "type": "Transitive", + "resolved": "4.1.0", + "contentHash": "3KlTJceQc3gnGIaHZ7UBZO26SHL1SHE4ddrmiwumFnId+CEHP+O8r386tZKaE6zlk5/mF8vifMBzHj9SaXN+mQ==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.0.1", + "Microsoft.NETCore.Targets": "1.0.1", + "System.Runtime": "4.1.0", + "System.Text.Encoding": "4.0.11", + "System.Threading.Tasks": "4.0.11" + } + }, + "System.IO.FileSystem": { + "type": "Transitive", + "resolved": "4.0.1", + "contentHash": "IBErlVq5jOggAD69bg1t0pJcHaDbJbWNUZTPI96fkYWzwYbN6D9wRHMULLDd9dHsl7C2YsxXL31LMfPI1SWt8w==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.0.1", + "Microsoft.NETCore.Targets": "1.0.1", + "System.IO": "4.1.0", + "System.IO.FileSystem.Primitives": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Handles": "4.0.1", + "System.Text.Encoding": "4.0.11", + "System.Threading.Tasks": "4.0.11" + } + }, + "System.IO.FileSystem.Primitives": { + "type": "Transitive", + "resolved": "4.0.1", + "contentHash": "kWkKD203JJKxJeE74p8aF8y4Qc9r9WQx4C0cHzHPrY3fv/L/IhWnyCHaFJ3H1QPOH6A93whlQ2vG5nHlBDvzWQ==", + "dependencies": { + "System.Runtime": "4.1.0" + } + }, + "System.IO.Pipelines": { + "type": "Transitive", + "resolved": "6.0.3", + "contentHash": "ryTgF+iFkpGZY1vRQhfCzX0xTdlV3pyaTTqRu2ETbEv+HlV7O6y7hyQURnghNIXvctl5DuZ//Dpks6HdL/Txgw==" + }, + "System.Linq": { + "type": "Transitive", + "resolved": "4.1.0", + "contentHash": "bQ0iYFOQI0nuTnt+NQADns6ucV4DUvMdwN6CbkB1yj8i7arTGiTN5eok1kQwdnnNWSDZfIUySQY+J3d5KjWn0g==", + "dependencies": { + "System.Collections": "4.0.11", + "System.Diagnostics.Debug": "4.0.11", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Extensions": "4.1.0" + } + }, + "System.Linq.Expressions": { + "type": "Transitive", + "resolved": "4.1.0", + "contentHash": "I+y02iqkgmCAyfbqOmSDOgqdZQ5tTj80Akm5BPSS8EeB0VGWdy6X1KCoYe8Pk6pwDoAKZUOdLVxnTJcExiv5zw==", + "dependencies": { + "System.Collections": "4.0.11", + "System.Diagnostics.Debug": "4.0.11", + "System.Globalization": "4.0.11", + "System.IO": "4.1.0", + "System.Linq": "4.1.0", + "System.ObjectModel": "4.0.12", + "System.Reflection": "4.1.0", + "System.Reflection.Emit": "4.0.1", + "System.Reflection.Emit.ILGeneration": "4.0.1", + "System.Reflection.Emit.Lightweight": "4.0.1", + "System.Reflection.Extensions": "4.0.1", + "System.Reflection.Primitives": "4.0.1", + "System.Reflection.TypeExtensions": "4.1.0", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Extensions": "4.1.0", + "System.Threading": "4.0.11" + } + }, + "System.Memory": { + "type": "Transitive", + "resolved": "4.5.4", + "contentHash": "1MbJTHS1lZ4bS4FmsJjnuGJOu88ZzTT2rLvrhW7Ygic+pC0NWA+3hgAen0HRdsocuQXCkUTdFn9yHJJhsijDXw==" + }, + "System.ObjectModel": { + "type": "Transitive", + "resolved": "4.0.12", + "contentHash": "tAgJM1xt3ytyMoW4qn4wIqgJYm7L7TShRZG4+Q4Qsi2PCcj96pXN7nRywS9KkB3p/xDUjc2HSwP9SROyPYDYKQ==", + "dependencies": { + "System.Collections": "4.0.11", + "System.Diagnostics.Debug": "4.0.11", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Threading": "4.0.11" + } + }, + "System.Reflection": { + "type": "Transitive", + "resolved": "4.1.0", + "contentHash": "JCKANJ0TI7kzoQzuwB/OoJANy1Lg338B6+JVacPl4TpUwi3cReg3nMLplMq2uqYfHFQpKIlHAUVAJlImZz/4ng==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.0.1", + "Microsoft.NETCore.Targets": "1.0.1", + "System.IO": "4.1.0", + "System.Reflection.Primitives": "4.0.1", + "System.Runtime": "4.1.0" + } + }, + "System.Reflection.Emit": { + "type": "Transitive", + "resolved": "4.0.1", + "contentHash": "P2wqAj72fFjpP6wb9nSfDqNBMab+2ovzSDzUZK7MVIm54tBJEPr9jWfSjjoTpPwj1LeKcmX3vr0ttyjSSFM47g==", + "dependencies": { + "System.IO": "4.1.0", + "System.Reflection": "4.1.0", + "System.Reflection.Emit.ILGeneration": "4.0.1", + "System.Reflection.Primitives": "4.0.1", + "System.Runtime": "4.1.0" + } + }, + "System.Reflection.Emit.ILGeneration": { + "type": "Transitive", + "resolved": "4.0.1", + "contentHash": "Ov6dU8Bu15Bc7zuqttgHF12J5lwSWyTf1S+FJouUXVMSqImLZzYaQ+vRr1rQ0OZ0HqsrwWl4dsKHELckQkVpgA==", + "dependencies": { + "System.Reflection": "4.1.0", + "System.Reflection.Primitives": "4.0.1", + "System.Runtime": "4.1.0" + } + }, + "System.Reflection.Emit.Lightweight": { + "type": "Transitive", + "resolved": "4.0.1", + "contentHash": "sSzHHXueZ5Uh0OLpUQprhr+ZYJrLPA2Cmr4gn0wj9+FftNKXx8RIMKvO9qnjk2ebPYUjZ+F2ulGdPOsvj+MEjA==", + "dependencies": { + "System.Reflection": "4.1.0", + "System.Reflection.Emit.ILGeneration": "4.0.1", + "System.Reflection.Primitives": "4.0.1", + "System.Runtime": "4.1.0" + } + }, + "System.Reflection.Extensions": { + "type": "Transitive", + "resolved": "4.0.1", + "contentHash": "GYrtRsZcMuHF3sbmRHfMYpvxZoIN2bQGrYGerUiWLEkqdEUQZhH3TRSaC/oI4wO0II1RKBPlpIa1TOMxIcOOzQ==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.0.1", + "Microsoft.NETCore.Targets": "1.0.1", + "System.Reflection": "4.1.0", + "System.Runtime": "4.1.0" + } + }, + "System.Reflection.Metadata": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "5NecZgXktdGg34rh1OenY1rFNDCI8xSjFr+Z4OU4cU06AQHUdRnIIEeWENu3Wl4YowbzkymAIMvi3WyK9U53pQ==" + }, + "System.Reflection.Primitives": { + "type": "Transitive", + "resolved": "4.0.1", + "contentHash": "4inTox4wTBaDhB7V3mPvp9XlCbeGYWVEM9/fXALd52vNEAVisc1BoVWQPuUuD0Ga//dNbA/WeMy9u9mzLxGTHQ==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.0.1", + "Microsoft.NETCore.Targets": "1.0.1", + "System.Runtime": "4.1.0" + } + }, + "System.Reflection.TypeExtensions": { + "type": "Transitive", + "resolved": "4.1.0", + "contentHash": "tsQ/ptQ3H5FYfON8lL4MxRk/8kFyE0A+tGPXmVP967cT/gzLHYxIejIYSxp4JmIeFHVP78g/F2FE1mUUTbDtrg==", + "dependencies": { + "System.Reflection": "4.1.0", + "System.Runtime": "4.1.0" + } + }, + "System.Resources.ResourceManager": { + "type": "Transitive", + "resolved": "4.0.1", + "contentHash": "TxwVeUNoTgUOdQ09gfTjvW411MF+w9MBYL7AtNVc+HtBCFlutPLhUCdZjNkjbhj3bNQWMdHboF0KIWEOjJssbA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.0.1", + "Microsoft.NETCore.Targets": "1.0.1", + "System.Globalization": "4.0.11", + "System.Reflection": "4.1.0", + "System.Runtime": "4.1.0" + } + }, + "System.Runtime": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "JufQi0vPQ0xGnAczR13AUFglDyVYt4Kqnz1AZaiKZ5+GICq0/1MH/mO/eAJHt/mHW1zjKBJd7kV26SrxddAhiw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0" + } + }, + "System.Runtime.CompilerServices.Unsafe": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "/iUeP3tq1S0XdNNoMz5C9twLSrM/TH+qElHkXWaPvuNOt+99G75NrV0OS2EqHx5wMN7popYjpc8oTjC1y16DLg==" + }, + "System.Runtime.Extensions": { + "type": "Transitive", + "resolved": "4.1.0", + "contentHash": "CUOHjTT/vgP0qGW22U4/hDlOqXmcPq5YicBaXdUR2UiUoLwBT+olO6we4DVbq57jeX5uXH2uerVZhf0qGj+sVQ==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.0.1", + "Microsoft.NETCore.Targets": "1.0.1", + "System.Runtime": "4.1.0" + } + }, + "System.Runtime.Handles": { + "type": "Transitive", + "resolved": "4.0.1", + "contentHash": "nCJvEKguXEvk2ymk1gqj625vVnlK3/xdGzx0vOKicQkoquaTBJTP13AIYkocSUwHCLNBwUbXTqTWGDxBTWpt7g==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.0.1", + "Microsoft.NETCore.Targets": "1.0.1", + "System.Runtime": "4.1.0" + } + }, + "System.Runtime.InteropServices": { + "type": "Transitive", + "resolved": "4.1.0", + "contentHash": "16eu3kjHS633yYdkjwShDHZLRNMKVi/s0bY8ODiqJ2RfMhDMAwxZaUaWVnZ2P71kr/or+X9o/xFWtNqz8ivieQ==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.0.1", + "Microsoft.NETCore.Targets": "1.0.1", + "System.Reflection": "4.1.0", + "System.Reflection.Primitives": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Handles": "4.0.1" + } + }, + "System.Runtime.Serialization.Primitives": { + "type": "Transitive", + "resolved": "4.1.1", + "contentHash": "HZ6Du5QrTG8MNJbf4e4qMO3JRAkIboGT5Fk804uZtg3Gq516S7hAqTm2UZKUHa7/6HUGdVy3AqMQKbns06G/cg==", + "dependencies": { + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0" + } + }, + "System.Text.Encoding": { + "type": "Transitive", + "resolved": "4.0.11", + "contentHash": "U3gGeMlDZXxCEiY4DwVLSacg+DFWCvoiX+JThA/rvw37Sqrku7sEFeVBBBMBnfB6FeZHsyDx85HlKL19x0HtZA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.0.1", + "Microsoft.NETCore.Targets": "1.0.1", + "System.Runtime": "4.1.0" + } + }, + "System.Text.Encoding.CodePages": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "ZFCILZuOvtKPauZ/j/swhvw68ZRi9ATCfvGbk1QfydmcXBkIWecWKn/250UH7rahZ5OoDBaiAudJtPvLwzw85A==", + "dependencies": { + "System.Runtime.CompilerServices.Unsafe": "6.0.0" + } + }, + "System.Text.Encoding.Extensions": { + "type": "Transitive", + "resolved": "4.0.11", + "contentHash": "jtbiTDtvfLYgXn8PTfWI+SiBs51rrmO4AAckx4KR6vFK9Wzf6tI8kcRdsYQNwriUeQ1+CtQbM1W4cMbLXnj/OQ==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.0.1", + "Microsoft.NETCore.Targets": "1.0.1", + "System.Runtime": "4.1.0", + "System.Text.Encoding": "4.0.11" + } + }, + "System.Text.Encodings.Web": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "Vg8eB5Tawm1IFqj4TVK1czJX89rhFxJo9ELqc/Eiq0eXy13RK00eubyU6TJE6y+GQXjyV5gSfiewDUZjQgSE0w==", + "dependencies": { + "System.Runtime.CompilerServices.Unsafe": "6.0.0" + } + }, + "System.Text.Json": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "zaJsHfESQvJ11vbXnNlkrR46IaMULk/gHxYsJphzSF+07kTjPHv+Oc14w6QEOfo3Q4hqLJgStUaYB9DBl0TmWg==", + "dependencies": { + "System.Runtime.CompilerServices.Unsafe": "6.0.0", + "System.Text.Encodings.Web": "6.0.0" + } + }, + "System.Text.RegularExpressions": { + "type": "Transitive", + "resolved": "4.1.0", + "contentHash": "i88YCXpRTjCnoSQZtdlHkAOx4KNNik4hMy83n0+Ftlb7jvV6ZiZWMpnEZHhjBp6hQVh8gWd/iKNPzlPF7iyA2g==", + "dependencies": { + "System.Collections": "4.0.11", + "System.Globalization": "4.0.11", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Extensions": "4.1.0", + "System.Threading": "4.0.11" + } + }, + "System.Threading": { + "type": "Transitive", + "resolved": "4.0.11", + "contentHash": "N+3xqIcg3VDKyjwwCGaZ9HawG9aC6cSDI+s7ROma310GQo8vilFZa86hqKppwTHleR/G0sfOzhvgnUxWCR/DrQ==", + "dependencies": { + "System.Runtime": "4.1.0", + "System.Threading.Tasks": "4.0.11" + } + }, + "System.Threading.Tasks": { + "type": "Transitive", + "resolved": "4.0.11", + "contentHash": "k1S4Gc6IGwtHGT8188RSeGaX86Qw/wnrgNLshJvsdNUOPP9etMmo8S07c+UlOAx4K/xLuN9ivA1bD0LVurtIxQ==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.0.1", + "Microsoft.NETCore.Targets": "1.0.1", + "System.Runtime": "4.1.0" + } + }, + "System.Threading.Tasks.Extensions": { + "type": "Transitive", + "resolved": "4.5.4", + "contentHash": "zteT+G8xuGu6mS+mzDzYXbzS7rd3K6Fjb9RiZlYlJPam2/hU7JCBZBVEcywNuR+oZ1ncTvc/cq0faRr3P01OVg==" + }, + "System.Xml.ReaderWriter": { + "type": "Transitive", + "resolved": "4.0.11", + "contentHash": "ZIiLPsf67YZ9zgr31vzrFaYQqxRPX9cVHjtPSnmx4eN6lbS/yEyYNr2vs1doGDEscF0tjCZFsk9yUg1sC9e8tg==", + "dependencies": { + "System.Collections": "4.0.11", + "System.Diagnostics.Debug": "4.0.11", + "System.Globalization": "4.0.11", + "System.IO": "4.1.0", + "System.IO.FileSystem": "4.0.1", + "System.IO.FileSystem.Primitives": "4.0.1", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Extensions": "4.1.0", + "System.Runtime.InteropServices": "4.1.0", + "System.Text.Encoding": "4.0.11", + "System.Text.Encoding.Extensions": "4.0.11", + "System.Text.RegularExpressions": "4.1.0", + "System.Threading.Tasks": "4.0.11", + "System.Threading.Tasks.Extensions": "4.0.0" + } + }, + "System.Xml.XDocument": { + "type": "Transitive", + "resolved": "4.0.11", + "contentHash": "Mk2mKmPi0nWaoiYeotq1dgeNK1fqWh61+EK+w4Wu8SWuTYLzpUnschb59bJtGywaPq7SmTuPf44wrXRwbIrukg==", + "dependencies": { + "System.Collections": "4.0.11", + "System.Diagnostics.Debug": "4.0.11", + "System.Diagnostics.Tools": "4.0.1", + "System.Globalization": "4.0.11", + "System.IO": "4.1.0", + "System.Reflection": "4.1.0", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Extensions": "4.1.0", + "System.Text.Encoding": "4.0.11", + "System.Threading": "4.0.11", + "System.Xml.ReaderWriter": "4.0.11" + } + }, + "xunit.abstractions": { + "type": "Transitive", + "resolved": "2.0.3", + "contentHash": "pot1I4YOxlWjIb5jmwvvQNbTrZ3lJQ+jUGkGjWE3hEFM0l5gOnBWS+H3qsex68s5cO52g+44vpGzhAt+42vwKg==" + }, + "xunit.analyzers": { + "type": "Transitive", + "resolved": "1.13.0", + "contentHash": "Pai9YnDV71/Ox14nBHB6/f62iyPyLbmUG/YYMiA4dfdFZvr0gIYE9yGxSr0i5Tr3INK75wgL2MCUNEKpeiZ2Fw==" + }, + "xunit.assert": { + "type": "Transitive", + "resolved": "2.8.0", + "contentHash": "lwf7Dy5/5HbDkaPx1YrGXCByytCEEcIn+KPI74jh2BD/RU/7RhO8c+S3k0Ph+Mr7+cLf338fl+o6UcgPCLa6PA==" + }, + "xunit.core": { + "type": "Transitive", + "resolved": "2.8.0", + "contentHash": "McSTFGTETCxLpmJKE9TWi9FtFthrRbpRrjz2V2g8sK2wRt1+JHs15vwi+B+nfftFkV9aFWIXZfzZM95TIGZNIA==", + "dependencies": { + "xunit.extensibility.core": "[2.8.0]", + "xunit.extensibility.execution": "[2.8.0]" + } + }, + "xunit.extensibility.core": { + "type": "Transitive", + "resolved": "2.8.0", + "contentHash": "eBJv9xQeY0p5z+C/L1tFjUFYqtl5pQqIEYCGTMl+MbRzA7sOlgYKwJE//vEePBp+mgBh7NjD0Qhz0liZBYM27w==", + "dependencies": { + "xunit.abstractions": "2.0.3" + } + }, + "nimbleblazor": { + "type": "Project", + "dependencies": { + "Microsoft.AspNetCore.Components.Web": "[6.0.29, )" + } + } + } + } +} \ No newline at end of file diff --git a/packages/blazor-workspace/Tests/NimbleBlazor.Tests.Acceptance/BlazorServerWebHostFixture.cs b/packages/blazor-workspace/Tests/NimbleBlazor.Tests.Acceptance/BlazorServerWebHostFixture.cs deleted file mode 100644 index 10206871f1..0000000000 --- a/packages/blazor-workspace/Tests/NimbleBlazor.Tests.Acceptance/BlazorServerWebHostFixture.cs +++ /dev/null @@ -1,18 +0,0 @@ -namespace NimbleBlazor.Tests.Acceptance; - -/// -/// Test fixture which starts up a Blazor Server web server -/// -public class BlazorServerWebHostFixture : WebHostServerFixture -{ - protected override IHost CreateWebHost() - { - return new HostBuilder() - .ConfigureWebHost(webHostBuilder => webHostBuilder - .UseKestrel() - .UseStartup() - .UseStaticWebAssets() - .UseUrls("http://127.0.0.1:0")) // Pick a port dynamically - .Build(); - } -} diff --git a/packages/blazor-workspace/Tests/NimbleBlazor.Tests.Acceptance/NimbleBlazor.Tests.Acceptance.csproj b/packages/blazor-workspace/Tests/NimbleBlazor.Tests.Acceptance/NimbleBlazor.Tests.Acceptance.csproj index 6ad6e83bbd..9487c4f12e 100644 --- a/packages/blazor-workspace/Tests/NimbleBlazor.Tests.Acceptance/NimbleBlazor.Tests.Acceptance.csproj +++ b/packages/blazor-workspace/Tests/NimbleBlazor.Tests.Acceptance/NimbleBlazor.Tests.Acceptance.csproj @@ -47,6 +47,7 @@ + diff --git a/packages/blazor-workspace/Tests/NimbleBlazor.Tests.Acceptance/NimbleBlazorWebHostServerFixture.cs b/packages/blazor-workspace/Tests/NimbleBlazor.Tests.Acceptance/NimbleBlazorWebHostServerFixture.cs new file mode 100644 index 0000000000..17d70f8e45 --- /dev/null +++ b/packages/blazor-workspace/Tests/NimbleBlazor.Tests.Acceptance/NimbleBlazorWebHostServerFixture.cs @@ -0,0 +1,15 @@ +using BlazorWorkspace.Testing.Acceptance; + +namespace NimbleBlazor.Tests.Acceptance; + +/// +/// Test fixture which starts up a Blazor Server web server +/// +public class NimbleBlazorWebHostServerFixture : WebHostServerFixture +{ + // In order for components in this assembly to be discoverable, the Startup instance must be created in this assembly. + protected override Startup StartupFactory(WebHostBuilderContext context) + { + return new Startup(); + } +} diff --git a/packages/blazor-workspace/Tests/NimbleBlazor.Tests.Acceptance/Program.cs b/packages/blazor-workspace/Tests/NimbleBlazor.Tests.Acceptance/Program.cs index bba031e698..7cdd5d1688 100644 --- a/packages/blazor-workspace/Tests/NimbleBlazor.Tests.Acceptance/Program.cs +++ b/packages/blazor-workspace/Tests/NimbleBlazor.Tests.Acceptance/Program.cs @@ -1,4 +1,6 @@ -namespace NimbleBlazor.Tests.Acceptance; +using BlazorWorkspace.Testing.Acceptance; + +namespace NimbleBlazor.Tests.Acceptance; /// /// Main entry point which spins up the web server and allows loading the Razor fixtures/pages in a browser @@ -10,7 +12,7 @@ public static void Main(string[] arguments) { var builder = WebApplication.CreateBuilder(arguments); - var startup = new Startup(builder.Configuration); + var startup = new Startup(); startup.ConfigureServices(builder.Services); var app = builder.Build(); startup.Configure(app); diff --git a/packages/blazor-workspace/Tests/NimbleBlazor.Tests.Acceptance/Shared/MainLayout.razor.cs b/packages/blazor-workspace/Tests/NimbleBlazor.Tests.Acceptance/Shared/MainLayout.razor.cs deleted file mode 100644 index df933abeb2..0000000000 --- a/packages/blazor-workspace/Tests/NimbleBlazor.Tests.Acceptance/Shared/MainLayout.razor.cs +++ /dev/null @@ -1,23 +0,0 @@ -using Microsoft.AspNetCore.Components; -using Microsoft.AspNetCore.Components.Web; -using Microsoft.JSInterop; - -namespace NimbleBlazor.Tests.Acceptance.Shared; - -/// -/// The MainLayout Component. -/// -public partial class MainLayout -{ - private Theme Theme { get; set; } = Theme.Light; - - public ErrorBoundary? ErrorBoundary { get; set; } - - [Inject] - public IJSRuntime? JSRuntime { get; set; } - - protected override void OnParametersSet() - { - ErrorBoundary?.Recover(); - } -} \ No newline at end of file diff --git a/packages/blazor-workspace/Tests/NimbleBlazor.Tests.Acceptance/SharedPlaywrightCollectionDefinition.cs b/packages/blazor-workspace/Tests/NimbleBlazor.Tests.Acceptance/SharedPlaywrightCollectionDefinition.cs index f3019290aa..ca50ead8b7 100644 --- a/packages/blazor-workspace/Tests/NimbleBlazor.Tests.Acceptance/SharedPlaywrightCollectionDefinition.cs +++ b/packages/blazor-workspace/Tests/NimbleBlazor.Tests.Acceptance/SharedPlaywrightCollectionDefinition.cs @@ -1,4 +1,5 @@ -using Xunit; +using BlazorWorkspace.Testing.Acceptance; +using Xunit; namespace NimbleBlazor.Tests.Acceptance; diff --git a/packages/blazor-workspace/Tests/NimbleBlazor.Tests.Acceptance/Tests/AcceptanceTestsBase.cs b/packages/blazor-workspace/Tests/NimbleBlazor.Tests.Acceptance/Tests/AcceptanceTestsBase.cs deleted file mode 100644 index 528cabb19f..0000000000 --- a/packages/blazor-workspace/Tests/NimbleBlazor.Tests.Acceptance/Tests/AcceptanceTestsBase.cs +++ /dev/null @@ -1,61 +0,0 @@ -using Microsoft.Playwright; -using Xunit; - -namespace NimbleBlazor.Tests.Acceptance; - -[Collection(nameof(PlaywrightFixture))] -public abstract class AcceptanceTestsBase : IClassFixture -{ - private readonly PlaywrightFixture _playwrightFixture; - private readonly BlazorServerWebHostFixture _blazorServerClassFixture; - - protected AcceptanceTestsBase( - PlaywrightFixture playwrightFixture, - BlazorServerWebHostFixture blazorServerClassFixture) - { - _playwrightFixture = playwrightFixture; - _blazorServerClassFixture = blazorServerClassFixture; - } - - private IBrowserContext BrowserContext - { - get - { - return _playwrightFixture.BrowserContext!; - } - } - - protected async Task NewPageForRouteAsync(string route) - { - var page = await BrowserContext.NewPageAsync(); - await NavigateToPageAsync(page, route); - await WaitForNimbleBlazorInitializationAsync(page); - return new AsyncDisposablePage(page); - } - - private async Task NavigateToPageAsync(IPage page, string route) - { - var address = new Uri(_blazorServerClassFixture.ServerAddress!, route).AbsoluteUri; - await page.GotoAsync(address); - } - - private async Task WaitForNimbleBlazorInitializationAsync(IPage page) - { - await page.WaitForFunctionAsync("window.NimbleBlazor && window.NimbleBlazor.calledAfterStarted === true"); - } - - protected sealed class AsyncDisposablePage : IAsyncDisposable - { - public IPage Page { get; private set; } - - public AsyncDisposablePage(IPage page) - { - Page = page; - } - - public async ValueTask DisposeAsync() - { - await Page.CloseAsync(); - } - } -} diff --git a/packages/blazor-workspace/Tests/NimbleBlazor.Tests.Acceptance/Tests/DialogTests.cs b/packages/blazor-workspace/Tests/NimbleBlazor.Tests.Acceptance/Tests/DialogTests.cs index 0706576629..b50f1b8074 100644 --- a/packages/blazor-workspace/Tests/NimbleBlazor.Tests.Acceptance/Tests/DialogTests.cs +++ b/packages/blazor-workspace/Tests/NimbleBlazor.Tests.Acceptance/Tests/DialogTests.cs @@ -1,11 +1,12 @@ -using Microsoft.Playwright; +using BlazorWorkspace.Testing.Acceptance; +using Microsoft.Playwright; using Xunit; namespace NimbleBlazor.Tests.Acceptance; -public class DialogTests : AcceptanceTestsBase +public class DialogTests : NimbleAcceptanceTestsBase { - public DialogTests(PlaywrightFixture playwrightFixture, BlazorServerWebHostFixture blazorServerClassFixture) + public DialogTests(PlaywrightFixture playwrightFixture, NimbleBlazorWebHostServerFixture blazorServerClassFixture) : base(playwrightFixture, blazorServerClassFixture) { } diff --git a/packages/blazor-workspace/Tests/NimbleBlazor.Tests.Acceptance/Tests/DrawerTests.cs b/packages/blazor-workspace/Tests/NimbleBlazor.Tests.Acceptance/Tests/DrawerTests.cs index 464c2f3f14..cad89ae218 100644 --- a/packages/blazor-workspace/Tests/NimbleBlazor.Tests.Acceptance/Tests/DrawerTests.cs +++ b/packages/blazor-workspace/Tests/NimbleBlazor.Tests.Acceptance/Tests/DrawerTests.cs @@ -1,11 +1,12 @@ -using Microsoft.Playwright; +using BlazorWorkspace.Testing.Acceptance; +using Microsoft.Playwright; using Xunit; namespace NimbleBlazor.Tests.Acceptance; -public class DrawerTests : AcceptanceTestsBase +public class DrawerTests : NimbleAcceptanceTestsBase { - public DrawerTests(PlaywrightFixture playwrightFixture, BlazorServerWebHostFixture blazorServerClassFixture) + public DrawerTests(PlaywrightFixture playwrightFixture, NimbleBlazorWebHostServerFixture blazorServerClassFixture) : base(playwrightFixture, blazorServerClassFixture) { } diff --git a/packages/blazor-workspace/Tests/NimbleBlazor.Tests.Acceptance/Tests/NimbleAcceptanceTestsBase.cs b/packages/blazor-workspace/Tests/NimbleBlazor.Tests.Acceptance/Tests/NimbleAcceptanceTestsBase.cs new file mode 100644 index 0000000000..b70ba17885 --- /dev/null +++ b/packages/blazor-workspace/Tests/NimbleBlazor.Tests.Acceptance/Tests/NimbleAcceptanceTestsBase.cs @@ -0,0 +1,18 @@ +using BlazorWorkspace.Testing.Acceptance; +using Xunit; + +namespace NimbleBlazor.Tests.Acceptance; + +public abstract class NimbleAcceptanceTestsBase : AcceptanceTestsBase, IClassFixture +{ + protected NimbleAcceptanceTestsBase( + PlaywrightFixture playwrightFixture, + NimbleBlazorWebHostServerFixture blazorServerClassFixture) + : base(playwrightFixture) + { + ServerAddress = blazorServerClassFixture.ServerAddress!; + } + + protected override Uri ServerAddress { get; } + protected override string ComponentLibraryInitializationTestJavaScript => "window.NimbleBlazor && window.NimbleBlazor.calledAfterStarted === true"; +} diff --git a/packages/blazor-workspace/Tests/NimbleBlazor.Tests.Acceptance/Tests/TableColumnMappingTests.cs b/packages/blazor-workspace/Tests/NimbleBlazor.Tests.Acceptance/Tests/TableColumnMappingTests.cs index 6c220dc348..5aed48fee6 100644 --- a/packages/blazor-workspace/Tests/NimbleBlazor.Tests.Acceptance/Tests/TableColumnMappingTests.cs +++ b/packages/blazor-workspace/Tests/NimbleBlazor.Tests.Acceptance/Tests/TableColumnMappingTests.cs @@ -1,11 +1,12 @@ +using BlazorWorkspace.Testing.Acceptance; using Microsoft.Playwright; using Xunit; namespace NimbleBlazor.Tests.Acceptance; -public class TableColumnMappingTests : AcceptanceTestsBase +public class TableColumnMappingTests : NimbleAcceptanceTestsBase { - public TableColumnMappingTests(PlaywrightFixture playwrightFixture, BlazorServerWebHostFixture blazorServerClassFixture) + public TableColumnMappingTests(PlaywrightFixture playwrightFixture, NimbleBlazorWebHostServerFixture blazorServerClassFixture) : base(playwrightFixture, blazorServerClassFixture) { } diff --git a/packages/blazor-workspace/Tests/NimbleBlazor.Tests.Acceptance/Tests/TableColumnNumberTextTests.cs b/packages/blazor-workspace/Tests/NimbleBlazor.Tests.Acceptance/Tests/TableColumnNumberTextTests.cs index dcab13fd97..1fe63801f5 100644 --- a/packages/blazor-workspace/Tests/NimbleBlazor.Tests.Acceptance/Tests/TableColumnNumberTextTests.cs +++ b/packages/blazor-workspace/Tests/NimbleBlazor.Tests.Acceptance/Tests/TableColumnNumberTextTests.cs @@ -1,11 +1,12 @@ -using Microsoft.Playwright; +using BlazorWorkspace.Testing.Acceptance; +using Microsoft.Playwright; using Xunit; namespace NimbleBlazor.Tests.Acceptance; -public class TableColumnNumberTextTests : AcceptanceTestsBase +public class TableColumnNumberTextTests : NimbleAcceptanceTestsBase { - public TableColumnNumberTextTests(PlaywrightFixture playwrightFixture, BlazorServerWebHostFixture blazorServerClassFixture) + public TableColumnNumberTextTests(PlaywrightFixture playwrightFixture, NimbleBlazorWebHostServerFixture blazorServerClassFixture) : base(playwrightFixture, blazorServerClassFixture) { } diff --git a/packages/blazor-workspace/Tests/NimbleBlazor.Tests.Acceptance/Tests/TableTests.cs b/packages/blazor-workspace/Tests/NimbleBlazor.Tests.Acceptance/Tests/TableTests.cs index c2279f79f5..7db867c826 100644 --- a/packages/blazor-workspace/Tests/NimbleBlazor.Tests.Acceptance/Tests/TableTests.cs +++ b/packages/blazor-workspace/Tests/NimbleBlazor.Tests.Acceptance/Tests/TableTests.cs @@ -1,11 +1,12 @@ -using Microsoft.Playwright; +using BlazorWorkspace.Testing.Acceptance; +using Microsoft.Playwright; using Xunit; namespace NimbleBlazor.Tests.Acceptance; -public class TableTests : AcceptanceTestsBase +public class TableTests : NimbleAcceptanceTestsBase { - public TableTests(PlaywrightFixture playwrightFixture, BlazorServerWebHostFixture blazorServerClassFixture) + public TableTests(PlaywrightFixture playwrightFixture, NimbleBlazorWebHostServerFixture blazorServerClassFixture) : base(playwrightFixture, blazorServerClassFixture) { } diff --git a/packages/blazor-workspace/Tests/NimbleBlazor.Tests.Acceptance/Tests/ThemeProviderTests.cs b/packages/blazor-workspace/Tests/NimbleBlazor.Tests.Acceptance/Tests/ThemeProviderTests.cs index 9d5055c982..63a8a90b65 100644 --- a/packages/blazor-workspace/Tests/NimbleBlazor.Tests.Acceptance/Tests/ThemeProviderTests.cs +++ b/packages/blazor-workspace/Tests/NimbleBlazor.Tests.Acceptance/Tests/ThemeProviderTests.cs @@ -1,11 +1,12 @@ -using Microsoft.Playwright; +using BlazorWorkspace.Testing.Acceptance; +using Microsoft.Playwright; using Xunit; namespace NimbleBlazor.Tests.Acceptance; -public class ThemeProviderTests : AcceptanceTestsBase +public class ThemeProviderTests : NimbleAcceptanceTestsBase { - public ThemeProviderTests(PlaywrightFixture playwrightFixture, BlazorServerWebHostFixture blazorServerClassFixture) + public ThemeProviderTests(PlaywrightFixture playwrightFixture, NimbleBlazorWebHostServerFixture blazorServerClassFixture) : base(playwrightFixture, blazorServerClassFixture) { } diff --git a/packages/blazor-workspace/Tests/NimbleBlazor.Tests.Acceptance/Tests/WaferMapTests.cs b/packages/blazor-workspace/Tests/NimbleBlazor.Tests.Acceptance/Tests/WaferMapTests.cs index fafd258c95..e00d47ecf9 100644 --- a/packages/blazor-workspace/Tests/NimbleBlazor.Tests.Acceptance/Tests/WaferMapTests.cs +++ b/packages/blazor-workspace/Tests/NimbleBlazor.Tests.Acceptance/Tests/WaferMapTests.cs @@ -1,12 +1,13 @@ -using Microsoft.Playwright; +using BlazorWorkspace.Testing.Acceptance; +using Microsoft.Playwright; using Xunit; namespace NimbleBlazor.Tests.Acceptance; -public class WaferMapTests : AcceptanceTestsBase +public class WaferMapTests : NimbleAcceptanceTestsBase { private const int RenderingTimeout = 200; - public WaferMapTests(PlaywrightFixture playwrightFixture, BlazorServerWebHostFixture blazorServerClassFixture) + public WaferMapTests(PlaywrightFixture playwrightFixture, NimbleBlazorWebHostServerFixture blazorServerClassFixture) : base(playwrightFixture, blazorServerClassFixture) { } diff --git a/packages/blazor-workspace/Tests/NimbleBlazor.Tests.Acceptance/WebHostServerFixture.cs b/packages/blazor-workspace/Tests/NimbleBlazor.Tests.Acceptance/WebHostServerFixture.cs deleted file mode 100644 index f4a209509d..0000000000 --- a/packages/blazor-workspace/Tests/NimbleBlazor.Tests.Acceptance/WebHostServerFixture.cs +++ /dev/null @@ -1,46 +0,0 @@ -using Microsoft.AspNetCore.Hosting.Server; -using Microsoft.AspNetCore.Hosting.Server.Features; -using Xunit; - -namespace NimbleBlazor.Tests.Acceptance; - -public abstract class WebHostServerFixture : IAsyncLifetime, IDisposable -{ - private IHost? _host; - - public Uri? ServerAddress { get; set; } - - public async Task InitializeAsync() - { - _host = CreateWebHost(); - await _host.StartAsync(); - - var server = _host.Services.GetRequiredService(); - var addressFeature = server.Features.Get(); - ServerAddress = new Uri(addressFeature!.Addresses.First()); - } - - public async Task DisposeAsync() - { - if (_host != null) - { - await _host.StopAsync(); - _host.Dispose(); - } - } - - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - protected virtual void Dispose(bool disposing) - { - if (disposing) - { - _host?.Dispose(); - } - } - - protected abstract IHost CreateWebHost(); -} diff --git a/packages/blazor-workspace/Tests/NimbleBlazor.Tests.Acceptance/_Imports.razor b/packages/blazor-workspace/Tests/NimbleBlazor.Tests.Acceptance/_Imports.razor index 27670ad173..12c3f0bdf5 100644 --- a/packages/blazor-workspace/Tests/NimbleBlazor.Tests.Acceptance/_Imports.razor +++ b/packages/blazor-workspace/Tests/NimbleBlazor.Tests.Acceptance/_Imports.razor @@ -7,5 +7,5 @@ @using Microsoft.AspNetCore.Components.Web.Virtualization @using Microsoft.JSInterop @using NimbleBlazor.Tests.Acceptance -@using NimbleBlazor.Tests.Acceptance.Shared +@using BlazorWorkspace.Testing.Acceptance @using NimbleBlazor.Tests.Acceptance.Pages diff --git a/packages/blazor-workspace/Tests/NimbleBlazor.Tests.Acceptance/packages.lock.json b/packages/blazor-workspace/Tests/NimbleBlazor.Tests.Acceptance/packages.lock.json index fa7e824863..30c7ab756b 100644 --- a/packages/blazor-workspace/Tests/NimbleBlazor.Tests.Acceptance/packages.lock.json +++ b/packages/blazor-workspace/Tests/NimbleBlazor.Tests.Acceptance/packages.lock.json @@ -1058,6 +1058,20 @@ "xunit.abstractions": "2.0.3" } }, + "blazorworkspace.testing.acceptance": { + "type": "Project", + "dependencies": { + "Microsoft.AspNetCore.Mvc.Testing": "[6.0.29, )", + "Microsoft.Extensions.Configuration": "[7.0.0, )", + "Microsoft.NET.Test.Sdk": "[16.11.0, )", + "Microsoft.Playwright": "[1.42.0, 1.42.0]", + "NI.CSharp.Analyzers": "[2.0.21, 2.0.21]", + "NimbleBlazor": "[1.0.0, )", + "System.ComponentModel": "[4.3.0, )", + "xunit": "[2.8.0, )", + "xunit.extensibility.execution": "[2.8.0, )" + } + }, "nimbleblazor": { "type": "Project", "dependencies": { diff --git a/packages/blazor-workspace/Tests/NimbleBlazor.Tests.Acceptance/wwwroot/css/site.css b/packages/blazor-workspace/Tests/NimbleBlazor.Tests.Acceptance/wwwroot/css/site.css index 3afadc202e..10c6ea115e 100644 --- a/packages/blazor-workspace/Tests/NimbleBlazor.Tests.Acceptance/wwwroot/css/site.css +++ b/packages/blazor-workspace/Tests/NimbleBlazor.Tests.Acceptance/wwwroot/css/site.css @@ -10,12 +10,12 @@ z-index: 1000; } - #blazor-error-ui .dismiss { - cursor: pointer; - position: absolute; - right: 0.75rem; - top: 0.5rem; - } +#blazor-error-ui .dismiss { + cursor: pointer; + position: absolute; + right: 0.75rem; + top: 0.5rem; +} .blazor-error-boundary { background: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTYiIGhlaWdodD0iNDkiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIG92ZXJmbG93PSJoaWRkZW4iPjxkZWZzPjxjbGlwUGF0aCBpZD0iY2xpcDAiPjxyZWN0IHg9IjIzNSIgeT0iNTEiIHdpZHRoPSI1NiIgaGVpZ2h0PSI0OSIvPjwvY2xpcFBhdGg+PC9kZWZzPjxnIGNsaXAtcGF0aD0idXJsKCNjbGlwMCkiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0yMzUgLTUxKSI+PHBhdGggZD0iTTI2My41MDYgNTFDMjY0LjcxNyA1MSAyNjUuODEzIDUxLjQ4MzcgMjY2LjYwNiA1Mi4yNjU4TDI2Ny4wNTIgNTIuNzk4NyAyNjcuNTM5IDUzLjYyODMgMjkwLjE4NSA5Mi4xODMxIDI5MC41NDUgOTIuNzk1IDI5MC42NTYgOTIuOTk2QzI5MC44NzcgOTMuNTEzIDI5MSA5NC4wODE1IDI5MSA5NC42NzgyIDI5MSA5Ny4wNjUxIDI4OS4wMzggOTkgMjg2LjYxNyA5OUwyNDAuMzgzIDk5QzIzNy45NjMgOTkgMjM2IDk3LjA2NTEgMjM2IDk0LjY3ODIgMjM2IDk0LjM3OTkgMjM2LjAzMSA5NC4wODg2IDIzNi4wODkgOTMuODA3MkwyMzYuMzM4IDkzLjAxNjIgMjM2Ljg1OCA5Mi4xMzE0IDI1OS40NzMgNTMuNjI5NCAyNTkuOTYxIDUyLjc5ODUgMjYwLjQwNyA1Mi4yNjU4QzI2MS4yIDUxLjQ4MzcgMjYyLjI5NiA1MSAyNjMuNTA2IDUxWk0yNjMuNTg2IDY2LjAxODNDMjYwLjczNyA2Ni4wMTgzIDI1OS4zMTMgNjcuMTI0NSAyNTkuMzEzIDY5LjMzNyAyNTkuMzEzIDY5LjYxMDIgMjU5LjMzMiA2OS44NjA4IDI1OS4zNzEgNzAuMDg4N0wyNjEuNzk1IDg0LjAxNjEgMjY1LjM4IDg0LjAxNjEgMjY3LjgyMSA2OS43NDc1QzI2Ny44NiA2OS43MzA5IDI2Ny44NzkgNjkuNTg3NyAyNjcuODc5IDY5LjMxNzkgMjY3Ljg3OSA2Ny4xMTgyIDI2Ni40NDggNjYuMDE4MyAyNjMuNTg2IDY2LjAxODNaTTI2My41NzYgODYuMDU0N0MyNjEuMDQ5IDg2LjA1NDcgMjU5Ljc4NiA4Ny4zMDA1IDI1OS43ODYgODkuNzkyMSAyNTkuNzg2IDkyLjI4MzcgMjYxLjA0OSA5My41Mjk1IDI2My41NzYgOTMuNTI5NSAyNjYuMTE2IDkzLjUyOTUgMjY3LjM4NyA5Mi4yODM3IDI2Ny4zODcgODkuNzkyMSAyNjcuMzg3IDg3LjMwMDUgMjY2LjExNiA4Ni4wNTQ3IDI2My41NzYgODYuMDU0N1oiIGZpbGw9IiNGRkU1MDAiIGZpbGwtcnVsZT0iZXZlbm9kZCIvPjwvZz48L3N2Zz4=) no-repeat 1rem/1.8rem, #b32121; @@ -23,6 +23,6 @@ color: white; } - .blazor-error-boundary::after { - content: "An error has occurred." - } +.blazor-error-boundary::after { + content: "An error has occurred." +} diff --git a/packages/blazor-workspace/Tests/SprightBlazor.Tests.Acceptance/BlazorServerWebHostFixture.cs b/packages/blazor-workspace/Tests/SprightBlazor.Tests.Acceptance/BlazorServerWebHostFixture.cs deleted file mode 100644 index 21d5a31127..0000000000 --- a/packages/blazor-workspace/Tests/SprightBlazor.Tests.Acceptance/BlazorServerWebHostFixture.cs +++ /dev/null @@ -1,18 +0,0 @@ -namespace SprightBlazor.Tests.Acceptance; - -/// -/// Test fixture which starts up a Blazor Server web server -/// -public class BlazorServerWebHostFixture : WebHostServerFixture -{ - protected override IHost CreateWebHost() - { - return new HostBuilder() - .ConfigureWebHost(webHostBuilder => webHostBuilder - .UseKestrel() - .UseStartup() - .UseStaticWebAssets() - .UseUrls("http://127.0.0.1:0")) // Pick a port dynamically - .Build(); - } -} diff --git a/packages/blazor-workspace/Tests/SprightBlazor.Tests.Acceptance/PlaywrightFixture.cs b/packages/blazor-workspace/Tests/SprightBlazor.Tests.Acceptance/PlaywrightFixture.cs deleted file mode 100644 index 703c6c42e5..0000000000 --- a/packages/blazor-workspace/Tests/SprightBlazor.Tests.Acceptance/PlaywrightFixture.cs +++ /dev/null @@ -1,44 +0,0 @@ -using Microsoft.Playwright; -using Xunit; - -namespace SprightBlazor.Tests.Acceptance; - -/// -/// Fixture to handle Playwright initialization for acceptance tests. -/// -public class PlaywrightFixture : IAsyncLifetime -{ - private IBrowser? _browser; - private IPlaywright? _playwright; - public IBrowserContext? BrowserContext { get; private set; } - - public async Task InitializeAsync() - { - _playwright = await Playwright.CreateAsync(); - _browser = await _playwright.Chromium.LaunchAsync( - new BrowserTypeLaunchOptions() - { -#if DEBUG - Headless = false, - SlowMo = 1000 -#endif - }); - BrowserContext = await _browser.NewContextAsync(new BrowserNewContextOptions { IgnoreHTTPSErrors = true }); -#if DEBUG - BrowserContext.SetDefaultTimeout(30000); -#endif - } - - public async Task DisposeAsync() - { - if (BrowserContext != null) - { - await BrowserContext.DisposeAsync(); - } - if (_browser != null) - { - await _browser.DisposeAsync(); - } - _playwright?.Dispose(); - } -} \ No newline at end of file diff --git a/packages/blazor-workspace/Tests/SprightBlazor.Tests.Acceptance/Program.cs b/packages/blazor-workspace/Tests/SprightBlazor.Tests.Acceptance/Program.cs index e90d7781ce..2163e04022 100644 --- a/packages/blazor-workspace/Tests/SprightBlazor.Tests.Acceptance/Program.cs +++ b/packages/blazor-workspace/Tests/SprightBlazor.Tests.Acceptance/Program.cs @@ -1,4 +1,6 @@ -namespace SprightBlazor.Tests.Acceptance; +using BlazorWorkspace.Testing.Acceptance; + +namespace SprightBlazor.Tests.Acceptance; /// /// Main entry point which spins up the web server and allows loading the Razor fixtures/pages in a browser @@ -10,7 +12,7 @@ public static void Main(string[] arguments) { var builder = WebApplication.CreateBuilder(arguments); - var startup = new Startup(builder.Configuration); + var startup = new Startup(); startup.ConfigureServices(builder.Services); var app = builder.Build(); startup.Configure(app); diff --git a/packages/blazor-workspace/Tests/SprightBlazor.Tests.Acceptance/Shared/MainLayout.razor b/packages/blazor-workspace/Tests/SprightBlazor.Tests.Acceptance/Shared/MainLayout.razor deleted file mode 100644 index b9118a8dba..0000000000 --- a/packages/blazor-workspace/Tests/SprightBlazor.Tests.Acceptance/Shared/MainLayout.razor +++ /dev/null @@ -1,20 +0,0 @@ -@using Microsoft.AspNetCore.Components -@using NimbleBlazor -@namespace SprightBlazor.Tests.Acceptance.Shared -@inherits LayoutComponentBase - -Spright Blazor tests - -
- - -
- @Body -
-
- -

@ex.Message

-
-
-
-
diff --git a/packages/blazor-workspace/Tests/SprightBlazor.Tests.Acceptance/Shared/MainLayout.razor.css b/packages/blazor-workspace/Tests/SprightBlazor.Tests.Acceptance/Shared/MainLayout.razor.css deleted file mode 100644 index 9c95a98781..0000000000 --- a/packages/blazor-workspace/Tests/SprightBlazor.Tests.Acceptance/Shared/MainLayout.razor.css +++ /dev/null @@ -1,6 +0,0 @@ -.root { - display: flex; - flex-direction: column; - height: 100%; - background-color: var(--ni-nimble-application-background-color); -} diff --git a/packages/blazor-workspace/Tests/SprightBlazor.Tests.Acceptance/SharedPlaywrightCollectionDefinition.cs b/packages/blazor-workspace/Tests/SprightBlazor.Tests.Acceptance/SharedPlaywrightCollectionDefinition.cs index ab0b7cf038..dd7360736a 100644 --- a/packages/blazor-workspace/Tests/SprightBlazor.Tests.Acceptance/SharedPlaywrightCollectionDefinition.cs +++ b/packages/blazor-workspace/Tests/SprightBlazor.Tests.Acceptance/SharedPlaywrightCollectionDefinition.cs @@ -1,4 +1,5 @@ -using Xunit; +using BlazorWorkspace.Testing.Acceptance; +using Xunit; namespace SprightBlazor.Tests.Acceptance; diff --git a/packages/blazor-workspace/Tests/SprightBlazor.Tests.Acceptance/SprightBlazor.Tests.Acceptance.csproj b/packages/blazor-workspace/Tests/SprightBlazor.Tests.Acceptance/SprightBlazor.Tests.Acceptance.csproj index 4f7c3fa9d0..af9f9692f3 100644 --- a/packages/blazor-workspace/Tests/SprightBlazor.Tests.Acceptance/SprightBlazor.Tests.Acceptance.csproj +++ b/packages/blazor-workspace/Tests/SprightBlazor.Tests.Acceptance/SprightBlazor.Tests.Acceptance.csproj @@ -48,6 +48,7 @@ + diff --git a/packages/blazor-workspace/Tests/SprightBlazor.Tests.Acceptance/SprightBlazorWebHostServerFixture.cs b/packages/blazor-workspace/Tests/SprightBlazor.Tests.Acceptance/SprightBlazorWebHostServerFixture.cs new file mode 100644 index 0000000000..53f1cb0499 --- /dev/null +++ b/packages/blazor-workspace/Tests/SprightBlazor.Tests.Acceptance/SprightBlazorWebHostServerFixture.cs @@ -0,0 +1,15 @@ +using BlazorWorkspace.Testing.Acceptance; + +namespace SprightBlazor.Tests.Acceptance; + +/// +/// Test fixture which starts up a Blazor Server web server +/// +public class SprightBlazorWebHostServerFixture : WebHostServerFixture +{ + // In order for components in this assembly to be discoverable, the Startup instance must be created in this assembly. + protected override Startup StartupFactory(WebHostBuilderContext context) + { + return new Startup(); + } +} diff --git a/packages/blazor-workspace/Tests/SprightBlazor.Tests.Acceptance/Startup.cs b/packages/blazor-workspace/Tests/SprightBlazor.Tests.Acceptance/Startup.cs deleted file mode 100644 index 856e6472fb..0000000000 --- a/packages/blazor-workspace/Tests/SprightBlazor.Tests.Acceptance/Startup.cs +++ /dev/null @@ -1,32 +0,0 @@ -namespace SprightBlazor.Tests.Acceptance; - -/// -/// Web server initialization for Blazor Server -/// -public sealed class Startup -{ - public Startup(IConfiguration configuration) - { - Configuration = configuration; - } - - public IConfiguration Configuration { get; } - - public void ConfigureServices(IServiceCollection services) - { - services.AddRazorPages(); - services.AddServerSideBlazor(); - } - - public void Configure(IApplicationBuilder app) - { - app.UseDeveloperExceptionPage(); - app.UseStaticFiles(); - app.UseRouting(); - app.UseEndpoints(endpoints => - { - endpoints.MapBlazorHub(); - endpoints.MapFallbackToPage("/_Host"); - }); - } -} \ No newline at end of file diff --git a/packages/blazor-workspace/Tests/SprightBlazor.Tests.Acceptance/Tests/AcceptanceTestsBase.cs b/packages/blazor-workspace/Tests/SprightBlazor.Tests.Acceptance/Tests/AcceptanceTestsBase.cs deleted file mode 100644 index 78d30c4fdc..0000000000 --- a/packages/blazor-workspace/Tests/SprightBlazor.Tests.Acceptance/Tests/AcceptanceTestsBase.cs +++ /dev/null @@ -1,61 +0,0 @@ -using Microsoft.Playwright; -using Xunit; - -namespace SprightBlazor.Tests.Acceptance; - -[Collection(nameof(PlaywrightFixture))] -public abstract class AcceptanceTestsBase : IClassFixture -{ - private readonly PlaywrightFixture _playwrightFixture; - private readonly BlazorServerWebHostFixture _blazorServerClassFixture; - - protected AcceptanceTestsBase( - PlaywrightFixture playwrightFixture, - BlazorServerWebHostFixture blazorServerClassFixture) - { - _playwrightFixture = playwrightFixture; - _blazorServerClassFixture = blazorServerClassFixture; - } - - private IBrowserContext BrowserContext - { - get - { - return _playwrightFixture.BrowserContext!; - } - } - - protected async Task NewPageForRouteAsync(string route) - { - var page = await BrowserContext.NewPageAsync(); - await NavigateToPageAsync(page, route); - await WaitForSprightBlazorInitializationAsync(page); - return new AsyncDisposablePage(page); - } - - private async Task NavigateToPageAsync(IPage page, string route) - { - var address = new Uri(_blazorServerClassFixture.ServerAddress!, route).AbsoluteUri; - await page.GotoAsync(address); - } - - private async Task WaitForSprightBlazorInitializationAsync(IPage page) - { - await page.WaitForFunctionAsync("window.SprightBlazor && window.SprightBlazor.calledAfterStarted === true"); - } - - protected sealed class AsyncDisposablePage : IAsyncDisposable - { - public IPage Page { get; private set; } - - public AsyncDisposablePage(IPage page) - { - Page = page; - } - - public async ValueTask DisposeAsync() - { - await Page.CloseAsync(); - } - } -} diff --git a/packages/blazor-workspace/Tests/SprightBlazor.Tests.Acceptance/Tests/RectangleTests.cs b/packages/blazor-workspace/Tests/SprightBlazor.Tests.Acceptance/Tests/RectangleTests.cs index c49dd21557..6c2f8e908e 100644 --- a/packages/blazor-workspace/Tests/SprightBlazor.Tests.Acceptance/Tests/RectangleTests.cs +++ b/packages/blazor-workspace/Tests/SprightBlazor.Tests.Acceptance/Tests/RectangleTests.cs @@ -1,11 +1,12 @@ -using Microsoft.Playwright; +using BlazorWorkspace.Testing.Acceptance; +using Microsoft.Playwright; using Xunit; namespace SprightBlazor.Tests.Acceptance; -public class RectangleTests : AcceptanceTestsBase +public class RectangleTests : SprightAcceptanceTestsBase { - public RectangleTests(PlaywrightFixture playwrightFixture, BlazorServerWebHostFixture blazorServerClassFixture) + public RectangleTests(PlaywrightFixture playwrightFixture, SprightBlazorWebHostServerFixture blazorServerClassFixture) : base(playwrightFixture, blazorServerClassFixture) { } diff --git a/packages/blazor-workspace/Tests/SprightBlazor.Tests.Acceptance/Tests/SprightAcceptanceTestsBase.cs b/packages/blazor-workspace/Tests/SprightBlazor.Tests.Acceptance/Tests/SprightAcceptanceTestsBase.cs new file mode 100644 index 0000000000..027ce124cb --- /dev/null +++ b/packages/blazor-workspace/Tests/SprightBlazor.Tests.Acceptance/Tests/SprightAcceptanceTestsBase.cs @@ -0,0 +1,18 @@ +using BlazorWorkspace.Testing.Acceptance; +using Xunit; + +namespace SprightBlazor.Tests.Acceptance; + +public abstract class SprightAcceptanceTestsBase : AcceptanceTestsBase, IClassFixture +{ + protected SprightAcceptanceTestsBase( + PlaywrightFixture playwrightFixture, + SprightBlazorWebHostServerFixture blazorServerClassFixture) + : base(playwrightFixture) + { + ServerAddress = blazorServerClassFixture.ServerAddress!; + } + + protected override Uri ServerAddress { get; } + protected override string ComponentLibraryInitializationTestJavaScript => "window.SprightBlazor && window.SprightBlazor.calledAfterStarted === true"; +} diff --git a/packages/blazor-workspace/Tests/SprightBlazor.Tests.Acceptance/_Imports.razor b/packages/blazor-workspace/Tests/SprightBlazor.Tests.Acceptance/_Imports.razor index 4983bda494..5d1ba94e54 100644 --- a/packages/blazor-workspace/Tests/SprightBlazor.Tests.Acceptance/_Imports.razor +++ b/packages/blazor-workspace/Tests/SprightBlazor.Tests.Acceptance/_Imports.razor @@ -7,6 +7,6 @@ @using Microsoft.AspNetCore.Components.Web.Virtualization @using Microsoft.JSInterop @using NimbleBlazor +@using BlazorWorkspace.Testing.Acceptance @using SprightBlazor.Tests.Acceptance -@using SprightBlazor.Tests.Acceptance.Shared @using SprightBlazor.Tests.Acceptance.Pages diff --git a/packages/blazor-workspace/Tests/SprightBlazor.Tests.Acceptance/packages.lock.json b/packages/blazor-workspace/Tests/SprightBlazor.Tests.Acceptance/packages.lock.json index 1bef860d9c..c8939a6687 100644 --- a/packages/blazor-workspace/Tests/SprightBlazor.Tests.Acceptance/packages.lock.json +++ b/packages/blazor-workspace/Tests/SprightBlazor.Tests.Acceptance/packages.lock.json @@ -1058,6 +1058,20 @@ "xunit.abstractions": "2.0.3" } }, + "blazorworkspace.testing.acceptance": { + "type": "Project", + "dependencies": { + "Microsoft.AspNetCore.Mvc.Testing": "[6.0.29, )", + "Microsoft.Extensions.Configuration": "[7.0.0, )", + "Microsoft.NET.Test.Sdk": "[16.11.0, )", + "Microsoft.Playwright": "[1.42.0, 1.42.0]", + "NI.CSharp.Analyzers": "[2.0.21, 2.0.21]", + "NimbleBlazor": "[1.0.0, )", + "System.ComponentModel": "[4.3.0, )", + "xunit": "[2.8.0, )", + "xunit.extensibility.execution": "[2.8.0, )" + } + }, "nimbleblazor": { "type": "Project", "dependencies": { diff --git a/packages/blazor-workspace/Tests/SprightBlazor.Tests.Acceptance/wwwroot/css/site.css b/packages/blazor-workspace/Tests/SprightBlazor.Tests.Acceptance/wwwroot/css/site.css index 3afadc202e..10c6ea115e 100644 --- a/packages/blazor-workspace/Tests/SprightBlazor.Tests.Acceptance/wwwroot/css/site.css +++ b/packages/blazor-workspace/Tests/SprightBlazor.Tests.Acceptance/wwwroot/css/site.css @@ -10,12 +10,12 @@ z-index: 1000; } - #blazor-error-ui .dismiss { - cursor: pointer; - position: absolute; - right: 0.75rem; - top: 0.5rem; - } +#blazor-error-ui .dismiss { + cursor: pointer; + position: absolute; + right: 0.75rem; + top: 0.5rem; +} .blazor-error-boundary { background: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTYiIGhlaWdodD0iNDkiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIG92ZXJmbG93PSJoaWRkZW4iPjxkZWZzPjxjbGlwUGF0aCBpZD0iY2xpcDAiPjxyZWN0IHg9IjIzNSIgeT0iNTEiIHdpZHRoPSI1NiIgaGVpZ2h0PSI0OSIvPjwvY2xpcFBhdGg+PC9kZWZzPjxnIGNsaXAtcGF0aD0idXJsKCNjbGlwMCkiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0yMzUgLTUxKSI+PHBhdGggZD0iTTI2My41MDYgNTFDMjY0LjcxNyA1MSAyNjUuODEzIDUxLjQ4MzcgMjY2LjYwNiA1Mi4yNjU4TDI2Ny4wNTIgNTIuNzk4NyAyNjcuNTM5IDUzLjYyODMgMjkwLjE4NSA5Mi4xODMxIDI5MC41NDUgOTIuNzk1IDI5MC42NTYgOTIuOTk2QzI5MC44NzcgOTMuNTEzIDI5MSA5NC4wODE1IDI5MSA5NC42NzgyIDI5MSA5Ny4wNjUxIDI4OS4wMzggOTkgMjg2LjYxNyA5OUwyNDAuMzgzIDk5QzIzNy45NjMgOTkgMjM2IDk3LjA2NTEgMjM2IDk0LjY3ODIgMjM2IDk0LjM3OTkgMjM2LjAzMSA5NC4wODg2IDIzNi4wODkgOTMuODA3MkwyMzYuMzM4IDkzLjAxNjIgMjM2Ljg1OCA5Mi4xMzE0IDI1OS40NzMgNTMuNjI5NCAyNTkuOTYxIDUyLjc5ODUgMjYwLjQwNyA1Mi4yNjU4QzI2MS4yIDUxLjQ4MzcgMjYyLjI5NiA1MSAyNjMuNTA2IDUxWk0yNjMuNTg2IDY2LjAxODNDMjYwLjczNyA2Ni4wMTgzIDI1OS4zMTMgNjcuMTI0NSAyNTkuMzEzIDY5LjMzNyAyNTkuMzEzIDY5LjYxMDIgMjU5LjMzMiA2OS44NjA4IDI1OS4zNzEgNzAuMDg4N0wyNjEuNzk1IDg0LjAxNjEgMjY1LjM4IDg0LjAxNjEgMjY3LjgyMSA2OS43NDc1QzI2Ny44NiA2OS43MzA5IDI2Ny44NzkgNjkuNTg3NyAyNjcuODc5IDY5LjMxNzkgMjY3Ljg3OSA2Ny4xMTgyIDI2Ni40NDggNjYuMDE4MyAyNjMuNTg2IDY2LjAxODNaTTI2My41NzYgODYuMDU0N0MyNjEuMDQ5IDg2LjA1NDcgMjU5Ljc4NiA4Ny4zMDA1IDI1OS43ODYgODkuNzkyMSAyNTkuNzg2IDkyLjI4MzcgMjYxLjA0OSA5My41Mjk1IDI2My41NzYgOTMuNTI5NSAyNjYuMTE2IDkzLjUyOTUgMjY3LjM4NyA5Mi4yODM3IDI2Ny4zODcgODkuNzkyMSAyNjcuMzg3IDg3LjMwMDUgMjY2LjExNiA4Ni4wNTQ3IDI2My41NzYgODYuMDU0N1oiIGZpbGw9IiNGRkU1MDAiIGZpbGwtcnVsZT0iZXZlbm9kZCIvPjwvZz48L3N2Zz4=) no-repeat 1rem/1.8rem, #b32121; @@ -23,6 +23,6 @@ color: white; } - .blazor-error-boundary::after { - content: "An error has occurred." - } +.blazor-error-boundary::after { + content: "An error has occurred." +} diff --git a/packages/nimble-components/CHANGELOG.json b/packages/nimble-components/CHANGELOG.json index dcdf11fe40..d5fc57277c 100644 --- a/packages/nimble-components/CHANGELOG.json +++ b/packages/nimble-components/CHANGELOG.json @@ -1,6 +1,36 @@ { "name": "@ni/nimble-components", "entries": [ + { + "date": "Wed, 08 May 2024 17:29:00 GMT", + "version": "28.0.4", + "tag": "@ni/nimble-components_v28.0.4", + "comments": { + "patch": [ + { + "author": "26874831+atmgrifter00@users.noreply.github.com", + "package": "@ni/nimble-components", + "commit": "7d71953ecbd516120f930e13934ee713a06e5cff", + "comment": "Don't change Select value on focusout." + } + ] + } + }, + { + "date": "Wed, 08 May 2024 16:52:33 GMT", + "version": "28.0.3", + "tag": "@ni/nimble-components_v28.0.3", + "comments": { + "none": [ + { + "author": "jattasNI@users.noreply.github.com", + "package": "@ni/nimble-components", + "commit": "3900eb4d5aa15fba8f34d6745120ba07eeb24772", + "comment": "Storybook CONTRIBUTING doc improvements" + } + ] + } + }, { "date": "Tue, 07 May 2024 20:15:55 GMT", "version": "28.0.3", diff --git a/packages/nimble-components/CHANGELOG.md b/packages/nimble-components/CHANGELOG.md index 8f47720684..633ac8b323 100644 --- a/packages/nimble-components/CHANGELOG.md +++ b/packages/nimble-components/CHANGELOG.md @@ -1,9 +1,17 @@ # Change Log - @ni/nimble-components -This log was last generated on Tue, 07 May 2024 20:15:55 GMT and should not be manually modified. +This log was last generated on Wed, 08 May 2024 17:29:00 GMT and should not be manually modified. +## 28.0.4 + +Wed, 08 May 2024 17:29:00 GMT + +### Patches + +- Don't change Select value on focusout. ([ni/nimble@7d71953](https://github.com/ni/nimble/commit/7d71953ecbd516120f930e13934ee713a06e5cff)) + ## 28.0.3 Tue, 07 May 2024 20:15:55 GMT diff --git a/packages/nimble-components/CONTRIBUTING.md b/packages/nimble-components/CONTRIBUTING.md index 7439a2fb52..438b0ea0e3 100644 --- a/packages/nimble-components/CONTRIBUTING.md +++ b/packages/nimble-components/CONTRIBUTING.md @@ -24,7 +24,7 @@ From the repo root directory: 2. Run `npm run build` 3. Run the different Nimble Components test configurations: - - To view the components and manually test behaviors in Storybook: `npm run start -w @ni-private/storybook` + - To view the components and manually test behaviors in Storybook: `npm run storybook` **Note**: You will need to refresh your browser window to see style changes made in source. @@ -41,19 +41,18 @@ Before building a new component, 3 specification documents need to be created: ## Development workflow 1. When creating new components, create the folder structure and decide how to implement the component as described in [Develop new components](#develop-new-components). -2. Run the Storybook build and start commands from the `storybook` package directory: - `npm run build` +2. Create Storybook documentation and tests for the component as described in [`@ni-private/storybook` CONTRIBUTING](/packages/storybook/CONTRIBUTING.md). - `npm run start` +3. Run the Storybook command from the repo root: `npm run storybook`. - Storybook will build its own copy of the component in a temporary folder which is separate from the normal build. + This command also causes `nimble-components` (and `spright-components`) to rebuild whenever a source file is changed so that Storybook can reflect the current state. -3. Make functional and style changes to the component. +4. Make functional and style changes to the component. The storybook will hot reload when you save changes, but the styles will not. On each save that changes `index.ts` or `styles.ts`, **you will need to refresh your browser window to see style changes**. -4. Create or update tests. +5. Create or update tests. To build and run the tests once, from the `nimble` directory run: @@ -65,17 +64,16 @@ Before building a new component, 3 specification documents need to be created: See [Unit tests](#unit-tests) for additional available commands. -5. Test out the component in each of the 3 major browsers: Chrome, Firefox, and Safari (WebKit). +6. Test out the component in each of the 3 major browsers: Chrome, Firefox, and Safari (WebKit). For developers on non-Mac platforms, Safari/WebKit can be tested via the Playwright package: - - To open Storybook with WebKit, after running the Storybook command, run the command `npm run storybook-open-webkit -w @ni/nimble-components` from the `nimble` directory. - To run the unit tests with WebKit, use the command `npm run test-webkit -w @ni/nimble-components` from the `nimble` directory. -6. Create change files for your work by running the following from the `nimble` directory: +7. Create change files for your work by running the following from the `nimble` directory: `npm run change` -7. Update the [Component Status table](./src/tests/component-status.stories.ts) to reflect the new component state. +8. Update the [Component Status table](./src/tests/component-status.stories.ts) to reflect the new component state. ## Develop new components diff --git a/packages/nimble-components/package.json b/packages/nimble-components/package.json index 27f994cd43..6a8e63c92e 100644 --- a/packages/nimble-components/package.json +++ b/packages/nimble-components/package.json @@ -1,6 +1,6 @@ { "name": "@ni/nimble-components", - "version": "28.0.3", + "version": "28.0.4", "description": "Styled web components for the NI Nimble Design System", "scripts": { "build": "npm run generate-icons && npm run generate-workers && npm run build-components && npm run bundle-components && npm run generate-scss", diff --git a/packages/nimble-components/src/select/index.ts b/packages/nimble-components/src/select/index.ts index 05fac5618b..389e3920f2 100644 --- a/packages/nimble-components/src/select/index.ts +++ b/packages/nimble-components/src/select/index.ts @@ -327,20 +327,27 @@ export class Select return; } + let optionClicked = false; if (this.open) { const captured = (e.target as HTMLElement).closest( 'option,[role=option]' ); + optionClicked = captured !== null; if (captured?.disabled) { return; } } + const currentIndex = this.openActiveIndex ?? this.selectedIndex; super.clickHandler(e); this.open = this.collapsible && !this.open; - if (!this.open && this.selectedIndex !== -1) { + if ( + !this.open + && this.selectedIndex !== currentIndex + && optionClicked + ) { this.updateValue(true); } } @@ -503,24 +510,13 @@ export class Select return true; } + this.open = false; const focusTarget = e.relatedTarget as HTMLElement; if (this.isSameNode(focusTarget)) { this.focus(); return true; } - if (!this.options?.includes(focusTarget as ListboxOption)) { - let currentActiveIndex = this.openActiveIndex ?? this.selectedIndex; - this.open = false; - if (currentActiveIndex === -1) { - currentActiveIndex = this.selectedIndex; - } - - if (this.selectedIndex !== currentActiveIndex) { - this.selectedIndex = currentActiveIndex; - this.updateValue(true); - } - } return true; } diff --git a/packages/nimble-components/src/select/tests/select.spec.ts b/packages/nimble-components/src/select/tests/select.spec.ts index 0be6a103c8..73b85c7b66 100644 --- a/packages/nimble-components/src/select/tests/select.spec.ts +++ b/packages/nimble-components/src/select/tests/select.spec.ts @@ -427,19 +427,35 @@ describe('Select', () => { await disconnect(); }); - it('when handling change event, value of select element matches what was selected in dropdown on focusout', async () => { + it('navigating to different option in dropdown and then clicking away does not change value', async () => { const { element, connect, disconnect } = await setup(); await connect(); await waitForUpdatesAsync(); const pageObject = new SelectPageObject(element); await clickAndWaitForOpen(element); - const changeValuePromise = pageObject.waitForChange(); pageObject.pressArrowDownKey(); await pageObject.clickAway(); - const selectValue = await changeValuePromise; - expect(selectValue).toBe('two'); + expect(element.value).toBe('one'); + + await disconnect(); + }); + + it('navigating to different option in dropdown and then clicking select (not dropdown) does not change value or emit change event', async () => { + const { element, connect, disconnect } = await setup(); + await connect(); + await waitForUpdatesAsync(); + const changeEvent = jasmine.createSpy(); + element.addEventListener('change', changeEvent); + const pageObject = new SelectPageObject(element); + await clickAndWaitForOpen(element); + + pageObject.pressArrowDownKey(); + pageObject.clickSelect(); + + expect(element.value).toBe('one'); + expect(changeEvent.calls.count()).toBe(0); await disconnect(); }); @@ -756,14 +772,14 @@ describe('Select', () => { expect(element.open).toBeFalse(); }); - it('filtering out current selected item and then pressing changes value and closes popup', async () => { + it('filtering out current selected item and then pressing does not change value and closes popup', async () => { const currentSelection = pageObject.getSelectedOption(); expect(currentSelection?.text).toBe('One'); expect(element.value).toBe('one'); await pageObject.openAndSetFilterText('T'); // Matches 'Two' and 'Three' pageObject.pressTabKey(); - expect(element.value).toBe('two'); // 'Two' is first option in list so it should be selected now + expect(element.value).toBe('one'); expect(element.open).toBeFalse(); }); @@ -789,14 +805,14 @@ describe('Select', () => { expect(element.open).toBeFalse(); }); - it('filtering out current selected item and then losing focus changes value and closes popup', async () => { + it('filtering out current selected item and then losing focus does not change value and closes popup', async () => { const currentSelection = pageObject.getSelectedOption(); expect(currentSelection?.text).toBe('One'); expect(element.value).toBe('one'); await pageObject.openAndSetFilterText('T'); // Matches 'Two' and 'Three' await pageObject.clickAway(); - expect(element.value).toBe('two'); // 'Two' is first option in list so it should be selected now + expect(element.value).toBe('one'); // 'Two' is first option in list so it should be selected now expect(element.open).toBeFalse(); }); diff --git a/packages/spright-components/CHANGELOG.json b/packages/spright-components/CHANGELOG.json index 3fc95cc7ea..eb149dad75 100644 --- a/packages/spright-components/CHANGELOG.json +++ b/packages/spright-components/CHANGELOG.json @@ -1,6 +1,21 @@ { "name": "@ni/spright-components", "entries": [ + { + "date": "Wed, 08 May 2024 17:29:00 GMT", + "version": "0.0.18", + "tag": "@ni/spright-components_v0.0.18", + "comments": { + "patch": [ + { + "author": "beachball", + "package": "@ni/spright-components", + "comment": "Bump @ni/nimble-components to v28.0.4", + "commit": "not available" + } + ] + } + }, { "date": "Tue, 07 May 2024 20:15:55 GMT", "version": "0.0.17", diff --git a/packages/spright-components/CHANGELOG.md b/packages/spright-components/CHANGELOG.md index 986ec3eb27..c2ab563104 100644 --- a/packages/spright-components/CHANGELOG.md +++ b/packages/spright-components/CHANGELOG.md @@ -1,9 +1,17 @@ # Change Log - @ni/spright-components -This log was last generated on Tue, 07 May 2024 20:15:55 GMT and should not be manually modified. +This log was last generated on Wed, 08 May 2024 17:29:00 GMT and should not be manually modified. +## 0.0.18 + +Wed, 08 May 2024 17:29:00 GMT + +### Patches + +- Bump @ni/nimble-components to v28.0.4 + ## 0.0.17 Tue, 07 May 2024 20:15:55 GMT diff --git a/packages/spright-components/package.json b/packages/spright-components/package.json index 85073ae287..ef5cd5e3a2 100644 --- a/packages/spright-components/package.json +++ b/packages/spright-components/package.json @@ -1,6 +1,6 @@ { "name": "@ni/spright-components", - "version": "0.0.17", + "version": "0.0.18", "description": "NI Spright Components", "scripts": { "build": "npm run build-components && npm run bundle-components", @@ -55,7 +55,7 @@ "@microsoft/fast-element": "^1.12.0", "@microsoft/fast-foundation": "^2.49.6", "@microsoft/fast-web-utilities": "^6.0.0", - "@ni/nimble-components": "28.0.3", + "@ni/nimble-components": "28.0.4", "@ni/nimble-tokens": "^6.13.5", "tslib": "^2.2.0" }, diff --git a/packages/storybook/CONTRIBUTING.md b/packages/storybook/CONTRIBUTING.md index 383712204a..9086c8dff5 100644 --- a/packages/storybook/CONTRIBUTING.md +++ b/packages/storybook/CONTRIBUTING.md @@ -1,4 +1,8 @@ -# Creating Storybook Component Documentation +# Creating Storybook Files for a Component + +This package contains Storybook files for each component which accomplish two things: +1. provide user facing documentation in the [public Nimble and Spright Storybook](https://nimble.ni.dev/storybook). +2. comprehensively test visual states of the component in [Chromatic](https://www.chromatic.com/builds?appId=60e89457a987cf003efc0a5b). ## Getting Started @@ -6,7 +10,20 @@ From the Nimble repo root directory: 1. Run `npm install` 2. Run `npm run build` -3. To view the component documentation in Storybook: `npm run start -w @ni-private/storybook` +3. To view the component documentation in Storybook: `npm run storybook` + +## Folder Structure + +Create a folder for each component under `src/nimble` or `src/spright`. The folder should match the name of the component in the corresponding `@ni/nimble-components` or `@ni/spright-components` package. + +Each folder should include the following files: + +| File | Description | +| -------------------------------- | ------------------------------------ | +| component-name.stories.ts | Contains the component hosted in Storybook. This provides a live component view for development and testing along with API documentation. | +| component-name-matrix.stories.ts | Contains a story that shows all component states for all themes hosted in Storybook. This is used by Chromatic visual tests to verify styling changes across all themes and states. | +| component-name.mdx | Contains the Storybook documentation for this component. This should provide design guidance and usage information. See below for more information about the structure of this file. | +| component-name.react.tsx | Simple React wrapper for the component to be used in Storybook MDX documentation. | ## Documentation Workflow @@ -23,7 +40,11 @@ import * as componentNameStories from './component-name.stories'; *Component description* + +## API + + ## Appearances diff --git a/packages/storybook/README.md b/packages/storybook/README.md index 64f2619f24..cca6d9f04f 100644 --- a/packages/storybook/README.md +++ b/packages/storybook/README.md @@ -2,6 +2,7 @@ Private package containing the Storybook for the Nimble repo. -## Developer Workflows +## Contributing -When running Storybook locally with `npm run start`, changes to `nimble-components` or `spright-components` will not be reflected in the stories until the modified package is rebuilt and the page is refreshed. To avoid having to manually run `npm run build-components` any time you make a change, you can instead run `npm run build-components:watch` to have the package automatically rebuild whenever it is modified. \ No newline at end of file +See `Getting Started` in [`CONTRIBUTING.md`](/CONTRIBUTING.md#getting-started) to get started with building +and running storybook. \ No newline at end of file diff --git a/packages/storybook/src/nimble/anchor-button/anchor-button.stories.ts b/packages/storybook/src/nimble/anchor-button/anchor-button.stories.ts index 291e9f56ab..5892314b4f 100644 --- a/packages/storybook/src/nimble/anchor-button/anchor-button.stories.ts +++ b/packages/storybook/src/nimble/anchor-button/anchor-button.stories.ts @@ -14,10 +14,7 @@ import { iconDescription } from '../patterns/button/doc-strings'; import { createUserSelectedThemeStory } from '../../utilities/storybook'; - -const hrefDescription = ` -In addition to \`href\`, all other attributes of \`\` are also supported, e.g. \`ping\`, \`target\`, \`type\`, etc. -`; +import { hrefDescription } from '../patterns/anchor/anchor-docs'; interface AnchorButtonArgs { label: string; @@ -55,7 +52,7 @@ const metadata: Meta = { `), argTypes: { href: { - description: hrefDescription + description: hrefDescription({ componentName: 'anchor button', includeDisable: false }) }, appearance: { options: Object.keys(ButtonAppearance), diff --git a/packages/storybook/src/nimble/anchor/anchor.stories.ts b/packages/storybook/src/nimble/anchor/anchor.stories.ts index e4f45d49fd..beb99d05b4 100644 --- a/packages/storybook/src/nimble/anchor/anchor.stories.ts +++ b/packages/storybook/src/nimble/anchor/anchor.stories.ts @@ -4,12 +4,7 @@ import { bodyFont } from '@ni/nimble-components/dist/esm/theme-provider/design-t import { anchorTag } from '@ni/nimble-components/dist/esm/anchor'; import { AnchorAppearance } from '@ni/nimble-components/dist/esm/anchor/types'; import { createUserSelectedThemeStory } from '../../utilities/storybook'; - -const hrefDescription = ` -To disable the control, remove the \`href\` attribute. - -In addition to \`href\`, all other attributes of \`\` are also supported, e.g. \`ping\`, \`target\`, \`type\`, etc. -`; +import { hrefDescription } from '../patterns/anchor/anchor-docs'; interface AnchorArgs { label: string; @@ -41,7 +36,7 @@ const metadata: Meta = { `), argTypes: { href: { - description: hrefDescription + description: hrefDescription({ componentName: 'anchor', includeDisable: true }) }, underlineHidden: { name: 'underline-hidden', diff --git a/packages/storybook/src/nimble/menu/menu.mdx b/packages/storybook/src/nimble/menu/menu.mdx index 9c2b0accff..de16d3422f 100644 --- a/packages/storybook/src/nimble/menu/menu.mdx +++ b/packages/storybook/src/nimble/menu/menu.mdx @@ -1,5 +1,6 @@ import { Controls, Canvas, Meta, Title } from '@storybook/blocks'; import TargetDocs from '../patterns/anchor/target-docs.mdx'; +import ComponentApisLink from '../patterns/docs/component-apis-link.mdx'; import * as menuStories from './menu.stories'; import { menuTag } from '@ni/nimble-components/dist/esm/menu'; import { menuItemTag } from '@ni/nimble-components/dist/esm/menu-item'; @@ -14,27 +15,53 @@ menubars commonly found at the top of many desktop application windows. A menu i choosing an item in a menu that opens a sub menu, or by invoking a command, such as Shift + F10 in Windows, that opens a context specific menu. When a user activates a choice in a menu, the menu usually closes unless the choice opened a submenu. -The supports several child elements including `
`, `
`, and . - + +## API + + + +### Menu Item + +Use the child element to execute a function when + the item is activated or to include a sub-menu. -## Child Elements + + -- - Use this child element to execute a function when - the item is activated or to include a sub-menu. To include a sub-menu, place - a as a child of a . -- - Use this child element to navigate to a URL - when the item is activated. -### Anchor Menu Item Target Configuration +### Anchor Menu Item + +Use the child element to navigate to a URL when the item is activated. + + + + +#### Anchor Menu Item Target Configuration -## Custom Header +{/* ## Usage */} + +## Examples + +### Nested Menu + +To include a sub-menu, place a as a child of a . + +For example: + + + +### Custom Header The menu can be configured to display a custom header with arbitrary content. This could include other nimble components, or even custom elements. For example: + +{/* ## Accessibility */} + +{/* ## Resources */} \ No newline at end of file diff --git a/packages/storybook/src/nimble/menu/menu.stories.ts b/packages/storybook/src/nimble/menu/menu.stories.ts index eb35c91c91..648e45d320 100644 --- a/packages/storybook/src/nimble/menu/menu.stories.ts +++ b/packages/storybook/src/nimble/menu/menu.stories.ts @@ -13,18 +13,23 @@ import { bodyFontColor } from '@ni/nimble-components/dist/esm/theme-provider/design-tokens'; import { menuTag } from '@ni/nimble-components/dist/esm/menu'; -import { createUserSelectedThemeStory } from '../../utilities/storybook'; +import { apiCategory, createUserSelectedThemeStory, disabledDescription, iconDescription, textContentDescription } from '../../utilities/storybook'; +import { hrefDescription } from '../patterns/anchor/anchor-docs'; interface MenuArgs { itemOptions: ItemArgs[]; } -interface MenuItemArgs { +interface MenuItemArgsBase { text: string; disabled: boolean; icon: boolean; } +interface MenuItemArgs extends MenuItemArgsBase { + change: () => void; +} + interface AnchorMenuItemArgs { text: string; href: string; @@ -32,7 +37,7 @@ interface AnchorMenuItemArgs { icon: boolean; } -interface ItemArgs extends MenuItemArgs { +interface ItemArgs extends MenuItemArgsBase { type: 'nimble-menu-item' | 'header' | 'hr'; } @@ -127,6 +132,14 @@ export const menu: StoryObj = { type: 'nimble-menu-item' } ] + }, + argTypes: { + itemOptions: { + name: 'default', + description: `The \`${menuTag}\` supports several child elements including \`
\`, \`
\`, \`<${menuItemTag}>\`, and \`<${anchorMenuItemTag}>\``, + control: false, + table: { category: apiCategory.slots } + } } }; @@ -143,12 +156,28 @@ export const menuItem: StoryObj = { args: { text: 'Menu Item', disabled: false, - icon: true + icon: true, + change: undefined }, argTypes: { + text: { + name: 'default', + description: textContentDescription({ componentName: 'menu item' }), + table: { category: apiCategory.slots } + }, icon: { - description: - 'When including an icon, set `slot="start"` on the icon to ensure proper styling.' + name: 'start', + description: iconDescription, + table: { category: apiCategory.slots } + }, + disabled: { + description: disabledDescription({ componentName: 'menu item' }), + table: { category: apiCategory.attributes } + }, + change: { + description: 'Fires after the menu item is selected.', + table: { category: apiCategory.events }, + control: false } } }; @@ -164,15 +193,30 @@ export const anchorMenuItem: StoryObj = { `), args: { - text: 'Menu Item', + text: 'Anchor Menu Item', href: 'https://nimble.ni.dev', disabled: false, icon: true }, argTypes: { + text: { + name: 'default', + description: textContentDescription({ componentName: 'anchor menu item' }), + table: { category: apiCategory.slots } + }, + href: { + name: 'href', + description: hrefDescription({ componentName: 'anchor menu item', includeDisable: false }), + table: { category: apiCategory.attributes } + }, icon: { - description: - 'When including an icon, set `slot="start"` on the icon to ensure proper styling.' + name: 'start', + description: iconDescription, + table: { category: apiCategory.slots } + }, + disabled: { + description: disabledDescription({ componentName: 'anchor menu item' }), + table: { category: apiCategory.attributes } } } }; diff --git a/packages/storybook/src/nimble/patterns/anchor/anchor-docs.ts b/packages/storybook/src/nimble/patterns/anchor/anchor-docs.ts new file mode 100644 index 0000000000..276a150a02 --- /dev/null +++ b/packages/storybook/src/nimble/patterns/anchor/anchor-docs.ts @@ -0,0 +1,5 @@ +export const hrefDescription = (options: { componentName: string, includeDisable: boolean }): string => `The URL that the ${options.componentName} points to. +${options.includeDisable ? 'To disable the control, remove the `href` attribute.' : ''} + +In addition to \`href\`, all other attributes of \`
\` are also supported, e.g. \`ping\`, \`target\`, \`type\`, etc. +`; diff --git a/packages/storybook/src/nimble/patterns/button/doc-strings.ts b/packages/storybook/src/nimble/patterns/button/doc-strings.ts index e25152dc81..e57b09b90a 100644 --- a/packages/storybook/src/nimble/patterns/button/doc-strings.ts +++ b/packages/storybook/src/nimble/patterns/button/doc-strings.ts @@ -1,10 +1,12 @@ +import { iconDescription as baseIconDescription } from '../../../utilities/storybook'; + export const appearanceDescription = 'This attribute affects the appearance of the button.'; export const appearanceVariantDescription = 'This attribute has no effect on buttons with a `ghost` appearance. There is no `accent` appearance-variant for the `color` UI.'; export const contentHiddenDescription = 'When set, this attribute hides the text and end icon, leaving only the start icon visible.'; -export const iconDescription = `Set \`slot="start"\` to include an icon before the text content (or instead of the content when \`content-hidden\` is set). +export const iconDescription = `${baseIconDescription} When \`content-hidden\` is set the icon will be displayed instead of the text content.
Icon Usage diff --git a/packages/storybook/src/nimble/tree-view/tree-view.stories.ts b/packages/storybook/src/nimble/tree-view/tree-view.stories.ts index a52a3a3323..ba9101dd6f 100644 --- a/packages/storybook/src/nimble/tree-view/tree-view.stories.ts +++ b/packages/storybook/src/nimble/tree-view/tree-view.stories.ts @@ -8,6 +8,7 @@ import { anchorTreeItemTag } from '@ni/nimble-components/dist/esm/anchor-tree-it import { treeViewTag } from '@ni/nimble-components/dist/esm/tree-view'; import { TreeViewSelectionMode } from '@ni/nimble-components/dist/esm/tree-view/types'; import { createUserSelectedThemeStory } from '../../utilities/storybook'; +import { hrefDescription } from '../patterns/anchor/anchor-docs'; interface TreeArgs { selectionMode: TreeViewSelectionMode; @@ -39,10 +40,6 @@ const selectionModeDescription = ` Note: Changing the selection mode does not affect which items can be selected programmatically. `; -const hrefDescription = ` -In addition to \`href\`, all other attributes of \`\` are also supported, e.g. \`ping\`, \`target\`, \`type\`, etc. -`; - const metadata: Meta = { title: 'Components/Tree View', decorators: [withActions], @@ -114,7 +111,7 @@ export const anchorTreeItem: StoryObj = { 'Cannot be selected interactively, as click/Enter causes navigation.' }, href: { - description: hrefDescription + description: hrefDescription({ componentName: 'anchor tree item', includeDisable: false }) } }, // prettier-ignore diff --git a/packages/storybook/src/utilities/storybook.ts b/packages/storybook/src/utilities/storybook.ts index 085d3c43b4..439fc977db 100644 --- a/packages/storybook/src/utilities/storybook.ts +++ b/packages/storybook/src/utilities/storybook.ts @@ -168,3 +168,7 @@ export const apiCategory = { methods: 'Methods', slots: 'Slots' } as const; + +export const iconDescription = 'Set `slot="start"` to include an icon before the text content.'; +export const disabledDescription = (options: { componentName: string }): string => `Disables the ${options.componentName}.`; +export const textContentDescription = (options: { componentName: string }): string => `The text content of the ${options.componentName}.`;