Skip to content

Commit

Permalink
refactor(component): clean up cdAware creator and simplify strategy (#…
Browse files Browse the repository at this point in the history
…2566)

Closes #2443
  • Loading branch information
BioPhoton authored Jun 6, 2020
1 parent 75ccf92 commit 0b41c71
Show file tree
Hide file tree
Showing 29 changed files with 562 additions and 540 deletions.
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
import { OnDestroy } from '@angular/core';
import { CdAware, createCdAware } from '../../../src/core';
import { CdAware, createCdAware, createRender } from '../../../src/core';
import {
concat,
EMPTY,
NEVER,
NextObserver,
Observable,
Observer,
of,
PartialObserver,
Unsubscribable,
} from 'rxjs';
import { tap } from 'rxjs/operators';
import {
manualInstanceNgZone,
MockChangeDetectorRef,
} from '../../fixtures/fixtures';

class CdAwareImplementation<U> implements OnDestroy {
public renderedValue: any = undefined;
Expand All @@ -20,24 +22,21 @@ class CdAwareImplementation<U> implements OnDestroy {
public cdAware: CdAware<U | undefined | null>;
resetContextObserver: NextObserver<any> = {
next: _ => (this.renderedValue = undefined),
error: e => (this.error = e),
complete: () => (this.completed = true),
};
updateViewContextObserver: PartialObserver<U | undefined | null> = {
updateViewContextObserver: Observer<U | undefined | null> = {
next: (n: U | undefined | null) => (this.renderedValue = n),
error: e => (this.error = e),
complete: () => (this.completed = true),
};
configurableBehaviour = <T>(
o$: Observable<Observable<T>>
): Observable<Observable<T>> => o$.pipe(tap());

constructor() {
this.cdAware = createCdAware<U>({
work: () => {},
resetContextObserver: this.resetContextObserver,
render: createRender({
ngZone: manualInstanceNgZone,
cdRef: new MockChangeDetectorRef(),
}),
updateViewContextObserver: this.updateViewContextObserver,
configurableBehaviour: this.configurableBehaviour,
resetContextObserver: this.resetContextObserver,
});
this.subscription = this.cdAware.subscribe();
}
Expand Down Expand Up @@ -69,59 +68,61 @@ describe('CdAware', () => {
expect(cdAwareImplementation.renderedValue).toBe(undefined);
});

it('should render undefined as value when initially undefined was passed (as no value ever was emitted)', () => {
cdAwareImplementation.cdAware.next(undefined);
it('should render_creator undefined as value when initially undefined was passed (as no value ever was emitted)', () => {
cdAwareImplementation.cdAware.nextPotentialObservable(undefined);
expect(cdAwareImplementation.renderedValue).toBe(undefined);
});

it('should render null as value when initially null was passed (as no value ever was emitted)', () => {
cdAwareImplementation.cdAware.next(null);
it('should render_creator null as value when initially null was passed (as no value ever was emitted)', () => {
cdAwareImplementation.cdAware.nextPotentialObservable(null);
expect(cdAwareImplementation.renderedValue).toBe(null);
});

it('should render undefined as value when initially of(undefined) was passed (as undefined was emitted)', () => {
cdAwareImplementation.cdAware.next(of(undefined));
it('should render_creator undefined as value when initially of(undefined) was passed (as undefined was emitted)', () => {
cdAwareImplementation.cdAware.nextPotentialObservable(of(undefined));
expect(cdAwareImplementation.renderedValue).toBe(undefined);
});

it('should render null as value when initially of(null) was passed (as null was emitted)', () => {
cdAwareImplementation.cdAware.next(of(null));
it('should render_creator null as value when initially of(null) was passed (as null was emitted)', () => {
cdAwareImplementation.cdAware.nextPotentialObservable(of(null));
expect(cdAwareImplementation.renderedValue).toBe(null);
});

it('should render undefined as value when initially EMPTY was passed (as no value ever was emitted)', () => {
cdAwareImplementation.cdAware.next(EMPTY);
it('should render_creator undefined as value when initially EMPTY was passed (as no value ever was emitted)', () => {
cdAwareImplementation.cdAware.nextPotentialObservable(EMPTY);
expect(cdAwareImplementation.renderedValue).toBe(undefined);
});

it('should render undefined as value when initially NEVER was passed (as no value ever was emitted)', () => {
cdAwareImplementation.cdAware.next(NEVER);
it('should render_creator undefined as value when initially NEVER was passed (as no value ever was emitted)', () => {
cdAwareImplementation.cdAware.nextPotentialObservable(NEVER);
expect(cdAwareImplementation.renderedValue).toBe(undefined);
});
// Also: 'should keep last emitted value in the view until a new observable NEVER was passed (as no value ever was emitted from new observable)'
it('should render emitted value from passed observable without changing it', () => {
cdAwareImplementation.cdAware.next(of(42));
it('should render_creator emitted value from passed observable without changing it', () => {
cdAwareImplementation.cdAware.nextPotentialObservable(of(42));
expect(cdAwareImplementation.renderedValue).toBe(42);
});

it('should render undefined as value when a new observable NEVER was passed (as no value ever was emitted from new observable)', () => {
cdAwareImplementation.cdAware.next(of(42));
it('should render_creator undefined as value when a new observable NEVER was passed (as no value ever was emitted from new observable)', () => {
cdAwareImplementation.cdAware.nextPotentialObservable(of(42));
expect(cdAwareImplementation.renderedValue).toBe(42);
cdAwareImplementation.cdAware.next(NEVER);
cdAwareImplementation.cdAware.nextPotentialObservable(NEVER);
expect(cdAwareImplementation.renderedValue).toBe(undefined);
});
});

describe('observable context', () => {
it('next handling running observable', () => {
cdAwareImplementation.cdAware.next(concat(of(42), NEVER));
cdAwareImplementation.cdAware.nextPotentialObservable(
concat(of(42), NEVER)
);
expect(cdAwareImplementation.renderedValue).toBe(42);
expect(cdAwareImplementation.error).toBe(undefined);
expect(cdAwareImplementation.completed).toBe(false);
});

it('next handling completed observable', () => {
cdAwareImplementation.cdAware.next(of(42));
cdAwareImplementation.cdAware.nextPotentialObservable(of(42));
expect(cdAwareImplementation.renderedValue).toBe(42);
expect(cdAwareImplementation.error).toBe(undefined);
expect(cdAwareImplementation.completed).toBe(true);
Expand All @@ -139,7 +140,7 @@ describe('CdAware', () => {
});

it('completion handling', () => {
cdAwareImplementation.cdAware.next(EMPTY);
cdAwareImplementation.cdAware.nextPotentialObservable(EMPTY);
expect(cdAwareImplementation.renderedValue).toBe(undefined);
expect(cdAwareImplementation.error).toBe(undefined);
expect(cdAwareImplementation.completed).toBe(true);
Expand Down

This file was deleted.

32 changes: 32 additions & 0 deletions modules/component/spec/core/cd-aware/render_creator.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { createRender } from '../../../src/core/cd-aware';
import {
manualInstanceNgZone,
MockChangeDetectorRef,
manualInstanceNoopNgZone,
} from '../../fixtures/fixtures';

describe('renderCreator', () => {
it('should create', () => {
const render = createRender({
ngZone: manualInstanceNgZone,
cdRef: new MockChangeDetectorRef(),
});
expect(render).toBeDefined();
});

it('should call markForCheck', () => {
const cdRef = new MockChangeDetectorRef();
const render = createRender({ ngZone: manualInstanceNgZone, cdRef });
render();
expect(cdRef.detectChanges).toHaveBeenCalledTimes(0);
expect(cdRef.markForCheck).toHaveBeenCalledTimes(1);
});

it('should call detectChanges', () => {
const cdRef = new MockChangeDetectorRef();
const render = createRender({ ngZone: manualInstanceNoopNgZone, cdRef });
render();
expect(cdRef.detectChanges).toHaveBeenCalledTimes(1);
expect(cdRef.markForCheck).toHaveBeenCalledTimes(0);
});
});
48 changes: 0 additions & 48 deletions modules/component/spec/core/projections/toObservableValue.spec.ts

This file was deleted.

14 changes: 0 additions & 14 deletions modules/component/spec/core/utils/has-zone.spec.ts

This file was deleted.

15 changes: 15 additions & 0 deletions modules/component/spec/core/utils/zone-check.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { isNgZone } from '../../../src/core/utils';
import {
manualInstanceNgZone,
manualInstanceNoopNgZone,
} from '../../fixtures/fixtures';

describe('envZonePatched', () => {
it('should return true if `zone.js` did patch the global API', () => {
expect(isNgZone(manualInstanceNgZone)).toBe(true);
});

it('should return false if `zone.js` did not patch the global API', () => {
expect(isNgZone(manualInstanceNoopNgZone)).toBe(false);
});
});
49 changes: 49 additions & 0 deletions modules/component/spec/fixtures/fixtures.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import createSpy = jasmine.createSpy;
import { ChangeDetectorRef } from '@angular/core';
import { MockNgZone } from './mock-ng-zone';
import { MockNoopNgZone } from './mock-noop-ng-zone';

/**
* this is not exposed as NgZone should never be exposed to get miss matched with the real one
*/
class NgZone extends MockNgZone {}

/**
* this is not exposed as NgZone should never be exposed to get miss matched with the real one
*/
class NoopNgZone extends MockNoopNgZone {}

export const manualInstanceNgZone = new NgZone({
enableLongStackTrace: false,
shouldCoalesceEventChangeDetection: false,
});
export const manualInstanceNoopNgZone = new NoopNgZone({
enableLongStackTrace: false,
shouldCoalesceEventChangeDetection: false,
});

export class MockChangeDetectorRef {
markForCheck = createSpy('markForCheck');
detectChanges = createSpy('detectChanges');
checkNoChanges = createSpy('checkNoChanges');
detach = createSpy('detach');
reattach = createSpy('reattach');
}

export const mockPromise = {
then: () => {},
};

export function getMockOptimizedStrategyConfig() {
return {
component: {},
cdRef: (new MockChangeDetectorRef() as any) as ChangeDetectorRef,
};
}

export function getMockNoopStrategyConfig() {
return {
component: {},
cdRef: (new MockChangeDetectorRef() as any) as ChangeDetectorRef,
};
}
8 changes: 8 additions & 0 deletions modules/component/spec/fixtures/mock-event-emitter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { EventEmitter } from '@angular/core';

export class MockEventEmitter<T> extends EventEmitter<T> {
next(value: any) {}
error(error: any) {}
complete() {}
emit() {}
}
Loading

0 comments on commit 0b41c71

Please sign in to comment.