@tellescope/sdk 1.13.5 → 1.14.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -20,10 +20,9 @@ import {
20
20
  CalendarEvent,
21
21
  CUDSubscription,
22
22
  AutomationAction,
23
- AttendeeInfo,
24
23
  } from "@tellescope/types-models"
25
24
 
26
- import { Session } from "../sdk"
25
+ import { EnduserSession, Session } from "../sdk"
27
26
  import { ChatMessage, Meeting } from "@tellescope/types-client"
28
27
 
29
28
  const [email, password] = [process.env.TEST_EMAIL, process.env.TEST_PASSWORD]
@@ -31,6 +30,10 @@ const [email2, password2] = [process.env.TEST_EMAIL_2, process.env.TEST_PASSWORD
31
30
  const [nonAdminEmail, nonAdminPassword] = [process.env.NON_ADMIN_EMAIL, process.env.NON_ADMIN_PASSWORD]
32
31
  const subUserEmail = process.env.SUB_EMAIL
33
32
 
33
+ const host = process.env.TEST_URL || 'http://localhost:8080'
34
+ const businessId = '60398b1131a295e64f084ff6'
35
+ const enduserSDK = new EnduserSession({ host, businessId })
36
+
34
37
  if (!(email && subUserEmail && password && email2 && password2 && nonAdminEmail && nonAdminPassword)) {
35
38
  console.error("Set TEST_EMAIL and TEST_PASSWORD")
36
39
  process.exit(1)
@@ -89,7 +92,7 @@ for (const model in WEBHOOK_MODELS) {
89
92
  emptySubscription[model as WebhookSupportedModel] = { create: false, update: false, delete: false }
90
93
  }
91
94
 
92
- const CHECK_WEBHOOK_DELAY_MS = 50
95
+ const CHECK_WEBHOOK_DELAY_MS = 75
93
96
  let webhookIndex = 0
94
97
  const check_next_webhook = async (evaluate: (hook: WebhookCall) => boolean, name: string, error: string, isSubscribed: boolean, noHookExpected?: boolean) => {
95
98
  if (isSubscribed === false) return
@@ -100,7 +103,7 @@ const check_next_webhook = async (evaluate: (hook: WebhookCall) => boolean, name
100
103
  if (noHookExpected) {
101
104
  assert(!event, error, name)
102
105
  } else {
103
- assert(!!event, error || 'did not get hook', name || 'got hook')
106
+ assert(!!event, (error || '') + '(did not get hook)', name || 'got hook')
104
107
  }
105
108
  if (!event) return // ensure webhookIndex not incremented
106
109
 
@@ -505,6 +508,113 @@ const calendar_event_reminders_tests = async (isSubscribed: boolean) => {
505
508
  await sdk.api.calendar_events.deleteOne(calendarEvent.id)
506
509
  }
507
510
 
511
+ const self_serve_appointment_booking_tests = async () => {
512
+ log_header("Self Serve Appointment Booking")
513
+
514
+ await sdk.api.webhooks.update({ subscriptionUpdates: {
515
+ ...emptySubscription,
516
+ calendar_events: { create: true, update: true } }
517
+ })
518
+
519
+ const e1 = await sdk.api.endusers.createOne({ email: 'sebass+selfserve@tellescope.com' })
520
+ await sdk.api.endusers.set_password({ id: e1.id, password })
521
+ await enduserSDK.authenticate('sebass+selfserve@tellescope.com', password)
522
+
523
+ const event30min = await sdk.api.calendar_event_templates.createOne({
524
+ title: 'test 1', durationInMinutes: 30, confirmationEmailDisabled: true, confirmationSMSDisabled: true,
525
+ })
526
+
527
+ // ensure it doesn't match current day, to avoid errors on testing
528
+ const dayOfWeekStartingSundayIndexedByZero = (new Date().getDay() + 1) % 7
529
+
530
+ await sdk.api.users.updateOne(sdk.userInfo.id, {
531
+ weeklyAvailabilities: [
532
+ {
533
+ dayOfWeekStartingSundayIndexedByZero,
534
+ startTimeInMinutes: 60 * 12, // noon,
535
+ endTimeInMinutes: 60 * 14, // 2pm,
536
+ },
537
+ ],
538
+ timezone: 'America/New_York',
539
+ }, {
540
+ replaceObjectFields: true,
541
+ })
542
+
543
+ const slots = await enduserSDK.api.calendar_events.get_appointment_availability({
544
+ calendarEventTemplateId: event30min.id,
545
+ from: new Date(),
546
+ })
547
+ const toCancel = (await enduserSDK.api.calendar_events.book_appointment({
548
+ calendarEventTemplateId: event30min.id,
549
+ startTime: new Date(slots.availabilityBlocks[0].startTimeInMS),
550
+ userId: slots.availabilityBlocks[0].userId,
551
+ })).createdEvent
552
+ await check_next_webhook(
553
+ a => (
554
+ a.type === 'create' && a.records[0].id === toCancel.id
555
+ ),
556
+ 'book-appointment webhook', 'book-appointment webhook error', true,
557
+ )
558
+
559
+ await enduserSDK.api.calendar_events.updateOne(toCancel.id, { cancelledAt: new Date() })
560
+ await check_next_webhook(
561
+ a => (
562
+ a.records[0].id === toCancel.id
563
+ && a.type === 'update'
564
+ ),
565
+ 'cancel appointment webhook', 'cancel appointment webhook error', true,
566
+ )
567
+
568
+ const toReschedule = (await enduserSDK.api.calendar_events.book_appointment({
569
+ calendarEventTemplateId: event30min.id,
570
+ startTime: new Date(slots.availabilityBlocks[0].startTimeInMS),
571
+ userId: slots.availabilityBlocks[0].userId,
572
+ })).createdEvent
573
+ await check_next_webhook(
574
+ a => (
575
+ a.records[0].id === toReschedule.id
576
+ ),
577
+ 'to reschedule webhook', 'to reschedule webhook error', true,
578
+ )
579
+
580
+ const rescheduledAppointment = (await enduserSDK.api.calendar_events.book_appointment({
581
+ calendarEventTemplateId: event30min.id,
582
+ rescheduledCalendarEventId: toReschedule.id,
583
+ startTime: new Date(slots.availabilityBlocks[1].startTimeInMS),
584
+ userId: slots.availabilityBlocks[1].userId,
585
+ })).createdEvent
586
+
587
+ // should get two webhooks on reschedule, and order may not be guaranteed
588
+ await check_next_webhook(
589
+ a => (
590
+ (a.type === 'create' && a.records[0].id === rescheduledAppointment.id)
591
+ || (a.type === 'update' && a.records[0].id === toReschedule.id && a.message === 'calendar event rescheduled')
592
+ ),
593
+ 'reschedule webhook', 'reschedule webhook error', true,
594
+ )
595
+ await check_next_webhook(
596
+ a => (
597
+ (a.type === 'create' && a.records[0].id === rescheduledAppointment.id)
598
+ || (a.type === 'update' && a.records[0].id === toReschedule.id && a.description === 'calendar event rescheduled')
599
+ ),
600
+ 'reschedule webhook', 'reschedule webhook error', true,
601
+ )
602
+
603
+ await Promise.all([
604
+ sdk.api.endusers.deleteOne(e1.id),
605
+ sdk.api.calendar_event_templates.deleteOne(event30min.id),
606
+ sdk.api.calendar_events.deleteOne(toCancel.id),
607
+ sdk.api.calendar_events.deleteOne(toReschedule.id),
608
+ sdk.api.calendar_events.deleteOne(rescheduledAppointment.id),
609
+ sdk.api.users.updateOne(sdk.userInfo.id,
610
+ { weeklyAvailabilities: [] },
611
+ { replaceObjectFields: true },
612
+ ),
613
+ sdk.api.webhooks.update({ subscriptionUpdates: emptySubscription })
614
+ ])
615
+ }
616
+
617
+
508
618
  const tests: { [K in WebhookSupportedModel | 'calendarEventReminders' | 'sub']?: (isSubscribed: boolean) => Promise<void> } = {
509
619
  form_responses: form_response_tests,
510
620
  sub: sub_organization_tests,
@@ -574,6 +684,8 @@ const run_tests = async () => {
574
684
  { onResult: r => r.url === webhookURL && objects_equivalent(r.subscriptions, fullSubscription) }
575
685
  )
576
686
 
687
+ await self_serve_appointment_booking_tests()
688
+
577
689
  // reset to only poartial / testing fields
578
690
  // todo: subscribe in individual tests to avoid issues in ordering of tests / subscriptions
579
691
  await sdk.api.webhooks.update({ subscriptionUpdates: {