@bigbinary/neeto-playwright-commons 4.2.3 → 4.3.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/index.d.ts +135 -2
- package/index.js +435 -107
- package/package.json +1 -1
package/index.d.ts
CHANGED
|
@@ -870,6 +870,81 @@ declare class IpRestrictionsApi {
|
|
|
870
870
|
}: AllowedIpRange) => Promise<playwright_core.APIResponse | undefined>;
|
|
871
871
|
disable: () => Promise<playwright_core.APIResponse | undefined>;
|
|
872
872
|
}
|
|
873
|
+
interface MailpitAddress {
|
|
874
|
+
Name: string;
|
|
875
|
+
Address: string;
|
|
876
|
+
}
|
|
877
|
+
interface MailpitPart {
|
|
878
|
+
PartID: string;
|
|
879
|
+
FileName: string;
|
|
880
|
+
ContentType: string;
|
|
881
|
+
ContentID: string;
|
|
882
|
+
Size: number;
|
|
883
|
+
}
|
|
884
|
+
interface MailpitMessageSummary {
|
|
885
|
+
ID: string;
|
|
886
|
+
MessageID: string;
|
|
887
|
+
From: MailpitAddress | null;
|
|
888
|
+
To: MailpitAddress[] | null;
|
|
889
|
+
Cc: MailpitAddress[] | null;
|
|
890
|
+
Bcc: MailpitAddress[] | null;
|
|
891
|
+
ReplyTo: MailpitAddress[] | null;
|
|
892
|
+
Subject: string;
|
|
893
|
+
Created: string;
|
|
894
|
+
Size: number;
|
|
895
|
+
Attachments: number;
|
|
896
|
+
Snippet: string;
|
|
897
|
+
}
|
|
898
|
+
interface MailpitMessage {
|
|
899
|
+
ID: string;
|
|
900
|
+
MessageID: string;
|
|
901
|
+
From: MailpitAddress | null;
|
|
902
|
+
To: MailpitAddress[] | null;
|
|
903
|
+
Cc: MailpitAddress[] | null;
|
|
904
|
+
Bcc: MailpitAddress[] | null;
|
|
905
|
+
ReplyTo: MailpitAddress[] | null;
|
|
906
|
+
Subject: string;
|
|
907
|
+
Date: string;
|
|
908
|
+
Text: string;
|
|
909
|
+
HTML: string;
|
|
910
|
+
Size: number;
|
|
911
|
+
Attachments: MailpitPart[] | null;
|
|
912
|
+
Inline: MailpitPart[] | null;
|
|
913
|
+
}
|
|
914
|
+
interface MailpitSearchParams {
|
|
915
|
+
query?: string;
|
|
916
|
+
start?: number;
|
|
917
|
+
limit?: number;
|
|
918
|
+
tz?: string;
|
|
919
|
+
}
|
|
920
|
+
interface MailpitSearchResult {
|
|
921
|
+
messages: MailpitMessageSummary[];
|
|
922
|
+
messagesCount: number;
|
|
923
|
+
}
|
|
924
|
+
declare class MailpitApi {
|
|
925
|
+
private neetoPlaywrightUtilities;
|
|
926
|
+
readonly baseUrl: string;
|
|
927
|
+
private readonly headers;
|
|
928
|
+
constructor(neetoPlaywrightUtilities: CustomCommands);
|
|
929
|
+
/**
|
|
930
|
+
*
|
|
931
|
+
* Used to authorize the Fastmail API and get the account details. There is usually no need to call this method since this is invoked when the fixture is setup and will save the credentials for all the future callback of mailerUtils methods.
|
|
932
|
+
*
|
|
933
|
+
* This method doesn't accept any arguments and doesn't return anything.
|
|
934
|
+
*
|
|
935
|
+
*/
|
|
936
|
+
authorizeAndSetAccountId: () => Promise<void>;
|
|
937
|
+
private warnOnUnexpectedResponse;
|
|
938
|
+
search: ({
|
|
939
|
+
query,
|
|
940
|
+
start,
|
|
941
|
+
limit,
|
|
942
|
+
tz
|
|
943
|
+
}: MailpitSearchParams) => Promise<MailpitSearchResult>;
|
|
944
|
+
getMessage: (id: string) => Promise<MailpitMessage | null>;
|
|
945
|
+
fetchRawMessage: (id: string) => Promise<Buffer<ArrayBufferLike> | null>;
|
|
946
|
+
deleteMessages: (ids: string[]) => Promise<void>;
|
|
947
|
+
}
|
|
873
948
|
declare class MemberApis {
|
|
874
949
|
private neetoPlaywrightUtilities;
|
|
875
950
|
private readonly teamMembersBaseUrl;
|
|
@@ -898,6 +973,7 @@ interface RailsEmail {
|
|
|
898
973
|
htmlBody?: string;
|
|
899
974
|
textBody?: string;
|
|
900
975
|
receivedAt: string;
|
|
976
|
+
messageId?: string;
|
|
901
977
|
attachments?: RailsEmailAttachment[];
|
|
902
978
|
}
|
|
903
979
|
interface BaseRailsEmailSearchParams {
|
|
@@ -1249,6 +1325,7 @@ interface FormattedList$1 {
|
|
|
1249
1325
|
subject: string;
|
|
1250
1326
|
attachments: Attachment$1[];
|
|
1251
1327
|
blobId: string;
|
|
1328
|
+
messageId?: string;
|
|
1252
1329
|
}
|
|
1253
1330
|
interface AttachmentDetails$1 {
|
|
1254
1331
|
filename: string | null;
|
|
@@ -1263,7 +1340,7 @@ declare class RailsEmailUtils {
|
|
|
1263
1340
|
private convertRailsEmailToFormattedList;
|
|
1264
1341
|
clearEmails: () => Promise<unknown>;
|
|
1265
1342
|
clearStaleEmails: () => Promise<unknown>;
|
|
1266
|
-
getLatestEmail: (searchParams: RailsEmailSearchParams) => Promise<
|
|
1343
|
+
getLatestEmail: (searchParams: RailsEmailSearchParams) => Promise<RailsEmail | null>;
|
|
1267
1344
|
listEmails: (searchParams?: RailsEmailSearchParams) => Promise<RailsEmail[]>;
|
|
1268
1345
|
/**
|
|
1269
1346
|
*
|
|
@@ -1403,6 +1480,10 @@ declare class RailsEmailUtils {
|
|
|
1403
1480
|
receivedAfter,
|
|
1404
1481
|
expectedEmailCount
|
|
1405
1482
|
}?: Partial<FindMessageFilterOptions$1> | undefined, shouldThrowErrorOnTimeout?: boolean) => Promise<FormattedList$1 | Record<string, never>>;
|
|
1483
|
+
getLatestMessageId: (subject: string, {
|
|
1484
|
+
timeout,
|
|
1485
|
+
receivedAfter
|
|
1486
|
+
}?: Partial<FindMessageFilterOptions$1> | undefined) => Promise<string | undefined>;
|
|
1406
1487
|
/**
|
|
1407
1488
|
*
|
|
1408
1489
|
* A helper method that is used to find the first code value from the matching email body. This method has been built to match the Neeto OTP emails.
|
|
@@ -1524,6 +1605,7 @@ declare class FastmailApi {
|
|
|
1524
1605
|
headers: FastmailHeaders;
|
|
1525
1606
|
accountId: string | undefined;
|
|
1526
1607
|
constructor(neetoPlaywrightUtilities: CustomCommands);
|
|
1608
|
+
private assertApiKey;
|
|
1527
1609
|
/**
|
|
1528
1610
|
*
|
|
1529
1611
|
* Used to authorize the Fastmail API and get the account details. There is usually no need to call this method since this is invoked when the fixture is setup and will save the credentials for all the future callback of mailerUtils methods.
|
|
@@ -1615,14 +1697,17 @@ interface FormattedList {
|
|
|
1615
1697
|
subject: string;
|
|
1616
1698
|
attachments: Attachment[];
|
|
1617
1699
|
blobId: string;
|
|
1700
|
+
messageId?: string;
|
|
1618
1701
|
}
|
|
1619
1702
|
declare class MailerUtils {
|
|
1620
1703
|
private neetoPlaywrightUtilities;
|
|
1621
1704
|
accountId: string | undefined;
|
|
1622
1705
|
fastmailApi: FastmailApi;
|
|
1706
|
+
mailpitApi: MailpitApi;
|
|
1623
1707
|
railsEmailUtils: RailsEmailUtils;
|
|
1624
1708
|
constructor(neetoPlaywrightUtilities: CustomCommands);
|
|
1625
1709
|
private queryEmail;
|
|
1710
|
+
private buildMessageBodies;
|
|
1626
1711
|
private getEmails;
|
|
1627
1712
|
/**
|
|
1628
1713
|
*
|
|
@@ -1800,6 +1885,10 @@ declare class MailerUtils {
|
|
|
1800
1885
|
*
|
|
1801
1886
|
*/
|
|
1802
1887
|
generateRandomEmail: () => string;
|
|
1888
|
+
getLatestMessageId: (subject: string, {
|
|
1889
|
+
timeout,
|
|
1890
|
+
receivedAfter
|
|
1891
|
+
}?: Partial<FindMessageFilterOptions> | undefined) => Promise<string | undefined>;
|
|
1803
1892
|
/**
|
|
1804
1893
|
*
|
|
1805
1894
|
* This method is used to return an attachment from the first email matching the search criteria. It supports filtering attachments by name, by MIME content-type, or both. If no matching attachment is found, an error is thrown.
|
|
@@ -1883,6 +1972,45 @@ declare class MailerUtils {
|
|
|
1883
1972
|
receivedAfter,
|
|
1884
1973
|
expectedEmailCount
|
|
1885
1974
|
}?: Partial<FindMessageFilterOptions> | undefined, shouldThrowErrorOnTimeout?: boolean) => Promise<AttachmentDetails | undefined>;
|
|
1975
|
+
private toIdentifiers;
|
|
1976
|
+
private toMailpitAttachments;
|
|
1977
|
+
private toFormattedList;
|
|
1978
|
+
private matchesSummaryCriteria;
|
|
1979
|
+
private warnOnNonMailpitRecipient;
|
|
1980
|
+
private queryMailpitEmails;
|
|
1981
|
+
private getEmailsV2;
|
|
1982
|
+
private pollForMailpitSummaries;
|
|
1983
|
+
listMessagesV2: (messageSearchCriteria?: Partial<MessageSearchCriteria> | undefined, listMessagesFilterCriteria?: Partial<ListMessagesFilterCriteria> | undefined) => Promise<FormattedList[]>;
|
|
1984
|
+
getEmailIdsV2: (messageSearchCriteria?: Partial<MessageSearchCriteria>, {
|
|
1985
|
+
timeout,
|
|
1986
|
+
receivedAfter,
|
|
1987
|
+
expectedEmailCount
|
|
1988
|
+
}?: Partial<FindMessageFilterOptions> | undefined, shouldThrowErrorOnTimeout?: boolean) => Promise<string[]>;
|
|
1989
|
+
findMessageV2: (messageSearchCriteria?: Partial<MessageSearchCriteria>, {
|
|
1990
|
+
timeout,
|
|
1991
|
+
receivedAfter,
|
|
1992
|
+
expectedEmailCount
|
|
1993
|
+
}?: Partial<FindMessageFilterOptions> | undefined, shouldThrowErrorOnTimeout?: boolean) => Promise<FormattedList | Record<string, never>>;
|
|
1994
|
+
findOtpFromEmailV2: ({
|
|
1995
|
+
email,
|
|
1996
|
+
subjectSubstring,
|
|
1997
|
+
timeout,
|
|
1998
|
+
receivedAfter,
|
|
1999
|
+
expectedEmailCount
|
|
2000
|
+
}: FindOtpFromEmailParams) => Promise<string | undefined>;
|
|
2001
|
+
generateRandomEmailV2: () => string;
|
|
2002
|
+
getLatestMessageIdV2: (subject: string, {
|
|
2003
|
+
timeout,
|
|
2004
|
+
receivedAfter
|
|
2005
|
+
}?: Partial<FindMessageFilterOptions> | undefined) => Promise<string | undefined>;
|
|
2006
|
+
getEmailAttachmentV2: ({
|
|
2007
|
+
name,
|
|
2008
|
+
type
|
|
2009
|
+
}: AttachmentFilter, messageSearchCriteria?: Partial<MessageSearchCriteria>, {
|
|
2010
|
+
timeout,
|
|
2011
|
+
receivedAfter,
|
|
2012
|
+
expectedEmailCount
|
|
2013
|
+
}?: Partial<FindMessageFilterOptions> | undefined, shouldThrowErrorOnTimeout?: boolean) => Promise<AttachmentDetails | undefined>;
|
|
1886
2014
|
}
|
|
1887
2015
|
/**
|
|
1888
2016
|
*
|
|
@@ -4067,6 +4195,11 @@ declare const CUSTOM_DOMAIN_SUFFIX = "aceinvoice.com";
|
|
|
4067
4195
|
* @endexample
|
|
4068
4196
|
*/
|
|
4069
4197
|
declare const ZAPIER_TEST_EMAIL: (product: string) => string;
|
|
4198
|
+
declare const MAILPIT_BASE_URL = "https://mailpit.neetodeployapp.com";
|
|
4199
|
+
declare const MAILPIT_DOMAIN_NAME = "mail.aceinvoice.com";
|
|
4200
|
+
declare const IS_MAILPIT_ENABLED: boolean;
|
|
4201
|
+
declare const mailpitDomainName: () => string;
|
|
4202
|
+
declare const ZAPIER_TEST_EMAIL_V2: (product: string) => string;
|
|
4070
4203
|
declare const SINGULAR: {
|
|
4071
4204
|
count: number;
|
|
4072
4205
|
};
|
|
@@ -9344,5 +9477,5 @@ interface Overrides {
|
|
|
9344
9477
|
* @endexample
|
|
9345
9478
|
*/
|
|
9346
9479
|
declare const definePlaywrightConfig: (overrides: Overrides) => PlaywrightTestConfig<{}, {}>;
|
|
9347
|
-
export { ACTIONS, ADMIN_PANEL_SELECTORS, ALL_RESOURCES, ANALYTICS_RESOURCES, API_KEYS_SELECTORS, API_ROUTES, APP_RESOURCES, AUDIT_LOGS_SELECTORS, ApiKeysApi, ApiKeysPage, AuditLogsPage, BASE_URL, CALENDAR_LABELS, CERTIFICATE_LIMIT_EXCEEDED_MESSAGE, CERTIFICATE_LIMIT_EXCEEDED_REGEXP, CHANGELOG_WIDGET_SELECTORS, CHAT_WIDGET_SELECTORS, CHAT_WIDGET_TEXTS, COLOR, COMMON_SELECTORS, COMMON_TEXTS, COMMUNITY_TEXTS, CREDENTIALS, CURRENT_TIME_RANGES, CUSTOM_DOMAIN_SELECTORS, CUSTOM_DOMAIN_SUFFIX, ColorPickerUtils, CustomCommands, CustomDomainApi, CustomDomainPage, DATE_FORMATS, DATE_PICKER_SELECTORS, DATE_RANGES, DATE_TEXTS, DEFAULT_WEBHOOKS_RESPONSE_TEXT, DESCRIPTION_EDITOR_TEXTS, EDITOR_VERIFY_TEXT_COLOR, EMBED_SELECTORS, EMOJI_LABEL, EMPTY_STORAGE_STATE, ENGAGE_TEXTS, ENVIRONMENT, EXAMPLE_URL, EXPANDED_FONT_SIZE, EXPORT_FILE_TYPES, EditorPage, EmailDeliveryUtils, EmbedBase, FILE_FORMATS, FONTS_RESOURCES, FONT_SIZE_SELECTORS, FROM_EMAIL_ENV_KEYS, GLOBAL_TRANSLATIONS_PATTERN, GOOGLE_ANALYTICS_SELECTORS, GOOGLE_CALENDAR_DATE_FORMAT, GOOGLE_LOGIN_SELECTORS, GOOGLE_LOGIN_TEXTS, GOOGLE_SHEETS_SELECTORS, GooglePage, HELP_CENTER_ROUTES, HELP_CENTER_SELECTORS, HelpAndProfilePage, INTEGRATIONS_TEXTS, INTEGRATION_SELECTORS, IPRestrictionsPage, IP_RESTRICTIONS_SELECTORS, IS_CI, IS_DEV_ENV, IS_STAGING_ENV, ImageUploader, IntegrationBase, IpRestrictionsApi, KEYBOARD_SHORTCUTS_SELECTORS, KEYBOARD_SHORTCUT_TEST_CASES, LIST_MODIFIER_SELECTORS, LIST_MODIFIER_TAGS, LOGIN_SELECTORS, MEMBER_FORM_SELECTORS, MEMBER_SELECTORS, MEMBER_TEXTS, MERGE_TAGS_SELECTORS, MICROSOFT_LOGIN_SELECTORS, MICROSOFT_LOGIN_TEXTS, MailerUtils, Member, MemberApis, MicrosoftPage, NEETO_AUTH_BASE_URL, NEETO_EDITOR_SELECTORS, NEETO_FILTERS_SELECTORS, NEETO_IMAGE_UPLOADER_SELECTORS, NEETO_ROUTES, NEETO_SEO_SELECTORS, NEETO_TEXT_MODIFIER_SELECTORS, NeetoAuthServer, NeetoChatWidget, NeetoEmailDeliveryApi, NeetoTowerApi, ONBOARDING_SELECTORS, ORGANIZATION_TEXTS, OTP_EMAIL_PATTERN, OrganizationPage, PAST_TIME_RANGES, PHONE_NUMBER_FORMATS, PLURAL, PRODUCT_ROLES_ROUTE_MAP, PROFILE_LINKS, PROFILE_SECTION_SELECTORS, PROJECT_NAMES, PROJECT_TRANSLATIONS_PATH, ROLES_SELECTORS, ROUTES, RailsEmailApiClient, RailsEmailUtils, RoleApis, RolesPage, SIGNUP_SELECTORS, SINGULAR, SLACK_DATA_QA_SELECTORS, SLACK_DEFAULT_CHANNEL, SLACK_SELECTORS, SLACK_WEB_TEXTS, STATUS_TEXTS, STORAGE_STATE, SecurityApi, SidebarSection, SlackApi, SlackPage, TABLE_SELECTORS, TAB_SELECTORS, TAGS_SELECTORS, TEAM_MEMBER_TEXTS, TEXT_MODIFIER_ROLES, TEXT_MODIFIER_SELECTORS, TEXT_MODIFIER_TAGS, THANK_YOU_SELECTORS, THEMES_SELECTORS, THEMES_TEXTS, THIRD_PARTY_RESOURCES, THIRD_PARTY_ROUTES, TIME_RANGES, TOASTR_MESSAGES, TWILIO_SELECTORS, TagsApi, TagsPage, TeamMembers, ThankYouApi, ThankYouPage, TwilioApi, USER_AGENTS, WEBHOOK_SELECTORS, WebhookSiteApi, WebhooksPage, ZAPIER_LIMIT_EXHAUSTED_MESSAGE, ZAPIER_SELECTORS, ZAPIER_TEST_EMAIL, ZAPIER_WEB_TEXTS, ZapierPage, authenticateUser, baseURLGenerator, basicHTMLContent, clearCredentials, commands, cpuThrottlingUsingCDP, createOrganizationViaRake, currencyUtils, dataQa, decodeQRCodeFromFile, definePlaywrightConfig, executeWithThrottledResources, extractSubdomainFromError, filterUtils, fixedMenuSelector, generatePhoneNumber, generatePhoneNumberDetails, generateRandomBypassEmail, generateRandomFile, generateStagingData, getByDataQA, getClipboardContent, getDirname, getFormattedPhoneNumber, getFullUrl, getGlobalUserProps, getGlobalUserState, getImagePathAndName, getIsoCodeFromPhoneCode, getListCount, globalShortcuts, grantClipboardPermissions, hexToRGB, hexToRGBA, i18nFixture, imageRegex, initializeCredentials, initializeTestData, initializeTotp, isGithubIssueOpen, isStagingOrganizationExpired, joinHyphenCase, joinString, login, networkConditions, networkThrottlingUsingCDP, optionSelector, readFileSyncIfExists, removeCredentialFile, serializeFileForBrowser, shouldSkipCustomDomainSetup, shouldSkipSetupAndTeardown, simulateClickWithDelay, simulateTypingWithDelay, skipTest, squish, _default as stealthTest, tableUtils, toCamelCase, updateCredentials, warmup, withCookieCache, writeDataToFile };
|
|
9480
|
+
export { ACTIONS, ADMIN_PANEL_SELECTORS, ALL_RESOURCES, ANALYTICS_RESOURCES, API_KEYS_SELECTORS, API_ROUTES, APP_RESOURCES, AUDIT_LOGS_SELECTORS, ApiKeysApi, ApiKeysPage, AuditLogsPage, BASE_URL, CALENDAR_LABELS, CERTIFICATE_LIMIT_EXCEEDED_MESSAGE, CERTIFICATE_LIMIT_EXCEEDED_REGEXP, CHANGELOG_WIDGET_SELECTORS, CHAT_WIDGET_SELECTORS, CHAT_WIDGET_TEXTS, COLOR, COMMON_SELECTORS, COMMON_TEXTS, COMMUNITY_TEXTS, CREDENTIALS, CURRENT_TIME_RANGES, CUSTOM_DOMAIN_SELECTORS, CUSTOM_DOMAIN_SUFFIX, ColorPickerUtils, CustomCommands, CustomDomainApi, CustomDomainPage, DATE_FORMATS, DATE_PICKER_SELECTORS, DATE_RANGES, DATE_TEXTS, DEFAULT_WEBHOOKS_RESPONSE_TEXT, DESCRIPTION_EDITOR_TEXTS, EDITOR_VERIFY_TEXT_COLOR, EMBED_SELECTORS, EMOJI_LABEL, EMPTY_STORAGE_STATE, ENGAGE_TEXTS, ENVIRONMENT, EXAMPLE_URL, EXPANDED_FONT_SIZE, EXPORT_FILE_TYPES, EditorPage, EmailDeliveryUtils, EmbedBase, FILE_FORMATS, FONTS_RESOURCES, FONT_SIZE_SELECTORS, FROM_EMAIL_ENV_KEYS, GLOBAL_TRANSLATIONS_PATTERN, GOOGLE_ANALYTICS_SELECTORS, GOOGLE_CALENDAR_DATE_FORMAT, GOOGLE_LOGIN_SELECTORS, GOOGLE_LOGIN_TEXTS, GOOGLE_SHEETS_SELECTORS, GooglePage, HELP_CENTER_ROUTES, HELP_CENTER_SELECTORS, HelpAndProfilePage, INTEGRATIONS_TEXTS, INTEGRATION_SELECTORS, IPRestrictionsPage, IP_RESTRICTIONS_SELECTORS, IS_CI, IS_DEV_ENV, IS_MAILPIT_ENABLED, IS_STAGING_ENV, ImageUploader, IntegrationBase, IpRestrictionsApi, KEYBOARD_SHORTCUTS_SELECTORS, KEYBOARD_SHORTCUT_TEST_CASES, LIST_MODIFIER_SELECTORS, LIST_MODIFIER_TAGS, LOGIN_SELECTORS, MAILPIT_BASE_URL, MAILPIT_DOMAIN_NAME, MEMBER_FORM_SELECTORS, MEMBER_SELECTORS, MEMBER_TEXTS, MERGE_TAGS_SELECTORS, MICROSOFT_LOGIN_SELECTORS, MICROSOFT_LOGIN_TEXTS, MailerUtils, MailpitApi, Member, MemberApis, MicrosoftPage, NEETO_AUTH_BASE_URL, NEETO_EDITOR_SELECTORS, NEETO_FILTERS_SELECTORS, NEETO_IMAGE_UPLOADER_SELECTORS, NEETO_ROUTES, NEETO_SEO_SELECTORS, NEETO_TEXT_MODIFIER_SELECTORS, NeetoAuthServer, NeetoChatWidget, NeetoEmailDeliveryApi, NeetoTowerApi, ONBOARDING_SELECTORS, ORGANIZATION_TEXTS, OTP_EMAIL_PATTERN, OrganizationPage, PAST_TIME_RANGES, PHONE_NUMBER_FORMATS, PLURAL, PRODUCT_ROLES_ROUTE_MAP, PROFILE_LINKS, PROFILE_SECTION_SELECTORS, PROJECT_NAMES, PROJECT_TRANSLATIONS_PATH, ROLES_SELECTORS, ROUTES, RailsEmailApiClient, RailsEmailUtils, RoleApis, RolesPage, SIGNUP_SELECTORS, SINGULAR, SLACK_DATA_QA_SELECTORS, SLACK_DEFAULT_CHANNEL, SLACK_SELECTORS, SLACK_WEB_TEXTS, STATUS_TEXTS, STORAGE_STATE, SecurityApi, SidebarSection, SlackApi, SlackPage, TABLE_SELECTORS, TAB_SELECTORS, TAGS_SELECTORS, TEAM_MEMBER_TEXTS, TEXT_MODIFIER_ROLES, TEXT_MODIFIER_SELECTORS, TEXT_MODIFIER_TAGS, THANK_YOU_SELECTORS, THEMES_SELECTORS, THEMES_TEXTS, THIRD_PARTY_RESOURCES, THIRD_PARTY_ROUTES, TIME_RANGES, TOASTR_MESSAGES, TWILIO_SELECTORS, TagsApi, TagsPage, TeamMembers, ThankYouApi, ThankYouPage, TwilioApi, USER_AGENTS, WEBHOOK_SELECTORS, WebhookSiteApi, WebhooksPage, ZAPIER_LIMIT_EXHAUSTED_MESSAGE, ZAPIER_SELECTORS, ZAPIER_TEST_EMAIL, ZAPIER_TEST_EMAIL_V2, ZAPIER_WEB_TEXTS, ZapierPage, authenticateUser, baseURLGenerator, basicHTMLContent, clearCredentials, commands, cpuThrottlingUsingCDP, createOrganizationViaRake, currencyUtils, dataQa, decodeQRCodeFromFile, definePlaywrightConfig, executeWithThrottledResources, extractSubdomainFromError, filterUtils, fixedMenuSelector, generatePhoneNumber, generatePhoneNumberDetails, generateRandomBypassEmail, generateRandomFile, generateStagingData, getByDataQA, getClipboardContent, getDirname, getFormattedPhoneNumber, getFullUrl, getGlobalUserProps, getGlobalUserState, getImagePathAndName, getIsoCodeFromPhoneCode, getListCount, globalShortcuts, grantClipboardPermissions, hexToRGB, hexToRGBA, i18nFixture, imageRegex, initializeCredentials, initializeTestData, initializeTotp, isGithubIssueOpen, isStagingOrganizationExpired, joinHyphenCase, joinString, login, mailpitDomainName, networkConditions, networkThrottlingUsingCDP, optionSelector, readFileSyncIfExists, removeCredentialFile, serializeFileForBrowser, shouldSkipCustomDomainSetup, shouldSkipSetupAndTeardown, simulateClickWithDelay, simulateTypingWithDelay, skipTest, squish, _default as stealthTest, tableUtils, toCamelCase, updateCredentials, warmup, withCookieCache, writeDataToFile };
|
|
9348
9481
|
export type { BaseThemeStyle, BaseThemeStyleType, ColumnMenuAction, CountryProps, CustomFixture, EmailDeliveryConnectParams, EmailDeliveryProvider, EmailDeliveryVerifiedEmail, EmailDeliveryVerifyEmailParams, EmailDeliveryVerifyEmailResponse, EmailMatchCriteria, IntroPageThemeStyle, IntroPageThemeStyleType, OAuthEmailDeliveryProvider, ProjectName, ThemeCategory, ValueOf };
|
package/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { isPresent, keysToSnakeCase, hyphenate, isNotPresent, noop as noop$2, humanize, findBy, dynamicArray, truncate, isNotEmpty, isNotEqualDeep, randomPick } from '@bigbinary/neeto-cist';
|
|
2
2
|
import { faker } from '@faker-js/faker';
|
|
3
3
|
import * as fs from 'fs';
|
|
4
4
|
import fs__default, { readFileSync, promises, existsSync, writeFileSync, unlinkSync, mkdirSync, rmSync, createWriteStream } from 'fs';
|
|
@@ -299,6 +299,162 @@ class IpRestrictionsApi {
|
|
|
299
299
|
});
|
|
300
300
|
}
|
|
301
301
|
|
|
302
|
+
const ENVIRONMENT = {
|
|
303
|
+
development: "development",
|
|
304
|
+
staging: "staging",
|
|
305
|
+
review: "review",
|
|
306
|
+
};
|
|
307
|
+
const EXAMPLE_URL = "https://example.com";
|
|
308
|
+
const IS_STAGING_ENV = process.env.TEST_ENV === ENVIRONMENT.staging;
|
|
309
|
+
const IS_DEV_ENV = process.env.TEST_ENV === ENVIRONMENT.development;
|
|
310
|
+
const IS_CI = isPresent(process.env.NEETO_CI_JOB_ID);
|
|
311
|
+
const DEFAULT_WEBHOOKS_RESPONSE_TEXT = JSON.stringify({ success: true });
|
|
312
|
+
const STORAGE_STATE = "./e2e/auth/user.json";
|
|
313
|
+
const GLOBAL_TRANSLATIONS_PATTERN = "../node_modules/@bigbinary/**/translations/en.json";
|
|
314
|
+
const PROJECT_TRANSLATIONS_PATH = "../app/javascript/src/translations/en.json";
|
|
315
|
+
const CREDENTIALS = {
|
|
316
|
+
firstName: "Oliver",
|
|
317
|
+
lastName: "Smith",
|
|
318
|
+
name: "Oliver Smith",
|
|
319
|
+
email: "oliver@example.com",
|
|
320
|
+
password: "welcome",
|
|
321
|
+
subdomainName: "spinkart",
|
|
322
|
+
};
|
|
323
|
+
const OTP_EMAIL_PATTERN = "Your login code is";
|
|
324
|
+
const SLACK_DEFAULT_CHANNEL = "general";
|
|
325
|
+
const CUSTOM_DOMAIN_SUFFIX = "aceinvoice.com";
|
|
326
|
+
const ZAPIER_TEST_EMAIL = (product) => `neeto-${product}-zapier-test@${process.env.FASTMAIL_DOMAIN_NAME}`;
|
|
327
|
+
const MAILPIT_BASE_URL = "https://mailpit.neetodeployapp.com";
|
|
328
|
+
const MAILPIT_DOMAIN_NAME = "mail.aceinvoice.com";
|
|
329
|
+
const IS_MAILPIT_ENABLED = isPresent(process.env.MAILPIT_DOMAIN_NAME);
|
|
330
|
+
const mailpitDomainName = () => process.env.MAILPIT_DOMAIN_NAME || MAILPIT_DOMAIN_NAME;
|
|
331
|
+
const ZAPIER_TEST_EMAIL_V2 = (product) => `neeto-${product}-zapier-test@${mailpitDomainName()}`;
|
|
332
|
+
// constants for translation
|
|
333
|
+
const SINGULAR = { count: 1 };
|
|
334
|
+
const PLURAL = { count: 2 };
|
|
335
|
+
const COLOR = {
|
|
336
|
+
transparent: "rgba(0, 0, 0, 0)",
|
|
337
|
+
softBlue: "rgb(230, 244, 255)",
|
|
338
|
+
};
|
|
339
|
+
const DATE_TEXTS = { now: "Now", nextYear: "next-year" };
|
|
340
|
+
const EMPTY_STORAGE_STATE = {
|
|
341
|
+
storageState: { cookies: [], origins: [] },
|
|
342
|
+
};
|
|
343
|
+
const CURRENT_TIME_RANGES = {
|
|
344
|
+
last24Hours: "Last 24 hours",
|
|
345
|
+
thisWeek: "This week",
|
|
346
|
+
thisMonth: "This month",
|
|
347
|
+
thisYear: "This year",
|
|
348
|
+
thisQuarter: "This quarter",
|
|
349
|
+
last30Days: "Last 30 days",
|
|
350
|
+
last7Days: "Last 7 days",
|
|
351
|
+
};
|
|
352
|
+
const PAST_TIME_RANGES = {
|
|
353
|
+
lastWeek: "Last week",
|
|
354
|
+
lastMonth: "Last month",
|
|
355
|
+
lastYear: "Last year",
|
|
356
|
+
lastQuarter: "Last quarter",
|
|
357
|
+
};
|
|
358
|
+
const TIME_RANGES = {
|
|
359
|
+
...PAST_TIME_RANGES,
|
|
360
|
+
...CURRENT_TIME_RANGES,
|
|
361
|
+
customDuration: "Custom duration",
|
|
362
|
+
};
|
|
363
|
+
const DATE_RANGES = {
|
|
364
|
+
...PAST_TIME_RANGES,
|
|
365
|
+
...CURRENT_TIME_RANGES,
|
|
366
|
+
after: "After",
|
|
367
|
+
before: "Before",
|
|
368
|
+
customDateRange: "Custom date range",
|
|
369
|
+
};
|
|
370
|
+
const CERTIFICATE_LIMIT_EXCEEDED_REGEXP = `too many certificates \\(\\d+\\) already issued for "${CUSTOM_DOMAIN_SUFFIX}"`;
|
|
371
|
+
const CERTIFICATE_LIMIT_EXCEEDED_MESSAGE = "Certificate limit exceeded for custom domain";
|
|
372
|
+
const EXPORT_FILE_TYPES = {
|
|
373
|
+
pdf: "pdf",
|
|
374
|
+
excel: "excel",
|
|
375
|
+
csv: "csv",
|
|
376
|
+
};
|
|
377
|
+
const CALENDAR_LABELS = {
|
|
378
|
+
month: "month panel",
|
|
379
|
+
year: "year panel",
|
|
380
|
+
};
|
|
381
|
+
const DATE_FORMATS = {
|
|
382
|
+
month: "MMM",
|
|
383
|
+
year: "YYYY",
|
|
384
|
+
date: "DD/MM/YYYY",
|
|
385
|
+
calendarDate: "YYYY-MM-DD",
|
|
386
|
+
};
|
|
387
|
+
|
|
388
|
+
const EMPTY_SEARCH_RESULT = {
|
|
389
|
+
messages: [],
|
|
390
|
+
messagesCount: 0,
|
|
391
|
+
};
|
|
392
|
+
class MailpitApi {
|
|
393
|
+
neetoPlaywrightUtilities;
|
|
394
|
+
baseUrl;
|
|
395
|
+
headers;
|
|
396
|
+
constructor(neetoPlaywrightUtilities) {
|
|
397
|
+
this.neetoPlaywrightUtilities = neetoPlaywrightUtilities;
|
|
398
|
+
this.baseUrl = (process.env.MAILPIT_BASE_URL || MAILPIT_BASE_URL).replace(/\/+$/, "");
|
|
399
|
+
const { MAILPIT_USERNAME, MAILPIT_PASSWORD } = process.env;
|
|
400
|
+
this.headers =
|
|
401
|
+
MAILPIT_USERNAME && MAILPIT_PASSWORD
|
|
402
|
+
? {
|
|
403
|
+
Authorization: `Basic ${Buffer.from(`${MAILPIT_USERNAME}:${MAILPIT_PASSWORD}`).toString("base64")}`,
|
|
404
|
+
}
|
|
405
|
+
: {};
|
|
406
|
+
}
|
|
407
|
+
authorizeAndSetAccountId = async () => { };
|
|
408
|
+
warnOnUnexpectedResponse = (endpoint, response) => {
|
|
409
|
+
if (response.ok() || response.status() === 404)
|
|
410
|
+
return;
|
|
411
|
+
if (response.status() === 401) {
|
|
412
|
+
console.warn(`Mailpit rejected the credentials for ${endpoint}. Set MAILPIT_USERNAME and MAILPIT_PASSWORD to the basic auth credentials of ${this.baseUrl}, otherwise every email lookup will time out.`);
|
|
413
|
+
return;
|
|
414
|
+
}
|
|
415
|
+
console.warn(`Mailpit responded with ${response.status()} for ${endpoint}. Treating it as no result, so an email lookup may time out even though the email exists.`);
|
|
416
|
+
};
|
|
417
|
+
search = async ({ query, start = 0, limit = 50, tz = "UTC", }) => {
|
|
418
|
+
const isSearch = Boolean(query);
|
|
419
|
+
const endpoint = `/api/v1/${isSearch ? "search" : "messages"}`;
|
|
420
|
+
const response = await this.neetoPlaywrightUtilities.request.get(`${this.baseUrl}${endpoint}`, {
|
|
421
|
+
params: isSearch
|
|
422
|
+
? { query: query, start, limit, tz }
|
|
423
|
+
: { start, limit },
|
|
424
|
+
headers: this.headers,
|
|
425
|
+
failOnStatusCode: false,
|
|
426
|
+
timeout: 15_000,
|
|
427
|
+
});
|
|
428
|
+
this.warnOnUnexpectedResponse(endpoint, response);
|
|
429
|
+
if (!response.ok())
|
|
430
|
+
return EMPTY_SEARCH_RESULT;
|
|
431
|
+
const { messages, messages_count: messagesCount } = await response.json();
|
|
432
|
+
return { messages: messages ?? [], messagesCount: messagesCount ?? 0 };
|
|
433
|
+
};
|
|
434
|
+
getMessage = async (id) => {
|
|
435
|
+
const endpoint = `/api/v1/message/${id}`;
|
|
436
|
+
const response = await this.neetoPlaywrightUtilities.request.get(`${this.baseUrl}${endpoint}`, { headers: this.headers, failOnStatusCode: false, timeout: 15_000 });
|
|
437
|
+
this.warnOnUnexpectedResponse(endpoint, response);
|
|
438
|
+
return response.ok() ? await response.json() : null;
|
|
439
|
+
};
|
|
440
|
+
fetchRawMessage = async (id) => {
|
|
441
|
+
const endpoint = `/api/v1/message/${id}/raw`;
|
|
442
|
+
const response = await this.neetoPlaywrightUtilities.request.get(`${this.baseUrl}${endpoint}`, { headers: this.headers, failOnStatusCode: false, timeout: 15_000 });
|
|
443
|
+
this.warnOnUnexpectedResponse(endpoint, response);
|
|
444
|
+
return response.ok() ? await response.body() : null;
|
|
445
|
+
};
|
|
446
|
+
deleteMessages = async (ids) => {
|
|
447
|
+
if (!ids?.length)
|
|
448
|
+
throw new Error("MailpitApi.deleteMessages requires a non-empty list of message IDs. Mailpit deletes every stored message when the list is empty, and the inbox is shared across neeto products.");
|
|
449
|
+
await this.neetoPlaywrightUtilities.request.delete(`${this.baseUrl}/api/v1/messages`, {
|
|
450
|
+
data: { IDs: ids },
|
|
451
|
+
headers: this.headers,
|
|
452
|
+
failOnStatusCode: false,
|
|
453
|
+
timeout: 15_000,
|
|
454
|
+
});
|
|
455
|
+
};
|
|
456
|
+
}
|
|
457
|
+
|
|
302
458
|
class MemberApis {
|
|
303
459
|
neetoPlaywrightUtilities;
|
|
304
460
|
teamMembersBaseUrl;
|
|
@@ -351,6 +507,7 @@ class RailsEmailApiClient {
|
|
|
351
507
|
htmlBody: raw.html_body,
|
|
352
508
|
textBody: raw.text_body,
|
|
353
509
|
receivedAt: raw.received_at,
|
|
510
|
+
...(raw.message_id && { messageId: raw.message_id }),
|
|
354
511
|
attachments: raw.attachments?.map(({ filename, mime_type, data }) => ({
|
|
355
512
|
name: filename,
|
|
356
513
|
type: mime_type,
|
|
@@ -477,87 +634,6 @@ class TagsApi {
|
|
|
477
634
|
});
|
|
478
635
|
}
|
|
479
636
|
|
|
480
|
-
const ENVIRONMENT = {
|
|
481
|
-
development: "development",
|
|
482
|
-
staging: "staging",
|
|
483
|
-
review: "review",
|
|
484
|
-
};
|
|
485
|
-
const EXAMPLE_URL = "https://example.com";
|
|
486
|
-
const IS_STAGING_ENV = process.env.TEST_ENV === ENVIRONMENT.staging;
|
|
487
|
-
const IS_DEV_ENV = process.env.TEST_ENV === ENVIRONMENT.development;
|
|
488
|
-
const IS_CI = isPresent(process.env.NEETO_CI_JOB_ID);
|
|
489
|
-
const DEFAULT_WEBHOOKS_RESPONSE_TEXT = JSON.stringify({ success: true });
|
|
490
|
-
const STORAGE_STATE = "./e2e/auth/user.json";
|
|
491
|
-
const GLOBAL_TRANSLATIONS_PATTERN = "../node_modules/@bigbinary/**/translations/en.json";
|
|
492
|
-
const PROJECT_TRANSLATIONS_PATH = "../app/javascript/src/translations/en.json";
|
|
493
|
-
const CREDENTIALS = {
|
|
494
|
-
firstName: "Oliver",
|
|
495
|
-
lastName: "Smith",
|
|
496
|
-
name: "Oliver Smith",
|
|
497
|
-
email: "oliver@example.com",
|
|
498
|
-
password: "welcome",
|
|
499
|
-
subdomainName: "spinkart",
|
|
500
|
-
};
|
|
501
|
-
const OTP_EMAIL_PATTERN = "Your login code is";
|
|
502
|
-
const SLACK_DEFAULT_CHANNEL = "general";
|
|
503
|
-
const CUSTOM_DOMAIN_SUFFIX = "aceinvoice.com";
|
|
504
|
-
const ZAPIER_TEST_EMAIL = (product) => `neeto-${product}-zapier-test@${process.env.FASTMAIL_DOMAIN_NAME}`;
|
|
505
|
-
// constants for translation
|
|
506
|
-
const SINGULAR = { count: 1 };
|
|
507
|
-
const PLURAL = { count: 2 };
|
|
508
|
-
const COLOR = {
|
|
509
|
-
transparent: "rgba(0, 0, 0, 0)",
|
|
510
|
-
softBlue: "rgb(230, 244, 255)",
|
|
511
|
-
};
|
|
512
|
-
const DATE_TEXTS = { now: "Now", nextYear: "next-year" };
|
|
513
|
-
const EMPTY_STORAGE_STATE = {
|
|
514
|
-
storageState: { cookies: [], origins: [] },
|
|
515
|
-
};
|
|
516
|
-
const CURRENT_TIME_RANGES = {
|
|
517
|
-
last24Hours: "Last 24 hours",
|
|
518
|
-
thisWeek: "This week",
|
|
519
|
-
thisMonth: "This month",
|
|
520
|
-
thisYear: "This year",
|
|
521
|
-
thisQuarter: "This quarter",
|
|
522
|
-
last30Days: "Last 30 days",
|
|
523
|
-
last7Days: "Last 7 days",
|
|
524
|
-
};
|
|
525
|
-
const PAST_TIME_RANGES = {
|
|
526
|
-
lastWeek: "Last week",
|
|
527
|
-
lastMonth: "Last month",
|
|
528
|
-
lastYear: "Last year",
|
|
529
|
-
lastQuarter: "Last quarter",
|
|
530
|
-
};
|
|
531
|
-
const TIME_RANGES = {
|
|
532
|
-
...PAST_TIME_RANGES,
|
|
533
|
-
...CURRENT_TIME_RANGES,
|
|
534
|
-
customDuration: "Custom duration",
|
|
535
|
-
};
|
|
536
|
-
const DATE_RANGES = {
|
|
537
|
-
...PAST_TIME_RANGES,
|
|
538
|
-
...CURRENT_TIME_RANGES,
|
|
539
|
-
after: "After",
|
|
540
|
-
before: "Before",
|
|
541
|
-
customDateRange: "Custom date range",
|
|
542
|
-
};
|
|
543
|
-
const CERTIFICATE_LIMIT_EXCEEDED_REGEXP = `too many certificates \\(\\d+\\) already issued for "${CUSTOM_DOMAIN_SUFFIX}"`;
|
|
544
|
-
const CERTIFICATE_LIMIT_EXCEEDED_MESSAGE = "Certificate limit exceeded for custom domain";
|
|
545
|
-
const EXPORT_FILE_TYPES = {
|
|
546
|
-
pdf: "pdf",
|
|
547
|
-
excel: "excel",
|
|
548
|
-
csv: "csv",
|
|
549
|
-
};
|
|
550
|
-
const CALENDAR_LABELS = {
|
|
551
|
-
month: "month panel",
|
|
552
|
-
year: "year panel",
|
|
553
|
-
};
|
|
554
|
-
const DATE_FORMATS = {
|
|
555
|
-
month: "MMM",
|
|
556
|
-
year: "YYYY",
|
|
557
|
-
date: "DD/MM/YYYY",
|
|
558
|
-
calendarDate: "YYYY-MM-DD",
|
|
559
|
-
};
|
|
560
|
-
|
|
561
637
|
const THANK_YOU_URL = "/neeto_thank_you/thank_you_configurations";
|
|
562
638
|
class ThankYouApi {
|
|
563
639
|
neetoPlaywrightUtilities;
|
|
@@ -69536,16 +69612,19 @@ class FastmailApi {
|
|
|
69536
69612
|
accountId;
|
|
69537
69613
|
constructor(neetoPlaywrightUtilities) {
|
|
69538
69614
|
this.neetoPlaywrightUtilities = neetoPlaywrightUtilities;
|
|
69539
|
-
if (!IS_DEV_ENV && !process.env.NEETO_AUTOMATION_FASTMAIL_API_KEY)
|
|
69540
|
-
throw new Error("Please set the environment variable NEETO_AUTOMATION_FASTMAIL_API_KEYS. Credentials can be found in the Automation Credentials vault in the BigBinary 1Password account.");
|
|
69541
69615
|
this.headers = {
|
|
69542
69616
|
"Content-Type": "application/json",
|
|
69543
69617
|
Authorization: `Bearer ${process.env.NEETO_AUTOMATION_FASTMAIL_API_KEY}`,
|
|
69544
69618
|
};
|
|
69545
69619
|
}
|
|
69620
|
+
assertApiKey = () => {
|
|
69621
|
+
if (!process.env.NEETO_AUTOMATION_FASTMAIL_API_KEY)
|
|
69622
|
+
throw new Error("Please set the environment variable NEETO_AUTOMATION_FASTMAIL_API_KEY. Credentials can be found in the Automation Credentials vault in the BigBinary 1Password account.");
|
|
69623
|
+
};
|
|
69546
69624
|
authorizeAndSetAccountId = async () => {
|
|
69547
69625
|
if (IS_DEV_ENV)
|
|
69548
69626
|
return;
|
|
69627
|
+
this.assertApiKey();
|
|
69549
69628
|
const response = await this.neetoPlaywrightUtilities.apiRequest({
|
|
69550
69629
|
method: "get",
|
|
69551
69630
|
url: "https://api.fastmail.com/.well-known/jmap",
|
|
@@ -69555,6 +69634,7 @@ class FastmailApi {
|
|
|
69555
69634
|
this.accountId = accountId;
|
|
69556
69635
|
};
|
|
69557
69636
|
apiRequest = async (method, body) => {
|
|
69637
|
+
this.assertApiKey();
|
|
69558
69638
|
const response = await this.neetoPlaywrightUtilities.apiRequest({
|
|
69559
69639
|
method: "post",
|
|
69560
69640
|
url: "https://api.fastmail.com/jmap/api/",
|
|
@@ -69653,6 +69733,7 @@ class RailsEmailUtils {
|
|
|
69653
69733
|
type: att.type,
|
|
69654
69734
|
})) || [],
|
|
69655
69735
|
blobId: "",
|
|
69736
|
+
...(railsEmail.messageId && { messageId: railsEmail.messageId }),
|
|
69656
69737
|
};
|
|
69657
69738
|
};
|
|
69658
69739
|
clearEmails = () => this.railsEmailClient.clearEmails();
|
|
@@ -69662,7 +69743,7 @@ class RailsEmailUtils {
|
|
|
69662
69743
|
};
|
|
69663
69744
|
getLatestEmail = async (searchParams) => {
|
|
69664
69745
|
await this.clearStaleEmails();
|
|
69665
|
-
|
|
69746
|
+
return this.railsEmailClient.getLatestEmail(searchParams);
|
|
69666
69747
|
};
|
|
69667
69748
|
listEmails = (searchParams) => this.railsEmailClient.listEmails(searchParams);
|
|
69668
69749
|
listMessages = async (messageSearchCriteria = {}, { receivedAfter = new Date(new Date().valueOf() - 60 * 60 * 1000), } = {}) => {
|
|
@@ -69702,6 +69783,12 @@ class RailsEmailUtils {
|
|
|
69702
69783
|
}
|
|
69703
69784
|
return email;
|
|
69704
69785
|
};
|
|
69786
|
+
getLatestMessageId = async (subject, { timeout = 10_000, receivedAfter = new Date(new Date().valueOf() - 60 * 1000), } = {}) => {
|
|
69787
|
+
const email = await this.findMessage({ subject }, { timeout, receivedAfter }, false);
|
|
69788
|
+
if (!("messageId" in email) || !email.messageId)
|
|
69789
|
+
return undefined;
|
|
69790
|
+
return email.messageId.replace(/^<|>$/g, "");
|
|
69791
|
+
};
|
|
69705
69792
|
findOtpFromEmail = async ({ email, subjectSubstring = OTP_EMAIL_PATTERN, timeout = 10_000, receivedAfter = new Date(), expectedEmailCount = 1, }) => {
|
|
69706
69793
|
const otp = await this.neetoPlaywrightUtilities.executeRecursively({
|
|
69707
69794
|
callback: async () => {
|
|
@@ -69772,14 +69859,23 @@ class RailsEmailUtils {
|
|
|
69772
69859
|
}
|
|
69773
69860
|
|
|
69774
69861
|
const dateTimeOneHourAgo = () => new Date(new Date().valueOf() - 60 * 60 * 1000);
|
|
69862
|
+
const MAILPIT_SEARCH_DATE_MARGIN = 24 * 60 * 60 * 1000;
|
|
69863
|
+
const toMailpitSearchDate = (date) => new Date(date.valueOf() - MAILPIT_SEARCH_DATE_MARGIN)
|
|
69864
|
+
.toISOString()
|
|
69865
|
+
.slice(0, 10)
|
|
69866
|
+
.replace(/-/g, "/");
|
|
69867
|
+
const toMailpitSearchTerm = (value) => `"${value.replace(/"/g, "")}"`;
|
|
69868
|
+
const mailpitTimeoutError = (messageSearchCriteria, receivedAfter, expectedEmailCount) => new Error(`Timed out waiting for matching message. Searched Mailpit for ${JSON.stringify(messageSearchCriteria)} received after ${receivedAfter.toISOString()}, expecting at least ${expectedEmailCount}.`);
|
|
69775
69869
|
class MailerUtils {
|
|
69776
69870
|
neetoPlaywrightUtilities;
|
|
69777
69871
|
accountId;
|
|
69778
69872
|
fastmailApi;
|
|
69873
|
+
mailpitApi;
|
|
69779
69874
|
railsEmailUtils;
|
|
69780
69875
|
constructor(neetoPlaywrightUtilities) {
|
|
69781
69876
|
this.neetoPlaywrightUtilities = neetoPlaywrightUtilities;
|
|
69782
69877
|
this.fastmailApi = new FastmailApi(neetoPlaywrightUtilities);
|
|
69878
|
+
this.mailpitApi = new MailpitApi(neetoPlaywrightUtilities);
|
|
69783
69879
|
this.railsEmailUtils = new RailsEmailUtils(neetoPlaywrightUtilities);
|
|
69784
69880
|
}
|
|
69785
69881
|
queryEmail = async (messageSearchCriteria, { receivedAfter = dateTimeOneHourAgo(), page = 1, itemsPerPage = 50, }) => {
|
|
@@ -69805,9 +69901,29 @@ class MailerUtils {
|
|
|
69805
69901
|
}
|
|
69806
69902
|
return { ids, total };
|
|
69807
69903
|
};
|
|
69808
|
-
|
|
69904
|
+
buildMessageBodies = (emailBody, { stripInjectedLinks = false } = {}) => {
|
|
69809
69905
|
const LINK_REGEX = /(http|ftp|https):\/\/([\w_-]+(?:(?:\.[\w_-]+)+))([\w.,@?^=%&:/~+#-]*[\w@?^=%&/~+#-])/g;
|
|
69810
69906
|
const CODE_REGEX = /(?<![#/])\b\d{4,}\b/g;
|
|
69907
|
+
const emailBodyWithStrippedHead = emailBody.split("</head>").at(-1);
|
|
69908
|
+
const links = emailBodyWithStrippedHead.match(LINK_REGEX);
|
|
69909
|
+
const codes = emailBodyWithStrippedHead.match(CODE_REGEX);
|
|
69910
|
+
const filteredLinks = stripInjectedLinks && links && links.length > 2
|
|
69911
|
+
? links.slice(1, -1)
|
|
69912
|
+
: links;
|
|
69913
|
+
const contentRecognitions = {
|
|
69914
|
+
links: filteredLinks,
|
|
69915
|
+
codes: codes && [...codes],
|
|
69916
|
+
};
|
|
69917
|
+
const html = { body: emailBody, ...contentRecognitions };
|
|
69918
|
+
const wrappedHtml = /<html[\s>]/i.test(emailBody)
|
|
69919
|
+
? emailBody.replace(/\sxmlns="[^"]+"/g, "")
|
|
69920
|
+
: basicHTMLContent(emailBody);
|
|
69921
|
+
const root = distExports.parse(wrappedHtml, { comment: false });
|
|
69922
|
+
const textBody = root.querySelector("body")?.text.trim() || "";
|
|
69923
|
+
const text = { body: textBody, ...contentRecognitions };
|
|
69924
|
+
return { html, text };
|
|
69925
|
+
};
|
|
69926
|
+
getEmails = async (ids) => {
|
|
69811
69927
|
const messageDetailsBody = {
|
|
69812
69928
|
ids,
|
|
69813
69929
|
bodyProperties: ["type", "name"],
|
|
@@ -69815,24 +69931,11 @@ class MailerUtils {
|
|
|
69815
69931
|
};
|
|
69816
69932
|
const { methodResponses: [[, { list }]], } = await this.fastmailApi.apiRequest("Email/get", messageDetailsBody);
|
|
69817
69933
|
const formattedList = list.map((listItem) => {
|
|
69818
|
-
const { id, from, to, bodyValues, cc, bcc, replyTo, receivedAt, subject, attachments, blobId, } = listItem;
|
|
69934
|
+
const { id, from, to, bodyValues, cc, bcc, replyTo, receivedAt, subject, messageId, attachments, blobId, } = listItem;
|
|
69819
69935
|
const emailBody = Object.values(pluck("value", bodyValues)).join(" ");
|
|
69820
|
-
const
|
|
69821
|
-
|
|
69822
|
-
|
|
69823
|
-
// Remove first and last links as Fastmail adds dot image links
|
|
69824
|
-
const filteredLinks = links && links.length > 2 ? links.slice(1, -1) : links;
|
|
69825
|
-
const contentRecognitions = {
|
|
69826
|
-
links: filteredLinks,
|
|
69827
|
-
codes: codes && [...codes],
|
|
69828
|
-
};
|
|
69829
|
-
const html = { body: emailBody, ...contentRecognitions };
|
|
69830
|
-
const wrappedHtml = /<html[\s>]/i.test(emailBody)
|
|
69831
|
-
? emailBody.replace(/\sxmlns="[^"]+"/g, "")
|
|
69832
|
-
: basicHTMLContent(emailBody);
|
|
69833
|
-
const root = distExports.parse(wrappedHtml, { comment: false });
|
|
69834
|
-
const textBody = root.querySelector("body")?.text.trim() || "";
|
|
69835
|
-
const text = { body: textBody, ...contentRecognitions };
|
|
69936
|
+
const { html, text } = this.buildMessageBodies(emailBody, {
|
|
69937
|
+
stripInjectedLinks: true,
|
|
69938
|
+
});
|
|
69836
69939
|
return {
|
|
69837
69940
|
html,
|
|
69838
69941
|
text,
|
|
@@ -69846,6 +69949,7 @@ class MailerUtils {
|
|
|
69846
69949
|
subject,
|
|
69847
69950
|
attachments,
|
|
69848
69951
|
blobId,
|
|
69952
|
+
...(messageId?.[0] && { messageId: messageId[0] }),
|
|
69849
69953
|
};
|
|
69850
69954
|
});
|
|
69851
69955
|
return formattedList;
|
|
@@ -69866,10 +69970,10 @@ class MailerUtils {
|
|
|
69866
69970
|
return ids;
|
|
69867
69971
|
},
|
|
69868
69972
|
condition: async () => {
|
|
69869
|
-
const {
|
|
69973
|
+
const { ids } = await this.queryEmail(messageSearchCriteria, {
|
|
69870
69974
|
receivedAfter,
|
|
69871
69975
|
});
|
|
69872
|
-
return
|
|
69976
|
+
return ids.length >= expectedEmailCount;
|
|
69873
69977
|
},
|
|
69874
69978
|
timeout,
|
|
69875
69979
|
}));
|
|
@@ -69926,6 +70030,46 @@ class MailerUtils {
|
|
|
69926
70030
|
return codes?.[0];
|
|
69927
70031
|
};
|
|
69928
70032
|
generateRandomEmail = () => faker.internet.email({ provider: process.env.FASTMAIL_DOMAIN_NAME });
|
|
70033
|
+
getLatestMessageId = async (subject, { timeout = 10_000, receivedAfter = dateTimeOneHourAgo(), } = {}) => {
|
|
70034
|
+
if (IS_DEV_ENV) {
|
|
70035
|
+
return this.railsEmailUtils.getLatestMessageId(subject, {
|
|
70036
|
+
timeout: timeout / 3,
|
|
70037
|
+
receivedAfter,
|
|
70038
|
+
});
|
|
70039
|
+
}
|
|
70040
|
+
if (!this.accountId) {
|
|
70041
|
+
await this.fastmailApi.authorizeAndSetAccountId();
|
|
70042
|
+
}
|
|
70043
|
+
const messageId = (await this.neetoPlaywrightUtilities.executeRecursively({
|
|
70044
|
+
callback: async () => {
|
|
70045
|
+
const { methodResponses: [[, { ids }]], } = await this.fastmailApi.apiRequest("Email/query", {
|
|
70046
|
+
filter: { subject, after: receivedAfter.toISOString() },
|
|
70047
|
+
sort: [{ property: "receivedAt", isAscending: false }],
|
|
70048
|
+
limit: 1,
|
|
70049
|
+
});
|
|
70050
|
+
const emailId = ids?.[0];
|
|
70051
|
+
if (!emailId)
|
|
70052
|
+
return null;
|
|
70053
|
+
const { methodResponses: [[, { list }]], } = await this.fastmailApi.apiRequest("Email/get", {
|
|
70054
|
+
ids: [emailId],
|
|
70055
|
+
properties: ["messageId"],
|
|
70056
|
+
});
|
|
70057
|
+
const rawMessageId = list?.[0]?.messageId?.[0];
|
|
70058
|
+
if (!rawMessageId)
|
|
70059
|
+
return null;
|
|
70060
|
+
return rawMessageId.replace(/^<|>$/g, "");
|
|
70061
|
+
},
|
|
70062
|
+
condition: async () => {
|
|
70063
|
+
const { methodResponses: [[, { ids }]], } = await this.fastmailApi.apiRequest("Email/query", {
|
|
70064
|
+
filter: { subject, after: receivedAfter.toISOString() },
|
|
70065
|
+
limit: 1,
|
|
70066
|
+
});
|
|
70067
|
+
return ids.length >= 1;
|
|
70068
|
+
},
|
|
70069
|
+
timeout,
|
|
70070
|
+
}));
|
|
70071
|
+
return messageId || undefined;
|
|
70072
|
+
};
|
|
69929
70073
|
getEmailAttachment = async ({ name, type }, messageSearchCriteria = {}, { timeout = 10_000, receivedAfter = dateTimeOneHourAgo(), expectedEmailCount = 1, } = {}, shouldThrowErrorOnTimeout = true) => {
|
|
69930
70074
|
if (IS_DEV_ENV)
|
|
69931
70075
|
return this.railsEmailUtils.getEmailAttachment({ name, type }, messageSearchCriteria, { receivedAfter, expectedEmailCount, timeout: timeout / 3 }, shouldThrowErrorOnTimeout);
|
|
@@ -69947,6 +70091,189 @@ class MailerUtils {
|
|
|
69947
70091
|
return matchesName && matchesType;
|
|
69948
70092
|
});
|
|
69949
70093
|
};
|
|
70094
|
+
toIdentifiers = (addresses) => {
|
|
70095
|
+
if (!addresses)
|
|
70096
|
+
return [];
|
|
70097
|
+
return (Array.isArray(addresses) ? addresses : [addresses]).map(({ Name, Address }) => ({ name: Name || "", email: Address || "" }));
|
|
70098
|
+
};
|
|
70099
|
+
toMailpitAttachments = (message) => [
|
|
70100
|
+
...(message?.Attachments || []),
|
|
70101
|
+
...(message?.Inline || []).filter(({ ContentID }) => !ContentID),
|
|
70102
|
+
];
|
|
70103
|
+
toFormattedList = (summary, message) => {
|
|
70104
|
+
const { html, text } = this.buildMessageBodies(message.HTML || "", {
|
|
70105
|
+
stripInjectedLinks: true,
|
|
70106
|
+
});
|
|
70107
|
+
const attachments = this.toMailpitAttachments(message).map(({ FileName, ContentType }) => ({
|
|
70108
|
+
name: FileName || null,
|
|
70109
|
+
type: ContentType,
|
|
70110
|
+
}));
|
|
70111
|
+
const messageId = (message.MessageID || summary.MessageID || "").replace(/^<|>$/g, "");
|
|
70112
|
+
return {
|
|
70113
|
+
html,
|
|
70114
|
+
text,
|
|
70115
|
+
id: summary.ID,
|
|
70116
|
+
from: this.toIdentifiers(message.From || summary.From),
|
|
70117
|
+
to: this.toIdentifiers(message.To || summary.To),
|
|
70118
|
+
cc: this.toIdentifiers(message.Cc || summary.Cc),
|
|
70119
|
+
bcc: this.toIdentifiers(message.Bcc || summary.Bcc),
|
|
70120
|
+
replyTo: this.toIdentifiers(message.ReplyTo || summary.ReplyTo),
|
|
70121
|
+
received: new Date(summary.Created),
|
|
70122
|
+
subject: message.Subject ?? summary.Subject,
|
|
70123
|
+
attachments,
|
|
70124
|
+
blobId: "",
|
|
70125
|
+
...(messageId && { messageId }),
|
|
70126
|
+
};
|
|
70127
|
+
};
|
|
70128
|
+
matchesSummaryCriteria = (summary, { to, from, subject }) => {
|
|
70129
|
+
if (to &&
|
|
70130
|
+
!this.toIdentifiers(summary.To).some(recipient => recipient.email.toLowerCase() === to.toLowerCase()))
|
|
70131
|
+
return false;
|
|
70132
|
+
if (from &&
|
|
70133
|
+
!this.toIdentifiers(summary.From).some(sender => sender.email.toLowerCase() === from.toLowerCase()))
|
|
70134
|
+
return false;
|
|
70135
|
+
if (subject &&
|
|
70136
|
+
!(summary.Subject || "").toLowerCase().includes(subject.toLowerCase()))
|
|
70137
|
+
return false;
|
|
70138
|
+
return true;
|
|
70139
|
+
};
|
|
70140
|
+
warnOnNonMailpitRecipient = ({ to, }) => {
|
|
70141
|
+
const domain = mailpitDomainName().toLowerCase();
|
|
70142
|
+
if (to && !to.toLowerCase().endsWith(`@${domain}`))
|
|
70143
|
+
console.warn(`MailerUtils V2 reads from Mailpit, but "${to}" is not on the Mailpit domain "${domain}". Unless mail for that address is relayed to Mailpit, this lookup will poll until it times out. Generate recipients with generateRandomEmailV2().`);
|
|
70144
|
+
};
|
|
70145
|
+
queryMailpitEmails = async (messageSearchCriteria, { receivedAfter = dateTimeOneHourAgo(), page = 1, itemsPerPage = 50, }) => {
|
|
70146
|
+
if (itemsPerPage > 100 || itemsPerPage < 1)
|
|
70147
|
+
throw new Error("itemsPerPage should be in the range of 1-100");
|
|
70148
|
+
const { to, from } = messageSearchCriteria;
|
|
70149
|
+
const query = [
|
|
70150
|
+
...(to ? [`to:${toMailpitSearchTerm(to)}`] : []),
|
|
70151
|
+
...(from ? [`from:${toMailpitSearchTerm(from)}`] : []),
|
|
70152
|
+
`after:${toMailpitSearchDate(receivedAfter)}`,
|
|
70153
|
+
].join(" ");
|
|
70154
|
+
const { messages } = await this.mailpitApi.search({
|
|
70155
|
+
query,
|
|
70156
|
+
start: (page - 1) * itemsPerPage,
|
|
70157
|
+
limit: itemsPerPage,
|
|
70158
|
+
});
|
|
70159
|
+
return messages.filter(summary => new Date(summary.Created).valueOf() >= receivedAfter.valueOf() &&
|
|
70160
|
+
this.matchesSummaryCriteria(summary, messageSearchCriteria));
|
|
70161
|
+
};
|
|
70162
|
+
getEmailsV2 = async (summaries) => {
|
|
70163
|
+
const emails = await Promise.all(summaries.map(async (summary) => {
|
|
70164
|
+
const message = await this.mailpitApi.getMessage(summary.ID);
|
|
70165
|
+
return message && this.toFormattedList(summary, message);
|
|
70166
|
+
}));
|
|
70167
|
+
return emails.filter(Boolean);
|
|
70168
|
+
};
|
|
70169
|
+
pollForMailpitSummaries = async (messageSearchCriteria, { timeout, receivedAfter, expectedEmailCount, }) => {
|
|
70170
|
+
const requiresBodyMatch = Boolean(messageSearchCriteria.body);
|
|
70171
|
+
let matchingSummaries = [];
|
|
70172
|
+
const summaries = await this.neetoPlaywrightUtilities.executeRecursively({
|
|
70173
|
+
callback: async () => matchingSummaries,
|
|
70174
|
+
condition: async () => {
|
|
70175
|
+
const candidates = await this.queryMailpitEmails(messageSearchCriteria, { receivedAfter });
|
|
70176
|
+
if (requiresBodyMatch) {
|
|
70177
|
+
const emails = await this.getEmailsV2(candidates);
|
|
70178
|
+
const matchedIds = new Set(emails
|
|
70179
|
+
.filter(email => this.matchesCriteria(email, messageSearchCriteria))
|
|
70180
|
+
.map(({ id }) => id));
|
|
70181
|
+
matchingSummaries = candidates.filter(({ ID }) => matchedIds.has(ID));
|
|
70182
|
+
}
|
|
70183
|
+
else {
|
|
70184
|
+
matchingSummaries = candidates;
|
|
70185
|
+
}
|
|
70186
|
+
return matchingSummaries.length >= expectedEmailCount;
|
|
70187
|
+
},
|
|
70188
|
+
timeout,
|
|
70189
|
+
});
|
|
70190
|
+
return summaries === false ? null : summaries;
|
|
70191
|
+
};
|
|
70192
|
+
listMessagesV2 = async (messageSearchCriteria = {}, listMessagesFilterCriteria = {}) => {
|
|
70193
|
+
if (IS_DEV_ENV) {
|
|
70194
|
+
return this.railsEmailUtils.listMessages(messageSearchCriteria, listMessagesFilterCriteria);
|
|
70195
|
+
}
|
|
70196
|
+
this.warnOnNonMailpitRecipient(messageSearchCriteria);
|
|
70197
|
+
const summaries = await this.queryMailpitEmails(messageSearchCriteria, listMessagesFilterCriteria);
|
|
70198
|
+
const emails = await this.getEmailsV2(summaries);
|
|
70199
|
+
return emails.filter(email => this.matchesCriteria(email, messageSearchCriteria));
|
|
70200
|
+
};
|
|
70201
|
+
getEmailIdsV2 = async (messageSearchCriteria = {}, { timeout = 10_000, receivedAfter = dateTimeOneHourAgo(), expectedEmailCount = 1, } = {}, shouldThrowErrorOnTimeout = true) => {
|
|
70202
|
+
if (IS_DEV_ENV) {
|
|
70203
|
+
const emails = await this.railsEmailUtils.listMessages(messageSearchCriteria, { receivedAfter });
|
|
70204
|
+
return emails.map(({ id }) => id);
|
|
70205
|
+
}
|
|
70206
|
+
this.warnOnNonMailpitRecipient(messageSearchCriteria);
|
|
70207
|
+
const summaries = await this.pollForMailpitSummaries(messageSearchCriteria, { timeout, receivedAfter, expectedEmailCount });
|
|
70208
|
+
if (!summaries) {
|
|
70209
|
+
if (shouldThrowErrorOnTimeout)
|
|
70210
|
+
throw mailpitTimeoutError(messageSearchCriteria, receivedAfter, expectedEmailCount);
|
|
70211
|
+
return [];
|
|
70212
|
+
}
|
|
70213
|
+
return summaries.map(({ ID }) => ID);
|
|
70214
|
+
};
|
|
70215
|
+
findMessageV2 = async (messageSearchCriteria = {}, { timeout = 10_000, receivedAfter = dateTimeOneHourAgo(), expectedEmailCount = 1, } = {}, shouldThrowErrorOnTimeout = true) => {
|
|
70216
|
+
if (IS_DEV_ENV) {
|
|
70217
|
+
return this.railsEmailUtils.findMessage(messageSearchCriteria, { receivedAfter, expectedEmailCount, timeout: timeout / 3 }, shouldThrowErrorOnTimeout);
|
|
70218
|
+
}
|
|
70219
|
+
this.warnOnNonMailpitRecipient(messageSearchCriteria);
|
|
70220
|
+
const summaries = await this.pollForMailpitSummaries(messageSearchCriteria, { timeout, receivedAfter, expectedEmailCount });
|
|
70221
|
+
if (!summaries) {
|
|
70222
|
+
if (shouldThrowErrorOnTimeout)
|
|
70223
|
+
throw mailpitTimeoutError(messageSearchCriteria, receivedAfter, expectedEmailCount);
|
|
70224
|
+
return {};
|
|
70225
|
+
}
|
|
70226
|
+
const emails = await this.getEmailsV2(summaries);
|
|
70227
|
+
const filteredEmails = emails.filter(email => this.matchesCriteria(email, messageSearchCriteria));
|
|
70228
|
+
return filteredEmails[0] || {};
|
|
70229
|
+
};
|
|
70230
|
+
findOtpFromEmailV2 = async ({ email, subjectSubstring = OTP_EMAIL_PATTERN, timeout = 2 * 60 * 1000, receivedAfter = new Date(Date.now() - 3000), expectedEmailCount = 1, }) => {
|
|
70231
|
+
if (IS_DEV_ENV) {
|
|
70232
|
+
return this.railsEmailUtils.findOtpFromEmail({
|
|
70233
|
+
email,
|
|
70234
|
+
subjectSubstring,
|
|
70235
|
+
receivedAfter,
|
|
70236
|
+
expectedEmailCount,
|
|
70237
|
+
timeout: timeout / 3,
|
|
70238
|
+
});
|
|
70239
|
+
}
|
|
70240
|
+
const message = await this.findMessageV2({ to: email, subject: subjectSubstring }, { timeout, receivedAfter, expectedEmailCount });
|
|
70241
|
+
return message.html?.codes?.[0];
|
|
70242
|
+
};
|
|
70243
|
+
generateRandomEmailV2 = () => {
|
|
70244
|
+
const domain = mailpitDomainName();
|
|
70245
|
+
const [localPart] = faker.internet.email({ provider: domain }).split("@");
|
|
70246
|
+
return `${localPart}.${faker.string.alphanumeric(8).toLowerCase()}@${domain}`;
|
|
70247
|
+
};
|
|
70248
|
+
getLatestMessageIdV2 = async (subject, { timeout = 10_000, receivedAfter = dateTimeOneHourAgo(), } = {}) => {
|
|
70249
|
+
if (IS_DEV_ENV) {
|
|
70250
|
+
return this.railsEmailUtils.getLatestMessageId(subject, {
|
|
70251
|
+
timeout: timeout / 3,
|
|
70252
|
+
receivedAfter,
|
|
70253
|
+
});
|
|
70254
|
+
}
|
|
70255
|
+
const summaries = await this.pollForMailpitSummaries({ subject }, { timeout, receivedAfter, expectedEmailCount: 1 });
|
|
70256
|
+
const messageId = summaries?.[0]?.MessageID;
|
|
70257
|
+
return messageId ? messageId.replace(/^<|>$/g, "") : undefined;
|
|
70258
|
+
};
|
|
70259
|
+
getEmailAttachmentV2 = async ({ name, type }, messageSearchCriteria = {}, { timeout = 10_000, receivedAfter = dateTimeOneHourAgo(), expectedEmailCount = 1, } = {}, shouldThrowErrorOnTimeout = true) => {
|
|
70260
|
+
if (IS_DEV_ENV)
|
|
70261
|
+
return this.railsEmailUtils.getEmailAttachment({ name, type }, messageSearchCriteria, { receivedAfter, expectedEmailCount, timeout: timeout / 3 }, shouldThrowErrorOnTimeout);
|
|
70262
|
+
const { id } = await this.findMessageV2(messageSearchCriteria, { expectedEmailCount, receivedAfter, timeout }, shouldThrowErrorOnTimeout);
|
|
70263
|
+
const rawMessage = id ? await this.mailpitApi.fetchRawMessage(id) : null;
|
|
70264
|
+
if (!rawMessage)
|
|
70265
|
+
throw new Error("No such attachment exists");
|
|
70266
|
+
const parsedEmail = await mailparserExports.simpleParser(rawMessage);
|
|
70267
|
+
const attachments = parsedEmail.attachments;
|
|
70268
|
+
const attachment = attachments.find(att => {
|
|
70269
|
+
const matchesName = name ? att.filename?.includes(name) : true;
|
|
70270
|
+
const matchesType = type ? att.contentType?.startsWith(type) : true;
|
|
70271
|
+
return matchesName && matchesType;
|
|
70272
|
+
});
|
|
70273
|
+
if (!attachment)
|
|
70274
|
+
throw new Error("No such attachment exists");
|
|
70275
|
+
return attachment;
|
|
70276
|
+
};
|
|
69950
70277
|
}
|
|
69951
70278
|
|
|
69952
70279
|
var HeaderTypes;
|
|
@@ -116619,7 +116946,8 @@ const commands = {
|
|
|
116619
116946
|
},
|
|
116620
116947
|
mailerUtils: async ({ neetoPlaywrightUtilities }, use) => {
|
|
116621
116948
|
const mailerUtils = new MailerUtils(neetoPlaywrightUtilities);
|
|
116622
|
-
|
|
116949
|
+
if (!IS_MAILPIT_ENABLED)
|
|
116950
|
+
await mailerUtils.fastmailApi.authorizeAndSetAccountId();
|
|
116623
116951
|
await use(mailerUtils);
|
|
116624
116952
|
IS_DEV_ENV && (await mailerUtils.railsEmailUtils.clearStaleEmails());
|
|
116625
116953
|
},
|
|
@@ -126177,4 +126505,4 @@ const definePlaywrightConfig = (overrides) => {
|
|
|
126177
126505
|
});
|
|
126178
126506
|
};
|
|
126179
126507
|
|
|
126180
|
-
export { ACTIONS, ADMIN_PANEL_SELECTORS, ALL_RESOURCES, ANALYTICS_RESOURCES, API_KEYS_SELECTORS, API_ROUTES, APP_RESOURCES, AUDIT_LOGS_SELECTORS, ApiKeysApi, ApiKeysPage, AuditLogsPage, BASE_URL, CALENDAR_LABELS, CERTIFICATE_LIMIT_EXCEEDED_MESSAGE, CERTIFICATE_LIMIT_EXCEEDED_REGEXP, CHANGELOG_WIDGET_SELECTORS, CHAT_WIDGET_SELECTORS, CHAT_WIDGET_TEXTS, COLOR, COMMON_SELECTORS, COMMON_TEXTS, COMMUNITY_TEXTS, CREDENTIALS, CURRENT_TIME_RANGES, CUSTOM_DOMAIN_SELECTORS, CUSTOM_DOMAIN_SUFFIX, ColorPickerUtils, CustomCommands, CustomDomainApi, CustomDomainPage, DATE_FORMATS, DATE_PICKER_SELECTORS, DATE_RANGES, DATE_TEXTS, DEFAULT_WEBHOOKS_RESPONSE_TEXT, DESCRIPTION_EDITOR_TEXTS, EDITOR_VERIFY_TEXT_COLOR, EMBED_SELECTORS, EMOJI_LABEL, EMPTY_STORAGE_STATE, ENGAGE_TEXTS, ENVIRONMENT, EXAMPLE_URL, EXPANDED_FONT_SIZE, EXPORT_FILE_TYPES, EditorPage, EmailDeliveryUtils, EmbedBase, FILE_FORMATS, FONTS_RESOURCES, FONT_SIZE_SELECTORS, FROM_EMAIL_ENV_KEYS, GLOBAL_TRANSLATIONS_PATTERN, GOOGLE_ANALYTICS_SELECTORS, GOOGLE_CALENDAR_DATE_FORMAT, GOOGLE_LOGIN_SELECTORS, GOOGLE_LOGIN_TEXTS, GOOGLE_SHEETS_SELECTORS, GooglePage, HELP_CENTER_ROUTES, HELP_CENTER_SELECTORS, HelpAndProfilePage, INTEGRATIONS_TEXTS, INTEGRATION_SELECTORS, IPRestrictionsPage, IP_RESTRICTIONS_SELECTORS, IS_CI, IS_DEV_ENV, IS_STAGING_ENV, ImageUploader, IntegrationBase, IpRestrictionsApi, KEYBOARD_SHORTCUTS_SELECTORS, KEYBOARD_SHORTCUT_TEST_CASES, LIST_MODIFIER_SELECTORS, LIST_MODIFIER_TAGS, LOGIN_SELECTORS, MEMBER_FORM_SELECTORS, MEMBER_SELECTORS, MEMBER_TEXTS, MERGE_TAGS_SELECTORS, MICROSOFT_LOGIN_SELECTORS, MICROSOFT_LOGIN_TEXTS, MailerUtils, Member, MemberApis, MicrosoftPage, NEETO_AUTH_BASE_URL, NEETO_EDITOR_SELECTORS, NEETO_FILTERS_SELECTORS, NEETO_IMAGE_UPLOADER_SELECTORS, NEETO_ROUTES, NEETO_SEO_SELECTORS, NEETO_TEXT_MODIFIER_SELECTORS, NeetoAuthServer, NeetoChatWidget, NeetoEmailDeliveryApi, NeetoTowerApi, ONBOARDING_SELECTORS, ORGANIZATION_TEXTS, OTP_EMAIL_PATTERN, OrganizationPage, PAST_TIME_RANGES, PHONE_NUMBER_FORMATS, PLURAL, PRODUCT_ROLES_ROUTE_MAP, PROFILE_LINKS, PROFILE_SECTION_SELECTORS, PROJECT_NAMES, PROJECT_TRANSLATIONS_PATH, ROLES_SELECTORS, ROUTES, RailsEmailApiClient, RailsEmailUtils, RoleApis, RolesPage, SIGNUP_SELECTORS, SINGULAR, SLACK_DATA_QA_SELECTORS, SLACK_DEFAULT_CHANNEL, SLACK_SELECTORS, SLACK_WEB_TEXTS, STATUS_TEXTS, STORAGE_STATE, SecurityApi, SidebarSection, SlackApi, SlackPage, TABLE_SELECTORS, TAB_SELECTORS, TAGS_SELECTORS, TEAM_MEMBER_TEXTS, TEXT_MODIFIER_ROLES, TEXT_MODIFIER_SELECTORS, TEXT_MODIFIER_TAGS, THANK_YOU_SELECTORS, THEMES_SELECTORS, THEMES_TEXTS, THIRD_PARTY_RESOURCES, THIRD_PARTY_ROUTES, TIME_RANGES, TOASTR_MESSAGES, TWILIO_SELECTORS, TagsApi, TagsPage, TeamMembers, ThankYouApi, ThankYouPage, TwilioApi, USER_AGENTS, WEBHOOK_SELECTORS, WebhookSiteApi, WebhooksPage, ZAPIER_LIMIT_EXHAUSTED_MESSAGE, ZAPIER_SELECTORS, ZAPIER_TEST_EMAIL, ZAPIER_WEB_TEXTS, ZapierPage, authenticateUser, baseURLGenerator, basicHTMLContent, clearCredentials, commands, cpuThrottlingUsingCDP, createOrganizationViaRake, currencyUtils, dataQa, decodeQRCodeFromFile, definePlaywrightConfig, executeWithThrottledResources, extractSubdomainFromError, filterUtils, fixedMenuSelector, generatePhoneNumber, generatePhoneNumberDetails, generateRandomBypassEmail, generateRandomFile, generateStagingData, getByDataQA, getClipboardContent, getDirname, getFormattedPhoneNumber, getFullUrl, getGlobalUserProps, getGlobalUserState, getImagePathAndName, getIsoCodeFromPhoneCode, getListCount, globalShortcuts, grantClipboardPermissions, hexToRGB, hexToRGBA, i18nFixture, imageRegex, initializeCredentials, initializeTestData, initializeTotp, isGithubIssueOpen, isStagingOrganizationExpired, joinHyphenCase, joinString, login, networkConditions, networkThrottlingUsingCDP, optionSelector, readFileSyncIfExists, removeCredentialFile, serializeFileForBrowser, shouldSkipCustomDomainSetup, shouldSkipSetupAndTeardown, simulateClickWithDelay, simulateTypingWithDelay, skipTest, squish, stealth as stealthTest, tableUtils, toCamelCase, updateCredentials, warmup, withCookieCache, writeDataToFile };
|
|
126508
|
+
export { ACTIONS, ADMIN_PANEL_SELECTORS, ALL_RESOURCES, ANALYTICS_RESOURCES, API_KEYS_SELECTORS, API_ROUTES, APP_RESOURCES, AUDIT_LOGS_SELECTORS, ApiKeysApi, ApiKeysPage, AuditLogsPage, BASE_URL, CALENDAR_LABELS, CERTIFICATE_LIMIT_EXCEEDED_MESSAGE, CERTIFICATE_LIMIT_EXCEEDED_REGEXP, CHANGELOG_WIDGET_SELECTORS, CHAT_WIDGET_SELECTORS, CHAT_WIDGET_TEXTS, COLOR, COMMON_SELECTORS, COMMON_TEXTS, COMMUNITY_TEXTS, CREDENTIALS, CURRENT_TIME_RANGES, CUSTOM_DOMAIN_SELECTORS, CUSTOM_DOMAIN_SUFFIX, ColorPickerUtils, CustomCommands, CustomDomainApi, CustomDomainPage, DATE_FORMATS, DATE_PICKER_SELECTORS, DATE_RANGES, DATE_TEXTS, DEFAULT_WEBHOOKS_RESPONSE_TEXT, DESCRIPTION_EDITOR_TEXTS, EDITOR_VERIFY_TEXT_COLOR, EMBED_SELECTORS, EMOJI_LABEL, EMPTY_STORAGE_STATE, ENGAGE_TEXTS, ENVIRONMENT, EXAMPLE_URL, EXPANDED_FONT_SIZE, EXPORT_FILE_TYPES, EditorPage, EmailDeliveryUtils, EmbedBase, FILE_FORMATS, FONTS_RESOURCES, FONT_SIZE_SELECTORS, FROM_EMAIL_ENV_KEYS, GLOBAL_TRANSLATIONS_PATTERN, GOOGLE_ANALYTICS_SELECTORS, GOOGLE_CALENDAR_DATE_FORMAT, GOOGLE_LOGIN_SELECTORS, GOOGLE_LOGIN_TEXTS, GOOGLE_SHEETS_SELECTORS, GooglePage, HELP_CENTER_ROUTES, HELP_CENTER_SELECTORS, HelpAndProfilePage, INTEGRATIONS_TEXTS, INTEGRATION_SELECTORS, IPRestrictionsPage, IP_RESTRICTIONS_SELECTORS, IS_CI, IS_DEV_ENV, IS_MAILPIT_ENABLED, IS_STAGING_ENV, ImageUploader, IntegrationBase, IpRestrictionsApi, KEYBOARD_SHORTCUTS_SELECTORS, KEYBOARD_SHORTCUT_TEST_CASES, LIST_MODIFIER_SELECTORS, LIST_MODIFIER_TAGS, LOGIN_SELECTORS, MAILPIT_BASE_URL, MAILPIT_DOMAIN_NAME, MEMBER_FORM_SELECTORS, MEMBER_SELECTORS, MEMBER_TEXTS, MERGE_TAGS_SELECTORS, MICROSOFT_LOGIN_SELECTORS, MICROSOFT_LOGIN_TEXTS, MailerUtils, MailpitApi, Member, MemberApis, MicrosoftPage, NEETO_AUTH_BASE_URL, NEETO_EDITOR_SELECTORS, NEETO_FILTERS_SELECTORS, NEETO_IMAGE_UPLOADER_SELECTORS, NEETO_ROUTES, NEETO_SEO_SELECTORS, NEETO_TEXT_MODIFIER_SELECTORS, NeetoAuthServer, NeetoChatWidget, NeetoEmailDeliveryApi, NeetoTowerApi, ONBOARDING_SELECTORS, ORGANIZATION_TEXTS, OTP_EMAIL_PATTERN, OrganizationPage, PAST_TIME_RANGES, PHONE_NUMBER_FORMATS, PLURAL, PRODUCT_ROLES_ROUTE_MAP, PROFILE_LINKS, PROFILE_SECTION_SELECTORS, PROJECT_NAMES, PROJECT_TRANSLATIONS_PATH, ROLES_SELECTORS, ROUTES, RailsEmailApiClient, RailsEmailUtils, RoleApis, RolesPage, SIGNUP_SELECTORS, SINGULAR, SLACK_DATA_QA_SELECTORS, SLACK_DEFAULT_CHANNEL, SLACK_SELECTORS, SLACK_WEB_TEXTS, STATUS_TEXTS, STORAGE_STATE, SecurityApi, SidebarSection, SlackApi, SlackPage, TABLE_SELECTORS, TAB_SELECTORS, TAGS_SELECTORS, TEAM_MEMBER_TEXTS, TEXT_MODIFIER_ROLES, TEXT_MODIFIER_SELECTORS, TEXT_MODIFIER_TAGS, THANK_YOU_SELECTORS, THEMES_SELECTORS, THEMES_TEXTS, THIRD_PARTY_RESOURCES, THIRD_PARTY_ROUTES, TIME_RANGES, TOASTR_MESSAGES, TWILIO_SELECTORS, TagsApi, TagsPage, TeamMembers, ThankYouApi, ThankYouPage, TwilioApi, USER_AGENTS, WEBHOOK_SELECTORS, WebhookSiteApi, WebhooksPage, ZAPIER_LIMIT_EXHAUSTED_MESSAGE, ZAPIER_SELECTORS, ZAPIER_TEST_EMAIL, ZAPIER_TEST_EMAIL_V2, ZAPIER_WEB_TEXTS, ZapierPage, authenticateUser, baseURLGenerator, basicHTMLContent, clearCredentials, commands, cpuThrottlingUsingCDP, createOrganizationViaRake, currencyUtils, dataQa, decodeQRCodeFromFile, definePlaywrightConfig, executeWithThrottledResources, extractSubdomainFromError, filterUtils, fixedMenuSelector, generatePhoneNumber, generatePhoneNumberDetails, generateRandomBypassEmail, generateRandomFile, generateStagingData, getByDataQA, getClipboardContent, getDirname, getFormattedPhoneNumber, getFullUrl, getGlobalUserProps, getGlobalUserState, getImagePathAndName, getIsoCodeFromPhoneCode, getListCount, globalShortcuts, grantClipboardPermissions, hexToRGB, hexToRGBA, i18nFixture, imageRegex, initializeCredentials, initializeTestData, initializeTotp, isGithubIssueOpen, isStagingOrganizationExpired, joinHyphenCase, joinString, login, mailpitDomainName, networkConditions, networkThrottlingUsingCDP, optionSelector, readFileSyncIfExists, removeCredentialFile, serializeFileForBrowser, shouldSkipCustomDomainSetup, shouldSkipSetupAndTeardown, simulateClickWithDelay, simulateTypingWithDelay, skipTest, squish, stealth as stealthTest, tableUtils, toCamelCase, updateCredentials, warmup, withCookieCache, writeDataToFile };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bigbinary/neeto-playwright-commons",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.3.0",
|
|
4
4
|
"description": "A package encapsulating common playwright code across neeto projects.",
|
|
5
5
|
"repository": "git@github.com:bigbinary/neeto-playwright-commons.git",
|
|
6
6
|
"license": "apache-2.0",
|