Skip to content

Commit 628b865

Browse files
dinvladMikeRyanDev
authored andcommitted
feat(Effects): Add getEffectsMetadata() helper for verifying metadata
Closes #491
1 parent aae4064 commit 628b865

File tree

4 files changed

+97
-2
lines changed

4 files changed

+97
-2
lines changed

docs/effects/testing.md

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,46 @@ describe('My Effects', () => {
4747
effects.someSource$.subscribe(result => {
4848
expect(result).toEqual(AnotherAction);
4949
});
50-
});
50+
});
51+
});
52+
```
53+
54+
### getEffectsMetadata
55+
Returns decorator configuration for all effects in a class instance.
56+
Use this function to ensure that effects have been properly decorated.
57+
58+
Usage:
59+
```ts
60+
import { TestBed } from '@angular/core/testing';
61+
import { EffectsMetadata, getEffectsMetadata } from '@ngrx/effects';
62+
import { MyEffects } from './my-effects';
63+
64+
describe('My Effects', () => {
65+
let effects: MyEffects;
66+
let metadata: EffectsMetadata<MyEffects>;
67+
68+
beforeEach(() => {
69+
TestBed.configureTestingModule({
70+
providers: [
71+
MyEffects,
72+
// other providers
73+
],
74+
});
75+
76+
effects = TestBed.get(MyEffects);
77+
metadata = getEffectsMetadata(effects);
78+
});
79+
80+
it('should register someSource$ that dispatches an action', () => {
81+
expect(metadata.someSource$).toEqual({ dispatch: true });
82+
});
83+
84+
it('should register someOtherSource$ that does not dispatch an action', () => {
85+
expect(metadata.someOtherSource$).toEqual({ dispatch: false });
86+
});
87+
88+
it('should not register undecoratedSource$', () => {
89+
expect(metadata.undecoratedSource$).toBeUndefined();
90+
});
5191
});
5292
```

modules/effects/spec/effects_metadata.spec.ts

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import {
22
Effect,
3+
getEffectsMetadata,
34
getSourceMetadata,
45
getSourceForInstance,
56
} from '../src/effects_metadata';
@@ -46,4 +47,36 @@ describe('Effect Metadata', () => {
4647
expect(proto).toBe(Fixture.prototype);
4748
});
4849
});
50+
51+
describe('getEffectsMetadata', () => {
52+
it('should get map of metadata for all decorated effects in a class instance', () => {
53+
class Fixture {
54+
@Effect() a: any;
55+
@Effect({ dispatch: true })
56+
b: any;
57+
@Effect({ dispatch: false })
58+
c: any;
59+
}
60+
61+
const mock = new Fixture();
62+
63+
expect(getEffectsMetadata(mock)).toEqual({
64+
a: { dispatch: true },
65+
b: { dispatch: true },
66+
c: { dispatch: false },
67+
});
68+
});
69+
70+
it('should return an empty map if the class has not been decorated', () => {
71+
class Fixture {
72+
a: any;
73+
b: any;
74+
c: any;
75+
}
76+
77+
const mock = new Fixture();
78+
79+
expect(getEffectsMetadata(mock)).toEqual({});
80+
});
81+
});
4982
});

modules/effects/src/effects_metadata.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,3 +40,21 @@ export const getSourceMetadata = compose(
4040
getEffectMetadataEntries,
4141
getSourceForInstance
4242
);
43+
44+
export type EffectsMetadata<T> = {
45+
[key in keyof T]?:
46+
| undefined
47+
| {
48+
dispatch: boolean;
49+
}
50+
};
51+
52+
export function getEffectsMetadata<T>(instance: T): EffectsMetadata<T> {
53+
const metadata: EffectsMetadata<T> = {};
54+
55+
getSourceMetadata(instance).forEach(({ propertyName, dispatch }) => {
56+
metadata[propertyName] = { dispatch };
57+
});
58+
59+
return metadata;
60+
}

modules/effects/src/index.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1-
export { Effect } from './effects_metadata';
1+
export {
2+
Effect,
3+
EffectsMetadata,
4+
getEffectsMetadata,
5+
} from './effects_metadata';
26
export { mergeEffects } from './effects_resolver';
37
export { Actions } from './actions';
48
export { EffectsModule } from './effects_module';

0 commit comments

Comments
 (0)