diff --git a/packages/testcontainers/__tests__/containers/PlaygroundApiContainer.test.ts b/packages/testcontainers/__tests__/containers/PlaygroundApiContainer.test.ts new file mode 100644 index 000000000..2f5e59ae0 --- /dev/null +++ b/packages/testcontainers/__tests__/containers/PlaygroundApiContainer.test.ts @@ -0,0 +1,58 @@ +import { Network } from 'testcontainers' +import { WhaleApiClient } from '@defichain/whale-api-client' +import { PlaygroundApiClient } from '@defichain/playground-api-client' + +import { + NativeChainContainer, + StartedNativeChainContainer, + StartedWhaleApiContainer, + WhaleApiContainer, + PlaygroundApiContainer, + StartedPlaygroundApiContainer +} from '../../src' + +let defid: StartedNativeChainContainer +let whale: StartedWhaleApiContainer +let playground: StartedPlaygroundApiContainer + +beforeAll(async () => { + const network = await new Network().start() + + defid = await new NativeChainContainer() + .withNetwork(network) + .withPreconfiguredRegtestMasternode() + .start() + + whale = await new WhaleApiContainer() + .withNetwork(network) + .withNativeChain(defid, network) + .start() + + playground = await new PlaygroundApiContainer() + .withNetwork(network) + .withNativeChain(defid, network) + .start() +}) + +afterAll(async () => { + await whale.stop() + await defid.stop() + await playground.stop() +}) + +it('should playground.waitForReady()', async () => { + await playground.waitForReady() + + const playgroundApi = new PlaygroundApiClient(playground.getPlaygroundApiClientOptions()) + const { block } = await playgroundApi.playground.info() + expect(block.count).toBeGreaterThanOrEqual(150) + + // Check if any PoolPair is created. + const whaleApi = new WhaleApiClient(whale.getWhaleApiClientOptions()) + const data = await whaleApi.poolpairs.list(1) + expect(data[0]).toStrictEqual( + expect.objectContaining({ + name: expect.any(String) + }) + ) +}) diff --git a/packages/testcontainers/__tests__/containers/WhaleApiContainer.test.ts b/packages/testcontainers/__tests__/containers/WhaleApiContainer.test.ts index 0953bdc07..7df4ff524 100644 --- a/packages/testcontainers/__tests__/containers/WhaleApiContainer.test.ts +++ b/packages/testcontainers/__tests__/containers/WhaleApiContainer.test.ts @@ -1,10 +1,12 @@ -import { NativeChainContainer, StartedNativeChainContainer } from '@defichain/testcontainers' import { Network } from 'testcontainers' +import { WhaleApiClient } from '@defichain/whale-api-client' + import { + NativeChainContainer, + StartedNativeChainContainer, StartedWhaleApiContainer, WhaleApiContainer -} from '@defichain/testcontainers/dist/containers/AppContainer/WhaleApiContainer' -import { WhaleApiClient } from '@defichain/whale-api-client' +} from '../../src' let defid: StartedNativeChainContainer let whale: StartedWhaleApiContainer diff --git a/packages/testcontainers/src/containers/AppContainer/PlaygroundApiContainer.ts b/packages/testcontainers/src/containers/AppContainer/PlaygroundApiContainer.ts new file mode 100644 index 000000000..f218848da --- /dev/null +++ b/packages/testcontainers/src/containers/AppContainer/PlaygroundApiContainer.ts @@ -0,0 +1,71 @@ +import { GenericContainer, StartedNetwork } from 'testcontainers' +import { AbstractStartedContainer } from 'testcontainers/dist/modules/abstract-started-container' +import { waitForCondition } from '../../utils' +import { StartedNativeChainContainer } from '../NativeChainContainer' +import fetch from 'cross-fetch' + +// eslint-disable-next-line +// @ts-ignore because `package.json` will always be available in the root of pnpm package +import packageJson from '../../../package.json' + +/** + * For local environment, `:latest` tag will be used as there isn't pipeline to automatically rebuild image locally. + */ +const PLAYGROUND_VERSION = packageJson.version === '0.0.0' ? 'latest' : packageJson.version + +const PLAYGROUND_API_PORT = 3000 + +export class PlaygroundApiContainer extends GenericContainer { + constructor (image: string = `ghcr.io/jellyfishsdk/playground-api:${PLAYGROUND_VERSION}`) { + super(image) + this.withExposedPorts(PLAYGROUND_API_PORT).withStartupTimeout(120_000) + } + + public withNativeChain ( + container: StartedNativeChainContainer, + network: StartedNetwork + ): this { + const ipAddress = container.getIpAddress(network.getName()) + this.withEnvironment({ + PLAYGROUND_DEFID_URL: `http://${container.rpcUser}:${container.rpcPassword}@${ipAddress}:19554/` + }) + return this + } + + public async start (): Promise { + return new StartedPlaygroundApiContainer(await super.start()) + } +} + +export class StartedPlaygroundApiContainer extends AbstractStartedContainer { + public getContainerPort (): number { + return PLAYGROUND_API_PORT + } + + public getPort (): number { + return this.getMappedPort(this.getContainerPort()) + } + + getEndpoint (): string { + return `http://localhost:${this.getPort()}` + } + + getPlaygroundApiClientOptions (): { url: string, version: 'v0' } { + return { + url: this.getEndpoint(), + version: 'v0' + } + } + + async waitForReady (timeout: number = 590000): Promise { + const url = `${this.getEndpoint()}/_actuator/probes/readiness` + + return await waitForCondition(async () => { + const response = await fetch(url, { + method: 'GET' + }) + const { data } = await response.json() + return data.details.playground.status === 'up' + }, timeout, 200, 'waitForIndexedBlockHeight') + } +} diff --git a/packages/testcontainers/src/index.ts b/packages/testcontainers/src/index.ts index 52d2fa4fc..9ad62568a 100644 --- a/packages/testcontainers/src/index.ts +++ b/packages/testcontainers/src/index.ts @@ -22,6 +22,7 @@ export * from './containers/RegTestContainer/LoanContainer' export * from './containers/AppContainer/WhaleSanityContainer' export * from './containers/AppContainer/WhaleApiContainer' +export * from './containers/AppContainer/PlaygroundApiContainer' export * from './containers/NativeChainContainer' export * from './containers/NativeChainRpc'