diff --git a/.github/workflows/integrationTests.yaml b/.github/workflows/integrationTests.yaml new file mode 100644 index 0000000000..cd9441507d --- /dev/null +++ b/.github/workflows/integrationTests.yaml @@ -0,0 +1,55 @@ +name: integration-test +on: + push: + branches: + - "*" + pull_request: + branches: + - "*" +jobs: + smoke-tests: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - uses: pnpm/action-setup@v3 + with: + version: 9.4.0 + + - uses: actions/setup-node@v4 + with: + node-version: "23" + cache: "pnpm" + + - name: Run smoke tests + run: pnpm run smokeTests + integration-tests: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - uses: pnpm/action-setup@v3 + with: + version: 9.4.0 + + - uses: actions/setup-node@v4 + with: + node-version: "23" + cache: "pnpm" + + - name: Install dependencies + run: pnpm install -r + + - name: Build packages + run: pnpm build + + - name: Run integration tests + env: + OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} + run: | + if [ -z "$OPENAI_API_KEY" ]; then + echo "Skipping integration tests due to missing required API keys" + exit 1 + else + pnpm run integrationTests + fi diff --git a/package.json b/package.json index 8c8886662a..ac6da05dad 100644 --- a/package.json +++ b/package.json @@ -18,7 +18,9 @@ "docker:bash": "bash ./scripts/docker.sh bash", "docker:start": "bash ./scripts/docker.sh start", "docker": "pnpm docker:build && pnpm docker:run && pnpm docker:bash", - "test": "bash ./scripts/test.sh" + "test": "bash ./scripts/test.sh", + "smokeTests": "bash ./scripts/smokeTests.sh", + "integrationTests": "bash ./scripts/integrationTests.sh" }, "devDependencies": { "@commitlint/cli": "18.6.1", @@ -38,7 +40,8 @@ "typedoc": "0.26.11", "typescript": "5.6.3", "vite": "5.4.11", - "vitest": "2.1.5" + "vitest": "2.1.5", + "zx": "^8.2.4" }, "pnpm": { "overrides": { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index bd6e2535fe..1e7fa94270 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -93,6 +93,9 @@ importers: vitest: specifier: 2.1.5 version: 2.1.5(@types/node@22.8.4)(jsdom@25.0.1(bufferutil@4.0.8)(canvas@2.11.2(encoding@0.1.13))(utf-8-validate@5.0.10))(terser@5.37.0) + zx: + specifier: ^8.2.4 + version: 8.2.4 agent: dependencies: @@ -585,7 +588,7 @@ importers: version: 8.57.1 jest: specifier: ^29.0.0 - version: 29.7.0(@types/node@20.17.9) + version: 29.7.0(@types/node@20.17.9)(ts-node@10.9.2(@swc/core@1.10.1(@swc/helpers@0.5.15))(@types/node@20.17.9)(typescript@5.6.3)) typescript: specifier: ^5.0.0 version: 5.6.3 @@ -1042,7 +1045,7 @@ importers: version: 29.5.14 jest: specifier: 29.7.0 - version: 29.7.0(@types/node@22.8.4) + version: 29.7.0(@types/node@22.8.4)(ts-node@10.9.2(@swc/core@1.10.1(@swc/helpers@0.5.15))(@types/node@22.8.4)(typescript@5.6.3)) tsup: specifier: 8.3.5 version: 8.3.5(@swc/core@1.10.1(@swc/helpers@0.5.15))(jiti@2.4.0)(postcss@8.4.49)(typescript@5.6.3)(yaml@2.6.1) @@ -1447,10 +1450,10 @@ importers: version: 8.16.0(eslint@9.16.0(jiti@2.4.0))(typescript@5.6.3) jest: specifier: 29.7.0 - version: 29.7.0(@types/node@20.17.9) + version: 29.7.0(@types/node@20.17.9)(ts-node@10.9.2(@swc/core@1.10.1(@swc/helpers@0.5.15))(@types/node@20.17.9)(typescript@5.6.3)) ts-jest: specifier: 29.2.5 - version: 29.2.5(@babel/core@7.26.0)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.26.0))(jest@29.7.0(@types/node@20.17.9))(typescript@5.6.3) + version: 29.2.5(@babel/core@7.26.0)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.26.0))(jest@29.7.0(@types/node@20.17.9)(ts-node@10.9.2(@swc/core@1.10.1(@swc/helpers@0.5.15))(@types/node@20.17.9)(typescript@5.6.3)))(typescript@5.6.3) typescript: specifier: 5.6.3 version: 5.6.3 @@ -4164,8 +4167,8 @@ packages: resolution: {integrity: sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - '@jridgewell/gen-mapping@0.3.5': - resolution: {integrity: sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==} + '@jridgewell/gen-mapping@0.3.8': + resolution: {integrity: sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==} engines: {node: '>=6.0.0'} '@jridgewell/resolve-uri@3.1.2': @@ -6487,6 +6490,9 @@ packages: '@types/fluent-ffmpeg@2.1.27': resolution: {integrity: sha512-QiDWjihpUhriISNoBi2hJBRUUmoj/BMTYcfz+F+ZM9hHWBYABFAE6hjP/TbCZC0GWwlpa3FzvHH9RzFeRusZ7A==} + '@types/fs-extra@11.0.4': + resolution: {integrity: sha512-yTbItCNreRooED33qjunPthRcSjERP1r4MqCZc7wv0u2sUkzTFp45tgUfS5+r7FrZPdmCCNflLhVSP/o+SemsQ==} + '@types/geojson@7946.0.15': resolution: {integrity: sha512-9oSxFzDCT2Rj6DfcHF8G++jxBKS7mBqXl5xrRW+Kbvjry6Uduya2iiwqHPhVXpasAVMBYKkEPGgKhd3+/HZ6xA==} @@ -6538,6 +6544,9 @@ packages: '@types/json-schema@7.0.15': resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} + '@types/jsonfile@6.1.4': + resolution: {integrity: sha512-D5qGUYwjvnNNextdU59/+fI+spnwtTFmyQP0h+PfIOSkNfpU6AOICUOkm4i0OnSk+NyjdPJrxCDro0sJsWlRpQ==} + '@types/jsonwebtoken@9.0.7': resolution: {integrity: sha512-ugo316mmTYBl2g81zDFnZ7cfxlut3o+/EQdaP7J8QN2kY6lJ22hmQYCK5EHcJHbrW+dkCGSCPgbG8JtYj6qSrg==} @@ -14785,9 +14794,9 @@ packages: resolution: {integrity: sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==} engines: {node: '>= 10.13.0'} - schema-utils@4.2.0: - resolution: {integrity: sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==} - engines: {node: '>= 12.13.0'} + schema-utils@4.3.0: + resolution: {integrity: sha512-Gf9qqc58SpCA/xdziiHz35F4GNIWYWZrEshUc/G/r5BnLph6xpKuLeoJoQuj5WfBIx/eQLf+hmVPYHaxJu7V2g==} + engines: {node: '>= 10.13.0'} scule@1.3.0: resolution: {integrity: sha512-6FtHJEvt+pVMIB9IBY+IcCJ6Z5f1iQnytgyfKMhDKgmzYG+TeH/wx1y3l27rshSbLiSanrR9ffZDrEsmjlQF2g==} @@ -16857,6 +16866,11 @@ packages: zwitch@2.0.4: resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==} + zx@8.2.4: + resolution: {integrity: sha512-g9wVU+5+M+zVen/3IyAZfsZFmeqb6vDfjqFggakviz5uLK7OAejOirX+jeTOkyvAh/OYRlCgw+SdqzN7F61QVQ==} + engines: {node: '>= 12.17.0'} + hasBin: true + snapshots: '@0glabs/0g-ts-sdk@0.2.1(bufferutil@4.0.8)(ethers@6.13.4(bufferutil@4.0.8)(utf-8-validate@5.0.10))(utf-8-validate@5.0.10)': @@ -17187,7 +17201,7 @@ snapshots: '@ampproject/remapping@2.3.0': dependencies: - '@jridgewell/gen-mapping': 0.3.5 + '@jridgewell/gen-mapping': 0.3.8 '@jridgewell/trace-mapping': 0.3.25 '@antfu/install-pkg@0.4.1': @@ -17963,7 +17977,7 @@ snapshots: dependencies: '@babel/parser': 7.26.3 '@babel/types': 7.26.3 - '@jridgewell/gen-mapping': 0.3.5 + '@jridgewell/gen-mapping': 0.3.8 '@jridgewell/trace-mapping': 0.3.25 jsesc: 3.1.0 @@ -20864,6 +20878,41 @@ snapshots: jest-util: 29.7.0 slash: 3.0.0 + '@jest/core@29.7.0(ts-node@10.9.2(@swc/core@1.10.1(@swc/helpers@0.5.15))(@types/node@20.17.9)(typescript@5.6.3))': + dependencies: + '@jest/console': 29.7.0 + '@jest/reporters': 29.7.0 + '@jest/test-result': 29.7.0 + '@jest/transform': 29.7.0 + '@jest/types': 29.6.3 + '@types/node': 20.17.9 + ansi-escapes: 4.3.2 + chalk: 4.1.2 + ci-info: 3.9.0 + exit: 0.1.2 + graceful-fs: 4.2.11 + jest-changed-files: 29.7.0 + jest-config: 29.7.0(@types/node@20.17.9)(ts-node@10.9.2(@swc/core@1.10.1(@swc/helpers@0.5.15))(@types/node@20.17.9)(typescript@5.6.3)) + jest-haste-map: 29.7.0 + jest-message-util: 29.7.0 + jest-regex-util: 29.6.3 + jest-resolve: 29.7.0 + jest-resolve-dependencies: 29.7.0 + jest-runner: 29.7.0 + jest-runtime: 29.7.0 + jest-snapshot: 29.7.0 + jest-util: 29.7.0 + jest-validate: 29.7.0 + jest-watcher: 29.7.0 + micromatch: 4.0.8 + pretty-format: 29.7.0 + slash: 3.0.0 + strip-ansi: 6.0.1 + transitivePeerDependencies: + - babel-plugin-macros + - supports-color + - ts-node + '@jest/core@29.7.0(ts-node@10.9.2(@swc/core@1.10.1(@swc/helpers@0.5.15))(@types/node@22.8.4)(typescript@5.6.3))': dependencies: '@jest/console': 29.7.0 @@ -21017,7 +21066,7 @@ snapshots: '@types/yargs': 17.0.33 chalk: 4.1.2 - '@jridgewell/gen-mapping@0.3.5': + '@jridgewell/gen-mapping@0.3.8': dependencies: '@jridgewell/set-array': 1.2.1 '@jridgewell/sourcemap-codec': 1.5.0 @@ -21029,7 +21078,7 @@ snapshots: '@jridgewell/source-map@0.3.6': dependencies: - '@jridgewell/gen-mapping': 0.3.5 + '@jridgewell/gen-mapping': 0.3.8 '@jridgewell/trace-mapping': 0.3.25 '@jridgewell/sourcemap-codec@1.5.0': {} @@ -24110,6 +24159,12 @@ snapshots: dependencies: '@types/node': 20.17.9 + '@types/fs-extra@11.0.4': + dependencies: + '@types/jsonfile': 6.1.4 + '@types/node': 20.17.9 + optional: true + '@types/geojson@7946.0.15': {} '@types/glob@8.1.0': @@ -24162,6 +24217,11 @@ snapshots: '@types/json-schema@7.0.15': {} + '@types/jsonfile@6.1.4': + dependencies: + '@types/node': 20.17.9 + optional: true + '@types/jsonwebtoken@9.0.7': dependencies: '@types/node': 20.17.9 @@ -25581,7 +25641,7 @@ snapshots: dependencies: '@babel/core': 7.26.0 find-cache-dir: 4.0.0 - schema-utils: 4.2.0 + schema-utils: 4.3.0 webpack: 5.97.1(@swc/core@1.10.1(@swc/helpers@0.5.15)) babel-plugin-dynamic-import-node@2.3.3: @@ -26636,7 +26696,7 @@ snapshots: glob-parent: 6.0.2 globby: 13.2.2 normalize-path: 3.0.0 - schema-utils: 4.2.0 + schema-utils: 4.3.0 serialize-javascript: 6.0.2 webpack: 5.97.1(@swc/core@1.10.1(@swc/helpers@0.5.15)) @@ -26704,13 +26764,13 @@ snapshots: ripemd160: 2.0.2 sha.js: 2.4.11 - create-jest@29.7.0(@types/node@20.17.9): + create-jest@29.7.0(@types/node@20.17.9)(ts-node@10.9.2(@swc/core@1.10.1(@swc/helpers@0.5.15))(@types/node@20.17.9)(typescript@5.6.3)): dependencies: '@jest/types': 29.6.3 chalk: 4.1.2 exit: 0.1.2 graceful-fs: 4.2.11 - jest-config: 29.7.0(@types/node@20.17.9)(ts-node@10.9.2(@swc/core@1.10.1(@swc/helpers@0.5.15))(@types/node@22.8.4)(typescript@5.6.3)) + jest-config: 29.7.0(@types/node@20.17.9)(ts-node@10.9.2(@swc/core@1.10.1(@swc/helpers@0.5.15))(@types/node@20.17.9)(typescript@5.6.3)) jest-util: 29.7.0 prompts: 2.4.2 transitivePeerDependencies: @@ -26811,7 +26871,7 @@ snapshots: cssnano: 6.1.2(postcss@8.4.49) jest-worker: 29.7.0 postcss: 8.4.49 - schema-utils: 4.2.0 + schema-utils: 4.3.0 serialize-javascript: 6.0.2 webpack: 5.97.1(@swc/core@1.10.1(@swc/helpers@0.5.15)) optionalDependencies: @@ -29830,16 +29890,16 @@ snapshots: - babel-plugin-macros - supports-color - jest-cli@29.7.0(@types/node@20.17.9): + jest-cli@29.7.0(@types/node@20.17.9)(ts-node@10.9.2(@swc/core@1.10.1(@swc/helpers@0.5.15))(@types/node@20.17.9)(typescript@5.6.3)): dependencies: - '@jest/core': 29.7.0(ts-node@10.9.2(@swc/core@1.10.1(@swc/helpers@0.5.15))(@types/node@22.8.4)(typescript@5.6.3)) + '@jest/core': 29.7.0(ts-node@10.9.2(@swc/core@1.10.1(@swc/helpers@0.5.15))(@types/node@20.17.9)(typescript@5.6.3)) '@jest/test-result': 29.7.0 '@jest/types': 29.6.3 chalk: 4.1.2 - create-jest: 29.7.0(@types/node@20.17.9) + create-jest: 29.7.0(@types/node@20.17.9)(ts-node@10.9.2(@swc/core@1.10.1(@swc/helpers@0.5.15))(@types/node@20.17.9)(typescript@5.6.3)) exit: 0.1.2 import-local: 3.2.0 - jest-config: 29.7.0(@types/node@20.17.9)(ts-node@10.9.2(@swc/core@1.10.1(@swc/helpers@0.5.15))(@types/node@22.8.4)(typescript@5.6.3)) + jest-config: 29.7.0(@types/node@20.17.9)(ts-node@10.9.2(@swc/core@1.10.1(@swc/helpers@0.5.15))(@types/node@20.17.9)(typescript@5.6.3)) jest-util: 29.7.0 jest-validate: 29.7.0 yargs: 17.7.2 @@ -29849,7 +29909,7 @@ snapshots: - supports-color - ts-node - jest-cli@29.7.0(@types/node@22.8.4): + jest-cli@29.7.0(@types/node@22.8.4)(ts-node@10.9.2(@swc/core@1.10.1(@swc/helpers@0.5.15))(@types/node@22.8.4)(typescript@5.6.3)): dependencies: '@jest/core': 29.7.0(ts-node@10.9.2(@swc/core@1.10.1(@swc/helpers@0.5.15))(@types/node@22.8.4)(typescript@5.6.3)) '@jest/test-result': 29.7.0 @@ -29868,24 +29928,36 @@ snapshots: - supports-color - ts-node - jest-cli@29.7.0(@types/node@22.8.4)(ts-node@10.9.2(@swc/core@1.10.1(@swc/helpers@0.5.15))(@types/node@22.8.4)(typescript@5.6.3)): + jest-config@29.7.0(@types/node@20.17.9)(ts-node@10.9.2(@swc/core@1.10.1(@swc/helpers@0.5.15))(@types/node@20.17.9)(typescript@5.6.3)): dependencies: - '@jest/core': 29.7.0(ts-node@10.9.2(@swc/core@1.10.1(@swc/helpers@0.5.15))(@types/node@22.8.4)(typescript@5.6.3)) - '@jest/test-result': 29.7.0 + '@babel/core': 7.26.0 + '@jest/test-sequencer': 29.7.0 '@jest/types': 29.6.3 + babel-jest: 29.7.0(@babel/core@7.26.0) chalk: 4.1.2 - create-jest: 29.7.0(@types/node@22.8.4)(ts-node@10.9.2(@swc/core@1.10.1(@swc/helpers@0.5.15))(@types/node@22.8.4)(typescript@5.6.3)) - exit: 0.1.2 - import-local: 3.2.0 - jest-config: 29.7.0(@types/node@22.8.4)(ts-node@10.9.2(@swc/core@1.10.1(@swc/helpers@0.5.15))(@types/node@22.8.4)(typescript@5.6.3)) + ci-info: 3.9.0 + deepmerge: 4.3.1 + glob: 7.2.3 + graceful-fs: 4.2.11 + jest-circus: 29.7.0 + jest-environment-node: 29.7.0 + jest-get-type: 29.6.3 + jest-regex-util: 29.6.3 + jest-resolve: 29.7.0 + jest-runner: 29.7.0 jest-util: 29.7.0 jest-validate: 29.7.0 - yargs: 17.7.2 + micromatch: 4.0.8 + parse-json: 5.2.0 + pretty-format: 29.7.0 + slash: 3.0.0 + strip-json-comments: 3.1.1 + optionalDependencies: + '@types/node': 20.17.9 + ts-node: 10.9.2(@swc/core@1.10.1(@swc/helpers@0.5.15))(@types/node@20.17.9)(typescript@5.6.3) transitivePeerDependencies: - - '@types/node' - babel-plugin-macros - supports-color - - ts-node jest-config@29.7.0(@types/node@20.17.9)(ts-node@10.9.2(@swc/core@1.10.1(@swc/helpers@0.5.15))(@types/node@22.8.4)(typescript@5.6.3)): dependencies: @@ -30170,24 +30242,12 @@ snapshots: merge-stream: 2.0.0 supports-color: 8.1.1 - jest@29.7.0(@types/node@20.17.9): - dependencies: - '@jest/core': 29.7.0(ts-node@10.9.2(@swc/core@1.10.1(@swc/helpers@0.5.15))(@types/node@22.8.4)(typescript@5.6.3)) - '@jest/types': 29.6.3 - import-local: 3.2.0 - jest-cli: 29.7.0(@types/node@20.17.9) - transitivePeerDependencies: - - '@types/node' - - babel-plugin-macros - - supports-color - - ts-node - - jest@29.7.0(@types/node@22.8.4): + jest@29.7.0(@types/node@20.17.9)(ts-node@10.9.2(@swc/core@1.10.1(@swc/helpers@0.5.15))(@types/node@20.17.9)(typescript@5.6.3)): dependencies: - '@jest/core': 29.7.0(ts-node@10.9.2(@swc/core@1.10.1(@swc/helpers@0.5.15))(@types/node@22.8.4)(typescript@5.6.3)) + '@jest/core': 29.7.0(ts-node@10.9.2(@swc/core@1.10.1(@swc/helpers@0.5.15))(@types/node@20.17.9)(typescript@5.6.3)) '@jest/types': 29.6.3 import-local: 3.2.0 - jest-cli: 29.7.0(@types/node@22.8.4) + jest-cli: 29.7.0(@types/node@20.17.9)(ts-node@10.9.2(@swc/core@1.10.1(@swc/helpers@0.5.15))(@types/node@20.17.9)(typescript@5.6.3)) transitivePeerDependencies: - '@types/node' - babel-plugin-macros @@ -31590,7 +31650,7 @@ snapshots: mini-css-extract-plugin@2.9.2(webpack@5.97.1(@swc/core@1.10.1(@swc/helpers@0.5.15))): dependencies: - schema-utils: 4.2.0 + schema-utils: 4.3.0 tapable: 2.2.1 webpack: 5.97.1(@swc/core@1.10.1(@swc/helpers@0.5.15)) @@ -34624,7 +34684,7 @@ snapshots: ajv: 6.12.6 ajv-keywords: 3.5.2(ajv@6.12.6) - schema-utils@4.2.0: + schema-utils@4.3.0: dependencies: '@types/json-schema': 7.0.15 ajv: 8.17.1 @@ -35287,7 +35347,7 @@ snapshots: sucrase@3.35.0: dependencies: - '@jridgewell/gen-mapping': 0.3.5 + '@jridgewell/gen-mapping': 0.3.8 commander: 4.1.1 glob: 10.4.5 lines-and-columns: 1.2.4 @@ -35670,12 +35730,12 @@ snapshots: ts-interface-checker@0.1.13: {} - ts-jest@29.2.5(@babel/core@7.26.0)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.26.0))(jest@29.7.0(@types/node@20.17.9))(typescript@5.6.3): + ts-jest@29.2.5(@babel/core@7.26.0)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.26.0))(jest@29.7.0(@types/node@20.17.9)(ts-node@10.9.2(@swc/core@1.10.1(@swc/helpers@0.5.15))(@types/node@20.17.9)(typescript@5.6.3)))(typescript@5.6.3): dependencies: bs-logger: 0.2.6 ejs: 3.1.10 fast-json-stable-stringify: 2.1.0 - jest: 29.7.0(@types/node@20.17.9) + jest: 29.7.0(@types/node@20.17.9)(ts-node@10.9.2(@swc/core@1.10.1(@swc/helpers@0.5.15))(@types/node@20.17.9)(typescript@5.6.3)) jest-util: 29.7.0 json5: 2.2.3 lodash.memoize: 4.1.2 @@ -35710,6 +35770,27 @@ snapshots: ts-mixer@6.0.4: {} + ts-node@10.9.2(@swc/core@1.10.1(@swc/helpers@0.5.15))(@types/node@20.17.9)(typescript@5.6.3): + dependencies: + '@cspotcode/source-map-support': 0.8.1 + '@tsconfig/node10': 1.0.11 + '@tsconfig/node12': 1.0.11 + '@tsconfig/node14': 1.0.3 + '@tsconfig/node16': 1.0.4 + '@types/node': 20.17.9 + acorn: 8.14.0 + acorn-walk: 8.3.4 + arg: 4.1.3 + create-require: 1.1.1 + diff: 4.0.2 + make-error: 1.3.6 + typescript: 5.6.3 + v8-compile-cache-lib: 3.0.1 + yn: 3.1.1 + optionalDependencies: + '@swc/core': 1.10.1(@swc/helpers@0.5.15) + optional: true + ts-node@10.9.2(@swc/core@1.10.1(@swc/helpers@0.5.15))(@types/node@22.8.4)(typescript@5.6.3): dependencies: '@cspotcode/source-map-support': 0.8.1 @@ -36545,7 +36626,7 @@ snapshots: memfs: 3.5.3 mime-types: 2.1.35 range-parser: 1.2.1 - schema-utils: 4.2.0 + schema-utils: 4.3.0 webpack: 5.97.1(@swc/core@1.10.1(@swc/helpers@0.5.15)) webpack-dev-server@4.15.2(bufferutil@4.0.8)(utf-8-validate@5.0.10)(webpack@5.97.1(@swc/core@1.10.1(@swc/helpers@0.5.15))): @@ -36573,7 +36654,7 @@ snapshots: open: 8.4.2 p-retry: 4.6.2 rimraf: 3.0.2 - schema-utils: 4.2.0 + schema-utils: 4.3.0 selfsigned: 2.4.1 serve-index: 1.9.1 sockjs: 0.3.24 @@ -36936,3 +37017,8 @@ snapshots: zwitch@1.0.5: {} zwitch@2.0.4: {} + + zx@8.2.4: + optionalDependencies: + '@types/fs-extra': 11.0.4 + '@types/node': 20.17.9 diff --git a/scripts/integrationTests.sh b/scripts/integrationTests.sh new file mode 100755 index 0000000000..6dff86b571 --- /dev/null +++ b/scripts/integrationTests.sh @@ -0,0 +1,16 @@ +#!/bin/bash + +# Check Node.js version +REQUIRED_NODE_VERSION=23 +CURRENT_NODE_VERSION=$(node -v | cut -d'.' -f1 | sed 's/v//') + +if (( CURRENT_NODE_VERSION < REQUIRED_NODE_VERSION )); then + echo "Error: Node.js version must be $REQUIRED_NODE_VERSION or higher. Current version is $CURRENT_NODE_VERSION." + exit 1 +fi + +# Navigate to the script's directory +cd "$(dirname "$0")"/.. + +cd tests +node test1.mjs diff --git a/scripts/smokeTests.sh b/scripts/smokeTests.sh new file mode 100755 index 0000000000..fcce311fe1 --- /dev/null +++ b/scripts/smokeTests.sh @@ -0,0 +1,86 @@ +#!/bin/bash + +# Print some information about the environment to aid in case of troubleshooting + +echo "node version:" +node --version + +echo "python version:" +python3 --version + +echo "make version:" +make --version + +echo "gcc version:" +gcc --version + +echo "g++ version:" +g++ --version + +# Check Node.js version +REQUIRED_NODE_VERSION=23 +CURRENT_NODE_VERSION=$(node -v | cut -d'.' -f1 | sed 's/v//') + +if (( CURRENT_NODE_VERSION < REQUIRED_NODE_VERSION )); then + echo "Error: Node.js version must be $REQUIRED_NODE_VERSION or higher. Current version is $CURRENT_NODE_VERSION." + exit 1 +fi + +# Autodetect project directory relative to this script's path +PROJECT_DIR="$0" +while [ -h "$PROJECT_DIR" ]; do + ls=$(ls -ld "$PROJECT_DIR") + link=$(expr "$ls" : '.*-> \(.*\)$') + if expr "$link" : '/.*' > /dev/null; then + PROJECT_DIR="$link" + else + PROJECT_DIR="$(dirname "$PROJECT_DIR")/$link" + fi +done +PROJECT_DIR="$(dirname "$PROJECT_DIR")/.." +PROJECT_DIR="$(cd "$PROJECT_DIR"; pwd)" + +cd $PROJECT_DIR + +cp .env.example .env + +pnpm install -r + +pnpm build + +OUTFILE="$(mktemp)" +echo $OUTFILE +( + # Wait for the ready message + while true; do + if grep -q "Chat started" "$OUTFILE"; then + echo "exit"; sleep 2 + break + fi + sleep 0.5 + done +) | pnpm start --character=characters/trump.character.json > "$OUTFILE" & + +# Wait for process to finish +wait $! +RESULT=$? +echo "----- OUTPUT START -----" +cat "$OUTFILE" +echo "----- OUTPUT END -----" + +# Check the exit code of the last command +if [[ $RESULT -ne 0 ]]; then + echo "Error: 'start' command exited with an error." + exit 1 +fi + +# Check if output.txt contains "Terminating and cleaning up resources..." +if grep -q "Terminating and cleaning up resources..." "$OUTFILE"; then + echo "Script completed successfully." +else + echo "Error: The output does not contain the expected string." + exit 1 +fi + +# Clean up +rm "$OUTFILE" diff --git a/tests/README.md b/tests/README.md new file mode 100644 index 0000000000..761b59b8b6 --- /dev/null +++ b/tests/README.md @@ -0,0 +1,25 @@ +# Integration tests + +This directory contains smoke and integration tests for Eliza project. + +## Smoke tests +- Should always be run on a freshly cloned project (i.e. no local changes) +- Building and installing is part of the test +- No configuration required +- To run: `pnpm run smokeTests` + +## Integration tests +- You need to configure your .env file before running (currently at least `OPENAI_API_KEY` is required) +- How to use: + 1. Install project dependencies and build the project as described in top-level `README` + 2. To run all the tests: `pnpm run integrationTests` + +## Integration test library +- For simplicity, integration tests are written in plain JavaScript (ESM) +- Currently this is just a "proof of concept" (single test), please reach out if you would like to contribute. + +## Using in GitHub CI/CD +- Settings -> Secrets and variables -> Actions: +- Create an enviroment +- Add repository secret `OPENAI_API_KEY` +- Refer to https://docs.github.com/en/actions/security-for-github-actions/security-guides/using-secrets-in-github-actions for more information diff --git a/tests/test1.mjs b/tests/test1.mjs new file mode 100644 index 0000000000..11ebbe37aa --- /dev/null +++ b/tests/test1.mjs @@ -0,0 +1,33 @@ +import { $, chalk } from 'zx'; +import assert from 'assert'; +import { + startAgent, + stopAgent, + send +} from "./testLibrary.mjs"; +import { stringToUuid } from '../packages/core/dist/index.js' + +export const DEFAULT_CHARACTER = "trump" +export const DEFAULT_AGENT_ID = stringToUuid(DEFAULT_CHARACTER ?? uuidv4()); + +async function test1() { + const proc = await startAgent(); + try { + + const reply = await send("Hi"); + assert(reply.length > 10); + console.log(chalk.green('✓ Test 1 passed')); + } catch (error) { + console.error(chalk.red(`✗ Test 1 failed: ${error.message}`)); + process.exit(1); + } finally { + await stopAgent(proc); + } +} + +try { + await test1(); +} catch (error) { + console.error(chalk.red(`Error: ${error.message}`)); + process.exit(1); +} \ No newline at end of file diff --git a/tests/testLibrary.mjs b/tests/testLibrary.mjs new file mode 100644 index 0000000000..7646bf0b04 --- /dev/null +++ b/tests/testLibrary.mjs @@ -0,0 +1,93 @@ +import { $, fs, path, chalk } from 'zx'; +import { DEFAULT_AGENT_ID, DEFAULT_CHARACTER } from './test1.mjs'; +import { spawn } from 'node:child_process'; +$.verbose = false; // Suppress command output unless there's an error + +function projectRoot() { + return path.join(import.meta.dirname, ".."); +} + +async function runProcess(command, args = [], directory = projectRoot()) { + try { + const result = await $`cd ${directory} && ${command} ${args}`; + return result.stdout.trim(); + } catch (error) { + throw new Error(`Command failed: ${error.message}`); + } +} + +async function installProjectDependencies() { + console.log(chalk.blue('Installing dependencies...')); + return await runProcess('pnpm', ['install', '-r']); +} + +async function buildProject() { + console.log(chalk.blue('Building project...')); + return await runProcess('pnpm', ['build']); +} + +async function writeEnvFile(entries) { + const envContent = Object.entries(entries) + .map(([key, value]) => `${key}=${value}`) + .join('\n'); + await fs.writeFile('.env', envContent); +} + +async function startAgent(character = DEFAULT_CHARACTER) { + console.log(chalk.blue(`Starting agent for character: ${character}`)); + const proc = spawn('pnpm', ['start', `--character=characters/${character}.character.json`, '--non-interactive'], { shell: true, "stdio": "inherit" }); + log(`proc=${JSON.stringify(proc)}`); + + // Wait for server to be ready + await new Promise(resolve => setTimeout(resolve, 20000)); + return proc; +} + +async function stopAgent(proc) { + console.log(chalk.blue('Stopping agent...')); + proc.kill('SIGTERM') +} + +async function send(message) { + const endpoint = `http://127.0.0.1:3000/${DEFAULT_AGENT_ID}/message`; + const payload = { + text: message, + userId: "user", + userName: "User" + }; + + try { + const response = await fetch(endpoint, { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify(payload) + }); + + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`); + } + + const data = await response.json(); + return data[0].text; + } catch (error) { + throw new Error(`Failed to send message: ${error.message}`); + } +} + +function log(message) { + console.log(message); +} + +export { + projectRoot, + runProcess, + installProjectDependencies, + buildProject, + writeEnvFile, + startAgent, + stopAgent, + send, + log +} \ No newline at end of file