Giter Site home page Giter Site logo

elastic / elasticsearch-js-mock Goto Github PK

View Code? Open in Web Editor NEW
45.0 5.0 10.0 94 KB

Mock utility for the Elasticsearch's Node.js client

Home Page: https://www.elastic.co/guide/en/elasticsearch/client/javascript-api/current/client-testing.html

License: Apache License 2.0

JavaScript 93.03% TypeScript 6.97%
elasticsearch nodejs client rest mock testing-tools

elasticsearch-js-mock's Issues

Mocking a "scroll" search

Hi,
I really appreciate the mocking library, I've been trying to mock a scroll request... To test it, I want to return the _scroll_id. But, when I include it, I get the error below. Wondering if someone can either point me at an example of how to mock this, or suggest a way forward?

    ResponseError: Response Error

      at Class.<anonymous> (node_modules/@elastic/elasticsearch/lib/Transport.js:257:25)
      at endReadableNT (node_modules/readable-stream/lib/_stream_readable.js:1010:12)

Here's how I'm trying to send the mock in

    esmock.add(
      {
        method: ["GET", "POST"],
        path: "/:index/_search"
      },
      () => {
        return {
          _scroll_id:
            "DXF1ZXJ5QW5kRmV0Y2gBAAAAAAAAAAQWSlpLQUZQbDNTSktXMWxWaDNJcnZZUQ==",
          hits: {
            total: { value: 1, relation: "eq" },
            max_score: 1.0,
            hits: [
              {
                _index: "test",
                _type: "doc",
                _id: "component/f745b673-25fe-5b68-9e8a-361b4e13185a",
                _score: 1.0,
                _source: {
                  id: "component/f745b673-25fe-5b68-9e8a-361b4e13185a"
                }
              }
            ]
          }
        };
      }
    );
    esmock.add(
      {
        method: ["GET", "POST"],
        path: "/_search/scroll"
      },
      () => {
        return {
          _scroll_id:
            "DXF1ZXJ5QW5kRmV0Y2gBAAAAAAAAAAQWSlpLQUZQbDNTSktXMWxWaDNJcnZZUQ==",
          hits: { hits: [] }
        };
      }
    );

How to simulate a delayed response or error?

Hi, I need to simulate a response or error returned by the mocked cluster with a specific time delay. How to do that? By reading the documentation I didn't found any solution.
Thanks

Support for multiple definitions

It can happen that a. user needs to mock in the same way different methods/paths, we should provide a nice way to do so. For example:

mock.add({
  method: ['GET', 'HEAD'],
  path: '/'
}, () => {
  return { status: 'ok' }
})

How to create ResponseErrors in TypeScript

Hi, thanks for this excellent library.

I'm trying to mock specific ResponseErrors in TypeScript but I'm getting stuck. The ResponseError constructor takes a huge amount of arguments that I'm unable to workaround without the compiler complaining or it not working.

This is as far as I've got:

import ClientMock from "@elastic/elasticsearch-mock";
import { Client, Connection } from "@elastic/elasticsearch";
import { ResponseError } from "@elastic/elasticsearch/lib/errors";

type RootCause = {
    type: string;
    reason: string;
};

export function addResponseError(
    clientMock: ClientMock,
    method: string,
    path: string,
    statusCode: number,
    rootCauses: RootCause[]
): void {
    const connection = clientMock.getConnection();
    clientMock.add(
        {
            method,
            path,
        },
        () => {
            return new ResponseError({
                body: {
                    errors: {
                        root_cause: rootCauses,
                    },
                    status: statusCode
                },
                statusCode,
                headers: {},
                meta: {
                    name: "foo",
                    context: {},
                    aborted: false,
                    attempts: 0,
                    request: {
                        id: 1,
                        options: {},
                        params: {
                            method,
                            path,
                        },
                    },
                    connection,
                },
                warnings: [],
            });
        }
    );
}

I had previously set connection to {} as Connection but I received no response in my test, so I thought I could use the one from ClientMock.getConnection() instead. However, I get an error:

Type 'typeof Connection' is missing the following properties from type 'Connection': url, ssl, id, headers, and 13 more.ts(2740)
Transport.d.ts(63, 5): The expected type comes from property 'connection' which is declared here on type '{ context: Context; name: string | symbol; request: { params: TransportRequestParams; options: TransportRequestOptions; id: any; }; connection: Connection; attempts: number; aborted: boolean; sniff?: { ...; } | undefined; }'

Any suggestions?

Clear mocks

It's very useful to clear mocks completely between different unit tests. Is there any way to do that currently?

how to use with multiple versions ?

Following install multiple versions

I have

"dependencies": {
  "es6": "npm:@elastic/elasticsearch@^6.7.0",
  "es7": "npm:@elastic/elasticsearch@^7.0.0"
}

in my package.json

However when adding elasticsearch-mock, it uses require('@elastic/elasticsearch') for { Connection, errors } (without a peer dependency too ...)

How can I use the client I want with mock ?

elastic mocks timeout when used with jest fake timers

Hi there ๐Ÿ‘‹๐Ÿป

Elasticsearch mocks don't work with jest fake timers and the jest test runner seems to just time out when I use fake timers

To reproduce the issue please check this codesandbox

// uncomment the following 2 lines and the tests will timeout and fail
// jest.useFakeTimers("modern");
// jest.setSystemTime(new Date());

it("should run", async () => {
  // when using fake timers you can use the following line to get the test to run correctly
  // jest.useRealTimers();
  const { Client } = require("@elastic/elasticsearch");
  const Mock = require("@elastic/elasticsearch-mock");
  const elasticMock = new Mock();
  const client = new Client({
    node: "http://localhost:9200",
    Connection: elasticMock.getConnection()
  });
  elasticMock.add({ method: "GET", path: "/_cat/health" }, () => ({
    status: "ok"
  }));
  const fake = await client.cat.health();
  expect(fake.status).toEqual("ok");
});

We push data to elastic search as a callback / side effect for write operations on some models, some of which are time sensitive... we use fake timers to help us tests different scenarios.

Is there a way where we can use elasticsearch-mock with jest fake timers or any other timer alternatives ?

How to use elastic-mock properly?

"@elastic/elasticsearch": "^8.1.0",
"@elastic/elasticsearch-mock": "^2.0.0",
"jest": "^24.9.0",
Node: v12.22.7

image

console.log(mock.getConnection()) -> [class MockConnection extends BaseConnection]

console.error node_modules/jest-jasmine2/build/jasmine/Env.js:289
  Unhandled error

console.error node_modules/jest-jasmine2/build/jasmine/Env.js:290
  ResponseError: {"error":"Mock not found"}
      at SniffingTransport.request (.../node_modules/@elastic/transport/src/Transport.ts:532:17)
      at Indices.delete (.../node_modules/@elastic/elasticsearch/src/api/api/indices.ts:301:12)

Fails since 7.14.0

Since updating to @elastic/elasticsearch 7.14.0, I'm getting "error":"Mock not found" in all my unit tests. They worked fine before the update. Has this something to do with client verification in 7.14?

High level API around the http mock

We should not assume that all users know the HTTP style query, we should provide a way to allow them to specify which API to mock.

mock.add({
  api: 'indices.delete'
}, () => {
  return { acknowledged: true }
})

Same request with no data and with data gets the same result even if they don't have same response.

Hello, I'm facing this issue.
Right now I'm trying to get different response for same verb with different query, but I always get the response for the one that do not have query content:

mock.add({
  method: 'GET',
  path: '/index/_search'
}, () => {
  return {
    hits: {
      total: { value: 1, relation: 'eq' },
      hits: [{ _source: { baz: 'faz' } }]
    }
  }
})
mock.add({
  method: 'GET',
  path: '/index/_search',
  querystring: { pretty: 'true' }
}, () => {
  return {
    hits: {
      total: { value: 1, relation: 'eq' },
      hits: [
       { _source: { baz: 'new' } },
       { _source: { baz: 'test' } }
     ]
    }
  }
})

So, client.search({ index: 'test' })
and client.search({ index: 'test', querystring: { pretty: 'true' }})
always gave me

hits: {
      total: { value: 1, relation: 'eq' },
      hits: [{ _source: { baz: 'faz' } }]
    }
  }

can someone help me with this?

Making assertions about how the mock was used

Particularly when using wildcards, I might want to make assertions about how the client was used.

Sample (with workaround to show want I want to do - should run with npx ts-node if the client and the mock are installed):

import { Client } from '@elastic/elasticsearch';
import Mock, { MockPattern } from '@elastic/elasticsearch-mock';

// Setup
const mock = new Mock();
const client = new Client({
    node: 'http://localhost:9200',
    Connection: mock.getConnection(),
});

// Prepare the mock for my "test"
// Use this to track calls (could use something more sophisticated like jest.fn)
const esIndexMockCalls: Array<MockPattern> = [];
mock.add({
    method: ['POST', 'PUT'],
    path: '/:index/_doc/:id',
}, (params: MockPattern) => {
    // Record the call
    esIndexMockCalls.push(params);
    return { status: 'ok' };
});

// Run the "test"
client.index({
    index: 'myindex',
    id: 'mydocument',
    body: {
        foo: 'bar',
    },
}).then(() => {
    // Make "assertions"
    // Check that only one call was made
    if (esIndexMockCalls.length !== 1) {
        throw new Error('Expected one call');
    }
    // Check that we indexed the right thing in the right place
    if (esIndexMockCalls[0].path !== '/myindex/_doc/mydocument') {
        throw new Error('Expected index of mydocument in myindex');
    }
    console.log('Indexed mydocument in myindex as expected');
});

The alternative is to put these assertions in the callback, eg:

mock.add({
    method: ['POST', 'PUT'],
    path: '/:index/_doc/:id',
}, (params: MockPattern) => {
    if (params.path !== 'myindex/_doc/mydocument' {
        throw new Error('Unexpected index path');
    }
    return { status: 'ok' };
});

but this doesn't allow for things like checking how many calls were made. Eg if I have code where I index multiple documents in parallel, I want to be able to check that each one got indexed exactly once.

Is something like this handled by the mock client? Or is using something like jest.fn to track the calls from within the callback the best way of going about this?

How to mock bulk method

Hi, I am trying to mock the bulk method but it is returning the following error:

import { Client } from '@elastic/elasticsearch';
import ElasticMock from '@elastic/elasticsearch-mock';

const esResponse = { took: 9, errors: false };

const mock = new ElasticMock();
const client = new Client({
  node: 'http://localhost:9200',
  Connection: mock.getConnection()
});

mock.add({
  method: 'POST',
  path: '/_bulk'
}, () => esResponse);

let response;
try {
  response = await client.bulk({ body: [{ foo: 'bar' }, { baz: 'fa\nz' }] });
  console.log(response);
} catch (error) {
  console.log(error);
  response = { body: {} };
}
ResponseError: Response Error
          at onBody (/Users/krishankant/Public/Work/fw-bt-3ds-metrics-lambda/node_modules/@elastic/elasticsearch/lib/Transport.js:349:23)
          at Class.onEnd (/Users/krishankant/Public/Work/fw-bt-3ds-metrics-lambda/node_modules/@elastic/elasticsearch/lib/Transport.js:275:11)
          at Class.emit (events.js:223:5)
          at endReadableNT (/Users/krishankant/Public/Work/fw-bt-3ds-metrics-lambda/node_modules/readable-stream/lib/_stream_readable.js:1010:12)
          at processTicksAndRejections (internal/process/task_queues.js:81:21) {
        name: 'ResponseError',
        meta: {
          body: { error: 'Mock not found' },
          statusCode: 404,
          headers: {
            'content-type': 'application/json;utf=8',
            date: '2021-08-16T12:09:51.899Z',
            connection: 'keep-alive',
            'content-length': 26
          },
          meta: {
            context: null,
            request: [Object],
            name: 'elasticsearch-js',
            connection: [Object],
            attempts: 0,
            aborted: false
          }
        }
      }

Can anyone help me to resolve this issue?

ReferenceError: setImmediate is not defined

I am using next.js project with typescript.

I am facing this issue when jest tries to run the mock file

ReferenceError: setImmediate is not defined

      12 | }
      13 |
    > 14 | import { Client } from '@elastic/elasticsearch';
         | ^
      15 | import Mock from '@elastic/elasticsearch-mock';
      16 |
      17 | const mock = new Mock();

      at Object.<anonymous> (node_modules/@elastic/elasticsearch/lib/Helpers.js:27:30)
      at Object.<anonymous> (node_modules/@elastic/elasticsearch/index.js:29:17)
      at Object.<anonymous> (__mocks__/elasticsearch.ts:14:1)

in the file __mocks__/elasticsearch.ts

import { Client } from '@elastic/elasticsearch';
import Mock from '@elastic/elasticsearch-mock';

const mock = new Mock();
const client = new Client({
  node: 'http://localhost:9200',
  Connection: mock.getConnection(),
});

mock.add(
  {
    method: 'GET',
    path: '/',
  },
  () => {
    return { status: 'ok' };
  }
);

client.info(console.log);

How to seperate mocks from implementation?

I'm trying to use this mock to write unit tests for production code that makes calls to elasticsearch.

I am struggling to see how the actual production code can be seperated from the mock.

For example, how could a test be written for code like this:

async function executeQuery(){
  const client = new Client({
    auth: {
      api_key: ...
    },
  });
  await client.query(...)
}

Test using jest:

test('call execute query with mocked elasticsearch client', async ()=>{
  // what needs to go here to make the function use a mocked client?
  await executeQuery()
})

Having to pass the mock to the Connection parameter of creating the Client requires having the mock in the implementation code that I'm trying to test. Surely it must be possible to have seperate files for the implementation logic and the unit test?

The example shown in the docs shows creating the client and mocking the responses in the same file, but in a real project wouldn't these necessarily be in different places?

ProductNotSupportedError for elasticsearch-js-mock >=v0.3.1 <=1.0.0 and @elasticsearch/elasticsearch >7.13.0 <= 7.17.0

We have a set of Elasticsearch client unit tests which make use of the mock interface. These tests were previously working using elasticsearch-js-mock v0.3.1 and an old version of Elasticsearchclient 7.6.1. Upon upgrading to the latest ES client 7.17, we also brought up the mock version to 1.0.0 (as it says it works with ES 7 clients). However, this causes the error:

ProductNotSupportedError: The client noticed that the server is not Elasticsearch and we do not support this unknown product.

to appear when the client getMapping endpoint is called. Further investigation shows that this error occurs for both elasticsearch-js-mock v0.3.1 and v1.0.0, with all elasticsearch 7 clients greater than 7.13.0. It appears that this problem was addressed a while ago for earlier versions of Elasticsearch, and thus 0.3.1 was born; could something have happened to break this version check with the latest versions of the Elasticsearchclient?

Full stack trace:
`
ProductNotSupportedError: The client noticed that the server is not Elasticsearch and we do not support this unknown product.

  75 | function getMappingFromElastic(params) {
  76 |     return __awaiter(this, void 0, void 0, function* () {
> 77 |         return client.indices.getMapping(params);
     |                               ^
  78 |     });
  79 | }
  80 | exports.getMappingFromElastic = getMappingFromElastic;

  at Transport.request (node_modules/@elastic/elasticsearch/lib/Transport.js:477:19)
  at IndicesApi.indicesGetMappingApi [as getMapping] (node_modules/@elastic/elasticsearch/api/api/indices.js:845:25)
  at getMapping (build/elasticsearch/elasticsearchClient.js:77:31)
  at next (build/elasticsearch/elasticsearchClient.js:8:71)
  at Object.<anonymous>.__awaiter (build/elasticsearch/elasticsearchClient.js:4:12)
  at __awaiter (build/elasticsearch/elasticsearchClient.js:76:12)
  at ElasticsearchMappingHelper.<anonymous> (build/elasticsearch/elasticsearchMappingHelper.js:35:83)
  at next (build/elasticsearch/elasticsearchMappingHelper.js:8:71)
  at Object.<anonymous>.__awaiter (build/elasticsearch/elasticsearchMappingHelper.js:4:12)
  at ElasticsearchMappingHelper.__awaiter [as getFieldNames] (build/elasticsearch/elasticsearchMappingHelper.js:29:16)
  at getFieldNames (build/elasticsearch/__testing__/elasticsearchMappingHelper.test.js:43:24)
  at next (build/elasticsearch/__testing__/elasticsearchMappingHelper.test.js:8:71)
  at Object.<anonymous>.__awaiter (build/elasticsearch/__testing__/elasticsearchMappingHelper.test.js:4:12)
  at Object.__awaiter (build/elasticsearch/__testing__/elasticsearchMappingHelper.test.js:42:40)

`

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.