name: Test on: pull_request: branches: [main] push: branches: [main] jobs: lint-and-unit: name: Lint & Unit Tests runs-on: ubuntu-latest steps: - uses: actions/checkout@v6 - name: Setup Node.js uses: actions/setup-node@v6 with: node-version: "20" cache: "npm" - name: Install dependencies run: npm ci - name: Run lint run: npm run check - name: Run unit tests run: npm run test -- --run # The MCP server package ships its own vitest because its DOM polyfill # (linkedom) needs `environment: node`, while the root vitest uses jsdom # for the Next.js app. Install + run its tests separately so CI catches # multi-page mxfile regressions. - name: Install MCP server dependencies run: npm --prefix packages/mcp-server ci - name: Run MCP server unit tests run: npm --prefix packages/mcp-server test # Tests run from src/, so check the built npm package separately - name: Build MCP server and check package contents run: npm --prefix packages/mcp-server run build && npm --prefix packages/mcp-server run check-package e2e: # Six jobs at once, each with a sixth of the tests and one worker: the # same conditions per test, a fraction of the time name: E2E Tests (${{ matrix.shard }}/6) runs-on: ubuntu-latest strategy: fail-fast: false matrix: shard: [1, 2, 3, 4, 5, 6] steps: - uses: actions/checkout@v6 - name: Setup Node.js uses: actions/setup-node@v6 with: node-version: "20" cache: "npm" - name: Install dependencies run: npm ci - name: Cache Playwright browsers uses: actions/cache@v5 id: playwright-cache with: path: ~/.cache/ms-playwright key: playwright-${{ runner.os }}-${{ hashFiles('**/package-lock.json') }} - name: Install Playwright browsers if: steps.playwright-cache.outputs.cache-hit != 'true' run: npx playwright install chromium --with-deps - name: Install Playwright deps (cached) if: steps.playwright-cache.outputs.cache-hit == 'true' run: npx playwright install-deps chromium - name: Build app run: npm run build # The MCP package ships a trimmed draw.io; this drives the full copy # (public/drawio, downloaded by the build) in Chromium and fails when # the editor requests a file its list does not have. Once is enough. - name: Check the MCP draw.io file list if: matrix.shard == 1 run: npm --prefix packages/mcp-server run check-drawio - name: Run E2E tests run: npm run test:e2e -- --shard=${{ matrix.shard }}/6 env: CI: true # The canvas shell in a browser, from the package as npm installs it: # the packed tarball goes into an empty directory, its dist/index.js is # started over stdio and headless Chromium opens the URL start_session # returns (packages/mcp-server/tests/e2e). Chromium is installed above; # the build shares the root build's draw.war download. - name: Run the MCP shell E2E tests on the packed tarball if: matrix.shard == 1 run: | npm --prefix packages/mcp-server ci npm --prefix packages/mcp-server run build mkdir -p "$RUNNER_TEMP/mcp-pack" "$RUNNER_TEMP/mcp-install" npm pack ./packages/mcp-server --pack-destination "$RUNNER_TEMP/mcp-pack" npm --prefix "$RUNNER_TEMP/mcp-install" install "$RUNNER_TEMP"/mcp-pack/*.tgz MCP_SERVER_ENTRY="$RUNNER_TEMP/mcp-install/node_modules/@next-ai-drawio/mcp-server/dist/index.js" \ npm --prefix packages/mcp-server run test:e2e env: CI: true - name: Upload test results uses: actions/upload-artifact@v6 if: always() with: name: playwright-report-${{ matrix.shard }} path: | playwright-report/ packages/mcp-server/test-results/ retention-days: 7