Browse Source

Merge branch 'master' into imprv/unchanged-revision

Yuki Takei 1 month ago
parent
commit
712dbfa943

+ 38 - 0
.claude/rules/testing.md

@@ -0,0 +1,38 @@
+# Testing Rules
+
+## Package Manager (CRITICAL)
+
+**NEVER use `npx` to run tests. ALWAYS use `pnpm`.**
+
+```bash
+# ❌ WRONG
+npx vitest run yjs.integ
+
+# ✅ CORRECT
+pnpm vitest run yjs.integ
+```
+
+## Test Execution Commands
+
+### Individual Test File (from package directory)
+
+```bash
+# Use partial file name - Vitest auto-matches
+pnpm vitest run yjs.integ
+pnpm vitest run helper.spec
+pnpm vitest run Button.spec
+
+# Flaky test detection
+pnpm vitest run yjs.integ --repeat=10
+```
+
+- Use **partial file name** (no `src/` prefix or full path needed)
+- No `--project` flag needed (Vitest auto-detects from file extension)
+
+### All Tests for a Package (from monorepo root)
+
+```bash
+turbo run test --filter @growi/app
+```
+
+For testing patterns (mocking, assertions, structure), see the `essential-test-patterns` skill.

+ 1 - 38
.claude/skills/learned/essential-test-patterns/SKILL.md

@@ -414,44 +414,7 @@ Before committing tests, ensure:
 
 ## Running Tests
 
-### From Monorepo Root (Recommended)
-
-```bash
-# Run all tests for a specific package
-turbo run test --filter @growi/app
-turbo run test --filter @growi/core
-
-# Or with Turborepo caching
-pnpm run test --filter @growi/app
-```
-
-### From Package Directory
-
-```bash
-# Run all tests
-pnpm vitest run
-
-# Run specific test file (use partial file name)
-pnpm vitest run yjs.integ
-pnpm vitest run helper.spec
-pnpm vitest run Button.spec
-
-# Run tests matching a pattern
-pnpm vitest run PageService
-```
-
-**File pattern tips**:
-- Use **partial file name** - Vitest automatically finds matching files
-- No need for `src/` prefix or full path
-- No need for `--project` flag - Vitest auto-detects based on file extension
-- Works across all packages (apps/app, packages/core, etc.)
-
-### Running Multiple Times (Flaky Test Detection)
-
-```bash
-# Repeat test execution to verify stability
-pnpm vitest run yjs.integ --repeat=10
-```
+See the `testing` rule (`.claude/rules/testing.md`) for test execution commands.
 
 ## Summary: GROWI Testing Philosophy
 

+ 4 - 3
.claude/skills/monorepo-overview/SKILL.md

@@ -172,10 +172,11 @@ turbo run bootstrap
 # Start all dev servers (apps/app + dependencies)
 turbo run dev
 
-# Run tests for specific package
-turbo run test --filter @growi/app
+# Run a specific test file (from package directory)
+pnpm vitest run yjs.integ
 
-# Lint specific package
+# Run ALL tests / lint for a package
+turbo run test --filter @growi/app
 turbo run lint --filter @growi/core
 ```
 

+ 10 - 2
.claude/skills/tech-stack/SKILL.md

@@ -101,7 +101,12 @@ turbo run bootstrap
 ### Testing & Quality
 
 ```bash
-# Run tests for specific package
+# Run a specific test file (from package directory, e.g. apps/app)
+pnpm vitest run yjs.integ          # Partial file name match
+pnpm vitest run helper.spec        # Works for any test file
+pnpm vitest run yjs.integ --repeat=10  # Repeat for flaky test detection
+
+# Run ALL tests for a package (uses Turborepo caching)
 turbo run test --filter @growi/app
 
 # Run linters for specific package
@@ -182,9 +187,12 @@ Package-specific tsconfig.json example:
 
 ### Command Usage
 
-1. **Always use Turborepo for cross-package tasks**:
+1. **Use Turborepo for full-package tasks** (all tests, lint, build):
    - ✅ `turbo run test --filter @growi/app`
    - ❌ `cd apps/app && pnpm test` (bypasses Turborepo caching)
+2. **Use vitest directly for individual test files** (from package directory):
+   - ✅ `pnpm vitest run yjs.integ` (simple, fast)
+   - ❌ `turbo run test --filter @growi/app -- yjs.integ` (unnecessary overhead)
 
 2. **Use pnpm for package management**:
    - ✅ `pnpm install`

+ 6 - 9
apps/app/.claude/skills/app-commands/SKILL.md

@@ -31,17 +31,14 @@ turbo run lint --filter @growi/app
 turbo run test --filter @growi/app
 turbo run build --filter @growi/app
 
-# Run INDIVIDUAL lint checks (package-specific scripts)
-pnpm --filter @growi/app run lint:typecheck   # TypeScript only
-pnpm --filter @growi/app run lint:biome       # Biome only
-pnpm --filter @growi/app run lint:styles      # Stylelint only
-
-# Alternative: Run from apps/app directory
-cd apps/app
-pnpm run lint:typecheck
-pnpm run lint:biome
+# Run INDIVIDUAL lint checks (package-specific scripts, from apps/app directory)
+pnpm run lint:typecheck   # TypeScript only
+pnpm run lint:biome       # Biome only
+pnpm run lint:styles      # Stylelint only
 ```
 
+> **Running individual test files**: See the `testing` rule (`.claude/rules/testing.md`).
+
 ### Common Mistake
 
 ```bash

+ 6 - 9
apps/app/src/server/service/yjs/yjs.integ.ts

@@ -1,5 +1,5 @@
 import { YDocStatus } from '@growi/core/dist/consts';
-import mongoose, { Types } from 'mongoose';
+import { Types } from 'mongoose';
 import type { Server } from 'socket.io';
 import { mock } from 'vitest-mock-extended';
 
@@ -28,15 +28,11 @@ const getPrivateMdbInstance = (yjsService: IYjsService): MongodbPersistence => {
 
 describe('YjsService', () => {
   describe('getYDocStatus()', () => {
-    beforeAll(async () => {
+    beforeAll(() => {
       const ioMock = mock<Server>();
 
       // initialize
       initializeYjsService(ioMock);
-
-      // Wait for index creation to complete to avoid race condition
-      const collection = mongoose.connection.collection('yjs-writings');
-      await collection.listIndexes().toArray();
     });
 
     afterAll(async () => {
@@ -49,9 +45,10 @@ describe('YjsService', () => {
       try {
         await privateMdb.flushDB();
       } catch (error) {
-        // Ignore IndexBuildAborted error (code: 276) which can occur in CI
-        // when cleanup happens while index creation is still in progress
-        if (error.code !== 276) {
+        // Ignore errors that can occur due to async index creation:
+        // - 26: NamespaceNotFound (collection not yet created)
+        // - 276: IndexBuildAborted (cleanup during index creation)
+        if (error.code !== 26 && error.code !== 276) {
           throw error;
         }
       }