Skip to content

Commit

Permalink
feat: add decorateAll & getDefinition methods to DapiWrapper class (#16)
Browse files Browse the repository at this point in the history
Add a method to be able to decorate all DAPI fns at once and a method to
get the DAPI definition
  • Loading branch information
carpasse authored Feb 17, 2024
2 parents 9811eec + 2952ec1 commit 598ebea
Show file tree
Hide file tree
Showing 3 changed files with 100 additions and 1 deletion.
31 changes: 31 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -334,6 +334,16 @@ The class also allows to decorate the Dapi functions with decorators and hooks.
#### Methods
##### `getDefinition`
`DapiDefinition` getter.
**Syntax**:
```Typescript
getDefinition(): DapiDefinition<DEPENDENCIES, DAPI>
```
##### `getDependencies`
Dependencies getter.
Expand Down Expand Up @@ -471,6 +481,27 @@ Removes a decorator from the `DapiWrapper` instance.
- `key` - The name of the decorated method. Must be a key of the [`DapiDefinition.fns`](#dapidefinition) fns dictionary.
- `decorator` - The decorator function to be removed from the method.

##### `decorateAll`

Decorates all the `DapiDefinition.fns` with the passed decorator.

**Syntax**:

```Typescript
decorateAll(decorator: DecoratorFn<DAPI[keyof DAPI], DapiWrapper>): () => void
```

**Parameters**:

- `decorator` - The decorator function to be added to the method. Each decorator must accept the following arguments
- `fn` - The function to be decorated.
- `deps` - The dependencies of the [`DapiDefinition.fns`](#dapidefinition).
- `args` - The arguments passed to the method.

**Returns**:

- Function to remove the all the added that accepts no arguments.

##### `addHook`

Adds a hook to a `DapiFn` of the `DapiWrapper` instance. Hooks are functions that are called before (`hookType` = `'pre'`) or after (`hookType` = `'post'`) the `DapiFn` is called.
Expand Down
28 changes: 28 additions & 0 deletions src/DapiMixin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,15 @@ export function DapiMixin<DEPENDENCIES, DAPI extends DapiFns<DEPENDENCIES>, T ex
this.__definition.dependencies = newDeps;
}

/**
* DapiDefinition getter.
*
* @returns DapiDefinition
*/
getDefinition() {
return this.__definition;
}

/**
* Returns a JSON representation of the `DapiWrapper` instance.
* @param replacer An array of strings and numbers that acts as an approved list for selecting the object properties that will be stringified.
Expand Down Expand Up @@ -241,6 +250,25 @@ export function DapiMixin<DEPENDENCIES, DAPI extends DapiFns<DEPENDENCIES>, T ex
};
}

/**
* Decorates all the Dapi functions of the `DapiWrapper`'s Dapi functions dictionary.
* @param decorator The decorator function. The decorator function receives the decorated function as its first argument and the rest of the arguments are the arguments of the decorated function.
* @returns A function to remove all the added decorators.
*/
decorateAll(decorator: DecoratorFn<DAPI[keyof DAPI], DapiWrapper>) {
const removeDecorators: (() => void)[] = [];

for (const key of Object.keys(this.__definition.fns)) {
removeDecorators.push(this.addDecorator(key as keyof DAPI, decorator));
}

return () => {
for (const removeDecorator of removeDecorators) {
removeDecorator();
}
};
}

/**
* Removes a decorator from the DapiWrapper instance.
* @param key The key of the function to remove the decorator from. Must be a key of the `DapiDefinition.fns` dictionary.
Expand Down
42 changes: 41 additions & 1 deletion src/__tests__/DapiMixin.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,13 @@ describe('DapiMixin', () => {
assert.deepStrictEqual(testClass.getDependencies(), newDependencies);
});

it('should expose a definition getter', () => {
const TestClass = DapiMixin(definition, BaseTestClass);
const instance = new TestClass();

assert.deepStrictEqual(instance.getDefinition(), definition);
});

it('should throw if you try to set the dependencies to a falsy value', () => {
const TestClass = DapiMixin(definition, BaseTestClass);
const instance = new TestClass();
Expand Down Expand Up @@ -308,7 +315,7 @@ describe('DapiMixin', () => {
assert.throws(() => instance.command4());
});

it('should be possible to decorate the commands', () => {
it('should be possible to decorate the dapi fns', () => {
const TestClass = DapiMixin(definition, BaseTestClass);
const instance = new TestClass();
const decorator = mock.fn(function (method, ...args) {
Expand Down Expand Up @@ -685,5 +692,38 @@ describe('DapiMixin', () => {
assert.strictEqual(TestClass.testProperty, 'test');
assert.strictEqual(TestClass.baseStaticProperty, 'baseStaticProperty');
});

it('should be possible to decorate all dapi functions at once', async () => {
const TestClass = DapiMixin(definition, BaseTestClass);
const instance = new TestClass();
const decorator = mock.fn(function (method, ...args) {
return method(...args);
});

const removeAllDecorators = instance.decorateAll(decorator);

assert.deepStrictEqual(instance.command1('a1', 'a2'), ['a1', 'a2']);
assert.deepStrictEqual(command1.mock.calls[0].arguments, [deps, 'a1', 'a2']);
assert.deepStrictEqual(command1.mock.calls[0].this, instance);
assert.equal(decorator.mock.callCount(), 1);

assert.deepStrictEqual(instance.command2(), undefined);
assert.deepStrictEqual(command2.mock.calls[0].arguments, [deps]);
assert.deepStrictEqual(command2.mock.calls[0].this, instance);
assert.equal(decorator.mock.callCount(), 2);

assert.deepStrictEqual(await instance.command3('a1', 'a2'), ['a1', 'a2']);
assert.deepStrictEqual(command3.mock.calls[0].arguments, [deps, 'a1', 'a2']);
assert.deepStrictEqual(command3.mock.calls[0].this, instance);
assert.equal(decorator.mock.callCount(), 3);

removeAllDecorators();

assert.deepStrictEqual(instance.command1('a1', 'a2'), ['a1', 'a2']);
assert.deepStrictEqual(instance.command2(), undefined);
assert.deepStrictEqual(await instance.command3('a1', 'a2'), ['a1', 'a2']);

assert.equal(decorator.mock.callCount(), 3);
});
});
});

0 comments on commit 598ebea

Please sign in to comment.