Skip to content

Commit

Permalink
Add more tests
Browse files Browse the repository at this point in the history
  • Loading branch information
davidkpiano committed Feb 25, 2024
1 parent 44bf275 commit 831aeec
Show file tree
Hide file tree
Showing 2 changed files with 107 additions and 1 deletion.
11 changes: 10 additions & 1 deletion packages/core/src/actors/promise.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,13 +95,20 @@ export function fromPromise<TOutput, TInput = NonReducibleUnknown>(
): PromiseActorLogic<TOutput, TInput> {
const logic: PromiseActorLogic<TOutput, TInput> = {
config: promiseCreator,
transition: (state, event) => {
transition: (state, event, actorScope) => {
if (state.status !== 'active') {
return state;
}

const stopChildren = () => {
for (const child of Object.values(state.children)) {
actorScope.stopChild(child);
}
};

switch (event.type) {
case XSTATE_PROMISE_RESOLVE: {
stopChildren();
const resolvedValue = (event as any).data;
return {
...state,
Expand All @@ -111,13 +118,15 @@ export function fromPromise<TOutput, TInput = NonReducibleUnknown>(
};
}
case XSTATE_PROMISE_REJECT:
stopChildren();
return {
...state,
status: 'error',
error: (event as any).data,
input: undefined
};
case XSTATE_STOP:
stopChildren();
return {
...state,
status: 'stopped',
Expand Down
97 changes: 97 additions & 0 deletions packages/core/test/actorLogic.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,103 @@ describe('promise logic (fromPromise)', () => {
expect(actor.getSnapshot().children.child).toBe(res);
});
});

it('stops spawned actors when it is stopped', async () => {
const promiseLogic = fromPromise<void>(async ({ spawnChild }) => {
spawnChild(
fromPromise(
() =>
new Promise((_res, _rej) => {
// ...
})
),
{
id: 'child'
}
);
await new Promise((_res, _rej) => {
// ...
});
});

const actor = createActor(promiseLogic).start();

const snapshot = await waitFor(
actor,
(s) => Object.keys(s.children).length > 0
);

const child = snapshot.children.child;

expect(isActorRef(child)).toBeTruthy();
expect((child as AnyActorRef)._parent).toBe(actor);

expect(actor.getSnapshot().children.child).toBe(child);

expect(child.getSnapshot().status).toEqual('active');

actor.stop();

expect(child.getSnapshot().status).toEqual('stopped');
});

it('stops spawned actors when it is done', async () => {
const promiseLogic = fromPromise<number>(async ({ spawnChild }) => {
spawnChild(
fromPromise(
() =>
new Promise((_res, _rej) => {
// ...
})
),
{
id: 'child'
}
);
return 42;
});

const actor = createActor(promiseLogic).start();

await toPromise(actor);

const snapshot = actor.getSnapshot();
const child = snapshot.children.child;

expect(isActorRef(child)).toBeTruthy();
expect((child as AnyActorRef)._parent).toBe(actor);
expect(actor.getSnapshot().children.child).toBe(child);
expect(child.getSnapshot().status).toEqual('stopped');
});

it('stops spawned actors when it errors', async () => {
const promiseLogic = fromPromise<void>(async ({ spawnChild }) => {
spawnChild(
fromPromise(
() =>
new Promise((_res, _rej) => {
// ...
})
),
{
id: 'child'
}
);
await Promise.reject('uh oh');
});

const actor = createActor(promiseLogic).start();

try {
await toPromise(actor);
} catch {
const snapshot = actor.getSnapshot();
const child = snapshot.children.child;

expect(isActorRef(child)).toBeTruthy();
expect(child.getSnapshot().status).toEqual('stopped');
}
});
});

describe('transition function logic (fromTransition)', () => {
Expand Down

0 comments on commit 831aeec

Please sign in to comment.