Skip to content

Commit

Permalink
Fix/remove-patching (#41)
Browse files Browse the repository at this point in the history
* rename method

* remove the experimental overriding

* improve effect testing
  • Loading branch information
kepta committed Oct 7, 2023
1 parent 6cdebb0 commit de854e0
Show file tree
Hide file tree
Showing 12 changed files with 180 additions and 1,080 deletions.
173 changes: 173 additions & 0 deletions packages/core/src/__tests__/effect-run.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
import { expect, jest, test, describe, beforeEach } from '@jest/globals';
import { testCleanup } from '../helpers/test-cleanup';
import { createKey } from '../slice/key';
import { EffectRun } from '../effect/effect-run';
import { createStore } from '../store';

const setup = () => {
const sliceAKey = createKey('slice1', []);
const fooField = sliceAKey.field('bar');
const sliceA = sliceAKey.slice({
fields: {
foo: fooField,
},
});

const sliceBKey = createKey('slice2', []);
const sliceBField = sliceBKey.field('bar');
const sliceBOtherField = sliceBKey.field('bizz');
const sliceB = sliceBKey.slice({
fields: {
sliceBField: sliceBField,
sliceBOtherField: sliceBOtherField,
},
});

const store = createStore({
name: 'test',
slices: [sliceA, sliceB],
});

return {
store,
sliceA,
fooField,
sliceBField,
sliceBOtherField,
sliceB,
};
};

beforeEach(() => {
testCleanup();
// Initialize your slices here. The actual initialization depends on your implementation
});

describe('EffectRun', () => {
describe('dependencies are tracked', () => {
test('should identify tracked slice correctly', () => {
const { store, sliceA, sliceB, fooField, sliceBField } = setup();
let runInstance = new EffectRun(store, 'test');
runInstance.addTrackedField(fooField, 'foo');
expect(
runInstance.getTrackedFields().find((r) => r.field === fooField),
).toBeDefined();
expect(
runInstance.getTrackedFields().find((r) => r.field === sliceBField),
).toBeUndefined();
});
});
});

describe('getFieldsThatChanged', () => {
test('should return false for a blank instance', () => {
const { store } = setup();
let runInstance1 = new EffectRun(store, 'test');

expect(runInstance1.getFieldsThatChanged()).toBeUndefined();
});

test('should return undefined when value is the same', () => {
const { store, sliceA, sliceB, fooField } = setup();
let runInstance1 = new EffectRun(store, 'test');
runInstance1.addTrackedField(fooField, fooField.initialValue);

expect(runInstance1.getFieldsThatChanged()).toBeUndefined();
expect(
// it should be still tracked
runInstance1.getTrackedFields().find((r) => r.field === fooField),
).toBeDefined();
});

test('should return field if tracked things have changed', () => {
const { store, sliceA, sliceB, fooField } = setup();
let runInstance1 = new EffectRun(store, 'test');
runInstance1.addTrackedField(fooField, fooField.initialValue);

expect(runInstance1.getFieldsThatChanged()).toBeUndefined();

store.dispatch(fooField.update('new value'));

expect(runInstance1.getFieldsThatChanged()).toBe(fooField);
});

test('should return undefined if none of tracked fields have changed', () => {
const { store, sliceA, sliceB, fooField, sliceBField } = setup();
let runInstance1 = new EffectRun(store, 'test');
runInstance1.addTrackedField(fooField, fooField.initialValue);

expect(runInstance1.getFieldsThatChanged()).toBeUndefined();

store.dispatch(sliceBField.update('new value'));

expect(runInstance1.getFieldsThatChanged()).toBeUndefined();
});

test('should return undefined if none of tracked fields have changed : 2', () => {
const { store, sliceA, sliceB, sliceBField, sliceBOtherField } = setup();
let updateField = (val: string) => sliceBField.update(val);

let updateOtherField = (val: string) => sliceBOtherField.update(val);

let runInstance1 = new EffectRun(store, 'test');

runInstance1.addTrackedField(
sliceBField,
sliceB.get(store.state).sliceBField,
);

expect(runInstance1.getFieldsThatChanged()).toBeUndefined();

store.dispatch(updateOtherField('xyz'));

expect(runInstance1.getFieldsThatChanged()).toBeUndefined();

store.dispatch(updateField('xyz'));

expect(runInstance1.getFieldsThatChanged()).toBe(sliceBField);
});

describe('cleanup', () => {
test('executes all cleanup callbacks on destroy', () => {
const { store, sliceA, sliceB, sliceBField, sliceBOtherField } = setup();

let runInstance1 = new EffectRun(store, 'test');
const cleanup = jest.fn(async () => {});
runInstance1.addCleanup(cleanup);
expect(cleanup).toBeCalledTimes(0);

runInstance1.destroy();
expect(cleanup).toBeCalledTimes(1);

// if called again, it should not be called again

runInstance1.destroy();
expect(cleanup).toBeCalledTimes(1);
});

test('should call callbacks only once', () => {
const { store, sliceA, sliceB, sliceBField, sliceBOtherField } = setup();

let runInstance1 = new EffectRun(store, 'test');
const cleanup = jest.fn(async () => {});
runInstance1.addCleanup(cleanup);

runInstance1.destroy();
runInstance1.destroy();
runInstance1.destroy();

expect(cleanup).toBeCalledTimes(1);
});

test('should run callback immediately if added after destroy', () => {
const { store, sliceA, sliceB, sliceBField, sliceBOtherField } = setup();

let runInstance1 = new EffectRun(store, 'test');
const cleanup = jest.fn(async () => {});

runInstance1.destroy();
runInstance1.addCleanup(cleanup);
expect(cleanup).toBeCalledTimes(1);
});
});
});
6 changes: 3 additions & 3 deletions packages/core/src/__tests__/effect.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ describe('effect with store', () => {
const store = createStore({
name: 'test',
overrides: {
effectSchedulerOverride: zeroTimeoutScheduler,
effectScheduler: zeroTimeoutScheduler,
},
slices: [sliceA, sliceB, sliceCDepB],
});
Expand Down Expand Up @@ -617,7 +617,7 @@ describe('effect only', () => {
await sleep(5);

jest
.spyOn(effect['runInstance'], 'whatDependenciesStateChange')
.spyOn(effect['runInstance'], 'getFieldsThatChanged')
.mockReturnValue(sliceAKey.field('some field that changed'));

effect._run();
Expand All @@ -634,7 +634,7 @@ describe('effect only', () => {
expect(callback).toHaveBeenCalledTimes(1);

jest
.spyOn(effect['runInstance'], 'whatDependenciesStateChange')
.spyOn(effect['runInstance'], 'getFieldsThatChanged')
.mockReturnValue(undefined);

effect._run();
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/effect/effect-run.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ export class EffectRun {
return;
}

whatDependenciesStateChange(): undefined | BaseField<any> {
getFieldsThatChanged(): undefined | BaseField<any> {
for (const { field, value } of this.trackedFields) {
const curVal = field.get(this.store.state);
if (!field.isEqual(curVal, value)) {
Expand Down
4 changes: 2 additions & 2 deletions packages/core/src/effect/effect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ export class Effect {
this.name = opts.name || effectCallback.name || 'anonymous';
this.debugLogger = rootStore.options.debug;
this.scheduler =
rootStore.options?.overrides?.effectSchedulerOverride || opts.scheduler;
rootStore.options?.overrides?.effectScheduler || opts.scheduler;

this.runInstance = new EffectRun(rootStore, this.name);
this.effectStore = new EffectStore(rootStore, this.name, () => {
Expand Down Expand Up @@ -178,7 +178,7 @@ export class Effect {

// if runCount == 0, always run, to ensure the effect runs at least once
if (this.runCount != 0) {
const depChanged = this.runInstance.whatDependenciesStateChange();
const depChanged = this.runInstance.getFieldsThatChanged();

fieldChanged = depChanged;

Expand Down
18 changes: 0 additions & 18 deletions packages/core/src/patch/README.md

This file was deleted.

Loading

0 comments on commit de854e0

Please sign in to comment.