Skip to content

[Sprint 3] Add UI component tests, Profile page, and RoleClaimsHelper#60

Closed
mpaulosky wants to merge 3 commits into
sprint/3-mongodb-persistencefrom
squad/59-ui-component-tests-profile-roleclaimshelper
Closed

[Sprint 3] Add UI component tests, Profile page, and RoleClaimsHelper#60
mpaulosky wants to merge 3 commits into
sprint/3-mongodb-persistencefrom
squad/59-ui-component-tests-profile-roleclaimshelper

Conversation

@mpaulosky

Copy link
Copy Markdown
Owner

Summary

Closes #59

Working as Ralph (Meta-coordinator)

Adds UI component coverage gate, Auth UI tests, Profile page component, NavMenu refactor, and RoleClaimsHelper with comprehensive unit tests.

Changes

  • src/Web/Components/Pages/Profile.razor — new Profile page
  • src/Web/Security/RoleClaimsHelper.cs — role claims mapping
  • tests/Unit.Tests/Components/ — NavMenu, Profile, and Auth component tests
  • tests/Unit.Tests/Security/RoleClaimsHelperTests.cs

Checklist

Copilot AI review requested due to automatic review settings April 19, 2026 20:48
@mpaulosky
mpaulosky force-pushed the sprint/3-mongodb-persistence branch from b271a7c to 5f32bf1 Compare April 19, 2026 20:50

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

@mpaulosky

Copy link
Copy Markdown
Owner Author

🏛️ Aragorn — Architecture Review

Verdict: ❌ NEEDS_CHANGES (3 blocking items, 2 non-blocking)


Gate Checklist

Gate Status Notes
Branch naming squad/* squad/59-ui-component-tests-profile-roleclaimshelper
Closes #N link Closes #59
Conventional commit format test: add component coverage gate and auth UI tests
CI green ⚠️ Only Copilot-agent checks ran; squad-test.yml does not trigger on sprint/** base branches. No build/test validation.
No merge conflicts mergeable_state: "dirty" — merge conflicts present. Branch cannot be merged until resolved.
Tests authored Gimli-style coverage present: NavMenuTests.cs, ProfileTests.cs, RoleClaimsHelperTests.cs, ResultTests.cs

Code Quality

The changes are substantial (1408 additions, 120 deletions, 15 files). The overall direction is sound — UI refactor to Tailwind, RoleClaimsHelper extraction, Profile page, and component test coverage. But several issues must be addressed:


🔴 BLOCKING — 1: Merge Conflicts

mergeable_state: "dirty". The sprint branch has moved ahead of this feature branch. Rebase or merge sprint/3-mongodb-persistence into the feature branch and resolve conflicts before review can proceed.


🔴 BLOCKING — 2: Missing Copyright Headers (Decision #2)

New .cs files are missing the mandatory 7-line copyright header (Decision #2, implemented PR #7):

  • src/Web/Security/RoleClaimsHelper.cs — no header
  • src/Web/Properties/AssemblyInfo.cs — no header

All .cs files must begin with:

//=======================================================
//Copyright (c) {year}. All rights reserved.
//File Name :     {filename}
//Company :       mpaulosky
//Author :        Matthew Paulosky
//Solution Name : MyBlog
//Project Name :  {project}
//=======================================================

🔴 BLOCKING — 3: Incorrect Agent Attribution

PR body states Working as Ralph (Meta-coordinator). Ralph is the work monitor/coordinator — not a domain implementer. This PR contains:

  • Blazor UI changes → Legolas domain
  • Security/auth helper → Gandalf domain
  • Test additions → Gimli domain

The work attribution should reflect the primary implementer(s). This is a process concern for future squad routing, not a code defect, but it should be corrected in the PR description.


🟡 NON-BLOCKING — 1: Duplicate InternalsVisibleTo in AssemblyInfo.cs

[assembly: InternalsVisibleTo("MyBlog.Unit.Tests")]
[assembly: InternalsVisibleTo("Unit.Tests")]

Both entries reference the same test project (different namespace resolutions). Confirm which assembly name is authoritative and remove the duplicate to avoid confusion.


🟡 NON-BLOCKING — 2: PR Body Path Inconsistency

PR body states src/Web/Components/Pages/Profile.razor but the actual file is at src/Web/Features/UserManagement/Profile.razor. Update the PR description to match the actual path.


Positive Observations

  • RoleClaimsHelper design is clean: configurable via Auth0:RoleClaimTypes, defensively defaults to well-known claim types, handles JSON array expansion correctly
  • AuthorizeView guards are preserved in the new NavMenu (critical — noted in Aragorn history as a previous concern)
  • Theme switching via CSS classes is a good approach for Tailwind + Blazor
  • The @implements IDisposable pattern on NavMenu is correct for NavigationManager event subscription cleanup

Required Actions (Blocking)

  1. Resolve merge conflicts — rebase onto sprint/3-mongodb-persistence
  2. Add copyright headers to RoleClaimsHelper.cs and AssemblyInfo.cs
  3. Update PR description — correct the Working as attribution

Per rejection protocol, fixes should be routed as follows:

  • Merge conflicts + copyright headers → Sam (backend/infra on existing branch)
  • PR description update → author or any agent

🔄 CHANGES_REQUESTED — Routing fix cycle

PR author (@mpaulosky) — per process, fixes should be pushed to squad/59-ui-component-tests-profile-roleclaimshelper. Once resolved, request re-review.

Co-authored-by: Copilot 223556219+Copilot@users.noreply.github.com

@mpaulosky

Copy link
Copy Markdown
Owner Author

Aragorn — PR Gate Review: NEEDS_CHANGES ❌

This PR has 3 blocking issues that must be resolved before merge:

  1. Merge conflicts — base branch has diverged. Run git pull origin sprint/2-cqrs-mediatr and resolve.
  2. Missing copyright headers — 2 new .cs files lack the standard header. Add at the top of each file:
    // Copyright (c) MyBlog Contributors. All rights reserved.
    // Licensed under the MIT License. See LICENSE file in the project root for full license information.
  3. Wrong attribution — Commit message attributes work to 'Ralph' (meta-monitor), but the actual author is you (@mpaulosky). Update to reflect the real contributor.

Systemic note: squad-test.yml does not trigger on sprint/** branches — CI validation was skipped. A follow-up issue will expand CI triggers to sprint branches.

Once these 3 items are resolved, re-request review.

@mpaulosky mpaulosky left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Aragorn — Architecture Gate Review (PR #60)

Verdict: ❌ NEEDS CHANGES (2 blocking items)


✅ What's Good

  • RoleClaimsHelper.cs — Design is solid. Configurable claim types via Auth0:RoleClaimTypes, JSON array expansion, comma-split fallback, deduplication, ordered output. Program.cs wiring via PostConfigure<OpenIdConnectOptions> is correct.
  • Profile.razor — Blazor conventions correct: [CascadingParameter] for AuthenticationState, OnInitializedAsync, [Authorize] attribute, private helper methods.
  • NavMenu.razor — AuthorizeView guards preserved ✅. Pure-CSS peer toggle for mobile. Theme/dark mode integration looks correct.
  • RoleClaimsHelperTests.cs[Theory]/[InlineData] used correctly; covers JSON array, comma-split, plain string.
  • NavMenuTests.cs / ProfileTests.cs — bUnit BunitContext base, [Fact], TestAuthorizationService mocking. Coverage is solid.
  • TestAuthorizationService.cs — Handles DenyAnonymousAuthorizationRequirement and RolesAuthorizationRequirement correctly.

❌ Blocking Issues

1. Merge conflicts — mergeStateStatus: DIRTY

The PR branch is conflicting with sprint/3-mongodb-persistence. Rebase or merge the target branch and resolve conflicts before this can land.

2. Missing copyright headers on all 8 new C# files (Decision #2)

Files missing headers:

  • src/Web/Security/RoleClaimsHelper.cs
  • src/Web/Properties/AssemblyInfo.cs
  • tests/Unit.Tests/Components/Layout/NavMenuTests.cs
  • tests/Unit.Tests/Components/RazorSmokeTests.cs
  • tests/Unit.Tests/Features/UserManagement/ProfileTests.cs
  • tests/Unit.Tests/ResultTests.cs
  • tests/Unit.Tests/Security/RoleClaimsHelperTests.cs
  • tests/Unit.Tests/Testing/TestAuthorizationService.cs

Required format:

//=======================================================
//Copyright (c) 2026. All rights reserved.
//File Name :     {filename}
//Company :       mpaulosky
//Author :        Matthew Paulosky
//Solution Name : MyBlog
//Project Name :  {Web|Unit.Tests}
//=======================================================

⚠️ Non-Blocking

  • Duplicate InternalsVisibleTo in AssemblyInfo.cs: both MyBlog.Unit.Tests and Unit.Tests listed. Canonical is MyBlog.Unit.Tests — remove the bare Unit.Tests entry.
  • PR body path says Components/Pages/Profile.razor but actual path is Features/UserManagement/Profile.razor.

Copilot review has been re-requested. Resolve conflicts + add copyright headers to unblock.

- Remove redundant 2025 copyright blocks from 5 test files
- Keep single clean 2026 copyright header per file
- Complies with PR #60 review feedback

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

@mpaulosky mpaulosky left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗡️ Code Review — Aragorn, Lead Developer

Verdict: REQUEST CHANGES — Do not merge. This PR has regressions and a stale base.

After a full diff analysis across all 15 changed files — including a direct comparison against sprint/3-mongodb-persistence HEAD — I've found that the sprint branch has since advanced beyond this PR's base in several places and is actively superior. Merging as-is would regress code that's already been improved.


🔴 CRITICAL — Build Failure

RazorSmokeTests.cs references deleted components

Counter_Increments_WhenButtonClicked (line ~43) and Weather_LoadsForecasts (line ~53) both Render<Counter>() and Render<Weather>() — but these Razor components were deleted in PR #6 (Decision #1). This PR would fail to compile.

Fix: Remove both test methods and using MyBlog.Web.Components.Shared; if Counter/Weather are its only consumers. The sprint branch's version of RazorSmokeTests.cs already does not include these tests.


🔴 CRITICAL — Merge Conflicts (mergeable_state: dirty)

This branch forked from an early commit of sprint/3-mongodb-persistence. The sprint branch has since evolved substantially. A git diff between the two branches reveals the PR would regress the following already-committed improvements:

File What the sprint branch has What this PR would overwrite with
Profile.razor _sensitiveClaimTypes filter (removes nonce, c_hash, at_hash, aud, etc. from claims display) No filter — all sensitive OIDC internal claims shown to user
NavMenu.razor @inject ILogger<NavMenu> Logger + Logger.LogError(ex, ...) in catch Logger removed; catch { } is empty — silent exception swallow
NavMenu.razor Hamburger label has role="button" + tabindex="0" (accessibility) Both attributes removed
Program.cs Copyright header present Copyright header absent
All test .cs files Copyright headers present (per Decision #2) All headers absent

The author must rebase onto the latest sprint/3-mongodb-persistence and resolve all conflicts, keeping the sprint branch's improvements where they exist.


🔴 CRITICAL — Security Regression (Profile.razor)

Removing _sensitiveClaimTypes causes the profile page to display OIDC protocol claims (nonce, c_hash, at_hash, iat, exp, nbf, aud, azp, auth_time) directly in the UI. While these aren't secrets, they expose internal token structure unnecessarily and are confusing to end users. The sprint branch already solved this. Do not remove that filter.


🟡 MAJOR — Policy Violations (Decision #2: Copyright Headers)

All new .cs files must have the 7-line copyright block per Decision #2. These files in the PR lack headers entirely:

  • src/Web/Security/RoleClaimsHelper.cs
  • src/Web/Properties/AssemblyInfo.cs
  • tests/Unit.Tests/Components/Layout/NavMenuTests.cs
  • tests/Unit.Tests/Components/RazorSmokeTests.cs
  • tests/Unit.Tests/Features/UserManagement/ProfileTests.cs
  • tests/Unit.Tests/ResultTests.cs
  • tests/Unit.Tests/Security/RoleClaimsHelperTests.cs
  • tests/Unit.Tests/Testing/TestAuthorizationService.cs

Note: the sprint branch's versions of the test files already have these headers. After rebasing, the conflicts should resolve this automatically.


🟡 MAJOR — AssemblyInfo.cs Has Duplicate InternalsVisibleTo

[assembly: InternalsVisibleTo("MyBlog.Unit.Tests")]
[assembly: InternalsVisibleTo("Unit.Tests")]

The canonical test project assembly name (confirmed by <RootNamespace>MyBlog.Unit.Tests</RootNamespace> in the .csproj) is MyBlog.Unit.Tests. Remove the bare "Unit.Tests" entry — it points to a non-existent assembly.


🟡 MAJOR — NavMenu.razor: Silent Exception Swallowing

The PR removes Logger.LogError(ex, ...) from both catch blocks in OnLocationChanged and SyncThemeFromJs, leaving bare catch { }. The sprint branch already logs these errors. Exception swallowing without logging makes theme/navigation failures invisible — keep the logger. This is fixed by the rebase, but explicitly flagged so it's not re-introduced.


🟡 MAJOR — Accessibility Regression in NavMenu.razor

The PR removes role="button" and tabindex="0" from the hamburger menu <label>. The sprint branch has these. Screen readers and keyboard-only users need role="button" on a <label> used as a button. Do not remove these attributes.


🟡 MAJOR — Package Version Regression in Unit.Tests.csproj

The PR introduces older package versions than what's already on the sprint branch:

Package Sprint branch PR branch
coverlet.collector 10.0.0 6.0.4
Microsoft.NET.Test.Sdk 18.4.0 17.14.1
xunit.runner.visualstudio 3.1.5 3.1.4

This will be resolved by rebasing, but confirms the PR is stale.


🔵 MINOR — PR Description Path Mismatch

PR body says src/Web/Components/Pages/Profile.razor. Actual location: src/Web/Features/UserManagement/Profile.razor (correct VSA placement ✅). Update the description to match.


🔵 MINOR — CI Coverage Validation Gap

squad-test.yml does not trigger on sprint/** branches. No build or test CI ran against this PR — all 8 check runs are Copilot agent jobs. The Counter/Weather build failure would have caught immediately with CI. Tracking this separately (see squad-test.yml trigger conditions).


✅ What's Good

  • RoleClaimsHelper design is architecturally sound: configurable Auth0:RoleClaimTypes, JSON array/CSV expansion, deduplication all correct.
  • Profile.razor is correctly placed in Features/UserManagement/ (VSA compliant).
  • PostConfigure<OpenIdConnectOptions> pattern in Program.cs for Auth0 role claims is correct.
  • TestAuthorizationService implementation is well-designed and reusable.
  • @implements IDisposable on NavMenu is correctly implemented — Dispose() unregisters LocationChanged (confirmed at line 195).
  • .razor files not having copyright headers is correct per charter rule #6.

Required Before Merge

  1. Rebase onto latest sprint/3-mongodb-persistence and resolve all conflicts
  2. After rebase, verify Counter/Weather tests are gone (or remove manually if they survive the merge)
  3. Restore _sensitiveClaimTypes filter in Profile.razor
  4. Add copyright headers to RoleClaimsHelper.cs and AssemblyInfo.cs (test file headers should be resolved by rebase)
  5. Remove duplicate InternalsVisibleTo("Unit.Tests") from AssemblyInfo.cs
  6. Keep ILogger<NavMenu> and exception logging in NavMenu.razor
  7. Keep accessibility attributes (role="button", tabindex="0") on hamburger label
  8. Update PR description with correct file path

— Aragorn 🗡️

@mpaulosky
mpaulosky force-pushed the squad/59-ui-component-tests-profile-roleclaimshelper branch from 55fbde1 to c006ac8 Compare April 20, 2026 16:18
@github-actions github-actions Bot added the squad Squad triage inbox — Lead will assign to a member label Apr 20, 2026
@github-actions

Copy link
Copy Markdown
Contributor

🏗️ PR Added to Squad Triage Queue

This PR has been labeled with squad and added to the triage queue.

Next steps:

  • The squad Lead will review and assign to an appropriate team member
  • A squad:member label will be added after triage

If you know which squad member should handle this, you can add the appropriate squad:member label yourself.

Full diff analysis of PR #60 vs sprint/3-mongodb-persistence HEAD revealed
the sprint branch has already evolved past the PR base with superior versions
of Profile.razor (sensitive claim filter), NavMenu.razor (logger + a11y),
and Program.cs (copyright header).

Key findings logged:
- Counter/Weather compile-failure in RazorSmokeTests.cs
- 5 file regressions if PR merged as-is
- Missing copyright headers on 8 new .cs files
- Duplicate InternalsVisibleTo in AssemblyInfo.cs
- Package version regression in Unit.Tests.csproj

Review comment posted on GitHub PR #60.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated no new comments.

@github-actions

github-actions Bot commented Apr 20, 2026

Copy link
Copy Markdown
Contributor

Summary

Summary
Generated on: 04/20/2026 - 16:40:57
Coverage date: 04/20/2026 - 16:40:21 - 04/20/2026 - 16:40:36
Parser: MultiReport (4x Cobertura)
Assemblies: 4
Classes: 51
Files: 50
Line coverage: 66.4% (556 of 837)
Covered lines: 556
Uncovered lines: 281
Coverable lines: 837
Total lines: 2525
Branch coverage: 66.5% (189 of 284)
Covered branches: 189
Total branches: 284
Method coverage: Feature is only available for sponsors
Tag: 72_24678523511

Coverage

AppHost - 0%
Name Line Branch
AppHost 0% ****
Program 0%
Domain - 87.2%
Name Line Branch
Domain 87.2% 91.6%
Domain.Abstractions.Result 95% 50%
Domain.Abstractions.Result`1 75% 50%
MyBlog.Domain.Behaviors.ValidationBehavior`2 100% 100%
MyBlog.Domain.Entities.BlogPost 100%
MyBlog.Domain.Features.BlogPosts.Commands.CreateBlogPost.CreateBlogPostComm
and
100%
MyBlog.Domain.Features.BlogPosts.Commands.CreateBlogPost.CreateBlogPostComm
andHandler
100%
MyBlog.Domain.Features.BlogPosts.Commands.CreateBlogPost.CreateBlogPostComm
andValidator
0%
MyBlog.Domain.Features.BlogPosts.Commands.DeleteBlogPost.DeleteBlogPostComm
and
100%
MyBlog.Domain.Features.BlogPosts.Commands.DeleteBlogPost.DeleteBlogPostComm
andHandler
100%
MyBlog.Domain.Features.BlogPosts.Commands.DeleteBlogPost.DeleteBlogPostComm
andValidator
0%
MyBlog.Domain.Features.BlogPosts.Commands.UpdateBlogPost.UpdateBlogPostComm
and
100%
MyBlog.Domain.Features.BlogPosts.Commands.UpdateBlogPost.UpdateBlogPostComm
andHandler
100% 100%
MyBlog.Domain.Features.BlogPosts.Commands.UpdateBlogPost.UpdateBlogPostComm
andValidator
0%
MyBlog.Domain.Features.BlogPosts.Queries.GetAllBlogPosts.GetAllBlogPostsQue
ryHandler
100%
MyBlog.Domain.Features.BlogPosts.Queries.GetBlogPostById.GetBlogPostByIdQue
ry
100%
MyBlog.Domain.Features.BlogPosts.Queries.GetBlogPostById.GetBlogPostByIdQue
ryHandler
100% 100%
ServiceDefaults - 0%
Name Line Branch
ServiceDefaults 0% 0%
Microsoft.Extensions.Hosting.Extensions 0% 0%
Web - 68.7%
Name Line Branch
Web 68.7% 69%
MyBlog.Web.Components.Layout.MainLayout 100%
MyBlog.Web.Components.Layout.NavMenu 82.8% 71.4%
MyBlog.Web.Components.Pages.Error 100% 75%
MyBlog.Web.Components.Routes 0% 0%
MyBlog.Web.Components.Shared.RedirectToLogin 100%
MyBlog.Web.Data.BlogDbContext 100%
MyBlog.Web.Data.BlogPostDto 100%
MyBlog.Web.Data.BlogPostMappings 100%
MyBlog.Web.Data.MongoDbBlogPostRepository 100% 100%
MyBlog.Web.Features.BlogPosts.Create.Create 75% 50%
MyBlog.Web.Features.BlogPosts.Create.CreateBlogPostCommand 100%
MyBlog.Web.Features.BlogPosts.Create.CreateBlogPostCommandValidator 100%
MyBlog.Web.Features.BlogPosts.Create.CreateBlogPostHandler 100%
MyBlog.Web.Features.BlogPosts.Delete.ConfirmDeleteDialog 100% 100%
MyBlog.Web.Features.BlogPosts.Delete.DeleteBlogPostCommand 100%
MyBlog.Web.Features.BlogPosts.Delete.DeleteBlogPostCommandValidator 100%
MyBlog.Web.Features.BlogPosts.Delete.DeleteBlogPostHandler 100%
MyBlog.Web.Features.BlogPosts.Edit.Edit 88% 75%
MyBlog.Web.Features.BlogPosts.Edit.EditBlogPostCommand 100%
MyBlog.Web.Features.BlogPosts.Edit.EditBlogPostCommandValidator 100%
MyBlog.Web.Features.BlogPosts.Edit.EditBlogPostHandler 84% 90%
MyBlog.Web.Features.BlogPosts.Edit.GetBlogPostByIdQuery 100%
MyBlog.Web.Features.BlogPosts.List.GetBlogPostsHandler 100% 100%
MyBlog.Web.Features.BlogPosts.List.Index 86.8% 84.6%
MyBlog.Web.Features.UserManagement.AssignRoleCommand 100%
MyBlog.Web.Features.UserManagement.ManageRoles 90.4% 75%
MyBlog.Web.Features.UserManagement.Profile 97.2% 82%
MyBlog.Web.Features.UserManagement.RemoveRoleCommand 100%
MyBlog.Web.Features.UserManagement.RoleDto 100%
MyBlog.Web.Features.UserManagement.UserManagementHandler 0% 0%
MyBlog.Web.Features.UserManagement.UserWithRolesDto 100%
MyBlog.Web.Security.RoleClaimsHelper 91.8% 91.1%
Program 0% 0%

- Add Directory.Packages.props with all 30 package versions
- Enable ManagePackageVersionsCentrally in Directory.Build.props
- Remove Version attributes from all 7 .csproj files
- Upgrade FluentValidation.AspNetCore to 11.3.1 (no 12.x exists; FV 12.0.0 satisfies the open-ended dep range [11.11.0, ))
- Normalise OpenTelemetry exporter/extensions to 1.15.2 (instrumentation packages kept at actual latest: AspNetCore 1.15.1, Http/Runtime 1.15.0)
- Update global.json SDK floor from 10.0.202 to 10.0.100 to match installed 10.0.106

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@mpaulosky mpaulosky closed this Apr 20, 2026
@mpaulosky
mpaulosky deleted the squad/59-ui-component-tests-profile-roleclaimshelper branch April 20, 2026 17:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

squad Squad triage inbox — Lead will assign to a member

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants