Skip to content

Commit

Permalink
- Added ability to pass optional params to self-proxy helper decorators
Browse files Browse the repository at this point in the history
- Added unit tests for self-proxy helper decorators
  • Loading branch information
lVlyke committed Sep 23, 2018
1 parent 1109737 commit 901df99
Show file tree
Hide file tree
Showing 4 changed files with 94 additions and 15 deletions.
2 changes: 1 addition & 1 deletion coverage/coverage.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@lithiumjs/angular",
"version": "2.1.0-beta.1",
"version": "2.1.0-rc.0",
"description": "A decorator-based library for Angular that enables seamless reactive data binding using RxJS.",
"main": "index.js",
"author": "Mychal Thompson <mychal.r.thompson@gmail.com>",
Expand Down
72 changes: 68 additions & 4 deletions spec/state-emitter.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -367,7 +367,7 @@ describe("Given a StateEmitter decorator", () => {
.fragment<StateEmitter.DecoratorParams>({ propertyName: Random.string() })
.fragmentList({ proxyMode: [undefined, EmitterMetadata.ProxyMode.Alias, EmitterMetadata.ProxyMode.From, EmitterMetadata.ProxyMode.Merge, EmitterMetadata.ProxyMode.None] })
.fragment({ proxyPath: undefined }, options => !options.proxyMode || options.proxyMode === EmitterMetadata.ProxyMode.None)
.fragmentList({ proxyPath: [_propertyKey, STATIC_PROXY_PATH, DYNAMIC_PROXY_PATH] }, options => options.proxyMode && options.proxyMode !== EmitterMetadata.ProxyMode.None)
.fragmentList({ proxyPath: ["", _propertyKey, STATIC_PROXY_PATH, DYNAMIC_PROXY_PATH] }, options => options.proxyMode && options.proxyMode !== EmitterMetadata.ProxyMode.None)
);

const InitialPropertyValueTemplateKeys: (keyof InitialPropertyValueTemplateInput)[] = ["propertyKey", "initialPropertyValue", "options"];
Expand All @@ -379,6 +379,7 @@ describe("Given a StateEmitter decorator", () => {
) => {
const createStateEmitter = () => StateEmitter(options);
const subjectInfo = Object.assign({ propertyKey, observable: undefined }, options);
const isSelfProxy = EmitterMetadata.SubjectInfo.IsSelfProxy(subjectInfo) || options.proxyPath === "";

function getMetadata(targetClass: any): EmitterMetadata.SubjectInfo {
return EmitterMetadata.GetOwnMetadataMap(targetClass).get(options.propertyName);
Expand Down Expand Up @@ -412,6 +413,17 @@ describe("Given a StateEmitter decorator", () => {
createStateEmitter()(params.targetPrototype, propertyKey);
});

if (options.proxyPath === "") {
describe("when an empty proxy path is specified", () => {

spec.it("should set the proxy path to the property key (self-proxy)", (params) => {
const metadata: EmitterMetadata.SubjectInfo = getMetadata(params.targetClass);

expect(metadata.proxyPath).toEqual(propertyKey);
});
});
}

describe("when a new class instance is created", () => {

spec.beforeEach(((params) => {
Expand Down Expand Up @@ -442,7 +454,7 @@ describe("Given a StateEmitter decorator", () => {
expect(params.targetInstance[propertyKey]).toBe(initialPropertyValue);
});
});
} else if (EmitterMetadata.SubjectInfo.IsSelfProxy(subjectInfo)) {
} else if (isSelfProxy) {
describe("when a proxy mode is set that is self-proxying", () => {

spec.it("it should NOT throw an error", (params) => {
Expand Down Expand Up @@ -511,7 +523,7 @@ describe("Given a StateEmitter decorator", () => {
} else {
describe("when the initial property value is NOT Observable-derived", () => {

if (EmitterMetadata.SubjectInfo.IsSelfProxy(subjectInfo)) {
if (isSelfProxy) {
describe("when the StateEmitter is self-proxying", () => {

spec.it("it should throw an error", (params) => {
Expand Down Expand Up @@ -550,7 +562,10 @@ describe("Given a StateEmitter decorator", () => {
.fragment({ proxyPath: Random.string() })
.fragment({ options: undefined }, input => !!input.proxyPath)
.fragmentBuilder("options", InputBuilder
.fragment<StateEmitter.ProxyDecoratorParams>({ path: Random.string() })
.fragmentList({ propertyName: [undefined, Random.string()] })
.fragmentList({ mergeUpdates: [undefined, true, false] })
.fragmentList({ readOnly: [undefined, true, false] })
)
.fragmentList({ propertyDecorators: [undefined, [jasmine.createSpy("propertyDecorator")]] });

Expand Down Expand Up @@ -578,9 +593,58 @@ describe("Given a StateEmitter decorator", () => {
propertyName: params.propertyName,
proxyMode: proxyMode,
proxyPath: params.path,
proxyMergeUpdates: params.mergeUpdates
proxyMergeUpdates: params.mergeUpdates,
readOnly: params.readOnly
}, ...propertyDecorators);
});
});
})();



type SelfHelperTemplateInput = {
helperName: "AliasSelf" | "FromSelf" | "MergeSelf",
options?: StateEmitter.SelfProxyDecoratorParams;
propertyDecorators?: PropertyDecorator[];
};

const SelfHelperTemplateInput = InputBuilder
.fragmentList<SelfHelperTemplateInput>({ helperName: ["AliasSelf", "FromSelf", "MergeSelf"] })
.fragment({ options: undefined })
.fragmentBuilder("options", InputBuilder
.fragmentList<StateEmitter.SelfProxyDecoratorParams>({ propertyName: [undefined, Random.string()] })
.fragmentList({ readOnly: [undefined, true, false] })
)
.fragmentList({ propertyDecorators: [undefined, [jasmine.createSpy("propertyDecorator")]] });

const SelfHelperTemplateKeys: (keyof SelfHelperTemplateInput)[] = ["helperName", "options", "propertyDecorators"];

Template(SelfHelperTemplateKeys, SelfHelperTemplateInput, (
helperName: "AliasSelf" | "FromSelf" | "MergeSelf",
options?: StateEmitter.SelfProxyDecoratorParams,
propertyDecorators?: PropertyDecorator[]
) => {
const $params = Object.assign(options || {}, { path: "" });
let delegateHelperFnName: "Alias" | "From" | "Merge";
propertyDecorators = propertyDecorators || [];

switch (helperName) {
case "AliasSelf": delegateHelperFnName = "Alias"; break;
case "FromSelf": delegateHelperFnName = "From"; break;
case "MergeSelf": delegateHelperFnName = "Merge"; break;
}

describe(`when the ${helperName} self-proxy helper decorator is called`, () => {

beforeEach(() => {
spyOn(StateEmitter, delegateHelperFnName).and.callThrough();

StateEmitter[helperName](options, ...propertyDecorators);
});

it(`should call StateEmitter.${delegateHelperFnName} with the expected parameters`, () => {
expect(StateEmitter[delegateHelperFnName]).toHaveBeenCalledWith($params, ...propertyDecorators);
});
});
})();
});
33 changes: 24 additions & 9 deletions src/state-emitter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,12 @@ export namespace StateEmitter {
path: string;
propertyName?: EmitterType;
mergeUpdates?: boolean;
readOnly?: boolean;
}

export interface SelfProxyDecoratorParams {
propertyName?: EmitterType;
readOnly?: boolean;
}

/** @PropertyDecoratorFactory */
Expand Down Expand Up @@ -88,7 +94,8 @@ export namespace StateEmitter {
propertyName: $params.propertyName,
proxyMode: EmitterMetadata.ProxyMode.Alias,
proxyPath: $params.path,
proxyMergeUpdates: $params.mergeUpdates
proxyMergeUpdates: $params.mergeUpdates,
readOnly: $params.readOnly
}, ...propertyDecorators);
}

Expand All @@ -100,7 +107,8 @@ export namespace StateEmitter {
propertyName: $params.propertyName,
proxyMode: EmitterMetadata.ProxyMode.From,
proxyPath: $params.path,
proxyMergeUpdates: $params.mergeUpdates
proxyMergeUpdates: $params.mergeUpdates,
readOnly: $params.readOnly
}, ...propertyDecorators);
}

Expand All @@ -112,23 +120,30 @@ export namespace StateEmitter {
propertyName: $params.propertyName,
proxyMode: EmitterMetadata.ProxyMode.Merge,
proxyPath: $params.path,
proxyMergeUpdates: $params.mergeUpdates
proxyMergeUpdates: $params.mergeUpdates,
readOnly: $params.readOnly
}, ...propertyDecorators);
}

/** @PropertyDecoratorFactory */
export function AliasSelf(...propertyDecorators: PropertyDecorator[]): PropertyDecorator {
return Alias("", ...propertyDecorators);
export function AliasSelf(params?: SelfProxyDecoratorParams, ...propertyDecorators: PropertyDecorator[]): PropertyDecorator {
const $params = Object.assign(params || {}, { path: "" });

return StateEmitter.Alias($params, ...propertyDecorators);
}

/** @PropertyDecoratorFactory */
export function FromSelf(...propertyDecorators: PropertyDecorator[]): PropertyDecorator {
return From("", ...propertyDecorators);
export function FromSelf(params?: SelfProxyDecoratorParams, ...propertyDecorators: PropertyDecorator[]): PropertyDecorator {
const $params = Object.assign(params || {}, { path: "" });

return StateEmitter.From($params, ...propertyDecorators);
}

/** @PropertyDecoratorFactory */
export function MergeSelf(...propertyDecorators: PropertyDecorator[]): PropertyDecorator {
return Merge("", ...propertyDecorators);
export function MergeSelf(params?: SelfProxyDecoratorParams, ...propertyDecorators: PropertyDecorator[]): PropertyDecorator {
const $params = Object.assign(params || {}, { path: "" });

return StateEmitter.Merge($params, ...propertyDecorators);
}

export namespace Facade {
Expand Down

0 comments on commit 901df99

Please sign in to comment.