Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@

export default new Map([
["src/content/docs/index.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2Findex.mdx&astroContentModuleFlag=true")],
["src/content/docs/reference.mdoc", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2Freference.mdoc&astroContentModuleFlag=true")],
["src/content/docs/01-backend-setup.mdoc", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2F01-backend-setup.mdoc&astroContentModuleFlag=true")],
["src/content/docs/01-config-file-overview.mdoc", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2F01-config-file-overview.mdoc&astroContentModuleFlag=true")],
["src/content/docs/02-feature-flags.mdoc", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2F02-feature-flags.mdoc&astroContentModuleFlag=true")],
["src/content/docs/03-display-defaults.mdoc", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2F03-display-defaults.mdoc&astroContentModuleFlag=true")],
["src/content/docs/04-apply-changes.mdoc", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2F04-apply-changes.mdoc&astroContentModuleFlag=true")],
["src/content/docs/05-whats-next.mdoc", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2F05-whats-next.mdoc&astroContentModuleFlag=true")]]);
["src/content/docs/05-whats-next.mdoc", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2F05-whats-next.mdoc&astroContentModuleFlag=true")],
["src/content/docs/index.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2Findex.mdx&astroContentModuleFlag=true")]]);

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"_variables": {
"lastUpdateCheck": 1782159370968
"lastUpdateCheck": 1782297484374
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"terminal",
"browser"
],
"repository": "https://github.com/Vonage/vonage-video-react-app",
"repository": "https://github.com/VZaphod/vonage-video-react-app",
"starterFiles": [],
"capabilities": [],
"version": "1.0.0",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@

export default new Map([
["src/content/docs/index.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2Findex.mdx&astroContentModuleFlag=true")],
["src/content/docs/reference.mdoc", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2Freference.mdoc&astroContentModuleFlag=true")],
["src/content/docs/01-backend-setup.mdoc", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2F01-backend-setup.mdoc&astroContentModuleFlag=true")],
["src/content/docs/01-config-file-overview.mdoc", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2F01-config-file-overview.mdoc&astroContentModuleFlag=true")],
["src/content/docs/02-feature-flags.mdoc", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2F02-feature-flags.mdoc&astroContentModuleFlag=true")],
["src/content/docs/03-display-defaults.mdoc", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2F03-display-defaults.mdoc&astroContentModuleFlag=true")],
["src/content/docs/02-feature-flags.mdoc", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2F02-feature-flags.mdoc&astroContentModuleFlag=true")],
["src/content/docs/04-apply-changes.mdoc", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2F04-apply-changes.mdoc&astroContentModuleFlag=true")],
["src/content/docs/05-whats-next.mdoc", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2F05-whats-next.mdoc&astroContentModuleFlag=true")]]);
["src/content/docs/05-whats-next.mdoc", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2F05-whats-next.mdoc&astroContentModuleFlag=true")],
["src/content/docs/index.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2Findex.mdx&astroContentModuleFlag=true")]]);

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"_variables": {
"lastUpdateCheck": 1782159370968
"lastUpdateCheck": 1782297484374
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ TypeScript version: `^5.8.3`
- `libs/ui` for visual components
- `libs/core` if it is faceless (non-visual logic).
- `libs/common` for helpers, utilities, and hooks that are agnostic of the project.
- **Rule:** If the code is **backend-oriented** and represents **agnostic Vonage Video API orchestration**, it must be placed in `libs/api`.
- **Rule:** Vera-specific business logic (roles, permissions, product policy/decisions) must stay in the app layer (`frontend`/`backend`).
- **Rule:** This is **especially enforced** for video-related components such as publishers, subscribers, sessions, `videoView`s, etc.
- **Rule:** Helpers, utilities, and hooks that are agnostic of the project must be placed in `libs/common`.
Expand All @@ -54,23 +55,10 @@ TypeScript version: `^5.8.3`
- **Rule:** Do not add new state management libraries. Use only existing tooling.
- **Rule:** Components must be kept small, focused, and composable.

## Import rules
## Testing Guidelines

- **Rule:** Always prefer specific imports over deep namespace imports.

**Violation:**

```tsx
// Bad
import { isNil } from 'lodash';
```

**Correct:**

```tsx
// Good
import isNil from 'lodash/isNil';
```
- **Rule:** Avoid overtesting. Simple helpers should be covered by only a couple of high-value use cases.
- **Rule:** Prefer tests that validate real functionality and behavior over redundant input permutations.

---

Expand Down Expand Up @@ -151,13 +139,13 @@ if (isUserEligible(user)) {
if (isNil(data)) return;
```

- **Rule:** Acronyms in names are banned across the codebase, except `req` and `res` when working with Express `Request` and `Response`.
- **Rule:** Abbreviated or shortened names are banned across the codebase, except `req` and `res` when working with Express `Request` and `Response`.
- **Rule:** Use fully descriptive names, even if they are longer. Minification handles bundle size.

**Violation:**

```tsx
// Bad
// Bad: abbreviating "User Details" to "UsrDtls"
function fetchUsrDtls() {
// ...
}
Expand All @@ -166,7 +154,7 @@ function fetchUsrDtls() {
**Correct:**

```tsx
// Good
// Good: fully spelled out words
function fetchUserDetails() {
// ...
}
Expand All @@ -175,14 +163,14 @@ function fetchUserDetails() {
**Violation:**

```tsx
// Bad
// Bad: abbreviating "VideoClient" to "vc"
const vc = new VideoClient();
```

**Correct:**

```tsx
// Good
// Good: fully spelled out variable name
const videoClient = new VonageVideoClient();
```

Expand Down Expand Up @@ -687,13 +675,11 @@ export const SurveyForm = () => {

# Async Logic & Suspense Usage Rules

- **Rule:** `setState` + `useEffect` patterns must not be used for async operations.
- **Rule:** `setState` + `useEffect` patterns should be rather used and strongly justified. Prefer linear non reactive code.
- **Rule:** Native `React.Suspense` and `React.use` must not be used directly.
Only `Suspense$` and `use$`/suspense-specific hooks provided by Vera are allowed.
- **Rule:** Asynchronous operations must be handled through:
- `Suspense$` component
- `use$`, `useSuspenseMemo`, or compatible Vera hooks
- **Rule:** `use$` must only be used inside a `Suspense$` boundary; by design it will throw an explicit error otherwise.
Only `SuspenseBoundary` and `use$` which are boundary aware.
- **Rule:** Asynchronous operations must be handle gracefully, consider using skeletons or placeholders instead of spinners or loading indicators. Take also advantage of tools like `Suspense` and `useSuspenseMemo`.
- **Rule:** `use$` must only be used inside a `SuspenseBoundary` boundary; by design it will throw an explicit error otherwise.

**Violation (async with state/effect):**

Expand Down Expand Up @@ -812,7 +798,7 @@ const ParentComponent = () => {
- **Rule:** Context state should either:
- be stable enough that you do not need fine-grained granularity, or
- be granular enough that consumers can subscribe to specific portions of the state.
- **Rule:** Context APIs must not be reactive. They should not re-render consumers unnecessarily.
- **Rule:** Context APIs must not be reactive highly reactive. They should not re-render consumers unnecessarily.

**Violation (manual React context for simple use case):**

Expand Down Expand Up @@ -1586,7 +1572,7 @@ const useComplexLogic = () => {
```

- **Rule:** Reactive effect architectures are banned.
- Effects must be used only for component lifecycle, not as a state reaction graph for side effects like fetching.
- Effects must be preferred for component lifecycle, not as a state reaction graph for side effects like fetching.

**Violation (reactive effect fetching):**

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
---
applyTo: "**/*.{spec,test}.{ts,tsx}"
---

# Test Authoring Instructions

These instructions apply to all test files across the codebase (unit, integration, backend, libs).

## Testing philosophy

- Do not overtest.
- Small helpers/components with one or two relevant behaviors should usually have one condensed, high-value test that validates the behavior end-to-end.
- Prefer business logic tests with clear input and expected output.
- Do not add snapshot tests. Screenshot-based assertions in integration tests (Playwright `toHaveScreenshot`) are the only allowed exception.
- After writing a test, evaluate quality:
- Does it validate real functionality?
- Or is it mostly validating test tooling, mocks, or framework internals?
- Avoid tests that only check a mocked value was returned because it was mocked.

## What to mock

| Mock | Do not mock |
|------|-------------|
| External SDKs (e.g. `@vonage/client-sdk-video`) | Application contexts |
| Browser APIs (e.g. `navigator.mediaDevices`) | Custom hooks |
| | Components |

## Mocking rules

- Do not overmock.
- Prefer spies over full module mocking whenever possible.
- Avoid mocking our own logic when the scenario can be prepared using real parameters, real state, or real providers.
- Keep mocking minimal and focused on third-party dependencies or APIs not available in the test environment.
- For typed mocked functions, always use `vi.mocked(...)`.
- `as Mocked<...>` type-casting in test files is banned.

## Provider/context testing rules

- Do not mock context for our own providers when #sym:makeTestProvider can be used.
- Compose only the providers strictly necessary for the scenario. Every extra provider increases test setup cost and coupling.
- Initialize provider state using provider options to prepare the use case.
- Use returned public contexts to inspect values and interact with exposed actions.

When a component requires providers, compose only what is needed:

```tsx
type RenderOptions = {
userContext?: ProviderOptions['UserContext'];
sessionContext?: ProviderOptions['SessionContext'];
};

function render(
ui: ReactElement,
{ userContext, sessionContext }: RenderOptions = {}
) {
const { wrapper, ...context } = makeTestProvider(
[providers.user, providers.session],
{ userContext, sessionContext }
);

return {
...context,
...renderBase(ui, { wrapper }),
};
}
```

For hooks, the same principle applies:

```tsx
type RenderOptions = {
userContext?: ProviderOptions['UserContext'];
};

function renderHook<Result, Props>(
render: (initialProps: Props) => Result,
{ userContext }: RenderOptions = {}
) {
const { wrapper, ...context } = makeTestProvider([providers.user], {
userContext,
});

return {
...context,
...renderHookBase(render, { wrapper }),
};
}
```

## Async test rules

- Do not use `setTimeout` or arbitrary `waitForTimeout` calls to make async tests pass. They slow the suite and hide real timing issues.
- Use `waitFor` from `@testing-library/react` to wait for observable state changes instead only when necessary.
- Every async test must declare an explicit assertion count with `expect.assertions(n)`.
- Place `expect.assertions(n)` at the start of the async test body so tests fail if execution exits before assertions run.

## Shared test helpers

Before adding custom setup, check and reuse existing helpers in:

- `libs/common/test`
- `libs/common/testNode`
- `libs/common/testBrowser`

Useful existing helpers include:

- `libs/common/test/setup.ts`
- Already clears mocks, restores spies, and unstubs globals after each test. Already included in the global test setup — do not duplicate.
- `libs/common/testNode/helpers/waitForEvent.ts`

### Banned boilerplate — already provided globally

Do not call any of the following in individual test files. They are already invoked for every test run via the global setup files (`frontend/src/test/setup.ts`, `libs/*/test/setup.ts`):

```ts
// Global cleanup — already runs after each test via mandatoryAfterEachCleanup()
cleanup();
vi.clearAllMocks();
vi.restoreAllMocks();
vi.unstubAllGlobals();
cancelablePromiseTracker.mockClear();

// Browser environment setup — already runs before each suite via setupFrontendTestEnvironment()
setupResizeObserverMock();
setupScrollIntoViewMock();
setupHtmlMediaElementGuards();
setupHtmlCanvasElementGuards();
setupCancelablePromiseHook();
```

Duplicating these calls in test files adds noise and can cause double-invocation side effects.
- Useful for event-driven async tests.
- `libs/common/testBrowser/renderAsyncComponent.ts`
- Use for components that resolve async behavior with Suspense boundaries.
- `libs/common/testBrowser/renderAsyncHook.ts`
- Use for hooks that need async/Suspense-aware rendering.
- `libs/common/testBrowser/makeGenericProviderWrapper.tsx`
- Generic provider/context wrapper utility for reusable context testing.
- `libs/common/testBrowser/fixtures/setupWindowNavigatorMock`
- Browser navigator setup helpers for web media-related tests.

Do not duplicate setup that these helpers already provide.

## Test data setup

- Avoid high-level shared variables when possible.
- Prefer creating scenario-specific inputs inside each test.
- Prefer fewer, more robust tests instead of many tiny tests that increase suite runtime with low value.
- Keep tests explicit and linear, with clear Arrange/Act/Assert intent.
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ jobs:
with:
node-version: 22
- name: Install dependencies
run: yarn install
run: yarn install --ignore-scripts --frozen-lockfile
- name: Run dependency update script
run: node scripts/generateDependenciesList.js
- name: Auto-commit updated dependencies file
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ jobs:
cache: yarn

- name: Install Dependencies
run: yarn
run: yarn install --ignore-scripts --frozen-lockfile

- name: Run ${{ matrix.check.name }}
run: ${{ matrix.check.command }}
Expand Down Expand Up @@ -76,7 +76,7 @@ jobs:
cache: yarn

- name: Install Dependencies
run: yarn
run: yarn install --ignore-scripts --frozen-lockfile

- name: Run license check
run: |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ env:
OT_API_SECRET: ${{secrets.API_SECRET}}
VONAGE_APP_ID: ${{secrets.VONAGE_APP_ID}}
VONAGE_PRIVATE_KEY: ${{secrets.VONAGE_PRIVATE_KEY}}
SESSION_KEY_SECRET: ${{secrets.SESSION_KEY_SECRET}}

jobs:
# ----------------------------------------------------
Expand Down Expand Up @@ -40,7 +41,7 @@ jobs:
cache: yarn

- name: Install Dependencies
run: yarn --ignore-scripts
run: yarn install --ignore-scripts --frozen-lockfile

- name: Run ${{ matrix.project }} unit tests
run: NX_DAEMON=false yarn nx test ${{ matrix.project }} --configuration=coverage
Expand Down Expand Up @@ -99,7 +100,7 @@ jobs:
- name: Install Dependencies
run: |
node -v
yarn --ignore-scripts
yarn install --ignore-scripts --frozen-lockfile

- name: Cache Playwright browsers
uses: actions/cache@v4
Expand Down Expand Up @@ -150,7 +151,7 @@ jobs:
- name: Install Dependencies
run: |
node -v
yarn --ignore-scripts
yarn install --ignore-scripts --frozen-lockfile

- name: Download all coverage artifacts
uses: actions/download-artifact@v4
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,3 +63,4 @@ vitest.config.*.timestamp*
vcr-dev.yml

/frontend/distRoom
room.zip
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
legacy-peer-deps=true
Loading