Skip to content

Add unit tests for DashboardController and DashboardQueryService - #7

Open
wesmacdonald wants to merge 1 commit into
mainfrom
feature/dashboard-ui
Open

wesmacdonald wants to merge 1 commit into
mainfrom
feature/dashboard-ui

Conversation

@wesmacdonald

Copy link
Copy Markdown
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.

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.

🟡 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 thread docker-compose.yml
Comment on lines +3 to +4
env_file:
- .env
Comment thread docker-compose.yml
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) => ({
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants