@meetelise/chat 1.57.0 → 1.58.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.
@@ -47,8 +47,7 @@ export const leasingChatStyles = css`
47
47
  justify-content: space-between;
48
48
  }
49
49
  .leasing-conversation-body-backdrop {
50
- background: rgba(193, 193, 193, 0.5);
51
- backdrop-filter: blur(4px);
50
+ background: #efefef;
52
51
 
53
52
  border-top: 1px solid rgba(0, 0, 0, 0.1);
54
53
  border-bottom: 1px solid rgba(0, 0, 0, 0.1);
@@ -144,6 +144,11 @@ export class MEChat extends LitElement {
144
144
  */
145
145
  @property({ type: String })
146
146
  private declaredBuildingSlug = "";
147
+ /**
148
+ * Org-level webchat on a host that knows the page's building by id (Elise
149
+ * Studio), set with `setDeclaredBuildingId`. Undefined until the host sets it.
150
+ */
151
+ private hostDeclaredBuildingId: number | null | undefined = undefined;
147
152
  /**
148
153
  * Org-level webchat (`centralConvo` started without a building). Stays true
149
154
  * after the widget adopts the org's triage general building from
@@ -700,10 +705,16 @@ export class MEChat extends LitElement {
700
705
  if (this.centralConvo) {
701
706
  const myPubnub = this.myPubnub;
702
707
  myPubnub.centralConvo = true;
703
- // Not awaited: only needed once the visitor sends a message.
704
- void this.fetchDeclaredBuildingId().then((id) => {
705
- myPubnub.declaredBuildingId = id;
706
- });
708
+ if (this.hostDeclaredBuildingId !== undefined) {
709
+ myPubnub.declaredBuildingId = this.hostDeclaredBuildingId;
710
+ } else {
711
+ // Not awaited: only needed once the visitor sends a message.
712
+ void this.fetchDeclaredBuildingId().then((id) => {
713
+ if (this.hostDeclaredBuildingId === undefined) {
714
+ myPubnub.declaredBuildingId = id;
715
+ }
716
+ });
717
+ }
707
718
  } else {
708
719
  this.myPubnub.declaredBuildingId = this.buildingWebchatView.id;
709
720
  }
@@ -814,6 +825,16 @@ export class MEChat extends LitElement {
814
825
  };
815
826
  };
816
827
 
828
+ /**
829
+ * Org-level webchat: the page's building, sent with later visitor messages as
830
+ * `declaredBuildingId`. For hosts that move between pages without restarting
831
+ * the widget; it doesn't change config or the conversation.
832
+ */
833
+ setDeclaredBuildingId(id: number | null): void {
834
+ this.hostDeclaredBuildingId = id;
835
+ if (this.myPubnub) this.myPubnub.declaredBuildingId = id;
836
+ }
837
+
817
838
  /** The numeric id of the snippet's building in org-level webchat, if it names one. */
818
839
  private fetchDeclaredBuildingId = async (): Promise<number | null> => {
819
840
  if (!this.declaredBuildingSlug || !this.orgSlug) return null;
@@ -253,6 +253,8 @@ export class PubnubChat extends LitElement {
253
253
  return html``; // error should be here
254
254
  }
255
255
 
256
+ const assistantName = this.building?.userFirstName || "Elise";
257
+
256
258
  const buildingId = this.building?.id;
257
259
  let styles = {};
258
260
  if (this._isMobile) {
@@ -357,9 +359,8 @@ export class PubnubChat extends LitElement {
357
359
  </li>
358
360
  <li
359
361
  class="message-container ai-message"
360
- tabindex="0"
361
362
  role="article"
362
- aria-label="Elise: Hi I'm Elise. How can I assist you today?"
363
+ aria-label="${assistantName}: Hi I'm ${assistantName}. How can I assist you today?"
363
364
  >
364
365
  <p
365
366
  class=${classMap({
@@ -368,7 +369,7 @@ export class PubnubChat extends LitElement {
368
369
  ["webchat-font__mobile"]: this._isMobile,
369
370
  })}
370
371
  >
371
- Hi I'm Elise. How can I assist you today?
372
+ Hi I'm ${assistantName}. How can I assist you today?
372
373
  </p>
373
374
  </li>
374
375
  ${this.messages.map((message) => {
@@ -378,11 +379,10 @@ export class PubnubChat extends LitElement {
378
379
  ? "message-container lead-message"
379
380
  : "message-container ai-message"}
380
381
  key=${message.timestamp}
381
- tabindex="0"
382
382
  role="article"
383
383
  aria-label="${message.isLeadMessage
384
384
  ? "You"
385
- : "Elise"}: ${messageAriaLabel(message)}"
385
+ : assistantName}: ${messageAriaLabel(message)}"
386
386
  >
387
387
  ${isSimpleNavigationChatMessage(message)
388
388
  ? html`<pubnub-navigation
@@ -436,6 +436,7 @@ export class PubnubChat extends LitElement {
436
436
  <div id="utilities-inner-footer">
437
437
  <textarea
438
438
  id="message-input"
439
+ aria-label="Message"
439
440
  class=${classMap({
440
441
  ["webchat-font__desktop"]: !this._isMobile,
441
442
  ["webchat-font__mobile"]: this._isMobile,
@@ -535,9 +536,8 @@ export class PubnubChat extends LitElement {
535
536
  </li>
536
537
  <li
537
538
  class="message-container ai-message"
538
- tabindex="0"
539
539
  role="article"
540
- aria-label="Elise: Hi I'm Elise. If this is a medical emergency, please call 911. How can I assist you today?"
540
+ aria-label="${assistantName}: Hi I'm ${assistantName}. If this is a medical emergency, please call 911. How can I assist you today?"
541
541
  >
542
542
  <p
543
543
  class=${classMap({
@@ -546,8 +546,8 @@ export class PubnubChat extends LitElement {
546
546
  ["webchat-font__mobile"]: this._isMobile,
547
547
  })}
548
548
  >
549
- Hi I'm Elise. If this is a medical emergency, please call 911.
550
- How can I assist you today?
549
+ Hi I'm ${assistantName}. If this is a medical emergency,
550
+ please call 911. How can I assist you today?
551
551
  </p>
552
552
  </li>
553
553
  ${this.messages.map((message) => {
@@ -557,11 +557,10 @@ export class PubnubChat extends LitElement {
557
557
  ? "message-container lead-message"
558
558
  : "message-container ai-message"}
559
559
  key=${message.timestamp}
560
- tabindex="0"
561
560
  role="article"
562
561
  aria-label="${message.isLeadMessage
563
562
  ? "You"
564
- : "Elise"}: ${messageAriaLabel(message)}"
563
+ : assistantName}: ${messageAriaLabel(message)}"
565
564
  >
566
565
  ${isSimpleNavigationChatMessage(message)
567
566
  ? html`<pubnub-navigation
@@ -615,6 +614,7 @@ export class PubnubChat extends LitElement {
615
614
  <div id="healthcare-inner-footer">
616
615
  <textarea
617
616
  id="message-input"
617
+ aria-label="Message"
618
618
  class=${classMap({
619
619
  ["webchat-font__desktop"]: !this._isMobile,
620
620
  ["webchat-font__mobile"]: this._isMobile,
@@ -734,9 +734,8 @@ export class PubnubChat extends LitElement {
734
734
  "ai-message": true,
735
735
  "with-box-shadow": orgId === 444,
736
736
  })}
737
- tabindex="0"
738
737
  role="article"
739
- aria-label="Elise: ${this.building.welcomeMessage}"
738
+ aria-label="${assistantName}: ${this.building.welcomeMessage}"
740
739
  >
741
740
  <p
742
741
  class=${classMap({
@@ -760,11 +759,10 @@ export class PubnubChat extends LitElement {
760
759
  "with-box-shadow": orgId === 444,
761
760
  })}
762
761
  key=${message.timestamp}
763
- tabindex="0"
764
762
  role="article"
765
763
  aria-label="${message.isLeadMessage
766
764
  ? "You"
767
- : "Elise"}: ${messageAriaLabel(message)}"
765
+ : assistantName}: ${messageAriaLabel(message)}"
768
766
  >
769
767
  ${isSimpleNavigationChatMessage(message)
770
768
  ? html`<pubnub-navigation
@@ -822,6 +820,7 @@ export class PubnubChat extends LitElement {
822
820
  >
823
821
  <textarea
824
822
  id="message-input"
823
+ aria-label="Message"
825
824
  class=${classMap({
826
825
  ["webchat-font__desktop"]: !this._isMobile,
827
826
  ["webchat-font__mobile"]: this._isMobile,
@@ -855,7 +854,6 @@ export class PubnubChat extends LitElement {
855
854
  @click=${() => this.sendMessage(this.messageInput.value)}
856
855
  ?disabled=${this.myPubnub?.isCurrentlyStreamingMessage}
857
856
  aria-label="Send message"
858
- aria-describedby="Send message"
859
857
  >
860
858
  ${shouldUsePrimaryColorForChatFooter(
861
859
  this.building.orgId,
@@ -0,0 +1,152 @@
1
+ import { expect } from "@esm-bundle/chai";
2
+ import "../public/dist/index";
3
+ import { BuildingWebchatView } from "./fetchBuildingWebchatView";
4
+ import type { SimpleChatMessage } from "./MyPubnub";
5
+ import type { PubnubChat } from "./WebComponent/pubnub-chat";
6
+
7
+ type WidgetTypeName = "default" | "healthcare" | "utilities";
8
+
9
+ declare const afterEach: (callback: () => void) => void;
10
+ declare const it: (name: string, callback: () => void | Promise<void>) => void;
11
+
12
+ const text = (visible: string): string => visible.replace(/\s+/g, " ").trim();
13
+
14
+ const conversation = (): SimpleChatMessage[] => [
15
+ {
16
+ timestamp: 1,
17
+ message: "Do you have a two bedroom?",
18
+ isLeadMessage: true,
19
+ chunks: [{ text: "Do you have a two bedroom?", order: 0, isDone: true }],
20
+ type: "text",
21
+ },
22
+ {
23
+ timestamp: 2,
24
+ message: "Yes, I can help with that.",
25
+ isLeadMessage: false,
26
+ chunks: [{ text: "Yes, I can help with that.", order: 0, isDone: true }],
27
+ type: "text",
28
+ },
29
+ {
30
+ timestamp: 3,
31
+ media: [{ title: null, description: null, url: null }],
32
+ isLeadMessage: false,
33
+ type: "media",
34
+ },
35
+ {
36
+ timestamp: 4,
37
+ navigation: {
38
+ url: "https://example.com/floor-plans",
39
+ label: "the floor plans",
40
+ },
41
+ isLeadMessage: false,
42
+ type: "navigation",
43
+ },
44
+ ];
45
+
46
+ const mount = async (
47
+ widgetType: WidgetTypeName,
48
+ assistantName: string | null
49
+ ): Promise<PubnubChat> => {
50
+ const chat = document.createElement("pubnub-chat") as PubnubChat;
51
+ chat.buildingSlug = "alta-federal-hill";
52
+ chat.orgSlug = "greystar";
53
+ chat.widgetType = widgetType;
54
+ if (assistantName !== null) {
55
+ chat.building = {
56
+ id: 1,
57
+ orgId: 1,
58
+ name: "Alta Federal Hill",
59
+ userFirstName: assistantName,
60
+ welcomeMessage: `Hi, I'm ${assistantName}. How can I help you today?`,
61
+ state: "MD",
62
+ country: "US",
63
+ customAdditionalDisclaimer: null,
64
+ } as BuildingWebchatView;
65
+ }
66
+ document.body.appendChild(chat);
67
+ await chat.updateComplete;
68
+ // firstUpdated clears messages until PubNub has history.
69
+ chat.messages = conversation();
70
+ await chat.updateComplete;
71
+ return chat;
72
+ };
73
+
74
+ const labels = (chat: PubnubChat): string[] =>
75
+ Array.from(
76
+ chat.shadowRoot?.querySelectorAll<HTMLElement>('[role="article"]') ?? []
77
+ ).map((article) => article.getAttribute("aria-label") ?? "");
78
+
79
+ afterEach(() => {
80
+ document.querySelectorAll("pubnub-chat").forEach((chat) => chat.remove());
81
+ });
82
+
83
+ it("announces leasing messages as the configured assistant", async () => {
84
+ const chat = await mount("default", "Emily");
85
+ const articles = Array.from(
86
+ chat.shadowRoot?.querySelectorAll<HTMLElement>('[role="article"]') ?? []
87
+ );
88
+
89
+ expect(text(articles[0].innerText)).to.equal(
90
+ "Hi, I'm Emily. How can I help you today?"
91
+ );
92
+ expect(labels(chat)).to.deep.equal([
93
+ "Emily: Hi, I'm Emily. How can I help you today?",
94
+ "You: Do you have a two bedroom?",
95
+ "Emily: Yes, I can help with that.",
96
+ "Emily: Media message",
97
+ "Emily: Take me to the floor plans",
98
+ ]);
99
+ });
100
+
101
+ it("announces healthcare messages as the configured assistant", async () => {
102
+ const chat = await mount("healthcare", "Ezra");
103
+ const greeting = chat.shadowRoot?.querySelector<HTMLElement>(
104
+ "#message-thread-list > li.message-container"
105
+ );
106
+
107
+ expect(text(greeting?.innerText ?? "")).to.equal(
108
+ "Hi I'm Ezra. If this is a medical emergency, please call 911. How can I assist you today?"
109
+ );
110
+ expect(labels(chat)[0]).to.equal(
111
+ "Ezra: Hi I'm Ezra. If this is a medical emergency, please call 911. How can I assist you today?"
112
+ );
113
+ expect(labels(chat).slice(1)).to.deep.equal([
114
+ "You: Do you have a two bedroom?",
115
+ "Ezra: Yes, I can help with that.",
116
+ "Ezra: Media message",
117
+ "Ezra: Take me to the floor plans",
118
+ ]);
119
+ });
120
+
121
+ it("announces utilities messages as the configured assistant", async () => {
122
+ const chat = await mount("utilities", "Emily");
123
+ const greeting = chat.shadowRoot?.querySelector<HTMLElement>(
124
+ "#message-thread-list > li.message-container"
125
+ );
126
+
127
+ expect(text(greeting?.innerText ?? "")).to.equal(
128
+ "Hi I'm Emily. How can I assist you today?"
129
+ );
130
+ expect(labels(chat)).to.deep.equal([
131
+ "Emily: Hi I'm Emily. How can I assist you today?",
132
+ "You: Do you have a two bedroom?",
133
+ "Emily: Yes, I can help with that.",
134
+ "Emily: Media message",
135
+ "Emily: Take me to the floor plans",
136
+ ]);
137
+ });
138
+
139
+ it("keeps Elise when a chat has no configured assistant name", async () => {
140
+ const chat = await mount("utilities", null);
141
+ const greeting = chat.shadowRoot?.querySelector<HTMLElement>(
142
+ "#message-thread-list > li.message-container"
143
+ );
144
+
145
+ expect(text(greeting?.innerText ?? "")).to.equal(
146
+ "Hi I'm Elise. How can I assist you today?"
147
+ );
148
+ expect(labels(chat)[0]).to.equal(
149
+ "Elise: Hi I'm Elise. How can I assist you today?"
150
+ );
151
+ expect(labels(chat)[2]).to.equal("Elise: Yes, I can help with that.");
152
+ });
@@ -40,7 +40,8 @@ export type StudioWebchatMode = "host_managed_context";
40
40
  export type StudioWebchatSessionScopeType =
41
41
  | "building"
42
42
  | "building_group"
43
- | "site";
43
+ | "site"
44
+ | "org";
44
45
 
45
46
  export interface StudioWebchatSessionScope {
46
47
  type: StudioWebchatSessionScopeType;
@@ -60,6 +61,11 @@ export interface StudioWebchatContext {
60
61
  building?: string | null;
61
62
  buildingGroupId?: string | number | null;
62
63
  sessionScope?: StudioWebchatSessionScope;
64
+ /**
65
+ * Org scope only: the page's building, sent with visitor messages as
66
+ * `declaredBuildingId`. Null on pages with no single building.
67
+ */
68
+ declaredBuildingId?: number | null;
63
69
  path?: string;
64
70
  pageId?: string;
65
71
  }
@@ -323,6 +329,11 @@ export default class MEChat {
323
329
  return;
324
330
  }
325
331
 
332
+ if (context.sessionScope?.type === "org") {
333
+ this.updateStudioOrgContext(context, opts, updateToken);
334
+ return;
335
+ }
336
+
326
337
  const orgSlug = coerceStudioContextString(context.organization);
327
338
  const buildingSlug = coerceStudioContextString(context.building);
328
339
 
@@ -368,6 +379,64 @@ export default class MEChat {
368
379
  });
369
380
  }
370
381
 
382
+ /**
383
+ * Org-level webchat on a Studio site: one org-anchored widget for the whole
384
+ * site, started as the org-level pixel starts it. Route changes only move the
385
+ * page's declared building, so the conversation carries across pages.
386
+ */
387
+ static updateStudioOrgContext(
388
+ context: StudioWebchatContext,
389
+ opts: Options,
390
+ updateToken: number
391
+ ): void {
392
+ const orgSlug = coerceStudioContextString(context.organization);
393
+ if (!orgSlug) {
394
+ this.clearStudioContext({
395
+ source: "elise_studio",
396
+ reason: "missing_context",
397
+ preserveCache: true,
398
+ });
399
+ return;
400
+ }
401
+
402
+ const normalizedOrgSlug = normalizeOrgSlug(orgSlug);
403
+ const sessionScopeKey = context.sessionScope?.key || `org:${orgSlug}`;
404
+ const declaredBuildingId = coerceDeclaredBuildingId(
405
+ context.declaredBuildingId
406
+ );
407
+
408
+ if (
409
+ this.meChat &&
410
+ this.activeStudioOrgSlug === normalizedOrgSlug &&
411
+ !this.activeStudioBuildingSlug &&
412
+ this.activeStudioSessionScopeKey === sessionScopeKey
413
+ ) {
414
+ this.meChat.setDeclaredBuildingId(declaredBuildingId);
415
+ return;
416
+ }
417
+
418
+ void this.removeWidget().then(() => {
419
+ if (updateToken !== this.studioUpdateToken) return;
420
+
421
+ this.activeStudioOrgSlug = normalizedOrgSlug;
422
+ this.activeStudioBuildingSlug = "";
423
+ this.activeStudioSessionScopeKey = sessionScopeKey;
424
+ this.orgSlug = normalizedOrgSlug;
425
+
426
+ this.start(
427
+ {
428
+ ...opts,
429
+ studio: undefined,
430
+ organization: orgSlug,
431
+ building: undefined,
432
+ centralConvo: true,
433
+ },
434
+ false
435
+ );
436
+ this.meChat?.setDeclaredBuildingId(declaredBuildingId);
437
+ });
438
+ }
439
+
371
440
  static clearStudioContext(_context?: StudioWebchatClearContext): void {
372
441
  void _context;
373
442
  this.studioUpdateToken += 1;
@@ -536,6 +605,11 @@ function normalizeOrgSlug(orgSlug: string): string {
536
605
  : orgSlug;
537
606
  }
538
607
 
608
+ function coerceDeclaredBuildingId(value: unknown): number | null {
609
+ const id = typeof value === "string" ? Number(value) : value;
610
+ return typeof id === "number" && Number.isInteger(id) && id > 0 ? id : null;
611
+ }
612
+
539
613
  function coerceStudioSessionScopeKey(
540
614
  sessionScope: StudioWebchatSessionScope | undefined,
541
615
  buildingSlug: string
@@ -1,6 +1,6 @@
1
1
  import { expect } from "@esm-bundle/chai";
2
2
  import { restore, stub, useFakeXMLHttpRequest } from "sinon/pkg/sinon-esm";
3
- import "../public/dist/index";
3
+ import MEChat from "../public/dist/index";
4
4
  import type MyPubnub from "./MyPubnub";
5
5
  import type { SimpleChatMessage } from "./MyPubnub";
6
6
  import type { PubnubChat } from "./WebComponent/pubnub-chat";
@@ -623,3 +623,116 @@ it("still opens a per-building widget's tour scheduler from its tour link", asyn
623
623
  expect(widgetTakesOverClick(buildingTourLink)).to.equal(true);
624
624
  [buildingTourLink, ...others].forEach((link) => link.remove());
625
625
  });
626
+
627
+ // --- Org mode on an Elise Studio site ---
628
+
629
+ const STUDIO_SITE = "site-1";
630
+
631
+ const studioOrgContext = (declaredBuildingId: number | null) => ({
632
+ source: "elise_studio" as const,
633
+ siteId: STUDIO_SITE,
634
+ organization: "test-org",
635
+ sessionScope: { type: "org" as const, key: "org:test-org" },
636
+ declaredBuildingId,
637
+ });
638
+
639
+ const studioWidget = async (): Promise<MeChatInternals> => {
640
+ for (let i = 0; i < 200; i++) {
641
+ const meChat = document.querySelector("me-chat") as MeChatInternals | null;
642
+ if (meChat && !meChat.isLoading) {
643
+ await meChat.updateComplete;
644
+ return meChat;
645
+ }
646
+ await new Promise((resolve) => setTimeout(resolve, 10));
647
+ }
648
+ throw new Error("Studio widget never finished loading");
649
+ };
650
+
651
+ it("runs a Studio site's org scope as org-level webchat, one widget across pages", async () => {
652
+ const requests = fakeBackend(inRollout);
653
+ MEChat.start({
654
+ studio: { siteId: STUDIO_SITE, mode: "host_managed_context" },
655
+ });
656
+ try {
657
+ // The homepage: no building.
658
+ MEChat.updateStudioContext(studioOrgContext(null));
659
+ const meChat = await studioWidget();
660
+
661
+ expect(initBodies(requests)).to.deep.equal([
662
+ { building_slug: "", org_slug: "test-org", central_convo: true },
663
+ ]);
664
+ expect(meChat.buildingSlug).to.equal(GENERAL_BUILDING);
665
+ expect(meChat.myPubnub?.declaredBuildingId).to.equal(null);
666
+
667
+ // A property page: same widget and conversation, with the page's building.
668
+ MEChat.updateStudioContext(studioOrgContext(445038));
669
+ await new Promise((resolve) => setTimeout(resolve, 50));
670
+
671
+ expect(document.querySelectorAll("me-chat")).to.have.length(1);
672
+ expect(document.querySelector("me-chat")).to.equal(meChat);
673
+ expect(initBodies(requests)).to.have.length(1);
674
+ const message = await publishedMessage(meChat.myPubnub as MyPubnub);
675
+ expect(message).to.include({ declaredBuildingId: 445038 });
676
+
677
+ // Back to a page with no building.
678
+ MEChat.updateStudioContext(studioOrgContext(null));
679
+ expect(meChat.myPubnub?.declaredBuildingId).to.equal(null);
680
+ } finally {
681
+ await MEChat.remove();
682
+ }
683
+ });
684
+
685
+ it("swaps a Studio site's building widget for org-level webchat", async () => {
686
+ const requests = fakeBackend(inRollout);
687
+ MEChat.start({
688
+ studio: { siteId: STUDIO_SITE, mode: "host_managed_context" },
689
+ });
690
+ try {
691
+ MEChat.updateStudioContext({
692
+ source: "elise_studio",
693
+ siteId: STUDIO_SITE,
694
+ organization: "test-org",
695
+ building: "test-building",
696
+ sessionScope: { type: "building", key: "building:test-building" },
697
+ });
698
+ const buildingWidget = await studioWidget();
699
+ expect(buildingWidget.myPubnub?.centralConvo).to.not.equal(true);
700
+
701
+ MEChat.updateStudioContext(studioOrgContext(445038));
702
+ for (
703
+ let i = 0;
704
+ i < 100 && document.querySelector("me-chat") === buildingWidget;
705
+ i++
706
+ ) {
707
+ await new Promise((resolve) => setTimeout(resolve, 10));
708
+ }
709
+ const orgWidget = await studioWidget();
710
+
711
+ expect(orgWidget).to.not.equal(buildingWidget);
712
+ expect(document.querySelectorAll("me-chat")).to.have.length(1);
713
+ expect(orgWidget.myPubnub?.centralConvo).to.equal(true);
714
+ expect(orgWidget.myPubnub?.declaredBuildingId).to.equal(445038);
715
+ expect(initBodies(requests).at(-1)).to.deep.equal({
716
+ building_slug: "",
717
+ org_slug: "test-org",
718
+ central_convo: true,
719
+ });
720
+ } finally {
721
+ await MEChat.remove();
722
+ }
723
+ });
724
+
725
+ it("clears a Studio site's org scope without an organization", async () => {
726
+ fakeBackend(inRollout);
727
+ MEChat.start({
728
+ studio: { siteId: STUDIO_SITE, mode: "host_managed_context" },
729
+ });
730
+ try {
731
+ MEChat.updateStudioContext({ ...studioOrgContext(null), organization: "" });
732
+ await new Promise((resolve) => setTimeout(resolve, 50));
733
+
734
+ expect(document.querySelector("me-chat")).to.equal(null);
735
+ } finally {
736
+ await MEChat.remove();
737
+ }
738
+ });