diff --git a/.github/workflows/make-and-test.yml b/.github/workflows/make-and-test.yml index b233bf2421..72a3df57fa 100644 --- a/.github/workflows/make-and-test.yml +++ b/.github/workflows/make-and-test.yml @@ -1,4 +1,4 @@ -name: Make all packages and run their tests +name: Test # newer commits in the same PR abort running ones for the same workflow concurrency: @@ -43,7 +43,7 @@ jobs: - name: Check doc links run: cd src/scripts && python3 check_doc_urls.py || sleep 5 || python3 check_doc_urls.py - build: + test: runs-on: ubuntu-latest services: @@ -94,7 +94,7 @@ jobs: - name: Download and install Valkey run: | VALKEY_VERSION=8.1.2 - curl -LO https://download.valkey.io/releases/valkey-${VALKEY_VERSION}-jammy-x86_64.tar.gz + curl -LOq https://download.valkey.io/releases/valkey-${VALKEY_VERSION}-jammy-x86_64.tar.gz tar -xzf valkey-${VALKEY_VERSION}-jammy-x86_64.tar.gz sudo cp valkey-${VALKEY_VERSION}-jammy-x86_64/bin/valkey-server /usr/local/bin/ @@ -106,6 +106,54 @@ jobs: pip install ipykernel python -m ipykernel install --prefix=./jupyter-local --name python3-local --display-name "Python 3 (Local)" - - run: cd src && npm install -g pnpm - - run: cd src && pnpm run make - - run: source venv/bin/activate && cd src && pnpm run test-github-ci + + - name: install pnpm + #run: cd src && npm install -g pnpm + uses: pnpm/action-setup@v4 + with: + version: 10 + run_install: false + + - name: build + run: cd src && pnpm run make + + - name: test + run: source venv/bin/activate && cd src && pnpm run test-github-ci:report + + - name: upload test results + uses: actions/upload-artifact@v4 # upload test results + if: ${{ !cancelled() }} # run this step even if previous step failed + with: + name: "test-results-node-${{ matrix.node-version }}-pg-${{ matrix.pg-version }}" + path: 'src/packages/*/junit.xml' + + - name: dependency check + run: cd src && pnpm run depcheck + + report: + runs-on: ubuntu-latest + + needs: [test] + + if: ${{ !cancelled() }} + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Download all test artifacts + uses: actions/download-artifact@v4 + with: + pattern: "test-results-*" + merge-multiple: true + path: test-results/ + + - name: Test Report + uses: dorny/test-reporter@v2 + with: + name: CoCalc Jest Tests + path: 'test-results/**/junit.xml' + reporter: jest-junit + use-actions-summary: 'true' + fail-on-error: false + diff --git a/.gitignore b/.gitignore index 7f06ad5a5c..331ad90a59 100644 --- a/.gitignore +++ b/.gitignore @@ -159,3 +159,6 @@ src/packages/frontend/i18n/trans/*.compiled.json **/*.db **/project-env.sh **/*.bash_history + +# test reports by jest-junit +junit.xml diff --git a/src/CLAUDE.md b/src/CLAUDE.md index a816597ef0..d530f9f0f4 100644 --- a/src/CLAUDE.md +++ b/src/CLAUDE.md @@ -1,18 +1,19 @@ -# CLAUDE.md +# CLAUDE.md and GEMINI.md -This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. +This file provides guidance to Claude Code (claude.ai/code) and also Gemini CLI (https://github.com/google-gemini/gemini-cli) when working with code in this repository. # CoCalc Source Repository -* This is the source code of CoCalc in a Git repository -* It is a complex JavaScript/TypeScript SaaS application -* CoCalc is organized as a monorepository (multi-packages) in the subdirectory "./packages" -* The packages are managed as a pnpm workspace in "./packages/pnpm-workspace.yaml" +- This is the source code of CoCalc in a Git repository +- It is a complex JavaScript/TypeScript SaaS application +- CoCalc is organized as a monorepository (multi-packages) in the subdirectory "./packages" +- The packages are managed as a pnpm workspace in "./packages/pnpm-workspace.yaml" ## Code Style - Everything is written in TypeScript code - Indentation: 2-spaces +- Run `pretter -w [filename]` after modifying a file (ts, tsx, md, json, ...) to format it correctly. - All .js and .ts files are formatted by the tool prettier - Add suitable types when you write code - Variable name styles are "camelCase" for local and "FOO_BAR" for global variables. If you edit older code not following these guidlines, adjust this rule to fit the files style. @@ -23,28 +24,32 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co ## Development Commands ### Essential Commands + - `pnpm build-dev` - Build all packages for development - `pnpm clean` - Clean all node_modules and dist directories -- `pnpm database` - Start PostgreSQL database server -- `pnpm hub` - Start the main hub server -- `pnpm psql` - Connect to the PostgreSQL database - `pnpm test` - Run full test suite -- `pnpm test-parallel` - Run tests in parallel across packages - `pnpm depcheck` - Check for dependency issues +- `prettier -w [filename]` to format the style of a file after editing it +- after creating a file, run `git add [filename]` to start tracking it ### Package-Specific Commands -- `cd packages/[package] && pnpm tsc` - Watch TypeScript compilation for a specific package + +- `cd packages/[package] && pnpm build` - Build and compile a specific package + - for packages/next and packages/static, run `cd packages/[package] && pnpm build-dev` +- `cd packages/[package] && pnpm tsc:watch` - TypeScript compilation in watch mode for a specific package - `cd packages/[package] && pnpm test` - Run tests for a specific package - `cd packages/[package] && pnpm build` - Build a specific package +- **IMPORTANT**: When modifying packages like `util` that other packages depend on, you must run `pnpm build` in the modified package before typechecking dependent packages -### Development Setup -1. Start database: `pnpm database` -2. Start hub: `pnpm hub` -3. For TypeScript changes, run `pnpm tsc` in the relevant package directory +### Development + +- **IMPORTANT**: Always run `prettier -w [filename]` immediately after editing any .ts, .tsx, .md, or .json file to ensure consistent styling +- After TypeScript or `*.tsx` changes, run `pnpm build` in the relevant package directory ## Architecture Overview ### Package Structure + CoCalc is organized as a monorepo with key packages: - **frontend** - React/TypeScript frontend application using Redux-style stores and actions @@ -62,12 +67,14 @@ CoCalc is organized as a monorepo with key packages: ### Key Architectural Patterns #### Frontend Architecture + - **Redux-style State Management**: Uses custom stores and actions pattern (see `packages/frontend/app-framework/actions-and-stores.ts`) - **TypeScript React Components**: All frontend code is TypeScript with proper typing - **Modular Store System**: Each feature has its own store/actions (AccountStore, BillingStore, etc.) - **WebSocket Communication**: Real-time communication with backend via WebSocket messages #### Backend Architecture + - **PostgreSQL Database**: Primary data store with sophisticated querying system - **WebSocket Messaging**: Real-time communication between frontend and backend - **Conat System**: Container orchestration for compute servers @@ -75,12 +82,15 @@ CoCalc is organized as a monorepo with key packages: - **Microservice-like Packages**: Each package handles specific functionality #### Communication Patterns + - **WebSocket Messages**: Primary communication method (see `packages/comm/websocket/types.ts`) - **Database Queries**: Structured query system with typed interfaces - **Event Emitters**: Inter-service communication within backend - **REST-like APIs**: Some HTTP endpoints for specific operations +- **API Schema**: API endpoints in `packages/next/pages/api/v2/` use Zod schemas in `packages/next/lib/api/schema/` for validation. These schemas must be kept in harmony with the TypeScript types sent from frontend applications using `apiPost` (in `packages/next/lib/api/post.ts`) or `api` (in `packages/frontend/client/api.ts`). When adding new fields to API requests, both the frontend types and the API schema validation must be updated. ### Key Technologies + - **TypeScript**: Primary language for all new code - **React**: Frontend framework - **PostgreSQL**: Database @@ -91,11 +101,13 @@ CoCalc is organized as a monorepo with key packages: - **SASS**: CSS preprocessing ### Database Schema + - Comprehensive schema in `packages/util/db-schema` - Query abstractions in `packages/database/postgres/` - Type-safe database operations with TypeScript interfaces ### Testing + - **Jest**: Primary testing framework - **ts-jest**: TypeScript support for Jest - **jsdom**: Browser environment simulation for frontend tests @@ -103,28 +115,42 @@ CoCalc is organized as a monorepo with key packages: - Each package has its own jest.config.js ### Import Patterns + - Use absolute imports with `@cocalc/` prefix for cross-package imports - Example: `import { cmp } from "@cocalc/util/misc"` - Type imports: `import type { Foo } from "./bar"` - Destructure imports when possible ### Development Workflow -1. Changes to TypeScript require compilation (`pnpm tsc` in relevant package) + +1. Changes to TypeScript require compilation (`pnpm build` in relevant package) 2. Database must be running before starting hub 3. Hub coordinates all services and should be restarted after changes 4. Use `pnpm clean && pnpm build-dev` when switching branches or after major changes # Workflow -- Be sure to typecheck when you're done making a series of code changes + +- Be sure to build when you're done making a series of code changes - Prefer running single tests, and not the whole test suite, for performance ## Git Workflow +- Never modify a file when in the `master` or `main` branch +- All changes happen through feature branches, which are pushed as pull requests to GitHub +- When creating a new file, run `git add [filename]` to track the file. - Prefix git commits with the package and general area. e.g. 'frontend/latex: ...' if it concerns latex editor changes in the packages/frontend/... code. - When pushing a new branch to Github, track it upstream. e.g. `git push --set-upstream origin feature-foo` for branch "feature-foo". -# important-instruction-reminders +# Important Instruction Reminders + - Do what has been asked; nothing more, nothing less. - NEVER create files unless they're absolutely necessary for achieving your goal. - ALWAYS prefer editing an existing file to creating a new one. -- NEVER proactively create documentation files (*.md) or README files. Only create documentation files if explicitly requested by the User. +- REFUSE to modify files when the git repository is on the `master` or `main` branch. +- NEVER proactively create documentation files (`*.md`) or README files. Only create documentation files if explicitly requested by the User. + +# Ignore + +- Ignore files covered by `.gitignore` +- Ignore everything in `node_modules` or `dist` directories +- Ignore all files not tracked by Git, unless they are newly created files diff --git a/src/GEMINI.md b/src/GEMINI.md new file mode 120000 index 0000000000..681311eb9c --- /dev/null +++ b/src/GEMINI.md @@ -0,0 +1 @@ +CLAUDE.md \ No newline at end of file diff --git a/src/package.json b/src/package.json index d0f0701277..02a304f3e8 100644 --- a/src/package.json +++ b/src/package.json @@ -19,6 +19,7 @@ "test-parallel": "unset DEBUG && pnpm run version-check && cd packages && pnpm run -r --parallel test", "test": "unset DEBUG && pnpm run depcheck && pnpm run version-check && ./workspaces.py test", "test-github-ci": "unset DEBUG && pnpm run depcheck && pnpm run version-check && ./workspaces.py test --exclude=jupyter,file-server --retries=1", + "test-github-ci:report": "pnpm run test-github-ci --report", "depcheck": "cd packages && pnpm run -r --parallel depcheck", "prettier-all": "cd packages/", "local-ci": "./scripts/ci.sh", diff --git a/src/packages/assets/package.json b/src/packages/assets/package.json index f21edd577a..0bbc2d006a 100644 --- a/src/packages/assets/package.json +++ b/src/packages/assets/package.json @@ -11,6 +11,7 @@ "preinstall": "npx only-allow pnpm", "build": "./build.sh", "test": "../node_modules/.bin/jest", + "test:report": "pnpm run test -- --reporters=default --reporters=jest-junit", "prepublishOnly": "pnpm test" }, "keywords": ["cocalc"], diff --git a/src/packages/backend/package.json b/src/packages/backend/package.json index ebcc660430..6bc48411a1 100644 --- a/src/packages/backend/package.json +++ b/src/packages/backend/package.json @@ -10,14 +10,19 @@ "./auth/*": "./dist/auth/*.js", "./auth/tokens/*": "./dist/auth/tokens/*.js" }, - "keywords": ["utilities", "cocalc"], + "keywords": [ + "utilities", + "cocalc" + ], "scripts": { "preinstall": "npx only-allow pnpm", "clean": "rm -rf dist node_modules", "build": "pnpm exec tsc --build", "tsc": "pnpm exec tsc --watch --pretty --preserveWatchOutput", "test": "pnpm exec jest --forceExit", + "test:report": "pnpm run test -- --reporters=default --reporters=jest-junit", "test-conat": " pnpm exec jest --forceExit conat", + "test-conat:report": " pnpm exec jest --forceExit conat --reporters=default --reporters=jest-junit", "testp": "pnpm exec jest --forceExit", "depcheck": "pnpx depcheck --ignores events", "prepublishOnly": "pnpm test", @@ -28,7 +33,12 @@ "conat-persist": "DEBUG=cocalc:* node ./bin/conat-persist.cjs", "conat-test-server": "node ./bin/conat-test-server.cjs" }, - "files": ["dist/**", "bin/**", "README.md", "package.json"], + "files": [ + "dist/**", + "bin/**", + "README.md", + "package.json" + ], "author": "SageMath, Inc.", "license": "SEE LICENSE.md", "dependencies": { @@ -57,6 +67,7 @@ }, "homepage": "https://github.com/sagemathinc/cocalc/tree/master/src/packages/backend", "devDependencies": { - "@types/node": "^18.16.14" + "@types/node": "^18.16.14", + "jest-junit": "^16.0.0" } } diff --git a/src/packages/cdn/package.json b/src/packages/cdn/package.json index 62c4a84578..54c1e6c935 100644 --- a/src/packages/cdn/package.json +++ b/src/packages/cdn/package.json @@ -16,6 +16,7 @@ "build": "rm -rf build dist && mkdir build && cp -rv *.json *.py *.js build/ && cd build && npm ci && mkdir dist && ./setup.py && mv dist .. && cd .. && rm -rf build ", "postinstall": "./postinstall.js", "test": "../node_modules/.bin/jest", + "test:report": "pnpm run test -- --reporters=default --reporters=jest-junit", "prepublishOnly": "npm test" }, "homepage": "https://github.com/sagemathinc/cocalc/tree/master/src/packages/cdn", diff --git a/src/packages/conat/package.json b/src/packages/conat/package.json index 79bfe77778..81cb3f475d 100644 --- a/src/packages/conat/package.json +++ b/src/packages/conat/package.json @@ -22,6 +22,7 @@ "clean": "rm -rf dist node_modules", "tsc": "pnpm exec tsc --watch --pretty --preserveWatchOutput", "test": "pnpm exec jest", + "test:report": "pnpm run test -- --reporters=default --reporters=jest-junit", "depcheck": "pnpx depcheck --ignores events" }, "files": [ diff --git a/src/packages/database/package.json b/src/packages/database/package.json index 15b29d94fe..d63912ffd6 100644 --- a/src/packages/database/package.json +++ b/src/packages/database/package.json @@ -38,7 +38,8 @@ "@types/lodash": "^4.14.202", "@types/node": "^18.16.14", "@types/pg": "^8.6.1", - "coffeescript": "^2.5.1" + "coffeescript": "^2.5.1", + "jest-junit": "^16.0.0" }, "scripts": { "preinstall": "npx only-allow pnpm", @@ -46,6 +47,7 @@ "clean": "rm -rf dist", "tsc": "../node_modules/.bin/tsc --watch --pretty --preserveWatchOutput", "test": "pnpm exec jest --forceExit --runInBand", + "test:report": "pnpm run test -- --reporters=default --reporters=jest-junit", "depcheck": "pnpx depcheck | grep -Ev '\\.coffee|coffee$'", "prepublishOnly": "pnpm test" }, diff --git a/src/packages/file-server/package.json b/src/packages/file-server/package.json index 58285c4bf6..3abd62ac07 100644 --- a/src/packages/file-server/package.json +++ b/src/packages/file-server/package.json @@ -11,6 +11,7 @@ "build": "pnpm exec tsc --build", "tsc": "pnpm exec tsc --watch --pretty --preserveWatchOutput", "test": "pnpm exec jest", + "test:report": "pnpm run test -- --reporters=default --reporters=jest-junit", "depcheck": "pnpx depcheck", "clean": "rm -rf node_modules dist" }, diff --git a/src/packages/frontend/package.json b/src/packages/frontend/package.json index 0273815472..bc7a579ad8 100644 --- a/src/packages/frontend/package.json +++ b/src/packages/frontend/package.json @@ -175,6 +175,7 @@ "build-coffee": "pnpm exec coffee -m -c -o dist/ .", "tsc": "NODE_OPTIONS=--max-old-space-size=8192 ../node_modules/.bin/tsc --watch --pretty --preserveWatchOutput ", "test": "jest", + "test:report": "pnpm run test -- --reporters=default --reporters=jest-junit", "depcheck": "pnpx depcheck --ignores cspell,@cspell/dict-typescript,events,@formatjs/cli | grep -Ev '\\.coffee|coffee$'", "prepublishOnly": "pnpm test", "update-color-scheme": "node ./update-color-scheme.js", diff --git a/src/packages/hub/package.json b/src/packages/hub/package.json index 5fee5ebd7d..86f16bfda4 100644 --- a/src/packages/hub/package.json +++ b/src/packages/hub/package.json @@ -49,7 +49,8 @@ "devDependencies": { "@types/express": "^4.17.21", "@types/node": "^18.16.14", - "coffeescript": "^2.5.1" + "coffeescript": "^2.5.1", + "jest-junit": "^16.0.0" }, "scripts": { "preinstall": "npx only-allow pnpm", @@ -64,6 +65,8 @@ "hub-docker-prod": "export DEBUG=${DEBUG:='cocalc:*,-cocalc:silly:*'} && COCALC_DOCKER=true NODE_ENV=production PROJECTS=/projects/[project_id] PORT=443 NODE_OPTIONS='--max_old_space_size=8000 --enable-source-maps' cocalc-hub-server --mode=multi-user --all --hostname=0.0.0.0 --https-key=/projects/conf/cert/key.pem --https-cert=/projects/conf/cert/cert.pem", "hub-docker-prod-nossl": "export DEBUG=${DEBUG:='cocalc:*,-cocalc:silly:*'} && COCALC_DOCKER=true NODE_ENV=production PROJECTS=/projects/[project_id] PORT=80 NODE_OPTIONS='--max_old_space_size=8000 --enable-source-maps' cocalc-hub-server --mode=multi-user --all --hostname=0.0.0.0", "tsc": "tsc --watch --pretty --preserveWatchOutput", + "test": "jest dist/", + "test:report": "pnpm run test -- --reporters=default --reporters=jest-junit", "depcheck": "pnpx depcheck | grep -Ev '\\.coffee|coffee$'", "prepublishOnly": "test" }, diff --git a/src/packages/jupyter/package.json b/src/packages/jupyter/package.json index d1e3f3ab14..a76b24cab7 100644 --- a/src/packages/jupyter/package.json +++ b/src/packages/jupyter/package.json @@ -24,6 +24,7 @@ "build": "../node_modules/.bin/tsc --build", "clean": "rm -rf node_modules dist", "test": "pnpm exec jest --forceExit --maxWorkers=1", + "test:report": "pnpm run test -- --reporters=default --reporters=jest-junit", "depcheck": "pnpx depcheck", "tsc": "../node_modules/.bin/tsc --watch --pretty --preserveWatchOutput" }, diff --git a/src/packages/next/package.json b/src/packages/next/package.json index 53e18c0b60..3c95db4652 100644 --- a/src/packages/next/package.json +++ b/src/packages/next/package.json @@ -36,6 +36,7 @@ "start": "unset PGHOST; pnpm exec next start", "start-project": "unset PGHOST PGUSER COCALC_ROOT; export PORT=5000 BASE_PATH=/$COCALC_PROJECT_ID/port/5000; echo https://cocalc.com$BASE_PATH; pnpm start", "test": "NODE_ENV='dev' pnpm exec jest", + "test:report": "pnpm run test -- --reporters=default --reporters=jest-junit", "test-api": "NODE_ENV='production' pnpm exec jest ./lib/api/framework.test.ts", "depcheck": "pnpx depcheck --ignores @openapitools/openapi-generator-cli,eslint-config-next,locales,components,lib,public,pages,software-inventory,pg", "prepublishOnly": "pnpm test", diff --git a/src/packages/pnpm-lock.yaml b/src/packages/pnpm-lock.yaml index 1fe4499fe0..b4005c5f2c 100644 --- a/src/packages/pnpm-lock.yaml +++ b/src/packages/pnpm-lock.yaml @@ -133,6 +133,9 @@ importers: '@types/node': specifier: ^18.16.14 version: 18.19.118 + jest-junit: + specifier: ^16.0.0 + version: 16.0.0 cdn: devDependencies: @@ -283,6 +286,9 @@ importers: coffeescript: specifier: ^2.5.1 version: 2.7.0 + jest-junit: + specifier: ^16.0.0 + version: 16.0.0 file-server: dependencies: @@ -826,6 +832,9 @@ importers: coffeescript: specifier: ^2.5.1 version: 2.7.0 + jest-junit: + specifier: ^16.0.0 + version: 16.0.0 jupyter: dependencies: @@ -1861,6 +1870,9 @@ importers: expect: specifier: ^26.6.2 version: 26.6.2 + jest-junit: + specifier: ^16.0.0 + version: 16.0.0 seedrandom: specifier: ^3.0.5 version: 3.0.5 @@ -7858,6 +7870,10 @@ packages: resolution: {integrity: sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + jest-junit@16.0.0: + resolution: {integrity: sha512-A94mmw6NfJab4Fg/BlvVOUXzXgF0XIH6EmTgJ5NDPp4xoKq0Kr7sErb+4Xs9nZvu58pJojz5RFGpqnZYJTrRfQ==} + engines: {node: '>=10.12.0'} + jest-leak-detector@29.7.0: resolution: {integrity: sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -11607,6 +11623,9 @@ packages: resolution: {integrity: sha512-T4rieHaC1EXcES0Kxxj4JWgaUQHDk+qwHcYOCFHfiwKz7tOVPLq7Hjq9dM1WCMhylqMEfP7hMcOIChvotiZegA==} engines: {node: '>=4.0.0'} + xml@1.0.1: + resolution: {integrity: sha512-huCv9IH9Tcf95zuYCsQraZtWnJvBtLVE0QHMOs8bWyZAFZNDcYjsPq1nEx8jKA9y+Beo9v+7OBPRisQTjinQMw==} + xmlbuilder2@3.1.1: resolution: {integrity: sha512-WCSfbfZnQDdLQLiMdGUQpMxxckeQ4oZNMNhLVkcekTu7xhD4tuUDyAPoY8CwXvBYE6LwBHd6QW2WZXlOWr1vCw==} engines: {node: '>=12.0'} @@ -15321,7 +15340,7 @@ snapshots: axios@1.10.0: dependencies: - follow-redirects: 1.15.9 + follow-redirects: 1.15.9(debug@4.4.1) form-data: 4.0.3 proxy-from-env: 1.1.0 transitivePeerDependencies: @@ -17457,8 +17476,6 @@ snapshots: dependencies: dtype: 2.0.0 - follow-redirects@1.15.9: {} - follow-redirects@1.15.9(debug@4.4.1): optionalDependencies: debug: 4.4.1 @@ -18828,6 +18845,13 @@ snapshots: optionalDependencies: fsevents: 2.3.3 + jest-junit@16.0.0: + dependencies: + mkdirp: 1.0.4 + strip-ansi: 6.0.1 + uuid: 8.3.2 + xml: 1.0.1 + jest-leak-detector@29.7.0: dependencies: jest-get-type: 29.6.3 @@ -23324,6 +23348,8 @@ snapshots: sax: 1.4.1 xmlbuilder: 11.0.1 + xml@1.0.1: {} + xmlbuilder2@3.1.1: dependencies: '@oozcitak/dom': 1.15.10 diff --git a/src/packages/project/package.json b/src/packages/project/package.json index 19f3fda579..dfab5227a8 100644 --- a/src/packages/project/package.json +++ b/src/packages/project/package.json @@ -69,6 +69,7 @@ "build": "../node_modules/.bin/tsc --build", "tsc": "../node_modules/.bin/tsc --watch --pretty --preserveWatchOutput", "test": "COCALC_PROJECT_ID=812abe34-a382-4bd1-9071-29b6f4334f03 COCALC_USERNAME=user pnpm exec jest", + "test:report": "pnpm run test -- --reporters=default --reporters=jest-junit", "depcheck": "pnpx depcheck", "prepublishOnly": "pnpm test", "clean": "rm -rf dist" diff --git a/src/packages/server/package.json b/src/packages/server/package.json index fd46d02793..202169a877 100644 --- a/src/packages/server/package.json +++ b/src/packages/server/package.json @@ -36,6 +36,7 @@ "build": "../node_modules/.bin/tsc --build", "tsc": "../node_modules/.bin/tsc --watch --pretty --preserveWatchOutput ", "test": "TZ=UTC jest --forceExit --runInBand", + "test:report": "pnpm run test -- --reporters=default --reporters=jest-junit", "depcheck": "pnpx depcheck", "prepublishOnly": "test" }, diff --git a/src/packages/static/package.json b/src/packages/static/package.json index e62caf3f97..1d64891b1c 100644 --- a/src/packages/static/package.json +++ b/src/packages/static/package.json @@ -20,6 +20,7 @@ "build-dev": "pnpm run build0 && NODE_ENV=development pnpm rspack build", "watch": "NO_RSPACK_DEV_SERVER=yes NODE_ENV=development pnpm rspack build -w", "test": "pnpm exec jest", + "test:report": "pnpm run test -- --reporters=default --reporters=jest-junit", "prepublishOnly": "pnpm test" }, "repository": { diff --git a/src/packages/sync-fs/package.json b/src/packages/sync-fs/package.json index 08b34f4b7c..547fd16be1 100644 --- a/src/packages/sync-fs/package.json +++ b/src/packages/sync-fs/package.json @@ -20,6 +20,7 @@ "tsc": "../node_modules/.bin/tsc --watch --pretty --preserveWatchOutput", "clean": "rm -rf node_modules dist", "test": "pnpm exec jest --forceExit --runInBand", + "test:report": "pnpm run test -- --reporters=default --reporters=jest-junit", "depcheck": "pnpx depcheck" }, "author": "SageMath, Inc.", diff --git a/src/packages/sync/package.json b/src/packages/sync/package.json index 8c1946fe61..e8ec36b52b 100644 --- a/src/packages/sync/package.json +++ b/src/packages/sync/package.json @@ -13,6 +13,7 @@ "build": "../node_modules/.bin/tsc --build", "tsc": "../node_modules/.bin/tsc --watch --pretty --preserveWatchOutput", "test": "pnpm exec jest --forceExit", + "test:report": "pnpm run test -- --reporters=default --reporters=jest-junit", "depcheck": "pnpx depcheck --ignores events", "prepublishOnly": "pnpm test" }, diff --git a/src/packages/util/package.json b/src/packages/util/package.json index e9656ac1e3..315de1c988 100644 --- a/src/packages/util/package.json +++ b/src/packages/util/package.json @@ -20,6 +20,7 @@ "build": "pnpm exec tsc --build", "tsc": "pnpm exec tsc --watch --pretty --preserveWatchOutput", "test": "pnpm exec jest", + "test:report": "pnpm run test -- --reporters=default --reporters=jest-junit", "depcheck": "pnpx depcheck --ignores events", "prepublishOnly": "pnpm test" }, @@ -76,6 +77,7 @@ "@types/node": "^18.16.14", "@types/seedrandom": "^3.0.8", "@types/uuid": "^8.3.1", + "jest-junit": "^16.0.0", "expect": "^26.6.2", "seedrandom": "^3.0.5", "tsd": "^0.22.0" diff --git a/src/workspaces.py b/src/workspaces.py index da60e90a8d..04c2bb0820 100755 --- a/src/workspaces.py +++ b/src/workspaces.py @@ -284,11 +284,7 @@ def test(args) -> None: success = [] def status(): - print("Status: ", { - "flaky": flaky, - "fails": fails, - "success": success - }) + print("Status: ", {"flaky": flaky, "fails": fails, "success": success}) v = packages(args) v.sort() @@ -307,11 +303,14 @@ def f(): print(f"TESTING {n}/{len(v)}: {path}") print("*") print("*" * 40) - cmd("pnpm run --if-present test", package_path) + test_cmd = "pnpm run --if-present test" + if args.report: + test_cmd += ":report" + cmd(test_cmd, package_path) success.append(path) worked = False - for i in range(args.retries+1): + for i in range(args.retries + 1): try: f() worked = True @@ -325,7 +324,9 @@ def f(): flaky.append(path) print(f"ERROR testing {path}") if args.retries - i >= 1: - print(f"Trying {path} again at most {args.retries - i} more times") + print( + f"Trying {path} again at most {args.retries - i} more times" + ) if not worked: fails.append(path) @@ -577,7 +578,13 @@ def packages_arg(parser): "--retries", type=int, default=2, - help="how many times to retry a failed test suite before giving up; set to 0 to NOT retry") + help= + "how many times to retry a failed test suite before giving up; set to 0 to NOT retry" + ) + subparser.add_argument('--report', + action="store_const", + const=True, + help='if given, generate test reports') packages_arg(subparser) subparser.set_defaults(func=test)