Skip to content

Commit ce07658

Browse files
authored
Merge pull request #73 from ntziolis/fix/ng-directive-unregister
fix(effects-directive): unregister all effects of a provider
2 parents da32a41 + 56ddefb commit ce07658

File tree

2 files changed

+35
-10
lines changed

2 files changed

+35
-10
lines changed

libs/effects-ng/src/lib/use-directive-effects.spec.ts

+16-3
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,20 @@ import { provideEffects } from './provide-effects';
1313

1414
const spy = jest.fn();
1515
const spy2 = jest.fn();
16+
const spy3 = jest.fn();
1617
const loadTodos = createAction('[Todos] Load Todos');
1718
const loadTodos2 = createAction('[Todos] Load Todos 2');
19+
const loadTodos3 = createAction('[Todos] Load Todos 3');
1820

1921
@Injectable()
2022
class EffectsOne {
2123
loadTodos$ = createEffect((actions) =>
2224
actions.pipe(ofType(loadTodos), tap(spy))
2325
);
26+
27+
loadTodos3$ = createEffect((actions) =>
28+
actions.pipe(ofType(loadTodos3), tap(spy3))
29+
);
2430
}
2531

2632
@Injectable()
@@ -54,6 +60,7 @@ describe('provideDirectiveEffects & EffectsDirective', () => {
5460
beforeEach(() => {
5561
spy.mockClear();
5662
spy2.mockClear();
63+
spy3.mockClear();
5764
});
5865

5966
it('should provide effects', () => {
@@ -95,6 +102,8 @@ describe('provideDirectiveEffects & EffectsDirective', () => {
95102
TestBed.createComponent(componentType);
96103

97104
expect(spy).toHaveBeenCalled();
105+
expect(spy2).not.toHaveBeenCalled();
106+
expect(spy3).not.toHaveBeenCalled();
98107
});
99108

100109
it('should subscribe on the same effects only once', () => {
@@ -116,6 +125,7 @@ describe('provideDirectiveEffects & EffectsDirective', () => {
116125

117126
expect(spy).toHaveBeenCalledTimes(2);
118127
expect(spy2).toHaveBeenCalledTimes(1);
128+
expect(spy3).not.toHaveBeenCalled();
119129
});
120130

121131
it('should unsubscribe only from effects that was registered via provideDirectiveEffects when component is destroyed', () => {
@@ -148,25 +158,28 @@ describe('provideDirectiveEffects & EffectsDirective', () => {
148158
const fixture3 = TestBed.createComponent(TestComponent);
149159
const actions = TestBed.inject(Actions);
150160

151-
actions.dispatch(loadTodos2());
161+
actions.dispatch(loadTodos2(), loadTodos3());
152162

153163
expect(spy).toHaveBeenCalledTimes(3);
154164
expect(spy2).toHaveBeenCalledTimes(1);
165+
expect(spy2).toHaveBeenCalledTimes(1);
155166

156167
fixture.destroy();
157168
fixture2.destroy();
158169

159-
actions.dispatch(loadTodos(), loadTodos2());
170+
actions.dispatch(loadTodos(), loadTodos2(), loadTodos3());
160171

161172
expect(spy).toHaveBeenCalledTimes(4);
162173
expect(spy2).toHaveBeenCalledTimes(2);
174+
expect(spy3).toHaveBeenCalledTimes(2);
163175

164176
fixture3.destroy();
165177

166-
actions.dispatch(loadTodos(), loadTodos2());
178+
actions.dispatch(loadTodos(), loadTodos2(), loadTodos3());
167179

168180
expect(spy).toHaveBeenCalledTimes(4);
169181
expect(spy2).toHaveBeenCalledTimes(3);
182+
expect(spy3).toHaveBeenCalledTimes(2);
170183
});
171184

172185
it('should properly determine source instances and manage their effects', () => {

libs/effects-ng/src/lib/use-directive-effects.ts

+19-7
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ export class EffectsDirective implements OnDestroy {
4242
private readonly manager = inject(EFFECTS_MANAGER, { optional: true });
4343
private readonly sourceInstancesWithProvidersEffectsTokens = new Map<
4444
any,
45-
ProvidedEffectToken
45+
Array<ProvidedEffectToken>
4646
>();
4747

4848
constructor() {
@@ -67,9 +67,19 @@ export class EffectsDirective implements OnDestroy {
6767
const sourceInstance = Object.getPrototypeOf(instance);
6868
const token = generateProvidedEffectToken(provider, key);
6969

70+
const tokens = this.sourceInstancesWithProvidersEffectsTokens.has(
71+
sourceInstance
72+
)
73+
? (this.sourceInstancesWithProvidersEffectsTokens.get(
74+
sourceInstance
75+
) as Array<ProvidedEffectToken>)
76+
: [];
77+
78+
tokens.push(token);
79+
7080
this.sourceInstancesWithProvidersEffectsTokens.set(
7181
Object.getPrototypeOf(instance),
72-
token
82+
tokens
7383
);
7484

7585
if (isEffectProvided(sourceInstance, token)) {
@@ -94,13 +104,15 @@ export class EffectsDirective implements OnDestroy {
94104
private unregisterEffect(): void {
95105
const effects = [
96106
...this.sourceInstancesWithProvidersEffectsTokens.entries(),
97-
].reduce<Effect[]>((effects, [sourceInstance, token]) => {
98-
const effect = getProvidedEffect(sourceInstance, token);
107+
].reduce<Effect[]>((effects, [sourceInstance, tokens]) => {
108+
for (const token of tokens) {
109+
const effect = getProvidedEffect(sourceInstance, token);
99110

100-
decreaseProvidedEffectSources(sourceInstance, token);
111+
decreaseProvidedEffectSources(sourceInstance, token);
101112

102-
if (effect && !isEffectProvided(sourceInstance, token)) {
103-
effects.push(effect);
113+
if (effect && !isEffectProvided(sourceInstance, token)) {
114+
effects.push(effect);
115+
}
104116
}
105117

106118
return effects;

0 commit comments

Comments
 (0)