diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 746a58908b..0e24143d6b 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -25,5 +25,13 @@ jobs: - name: Run Prettier run: pnpm run prettier --check . + - name: Create test env file + run: | + echo "TEST_DATABASE_CLIENT=sqlite" > core/.env.test + echo "NODE_ENV=test" >> core/.env.test + + - name: Run tests + run: cd core && pnpm test + - name: Build packages run: pnpm run build diff --git a/README.md b/README.md index 0fffaea20a..c35d4fd431 100644 --- a/README.md +++ b/README.md @@ -143,3 +143,28 @@ downloads the model from huggingface and queries it locally ## Discord Bot For help with setting up your Discord Bot, check out here: https://discordjs.guide/preparations/setting-up-a-bot-application.html + +# Development + +## Testing + +To run the test suite: + +```bash +pnpm test # Run tests once +pnpm test:watch # Run tests in watch mode +``` + +For database-specific tests: +```bash +pnpm test:sqlite # Run tests with SQLite +pnpm test:sqljs # Run tests with SQL.js +``` + +Tests are written using Jest and can be found in `src/**/*.test.ts` files. The test environment is configured to: +- Load environment variables from `.env.test` +- Use a 2-minute timeout for long-running tests +- Support ESM modules +- Run tests in sequence (--runInBand) + +To create new tests, add a `.test.ts` file adjacent to the code you're testing. \ No newline at end of file diff --git a/core/.env.test b/core/.env.test new file mode 100644 index 0000000000..3f383adc69 --- /dev/null +++ b/core/.env.test @@ -0,0 +1,2 @@ +TEST_DATABASE_CLIENT=sqlite +NODE_ENV=test diff --git a/core/jest.config.js b/core/jest.config.js index cc88ff8fef..9d609fa678 100644 --- a/core/jest.config.js +++ b/core/jest.config.js @@ -1,17 +1,16 @@ /** @type {import('ts-jest').JestConfigWithTsJest} */ export default { preset: "ts-jest", - testEnvironment: "jest-environment-node", + testEnvironment: "node", rootDir: "./src", testMatch: ["**/*.test.ts"], + setupFilesAfterEnv: ["/test_resources/testSetup.ts"], + testTimeout: 120000, globals: { __DEV__: true, __TEST__: true, __VERSION__: "0.0.1", }, - // collectCoverage: true, - // collectCoverageFrom: ["**/*.{ts}", "!**/*.test.{ts}", "!**/node_modules/**", "!**/vendor/**"], - // coverageDirectory: "../coverage", transform: { "^.+\\.tsx?$": [ "ts-jest", @@ -24,4 +23,4 @@ export default { "^(\\.{1,2}/.*)\\.js$": "$1", }, extensionsToTreatAsEsm: [".ts"], -}; +} diff --git a/core/package.json b/core/package.json index f7fbe5f85e..9a00fd6288 100644 --- a/core/package.json +++ b/core/package.json @@ -29,9 +29,10 @@ "dev": "tsc && nodemon", "build:docs": "cd docs && pnpm run build", "postinstall": "npx playwright install-deps && npx playwright install", - "test": "NODE_OPTIONS=\"$NODE_OPTIONS --experimental-vm-modules\" jest --runInBand --watch -f", - "test:sqlite": "NODE_OPTIONS=\"$NODE_OPTIONS --experimental-vm-modules\" TEST_DATABASE_CLIENT=sqlite jest --runInBand --watch -f", - "test:sqljs": "NODE_OPTIONS=\"$NODE_OPTIONS --experimental-vm-modules\" TEST_DATABASE_CLIENT=sqljs jest --runInBand --watch -f" + "test": "jest --runInBand", + "test:watch": "jest --runInBand --watch", + "test:sqlite": "cross-env TEST_DATABASE_CLIENT=sqlite jest --runInBand --watch", + "test:sqljs": "cross-env TEST_DATABASE_CLIENT=sqljs jest --runInBand --watch" }, "author": "", "license": "MIT", @@ -66,7 +67,8 @@ "ts-node": "10.9.2", "tslib": "2.8.0", "typescript": "5.6.3", - "wrangler": "3.84.0" + "wrangler": "3.84.0", + "@types/pdfjs-dist": "^2.10.378" }, "pnpm": { "overrides": { diff --git a/core/src/core/types.ts b/core/src/core/types.ts index e088e446c1..d2cba44320 100644 --- a/core/src/core/types.ts +++ b/core/src/core/types.ts @@ -1,5 +1,5 @@ import { Readable } from "stream"; -import { ImageGenModel } from "./imageGenModels"; +import { ImageGenModel } from "./imageGenModels.ts"; /** * Represents a UUID, which is a universally unique identifier conforming to the UUID standard. diff --git a/core/src/providers/token.ts b/core/src/providers/token.ts index 9623cb2b57..d20aedaeba 100644 --- a/core/src/providers/token.ts +++ b/core/src/providers/token.ts @@ -2,7 +2,7 @@ import { Connection } from "@solana/web3.js"; // import fetch from "cross-fetch"; import { IAgentRuntime, Memory, Provider, State } from "../core/types.ts"; import settings from "../core/settings.ts"; -import BigNumber from "bignumber.js"; +import { toBN, BN } from '../utils/bignumber.js'; import { ProcessedTokenData, TokenSecurityData, @@ -609,40 +609,38 @@ export class TokenProvider { ): Promise> { const holdersData = await this.fetchHolderList(); - const tokenPriceUsd = new BigNumber(tradeData.price); + const tokenPriceUsd = toBN(tradeData.price); const highValueHolders = holdersData .filter((holder) => { - const balanceUsd = new BigNumber(holder.balance).multipliedBy( + const balanceUsd = toBN(holder.balance).multipliedBy( tokenPriceUsd ); return balanceUsd.isGreaterThan(5); }) .map((holder) => ({ holderAddress: holder.address, - balanceUsd: new BigNumber(holder.balance) - .multipliedBy(tokenPriceUsd) - .toFixed(2), + balanceUsd: toBN(holder.balance).multipliedBy(tokenPriceUsd).toFixed(2), })); return highValueHolders; } async checkRecentTrades(tradeData: TokenTradeData): Promise { - return new BigNumber(tradeData.volume_24h_usd).isGreaterThan(0); + return toBN(tradeData.volume_24h_usd).isGreaterThan(0); } async countHighSupplyHolders( securityData: TokenSecurityData ): Promise { try { - const ownerBalance = new BigNumber(securityData.ownerBalance); + const ownerBalance = toBN(securityData.ownerBalance); const totalSupply = ownerBalance.plus(securityData.creatorBalance); const highSupplyHolders = await this.fetchHolderList(); const highSupplyHoldersCount = highSupplyHolders.filter( (holder) => { - const balance = new BigNumber(holder.balance); + const balance = toBN(holder.balance); return balance.dividedBy(totalSupply).isGreaterThan(0.02); } ).length; @@ -738,8 +736,8 @@ export class TokenProvider { output += `- Unique Wallets (24h): ${data.tradeData.unique_wallet_24h}\n`; output += `- Price Change (24h): ${data.tradeData.price_change_24h_percent}%\n`; output += `- Price Change (12h): ${data.tradeData.price_change_12h_percent}%\n`; - output += `- Volume (24h USD): $${new BigNumber(data.tradeData.volume_24h_usd).toFixed(2)}\n`; - output += `- Current Price: $${new BigNumber(data.tradeData.price).toFixed(2)}\n\n`; + output += `- Volume (24h USD): $${toBN(data.tradeData.volume_24h_usd).toFixed(2)}\n`; + output += `- Current Price: $${toBN(data.tradeData.price).toFixed(2)}\n\n`; // Holder Distribution Trend output += `**Holder Distribution Trend:** ${data.holderDistributionTrend}\n\n`; @@ -771,10 +769,10 @@ export class TokenProvider { output += `\n**Pair ${index + 1}:**\n`; output += `- DEX: ${pair.dexId}\n`; output += `- URL: ${pair.url}\n`; - output += `- Price USD: $${new BigNumber(pair.priceUsd).toFixed(6)}\n`; - output += `- Volume (24h USD): $${new BigNumber(pair.volume.h24).toFixed(2)}\n`; + output += `- Price USD: $${toBN(pair.priceUsd).toFixed(6)}\n`; + output += `- Volume (24h USD): $${toBN(pair.volume.h24).toFixed(2)}\n`; output += `- Boosts Active: ${pair.boosts && pair.boosts.active}\n`; - output += `- Liquidity USD: $${new BigNumber(pair.liquidity.usd).toFixed(2)}\n`; + output += `- Liquidity USD: $${toBN(pair.liquidity.usd).toFixed(2)}\n`; }); } output += `\n`; diff --git a/core/src/test_resources/basic.test.ts b/core/src/test_resources/basic.test.ts new file mode 100644 index 0000000000..bc712869a1 --- /dev/null +++ b/core/src/test_resources/basic.test.ts @@ -0,0 +1,10 @@ +describe('Basic Test Suite', () => { + it('should run a basic test', () => { + expect(true).toBe(true); + }); + + it('should have access to environment variables', () => { + expect(process.env.NODE_ENV).toBe('test'); + expect(process.env.TEST_DATABASE_CLIENT).toBe('sqlite'); + }); +}); \ No newline at end of file diff --git a/core/src/test_resources/testSetup.ts b/core/src/test_resources/testSetup.ts new file mode 100644 index 0000000000..76497eb260 --- /dev/null +++ b/core/src/test_resources/testSetup.ts @@ -0,0 +1,8 @@ +import dotenv from "dotenv"; +import path from 'path'; + +// Load test environment variables +dotenv.config({ path: '.env.test' }); + +// Set longer timeout for tests +jest.setTimeout(120000); diff --git a/core/src/utils/bignumber.ts b/core/src/utils/bignumber.ts new file mode 100644 index 0000000000..7bcf3cfb10 --- /dev/null +++ b/core/src/utils/bignumber.ts @@ -0,0 +1,9 @@ +import BigNumber from 'bignumber.js'; + +// Re-export BigNumber constructor +export const BN = BigNumber; + +// Helper function to create new BigNumber instances +export function toBN(value: string | number | BigNumber): BigNumber { + return new BigNumber(value); +} \ No newline at end of file diff --git a/core/src/utils/youtube.ts b/core/src/utils/youtube.ts new file mode 100644 index 0000000000..253dd060c1 --- /dev/null +++ b/core/src/utils/youtube.ts @@ -0,0 +1,3 @@ +import youtubeDl from 'youtube-dl-exec'; + +export const youtube = (url: string, options?: any) => youtubeDl(url, options); \ No newline at end of file diff --git a/core/tsconfig.json b/core/tsconfig.json index 3527f3ee01..54842ba1c4 100644 --- a/core/tsconfig.json +++ b/core/tsconfig.json @@ -1,9 +1,9 @@ { "compilerOptions": { - "target": "es2022", - "module": "es2022", - "lib": ["es2023", "dom"], - "moduleResolution": "bundler", + "target": "ESNext", + "module": "ESNext", + "lib": ["ESNext", "dom"], + "moduleResolution": "Bundler", "outDir": "./dist", "rootDir": "./src", "strict": false, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c8c30affc7..e5b27b7ee7 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -11911,7 +11911,7 @@ snapshots: detect-libc: 2.0.3 https-proxy-agent: 5.0.1 make-dir: 3.1.0 - node-fetch: 2.6.7(encoding@0.1.13) + node-fetch: 2.7.0(encoding@0.1.13) nopt: 5.0.0 npmlog: 5.0.1 rimraf: 3.0.2