Repository: temporalio/ui
Pull request #186 (2021-12-28 19:39:05)

Implement routing and data structures for compact view
Lays all of the ground work for the compact view. The view layer itself still needs to be implemented.


Patch:
diff --git a/src/events.d.ts b/src/events.d.ts
index f9e2defc..4fbb984a 100644
--- a/src/events.d.ts
+++ b/src/events.d.ts
@@ -374,3 +374,7 @@ type EventTypeCategory =
   | 'timer'
   | 'workflow'
   | 'command';
+
+type ActivityEvent = HistoryEventWithId & {
+  eventType: ActivityType;
+};
diff --git a/src/lib/components/event-table.svelte b/src/lib/components/event-table.svelte
index 90f2bd26..46820d62 100644
--- a/src/lib/components/event-table.svelte
+++ b/src/lib/components/event-table.svelte
@@ -1,8 +1,10 @@
 <script lang="ts">
-  import Event from './event.svelte';
   import VirtualList from '@sveltejs/svelte-virtual-list';
 
-  export let events: (HistoryEventWithId | PendingActivity)[];
+  import type { Activities } from '$lib/models/activity';
+  import Event from './event.svelte';
+
+  export let events: (HistoryEventWithId | PendingActivity)[] | Activities;
 </script>
 
 <section
diff --git a/src/lib/components/event.svelte b/src/lib/components/event.svelte
index 17b95fd9..b33029b0 100644
--- a/src/lib/components/event.svelte
+++ b/src/lib/components/event.svelte
@@ -1,4 +1,5 @@
 <script lang="ts">
+  import type { Activity } from '$lib/models/activity';
   import { page } from '$app/stores';
 
   import Icon from 'svelte-fa';
@@ -6,21 +7,17 @@
 
   import { formatEvent } from '$lib/utilities/get-event-classification';
   import { formatDate } from '$lib/utilities/format-date';
-  import { routeFor } from '$lib/utilities/route-for';
 
   import EventLabel from '$lib/components/event-label.svelte';
 
-  export let event: HistoryEventWithId | PendingActivity;
+  export let event: HistoryEventWithId | PendingActivity | Activity;
 
-  let { id, pending, timeStamp, name, tag, classification } =
+  let { id, routeFor, pending, timeStamp, name, tag, classification } =
     formatEvent(event);
 
   let { namespace, workflow: workflowId, run: runId } = $page.params;
   let parameters = { namespace, workflowId, runId, eventId: id };
-
-  let href = pending
-    ? routeFor('workflow.events.full.pending', parameters)
-    : routeFor('workflow.events.full.event', parameters);
+  let href = routeFor(parameters);
 </script>
 
 <a
diff --git a/src/lib/models/activity.ts b/src/lib/models/activity.ts
new file mode 100644
index 00000000..5a9b1e8c
--- /dev/null
+++ b/src/lib/models/activity.ts
@@ -0,0 +1,143 @@
+type ScheduledActivityEvent = HistoryEventWithId & {
+  eventType: 'ActivityTaskScheduled';
+};
+
+const activityTypes = [
+  'ActivityTaskCanceled',
+  'ActivityTaskCancelRequested',
+  'ActivityTaskCompleted',
+  'ActivityTaskFailed',
+  'ActivityTaskScheduled',
+  'ActivityTaskStarted',
+  'ActivityTaskTimedOut',
+];
+
+const isActivity = (event: HistoryEventWithId): event is ActivityEvent => {
+  if (activityTypes.includes(event.eventType)) return true;
+  return false;
+};
+
+const isActivityScheduledEvent = (
+  event: HistoryEventWithId,
+): event is ScheduledActivityEvent => {
+  return event.eventType === 'ActivityTaskScheduled';
+};
+
+export class Activity {
+  id: string;
+  name: string;
+  private _events: Map<ActivityType, HistoryEventWithId> = new Map();
+
+  constructor(event: ScheduledActivityEvent) {
+    this.id = event?.activityTaskScheduledEventAttributes?.activityId;
+    this.name = event?.activityTaskScheduledEventAttributes?.activityType?.name;
+
+    this.set(event.eventType, event);
+  }
+
+  set(type: ActivityType, event: HistoryEventWithId) {
+    this._events.set(type, event);
+  }
+
+  get(type: ActivityType): HistoryEventWithId {
+    return this._events.get(type);
+  }
+
+  get events(): typeof this._events {
+    return this._events;
+  }
+
+  get length(): number {
+    return this.events.size;
+  }
+
+  get last(): HistoryEventWithId {
+    let last: HistoryEventWithId;
+
+    for (const event of this) {
+      last = event;
+    }
+
+    return last;
+  }
+
+  [Symbol.iterator]() {
+    return this._events.values();
+  }
+}
+
+export class Activities {
+  private _activities: Map<string, Activity> = new Map();
+
+  static from = (
+    events: HistoryEventWithId[],
+    activities = new Activities(),
+  ): Activities => {
+    for (const event of events) {
+      if (isActivity(event)) {
+        activities.add(event);
+      }
+    }
+
+    return activities;
+  };
+
+  constructor(event?: ActivityEvent | HistoryEventWithId[]) {
+    if (Array.isArray(event)) return Activities.from(event, this);
+    if (event) this.add(event);
+  }
+
+  get(id: string | number | Long) {
+    return this._activities.get(String(id));
+  }
+
+  add(event: ActivityEvent) {
+    if (isActivityScheduledEvent(event)) {
+      const id = String(event.id);
+      return this._activities.set(id, new Activity(event));
+    }
+
+    if (event.eventType === 'ActivityTaskStarted') {
+      const { scheduledEventId } = event.activityTaskStartedEventAttributes;
+      return this.get(scheduledEventId).set(event.eventType, event);
+    }
+
+    if (event.eventType === 'ActivityTaskCanceled') {
+      const { scheduledEventId } = event.activityTaskCanceledEventAttributes;
+      return this.get(scheduledEventId).set(event.eventType, event);
+    }
+
+    if (event.eventType === 'ActivityTaskCancelRequested') {
+      const { scheduledEventId } =
+        event.activityTaskCancelRequestedEventAttributes;
+      return this.get(scheduledEventId).set(event.eventType, event);
+    }
+
+    if (event.eventType === 'ActivityTaskFailed') {
+      const { scheduledEventId } = event.activityTaskFailedEventAttributes;
+      return this.get(scheduledEventId).set(event.eventType, event);
+    }
+
+    if (event.eventType === 'ActivityTaskTimedOut') {
+      const { scheduledEventId } = event.activityTaskTimedOutEventAttributes;
+      return this.get(scheduledEventId).set(event.eventType, event);
+    }
+
+    if (event.eventType === 'ActivityTaskCompleted') {
+      const { scheduledEventId } = event.activityTaskCompletedEventAttributes;
+      return this.get(scheduledEventId).set(event.eventType, event);
+    }
+  }
+
+  get length(): number {
+    return this._activities.size;
+  }
+
+  slice(...args: Parameters<typeof Array.prototype.slice>): Activity[] {
+    return [...this].slice(...args);
+  }
+
+  [Symbol.iterator]() {
+    return this._activities.values();
+  }
+}
diff --git a/src/lib/utilities/collect-activities.ts b/src/lib/utilities/collect-activities.ts
deleted file mode 100644
index 38d87a6b..00000000
--- a/src/lib/utilities/collect-activities.ts
+++ /dev/null
@@ -1,105 +0,0 @@
-type Activity = Record<ActivityType, HistoryEventWithId>;
-type Activities = Record<string, Activity>;
-type ActivityGroup = {
-  name?: string;
-  taskQueue?: string;
-  events: Activities;
-};
-
-const set = (
-  activities: ActivityGroup,
-  activityId: string | Long,
-  property: ActivityType,
-  value: HistoryEventWithId,
-): void => {
-  const id = String(activityId);
-  if (!activities[id]) {
-    const events = {} as Activities;
-    activities[id] = {
-      events,
-    } as ActivityGroup;
-  }
-  activities[id].events[property] = value;
-};
-
-const setMetadata = (
-  activities: ActivityGroup,
-  eventId: string | Long,
-  scheduledEvent: HistoryEventWithId,
-): void => {
-  const id = String(eventId);
-  const { activityType, taskQueue } =
-    scheduledEvent.activityTaskScheduledEventAttributes;
-
-  activities[id].name = activityType.name;
-  activities[id].taskQueue = taskQueue.name;
-};
-
-export const collectActivities = (events: HistoryEventWithId[]) => {
-  const activities: ActivityGroup = {
-    events: {} as Activities,
-  };
-
-  for (const event of events) {
-    if (event.eventType === 'ActivityTaskScheduled') {
-      set(activities, event.id, event.eventType, event);
-      setMetadata(activities, event.id, event);
-    }
-
-    if (event.eventType === 'ActivityTaskStarted') {
-      set(
-        activities,
-        event.activityTaskStartedEventAttributes.scheduledEventId,
-        event.eventType,
-        event,
-      );
-    }
-
-    if (event.eventType === 'ActivityTaskCanceled') {
-      set(
-        activities,
-        event.activityTaskCanceledEventAttributes.scheduledEventId,
-        event.eventType,
-        event,
-      );
-    }
-
-    if (event.eventType === 'ActivityTaskCancelRequested') {
-      set(
-        activities,
-        event.activityTaskCancelRequestedEventAttributes.scheduledEventId,
-        event.eventType,
-        event,
-      );
-    }
-
-    if (event.eventType === 'ActivityTaskFailed') {
-      set(
-        activities,
-        event.activityTaskFailedEventAttributes.scheduledEventId,
-        event.eventType,
-        event,
-      );
-    }
-
-    if (event.eventType === 'ActivityTaskTimedOut') {
-      set(
-        activities,
-        event.activityTaskTimedOutEventAttributes.scheduledEventId,
-        event.eventType,
-        event,
-      );
-    }
-
-    if (event.eventType === 'ActivityTaskCompleted') {
-      set(
-        activities,
-        event.activityTaskCompletedEventAttributes.scheduledEventId,
-        event.eventType,
-        event,
-      );
-    }
-  }
-
-  return activities;
-};
diff --git a/src/lib/utilities/get-event-classification.ts b/src/lib/utilities/get-event-classification.ts
index 78ff0e7b..8d786ff5 100644
--- a/src/lib/utilities/get-event-classification.ts
+++ b/src/lib/utilities/get-event-classification.ts
@@ -1,6 +1,10 @@
+import { Activity } from '../models/activity';
 import { format } from './format-camel-case';
+import { routeFor } from './route-for';
+import type { EventParameter } from './route-for';
 
 export type EventClassification = typeof eventClassifications[number];
+type EventOrActivity = HistoryEventWithId | PendingActivity | Activity;
 
 type EventSummary = {
   id: string;
@@ -9,6 +13,9 @@ type EventSummary = {
   classification: EventClassification;
   tag: string;
   pending: boolean;
+  activity: boolean;
+  type: 'event' | 'pending-activity' | 'activity';
+  routeFor: (parameters: EventParameter) => string;
 };
 
 export const eventClassifications = [
@@ -41,8 +48,8 @@ export const isEvent = (event: unknown): event is HistoryEventWithId => {
   return false;
 };
 
-export const isActivity = (
-  event: HistoryEventWithId | PendingActivity,
+export const isPendingActivity = (
+  event: EventOrActivity,
 ): event is PendingActivity => {
   if (event === null) return false;
   if (typeof event !== 'object') return false;
@@ -51,10 +58,15 @@ export const isActivity = (
   return false;
 };
 
+export const isActivity = (event: EventOrActivity): event is Activity => {
+  return event instanceof Activity;
+};
+
 export const getEventClassification = (
-  event: HistoryEventWithId | PendingActivity,
+  event: EventOrActivity,
 ): EventClassification => {
-  if (isActivity(event)) return event.state;
+  if (isPendingActivity(event)) return event.state;
+  if (isActivity(event)) event = event.get('ActivityTaskScheduled');
 
   const eventType = event.eventType;
 
@@ -64,23 +76,46 @@ export const getEventClassification = (
   }
 };
 
-const getName = (event: HistoryEventWithId | PendingActivity): string => {
+const getName = (event: EventOrActivity): string => {
   if (isEvent(event)) return String(event.eventType);
-  if (isActivity(event)) return `${event.activityType.name}:${event.state}`;
+  if (isPendingActivity(event))
+    return `${event.activityType.name}:${event.state}`;
+  if (isActivity(event)) return event.name;
 };
 
-const getTime = (event: HistoryEventWithId | PendingActivity): string => {
+const getTime = (event: EventOrActivity): string => {
   if (isEvent(event)) return String(event.eventTime);
-  if (isActivity(event)) return String(event.lastStartedTime);
+  if (isPendingActivity(event)) return String(event.lastStartedTime);
+  if (isActivity(event)) return String(event.last.eventTime);
 };
 
-const getId = (event: HistoryEventWithId | PendingActivity): string => {
+const getId = (event: EventOrActivity): string => {
   if (isEvent(event)) return String(event.eventId);
-  if (isActivity(event)) return String(event.activityId);
+  if (isPendingActivity(event)) return String(event.activityId);
+  if (isActivity(event)) return String(event.id);
+};
+
+const getType = (
+  event: EventOrActivity,
+): 'event' | 'pending-activity' | 'activity' => {
+  if (isEvent(event)) return 'event';
+  if (isPendingActivity(event)) return 'pending-activity';
+  if (isActivity(event)) return 'activity';
+};
+
+export const getHref = (
+  event: EventOrActivity,
+  parameters: EventParameter,
+): string => {
+  if (isEvent(event)) return routeFor('workflow.events.full.event', parameters);
+  if (isPendingActivity(event))
+    routeFor('workflow.events.full.pending', parameters);
+  if (isActivity(event))
+    return routeFor('workflow.events.compact.activity', parameters);
 };
 
 export const formatEvent = (
-  event: HistoryEventWithId | PendingActivity,
+  event: EventOrActivity | Activity,
 ): EventSummary => {
   return {
     id: getId(event),
@@ -88,6 +123,9 @@ export const formatEvent = (
     timeStamp: getTime(event),
     classification: getEventClassification(event),
     tag: getName(event),
-    pending: isActivity(event),
+    type: getType(event),
+    pending: isPendingActivity(event),
+    activity: isActivity(event),
+    routeFor: (parameters: EventParameter) => getHref(event, parameters),
   };
 };
diff --git a/src/lib/utilities/route-for.ts b/src/lib/utilities/route-for.ts
index 5a20edd3..f1451557 100644
--- a/src/lib/utilities/route-for.ts
+++ b/src/lib/utilities/route-for.ts
@@ -27,7 +27,7 @@ export type TaskQueueParameter = {
   queue: string;
 } & NamespaceParameter;
 
-type CompositeParameters = NamespaceParameter &
+export type RouteParameters = NamespaceParameter &
   WorkflowParameters &
   EventParameter &
   TaskQueueParameter;
@@ -98,10 +98,7 @@ export function routeFor(
   path: 'workers',
   parameters: TaskQueueParameter,
 ): string;
-export function routeFor(
-  path: RoutePath,
-  parameters: CompositeParameters,
-): string {
+export function routeFor(path: RoutePath, parameters: RouteParameters): string {
   if (path === 'workflows') {
     return routeForWorkflows(parameters);
   }
diff --git a/src/routes/namespaces/[namespace]/workflows/[workflow]/[run]/history/compact/__layout.svelte b/src/routes/namespaces/[namespace]/workflows/[workflow]/[run]/history/compact/__layout.svelte
index 114b1369..46427672 100644
--- a/src/routes/namespaces/[namespace]/workflows/[workflow]/[run]/history/compact/__layout.svelte
+++ b/src/routes/namespaces/[namespace]/workflows/[workflow]/[run]/history/compact/__layout.svelte
@@ -15,31 +15,15 @@
 </script>
 
 <script lang="ts">
-  import { eventTypeInCategory } from '$lib/utilities/get-event-categorization';
-
-  import FilterSelect from '$lib/components/select/filter-select.svelte';
-  import Option from '$lib/components/select/option.svelte';
+  import { Activities } from '$lib/models/activity';
   import EventTable from '$lib/components/event-table.svelte';
 
   export let events: HistoryEventWithId[];
 
-  let category: EventTypeCategory = null;
-
-  $: visibleEvents = events.filter(eventTypeInCategory(category));
+  let activities = new Activities(events);
 </script>
 
-<EventTable events={visibleEvents}>
-  <div slot="filters">
-    <FilterSelect parameter="event-type" bind:value={category}>
-      <Option value={null}>All</Option>
-      <Option value="activity">Activity</Option>
-      <Option value="command">Command</Option>
-      <Option value="signal">Signal</Option>
-      <Option value="timer">Timer</Option>
-      <Option value="child-workflow">Child Workflow</Option>
-      <Option value="workflow">Workflow</Option>
-    </FilterSelect>
-  </div>
+<EventTable events={activities}>
   <div slot="details" class="w-full h-full">
     <slot />
   </div>
diff --git a/src/routes/namespaces/[namespace]/workflows/[workflow]/[run]/history/compact/activity-[id].svelte b/src/routes/namespaces/[namespace]/workflows/[workflow]/[run]/history/compact/activity-[id].svelte
index 6dd56890..8354a915 100644
--- a/src/routes/namespaces/[namespace]/workflows/[workflow]/[run]/history/compact/activity-[id].svelte
+++ b/src/routes/namespaces/[namespace]/workflows/[workflow]/[run]/history/compact/activity-[id].svelte
@@ -1,3 +1,29 @@
+<script context="module" lang="ts">
+  import type { LoadInput } from '@sveltejs/kit';
+
+  export async function load({ stuff }: LoadInput) {
+    const { events } = stuff as {
+      events: HistoryEventWithId[];
+    };
+
+    return {
+      props: {
+        events,
+      },
+    };
+  }
+</script>
+
+<script lang="ts">
+  import { page } from '$app/stores';
+  import { Activities } from '$lib/models/activity';
+
+  export let events: HistoryEventWithId[];
+
+  const activities = new Activities(events);
+  const activity = activities.get($page.params.id);
+</script>
+
 <div class="flex items-center justify-center w-full h-full">
-  <p>(To be implemented.)</p>
+  <p>{activity.name} (To be implemented.)</p>
 </div>


Test patch:
diff --git a/src/lib/models/activity.test.ts b/src/lib/models/activity.test.ts
new file mode 100644
index 00000000..32129333
--- /dev/null
+++ b/src/lib/models/activity.test.ts
@@ -0,0 +1,218 @@
+import { Activity, Activities } from './activity';
+
+const scheduledEvent = {
+  id: '5',
+  eventId: '5',
+  eventTime: '2021-12-27T15:23:21.806965200Z',
+  eventType: 'ActivityTaskScheduled',
+  version: '0',
+  taskId: '1049493',
+  activityTaskScheduledEventAttributes: {
+    activityId: '5',
+    activityType: {
+      name: 'CompletedActivity',
+    },
+    namespace: '',
+    taskQueue: {
+      name: 'rainbow-statuses',
+      kind: 'Normal',
+    },
+    input: null,
+  },
+};
+
+const anotherScheduledEvent = {
+  id: '99',
+  eventId: '99',
+  eventTime: '2021-12-27T15:23:21.806965200Z',
+  eventType: 'ActivityTaskScheduled',
+  version: '0',
+  taskId: '1049494',
+  activityTaskScheduledEventAttributes: {
+    activityId: '5',
+    activityType: {
+      name: 'FicticiousEvent',
+    },
+    namespace: '',
+    taskQueue: {
+      name: 'test-events',
+      kind: 'Normal',
+    },
+    input: null,
+  },
+};
+
+const startedEvent = {
+  id: '6',
+  eventId: '6',
+  eventTime: '2021-12-27T15:23:21.824600700Z',
+  eventType: 'ActivityTaskStarted',
+  version: '0',
+  taskId: '1049497',
+  activityTaskStartedEventAttributes: {
+    scheduledEventId: '5',
+    identity: '21665@temporal@',
+    requestId: '0202572f-485c-426a-a3ee-02ea46d3cad7',
+    attempt: 1,
+    lastFailure: null,
+  },
+};
+
+const completedEvent = {
+  id: '7',
+  eventId: '7',
+  eventTime: '2021-12-27T15:23:21.841178500Z',
+  eventType: 'ActivityTaskCompleted',
+  version: '0',
+  taskId: '1049498',
+  activityTaskCompletedEventAttributes: {
+    result: null,
+    scheduledEventId: '5',
+    startedEventId: '6',
+    identity: '21665@temporal@',
+  },
+};
+
+const eventHistory = [
+  scheduledEvent,
+  startedEvent,
+  anotherScheduledEvent,
+  completedEvent,
+];
+
+describe(Activity, () => {
+  it('should grab the name of the ActivityTaskScheduledEvent', () => {
+    const activity = new Activity(scheduledEvent);
+
+    expect(activity.name).toBe('CompletedActivity');
+  });
+
+  it('should grab the id of the ActivityTaskScheduledEvent', () => {
+    const activity = new Activity(scheduledEvent);
+
+    expect(activity.id).toBe('5');
+  });
+
+  it('should store the ActivityTaskScheduled', () => {
+    const activity = new Activity(scheduledEvent);
+
+    expect(activity.get('ActivityTaskScheduled')).toBe(scheduledEvent);
+  });
+
+  it('should be able to add a started event', () => {
+    const activity = new Activity(scheduledEvent);
+    activity.set(completedEvent.eventType, completedEvent);
+
+    expect(activity.length).toBe(2);
+    expect(activity.get('ActivityTaskCompleted')).toBe(completedEvent);
+  });
+});
+
+describe(Activity, () => {
+  it('should create a new entry when given an ActivityTaskScheduled event', () => {
+    const activities = new Activities();
+
+    activities.add(scheduledEvent);
+
+    const activity = activities.get(scheduledEvent.id);
+
+    expect(activity.get('ActivityTaskScheduled')).toBe(scheduledEvent);
+  });
+
+  it('should correctly set the name of the activity', () => {
+    const activities = new Activities();
+
+    activities.add(scheduledEvent);
+
+    const activity = activities.get(scheduledEvent.id);
+
+    expect(activity.name).toBe('CompletedActivity');
+  });
+
+  it('should correctly set the id of the activity', () => {
+    const activities = new Activities();
+
+    activities.add(scheduledEvent);
+
+    const activity = activities.get(scheduledEvent.id);
+
+    expect(activity.id).toBe('5');
+  });
+
+  it('should correctly set the name of the activity', () => {
+    const activities = new Activities();
+
+    activities.add(scheduledEvent);
+
+    const activity = activities.get(scheduledEvent.id);
+
+    expect(activity.id).toBe('5');
+  });
+
+  it('should be able to store multiple activities', () => {
+    const activities = new Activities();
+
+    activities.add(scheduledEvent);
+    activities.add(anotherScheduledEvent);
+
+    expect(activities.length).toBe(2);
+  });
+
+  it('should add a completed event to the correct activity', () => {
+    const activities = new Activities();
+
+    activities.add(scheduledEvent);
+    activities.add(completedEvent);
+
+    const activity = activities.get(scheduledEvent.id);
+
+    expect(activity.length).toBe(2);
+    expect(activity.get('ActivityTaskCompleted')).toBe(completedEvent);
+  });
+
+  it('should be able to add multiple activities and their associated events', () => {
+    const activities = new Activities();
+
+    activities.add(scheduledEvent);
+    activities.add(startedEvent);
+    activities.add(completedEvent);
+    activities.add(anotherScheduledEvent);
+
+    const [first, second] = activities;
+
+    expect(activities.length).toBe(2);
+    expect(first.length).toBe(3);
+    expect(second.length).toBe(1);
+  });
+
+  describe('from event history', () => {
+    it('should create a collection with the correct number of activities', () => {
+      const activities = Activities.from(eventHistory);
+
+      const [first, second] = activities;
+
+      expect(activities.length).toBe(2);
+      expect(first.length).toBe(3);
+      expect(second.length).toBe(1);
+    });
+
+    it('should create a collection with the correct number of activities using the constructor', () => {
+      const activities = new Activities(eventHistory);
+
+      const [first, second] = activities;
+
+      expect(activities.length).toBe(2);
+      expect(first.length).toBe(3);
+      expect(second.length).toBe(1);
+    });
+
+    it('should instantiate correctly when given a single event', () => {
+      const activities = new Activities(scheduledEvent);
+
+      const [activity] = activities;
+
+      expect(activities.length).toBe(1);
+      expect(activity.length).toBe(1);
+    });
+  });
+});
diff --git a/src/lib/utilities/collect-activities.test.ts b/src/lib/utilities/collect-activities.test.ts
deleted file mode 100644
index 26920e82..00000000
--- a/src/lib/utilities/collect-activities.test.ts
+++ /dev/null
@@ -1,106 +0,0 @@
-import { collectActivities } from './collect-activities';
-
-const eventHistory = [
-  {
-    id: '5',
-    eventId: '5',
-    eventTime: '2021-12-27T15:23:21.806965200Z',
-    eventType: 'ActivityTaskScheduled',
-    version: '0',
-    taskId: '1049493',
-    activityTaskScheduledEventAttributes: {
-      activityId: '5',
-      activityType: {
-        name: 'CompletedActivity',
-      },
-      namespace: '',
-      taskQueue: {
-        name: 'rainbow-statuses',
-        kind: 'Normal',
-      },
-      header: {
-        fields: {},
-      },
-      input: null,
-      scheduleToCloseTimeout: '0s',
-      scheduleToStartTimeout: '0s',
-      startToCloseTimeout: '3600s',
-      heartbeatTimeout: '0s',
-      workflowTaskCompletedEventId: '4',
-      retryPolicy: {
-        initialInterval: '1s',
-        backoffCoefficient: 2,
-        maximumInterval: '100s',
-        maximumAttempts: 1,
-        nonRetryableErrorTypes: [],
-      },
-    },
-  },
-  {
-    id: '6',
-    eventId: '6',
-    eventTime: '2021-12-27T15:23:21.824600700Z',
-    eventType: 'ActivityTaskStarted',
-    version: '0',
-    taskId: '1049497',
-    activityTaskStartedEventAttributes: {
-      scheduledEventId: '5',
-      identity: '21665@temporal@',
-      requestId: '0202572f-485c-426a-a3ee-02ea46d3cad7',
-      attempt: 1,
-      lastFailure: null,
-    },
-  },
-  {
-    id: '7',
-    eventId: '7',
-    eventTime: '2021-12-27T15:23:21.841178500Z',
-    eventType: 'ActivityTaskCompleted',
-    version: '0',
-    taskId: '1049498',
-    activityTaskCompletedEventAttributes: {
-      result: null,
-      scheduledEventId: '5',
-      startedEventId: '6',
-      identity: '21665@temporal@',
-    },
-  },
-];
-
-describe(collectActivities, () => {
-  it('have the activity name', () => {
-    const result = collectActivities(eventHistory);
-    const activity = result[5];
-
-    expect(activity.name).toBe('CompletedActivity');
-  });
-
-  it('should have a key with the ID of the ActivityTaskScheduledEvent', () => {
-    const result = collectActivities(eventHistory);
-    expect(result[5]).toBeDefined();
-  });
-
-  it('should have a scheduled activity of the first event', () => {
-    const [activityScheduled] = eventHistory;
-    const result = collectActivities(eventHistory);
-    const activity = result[5];
-
-    expect(activity.events.ActivityTaskScheduled).toBe(activityScheduled);
-  });
-
-  it('should have a scheduled activity of the first event', () => {
-    const [, activityStarted] = eventHistory;
-    const result = collectActivities(eventHistory);
-    const activity = result[5];
-
-    expect(activity.events.ActivityTaskStarted).toBe(activityStarted);
-  });
-
-  it('should have a scheduled activity of the first event', () => {
-    const [, , activityCompleted] = eventHistory;
-    const result = collectActivities(eventHistory);
-    const activity = result[5];
-
-    expect(activity.events.ActivityTaskCompleted).toBe(activityCompleted);
-  });
-});
diff --git a/src/lib/utilities/get-event-classification.test.ts b/src/lib/utilities/get-event-classification.test.ts
index c0cee89f..a9ad295c 100644
--- a/src/lib/utilities/get-event-classification.test.ts
+++ b/src/lib/utilities/get-event-classification.test.ts
@@ -1,7 +1,7 @@
 import {
   getEventClassification,
   isEvent,
-  isActivity,
+  isPendingActivity,
   formatEvent,
 } from './get-event-classification';
 
@@ -307,31 +307,31 @@ describe(isEvent, () => {
   });
 });
 
-describe(isActivity, () => {
+describe(isPendingActivity, () => {
   it('should return true if the event has an eventType', () => {
-    expect(isActivity({ activityType: { name: 'Workflow Started' } })).toBe(
-      true,
-    );
+    expect(
+      isPendingActivity({ activityType: { name: 'Workflow Started' } }),
+    ).toBe(true);
   });
 
   it('should return false if the event does not have an eventType', () => {
-    expect(isActivity({ eventType: 'Workflow Started' })).toBe(false);
+    expect(isPendingActivity({ eventType: 'Workflow Started' })).toBe(false);
   });
 
   it('should return false if passed null', () => {
-    expect(isActivity(null)).toBe(false);
+    expect(isPendingActivity(null)).toBe(false);
   });
 
   it('should return false if passed a string', () => {
-    expect(isActivity('string')).toBe(false);
+    expect(isPendingActivity('string')).toBe(false);
   });
 
   it('should return false if passed a number', () => {
-    expect(isActivity(4)).toBe(false);
+    expect(isPendingActivity(4)).toBe(false);
   });
 
   it('should return false if passed an array', () => {
-    expect(isActivity([])).toBe(false);
+    expect(isPendingActivity([])).toBe(false);
   });
 });