mirror of
https://github.com/Azure/cosmos-explorer.git
synced 2026-04-16 19:39:19 +01:00
Copilot instructions and build/test skills (#2444)
* Add copilot instructions and skills for build and tests. * Add dev-server skill. * Auth Util changes to fix Entra login while running from copilot. * Fix lint issue.
This commit is contained in:
163
.github/copilot-instructions.md
vendored
Normal file
163
.github/copilot-instructions.md
vendored
Normal file
@@ -0,0 +1,163 @@
|
||||
# Copilot Instructions for Cosmos Explorer
|
||||
|
||||
## Build, Test, and Lint
|
||||
|
||||
**To build the project, use the `/build` skill.** It handles dependency checks (`npm install`) and all build variants. See `.github/skills/build/SKILL.md` for full details.
|
||||
|
||||
Quick reference:
|
||||
|
||||
```bash
|
||||
npm install # Install dependencies (runs patch-package and i18n key generation automatically)
|
||||
npm run build # Full build: format check → lint → compile → strict compile → webpack prod → copy
|
||||
npm run build:ci # CI build: same as above but uses webpack dev mode (faster)
|
||||
npm start # Dev server with hot reload at https://localhost:1234 (see /dev-server skill)
|
||||
|
||||
npm run compile # TypeScript check only (no emit)
|
||||
npm run compile:strict # TypeScript strict mode check (subset of files in tsconfig.strict.json)
|
||||
npm run lint # ESLint across all .ts/.tsx files
|
||||
npm run format # Prettier format (write)
|
||||
npm run format:check # Prettier format (check only)
|
||||
```
|
||||
|
||||
### Testing
|
||||
|
||||
**To run unit tests, use the `/run-unit-tests` skill.** It handles dependency checks and all test variants. See `.github/skills/run-unit-tests/SKILL.md` for full details.
|
||||
|
||||
Quick reference:
|
||||
|
||||
```bash
|
||||
npm test # Run all unit tests with Jest (includes coverage)
|
||||
npm run test:file -- path/to/file.test.ts # Run a single test file (no coverage)
|
||||
npm run test:debug # Run tests serially for debugging (--runInBand)
|
||||
|
||||
# E2E tests (requires .env config and running dev server)
|
||||
npm run test:e2e # Playwright E2E tests
|
||||
npx playwright test test/sql/document.spec.ts # Run a single E2E spec
|
||||
```
|
||||
|
||||
Unit tests live adjacent to source files (`*.test.ts` / `*.test.tsx` in `src/`). E2E tests are in `test/` organized by API type (sql, mongo, cassandra, gremlin, tables).
|
||||
|
||||
### Dev Server
|
||||
|
||||
**To start the local dev server and connect a browser, use the `/dev-server` skill.** It handles dependency checks, server startup, readiness polling, and Playwright browser navigation. See `.github/skills/dev-server/SKILL.md` for full details.
|
||||
|
||||
The dev server runs at `https://localhost:1234` with a `/_ready` health-check endpoint. Entry points include `hostedExplorer.html` (standalone), `explorer.html` (portal iframe), and `index.html` (emulator).
|
||||
|
||||
## Architecture
|
||||
|
||||
### Platform Modes
|
||||
|
||||
The app runs in four hosting contexts, determined by `ConfigContext.platform`:
|
||||
- **Portal** – Embedded as an iframe inside Azure Portal
|
||||
- **Hosted** – Standalone at cosmos.azure.com, supports AAD, connection string, and resource token auth
|
||||
- **Emulator** – Connects to local Cosmos DB Emulator via master key
|
||||
- **Fabric** – Embedded in Microsoft Fabric, communicates via postMessage RPC
|
||||
|
||||
Platform-specific code lives in `src/Platform/{Emulator,Hosted,Fabric}/`. The active platform is set during initialization in `src/hooks/useKnockoutExplorer.ts`, which orchestrates bootstrapping for all modes.
|
||||
|
||||
### Global State (Module Singletons + Zustand)
|
||||
|
||||
State is **not** managed by React Context or Redux for most application concerns. Instead:
|
||||
|
||||
- **`userContext`** (`src/UserContext.ts`) – Module-level singleton holding current account info, auth tokens, API type, and feature flags. Updated via `updateUserContext()`. Not a React store; components read it directly.
|
||||
- **`configContext`** (`src/ConfigContext.ts`) – Module-level singleton for environment/endpoint configuration. Updated via `updateConfigContext()`.
|
||||
- **Zustand stores** (`src/hooks/use*.ts`) – Used for UI state that React components need to subscribe to reactively. Key stores:
|
||||
- `useDatabases` – Database/collection tree state
|
||||
- `useTabs` – Open tab management
|
||||
- `useQueryCopilot` – Copilot query assistant state
|
||||
- `useNotificationConsole` – Console notifications
|
||||
- `useSidePanel` – Side panel visibility
|
||||
- `useSelectedNode` – Currently selected tree node
|
||||
|
||||
### Data Access Layer
|
||||
|
||||
`src/Common/dataAccess/` contains all Cosmos DB CRUD operations (createCollection, readDatabases, queryDocuments, etc.). These functions call either the Cosmos SDK (`@azure/cosmos`) directly or go through proxy endpoints depending on the API type and auth method.
|
||||
|
||||
ARM (Azure Resource Manager) clients are auto-generated in `src/Utils/arm/generatedClients/` — regenerate with `npm run generateARMClients`.
|
||||
|
||||
### Multi-API Support
|
||||
|
||||
Cosmos DB supports multiple APIs: SQL, Mongo, Gremlin, Tables, Cassandra, Postgres, and VCoreMongo. The current API type is determined from `userContext.apiType` (derived from the database account's capabilities). API-specific UI components branch on this value.
|
||||
|
||||
### Entry Points
|
||||
|
||||
Webpack builds multiple independent entry points (see `webpack.config.js`):
|
||||
- `src/Main.tsx` → `explorer.html` (Portal iframe)
|
||||
- `src/Index.tsx` → `index.html` (Emulator)
|
||||
- `src/HostedExplorer.tsx` → `hostedExplorer.html` (cosmos.azure.com)
|
||||
- Plus: terminal, cellOutputViewer, galleryViewer, selfServe, connectToGitHub, quickstart
|
||||
|
||||
### Knockout → React Migration
|
||||
|
||||
The codebase is actively migrating from Knockout.js to React. Legacy Knockout code still exists (observables, bindings), but all new UI must be React. The main `Explorer` class (`src/Explorer/Explorer.tsx`) is a large legacy class that orchestrates much of the app — it is not a React component but interacts with React via hooks and stores.
|
||||
|
||||
## Key Conventions
|
||||
|
||||
### Ignored Directories
|
||||
|
||||
The `src/preview/` folder is a separate project and should not be modified or referenced.
|
||||
|
||||
### Localization
|
||||
|
||||
All user-facing strings must be defined in `src/Localization/en/Resources.json` and referenced via the type-safe `t()` helper:
|
||||
```typescript
|
||||
import { t } from "Localization/t";
|
||||
|
||||
// Use dot-notation keys matching the JSON structure
|
||||
const label = t("common.save");
|
||||
const title = t("splashScreen.title.default");
|
||||
```
|
||||
The `ResourceKey` type (derived from `Resources.json`) ensures compile-time safety — invalid keys will cause a type error. When adding new strings, add the English entry to `Resources.json` first, then reference it with `t()`.
|
||||
|
||||
### Imports
|
||||
|
||||
TypeScript `baseUrl` is set to `src/`, so imports from `src/` are written without a leading `./src/` prefix:
|
||||
```typescript
|
||||
import { userContext } from "UserContext"; // src/UserContext.ts
|
||||
import { configContext } from "ConfigContext"; // src/ConfigContext.ts
|
||||
import { readDatabases } from "Common/dataAccess/readDatabases";
|
||||
```
|
||||
|
||||
### React Components
|
||||
|
||||
- Use **Fluent UI v9** (`@fluentui/react-components`) for new components. Legacy code uses v8 (`@fluentui/react`), but new code should prefer v9.
|
||||
- Prefer pure functional components; hooks and class components are both acceptable
|
||||
- Do **not** use component inheritance for shared behavior
|
||||
- Do **not** suffix file or component names with "Component"
|
||||
|
||||
### ESLint Rules to Note
|
||||
|
||||
- `no-console`: Only `console.error` and `console.warn` are allowed (not `console.log`)
|
||||
- `@typescript-eslint/no-explicit-any`: Error — avoid `any` types
|
||||
- `prefer-arrow/prefer-arrow-functions`: Arrow functions preferred (standalone declarations allowed)
|
||||
- `eqeqeq`: Strict equality required
|
||||
- `@typescript-eslint/switch-exhaustiveness-check`: Switch statements must handle all cases
|
||||
- Do not use `JSON.stringify(error)` — it prints `'{}'`. The linter catches variable names matching `$err`.
|
||||
|
||||
### Testing
|
||||
|
||||
Any code change should consider both unit and E2E test coverage:
|
||||
|
||||
- **Unit tests** – Write or update unit tests for all logic, utility, and component changes. Place test files adjacent to the source file (`Foo.test.ts` next to `Foo.ts`). Do not decrease existing coverage.
|
||||
- **E2E tests** – Write or update a Playwright E2E test when a change affects a user-facing workflow (e.g., creating a container, running a query, editing a document). E2E tests live in `test/` organized by API type.
|
||||
|
||||
Tooling and conventions:
|
||||
- Use **Jest** for unit tests with `jest-environment-jsdom`
|
||||
- Use `@testing-library/react` for new component tests. Enzyme exists in legacy tests but should not be used for new code.
|
||||
- Use Jest built-in mocking (not sinon.js)
|
||||
- E2E tests use **Playwright** (configured in `playwright.config.ts`); use accessible attributes (role, title, label) over `data-*` attributes for selectors
|
||||
|
||||
### Strict Null Checks
|
||||
|
||||
The project is incrementally adopting strict null checks. `tsconfig.strict.json` lists files that compile under `--strictNullChecks`. **New files must be added to `tsconfig.strict.json`** so they compile under strict mode. Use `npm run strict:add` to add eligible files.
|
||||
|
||||
### Libraries to Avoid
|
||||
|
||||
- **underscore.js** – Use native JS methods instead (legacy usage exists)
|
||||
- **jQuery** – Being removed; do not add new usage
|
||||
- **sinon.js** – Deprecated; use Jest mocking
|
||||
- **TSLint** – Removed; use ESLint only
|
||||
|
||||
### Formatting
|
||||
|
||||
Prettier with `printWidth: 120` and `endOfLine: auto`. Format is enforced in the build pipeline via `npm run format:check`.
|
||||
95
.github/skills/build/SKILL.md
vendored
Normal file
95
.github/skills/build/SKILL.md
vendored
Normal file
@@ -0,0 +1,95 @@
|
||||
---
|
||||
name: build
|
||||
description: Build the Cosmos Explorer project. Use this skill when asked to build, compile, or check the build status of the project.
|
||||
allowed-tools: shell
|
||||
---
|
||||
|
||||
# Build Skill
|
||||
|
||||
Use the following commands to build the Cosmos Explorer project. Choose the appropriate command based on the task.
|
||||
|
||||
## Full Production Build
|
||||
|
||||
Run a complete production build (format check → lint → compile → strict compile → webpack prod → copy):
|
||||
|
||||
```bash
|
||||
npm run build
|
||||
```
|
||||
|
||||
## CI Build (Faster)
|
||||
|
||||
Run a CI build that uses webpack dev mode for faster bundling:
|
||||
|
||||
```bash
|
||||
npm run build:ci
|
||||
```
|
||||
|
||||
## TypeScript Compile Only
|
||||
|
||||
Run a TypeScript type-check without emitting output:
|
||||
|
||||
```bash
|
||||
npm run compile
|
||||
```
|
||||
|
||||
## Strict TypeScript Compile
|
||||
|
||||
Run a strict null-checks compile on the subset of files in `tsconfig.strict.json`:
|
||||
|
||||
```bash
|
||||
npm run compile:strict
|
||||
```
|
||||
|
||||
## Lint Only
|
||||
|
||||
Run ESLint across all `.ts` and `.tsx` files:
|
||||
|
||||
```bash
|
||||
npm run lint
|
||||
```
|
||||
|
||||
## Format Check
|
||||
|
||||
Run Prettier to verify formatting without modifying files:
|
||||
|
||||
```bash
|
||||
npm run format:check
|
||||
```
|
||||
|
||||
## Pre-Build: Check Dependencies
|
||||
|
||||
Before running any build command, check whether `npm install` needs to be run. Do this by comparing `package.json` and `package-lock.json` against the installed `node_modules`:
|
||||
|
||||
1. Check if the `node_modules` directory exists. If it does not, run `npm install`.
|
||||
2. If `node_modules` exists, check whether `package.json` or `package-lock.json` have been modified more recently than `node_modules`. If so, run `npm install`.
|
||||
|
||||
```bash
|
||||
# Check if node_modules is missing or outdated
|
||||
if [ ! -d node_modules ] || [ package.json -nt node_modules ] || [ package-lock.json -nt node_modules ]; then
|
||||
npm install
|
||||
fi
|
||||
```
|
||||
|
||||
On Windows PowerShell:
|
||||
|
||||
```powershell
|
||||
if (-not (Test-Path node_modules) -or
|
||||
(Get-Item package.json).LastWriteTime -gt (Get-Item node_modules).LastWriteTime -or
|
||||
(Get-Item package-lock.json).LastWriteTime -gt (Get-Item node_modules).LastWriteTime) {
|
||||
npm install
|
||||
}
|
||||
```
|
||||
|
||||
Always run this check before proceeding with any build command.
|
||||
|
||||
## Guidelines
|
||||
|
||||
- When asked to simply "build", run `npm run build` for a full production build.
|
||||
- When asked for a quick or fast build, use `npm run build:ci`.
|
||||
- When asked to just check types, use `npm run compile`.
|
||||
- If the build fails, read the error output carefully. Common issues include:
|
||||
- **TypeScript errors**: Fix type errors shown in the `npm run compile` output.
|
||||
- **Strict null-check errors**: Fix strict errors shown in `npm run compile:strict` output.
|
||||
- **Lint errors**: Fix lint issues shown in `npm run lint` output.
|
||||
- **Format errors**: Run `npm run format` to auto-fix formatting, then retry the build.
|
||||
- New files must be added to `tsconfig.strict.json` so they compile under strict mode.
|
||||
157
.github/skills/dev-server/SKILL.md
vendored
Normal file
157
.github/skills/dev-server/SKILL.md
vendored
Normal file
@@ -0,0 +1,157 @@
|
||||
---
|
||||
name: dev-server
|
||||
description: Start the local webpack dev server and connect to it with the Playwright browser. Use this skill when asked to start the dev server, preview the app, or interact with the running application in a browser.
|
||||
allowed-tools: shell, browser
|
||||
---
|
||||
|
||||
# Dev Server Skill
|
||||
|
||||
Use this skill to start the Cosmos Explorer webpack dev server and connect to it with the Playwright MCP browser for interactive testing, debugging, or previewing the application.
|
||||
|
||||
## Pre-Start: Check Dependencies
|
||||
|
||||
Before starting the dev server, check whether `npm install` needs to be run:
|
||||
|
||||
```bash
|
||||
if [ ! -d node_modules ] || [ package.json -nt node_modules ] || [ package-lock.json -nt node_modules ]; then
|
||||
npm install
|
||||
fi
|
||||
```
|
||||
|
||||
On Windows PowerShell:
|
||||
|
||||
```powershell
|
||||
if (-not (Test-Path node_modules) -or
|
||||
(Get-Item package.json).LastWriteTime -gt (Get-Item node_modules).LastWriteTime -or
|
||||
(Get-Item package-lock.json).LastWriteTime -gt (Get-Item node_modules).LastWriteTime) {
|
||||
npm install
|
||||
}
|
||||
```
|
||||
|
||||
Always run this check before starting the dev server.
|
||||
|
||||
## Check for Existing Server
|
||||
|
||||
Before starting a new server, check if one is already running on port 1234:
|
||||
|
||||
```powershell
|
||||
try {
|
||||
$response = Invoke-WebRequest -Uri "https://localhost:1234/_ready" -SkipCertificateCheck -UseBasicParsing -ErrorAction Stop
|
||||
if ($response.StatusCode -eq 200) {
|
||||
Write-Host "Dev server is already running and ready!"
|
||||
}
|
||||
} catch {
|
||||
Write-Host "No dev server detected, starting a new one..."
|
||||
}
|
||||
```
|
||||
|
||||
If the server is already running and ready, skip to **Connect the Playwright Browser**.
|
||||
|
||||
## Start the Dev Server
|
||||
|
||||
Start the webpack dev server as a **detached background process** so it persists across session changes:
|
||||
|
||||
```bash
|
||||
npm start
|
||||
```
|
||||
|
||||
The dev server:
|
||||
- Runs at **`https://localhost:1234`** (HTTPS with self-signed certificate)
|
||||
- Uses webpack dev mode with live reload
|
||||
- Exposes a `/_ready` health-check endpoint
|
||||
|
||||
## Wait for Compilation
|
||||
|
||||
After starting the server, poll the `/_ready` endpoint until it returns HTTP 200. **Do not proceed to browser navigation until `/_ready` returns 200.**
|
||||
|
||||
On Windows PowerShell:
|
||||
|
||||
```powershell
|
||||
$timeout = 120
|
||||
$elapsed = 0
|
||||
while ($elapsed -lt $timeout) {
|
||||
try {
|
||||
$response = Invoke-WebRequest -Uri "https://localhost:1234/_ready" -SkipCertificateCheck -UseBasicParsing -ErrorAction Stop
|
||||
if ($response.StatusCode -eq 200) {
|
||||
Write-Host "Dev server is ready!"
|
||||
break
|
||||
}
|
||||
} catch {
|
||||
# Server not ready yet
|
||||
}
|
||||
Start-Sleep -Seconds 3
|
||||
$elapsed += 3
|
||||
}
|
||||
if ($elapsed -ge $timeout) {
|
||||
Write-Error "Dev server did not become ready within $timeout seconds"
|
||||
}
|
||||
```
|
||||
|
||||
On bash:
|
||||
|
||||
```bash
|
||||
timeout=120
|
||||
elapsed=0
|
||||
while [ $elapsed -lt $timeout ]; do
|
||||
if curl -sk https://localhost:1234/_ready 2>/dev/null | grep -q "Compilation complete"; then
|
||||
echo "Dev server is ready!"
|
||||
break
|
||||
fi
|
||||
sleep 3
|
||||
elapsed=$((elapsed + 3))
|
||||
done
|
||||
if [ $elapsed -ge $timeout ]; then
|
||||
echo "Dev server did not become ready within $timeout seconds" >&2
|
||||
fi
|
||||
```
|
||||
|
||||
## Connect the Playwright Browser
|
||||
|
||||
Once the dev server is ready, use the Playwright MCP browser tools to navigate to the application.
|
||||
|
||||
Navigate to the desired entry point:
|
||||
|
||||
- **`https://localhost:1234/hostedExplorer.html`** — Hosted explorer (standalone mode). Best for general UI testing and interaction without Azure Portal framing.
|
||||
- **`https://localhost:1234/explorer.html`** — Portal explorer (Azure Portal iframe mode). Requires portal context/messages to initialize fully.
|
||||
- **`https://localhost:1234/index.html`** — Emulator mode. Requires a local Cosmos DB Emulator running on port 8081.
|
||||
- **`https://localhost:1234/testExplorer.html`** — Test explorer (dev mode only). Used for E2E test harness.
|
||||
|
||||
### Default Navigation
|
||||
|
||||
When no specific page is requested, navigate to **`https://localhost:1234/hostedExplorer.html`** as it provides the most complete standalone experience.
|
||||
|
||||
### Dismiss Webpack Warnings Overlay
|
||||
|
||||
After the page loads, a webpack dev server overlay may appear inside an iframe showing `DefinePlugin` warnings. If a "Dismiss" button (`×`) is visible in the overlay, click it to close the warnings before proceeding with any other interaction.
|
||||
|
||||
## Available Pages Reference
|
||||
|
||||
| URL | Entry Point | Description |
|
||||
|-----|-------------|-------------|
|
||||
| `/hostedExplorer.html` | `src/HostedExplorer.tsx` | Standalone hosted explorer (cosmos.azure.com) |
|
||||
| `/explorer.html` | `src/Main.tsx` | Portal iframe explorer |
|
||||
| `/index.html` | `src/Index.tsx` | Emulator explorer |
|
||||
| `/testExplorer.html` | `test/testExplorer/TestExplorer.ts` | Test harness (dev mode only) |
|
||||
| `/terminal.html` | `src/Terminal/index.ts` | Notebook terminal |
|
||||
| `/quickstart.html` | `src/quickstart.ts` | Quickstart page |
|
||||
| `/selfServe.html` | `src/SelfServe/SelfServe.tsx` | Self-serve configuration |
|
||||
| `/galleryViewer.html` | `src/GalleryViewer/GalleryViewer.tsx` | Notebook gallery viewer |
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### HTTPS / Self-Signed Certificate Errors
|
||||
|
||||
The dev server uses HTTPS with a self-signed certificate. If the Playwright browser fails to navigate with an error like `ERR_CERT_AUTHORITY_INVALID` or any other SSL/TLS certificate error, **stop immediately** and tell the user:
|
||||
|
||||
> The Playwright MCP server needs the `--ignore-https-errors` argument to connect to the dev server's self-signed certificate. Please add `--ignore-https-errors` to your Playwright MCP server configuration and try again.
|
||||
|
||||
Do not attempt workarounds (e.g., creating new browser contexts manually). The `--ignore-https-errors` flag is the correct fix.
|
||||
|
||||
## Guidelines
|
||||
|
||||
- Always start the dev server as a **detached background process** so it survives session changes.
|
||||
- Always wait for `/_ready` to return 200 before navigating the browser.
|
||||
- Ignore certificate errors in shell HTTP requests (e.g., `-SkipCertificateCheck`, `curl -k`). For the Playwright browser, the `--ignore-https-errors` MCP argument must be configured.
|
||||
- If the dev server is already running on port 1234, reuse it instead of starting a new one.
|
||||
- If the server fails to start, check for port conflicts (`netstat -ano | findstr :1234` on Windows).
|
||||
- When stopping the dev server, use `Stop-Process` with the specific PID of the node process.
|
||||
81
.github/skills/run-unit-tests/SKILL.md
vendored
Normal file
81
.github/skills/run-unit-tests/SKILL.md
vendored
Normal file
@@ -0,0 +1,81 @@
|
||||
---
|
||||
name: run-unit-tests
|
||||
description: Run unit tests for the Cosmos Explorer project. Use this skill when asked to run tests, check test results, or debug test failures.
|
||||
allowed-tools: shell
|
||||
---
|
||||
|
||||
# Test Skill
|
||||
|
||||
Use the following commands to run unit tests for the Cosmos Explorer project.
|
||||
|
||||
## Pre-Test: Check Dependencies
|
||||
|
||||
Before running tests, check whether `npm install` needs to be run:
|
||||
|
||||
```bash
|
||||
if [ ! -d node_modules ] || [ package.json -nt node_modules ] || [ package-lock.json -nt node_modules ]; then
|
||||
npm install
|
||||
fi
|
||||
```
|
||||
|
||||
On Windows PowerShell:
|
||||
|
||||
```powershell
|
||||
if (-not (Test-Path node_modules) -or
|
||||
(Get-Item package.json).LastWriteTime -gt (Get-Item node_modules).LastWriteTime -or
|
||||
(Get-Item package-lock.json).LastWriteTime -gt (Get-Item node_modules).LastWriteTime) {
|
||||
npm install
|
||||
}
|
||||
```
|
||||
|
||||
Always run this check before proceeding with any test command.
|
||||
|
||||
## Run All Unit Tests
|
||||
|
||||
Run the full test suite with coverage:
|
||||
|
||||
```bash
|
||||
npm test
|
||||
```
|
||||
|
||||
This clears the `coverage/` directory and runs Jest with coverage collection enabled.
|
||||
|
||||
## Run a Single Test File
|
||||
|
||||
Run a specific test file without coverage (faster):
|
||||
|
||||
```bash
|
||||
npm run test:file -- path/to/file.test.ts
|
||||
```
|
||||
|
||||
## Run Tests in Debug Mode
|
||||
|
||||
Run tests serially (useful for debugging flaky or interdependent tests):
|
||||
|
||||
```bash
|
||||
npm run test:debug
|
||||
```
|
||||
|
||||
## Run Tests Matching a Pattern
|
||||
|
||||
Run only tests whose names match a pattern:
|
||||
|
||||
```bash
|
||||
npx jest --coverage=false --testPathPattern="SomeComponent"
|
||||
```
|
||||
|
||||
## Guidelines
|
||||
|
||||
- When asked to simply "run tests" or "test", run `npm test` for the full suite.
|
||||
- When asked to test a specific file or component, use `npm run test:file -- <path>`.
|
||||
- When debugging test failures, use `npm run test:debug` to run serially.
|
||||
- Unit test files live adjacent to source files (`Foo.test.ts` next to `Foo.ts` in `src/`).
|
||||
- Tests use **Jest** with `jest-environment-jsdom`.
|
||||
- Use `@testing-library/react` for new component tests. Do not use Enzyme for new tests.
|
||||
- Use Jest built-in mocking, not sinon.js.
|
||||
- Coverage thresholds are enforced globally: branches 25%, functions 24%, lines 28%, statements 28%.
|
||||
- If tests fail, read the error output carefully. Common issues include:
|
||||
- **Snapshot mismatches**: Review the diff. If the change is intentional, update snapshots with `npx jest --updateSnapshot`.
|
||||
- **Mock issues**: Ensure mocks are set up correctly and reset between tests.
|
||||
- **Import errors**: Check that module name mappings in `jest.config.js` are correct.
|
||||
- **Type errors in tests**: Run `npm run compile` to check for TypeScript issues.
|
||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -22,3 +22,5 @@ src/Localization/Keys.generated.ts
|
||||
/playwright-report/
|
||||
/blob-report/
|
||||
/playwright/.cache/
|
||||
.vscode/mcp.json
|
||||
.playwright-mcp/
|
||||
@@ -1,8 +1,14 @@
|
||||
import { AuthType } from "../AuthType";
|
||||
import * as Constants from "../Common/Constants";
|
||||
import { resetConfigContext, updateConfigContext } from "../ConfigContext";
|
||||
import { ApiType, updateUserContext, userContext } from "../UserContext";
|
||||
import * as AuthorizationUtils from "./AuthorizationUtils";
|
||||
jest.mock("../Explorer/Explorer");
|
||||
jest.mock("@azure/msal-browser", () => ({
|
||||
PublicClientApplication: jest.fn().mockImplementation((config) => ({
|
||||
_config: config,
|
||||
})),
|
||||
}));
|
||||
|
||||
describe("AuthorizationUtils", () => {
|
||||
const setAadDataPlane = (enabled: boolean) => {
|
||||
@@ -134,4 +140,43 @@ describe("AuthorizationUtils", () => {
|
||||
expect(AuthorizationUtils.useDataplaneRbacAuthorization(userContext)).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe("getMsalInstance()", () => {
|
||||
const originalHostname = window.location.hostname;
|
||||
|
||||
afterEach(() => {
|
||||
resetConfigContext();
|
||||
Object.defineProperty(window, "location", {
|
||||
value: { ...window.location, hostname: originalHostname },
|
||||
writable: true,
|
||||
});
|
||||
});
|
||||
|
||||
it("should use configContext.msalRedirectURI when set", async () => {
|
||||
updateConfigContext({ msalRedirectURI: "https://dataexplorer-preview.azurewebsites.net/" });
|
||||
const instance = await AuthorizationUtils.getMsalInstance();
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
expect((instance as any)._config.auth.redirectUri).toBe("https://dataexplorer-preview.azurewebsites.net/");
|
||||
});
|
||||
|
||||
it("should use dev redirect URI on localhost", async () => {
|
||||
Object.defineProperty(window, "location", {
|
||||
value: { ...window.location, hostname: "localhost" },
|
||||
writable: true,
|
||||
});
|
||||
const instance = await AuthorizationUtils.getMsalInstance();
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
expect((instance as any)._config.auth.redirectUri).toBe("https://dataexplorer-dev.azurewebsites.net");
|
||||
});
|
||||
|
||||
it("should not set redirect URI in non-localhost production", async () => {
|
||||
Object.defineProperty(window, "location", {
|
||||
value: { ...window.location, hostname: "cosmos.azure.com" },
|
||||
writable: true,
|
||||
});
|
||||
const instance = await AuthorizationUtils.getMsalInstance();
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
expect((instance as any)._config.auth.redirectUri).toBeUndefined();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -61,7 +61,9 @@ export async function getMsalInstance() {
|
||||
},
|
||||
};
|
||||
|
||||
if (process.env.NODE_ENV === "development") {
|
||||
if (configContext.msalRedirectURI) {
|
||||
msalConfig.auth.redirectUri = configContext.msalRedirectURI;
|
||||
} else if (process.env.NODE_ENV === "development" || window.location.hostname === "localhost") {
|
||||
msalConfig.auth.redirectUri = "https://dataexplorer-dev.azurewebsites.net";
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user