forked from angular-redux/platform
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(dispatch): Create dispatch decorator (#385)
* feat(dispatch): Create dispatch decorator Initial implementation of a `@dispatch` decorator. ```ts class TestClass { instanceProperty = 'test' @dispatch() myMethod(value) { return { type: 'TEST', payload: { value, instanceProperty: this.instanceProperty } } } } ``` Need to do some integration testing, and ensure that the context of `this` is preserved as expected if action creators are using it. * chore(cleanup) Cleanup dispatch decorator * DRY up the unit tests a bit * Modify tsconfig setup so .spec files don't show errors in editor
- Loading branch information
Showing
8 changed files
with
219 additions
and
9 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,126 @@ | ||
import 'reflect-metadata'; | ||
import { NgZone } from '@angular/core'; | ||
import { NgRedux } from '../components/ng-redux'; | ||
import { dispatch } from './dispatch'; | ||
|
||
|
||
class MockNgZone { | ||
run = fn => fn() | ||
} | ||
|
||
describe('@dispatch', () => { | ||
let ngRedux; | ||
const mockNgZone = new MockNgZone() as NgZone; | ||
let defaultState; | ||
let rootReducer; | ||
|
||
beforeEach(() => { | ||
defaultState = { | ||
value: 'init-value', | ||
instanceProperty: 'init-instanceProperty' | ||
}; | ||
rootReducer = (state = defaultState, action) => { | ||
switch (action.type) { | ||
case 'TEST': | ||
const { value, instanceProperty } = action.payload; | ||
return Object.assign({}, state, { value, instanceProperty }); | ||
default: | ||
return state; | ||
} | ||
|
||
}; | ||
ngRedux = new NgRedux(mockNgZone); | ||
ngRedux.configureStore(rootReducer, defaultState); | ||
}); | ||
|
||
it('should call dispatch with the result of the function', () => { | ||
|
||
spyOn(NgRedux.instance, 'dispatch'); | ||
const instance = new TestClass(); | ||
const result = instance.classMethod('class method'); | ||
const expectedArgs = { | ||
type: 'TEST', | ||
payload: { | ||
value: 'class method', | ||
instanceProperty: 'test' | ||
} | ||
} | ||
expect(result.type).toBe('TEST'); | ||
expect(result.payload.value).toBe('class method'); | ||
expect(result.payload.instanceProperty).toBe('test'); | ||
expect(NgRedux.instance.dispatch).toHaveBeenCalledWith(expectedArgs) | ||
}); | ||
|
||
it('should work with property initalizers', () => { | ||
|
||
spyOn(NgRedux.instance, 'dispatch'); | ||
const instance = new TestClass(); | ||
const result = instance.boundProperty('bound property'); | ||
const expectedArgs = { | ||
type: 'TEST', | ||
payload: { | ||
value: 'bound property', | ||
instanceProperty: 'test' | ||
} | ||
} | ||
expect(result.type).toBe('TEST'); | ||
expect(result.payload.value).toBe('bound property'); | ||
expect(result.payload.instanceProperty).toBe('test'); | ||
expect(NgRedux.instance.dispatch).toHaveBeenCalledWith(expectedArgs) | ||
}) | ||
|
||
it('work with properties bound to function defined outside of the class', () => { | ||
spyOn(NgRedux.instance, 'dispatch'); | ||
const instance = new TestClass(); | ||
const result = instance.externalFunction('external function'); | ||
const expectedArgs = { | ||
type: 'TEST', | ||
payload: { | ||
value: 'external function', | ||
instanceProperty: 'test' | ||
} | ||
} | ||
expect(result.type).toBe('TEST'); | ||
expect(result.payload.value).toBe('external function'); | ||
expect(result.payload.instanceProperty).toBe('test'); | ||
expect(NgRedux.instance.dispatch).toHaveBeenCalledWith(expectedArgs); | ||
}) | ||
|
||
|
||
|
||
function externalFunction(value) { | ||
return { | ||
type: 'TEST', | ||
payload: { | ||
value, | ||
instanceProperty: this.instanceProperty | ||
} | ||
} | ||
} | ||
class TestClass { | ||
instanceProperty = 'test' | ||
@dispatch() | ||
externalFunction = externalFunction | ||
@dispatch() | ||
classMethod(value) { | ||
return { | ||
type: 'TEST', | ||
payload: { | ||
value, | ||
instanceProperty: this.instanceProperty | ||
} | ||
} | ||
} | ||
|
||
@dispatch() | ||
boundProperty = (value) => { | ||
return { | ||
type: 'TEST', | ||
payload: { | ||
value, | ||
instanceProperty: this.instanceProperty | ||
} | ||
} | ||
} | ||
} | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
import { | ||
NgRedux, | ||
} from '../components/ng-redux'; | ||
|
||
export function dispatch(): void | any { | ||
return function dispatchDecorator(target: object, key: string | symbol | number, descriptor?: PropertyDescriptor) { | ||
let originalMethod: Function; | ||
|
||
descriptor = descriptor || Object.getOwnPropertyDescriptor(target, key); | ||
const wrapped = function (...args) { | ||
|
||
const result = originalMethod.apply(this, args); | ||
NgRedux.instance.dispatch(result); | ||
return result; | ||
} | ||
|
||
if (descriptor === undefined) { | ||
const dispatchDescriptor: PropertyDescriptor = { | ||
get: () => wrapped, | ||
set: (setMethod) => originalMethod = setMethod, | ||
} | ||
Object.defineProperty(target, key, dispatchDescriptor) | ||
return; | ||
} else { | ||
originalMethod = descriptor.value; | ||
descriptor.value = wrapped; | ||
return descriptor; | ||
} | ||
|
||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
{ | ||
"compilerOptions": { | ||
"baseUrl": ".", | ||
"target": "ES5", | ||
"module": "commonjs", | ||
"moduleResolution": "node", | ||
"sourceMap": true, | ||
"emitDecoratorMetadata": true, | ||
"experimentalDecorators": true, | ||
"removeComments": false, | ||
"outDir": "lib/src/", | ||
"noImplicitAny": false, | ||
"declaration": true, | ||
"lib": [ | ||
"es2015", | ||
"es2015.iterable", | ||
"dom" | ||
], | ||
"paths": { | ||
"@angular-redux/store": [ | ||
"./src" | ||
] | ||
} | ||
}, | ||
"compileOnSave": false, | ||
"buildOnSave": false, | ||
"include": [ | ||
"src/**/*.ts" | ||
], | ||
"exclude": [ | ||
"node_modules", | ||
"lib", | ||
"**/*.spec.ts" | ||
], | ||
"angularCompilerOptions": { | ||
"strictMetadataEmit": true, | ||
"genDir": ".compiled" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters