diff --git a/README.md b/README.md index ffe7417..75e6283 100644 --- a/README.md +++ b/README.md @@ -86,6 +86,25 @@ const fn = mock.get({ }) ``` +#### `clear` + +Clears/removes mocks for specific route(s). + +```js +mock.clear({ + method: ['GET'], + path: ['/_search', '/:index/_search'] +}) +``` + +#### `clearAll` + +Clears all mocks. + +```js +mock.clearAll() +``` + #### `getConnection` Returns a custom `Connection` class that you **must** pass to the Elasticsearch client instance. diff --git a/index.d.ts b/index.d.ts index 03c4e2d..f2c62f0 100644 --- a/index.d.ts +++ b/index.d.ts @@ -8,6 +8,8 @@ declare class ClientMock { constructor() add(pattern: MockPattern, resolver: ResolverFn): ClientMock get(pattern: MockPattern): ResolverFn | null + clear(pattern: Pick): ClientMock + clearAll(): ClientMock getConnection(): typeof Connection } diff --git a/index.js b/index.js index 719e12f..dba1671 100644 --- a/index.js +++ b/index.js @@ -76,6 +76,28 @@ class Mocker { return null } + clear (pattern) { + for (const key of ['method', 'path']) { + if (Array.isArray(pattern[key])) { + for (const value of pattern[key]) { + this.clear({ ...pattern, [key]: value }) + } + return this + } + } + + if (typeof pattern.method !== 'string') throw new ConfigurationError('The method is not defined') + if (typeof pattern.path !== 'string') throw new ConfigurationError('The path is not defined') + + this[kRouter].off(pattern.method, pattern.path) + return this + } + + clearAll () { + this[kRouter].reset() + return this + } + getConnection () { return buildConnectionClass(this) } diff --git a/test.js b/test.js index bf30a74..2227161 100644 --- a/test.js +++ b/test.js @@ -778,3 +778,103 @@ test('ndjson API support (as stream with compression)', async t => { t.deepEqual(response.body, { status: 'ok' }) t.is(response.statusCode, 200) }) + +test('Should clear individual mocks', async t => { + const mock = new Mock() + const client = new Client({ + node: 'http://localhost:9200', + Connection: mock.getConnection() + }) + + mock.add({ + method: 'GET', + path: ['/test1/_search', '/test2/_search'] + }, () => { + return { status: 'ok' } + }) + + // Clear test1 but not test2 + mock.clear({ method: 'GET', path: ['/test1/_search'] }) + + // test2 still works + const response = await client.search({ + index: 'test2', + q: 'foo:bar' + }) + t.deepEqual(response.body, { status: 'ok' }) + t.is(response.statusCode, 200) + + // test1 does not + try { + await client.search({ + index: 'test1', + q: 'foo:bar' + }) + t.fail('Should throw') + } catch (err) { + t.true(err instanceof errors.ResponseError) + t.deepEqual(err.body, { error: 'Mock not found' }) + t.is(err.statusCode, 404) + } +}) + +test('.mock should throw if method and path are not defined', async t => { + const mock = new Mock() + + try { + mock.clear({ path: '/' }, () => {}) + t.fail('Should throw') + } catch (err) { + t.true(err instanceof errors.ConfigurationError) + t.is(err.message, 'The method is not defined') + } + + try { + mock.clear({ method: 'GET' }, () => {}) + t.fail('Should throw') + } catch (err) { + t.true(err instanceof errors.ConfigurationError) + t.is(err.message, 'The path is not defined') + } +}) + +test('Should clear all mocks', async t => { + const mock = new Mock() + const client = new Client({ + node: 'http://localhost:9200', + Connection: mock.getConnection() + }) + + mock.add({ + method: 'GET', + path: ['/test1/_search', '/test2/_search'] + }, () => { + return { status: 'ok' } + }) + + // Clear mocks + mock.clearAll() + + try { + await client.search({ + index: 'test1', + q: 'foo:bar' + }) + t.fail('Should throw') + } catch (err) { + t.true(err instanceof errors.ResponseError) + t.deepEqual(err.body, { error: 'Mock not found' }) + t.is(err.statusCode, 404) + } + try { + await client.search({ + index: 'test2', + q: 'foo:bar' + }) + t.fail('Should throw') + } catch (err) { + t.true(err instanceof errors.ResponseError) + t.deepEqual(err.body, { error: 'Mock not found' }) + t.is(err.statusCode, 404) + } +})