Skip to content

Commit

Permalink
Subscribing a subscriber now works with tests
Browse files Browse the repository at this point in the history
  • Loading branch information
technoplato committed Mar 28, 2024
1 parent b26acac commit b138d0a
Show file tree
Hide file tree
Showing 3 changed files with 119 additions and 45 deletions.
103 changes: 77 additions & 26 deletions libs/permissions/permissionLogic/src/lib/permission-logic.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -325,46 +325,97 @@ describe('Permission Monitoring Machine', () => {
);
});
describe('Single Subscriber', () => {
const dummyFeatureMachine = setup({
actions: {
sendSubscriptionRequestForStatusUpdates:
//TODO this is not sending figure out whhy
sendTo(
it('should allow subscriptions from a subscriber to any permissions', () => {
const dummyFeatureMachine = setup({
actions: {
sendSubscriptionRequestForStatusUpdates: sendTo(
({ system }) => {
const actorRef: AnyActorRef = system.get('bigKahuna');
console.log({ actorRef });
return actorRef;
},
{
({ self }) => ({
type: 'subscribeToPermissionStatuses',
// permissions: [Permissions.bluetooth],
}
permissions: [Permissions.bluetooth],
self,
})
),
// satisfies /*TODO type these events to the receiving machine event type*/ AnyEventObject);
},
}).createMachine({
id: 'dummyFeatureId',
entry: [
'sendSubscriptionRequestForStatusUpdates',
log('subscribe to status updates'),
],
// satisfies /*TODO type these events to the receiving machine event type*/ AnyEventObject);
},
}).createMachine({
id: 'dummyFeatureId',
entry: [
'sendSubscriptionRequestForStatusUpdates',
log('subscribe to status updates'),
],
});

const actor = createActor(
permissionMonitoringMachine.provide({
actors: {
features: dummyFeatureMachine,
},
}),
{
parent: undefined,
systemId: 'bigKahuna',
}
).start();

const state = actor.getSnapshot();
expect(
state.context.permissionSubscribers[Permissions.bluetooth].length
).toEqual(1);
});
it('should allow subscriptions from a subscriber to any permissions', () => {
const actor = createActor(permissionMonitoringMachine, {
parent: undefined,
systemId: 'bigKahuna',
}).start();

const dummyFeatureActor = createActor(dummyFeatureMachine).start();
it(/*FIXME: how do I access the actor
or trigger the subscription request again
or configure different starting context via input
*/ 'should not add a subscriber if the subscriber is already subscribed', () => {
const dummyFeatureMachineThatSubscribesTwice = setup({
actions: {
sendSubscriptionRequestForStatusUpdates: sendTo(
({ system }) => {
const actorRef: AnyActorRef = system.get('bigKahuna');
return actorRef;
},
({ self }) => ({
type: 'subscribeToPermissionStatuses',
permissions: [Permissions.bluetooth],
self,
})
),
// satisfies /*TODO type these events to the receiving machine event type*/ AnyEventObject);
},
}).createMachine({
id: 'dummyFeatureId',
entry: [
'sendSubscriptionRequestForStatusUpdates',
'sendSubscriptionRequestForStatusUpdates',
log('subscribe to status updates'),
],
});

const actor = createActor(
permissionMonitoringMachine.provide({
actors: {
features: dummyFeatureMachineThatSubscribesTwice,
},
}),
{
parent: undefined,
systemId: 'bigKahuna',
}
).start();

const state = actor.getSnapshot();
expect(
state.context.permissionSubscribers?.[Permissions.bluetooth]
?.length ?? 0
actor.getSnapshot().context.permissionSubscribers[
Permissions.bluetooth
].length
).toEqual(1);
});
});
});

it('handle the happy path of being invoked, checking permission initially and then handle a permission request', async () => {
const permission: Permission = Permissions.microphone;

Expand Down
25 changes: 7 additions & 18 deletions libs/permissions/permissionLogic/src/lib/permission.types.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { AnyActorRef } from 'xstate';

export const Permissions = {
bluetooth: 'bluetooth',
microphone: 'microphone',
Expand All @@ -14,7 +16,11 @@ export type PermissionStatus =
(typeof PermissionStatuses)[keyof typeof PermissionStatuses];

export type PermissionMonitoringMachineEvents =
| { type: 'subscribeToPermissionStatuses'; permissions: Permission[] }
| {
type: 'subscribeToPermissionStatuses';
permissions: Permission[];
self: AnyActorRef;
}
| {
type: 'allPermissionsChecked';
statuses: PermissionStatusMapType;
Expand Down Expand Up @@ -45,23 +51,6 @@ export const PermissionCheckingStates = {
export type PermissionMonitoringMachineContext = {
permissionStatuses: PermissionStatusMapType;
};
// export type PermissionMonitoringMachineEvents =
// | { type: 'checkPermissions' }
// | {
// type: 'permissionChecked';
// permission: Permission;
// status: PermissionStatus;
// }
// | {
// type: 'triggerPermissionCheck';
// permission: Permission;
// }
// | {
// type: 'triggerPermissionRequest';
// permission: Permission;
// }
// | { type: 'applicationForegrounded' }
// | { type: 'applicationBackgrounded' };

export type PermissionMachineEvents =
| { type: 'triggerPermissionCheck' }
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {
Permission,
PermissionMonitoringMachineEvents,
Permissions,
PermissionStatusMapType,
Expand Down Expand Up @@ -30,6 +31,7 @@ export const permissionMonitoringMachine = setup({
applicationLifecycleReportingMachine:
stubApplicationLifecycleReportingActorLogic,
permissionCheckerAndRequesterMachine,
features: setup({}).createMachine({}),
},

actions: {
Expand Down Expand Up @@ -66,13 +68,45 @@ export const permissionMonitoringMachine = setup({
id: 'bigKahuna',
type: 'parallel',

// TODO: this should live at the top level of the application, not here
invoke: [{ src: 'features' }],

context: {
permissionsStatuses: InitialPermissionStatusMap,
permissionSubscribers: EmptyPermissionSubscriberMap,
},
on: {
subscribeToPermissionStatuses: {
actions: [log('received permission subscription'), log('or did we')],
actions: assign(({ context, event }) => {
const { permissions } = event;
const { permissionSubscribers } = context;

// Create a new permissionSubscribers object to avoid mutating the original
const updatedPermissionSubscribers: PermissionSubscriberMap = {
...permissionSubscribers,
};

// Iterate over each permission in the event's permissions array
permissions.forEach((permission: Permission) => {
// If the permission doesn't exist in the permissionSubscribers map, initialize it as an empty array
if (!updatedPermissionSubscribers[permission]) {
updatedPermissionSubscribers[permission] = [];
}

// Add the actor to the subscribers list for the permission, ensuring not to add duplicates
const actorAlreadySubscribed = updatedPermissionSubscribers[
permission
].some((actor) => actor.id === event.self.id);

if (!actorAlreadySubscribed) {
updatedPermissionSubscribers[permission].push(event.self);
}
});

return {
permissionSubscribers: updatedPermissionSubscribers,
};
}),
},
},
// entry: raise({ type: 'subscribeToPermissionStatuses', permissions: [] }),
Expand Down

0 comments on commit b138d0a

Please sign in to comment.