Skip to content

Commit

Permalink
ngrx#853 support for pause recording
Browse files Browse the repository at this point in the history
  • Loading branch information
dummdidumm committed Apr 3, 2018
1 parent de6f2e4 commit bb2b8ef
Show file tree
Hide file tree
Showing 5 changed files with 202 additions and 46 deletions.
76 changes: 73 additions & 3 deletions modules/store-devtools/spec/store.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
StateObservable,
Store,
StoreModule,
UPDATE,
} from '@ngrx/store';

import {
Expand All @@ -15,6 +16,7 @@ import {
StoreDevtoolsOptions,
} from '../';
import { IS_EXTENSION_OR_MONITOR_PRESENT } from '../src/instrument';
import { PerformAction } from '../src/actions';

const counter = jasmine
.createSpy('counter')
Expand Down Expand Up @@ -615,15 +617,18 @@ describe('Store Devtools', () => {
fixture.store.dispatch({ type: 'INCREMENT' });
fixture.store.dispatch({ type: 'INCREMENT' });
fixture.devtools.lockChanges(true);
expect(fixture.getLiftedState().isLocked).toBe(true);
expect(fixture.getLiftedState().nextActionId).toBe(3);
expect(fixture.getState()).toBe(2);
});

afterEach(() => {
fixture.cleanup();
});

it('should update state correctly', () => {
expect(fixture.getLiftedState().isLocked).toBe(true);
expect(fixture.getLiftedState().nextActionId).toBe(3);
expect(fixture.getState()).toBe(2);
});

it('should not accept changes during lock', () => {
fixture.store.dispatch({ type: 'INCREMENT' });
expect(fixture.getLiftedState().nextActionId).toBe(3);
Expand Down Expand Up @@ -655,4 +660,69 @@ describe('Store Devtools', () => {
expect(fixture.getState()).toBe(3);
});
});

describe('pause recording', () => {
let fixture: Fixture<number>;
beforeEach(() => {
fixture = createStore(counter);
fixture.store.dispatch({ type: 'INCREMENT' });
fixture.store.dispatch({ type: 'INCREMENT' });
fixture.devtools.pauseRecording(true);
});

afterEach(() => {
fixture.cleanup();
});

it('should update pause correctly', () => {
expect(fixture.getLiftedState().isPaused).toBe(true);
fixture.devtools.pauseRecording(false);
expect(fixture.getLiftedState().isPaused).toBe(false);
});

it('should create a copy of the last state before pausing', () => {
const computedStates = fixture.getLiftedState().computedStates;
expect(computedStates.length).toBe(4);
expect(computedStates[3]).toEqual(computedStates[2]);
expect(fixture.getLiftedState().currentStateIndex).toBe(3);
expect(fixture.getState()).toBe(2);
});

it('should add pause action', () => {
const liftedState = fixture.getLiftedState();
expect(liftedState.nextActionId).toBe(4);
expect(liftedState.actionsById[3].action.type).toEqual('@ngrx/devtools/pause');
});

it('should overwrite last state during pause but keep action', () => {
fixture.store.dispatch({ type: 'DECREMENT' });
const liftedState = fixture.getLiftedState();
expect(liftedState.currentStateIndex).toBe(3);
expect(liftedState.computedStates.length).toBe(4);
expect(fixture.getState()).toEqual(1);
expect(liftedState.nextActionId).toBe(4);
expect(liftedState.actionsById[3].action.type).toEqual('@ngrx/devtools/pause');
});

it('recomputation of states should preserve last state', () => {
fixture.devtools.jumpToState(1);
expect(fixture.getState()).toBe(1);
fixture.devtools.jumpToState(3);
expect(fixture.getState()).toBe(2);
fixture.devtools.toggleAction(1);
expect(fixture.getState()).toBe(2);
fixture.devtools.jumpToState(2);
expect(fixture.getState()).toBe(1);
});

it('reducer update should not be recorded but should still be applied', () => {
const oldComputedStates = fixture.getLiftedState().computedStates;
fixture.store.dispatch({ type: UPDATE });
expect(fixture.getState()).toBe(2);
const liftedState = fixture.getLiftedState();
expect(liftedState.nextActionId).toBe(4);
expect(liftedState.actionsById[3].action.type).toEqual('@ngrx/devtools/pause');
expect(oldComputedStates).not.toBe(liftedState.computedStates);
});
});
});
10 changes: 9 additions & 1 deletion modules/store-devtools/src/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export const JUMP_TO_STATE = 'JUMP_TO_STATE';
export const JUMP_TO_ACTION = 'JUMP_TO_ACTION';
export const IMPORT_STATE = 'IMPORT_STATE';
export const LOCK_CHANGES = 'LOCK_CHANGES';
export const PAUSE_RECORDING = 'PAUSE_RECORDING';

export class PerformAction implements Action {
readonly type = PERFORM_ACTION;
Expand Down Expand Up @@ -87,6 +88,12 @@ export class LockChanges implements Action {
constructor(public status: boolean) {}
}

export class PauseRecording implements Action {
readonly type = PAUSE_RECORDING;

constructor(public status: boolean) {}
}

export type All =
| PerformAction
| Reset
Expand All @@ -98,4 +105,5 @@ export type All =
| JumpToState
| JumpToAction
| ImportState
| LockChanges;
| LockChanges
| PauseRecording;
4 changes: 4 additions & 0 deletions modules/store-devtools/src/devtools.ts
Original file line number Diff line number Diff line change
Expand Up @@ -157,4 +157,8 @@ export class StoreDevtools implements Observer<any> {
lockChanges(status: boolean) {
this.dispatch(new Actions.LockChanges(status));
}

pauseRecording(status: boolean) {
this.dispatch(new Actions.PauseRecording(status));
}
}
8 changes: 6 additions & 2 deletions modules/store-devtools/src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ export class DevtoolsExtension {

// Check to see if the action requires a full update of the liftedState.
// If it is a simple action generated by the user's app and the recording
// is not locked, only send the action and the current state (fast).
// is not locked/paused, only send the action and the current state (fast).
//
// A full liftedState update (slow: serializes the entire liftedState) is
// only required when:
Expand All @@ -80,7 +80,11 @@ export class DevtoolsExtension {
// c) the state has been recomputed due to time-traveling
// d) any action that is not a PerformAction to err on the side of
// caution.
if (action.type === PERFORM_ACTION && !state.isLocked) {
if (action.type === PERFORM_ACTION) {
if (state.isLocked || state.isPaused) {
return;
}

const currentState = unliftState(state);
const sanitizedState = this.config.stateSanitizer
? sanitizeState(
Expand Down
Loading

0 comments on commit bb2b8ef

Please sign in to comment.