Skip to content
Merged
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
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/cherry-pick-prompt.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
uses: actions/checkout@v5
with:
fetch-depth: 0
token: ${{ secrets.GITHUB_TOKEN }}
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/codeql.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ jobs:
build-mode: none
steps:
- name: Checkout repository
uses: actions/checkout@v4
uses: actions/checkout@v5

- name: Initialize CodeQL
uses: github/codeql-action/init@v4
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/create-release-branch.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ jobs:
fi

- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v5
with:
ref: ${{ inputs.base_branch }}
fetch-depth: 0
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/package-e2e.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ jobs:
NX_DAEMON: "false"
steps:
- name: Checkout code
uses: actions/checkout@v4
uses: actions/checkout@v5
with:
fetch-depth: 0

Expand Down
12 changes: 6 additions & 6 deletions .github/workflows/perf-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -59,14 +59,14 @@ jobs:

steps:
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v5
with:
fetch-depth: 0

- name: Setup Node.js
uses: actions/setup-node@v4
uses: actions/setup-node@v6
with:
node-version: "22"
node-version-file: ".nvmrc"
cache: "yarn"

- name: Install dependencies
Expand Down Expand Up @@ -98,12 +98,12 @@ jobs:
contents: write

steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v5

- name: Setup Node.js
uses: actions/setup-node@v4
uses: actions/setup-node@v6
with:
node-version: "22"
node-version-file: ".nvmrc"
cache: "yarn"

- name: Install dependencies
Expand Down
8 changes: 4 additions & 4 deletions .github/workflows/perf.yml
Original file line number Diff line number Diff line change
Expand Up @@ -54,17 +54,17 @@ jobs:

steps:
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v5
with:
fetch-depth: 0

- name: Restore Nx cache
uses: ./.github/actions/nx-cache-restore

- name: Setup Node.js
uses: actions/setup-node@v4
uses: actions/setup-node@v6
with:
node-version: "22"
node-version-file: ".nvmrc"
cache: "yarn"

- name: Install dependencies
Expand Down Expand Up @@ -109,7 +109,7 @@ jobs:
pull-requests: write

steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v5

- name: Download all artifacts
uses: actions/download-artifact@v4
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/pr-testing-registry.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ jobs:
fi

- name: Checkout PR branch
uses: actions/checkout@v4
uses: actions/checkout@v5
with:
fetch-depth: 0
ref: refs/pull/${{ inputs.pr_number }}/head
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/publish-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ jobs:

steps:
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v5
with:
fetch-depth: 0

Expand Down Expand Up @@ -235,7 +235,7 @@ jobs:

steps:
- name: Checkout (for .nvmrc)
uses: actions/checkout@v4
uses: actions/checkout@v5
with:
sparse-checkout: |
.nvmrc
Expand Down Expand Up @@ -299,7 +299,7 @@ jobs:

steps:
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v5
with:
fetch-depth: 0

Expand Down
14 changes: 7 additions & 7 deletions .github/workflows/push.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ jobs:
node-version: ${{ steps.node-version.outputs.version }}
steps:
- name: Checkout code
uses: actions/checkout@v4
uses: actions/checkout@v5

- name: Get Node version
id: node-version
Expand All @@ -44,7 +44,7 @@ jobs:
NX_DAEMON: "false"
steps:
- name: Checkout code
uses: actions/checkout@v4
uses: actions/checkout@v5
with:
fetch-depth: 0

Expand Down Expand Up @@ -79,7 +79,7 @@ jobs:
NX_DAEMON: "false"
steps:
- name: Checkout code
uses: actions/checkout@v4
uses: actions/checkout@v5
with:
fetch-depth: 0

Expand Down Expand Up @@ -135,7 +135,7 @@ jobs:
matrix: ${{ steps.discover.outputs.projects }}
steps:
- name: Checkout code
uses: actions/checkout@v4
uses: actions/checkout@v5

- name: Setup Node
uses: actions/setup-node@v6
Expand Down Expand Up @@ -168,7 +168,7 @@ jobs:
RUN_COVERAGE: ${{ github.ref == 'refs/heads/main' }}
steps:
- name: Checkout code
uses: actions/checkout@v4
uses: actions/checkout@v5
with:
fetch-depth: 0

Expand Down Expand Up @@ -224,7 +224,7 @@ jobs:
RUN_COVERAGE: ${{ github.ref == 'refs/heads/main' }}
steps:
- name: Checkout code
uses: actions/checkout@v4
uses: actions/checkout@v5
with:
fetch-depth: 0

Expand Down Expand Up @@ -290,7 +290,7 @@ jobs:
NX_DAEMON: "false"
steps:
- name: Checkout code
uses: actions/checkout@v4
uses: actions/checkout@v5

- name: Setup Node
uses: actions/setup-node@v6
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/trigger-docs-update.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v5
with:
fetch-depth: 0

Expand Down
27 changes: 27 additions & 0 deletions apps/e2e/demo-e2e-react/e2e/browser/dynamic-tool.pw.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { test, expect } from '@playwright/test';
import { gotoSection } from './helpers';

test.describe('Dynamic Tool', () => {
test.beforeEach(async ({ page }) => {
await gotoSection(page, 'dynamic-tool');
});

test('shows registered status', async ({ page }) => {
const status = page.locator('[data-testid="dynamic-registered"]');
await expect(status).toHaveText('registered', { timeout: 10_000 });
});

test('reverses text input', async ({ page }) => {
await expect(page.locator('[data-testid="dynamic-registered"]')).toHaveText('registered', {
timeout: 10_000,
});

const input = page.locator('[data-testid="reverse-input"]');
const button = page.locator('[data-testid="reverse-button"]');
const result = page.locator('[data-testid="reverse-result"]');

await input.fill('hello');
await button.click();
await expect(result).toHaveText('olleh', { timeout: 10_000 });
});
});
14 changes: 14 additions & 0 deletions apps/e2e/demo-e2e-react/e2e/browser/global-setup.pw.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { test, expect } from '@playwright/test';

/**
* Warmup test — navigates to the app root to trigger Vite's initial JS compilation.
* Runs before all other tests via the 'setup' project dependency.
*/
test('warmup: app loads and connects', async ({ page }) => {
await page.goto('/#provider');
await page.waitForLoadState('domcontentloaded');
const content = page.locator('[data-testid="section-content"]');
await expect(content).toBeVisible({ timeout: 60_000 });
const status = page.locator('[data-testid="status"]');
await expect(status).toHaveText('connected', { timeout: 30_000 });
});
27 changes: 27 additions & 0 deletions apps/e2e/demo-e2e-react/e2e/browser/helpers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { expect, type Page } from '@playwright/test';

/**
* Navigate to a specific hash section and wait for DOM to load.
*/
export async function navigateTo(page: Page, hash: string): Promise<void> {
await page.goto(`/#${hash}`);
await page.waitForLoadState('domcontentloaded');
}

/**
* Wait for the provider to reach "connected" status on the current page.
* Works from any section by waiting for the section-content wrapper
* (which only renders after the provider connects and server is ready).
*/
export async function waitForConnected(page: Page, timeout = 30_000): Promise<void> {
const content = page.locator('[data-testid="section-content"]');
await expect(content).toBeVisible({ timeout });
}

/**
* Navigate to a section and wait for provider to be ready.
*/
export async function gotoSection(page: Page, hash: string, timeout = 30_000): Promise<void> {
await navigateTo(page, hash);
await waitForConnected(page, timeout);
}
38 changes: 38 additions & 0 deletions apps/e2e/demo-e2e-react/e2e/browser/mcp-component-table.pw.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { test, expect } from '@playwright/test';
import { gotoSection } from './helpers';

test.describe('MCP Component Table', () => {
test.beforeEach(async ({ page }) => {
await gotoSection(page, 'mcp-table');
});

test('shows fallback initially', async ({ page }) => {
const fallback = page.locator('[data-testid="table-fallback"]');
await expect(fallback).toBeVisible({ timeout: 10_000 });
});

test('renders table with data after trigger', async ({ page }) => {
const trigger = page.locator('[data-testid="table-trigger"]');

// Wait for trigger to be visible (tool registered) instead of arbitrary timeout
await trigger.waitFor({ state: 'visible' });
await trigger.click();

const container = page.locator('[data-testid="table-container"]');
const table = container.locator('table');
await expect(table).toBeVisible({ timeout: 10_000 });

// Check headers
const headers = table.locator('th');
await expect(headers).toHaveCount(3);
await expect(headers.nth(0)).toHaveText('Name');
await expect(headers.nth(1)).toHaveText('Age');
await expect(headers.nth(2)).toHaveText('Role');

// Check rows
const rows = table.locator('tbody tr');
await expect(rows).toHaveCount(2);
await expect(rows.nth(0).locator('td').nth(0)).toHaveText('Alice');
await expect(rows.nth(1).locator('td').nth(0)).toHaveText('Bob');
});
});
26 changes: 26 additions & 0 deletions apps/e2e/demo-e2e-react/e2e/browser/mcp-component.pw.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { test, expect } from '@playwright/test';
import { gotoSection } from './helpers';

test.describe('MCP Component', () => {
test.beforeEach(async ({ page }) => {
await gotoSection(page, 'mcp-component');
});

test('shows fallback initially', async ({ page }) => {
const fallback = page.locator('[data-testid="greeting-fallback"]');
await expect(fallback).toBeVisible({ timeout: 10_000 });
});

test('renders greeting card after trigger', async ({ page }) => {
const trigger = page.locator('[data-testid="greeting-trigger"]');
const card = page.locator('[data-testid="greeting-card"]');

// Wait for trigger to be visible (tool registered) instead of arbitrary timeout
await trigger.waitFor({ state: 'visible' });

await trigger.click();
await expect(card).toBeVisible({ timeout: 10_000 });
await expect(card.locator('h3')).toHaveText('Welcome');
await expect(card.locator('p')).toHaveText('Hello from MCP!');
});
});
29 changes: 29 additions & 0 deletions apps/e2e/demo-e2e-react/e2e/browser/provider.pw.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { test, expect } from '@playwright/test';
import { gotoSection } from './helpers';

test.describe('Provider Status', () => {
test.beforeEach(async ({ page }) => {
await gotoSection(page, 'provider');
});

test('shows connected status', async ({ page }) => {
const status = page.locator('[data-testid="status"]');
await expect(status).toHaveText('connected', { timeout: 15_000 });
});

test('displays server name', async ({ page }) => {
const serverName = page.locator('[data-testid="server-name"]');
await expect(serverName).toHaveText('default');
});

test('reports tool count >= 2', async ({ page }) => {
const toolCount = page.locator('[data-testid="tool-count"]');
const text = await toolCount.textContent();
expect(Number(text)).toBeGreaterThanOrEqual(2);
});

test('reports resource count', async ({ page }) => {
const resourceCount = page.locator('[data-testid="resource-count"]');
await expect(resourceCount).toBeVisible();
});
});
Loading
Loading