TEL Blazor Component Library Package
This readme is the repo readme, it is also used as the package readme as this is the solution for making the TELBlazor.Components package. There is also a cicd readme in the workflow folder.
The MVCBlazor repo readme has exploration of various of the choices and alternatives to what is implemented here, which may be useful along with the other blazor repos, when developing for this repo.
There are specific readmes within the solution for topics like components and cicd
Progressive Blazor components, intended for a Hosted Blazor Webassembly architecture with prerendering. They provide clientside functionality with the ability to produce static prerendered html. The prerendered html is written to have server-side interactvity via form posts and fallback mechanism to support browsers without javascript enabled.
Bottom file see tree diagram of solution
Easy viewing of TELBlazor Repo ReadMe (best with Markdown Reader Chrome extension)
View Packaged Dev Showcase Code
- Visual Studio 2022 (Community or higher)
- .NET 8 SDK version 8.0.407 or later (see global.json file in the solution)
- Node.js 18+ and npm
- Git configured with your credentials
- PowerShell 5.1+
⚠️ Important: All commands in this guide require PowerShell running as Administrator
- Get the repo: open powershell as admin,
cd
to where you keep your repos. Rungit clone https://github.com/TechnologyEnhancedLearning/TELBlazor.git
- Create local gitignored configuration files from templates: open the project in Visual Studio
- search template
- create a copy of each template removing the '.template' post fix
- search template
- Create GitHub Personal Access Token (PAT) for consuming TEL git hosted nuget packages :
- go to your GitHub profile tokens section
- SelectPersonal access tokens → Tokens classic → Generate new token (classic)
- give it a Note, e.g. 'TEL Package Access' (we will be storing it as the env var 'TEL_GIT_PACKAGES_TOKEN')
- set the expiration date to something reasonable (e.g. 90 days)
- select the scopes you need for the token
- as a minimum select
read:packages
and you may wish to increase the expiration date. - if you want to publish packages you will need
write:packages
anddelete:packages
but this is not recommended for development
- as a minimum select
- generate token
- copy the token immediately (it will not be accessible again)
- Set system wide environment variables (useful for future projects too):
- open Start, type 'Environment Variables', and select Edit the system environment variables
- in the System Properties window, select Environment Variables
- under System variables, select New
- enter the variable names and variable values as follows:
- GITHUB_USERNAME / [Your GitHub username]
- TEL_GIT_PACKAGES_TOKEN / [The copied token]
- then select OK
- select OK again to close all dialogs.
- Restore Nuget, Npm, Tooling, playwright and build:
- run a new admin powershell terminal in the TELBlazor repo root
- run the following commands
#1. Restore dotnet clean dotnet restore #2. Nuget TEL Git Feed setups dotnet nuget add source "https://nuget.pkg.github.com/TechnologyEnhancedLearning/index.json" ` --name "github" ` --username $env:GITHUB_USERNAME ` --password $env:TEL_GIT_PACKAGES_TOKEN ` --store-password-in-clear-text # 3. Restore .NET CLI tools (Playwright, report manager for code coverage) Write-Output "Restore Tools" dotnet tool restore # 4. Install Node dependencies (gulp, playwright, frontend libs) Write-Output "Restore Node" npm install # 5. Build solution or run other commands as needed Write-Output "Build solution without build package, using project references instead of local package or remote package" dotnet build # 6. Setup playwright Write-Output "Playwright setup" & ".\TELBlazor.Components.ShowCase.E2ETests\bin\Debug\net8.0\playwright.ps1" install
The project should now work. See other sections for what projects to run, and configuration.
⚠️ read the contribution section before creating a branch or commits⚠️
It is recommended you check setup by reading this section and making sure packages can be created and consumed and all tests pass.
- Branch naming rules
⚠️ commit names are used to generate the package version, repo version and change log so much be correct⚠️ Commit Naming Rules- e.g.
'docs(readme): added detail on commit rules'
Commit conventions
- e.g.
File | Description | Variable | Purpose |
---|---|---|---|
runsettings | configures playwrights | headless, tracing | make tests more detailed or visible or run faster |
nuget.config | overwritten in cicd so feel free to change it | Remote and local telblazor nuget sources | Comment in/out depending which source you need |
Package.Settings.Props | Used by CICD can receive environment variables or msbuild parameters | NugetPackagesOutputPath UseTELBlazorComponentsProjectReference TELBlazorPackageVersion DisablePackageGeneration | For CICD |
Package.Settings.Props.local | overwrite package.settings.props locally | NugetPackagesOutputPath | Where you want your package creating |
Package.Settings.Props.local | overwrite package.settings.props locally | UseTELBlazorComponentsProjectReference | For quick development use the project reference instead of a package |
Package.Settings.Props.local | overwrite package.settings.props locally | TELBlazorPackageVersion | local package version you're creating or consuming |
Package.Settings.Props.local | overwrite package.settings.props locally | DisablePackageGeneration | Stops package creation on build. |
appsettings | Serilog configuration |
Nb. It is recommended not to build the solution with package generation enabled and project reference disabled at the same time. Nb. Creating your package outside of the project can be convenient for other local solutions consuming it.
- depending on whether your consuming a package or using a project reference set package.settings.props.local UseTELBlazorComponentsProjectReference to what you want
- run wasmserverhost to see the showcase as blazor wasm prerendered
- run wasmstaticclient to see pure wasm site
- to build a package
- nuget config
- ensure the feed is still set to local
<add key="TELBlazorPackageSource" value="%LOCAL_PACKAGES_PATH%" />
- ensure the feed is still set to local
- package.settings.props.local to create package
- NugetPackagesOutputPath -> 'LOCAL_PACKAGES_PATH'
- UseTELBlazorComponentsProjectReference -> 'true'
- TELBlazorPackageVersion -> '9.9.9-local' or something higher than you have
- DisablePackageGeneration -> 'false'
- delete .lock files
- build solution
- change package.settings.props.local to consume package
- UseTELBlazorComponentsProjectReference -> 'false'
- DisablePackageGeneration -> 'true'
- build solution
- nuget config
- you can use the test runner
- runsettings allows configuration of headless and tracing
- packagesettings.props sets thresholds
- running at solution level ./run-tests-and-report-with-env-values.ps1 (see in the file for specific arguments you may want to set)
- will produce a test coverage site [your repo folder]/TELBlazor/CoverageReport/index.html
- then look at CoverageReport in solution root and you can bookmark index.html to see your coverage
- E2E project has a Reports folder for tracings
- Similarly run-tests-and-report-using-local-props.ps1 runs just using your local props file
- appsettings.Development can be set in the E2E Host to log to the Logs folder at project route, see template
- If you don't want to wait for the pipeline to fail your commit names and for pushes to accidently expose your secrets: you may want to add
-
gitguardian from confluence docs (follow it to the letter) gitguardian global setup instructions
-
and add a pre-commit and push hook (you need both as you cannot lint what hasn't yet been commit) you can add these to your git templates if you want them for every repo, or just to this repos pre- push- commits, or you can be lazy and add them into the gitguardian hook
-
you will need git commitlint globally (angular because it goes with the versioning tool for repo versioning)
npm install -g @commitlint/cli @commitlint/config-angular
-
You can put into your pre-push, pre-commit hook, commit-ms, or into the gitguardian hooks some logic like the below.
#### --- Commitlint Logic (force local config) --- REPO_ROOT=$(git rev-parse --show-toplevel) CONFIG_PATH="$REPO_ROOT/.commitlintrc.json" echo "COMMIT_MSG_FILE is one msg behind it is only set to the commit your trying to commit after the commit succeeds so this script is one behind" echo "so would work best in prepush template" echo "To fix squash out the commit following renaming and renaming commit_editmsg and if pushed to remote git push --force" COMMIT_MSG_FILE="$REPO_ROOT/.git/COMMIT_EDITMSG" # Check if the local .commitlintrc.json exists in the repository root if [ -f "$CONFIG_PATH" ]; then echo "✅ Local .commitlintrc.json found at: $CONFIG_PATH. Running commitlint..." echo "⚠️ if commit lint fails in precommit its actually reading previous commit name you need to reset or squash make a new commit and change .git/COMMIT_EDITMSG to something that would pass. ⚠️" if command -v npx &> /dev/null; then cd "$REPO_ROOT" || exit 1 # Debug: Print the commit message file content if [ -f "$COMMIT_MSG_FILE" ]; then echo "Commit message content:" cat "$COMMIT_MSG_FILE" else echo "❌ Commit message file not found!" exit 1 fi # Run commitlint, explicitly pointing to the local config and providing the commit message via stdin OUTPUT1=$(npx.cmd --no -- commitlint --config=".commitlintrc.json" --edit="$COMMIT_MSG_FILE" 2>&1) EXIT_CODE1=$? # echo "!!!!!!!!!!! OUTPUT1" # echo "$OUTPUT1" # OUTPUT2=$(npx.cmd --no -- commitlint --config=".commitlintrc.json" --from=origin/master --to=HEAD 2>&1) # EXIT_CODE2=$? # echo "!!!!!!!!!!! OUTPUT2" # echo "$OUTPUT2" # OUTPUT3=$(npx.cmd --no -- commitlint --config=".commitlintrc.json" --from-last-tag 2>&1) # EXIT_CODE3=$? # echo "!!!!!!!!!!! OUTPUT3" # echo "$OUTPUT3" #if [ "$EXIT_CODE1" -ne 0 ] || [ "$EXIT_CODE2" -ne 0 ] || [ "$EXIT_CODE3" -ne 0 ]; then if [ "$EXIT_CODE1" -ne 0 ]; then echo "❌ Commitlint failed:" echo "$OUTPUT1" exit 1 else echo "✅ Commitlint passed!" fi else echo "⚠️ npx not found. Please ensure Node.js and npm are installed to use commitlint." # Optionally fail here # exit 1 fi else echo "ℹ️ No local .commitlintrc.json found in $REPO_ROOT. Skipping commitlint." fi ```
-
- delete local TELBlazor.Components packages
- check TELBlazorPackageVersion has been incremented
- delete .lock files
- clean the solution
- check environment values in props and nuget.config
- restore nuget packages
- restore the solution
- if still not working delete bin and obj
- if still not working, restart Visual Studio
- if there are still issues its easier to problem solve by using a random very high TELBlazor.Components package version number and ensuring it fails and says it found the source but not the version
- git commit names can be caught locally
- if they are not
- fetch, pull and squash before the change and then
git push origin <your_branch_name> --force
- fetch, pull and squash before the change and then
- select a production version of the package Package list for TELBlazor.Component on git
- set up CSS references and dependency injection using lean host examples WasmServerHost, WasmServerHost.Client and WasmStaticClient from the repo and ShowCase project for how to include the package.
- you will need a copy of nhsuk.css and a reference see gulp in the previously mentioned projects
- see setup notes for instructions on getting a git nuget token for consuming the package.
- there is a readme in the CICD
- a DevShowCase site is created using a DevPackage and the same in production
- the dev pipeline also publishes a coverage report
-
Repo TELBlazor
-
TELBlazor.Components
- this is a blazor component library
-
TELBlazor.Components.UnitTests
- Bunit template from bunit site, configured to use Xunit
-
TELBlazor.Components.ShowCase.E2ETests
- NUnit Playwright Test project
-
TELBlazor.Components.ShowCase.Shared
- this is a set of example pages to showcase the blazor component and to enable testing with E2E
-
TELBlazor.Components.ShowCase.E2ETests.WasmServerHost
- Wasm host
-
TELBlazor.Components.ShowCase.E2ETests.WasmServerHost.Client
- Wasm hosted
-
TELBlazor.Components.ShowCase.WasmStaticClient
- Wasm standalone
- For more detailed dependency injected logging see MVCBlazor project
- it is not render auto per components because the intention is to be used in MVC views.
- Xunit is used with Bunit and Nunit with playwright, either could be changed so that they are using the same and this could be done in future as the libraries improve but currently each is being used with the recommend tool it is designed for though both support the others tool.
- not using data-testid="TELButton" because we should use aria selectors. We may change this later (first rule of aria dont use aria).
- e.g. data-attribute-telblazorcomponentname="TelBlazorButton"
- not using guid id as i have elsewhere either [Parameter] public string ElementId { get; set; } = $"tel-button-{Guid.NewGuid():N}";
- various things have been cut from mvcblazor so it is worth returning to for potential solutions if developing this solution MVCBlazor repo
Viewed best raw ReadMe see chrome
Description | File Structure |
---|---|
┣ TELBlazor | |
Test coverage from cicd or .ps1 | ┣ AllTestResults |
Convenient in solution location | ┣ CICDPackageLocation |
Test report site from cicd or .ps1 viewably locally or Dev Report | ┣ CoverageReport |
gh-pages site publish folder | ┣ docs |
Sets centralised solution a report thresholds | ┣ Directory.Build.props, |
Centralised nuget packages | ┣ Directory.Packages.props |
CICD setting .net version | ┣ global.json |
Uses environment variables to set packed package location locally or remote | ┣ nuget.config |
Centralised npm packages used with gulp and for testing | ┣ package.json |
Linting config for branch and commit names | ┣ .releaserc.json, .commitlintrc.json |
Useful for running tests and generating test report locally | ┣ run-tests-and-report-with-env-values.ps1 |
Env Setup | ┣ PackageSettings.props |
Env Setup, testing, package or project reference | ┣ PackageSettings.props.local |
The package create on build | ┣ TELBlazor.Components |
All using in imports so can add components by assembly | ┣ _Imports.razor |
┣ Components | |
Standard components made to TEL and NoJS requirements | ┣ BaseComponents |
┣ TELButton.razor | |
Only to support main component TELButton | ┗ TELButtonSubComponent.razor |
Useful components for development | ┗ TestComponents |
┣ Core | |
┣ Compliance | |
Create a contract of accessibility | ┗ IAccessibleComponent.cs |
┣ Configuration | |
┣ ITELBlazorBaseComponentConfiguration.cs | |
Logging, NoJS bool | ┗ TELBlazorBaseComponentConfiguration.cs |
┣ DI | |
┣ Enums | |
Enum of css styles for testing and setting component | ┗ TELButtonStyle.cs |
┣ Services | |
┗ HelperServices | |
┗ ILogLevelSwitcherService.cs | |
Custom component base with configuration injected | ┗ TELComponentBase.cs |
┗ TELBlazorPackageVersion | |
┣ TELBlazorPackageVersionInformation.razor | |
Programmatically generate via gulp csproj package versions | ┗ VersionInfo.cs |
┣ TELBlazor.Components.ShowCase.E2ETests | |
Enables run blazor pages in E2E | ┣ BlazeWright |
┣ BlazorApplicationFactory.cs | |
┣ BlazorPageExtensions.cs | |
┗ BlazorPageTest.cs | |
┣ Helpers | |
Enables using attributes to run same tests with different viewports and browsers | ┣ BrowserHelper.cs |
┗ ViewportHelper.cs | |
┣ Pages | |
Structure to mirror ShowCase | ┣ BaseComponentPages |
Check NoJs, in view, functionality | ┗ TELButtonPageTests.cs |
┣ ComponentPages | |
┗ TestComponentPages | |
┣ Reports | |
┣ SnapShots | |
┗ TestDoubles | |
Serverside so can have prerender behaviour for nojs lean host | ┣ TELBlazor.Components.ShowCase.E2ETests.WasmServerHost |
┣ TELBlazor.Components.ShowCase.E2ETests.WasmServerHost | |
┣ _Imports.razor | |
┣ App.razor | |
┗ Program.cs | |
Clientside for the host | ┗ TELBlazor.Components.ShowCase.E2ETests.WasmServerHost.Client |
┣ _Imports.razor | |
┣ App.razor | |
┣ Program.cs | |
┗ Routes.razor | |
ShowCase is an example of implementation also provides site for E2E and showcase | ┣ TELBlazor.Components.ShowCase.Shared |
┣ _Imports.razor | |
┣ DI | |
┣ Layouts | |
┣ ComponentLayouts | |
┣ ComponentNavMenu.razor | |
┣ ComponentPageLayout.razor | |
┗ ShowCase.razor | |
┗ MainLayout.razor | |
┣ Pages | |
┣ ComponentPages | |
┣ BaseComponentPages | |
┗ TELButtonPage.razor | |
┗ TestComponentPages | |
┣ CssSourceCheckerPage.razor | |
┗ LogLevelSwitcherPage.razor | |
┣ Error.razor | |
┗ Home.razor | |
┗ Services | |
┗ HelperServices | |
┗ SerilogLogLevelSwitcher.cs | |
Published to create gh-pages DevShowCase ShowCase | ┣ TELBlazor.Components.ShowCase.WasmStaticClient |
┣ _Imports.razor | |
┣ App.razor | |
┣ Program.cs | |
┗ Routes.razor | |
┣ TELBlazor.Components.UnitTests | |
┣ _Imports.razor | |
┣ Components | |
┣ BaseComponents | |
Axe and functionality test, does not simulate nojs or browser | ┗ TELButtonTests.razor |
┗ TestComponents | |
┣ Core | |
┣ DI | |
┣ DI.cs | |
┗ FallbackServiceProvider.cs | |
┣ HtmlComparisons | |
┗ TestDoubles |