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
58 changes: 58 additions & 0 deletions .github/workflows/deploy-docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,12 @@ jobs:
echo "prod=true" >> "$GITHUB_OUTPUT"
echo "base_url=docs" >> "$GITHUB_OUTPUT"
echo "project=marketdata-docs" >> "$GITHUB_OUTPUT"
echo "environment=production" >> "$GITHUB_OUTPUT"
else
echo "prod=" >> "$GITHUB_OUTPUT"
echo "base_url=docs-staging" >> "$GITHUB_OUTPUT"
echo "project=marketdata-docs-staging" >> "$GITHUB_OUTPUT"
echo "environment=staging" >> "$GITHUB_OUTPUT"
fi

- name: Build
Expand Down Expand Up @@ -67,6 +69,31 @@ jobs:
" Cache-Control: public, max-age=31536000, immutable" \
> build/_headers

- name: Upload to R2
env:
AWS_ACCESS_KEY_ID: ${{ secrets.R2_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.R2_SECRET_ACCESS_KEY }}
AWS_ENDPOINT_URL: https://${{ secrets.CLOUDFLARE_ACCOUNT_ID }}.r2.cloudflarestorage.com
AWS_REGION: auto
run: |
aws s3 sync build/ \
"s3://www-marketdata-app-builds/${{ steps.env.outputs.environment }}/" \
--delete

# - name: Notify orchestrator
# if: success()
# uses: peter-evans/repository-dispatch@v3
# with:
# token: ${{ secrets.ORCHESTRATOR_PAT }}
# repository: MarketDataApp/www-marketdata-app
# event-type: site-built
# client-payload: >-
# {
# "source": "docs",
# "environment": "${{ steps.env.outputs.environment }}",
# "commit_sha": "${{ github.sha }}"
# }

- name: Deploy to Cloudflare Pages
uses: cloudflare/wrangler-action@v3
with:
Expand Down Expand Up @@ -101,3 +128,34 @@ jobs:
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
command: deploy
workingDirectory: worker

post-deploy-tests:
needs: deploy
if: github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- uses: actions/setup-node@v4
with:
node-version: 22
cache: yarn

- run: yarn install --frozen-lockfile

- name: Install worker test dependencies
working-directory: worker
run: yarn install --frozen-lockfile

- name: Run integration tests against production
working-directory: worker
env:
TEST_ENV: production
run: yarn test:integration

- run: npx playwright install chromium

- name: Run e2e tests against production
env:
TEST_ENV: production
run: yarn test:e2e
62 changes: 62 additions & 0 deletions .github/workflows/pr-checks.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
name: PR Checks (Staging Integration Tests)

on:
pull_request:
branches: [main]

jobs:
worker-unit-tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- uses: actions/setup-node@v4
with:
node-version: 22
cache: yarn
cache-dependency-path: worker/yarn.lock

- run: yarn install --frozen-lockfile
working-directory: worker

- run: yarn test
working-directory: worker

staging-integration-tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- uses: actions/setup-node@v4
with:
node-version: 22
cache: yarn
cache-dependency-path: worker/yarn.lock

- run: yarn install --frozen-lockfile
working-directory: worker

- name: Run integration tests against staging
working-directory: worker
env:
TEST_ENV: staging
run: yarn test:integration

staging-e2e-tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- uses: actions/setup-node@v4
with:
node-version: 22
cache: yarn

- run: yarn install --frozen-lockfile

- run: npx playwright install chromium

- name: Run e2e tests against staging
env:
TEST_ENV: staging
run: yarn test:e2e
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ llm-docs/
*.draft
.cursorignore
.playwright-mcp/
test-results/

npm-debug.log*
yarn-debug.log*
Expand Down
28 changes: 28 additions & 0 deletions docusaurus.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,34 @@ const config = {
from: "/api/universal-parameters/feed",
to: "/api/universal-parameters/mode",
},
{
from: "/sheets/automatic-refreshing",
to: "/sheets/automatic-refresh",
},
{
from: "/sheets/stockdata",
to: "/sheets/stocks/stockdata",
},
{
from: "/sheets/earnings",
to: "/sheets/stocks/earnings",
},
{
from: "/sheets/optiondata",
to: "/sheets/options/optiondata",
},
{
from: "/sheets/optionlookup",
to: "/sheets/options/optionlookup",
},
{
from: "/sheets/optionchain",
to: "/sheets/options/optionchain",
},
{
from: "/sheets/marketstatus",
to: "/sheets/markets/marketstatus",
},
],
},
],
Expand Down
45 changes: 45 additions & 0 deletions e2e/context7-widget.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/**
* Smoke test: verifies the Context7 chat widget loads and renders
* the expected DOM structure on pages where it should appear.
*
* Catches breaking changes from Context7 (renamed classes, removed
* shadow DOM, changed container IDs, script load failures, etc.).
*
* Run with: yarn test:e2e
*/
import { test, expect } from '@playwright/test';

const BASE_URL = process.env.TEST_ENV === 'staging'
? 'https://www.marketdata.app/docs-staging'
: 'https://www.marketdata.app/docs';

// One representative page per widget configuration.
const WIDGET_PAGES = [
{ path: '/api', name: 'API' },
{ path: '/sheets', name: 'Sheets' },
{ path: '/sdk/py', name: 'Python SDK' },
{ path: '/sdk/go', name: 'Go SDK' },
{ path: '/sdk/php', name: 'PHP SDK' },
];

for (const { path, name } of WIDGET_PAGES) {
test(`Context7 widget loads on ${name} page (${path})`, async ({ page }) => {
await page.goto(`${BASE_URL}${path}`, { waitUntil: 'domcontentloaded' });

// 1. Widget script tag should be injected.
const script = page.locator('#context7-widget-script');
await expect(script).toBeAttached({ timeout: 10_000 });

// 2. Widget container should appear.
const container = page.locator('#context7-widget');
await expect(container).toBeAttached({ timeout: 15_000 });

// 3. Shadow DOM should be created with the expected panel structure.
const hasPanel = await container.evaluate((el) => {
const sr = el.shadowRoot;
if (!sr) return false;
return sr.querySelector('.c7-panel') !== null;
});
expect(hasPanel, 'Shadow DOM missing .c7-panel element').toBe(true);
});
}
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@
"write-translations": "docusaurus write-translations",
"write-heading-ids": "docusaurus write-heading-ids",
"typecheck": "tsc",
"generate-docs": "node scripts/generate-master-docs.js"
"generate-docs": "node scripts/generate-master-docs.js",
"test:e2e": "playwright test"
},
"dependencies": {
"@docusaurus/core": "3.0.1",
Expand All @@ -30,6 +31,7 @@
"devDependencies": {
"@docusaurus/module-type-aliases": "3.0.1",
"@docusaurus/tsconfig": "3.0.1",
"@playwright/test": "^1.58.2",
"@tsconfig/docusaurus": "^1.0.5",
"typescript": "^4.7.4"
},
Expand Down
13 changes: 13 additions & 0 deletions playwright.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { defineConfig } from '@playwright/test';

export default defineConfig({
testDir: './e2e',
timeout: 30_000,
retries: 1,
use: {
headless: true,
},
projects: [
{ name: 'chromium', use: { browserName: 'chromium' } },
],
});
Loading