Skip to content
This repository has been archived by the owner on Dec 10, 2022. It is now read-only.

Commit

Permalink
fix(preset): Allow to redefine decorated preset propesties
Browse files Browse the repository at this point in the history
And add unit tests for resolving decorated props
  • Loading branch information
gund committed Jan 23, 2018
1 parent ea681ab commit bc402a3
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 5 deletions.
65 changes: 63 additions & 2 deletions src/preset/preset.service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,16 @@ import {
ChangeDetectorRef,
Component,
NgModule,
OnDestroy,
Provider,
} from '@angular/core';
import { async, TestBed } from '@angular/core/testing';

import { PRESET_TYPES_TOKEN, PresetType } from './preset-token';
import { Preset } from './metadata';
import {
PRESET_TYPES_TOKEN,
PRESET_COMPS_TOKEN,
PresetType,
} from './preset-token';
import { PresetService } from './preset.service';

@Component({ selector: 'prst-mock-preset', template: '' })
Expand Down Expand Up @@ -183,4 +187,61 @@ describe('Service: Preset', () => {
});
});
});

describe('initDecoratedPresets() method', () => {
class T1 {
@Preset() preset: MockPresetComponent;
}
class T2 {
@Preset() preset: MockPresetComponent;
}
class T3 {
preset: MockPresetComponent;
}

beforeAll(
() =>
(extraProviders = [
{
provide: PRESET_COMPS_TOKEN,
useValue: [T1, T2, T3],
multi: true,
},
{
provide: PRESET_TYPES_TOKEN,
useValue: MockPresetComponent,
multi: true,
},
]),
);
afterAll(() => (extraProviders = []));

beforeEach(() => service.initDecoratedPresets());

it('should resolve decorated presets for components from `PRESET_COMPS_TOKEN`', () => {
const t1 = new T1();
const t2 = new T2();

expect(t1.preset).toBeTruthy();
expect(t1.preset.mockPreset).toBeTruthy();
expect(t2.preset).toBeTruthy();
expect(t2.preset.mockPreset).toBeTruthy();
});

it('should skip components without metadata', () => {
const t3 = new T3();

expect(t3.preset).toBeUndefined();
});

it('should allow to redefine resolved decorated value', () => {
const t1 = new T1();
const t3 = new T3();

t1.preset = null as any;
t3.preset = 'other value' as any;
expect(t1.preset).toBe(null);
expect(t3.preset).toBe('other value');
});
});
});
6 changes: 3 additions & 3 deletions src/preset/preset.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import {
PRESET_TYPES_TOKEN,
PresetType,
} from './preset-token';
import { hasTypeAsProto } from './utils';
import { EMPTY_VAL, hasTypeAsProto, isEmptyVal } from './utils';

interface TypeWithPresetMetadata<T = any> {
type: Type<T>;
Expand Down Expand Up @@ -114,8 +114,8 @@ export class PresetService implements OnDestroy {
}

private initPresetOn(type: Type<any>, metadata: PresetMetadata) {
let value: any;
const get = () => (value = this.getPreset());
let value: any = EMPTY_VAL;
const get = () => (isEmptyVal(value) ? (value = this.getPreset()) : value);
const set = (val: any) => (value = val);

if (delete type.prototype[metadata.propName]) {
Expand Down
6 changes: 6 additions & 0 deletions src/preset/utils.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
import { Type } from '@angular/core';

export const EMPTY_VAL = { __isEmpty: true };

export function isEmptyVal(val: any): val is typeof EMPTY_VAL {
return !!val && !!val.__isEmpty;
}

export function hasTypeAsProto(protoType: Type<any>, type: Type<any>): boolean {
const proto = Object.getPrototypeOf(type);

Expand Down

0 comments on commit bc402a3

Please sign in to comment.