kibana/packages/kbn-expect
Gerard Soldevila b24fdf5d3f
Sustainable Kibana Architecture: Categorise straightforward packages (#199630)
## Summary

This PR is part of the Kibana Sustainable Architecture effort.

The goal is to start categorising Kibana packages into _generic
platform_ (`group: "platform"`) vs _solution-specific_.

```
group?: 'search' | 'security' | 'observability' | 'platform'
visibility?: 'private' | 'shared'
```
Uncategorised modules are considered to be `group: 'common', visibility:
'shared'` by default.

We want to prevent code from solution A to depend on code from solution
B.
Thus, the rules are pretty simple:

* Modules can only depend on:
  * Modules in the same group
  * OR modules with 'shared' visibility
* Modules in `'observability', 'security', 'search'` groups are
mandatorily `visibility: "private"`.

Long term, the goal is to re-organise packages into dedicated folders,
e.g.:

```
x-pack/platform/plugins/private
x-pack/observability/packages
```

For this first wave, we have categorised packages that seem
"straightforward":
* Any packages that have:
  * at least one dependant module
  * all dependants belong to the same group
* Categorise all Core packages:
  * `@kbn/core-...-internal` => _platform/private_
  * everything else => _platform/shared_
* Categorise as _platform/shared_ those packages that:
  * Have at least one dependant in the _platform_ group.
  * Don't have any `devOnly: true` dependants.

### What we ask from you, as CODEOWNERS of the _package manifests_, is
that you confirm that the categorisation is correct:

* `group: "platform", visibility: "private"` if it's a package that
should only be used from platform code, not from any solution code. It
will be loaded systematically in all serverless flavors, but solution
plugins and packages won't be able to `import` from it.
* `group: "platform", visibility: "shared"` if it's a package that can
be consumed by both platform and solutions code. It will be loaded
systematically in all serverless flavors, and anybody can import / use
code from it.
* `group: "observability" | "security" | "search", visibility:
"private"` if it's a package that is intented to be used exclusively
from a given solution. It won't be accessible nor loaded from other
solutions nor platform code.

Please refer to
[#kibana-sustainable-architecture](https://elastic.slack.com/archives/C07TCKTA22E)
for any related questions.

---------

Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
2024-11-22 10:33:25 +01:00
..
expect.d.ts chore(NA): eslint rule for disallowing naked eslint-disable (#136408) 2022-07-19 17:11:04 +01:00
expect.js kbn-expect - add .eql support for sets (#200034) 2024-11-14 14:59:28 +01:00
expect.test.ts kbn-expect - add .eql support for sets (#200034) 2024-11-14 14:59:28 +01:00
jest.config.js kbn-expect - add .eql support for sets (#200034) 2024-11-14 14:59:28 +01:00
kibana.jsonc Sustainable Kibana Architecture: Categorise straightforward packages (#199630) 2024-11-22 10:33:25 +01:00
LICENSE.txt
package.json add kibana.jsonc files to existing packages (#138965) 2022-09-08 13:31:57 -07:00
README.mdx
tsconfig.json kbn-expect - add .eql support for sets (#200034) 2024-11-14 14:59:28 +01:00

---
id: kibDevDocsOpsExpect
slug: /kibana-dev-docs/ops/expect
title: "@kbn/expect"
description: An assertion toolkit based on should.js
date: 2022-05-17
tags: ['kibana', 'dev', 'contributor', 'operations', 'expect']
---

Minimalistic BDD assertion toolkit based on
[should.js](http://github.com/visionmedia/should.js)

```js
expect(window.r).to.be(undefined);
expect({ a: 'b' }).to.eql({ a: 'b' })
expect(5).to.be.a('number');
expect([]).to.be.an('array');
expect(window).not.to.be.an(Image);
```

> NOTE: This is a local fork of https://github.com/Automattic/expect.js

## Features

- Cross-browser: works on IE6+, Firefox, Safari, Chrome, Opera.
- Compatible with all test frameworks.
- Node.JS ready (`require('@kbn/expect')`).

## API

**ok**: asserts that the value is _truthy_ or not

```js
expect(1).to.be.ok();
expect(true).to.be.ok();
expect({}).to.be.ok();
expect(0).to.not.be.ok();
```

**be** / **equal**: asserts `===` equality

```js
expect(1).to.be(1)
expect(NaN).not.to.equal(NaN);
expect(1).not.to.be(true)
expect('1').to.not.be(1);
```

**eql**: asserts loose equality that works with objects

```js
expect({ a: 'b' }).to.eql({ a: 'b' });
expect(1).to.eql('1');
```

**a**/**an**: asserts `typeof` with support for `array` type and `instanceof`

```js
// typeof with optional `array`
expect(5).to.be.a('number');
expect([]).to.be.an('array');  // works
expect([]).to.be.an('object'); // works too, since it uses `typeof`

// constructors
expect([]).to.be.an(Array);
expect(tobi).to.be.a(Ferret);
expect(person).to.be.a(Mammal);
```

**match**: asserts `String` regular expression match

```js
expect(program.version).to.match(/[0-9]+\.[0-9]+\.[0-9]+/);
```

**contain**: asserts indexOf for an array or string

```js
expect([1, 2]).to.contain(1);
expect('hello world').to.contain('world');
```

**length**: asserts array `.length`

```js
expect([]).to.have.length(0);
expect([1,2,3]).to.have.length(3);
```

**empty**: asserts that an array is empty or not

```js
expect([]).to.be.empty();
expect({}).to.be.empty();
expect({ length: 0, duck: 'typing' }).to.be.empty();
expect({ my: 'object' }).to.not.be.empty();
expect([1,2,3]).to.not.be.empty();
```

**property**: asserts presence of an own property (and value optionally)

```js
expect(window).to.have.property('expect')
expect(window).to.have.property('expect', expect)
expect({a: 'b'}).to.have.property('a');
```

**key**/**keys**: asserts the presence of a key. Supports the `only` modifier

```js
expect({ a: 'b' }).to.have.key('a');
expect({ a: 'b', c: 'd' }).to.only.have.keys('a', 'c');
expect({ a: 'b', c: 'd' }).to.only.have.keys(['a', 'c']);
expect({ a: 'b', c: 'd' }).to.not.only.have.key('a');
```

**throw**/**throwException**/**throwError**: asserts that the `Function` throws or not when called

```js
expect(fn).to.throw(); // synonym of throwException
expect(fn).to.throwError(); // synonym of throwException
expect(fn).to.throwException(function (e) { // get the exception object
  expect(e).to.be.a(SyntaxError);
});
expect(fn).to.throwException(/matches the exception message/);
expect(fn2).to.not.throwException();
```

**withArgs**: creates anonymous function to call fn with arguments

```js
expect(fn).withArgs(invalid, arg).to.throwException();
expect(fn).withArgs(valid, arg).to.not.throwException();
```

**within**: asserts a number within a range

```js
expect(1).to.be.within(0, Infinity);
```

**greaterThan**/**above**: asserts `>`

```js
expect(3).to.be.above(0);
expect(5).to.be.greaterThan(3);
```

**lessThan**/**below**: asserts `<`

```js
expect(0).to.be.below(3);
expect(1).to.be.lessThan(3);
```

**fail**: explicitly forces failure.

```js
expect().fail()
expect().fail("Custom failure message")
```

## Using with a test framework

For example, if you create a test suite with
[mocha](http://github.com/visionmedia/mocha).

Let's say we wanted to test the following program:

**math.js**

```js
function add (a, b) { return a + b; };
```

Our test file would look like this:

```js
describe('test suite', function () {
  it('should expose a function', function () {
    expect(add).to.be.a('function');
  });

  it('should do math', function () {
    expect(add(1, 3)).to.equal(4);
  });
});
```

If a certain expectation fails, an exception will be raised which gets captured
and shown/processed by the test runner.

## Differences with should.js

- No need for static `should` methods like `should.strictEqual`. For example,
  `expect(obj).to.be(undefined)` works well.
- Some API simplifications / changes.
- API changes related to browser compatibility.