技能 编程开发 OneNote CI/CD集成测试部署

OneNote CI/CD集成测试部署

v20260423
onenote-ci-integration
本技能旨在帮助用户为OneNote的Graph API集成建立完整的CI/CD测试流程。它提供了两种测试策略:使用Mock Service Worker (MSW) 进行零依赖的PR检查,以及使用Azure AD凭证进行夜间实时的集成测试,确保代码质量和稳定性。
获取技能
394 次下载
概览

OneNote CI Integration

Overview

Testing OneNote integrations in CI requires Azure AD app registration, credential management, and mock strategies for Graph API responses. This skill provides two proven CI strategies: mock-only PR checks (zero Azure credentials required) and nightly live integration tests with proper credential isolation and rate limit awareness.

Prerequisites

  • GitHub Actions or equivalent CI platform
  • Node.js 18+ or Python 3.10+
  • For mock-only CI: no Azure credentials needed
  • For live integration tests: Azure AD test tenant with app registration
  • GitHub repository secrets configured (live tests only)

Instructions

Strategy 1: Mock-Only CI (PR Checks)

Use msw (Mock Service Worker) to intercept Graph API calls with zero Azure dependency:

// tests/mocks/handlers.ts
import { http, HttpResponse } from "msw";
const GRAPH = "https://graph.microsoft.com/v1.0";

export const handlers = [
  http.get(`${GRAPH}/me/onenote/notebooks`, () =>
    HttpResponse.json({ value: [
      { id: "nb-001", displayName: "Work Notes", createdDateTime: "2026-01-15T10:00:00Z" },
    ]})),

  http.get(`${GRAPH}/me/onenote/sections/:sectionId/pages`, () =>
    HttpResponse.json({ value: [
      { id: "page-001", title: "Sprint Review", createdDateTime: "2026-03-10T14:00:00Z" },
    ]})),

  http.post(`${GRAPH}/me/onenote/sections/:sectionId/pages`, async ({ request }) => {
    const body = await request.text();
    if (!body.includes("<html")) {
      return new HttpResponse(JSON.stringify({
        error: { code: "InvalidArgument", message: "Page content must be valid XHTML" }
      }), { status: 400 });
    }
    return HttpResponse.json({ id: "page-new", title: "Created Page" }, { status: 201 });
  }),
];
// tests/setup.ts
import { setupServer } from "msw/node";
import { handlers } from "./mocks/handlers";
export const server = setupServer(...handlers);
beforeAll(() => server.listen({ onUnhandledRequest: "error" }));
afterEach(() => server.resetHandlers());
afterAll(() => server.close());

Strategy 2: Live Integration Tests (Nightly)

Required GitHub Secrets: AZURE_TENANT_ID, AZURE_CLIENT_ID, AZURE_CLIENT_SECRET.

Warning: ClientSecretCredential (app-only auth) was deprecated March 31, 2025 for OneNote APIs. CI test environments may still use it for automation, but production code must use delegated auth. Monitor Microsoft deprecation notices.

GitHub Actions Workflows

# .github/workflows/onenote-pr.yml — Mock-only, every PR
name: OneNote PR Checks
on: [push, pull_request]
jobs:
  mock-tests:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with: { node-version: 20, cache: npm }
      - run: npm ci && npm test -- --reporter=verbose
        env: { ONENOTE_TEST_MODE: mock }
# .github/workflows/onenote-nightly.yml — Live tests, daily 3AM UTC
name: OneNote Integration Tests
on:
  schedule: [{ cron: "0 3 * * *" }]
  workflow_dispatch:
jobs:
  integration:
    runs-on: ubuntu-latest
    concurrency: { group: onenote-live-tests, cancel-in-progress: false }
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with: { node-version: 20, cache: npm }
      - run: npm ci && npm test -- --testPathPattern="integration"
        env:
          ONENOTE_TEST_MODE: live
          AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
          AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
          AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
      - name: Cleanup test notebooks
        if: always()
        run: node scripts/cleanup-test-notebooks.js
        env:
          AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
          AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
          AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}

Test Isolation

Each test creates resources with a unique prefix. Note: OneNote notebooks cannot be deleted via Graph API — use a disposable test tenant or archive-based cleanup.

// tests/helpers/test-context.ts
import { randomUUID } from "crypto";
export function createTestContext() {
  const prefix = `ci-test-${randomUUID().slice(0, 8)}`;
  return {
    notebookName: `${prefix}-notebook`,
    sectionName: `${prefix}-section`,
    prefix,
  };
}

Rate Limit Awareness

Stay under 600 req/60s per user across parallel test jobs:

export async function withRateLimit<T>(fn: () => Promise<T>): Promise<T> {
  await new Promise((r) => setTimeout(r, 200));
  try { return await fn(); }
  catch (err: any) {
    if (err?.statusCode === 429) {
      const retry = parseInt(err.headers?.["retry-after"] ?? "5", 10);
      await new Promise((r) => setTimeout(r, retry * 1000));
      return fn();
    }
    throw err;
  }
}

Output

  • .github/workflows/onenote-pr.yml — mock-based PR check workflow
  • .github/workflows/onenote-nightly.yml — live integration test workflow
  • tests/mocks/handlers.ts — MSW handlers for Graph API endpoints
  • tests/setup.ts — mock server lifecycle management
  • tests/helpers/test-context.ts — test isolation with unique prefixes

Error Handling

CI Error Cause Fix
401 Unauthorized in nightly Expired client secret Rotate AZURE_CLIENT_SECRET in GitHub Settings > Secrets
403 Forbidden in live tests Missing Notes.ReadWrite scope Update app registration API permissions in Azure portal
Mock handler mismatch onUnhandledRequest: "error" caught unknown URL Add missing endpoint to handlers.ts
Rate limit in parallel jobs Multiple CI runs hitting same tenant Use concurrency group to serialize nightly runs
Orphaned test notebooks Cleanup step skipped OneNote notebooks cannot be API-deleted; archive manually

Examples

# Run mock tests locally
ONENOTE_TEST_MODE=mock npm test

# Run single integration test against live API
ONENOTE_TEST_MODE=live AZURE_TENANT_ID=xxx AZURE_CLIENT_ID=yyy \
  AZURE_CLIENT_SECRET=zzz npx vitest run tests/integration/notebooks.test.ts

Resources

Next Steps

  • Deploy tested integrations with onenote-deploy-integration
  • Debug CI failures with onenote-debug-bundle
  • Monitor rate limits in CI with onenote-rate-limits
信息
Category 编程开发
Name onenote-ci-integration
版本 v20260423
大小 4.33KB
更新时间 2026-04-28
语言