From ab5416f44323c5fd5d479caffd2fb3da6201dd7d Mon Sep 17 00:00:00 2001 From: Evgeny Gamov Date: Tue, 16 Jun 2026 21:12:55 +0500 Subject: [PATCH] test(esmole): integration against ES 7 and 8 --- .../test/integration/elasticsearch.test.ts | 79 +++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 packages/esmole-mcp/test/integration/elasticsearch.test.ts diff --git a/packages/esmole-mcp/test/integration/elasticsearch.test.ts b/packages/esmole-mcp/test/integration/elasticsearch.test.ts new file mode 100644 index 0000000..9754ea4 --- /dev/null +++ b/packages/esmole-mcp/test/integration/elasticsearch.test.ts @@ -0,0 +1,79 @@ +import { GenericContainer, type StartedTestContainer, Wait } from 'testcontainers' +import { afterAll, beforeAll, describe, expect, it } from 'vitest' +import { createEsBackend } from '../../src/es/backend.js' +import type { ConnectionConfig } from '../../src/schema.js' +import { runGetMapping } from '../../src/tools/mappingTool.js' +import { runEsSearch } from '../../src/tools/search.js' + +const VERSIONS = ['7.17.22', '8.15.0'] + +for (const version of VERSIONS) { + describe('elasticsearch ' + version, () => { + let container: StartedTestContainer + let backend: ReturnType + + beforeAll(async () => { + container = await new GenericContainer( + 'docker.elastic.co/elasticsearch/elasticsearch:' + version + ) + .withExposedPorts(9200) + .withEnvironment({ + 'discovery.type': 'single-node', + 'xpack.security.enabled': 'false', + ES_JAVA_OPTS: '-Xms512m -Xmx512m' + }) + .withWaitStrategy( + Wait.forHttp('/_cluster/health', 9200).forStatusCodeMatching((c) => c === 200) + ) + .withStartupTimeout(180_000) + .start() + + const config = { + name: 'it', + host: container.getHost(), + type: 'elasticsearch', + scheme: 'http', + verifyTls: false, + user: 'elastic', + password: 'x', + readonly: false + } as ConnectionConfig + backend = createEsBackend({ + config, + connectHost: container.getHost(), + connectPort: container.getMappedPort(9200), + serverName: container.getHost() + }) + }, 240_000) + + afterAll(async () => { + await backend?.dispose() + await container?.stop() + }) + + it('indexes, refreshes, searches, and reads mapping', async () => { + await backend.request('PUT', '/books/_doc/1', { + body: { title: 'Dune', author: { name: 'Herbert' }, year: 1965 } + }) + await backend.request('POST', '/books/_refresh') + const managed = { + config: { name: 'it', readonly: false, type: 'elasticsearch' }, + backend + } as never + + const search = await runEsSearch( + managed, + 'books', + { match: { title: 'Dune' } }, + undefined, + 10, + ['title'] + ) + expect(search.status).toBe(200) + expect((search.body as { hits: { total: { value: number } } }).hits.total.value).toBe(1) + + const mapping = await runGetMapping(managed, 'books', false) + expect(mapping.fields).toContainEqual({ field: 'year', type: 'long' }) + }) + }) +}