@meetelise/chat 1.52.0 → 1.53.0
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.
- package/dist/src/WebComponent/Scheduler/tour-scheduler.d.ts +1 -0
- package/dist/src/WebComponent/actions/call-us-window.d.ts +1 -0
- package/dist/src/WebComponent/actions/email-us-window.d.ts +1 -0
- package/dist/src/WebComponent/launcher/Launcher.d.ts +1 -0
- package/dist/src/disclaimers.d.ts +5 -1
- package/package.json +1 -1
- package/public/dist/index.js +379 -306
- package/src/WebComponent/Scheduler/tour-scheduler.ts +5 -0
- package/src/WebComponent/actions/call-us-window.ts +7 -1
- package/src/WebComponent/actions/email-us-window.ts +3 -0
- package/src/WebComponent/launcher/Launcher.ts +5 -0
- package/src/WebComponent/me-chat.ts +1 -0
- package/src/disclaimers.ts +138 -0
- package/src/quebecConsentDisclaimers.test.ts +161 -0
|
@@ -195,6 +195,8 @@ export class TourScheduler extends LitElement {
|
|
|
195
195
|
|
|
196
196
|
@property({ attribute: false })
|
|
197
197
|
country: string | null = null;
|
|
198
|
+
@property({ attribute: false })
|
|
199
|
+
buildingState: string | null = null;
|
|
198
200
|
|
|
199
201
|
@property({ attribute: true })
|
|
200
202
|
currentLeadSource = ""; // the default lead source based on referrer and query params.
|
|
@@ -1645,6 +1647,7 @@ export class TourScheduler extends LitElement {
|
|
|
1645
1647
|
orgLegalName: this.orgLegalName,
|
|
1646
1648
|
orgSlug: this.orgSlug,
|
|
1647
1649
|
country: this.country,
|
|
1650
|
+
buildingState: this.buildingState,
|
|
1648
1651
|
clickingButtonText: "schedule tour",
|
|
1649
1652
|
})}
|
|
1650
1653
|
</div>
|
|
@@ -1700,6 +1703,7 @@ export class TourScheduler extends LitElement {
|
|
|
1700
1703
|
orgLegalName: this.orgLegalName,
|
|
1701
1704
|
orgSlug: this.orgSlug,
|
|
1702
1705
|
country: this.country,
|
|
1706
|
+
buildingState: this.buildingState,
|
|
1703
1707
|
clickingButtonText: "schedule tour",
|
|
1704
1708
|
})}
|
|
1705
1709
|
</div>
|
|
@@ -1810,6 +1814,7 @@ export class TourScheduler extends LitElement {
|
|
|
1810
1814
|
orgLegalName: this.orgLegalName,
|
|
1811
1815
|
orgSlug: this.orgSlug,
|
|
1812
1816
|
country: this.country,
|
|
1817
|
+
buildingState: this.buildingState,
|
|
1813
1818
|
clickingButtonText: "schedule tour",
|
|
1814
1819
|
})}
|
|
1815
1820
|
`
|
|
@@ -25,6 +25,8 @@ import { InputStyles } from "./InputStyles";
|
|
|
25
25
|
import {
|
|
26
26
|
CANADA_PRIVACY_POLICY_URL,
|
|
27
27
|
isCanadianBuilding,
|
|
28
|
+
isQuebecBuilding,
|
|
29
|
+
quebecConsentDisclaimer,
|
|
28
30
|
} from "../../disclaimers";
|
|
29
31
|
|
|
30
32
|
@customElement("call-us-window")
|
|
@@ -173,6 +175,8 @@ export class CallUsWindow extends LitElement {
|
|
|
173
175
|
orgLegalName = "";
|
|
174
176
|
@property({ attribute: false })
|
|
175
177
|
country: string | null = null;
|
|
178
|
+
@property({ attribute: false })
|
|
179
|
+
buildingState: string | null = null;
|
|
176
180
|
|
|
177
181
|
@property({ attribute: true })
|
|
178
182
|
private leadSourceClient: LeadSourceClient | null = null;
|
|
@@ -321,7 +325,9 @@ export class CallUsWindow extends LitElement {
|
|
|
321
325
|
</div>
|
|
322
326
|
|
|
323
327
|
<div class="text-us-window__description">
|
|
324
|
-
${
|
|
328
|
+
${isQuebecBuilding(this.buildingState)
|
|
329
|
+
? quebecConsentDisclaimer("textUs", this.orgLegalName)
|
|
330
|
+
: isCanadianBuilding(this.country)
|
|
325
331
|
? html`By providing your number and clicking send, you consent to
|
|
326
332
|
receive recurring commercial electronic messages from or on behalf
|
|
327
333
|
of ${this.orgLegalName} at this number. Messages may be AI or
|
|
@@ -121,6 +121,8 @@ export class EmailUsWindow extends LitElement {
|
|
|
121
121
|
orgLegalName = "";
|
|
122
122
|
@property({ attribute: false })
|
|
123
123
|
country: string | null = null;
|
|
124
|
+
@property({ attribute: false })
|
|
125
|
+
buildingState: string | null = null;
|
|
124
126
|
|
|
125
127
|
@property({ attribute: true })
|
|
126
128
|
private leadSourceClient: LeadSourceClient | null = null;
|
|
@@ -492,6 +494,7 @@ export class EmailUsWindow extends LitElement {
|
|
|
492
494
|
orgLegalName: this.orgLegalName,
|
|
493
495
|
orgSlug: this.orgSlug,
|
|
494
496
|
country: this.country,
|
|
497
|
+
buildingState: this.buildingState,
|
|
495
498
|
clickingButtonText: "send",
|
|
496
499
|
})}
|
|
497
500
|
</details-window>
|
|
@@ -81,6 +81,8 @@ export class Launcher extends LitElement {
|
|
|
81
81
|
orgLegalName = "";
|
|
82
82
|
@property({ attribute: false })
|
|
83
83
|
country: string | null = null;
|
|
84
|
+
@property({ attribute: false })
|
|
85
|
+
buildingState: string | null = null;
|
|
84
86
|
@property({ attribute: true })
|
|
85
87
|
chatCallUsHeader = "";
|
|
86
88
|
@property({ attribute: false })
|
|
@@ -1340,6 +1342,7 @@ export class Launcher extends LitElement {
|
|
|
1340
1342
|
.leadSourceMultitouchClient=${this.leadSourceMultitouchClient}
|
|
1341
1343
|
.orgLegalName=${this.orgLegalName}
|
|
1342
1344
|
.country=${this.country}
|
|
1345
|
+
.buildingState=${this.buildingState}
|
|
1343
1346
|
>
|
|
1344
1347
|
</email-us-window>
|
|
1345
1348
|
</div>`
|
|
@@ -1369,6 +1372,7 @@ export class Launcher extends LitElement {
|
|
|
1369
1372
|
.bedroomPreferenceRequired=${this.bedroomPreferenceRequired}
|
|
1370
1373
|
.orgLegalName=${this.orgLegalName}
|
|
1371
1374
|
.country=${this.country}
|
|
1375
|
+
.buildingState=${this.buildingState}
|
|
1372
1376
|
buildingId=${this.buildingId}
|
|
1373
1377
|
orgId=${this.orgId}
|
|
1374
1378
|
.leadSourceParams=${this.leadSourceParams}
|
|
@@ -1414,6 +1418,7 @@ export class Launcher extends LitElement {
|
|
|
1414
1418
|
.leadSourceMultitouchClient=${this.leadSourceMultitouchClient}
|
|
1415
1419
|
.orgLegalName=${this.orgLegalName}
|
|
1416
1420
|
.country=${this.country}
|
|
1421
|
+
.buildingState=${this.buildingState}
|
|
1417
1422
|
></call-us-window>
|
|
1418
1423
|
</div>
|
|
1419
1424
|
`
|
|
@@ -1044,6 +1044,7 @@ export class MEChat extends LitElement {
|
|
|
1044
1044
|
?.usesDynamicScheduling ?? false}
|
|
1045
1045
|
.orgLegalName=${this.buildingWebchatView?.orgLegalName ?? ""}
|
|
1046
1046
|
.country=${this.buildingWebchatView?.country ?? null}
|
|
1047
|
+
.buildingState=${this.buildingWebchatView?.state ?? null}
|
|
1047
1048
|
.tourTypeOptions=${this.buildingWebchatView
|
|
1048
1049
|
?.tourTypeOptions ?? []}
|
|
1049
1050
|
.layoutOptions=${this.buildingWebchatView?.layoutOptions ??
|
package/src/disclaimers.ts
CHANGED
|
@@ -12,6 +12,9 @@ const disclaimerStyles = {
|
|
|
12
12
|
link: {
|
|
13
13
|
color: "#4287f5",
|
|
14
14
|
},
|
|
15
|
+
paragraph: {
|
|
16
|
+
margin: "0 0 4px",
|
|
17
|
+
},
|
|
15
18
|
};
|
|
16
19
|
|
|
17
20
|
// States where we need to say "you are interacting with generative AI".
|
|
@@ -23,6 +26,129 @@ export const isCanadianBuilding = (
|
|
|
23
26
|
country: string | null | undefined
|
|
24
27
|
): boolean => country === "CA";
|
|
25
28
|
|
|
29
|
+
const QUEBEC_PRIVACY_POLICY_URL = "https://eliseai.com/fr/canada-policy";
|
|
30
|
+
const QUEBEC_TERMS_URL = "https://eliseai.com/fr/msgterms";
|
|
31
|
+
|
|
32
|
+
export const isQuebecBuilding = (state: string | null | undefined): boolean =>
|
|
33
|
+
state?.trim().toUpperCase() === "QC";
|
|
34
|
+
|
|
35
|
+
type QuebecConsentForm = "emailUs" | "textUs" | "scheduleTour";
|
|
36
|
+
|
|
37
|
+
const disclaimerLink = (href: string, label: string): TemplateResult =>
|
|
38
|
+
html`<a
|
|
39
|
+
style=${styleMap(disclaimerStyles.link)}
|
|
40
|
+
href=${href}
|
|
41
|
+
target="_blank"
|
|
42
|
+
rel="noopener noreferrer"
|
|
43
|
+
>${label}</a
|
|
44
|
+
>`;
|
|
45
|
+
|
|
46
|
+
const quebecConsentText = (
|
|
47
|
+
form: QuebecConsentForm,
|
|
48
|
+
orgLegalName: string
|
|
49
|
+
): [TemplateResult, TemplateResult] => {
|
|
50
|
+
const frenchLinks = html`${disclaimerLink(
|
|
51
|
+
QUEBEC_PRIVACY_POLICY_URL,
|
|
52
|
+
"Politique relative à la protection des renseignements personnels"
|
|
53
|
+
)}
|
|
54
|
+
ainsi qu’à ces ${disclaimerLink(QUEBEC_TERMS_URL, "Conditions générales")}`;
|
|
55
|
+
const englishLinks = html`${disclaimerLink(
|
|
56
|
+
QUEBEC_PRIVACY_POLICY_URL,
|
|
57
|
+
"privacy policy"
|
|
58
|
+
)}
|
|
59
|
+
and these ${disclaimerLink(QUEBEC_TERMS_URL, "terms and conditions")}`;
|
|
60
|
+
|
|
61
|
+
if (form === "textUs") {
|
|
62
|
+
return [
|
|
63
|
+
html`Lorsque vous fournissez votre numéro de téléphone et que vous cliquez
|
|
64
|
+
sur Envoyer (send), vous consentez à recevoir des messages électroniques
|
|
65
|
+
et des appels récurrents de nature commerciale de la part de
|
|
66
|
+
${orgLegalName} ou en son nom à ce numéro, dans la mesure où cela est
|
|
67
|
+
permis par les lois applicables. Les messages peuvent être générés par une
|
|
68
|
+
intelligence artificielle (IA) ou par un humain. Frais std SMS/données
|
|
69
|
+
applicables. Vous consentez à cette ${frenchLinks}, y compris à ce que
|
|
70
|
+
notre fournisseur de services, EliseAI, enregistre et utilise votre numéro
|
|
71
|
+
de téléphone et vos communications afin de générer des réponses et
|
|
72
|
+
d’améliorer ses services. Vous pouvez retirer votre consentement en tout
|
|
73
|
+
temps en vous désabonnant ou en communiquant avec nous.`,
|
|
74
|
+
html`By providing your number and clicking send, you consent to receive
|
|
75
|
+
recurring commercial electronic messages and calls from or on behalf of
|
|
76
|
+
${orgLegalName} at this number, to the extent permitted by applicable law.
|
|
77
|
+
Messages may be AI or human generated. StdMsg&DataRatesMayApply. You
|
|
78
|
+
consent to this ${englishLinks}, including having your number and
|
|
79
|
+
communications recorded and used by our service provider EliseAI to
|
|
80
|
+
generate responses and improve their services. You may withdraw your
|
|
81
|
+
consent at any time by unsubscribing or contacting us.`,
|
|
82
|
+
];
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
if (form === "scheduleTour") {
|
|
86
|
+
return [
|
|
87
|
+
html`Lorsque vous fournissez votre numéro de téléphone ou votre adresse
|
|
88
|
+
courriel et que vous cliquez sur Planifier une visite (schedule tour),
|
|
89
|
+
vous consentez à recevoir des messages électroniques et des appels
|
|
90
|
+
récurrents de nature commerciale de la part de ${orgLegalName} ou en son
|
|
91
|
+
nom à ce numéro ou à cette adresse courriel, dans la mesure où cela est
|
|
92
|
+
permis par les lois applicables. Les messages peuvent être générés par une
|
|
93
|
+
intelligence artificielle (IA) ou par un humain. Frais std SMS/données
|
|
94
|
+
applicables. Vous consentez à cette ${frenchLinks}, y compris à ce que
|
|
95
|
+
notre fournisseur de services, EliseAI, enregistre et utilise votre numéro
|
|
96
|
+
de téléphone, votre adresse courriel et vos communications afin de générer
|
|
97
|
+
des réponses et d’améliorer ses services. Vous pouvez retirer votre
|
|
98
|
+
consentement en tout temps en vous désabonnant ou en communiquant avec
|
|
99
|
+
nous.`,
|
|
100
|
+
html`By providing your number and/or email address and clicking schedule
|
|
101
|
+
tour, you consent to receive recurring commercial electronic messages and
|
|
102
|
+
calls from or on behalf of ${orgLegalName} at the provided number and/or
|
|
103
|
+
email address, to the extent permitted by applicable law. Messages may be
|
|
104
|
+
AI or human generated. StdMsg&DataRatesMayApply. You consent to this
|
|
105
|
+
${englishLinks}, including having your number, email address, and
|
|
106
|
+
communications recorded and used by our service provider EliseAI to
|
|
107
|
+
generate responses and improve their services. You may withdraw your
|
|
108
|
+
consent at any time by unsubscribing or contacting us.`,
|
|
109
|
+
];
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
return [
|
|
113
|
+
html`Lorsque vous fournissez votre adresse courriel ou votre numéro de
|
|
114
|
+
téléphone et que vous cliquez sur Envoyer (send), vous consentez à recevoir
|
|
115
|
+
des messages électroniques et des appels récurrents de nature commerciale de
|
|
116
|
+
la part de ${orgLegalName} ou en son nom à cette adresse courriel ou à ce
|
|
117
|
+
numéro, dans la mesure où cela est permis par les lois applicables. Les
|
|
118
|
+
messages peuvent être générés par une intelligence artificielle (IA) ou par
|
|
119
|
+
un humain. Vous consentez à cette ${frenchLinks}, y compris à ce que notre
|
|
120
|
+
fournisseur de services, EliseAI, enregistre et utilise votre adresse
|
|
121
|
+
courriel, votre numéro de téléphone et vos communications afin de générer
|
|
122
|
+
des réponses et d’améliorer ses services. Vous pouvez retirer votre
|
|
123
|
+
consentement en tout temps en vous désabonnant ou en communiquant avec nous.`,
|
|
124
|
+
html`By providing your email address and/or number and clicking send, you
|
|
125
|
+
consent to receive recurring commercial electronic messages and calls from
|
|
126
|
+
or on behalf of ${orgLegalName} at that email address and/or number, to the
|
|
127
|
+
extent permitted by applicable law. Messages may be AI or human generated.
|
|
128
|
+
You consent to this ${englishLinks}, including having your email address,
|
|
129
|
+
number, and communications recorded and used by our service provider EliseAI
|
|
130
|
+
to generate responses and improve their services. You may withdraw your
|
|
131
|
+
consent at any time by unsubscribing or contacting us.`,
|
|
132
|
+
];
|
|
133
|
+
};
|
|
134
|
+
|
|
135
|
+
export const quebecConsentDisclaimer = (
|
|
136
|
+
form: QuebecConsentForm,
|
|
137
|
+
orgLegalName: string,
|
|
138
|
+
hasPhoneNumber = false
|
|
139
|
+
): TemplateResult => {
|
|
140
|
+
const [french, english] = quebecConsentText(form, orgLegalName);
|
|
141
|
+
const paragraphStyle = styleMap(disclaimerStyles.paragraph);
|
|
142
|
+
return html`<p style=${paragraphStyle}>${french}</p>
|
|
143
|
+
<p style=${paragraphStyle}>${english}</p>
|
|
144
|
+
${form === "textUs" || hasPhoneNumber
|
|
145
|
+
? html`<p style=${paragraphStyle}>
|
|
146
|
+
Msg freq varies. Text STOP to opt-out of messages. Text HELP for
|
|
147
|
+
assistance.
|
|
148
|
+
</p>`
|
|
149
|
+
: ""}`;
|
|
150
|
+
};
|
|
151
|
+
|
|
26
152
|
export const CURRENT_CONSENT_ID = "currentConsentId";
|
|
27
153
|
|
|
28
154
|
const formDisclaimer = ({
|
|
@@ -31,6 +157,7 @@ const formDisclaimer = ({
|
|
|
31
157
|
orgLegalName,
|
|
32
158
|
orgSlug,
|
|
33
159
|
country,
|
|
160
|
+
buildingState,
|
|
34
161
|
clickingButtonText = "send",
|
|
35
162
|
}: {
|
|
36
163
|
buildingName: string;
|
|
@@ -39,8 +166,19 @@ const formDisclaimer = ({
|
|
|
39
166
|
orgLegalName: string;
|
|
40
167
|
orgSlug: string;
|
|
41
168
|
country?: string | null;
|
|
169
|
+
buildingState?: string | null;
|
|
42
170
|
clickingButtonText?: string;
|
|
43
171
|
}): TemplateResult => {
|
|
172
|
+
if (isQuebecBuilding(buildingState)) {
|
|
173
|
+
return html`<div style=${styleMap(disclaimerStyles.container)}>
|
|
174
|
+
${quebecConsentDisclaimer(
|
|
175
|
+
clickingButtonText === "schedule tour" ? "scheduleTour" : "emailUs",
|
|
176
|
+
orgLegalName,
|
|
177
|
+
!!phoneNumberInput
|
|
178
|
+
)}
|
|
179
|
+
</div>`;
|
|
180
|
+
}
|
|
181
|
+
|
|
44
182
|
const policyUrl = isCanadianBuilding(country)
|
|
45
183
|
? CANADA_PRIVACY_POLICY_URL
|
|
46
184
|
: "http://bit.ly/me_privacy_policy";
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import { expect } from "@esm-bundle/chai";
|
|
2
|
+
import { restore, useFakeXMLHttpRequest } from "sinon/pkg/sinon-esm";
|
|
3
|
+
import "../public/dist/index";
|
|
4
|
+
|
|
5
|
+
type Region = { state: string | null; country: string | null };
|
|
6
|
+
type Widget = HTMLElement & { updateComplete: Promise<boolean> };
|
|
7
|
+
type WidgetCase = {
|
|
8
|
+
name: string;
|
|
9
|
+
tag: string;
|
|
10
|
+
props: Record<string, string>;
|
|
11
|
+
propsAfterMount?: Record<string, boolean>;
|
|
12
|
+
french: string;
|
|
13
|
+
english: string;
|
|
14
|
+
ontarioCopy: string;
|
|
15
|
+
newYorkCopy: string;
|
|
16
|
+
newYorkLinks: string[];
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
const ORG = "Test Org Legal Inc.";
|
|
20
|
+
const QUEBEC: Region[] = [
|
|
21
|
+
{ state: "QC", country: "CA" },
|
|
22
|
+
{ state: "qc", country: null },
|
|
23
|
+
];
|
|
24
|
+
const ONTARIO: Region = { state: "ON", country: "CA" };
|
|
25
|
+
const NEW_YORK: Region = { state: "NY", country: "US" };
|
|
26
|
+
|
|
27
|
+
const FR_PRIVACY =
|
|
28
|
+
"Politique relative à la protection des renseignements personnels";
|
|
29
|
+
const PHONE_OPT_OUT =
|
|
30
|
+
"Msg freq varies. Text STOP to opt-out of messages. Text HELP for assistance.";
|
|
31
|
+
|
|
32
|
+
const EMAIL_US_FR = `Lorsque vous fournissez votre adresse courriel ou votre numéro de téléphone et que vous cliquez sur Envoyer (send), vous consentez à recevoir des messages électroniques et des appels récurrents de nature commerciale de la part de ${ORG} ou en son nom à cette adresse courriel ou à ce numéro, dans la mesure où cela est permis par les lois applicables. Les messages peuvent être générés par une intelligence artificielle (IA) ou par un humain. Vous consentez à cette ${FR_PRIVACY} ainsi qu’à ces Conditions générales, y compris à ce que notre fournisseur de services, EliseAI, enregistre et utilise votre adresse courriel, votre numéro de téléphone et vos communications afin de générer des réponses et d’améliorer ses services. Vous pouvez retirer votre consentement en tout temps en vous désabonnant ou en communiquant avec nous.`;
|
|
33
|
+
const EMAIL_US_EN = `By providing your email address and/or number and clicking send, you consent to receive recurring commercial electronic messages and calls from or on behalf of ${ORG} at that email address and/or number, to the extent permitted by applicable law. Messages may be AI or human generated. You consent to this privacy policy and these terms and conditions, including having your email address, number, and communications recorded and used by our service provider EliseAI to generate responses and improve their services. You may withdraw your consent at any time by unsubscribing or contacting us.`;
|
|
34
|
+
|
|
35
|
+
const TEXT_US_FR = `Lorsque vous fournissez votre numéro de téléphone et que vous cliquez sur Envoyer (send), vous consentez à recevoir des messages électroniques et des appels récurrents de nature commerciale de la part de ${ORG} ou en son nom à ce numéro, dans la mesure où cela est permis par les lois applicables. Les messages peuvent être générés par une intelligence artificielle (IA) ou par un humain. Frais std SMS/données applicables. Vous consentez à cette ${FR_PRIVACY} ainsi qu’à ces Conditions générales, y compris à ce que notre fournisseur de services, EliseAI, enregistre et utilise votre numéro de téléphone et vos communications afin de générer des réponses et d’améliorer ses services. Vous pouvez retirer votre consentement en tout temps en vous désabonnant ou en communiquant avec nous.`;
|
|
36
|
+
const TEXT_US_EN = `By providing your number and clicking send, you consent to receive recurring commercial electronic messages and calls from or on behalf of ${ORG} at this number, to the extent permitted by applicable law. Messages may be AI or human generated. StdMsg&DataRatesMayApply. You consent to this privacy policy and these terms and conditions, including having your number and communications recorded and used by our service provider EliseAI to generate responses and improve their services. You may withdraw your consent at any time by unsubscribing or contacting us.`;
|
|
37
|
+
|
|
38
|
+
const SCHEDULE_TOUR_FR = `Lorsque vous fournissez votre numéro de téléphone ou votre adresse courriel et que vous cliquez sur Planifier une visite (schedule tour), vous consentez à recevoir des messages électroniques et des appels récurrents de nature commerciale de la part de ${ORG} ou en son nom à ce numéro ou à cette adresse courriel, dans la mesure où cela est permis par les lois applicables. Les messages peuvent être générés par une intelligence artificielle (IA) ou par un humain. Frais std SMS/données applicables. Vous consentez à cette ${FR_PRIVACY} ainsi qu’à ces Conditions générales, y compris à ce que notre fournisseur de services, EliseAI, enregistre et utilise votre numéro de téléphone, votre adresse courriel et vos communications afin de générer des réponses et d’améliorer ses services. Vous pouvez retirer votre consentement en tout temps en vous désabonnant ou en communiquant avec nous.`;
|
|
39
|
+
const SCHEDULE_TOUR_EN = `By providing your number and/or email address and clicking schedule tour, you consent to receive recurring commercial electronic messages and calls from or on behalf of ${ORG} at the provided number and/or email address, to the extent permitted by applicable law. Messages may be AI or human generated. StdMsg&DataRatesMayApply. You consent to this privacy policy and these terms and conditions, including having your number, email address, and communications recorded and used by our service provider EliseAI to generate responses and improve their services. You may withdraw your consent at any time by unsubscribing or contacting us.`;
|
|
40
|
+
|
|
41
|
+
const renderedText = (root: ShadowRoot | null | undefined): string =>
|
|
42
|
+
(root?.textContent ?? "").replace(/\s+/g, " ");
|
|
43
|
+
|
|
44
|
+
const linkHrefs = (root: ShadowRoot | null | undefined): string[] =>
|
|
45
|
+
Array.from(root?.querySelectorAll("a") ?? []).map(
|
|
46
|
+
(a) => `${a.textContent?.trim()} -> ${a.getAttribute("href")}`
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
const expectQuebecConsent = (
|
|
50
|
+
root: ShadowRoot | null | undefined,
|
|
51
|
+
french: string,
|
|
52
|
+
english: string
|
|
53
|
+
): void => {
|
|
54
|
+
const text = renderedText(root);
|
|
55
|
+
expect(text).to.include(french);
|
|
56
|
+
expect(text).to.include(english);
|
|
57
|
+
expect(text.indexOf(french)).to.be.lessThan(text.indexOf(english));
|
|
58
|
+
expect(text.indexOf(english)).to.be.lessThan(text.indexOf(PHONE_OPT_OUT));
|
|
59
|
+
expect(linkHrefs(root)).to.include.members([
|
|
60
|
+
`${FR_PRIVACY} -> https://eliseai.com/fr/canada-policy`,
|
|
61
|
+
"Conditions générales -> https://eliseai.com/fr/msgterms",
|
|
62
|
+
"privacy policy -> https://eliseai.com/fr/canada-policy",
|
|
63
|
+
"terms and conditions -> https://eliseai.com/fr/msgterms",
|
|
64
|
+
]);
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
const expectNoFrench = (root: ShadowRoot | null | undefined): void => {
|
|
68
|
+
expect(renderedText(root)).not.to.include("Lorsque vous fournissez");
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
const US_PRIVACY_LINK = "privacy policy -> http://bit.ly/me_privacy_policy";
|
|
72
|
+
const PHONE = "(514) 555-0123";
|
|
73
|
+
|
|
74
|
+
const WIDGETS: WidgetCase[] = [
|
|
75
|
+
{
|
|
76
|
+
name: "Email Us form",
|
|
77
|
+
tag: "email-us-window",
|
|
78
|
+
props: { email: "local.test@example.com", phoneNumber: PHONE },
|
|
79
|
+
french: EMAIL_US_FR,
|
|
80
|
+
english: EMAIL_US_EN,
|
|
81
|
+
ontarioCopy: `By providing your email address and/or number and clicking send, you consent to receive recurring commercial electronic messages and calls from or on behalf of ${ORG} at that email address and/or number. Messages may be AI or human generated.`,
|
|
82
|
+
newYorkCopy: `By providing your number and clicking send, you consent to receive recurring marketing text and voice messages and calls from or on behalf of ${ORG} at this number using artificial voice or an autodialer system.`,
|
|
83
|
+
newYorkLinks: [US_PRIVACY_LINK],
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
name: "Text Us form",
|
|
87
|
+
tag: "call-us-window",
|
|
88
|
+
props: { hasTextUsEnabled: "true" },
|
|
89
|
+
french: TEXT_US_FR,
|
|
90
|
+
english: TEXT_US_EN,
|
|
91
|
+
ontarioCopy: `By providing your number and clicking send, you consent to receive recurring commercial electronic messages from or on behalf of ${ORG} at this number.`,
|
|
92
|
+
newYorkCopy: `By providing your number and clicking send, you consent to receive recurring marketing text and voice messages and calls from or on behalf of ${ORG} at this number using artificial voice or an autodialer system.`,
|
|
93
|
+
newYorkLinks: [
|
|
94
|
+
US_PRIVACY_LINK,
|
|
95
|
+
"terms and conditions -> https://eliseai.com/msgterms",
|
|
96
|
+
],
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
name: "tour scheduler",
|
|
100
|
+
tag: "tour-scheduler",
|
|
101
|
+
props: { phoneNumber: PHONE },
|
|
102
|
+
propsAfterMount: {
|
|
103
|
+
waitingForAvailabilities: false,
|
|
104
|
+
shouldAllowScheduleLoading: false,
|
|
105
|
+
shouldAllowScheduling: true,
|
|
106
|
+
},
|
|
107
|
+
french: SCHEDULE_TOUR_FR,
|
|
108
|
+
english: SCHEDULE_TOUR_EN,
|
|
109
|
+
ontarioCopy: `By providing your number and/or email address and clicking schedule tour, you consent to receive recurring commercial electronic messages and calls from or on behalf of ${ORG} at the provided number and/or email address. Messages may be AI or human generated.`,
|
|
110
|
+
newYorkCopy: `By providing your number and clicking schedule tour, you consent to receive recurring marketing text and voice messages and calls from or on behalf of ${ORG} at this number using artificial voice or an autodialer system.`,
|
|
111
|
+
newYorkLinks: [US_PRIVACY_LINK],
|
|
112
|
+
},
|
|
113
|
+
];
|
|
114
|
+
|
|
115
|
+
const renderWidget = async (
|
|
116
|
+
widget: WidgetCase,
|
|
117
|
+
region: Region
|
|
118
|
+
): Promise<Widget> => {
|
|
119
|
+
const element = document.createElement(widget.tag) as Widget;
|
|
120
|
+
Object.assign(element, widget.props, {
|
|
121
|
+
orgLegalName: ORG,
|
|
122
|
+
country: region.country,
|
|
123
|
+
buildingState: region.state,
|
|
124
|
+
});
|
|
125
|
+
document.body.appendChild(element);
|
|
126
|
+
Object.assign(element, widget.propsAfterMount);
|
|
127
|
+
await element.updateComplete;
|
|
128
|
+
return element;
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
afterEach(() => {
|
|
132
|
+
restore();
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
for (const widget of WIDGETS) {
|
|
136
|
+
it(`shows legal's French then English consent on the ${widget.name} only for Quebec`, async () => {
|
|
137
|
+
useFakeXMLHttpRequest();
|
|
138
|
+
|
|
139
|
+
for (const region of QUEBEC) {
|
|
140
|
+
const quebec = await renderWidget(widget, region);
|
|
141
|
+
expectQuebecConsent(quebec.shadowRoot, widget.french, widget.english);
|
|
142
|
+
quebec.remove();
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
const ontario = await renderWidget(widget, ONTARIO);
|
|
146
|
+
expectNoFrench(ontario.shadowRoot);
|
|
147
|
+
expect(renderedText(ontario.shadowRoot)).to.include(widget.ontarioCopy);
|
|
148
|
+
expect(linkHrefs(ontario.shadowRoot)).to.include(
|
|
149
|
+
"privacy policy -> https://eliseai.com/canada-policy"
|
|
150
|
+
);
|
|
151
|
+
ontario.remove();
|
|
152
|
+
|
|
153
|
+
const newYork = await renderWidget(widget, NEW_YORK);
|
|
154
|
+
expectNoFrench(newYork.shadowRoot);
|
|
155
|
+
expect(renderedText(newYork.shadowRoot)).to.include(widget.newYorkCopy);
|
|
156
|
+
expect(linkHrefs(newYork.shadowRoot)).to.include.members(
|
|
157
|
+
widget.newYorkLinks
|
|
158
|
+
);
|
|
159
|
+
newYork.remove();
|
|
160
|
+
});
|
|
161
|
+
}
|