Add unit tests for DashboardController and DashboardQueryService - #7
Open
wesmacdonald wants to merge 1 commit into
Open
wesmacdonald wants to merge 1 commit into
wesmacdonald wants to merge 1 commit into
Conversation
wesmacdonald
commented
Sep 10, 2026
Owner
- Created App.test.tsx for testing the SecureFix dashboard UI components.
- Added setup.ts for configuring testing environment with @testing-library/jest-dom.
- Introduced tsconfig.app.json, tsconfig.node.json, and tsconfig.json for TypeScript configuration.
- Implemented vite.config.ts for Vite configuration with React and testing setup.
- Developed DashboardControllerTests.cs to validate API responses and authorization.
- Implemented DashboardQueryServiceTests.cs to test workflow retrieval and summary calculations.
- Updated SecureFix.Tests.csproj to include necessary package references.
- Created App.test.tsx for testing the SecureFix dashboard UI components. - Added setup.ts for configuring testing environment with @testing-library/jest-dom. - Introduced tsconfig.app.json, tsconfig.node.json, and tsconfig.json for TypeScript configuration. - Implemented vite.config.ts for Vite configuration with React and testing setup. - Developed DashboardControllerTests.cs to validate API responses and authorization. - Implemented DashboardQueryServiceTests.cs to test workflow retrieval and summary calculations. - Updated SecureFix.Tests.csproj to include necessary package references.
There was a problem hiding this comment.
🟡 Changes recommended
Security, data completeness, API-contract, CSP, and deployment configuration defects remain unresolved.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Pull request overview
Adds an integrated React dashboard, dashboard-query APIs, automated tests, and container/CI support.
Changes:
- Adds dashboard UI, demo/live data access, authentication, and tests.
- Adds workflow-list and dashboard-summary backend services and endpoints.
- Integrates frontend builds into API deployment and documentation.
File summaries
| File | Description |
|---|---|
tests/SecureFix.Tests/SecureFix.Tests.csproj |
Adds a test dependency. |
tests/SecureFix.Tests/DashboardQueryServiceTests.cs |
Tests dashboard queries and summaries. |
tests/SecureFix.Tests/DashboardControllerTests.cs |
Tests dashboard endpoints and authorization. |
src/SecureFix.Web/vite.config.ts |
Configures Vite, proxying, and Vitest. |
src/SecureFix.Web/tsconfig.node.json |
Configures tooling TypeScript compilation. |
src/SecureFix.Web/tsconfig.json |
Adds TypeScript project references. |
src/SecureFix.Web/tsconfig.app.json |
Configures application TypeScript compilation. |
src/SecureFix.Web/src/test/setup.ts |
Initializes DOM matchers. |
src/SecureFix.Web/src/test/App.test.tsx |
Tests dashboard rendering and filtering. |
src/SecureFix.Web/src/styles.css |
Defines dashboard styling and responsiveness. |
src/SecureFix.Web/src/pages/WorkflowsPage.tsx |
Adds workflow listing and filters. |
src/SecureFix.Web/src/pages/WorkflowDetailPage.tsx |
Adds workflow review and governance UI. |
src/SecureFix.Web/src/pages/OverviewPage.tsx |
Adds operational dashboard metrics. |
src/SecureFix.Web/src/pages/IngestPage.tsx |
Adds vulnerability ingestion UI. |
src/SecureFix.Web/src/main.tsx |
Boots the React application. |
src/SecureFix.Web/src/data/demo.ts |
Provides demonstration workflow data. |
src/SecureFix.Web/src/context/AppContext.tsx |
Manages dashboard state and operations. |
src/SecureFix.Web/src/components/ui.tsx |
Adds shared UI components. |
src/SecureFix.Web/src/components/Shell.tsx |
Adds navigation and identity shell. |
src/SecureFix.Web/src/auth/auth.ts |
Adds demo and Entra authentication adapters. |
src/SecureFix.Web/src/App.tsx |
Defines dashboard routes. |
src/SecureFix.Web/src/api/types.ts |
Defines frontend API models. |
src/SecureFix.Web/src/api/client.ts |
Implements backend API calls. |
src/SecureFix.Web/package.json |
Defines frontend dependencies and scripts. |
src/SecureFix.Web/index.html |
Adds the dashboard host page. |
src/SecureFix.Web/.gitignore |
Ignores frontend build artifacts. |
src/SecureFix.Web/.env.example |
Documents frontend configuration. |
src/SecureFix.Core/Services/IDashboardQueryService.cs |
Implements dashboard queries and aggregation. |
src/SecureFix.Core/Models/DashboardDtos.cs |
Defines dashboard API DTOs. |
src/SecureFix.Api/Program.cs |
Registers dashboard services and static hosting. |
src/SecureFix.Api/Controllers/WorkflowsController.cs |
Adds workflow listing and Viewer access. |
src/SecureFix.Api/Controllers/DashboardController.cs |
Exposes dashboard summaries. |
README.md |
Documents the integrated dashboard. |
docs/security-model.md |
Documents browser authentication and controls. |
docs/runbook.md |
Adds dashboard operating procedures. |
docs/architecture.md |
Updates the target architecture. |
Dockerfile |
Builds and packages the dashboard. |
docker-compose.yml |
Adds dashboard and authentication configuration. |
.gitignore |
Ignores generated web assets. |
.github/workflows/dotnet-ci.yml |
Adds frontend test, build, and audit steps. |
.env.example |
Documents dashboard environment variables. |
.dockerignore |
Excludes frontend artifacts from builds. |
Review details
- Files reviewed: 41/43 changed files
- Comments generated: 12
- Review effort level: Balanced
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Comment on lines
+100
to
+102
| "default-src 'self'; script-src 'self'; style-src 'self'; img-src 'self' data:; " + | ||
| "connect-src 'self' https://login.microsoftonline.com; " + | ||
| "frame-src https://login.microsoftonline.com; frame-ancestors 'none'; base-uri 'self'; form-action 'self'"); |
Comment on lines
+56
to
+60
| body: JSON.stringify({ | ||
| reviewer: identity.email, | ||
| reviewerRole: identity.role, | ||
| decision, | ||
| reason, |
| <section className="card"><div className="card__header"><div><span className="eyebrow">AI recommendation</span><h2>Remediation guidance</h2></div><Bot /></div> | ||
| {!workflow.remediation && !remediation ? <EmptyState title="No recommendation yet" detail={approval === "Approved" ? "Generate advisory remediation guidance using the configured provider." : "Human approval is required before remediation generation."} action={approval === "Approved" && canReview ? <button className="button button--primary" disabled={!!busy} onClick={() => void run("remediation", () => generateRemediation(id))}>{busy === "remediation" ? "Generating…" : "Generate recommendation"}</button> : undefined} /> : (() => { const item = remediation; return <div className="recommendation"><div className="recommendation__lead"><strong>{item?.recommendedAction || workflow.remediation?.recommendedAction}</strong><Badge tone="success">{Math.round((item?.confidenceScore || workflow.remediation?.confidenceScore || 0) * 100)}% confidence</Badge></div><p>{item?.explanation || `Upgrade to ${workflow.remediation?.targetVersion} using a minimal dependency-only change.`}</p><dl className="data-grid"><div><dt>Target version</dt><dd className="mono">{item?.targetVersion || workflow.remediation?.targetVersion}</dd></div><div><dt>Model</dt><dd>{item?.modelIdentifier || workflow.remediation?.modelIdentifier}</dd></div><div><dt>Prompt version</dt><dd>{item?.promptVersion || "remediation-v1.3"}</dd></div><div><dt>Human review</dt><dd>Required</dd></div></dl><div className="advisory-note"><LockKeyhole /><p>AI output is advisory and cannot authorize, merge, deploy, or release this change.</p></div></div>; })()} | ||
| </section> | ||
| <section className="card"><div className="card__header"><div><span className="eyebrow">Draft artifact</span><h2>Pull request proposal</h2></div><FileCode2 /></div>{!proposal ? <EmptyState title="No proposal generated" detail="Generate a review-ready draft after an approved remediation recommendation exists." action={(workflow.remediation || remediation) && canReview ? <button className="button button--primary" disabled={!!busy} onClick={() => void run("proposal", () => generateProposal(id))}>{busy === "proposal" ? "Preparing…" : "Generate draft proposal"}</button> : undefined} /> : <div className="proposal"><Badge tone="success">Ready for review</Badge><h3>{proposal.proposedTitle}</h3><p>{proposal.proposedDescription.replaceAll("#", "").replaceAll("*", "").replaceAll("`", "")}</p><div className="proposal__columns"><div><strong>Dependency change</strong>{proposal.dependencyChanges.map((item) => <code key={item}>{item}</code>)}</div><div><strong>Validation</strong>{proposal.validationCommands.map((item) => <code key={item}>{item}</code>)}</div></div><p><strong>Rollback:</strong> {proposal.rollbackGuidance}</p></div>}</section> |
Comment on lines
+3
to
+4
| env_file: | ||
| - .env |
| environment: | ||
| ASPNETCORE_ENVIRONMENT: ${ASPNETCORE_ENVIRONMENT:-Development} | ||
| ASPNETCORE_URLS: ${ASPNETCORE_URLS:-http://+:5000} | ||
| AUTH_MODE: ${AUTH_MODE:-entra} |
Comment on lines
+64
to
+68
| async initialize() { | ||
| await this.client.initialize(); | ||
| const redirect = await this.client.handleRedirectPromise(); | ||
| this.account = redirect?.account ?? this.client.getAllAccounts()[0]; | ||
| return this.account ? this.toIdentity(this.account, redirect) : this.signIn(); |
Comment on lines
+4
to
+6
| export const severityName = (value: Severity | number | undefined): Severity => { | ||
| if (typeof value === "string") return value; | ||
| return (["Low", "Low", "Medium", "High", "Critical"][value ?? 1] ?? "Low") as Severity; |
Comment on lines
+80
to
+81
| void api.getWorkflows() | ||
| .then((response) => setWorkflows(response.items.map((item) => ({ |
| workflows, | ||
| dataLoading, | ||
| dataError, | ||
| getWorkflow: (id) => workflows.find((item) => item.workflowId === id), |
| severity, | ||
| count: workflows.filter((item) => severityName(item.riskAssessment?.normalizedSeverity) === severity).length, | ||
| })); | ||
| const statusCounts = (["PendingApproval", "Approved", "Recommended", "Rejected", "Failed"] as const).map((status) => ({ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.