Browse Source

feat: add context strategies

pull/3544/head
Arman Ozak 6 years ago
parent
commit
08421d37cf
  1. 47
      npm/ng-packs/packages/core/src/lib/strategies/context.strategy.ts
  2. 1
      npm/ng-packs/packages/core/src/lib/strategies/index.ts
  3. 79
      npm/ng-packs/packages/core/src/lib/tests/context.strategy.spec.ts

47
npm/ng-packs/packages/core/src/lib/strategies/context.strategy.ts

@ -0,0 +1,47 @@
import { ComponentRef, TemplateRef, Type } from '@angular/core';
import { InferedContextOf, InferedInstanceOf } from '../models';
export abstract class ContextStrategy<T = any> {
constructor(public context: Partial<ContextType<T>>) {}
/* tslint:disable-next-line:no-unused-variable */
setContext(componentRef?: ComponentRef<InferedInstanceOf<T>>): Partial<ContextType<T>> {
return this.context;
}
}
export class NoContextStrategy<
T extends Type<any> | TemplateRef<any> = any
> extends ContextStrategy<T> {
constructor() {
super(undefined);
}
}
export class ComponentContextStrategy<T extends Type<any> = any> extends ContextStrategy<T> {
setContext(componentRef: ComponentRef<InferedInstanceOf<T>>): Partial<InferedInstanceOf<T>> {
Object.keys(this.context).forEach(key => (componentRef.instance[key] = this.context[key]));
componentRef.changeDetectorRef.detectChanges();
return this.context;
}
}
export class TemplateContextStrategy<T extends TemplateRef<any> = any> extends ContextStrategy<T> {
setContext(): Partial<InferedContextOf<T>> {
return this.context;
}
}
export const CONTEXT_STRATEGY = {
None<T extends Type<any> | TemplateRef<any> = any>() {
return new NoContextStrategy<T>();
},
Component<T extends Type<any> = any>(context: Partial<InferedInstanceOf<T>>) {
return new ComponentContextStrategy<T>(context);
},
Template<T extends TemplateRef<any> = any>(context: Partial<InferedContextOf<T>>) {
return new TemplateContextStrategy<T>(context);
},
};
type ContextType<T> = T extends Type<infer U> | TemplateRef<infer U> ? U : never;

1
npm/ng-packs/packages/core/src/lib/strategies/index.ts

@ -1,5 +1,6 @@
export * from './content-security.strategy';
export * from './content.strategy';
export * from './context.strategy';
export * from './cross-origin.strategy';
export * from './dom.strategy';
export * from './loading.strategy';

79
npm/ng-packs/packages/core/src/lib/tests/context.strategy.spec.ts

@ -0,0 +1,79 @@
import { ComponentRef } from '@angular/core';
import {
ComponentContextStrategy,
CONTEXT_STRATEGY,
NoContextStrategy,
TemplateContextStrategy,
} from '../strategies';
import { uuid } from '../utils';
describe('ComponentContextStrategy', () => {
describe('#setContext', () => {
let componentRef: ComponentRef<any>;
beforeEach(
() =>
(componentRef = {
instance: {
x: '',
y: '',
z: '',
},
changeDetectorRef: {
detectChanges: jest.fn(),
},
} as any),
);
test.each`
props | values
${['x']} | ${[uuid()]}
${['x', 'y']} | ${[uuid(), uuid()]}
${['x', 'y', 'z']} | ${[uuid(), uuid(), uuid()]}
`(
'should set $props as $values and call detectChanges once',
({ props, values }: { props: string[]; values: string[] }) => {
const context = {};
props.forEach((prop, i) => {
context[prop] = values[i];
});
const strategy = new ComponentContextStrategy(context);
strategy.setContext(componentRef);
expect(props.every(prop => componentRef.instance[prop] === context[prop])).toBe(true);
expect(componentRef.changeDetectorRef.detectChanges).toHaveBeenCalledTimes(1);
},
);
});
});
describe('NoContextStrategy', () => {
describe('#setContext', () => {
it('should return undefined', () => {
const strategy = new NoContextStrategy();
expect(strategy.setContext(null)).toBeUndefined();
});
});
});
describe('TemplateContextStrategy', () => {
describe('#setContext', () => {
it('should return context', () => {
const context = { x: uuid() };
const strategy = new TemplateContextStrategy(context);
expect(strategy.setContext()).toEqual(context);
});
});
});
describe('CONTEXT_STRATEGY', () => {
test.each`
name | Strategy
${'Component'} | ${ComponentContextStrategy}
${'None'} | ${NoContextStrategy}
${'Template'} | ${TemplateContextStrategy}
`('should successfully map $name to $Strategy.name', ({ name, Strategy }) => {
expect(CONTEXT_STRATEGY[name](undefined)).toEqual(new Strategy(undefined));
});
});
Loading…
Cancel
Save