-
-
Notifications
You must be signed in to change notification settings - Fork 32
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(checkout,order): move placed order facade and selector to checko…
…ut (#2750)
- Loading branch information
Showing
26 changed files
with
438 additions
and
1 deletion.
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,6 @@ | ||
{ | ||
"$schema": "../../../node_modules/ng-packagr/ng-entrypoint.schema.json", | ||
"lib": { | ||
"entryFile": "src/index.ts" | ||
} | ||
} |
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,3 @@ | ||
{ | ||
"name": "@daffodil/checkout/state" | ||
} |
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,15 @@ | ||
import { NgModule } from '@angular/core'; | ||
|
||
import { DaffCartStateModule } from '@daffodil/cart/state'; | ||
import { DaffOrderStateModule } from '@daffodil/order/state'; | ||
|
||
/** | ||
* The module for `@daffodil/checkout/state`. | ||
*/ | ||
@NgModule({ | ||
imports: [ | ||
DaffCartStateModule, | ||
DaffOrderStateModule, | ||
], | ||
}) | ||
export class DaffCheckoutStateModule {} |
19 changes: 19 additions & 0 deletions
19
libs/checkout/state/src/facades/placed-order/placed-order-facade.interface.ts
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,19 @@ | ||
import { Action } from '@ngrx/store'; | ||
import { Observable } from 'rxjs'; | ||
|
||
import { DaffStoreFacade } from '@daffodil/core/state'; | ||
import { DaffOrder } from '@daffodil/order'; | ||
|
||
/** | ||
* Represents the surface of placed order state. | ||
*/ | ||
export interface DaffCheckoutPlacedOrderFacadeInterface<T extends DaffOrder = DaffOrder> extends DaffStoreFacade<Action> { | ||
/** | ||
* The most recently placed order (if any). | ||
*/ | ||
placedOrder$: Observable<T>; | ||
/** | ||
* Whether there is a placed order. | ||
*/ | ||
hasPlacedOrder$: Observable<boolean>; | ||
} |
92 changes: 92 additions & 0 deletions
92
libs/checkout/state/src/facades/placed-order/placed-order.facade.spec.ts
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,92 @@ | ||
import { TestBed } from '@angular/core/testing'; | ||
import { | ||
StoreModule, | ||
combineReducers, | ||
Store, | ||
} from '@ngrx/store'; | ||
import { cold } from 'jasmine-marbles'; | ||
|
||
import { | ||
DaffCartPlaceOrderSuccess, | ||
daffCartReducers, | ||
DAFF_CART_STORE_FEATURE_KEY, | ||
} from '@daffodil/cart/state'; | ||
import { DaffCheckoutStateRootSlice } from '@daffodil/checkout/state'; | ||
import { DaffOrder } from '@daffodil/order'; | ||
import { | ||
DaffOrderLoadSuccess, | ||
daffOrderReducers, | ||
DAFF_ORDER_STORE_FEATURE_KEY, | ||
} from '@daffodil/order/state'; | ||
import { DaffOrderFactory } from '@daffodil/order/testing'; | ||
|
||
import { DaffCheckoutPlacedOrderFacade } from './placed-order.facade'; | ||
|
||
describe('@daffodil/checkout/state | DaffCheckoutPlacedOrderFacade', () => { | ||
let store: Store<DaffCheckoutStateRootSlice>; | ||
let facade: DaffCheckoutPlacedOrderFacade; | ||
let orderFactory: DaffOrderFactory; | ||
|
||
let mockOrder: DaffOrder; | ||
|
||
beforeEach(() => { | ||
TestBed.configureTestingModule({ | ||
imports: [ | ||
StoreModule.forRoot({ | ||
[DAFF_ORDER_STORE_FEATURE_KEY]: combineReducers(daffOrderReducers), | ||
[DAFF_CART_STORE_FEATURE_KEY]: combineReducers(daffCartReducers), | ||
}), | ||
], | ||
providers: [ | ||
DaffCheckoutPlacedOrderFacade, | ||
], | ||
}); | ||
|
||
store = TestBed.inject(Store); | ||
facade = TestBed.inject(DaffCheckoutPlacedOrderFacade); | ||
orderFactory = TestBed.inject(DaffOrderFactory); | ||
|
||
mockOrder = orderFactory.create(); | ||
}); | ||
|
||
it('should be created', () => { | ||
expect(facade).toBeTruthy(); | ||
}); | ||
|
||
it('should be able to dispatch an action to the store', () => { | ||
spyOn(store, 'dispatch'); | ||
const action = { type: 'SOME_TYPE' }; | ||
|
||
facade.dispatch(action); | ||
expect(store.dispatch).toHaveBeenCalledWith(action); | ||
expect(store.dispatch).toHaveBeenCalledTimes(1); | ||
}); | ||
|
||
describe('placedOrder$', () => { | ||
it('should initially be null', () => { | ||
const expected = cold('a', { a: null }); | ||
expect(facade.placedOrder$).toBeObservable(expected); | ||
}); | ||
|
||
it('should contain the order upon a successful place order and order load', () => { | ||
const expected = cold('a', { a: mockOrder }); | ||
store.dispatch(new DaffCartPlaceOrderSuccess({ orderId: mockOrder.id, cartId: 'cartId' })); | ||
store.dispatch(new DaffOrderLoadSuccess(mockOrder)); | ||
expect(facade.placedOrder$).toBeObservable(expected); | ||
}); | ||
}); | ||
|
||
describe('hasPlacedOrder$', () => { | ||
it('should initially be false', () => { | ||
const expected = cold('a', { a: false }); | ||
expect(facade.hasPlacedOrder$).toBeObservable(expected); | ||
}); | ||
|
||
it('should be true upon a successful place order and order load', () => { | ||
const expected = cold('a', { a: true }); | ||
store.dispatch(new DaffCartPlaceOrderSuccess({ orderId: mockOrder.id, cartId: 'cartId' })); | ||
store.dispatch(new DaffOrderLoadSuccess(mockOrder)); | ||
expect(facade.hasPlacedOrder$).toBeObservable(expected); | ||
}); | ||
}); | ||
}); |
38 changes: 38 additions & 0 deletions
38
libs/checkout/state/src/facades/placed-order/placed-order.facade.ts
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,38 @@ | ||
import { Injectable } from '@angular/core'; | ||
import { | ||
Action, | ||
Store, | ||
select, | ||
} from '@ngrx/store'; | ||
import { Observable } from 'rxjs'; | ||
|
||
import { DaffOrder } from '@daffodil/order'; | ||
|
||
import { DaffCheckoutPlacedOrderFacadeInterface } from './placed-order-facade.interface'; | ||
import { DaffCheckoutStateRootSlice } from '../../reducers/public_api'; | ||
import { getDaffCheckoutSelectors } from '../../selectors/public_api'; | ||
|
||
/** | ||
* @inheritdoc | ||
*/ | ||
@Injectable({ | ||
providedIn: 'root', | ||
}) | ||
export class DaffCheckoutPlacedOrderFacade<T extends DaffOrder = DaffOrder> implements DaffCheckoutPlacedOrderFacadeInterface<T> { | ||
placedOrder$: Observable<T>; | ||
hasPlacedOrder$: Observable<boolean>; | ||
|
||
constructor(private store: Store<DaffCheckoutStateRootSlice<T>>) { | ||
const { | ||
selectPlacedOrder, | ||
selectHasPlacedOrder, | ||
} = getDaffCheckoutSelectors<T>(); | ||
|
||
this.placedOrder$ = this.store.pipe(select(selectPlacedOrder)); | ||
this.hasPlacedOrder$ = this.store.pipe(select(selectHasPlacedOrder)); | ||
} | ||
|
||
dispatch(action: Action) { | ||
this.store.dispatch(action); | ||
} | ||
} |
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,2 @@ | ||
export { DaffCheckoutPlacedOrderFacadeInterface } from './placed-order/placed-order-facade.interface'; | ||
export { DaffCheckoutPlacedOrderFacade } from './placed-order/placed-order.facade'; |
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 @@ | ||
export * from './public_api'; |
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,5 @@ | ||
export * from './selectors/public_api'; | ||
export * from './facades/public_api'; | ||
export * from './reducers/public_api'; | ||
|
||
export { DaffCheckoutStateModule } from './checkout-state.module'; |
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,8 @@ | ||
import { DaffCartStateRootSlice } from '@daffodil/cart/state'; | ||
import { DaffOrder } from '@daffodil/order'; | ||
import { DaffOrderStateRootSlice } from '@daffodil/order/state'; | ||
|
||
/** | ||
* The footprint of `@daffodil/checkout/state` in root. | ||
*/ | ||
export interface DaffCheckoutStateRootSlice<T extends DaffOrder = DaffOrder> extends DaffCartStateRootSlice, DaffOrderStateRootSlice<T> {} |
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 @@ | ||
export { DaffCheckoutStateRootSlice } from './order-reducers.interface'; |
19 changes: 19 additions & 0 deletions
19
libs/checkout/state/src/selectors/checkout-all.selector.ts
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,19 @@ | ||
import { DaffOrder } from '@daffodil/order'; | ||
|
||
import { | ||
DaffCheckoutPlacedOrderSelectors, | ||
getCheckoutPlacedOrderSelectors, | ||
} from './placed-order.selector'; | ||
|
||
export type DaffCheckoutSelectors<T extends DaffOrder = DaffOrder> = DaffCheckoutPlacedOrderSelectors<T>; | ||
|
||
/** | ||
* Gets all of `@daffodil/checkout/state` selectors. | ||
*/ | ||
export const getDaffCheckoutSelectors = (() => { | ||
let cache; | ||
return <T extends DaffOrder = DaffOrder>(): DaffCheckoutSelectors<T> => | ||
cache = cache || { | ||
...getCheckoutPlacedOrderSelectors<T>(), | ||
}; | ||
})(); |
111 changes: 111 additions & 0 deletions
111
libs/checkout/state/src/selectors/placed-order.selector.spec.ts
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,111 @@ | ||
import { TestBed } from '@angular/core/testing'; | ||
import { | ||
Store, | ||
select, | ||
combineReducers, | ||
StoreModule, | ||
} from '@ngrx/store'; | ||
import { cold } from 'jasmine-marbles'; | ||
|
||
import { | ||
DAFF_CART_STORE_FEATURE_KEY, | ||
daffCartReducers, | ||
DaffCartPlaceOrderSuccess, | ||
} from '@daffodil/cart/state'; | ||
import { DaffCheckoutStateRootSlice } from '@daffodil/checkout/state'; | ||
import { | ||
DaffOrder, | ||
DaffOrderCollection, | ||
} from '@daffodil/order'; | ||
import { | ||
DaffOrderListSuccess, | ||
daffOrderReducers, | ||
DAFF_ORDER_STORE_FEATURE_KEY, | ||
} from '@daffodil/order/state'; | ||
import { | ||
DaffOrderCollectionFactory, | ||
DaffOrderFactory, | ||
} from '@daffodil/order/testing'; | ||
|
||
import { getCheckoutPlacedOrderSelectors } from './placed-order.selector'; | ||
|
||
describe('@daffodil/checkout/state | getCheckoutPlacedOrderSelectors', () => { | ||
let store: Store<DaffCheckoutStateRootSlice>; | ||
|
||
let orderFactory: DaffOrderFactory; | ||
let orderCollectionFactory: DaffOrderCollectionFactory; | ||
|
||
let mockOrder: DaffOrder; | ||
let mockOrderCollection: DaffOrderCollection; | ||
|
||
const { | ||
selectPlacedOrder, | ||
selectHasPlacedOrder, | ||
} = getCheckoutPlacedOrderSelectors(); | ||
|
||
beforeEach(() => { | ||
TestBed.configureTestingModule({ | ||
imports: [ | ||
StoreModule.forRoot({ | ||
[DAFF_CART_STORE_FEATURE_KEY]: combineReducers(daffCartReducers), | ||
[DAFF_ORDER_STORE_FEATURE_KEY]: combineReducers(daffOrderReducers), | ||
}), | ||
], | ||
}); | ||
|
||
store = TestBed.inject(Store); | ||
orderFactory = TestBed.inject(DaffOrderFactory); | ||
orderCollectionFactory = TestBed.inject(DaffOrderCollectionFactory); | ||
|
||
mockOrderCollection = orderCollectionFactory.create(); | ||
mockOrder = mockOrderCollection.data[mockOrderCollection.metadata.ids[0]]; | ||
|
||
store.dispatch(new DaffOrderListSuccess(mockOrderCollection)); | ||
}); | ||
|
||
describe('selectPlacedOrder', () => { | ||
it('should initially be null', () => { | ||
const selector = store.pipe(select(selectPlacedOrder)); | ||
const expected = cold('a', { a: null }); | ||
|
||
expect(selector).toBeObservable(expected); | ||
}); | ||
|
||
describe('when an order has been placed and loaded', () => { | ||
beforeEach(() => { | ||
store.dispatch(new DaffCartPlaceOrderSuccess({ orderId: mockOrder.id, cartId: 'cartId' })); | ||
store.dispatch(new DaffOrderListSuccess(mockOrderCollection)); | ||
}); | ||
|
||
it('should select the most recently placed order', () => { | ||
const selector = store.pipe(select(selectPlacedOrder)); | ||
const expected = cold('a', { a: mockOrder }); | ||
|
||
expect(selector).toBeObservable(expected); | ||
}); | ||
}); | ||
}); | ||
|
||
describe('selectHasPlacedOrder', () => { | ||
it('should initially be false', () => { | ||
const selector = store.pipe(select(selectHasPlacedOrder)); | ||
const expected = cold('a', { a: false }); | ||
|
||
expect(selector).toBeObservable(expected); | ||
}); | ||
|
||
describe('when an order has been placed and loaded', () => { | ||
beforeEach(() => { | ||
store.dispatch(new DaffCartPlaceOrderSuccess({ orderId: mockOrder.id, cartId: 'cartId' })); | ||
store.dispatch(new DaffOrderListSuccess(mockOrderCollection)); | ||
}); | ||
|
||
it('should select if the most recently placed order exists', () => { | ||
const selector = store.pipe(select(selectHasPlacedOrder)); | ||
const expected = cold('a', { a: true }); | ||
|
||
expect(selector).toBeObservable(expected); | ||
}); | ||
}); | ||
}); | ||
}); |
Oops, something went wrong.