diff --git a/packages/messenger-widget/cypress.config.ts b/packages/messenger-widget/cypress.config.ts index cfe5d0abc..1eb00f9e0 100644 --- a/packages/messenger-widget/cypress.config.ts +++ b/packages/messenger-widget/cypress.config.ts @@ -7,6 +7,6 @@ export default defineConfig({ bundler: 'webpack', webpackConfig: require('./webpack.config'), }, - specPattern: '**/*.cy.{js,jsx,ts,tsx}', + specPattern: './src/**/*.cy.{js,jsx,ts,tsx}', }, }); diff --git a/packages/messenger-widget/cypress/support/component.ts b/packages/messenger-widget/cypress/support/component.ts index a72b5dc9d..9eb6b79a1 100644 --- a/packages/messenger-widget/cypress/support/component.ts +++ b/packages/messenger-widget/cypress/support/component.ts @@ -15,6 +15,7 @@ // Import commands.js using ES2015 syntax: import './commands'; +window.Buffer = window.Buffer || require('buffer').Buffer; // Alternatively you can use CommonJS syntax: // require('./commands') diff --git a/packages/messenger-widget/src/components/AddConversation/AddConversation.cy.tsx b/packages/messenger-widget/src/components/AddConversation/AddConversation.cy.tsx new file mode 100644 index 000000000..e1372fab9 --- /dev/null +++ b/packages/messenger-widget/src/components/AddConversation/AddConversation.cy.tsx @@ -0,0 +1,199 @@ +import { Conversation } from '@dm3-org/dm3-lib-storage'; +import { AuthContext, AuthContextType } from '../../context/AuthContext'; +import { ConversationContext } from '../../context/ConversationContext'; +import { ModalContext } from '../../context/ModalContext'; +import { + StorageContext, + StorageContextType, +} from '../../context/StorageContext'; +import { getMockedAuthContext } from '../../context/testHelper/getMockedAuthContext'; +import { getMockedStorageContext } from '../../context/testHelper/getMockedStorageContext'; +import { UiViewContext } from '../../context/UiViewContext'; +import { DM3 } from '../../widget'; +import AddConversation from './AddConversation'; +import { + DeliveryServiceContext, + DeliveryServiceContextType, +} from '../../context/DeliveryServiceContext'; +import { getMockedDeliveryServiceContext } from '../../context/testHelper/getMockedDeliveryServiceContext'; +import { getMockedTldContext } from '../../context/testHelper/getMockedTldContext'; +import { TLDContext } from '../../context/TLDContext'; +import { getMockedConversationContext } from '../../context/testHelper/getMockedConversationContext'; +import { getEmptyContact } from '../../interfaces/utils'; +import { getMockedDm3Configuration } from '../../context/testHelper/getMockedDm3Configuration'; +import { DM3ConfigurationContext } from '../../context/DM3ConfigurationContext'; +import { getMockedUiViewContext } from '../../context/testHelper/getMockedUiViewContext'; +import { getMockedModalContext } from '../../context/testHelper/getMockedModalContext'; +import { getMockedMainnetProviderContext } from '../../context/testHelper/getMockedMainnetProviderContext'; +import { MainnetProviderContext } from '../../context/ProviderContext'; +import { + MessageContext, + MessageContextType, +} from '../../context/MessageContext'; +import { getMockedMessageContext } from '../../context/testHelper/getMockedMessageContext'; + +// AddConversation component tests +describe('', () => { + const dm3Config = { + userEnsSubdomain: process.env.REACT_APP_USER_ENS_SUBDOMAIN as string, + addressEnsSubdomain: process.env.REACT_APP_ADDR_ENS_SUBDOMAIN as string, + resolverBackendUrl: process.env.REACT_APP_RESOLVER_BACKEND as string, + profileBaseUrl: process.env.REACT_APP_PROFILE_BASE_URL as string, + defaultDeliveryService: process.env + .REACT_APP_DEFAULT_DELIVERY_SERVICE as string, + backendUrl: process.env.REACT_APP_BACKEND as string, + chainId: process.env.REACT_APP_CHAIN_ID as string, + defaultServiceUrl: process.env.REACT_APP_DEFAULT_SERVICE as string, + ethereumProvider: process.env.REACT_APP_MAINNET_PROVIDER_RPC as string, + walletConnectProjectId: process.env + .REACT_APP_WALLET_CONNECT_PROJECT_ID as string, + publicVapidKey: process.env.REACT_APP_PUBLIC_VAPID_KEY as string, + defaultContact: 'defaultcontact.eth', + nonce: process.env.REACT_APP_NONCE as string, + showAlways: true, + showContacts: true, + }; + + // Mount the Widget component before every test + beforeEach(() => { + // should mount DM3 component and render it + cy.mount(); + }); + + // test for render AddConversation component + it('Renders component', () => { + // should mount AddConversation component and render it + cy.mount(); + }); + + // test for change in conversation name + it('Should change conversation name', () => { + // should mount AddConversation component and render it + cy.mount(); + // should change conversation name input field + cy.get('.conversation-name') + .clear() + .type('bob.eth') + .should('have.value', 'bob.eth'); + }); + + // test for invalid conversation name + it('Should display error for invalid conversation name', () => { + // should mount AddConversation component and render it + cy.mount(); + // should change conversation name input field + cy.get('.conversation-name').clear().type('abc-xyz#.eth'); + // should show error for invalid conversation name + cy.get('.conversation-error').should( + 'have.text', + 'Invalid address or ENS name', + ); + }); + + // test to add conversation name successfully + it('Should change conversation name', () => { + const CONTACT_NAME = 'user.dm3.eth'; + + const authContext: AuthContextType = getMockedAuthContext({ + account: { + ensName: 'alice.eth', + profile: { + deliveryServices: ['ds.eth'], + publicEncryptionKey: '', + publicSigningKey: '', + }, + }, + }); + + const storageContext: StorageContextType = getMockedStorageContext({ + getConversations: function (page: number): Promise { + return Promise.resolve([]); + }, + initialized: true, + }); + + const deliveryServiceContext: DeliveryServiceContextType = + getMockedDeliveryServiceContext({ + fetchIncomingMessages: function (ensName: string) { + return Promise.resolve([]); + }, + getDeliveryServiceProperties: function (): Promise { + return Promise.resolve([{ sizeLimit: 0 }]); + }, + isInitialized: true, + }); + + const tldContext = getMockedTldContext({ + resolveTLDtoAlias: async (alias: string) => { + return CONTACT_NAME; + }, + }); + + const conversationContext = getMockedConversationContext({ + selectedContact: getEmptyContact( + 'max.eth', + undefined, + false, + 0, + [], + ), + }); + + const uiViewContext = getMockedUiViewContext(); + + const dm3ConfigurationContext = getMockedDm3Configuration(); + + const modalContext = getMockedModalContext({ + showAddConversationModal: true, + setLoaderContent: (loader: string) => { + console.log('loader active...'); + }, + }); + + const mainnetContext = getMockedMainnetProviderContext(); + + const messageContext = getMockedMessageContext() as MessageContextType; + + // should mount AddConversation component and render it + cy.mount( + <> + + + + + + + + + + + + + + + + + + + + + + , + ); + + // should change conversation name input field + cy.get('.conversation-name').clear().type('bob.eth'); + }); +}); diff --git a/packages/messenger-widget/src/context/testHelper/getMockedDm3Configuration.ts b/packages/messenger-widget/src/context/testHelper/getMockedDm3Configuration.ts index b7394d106..14a33d525 100644 --- a/packages/messenger-widget/src/context/testHelper/getMockedDm3Configuration.ts +++ b/packages/messenger-widget/src/context/testHelper/getMockedDm3Configuration.ts @@ -1,14 +1,39 @@ -import { - DM3ConfigurationContext, - DM3ConfigurationContextType, -} from '../DM3ConfigurationContext'; +import { SiweValidityStatus } from '../../utils/enum-type-utils'; +import { DM3Configuration, Siwe } from '../../widget'; +import { DM3ConfigurationContextType } from '../DM3ConfigurationContext'; //Provide a mocked DM3Configuration context //Override the default values with the provided values export const getMockedDm3Configuration = ( override?: Partial, ) => { - return { ...DM3ConfigurationContext, ...override }; + const defaultValue = { + setDm3Configuration: (configuration: DM3Configuration) => {}, + dm3Configuration: { + defaultContact: '', + defaultServiceUrl: '', + ethereumProvider: '', + walletConnectProjectId: '', + userEnsSubdomain: '', + addressEnsSubdomain: '', + resolverBackendUrl: '', + profileBaseUrl: '', + defaultDeliveryService: '', + backendUrl: '', + chainId: '', + showAlways: true, + showContacts: true, + publicVapidKey: '', + nonce: '', + }, + screenWidth: window.innerWidth, + setScreenWidth: (width: number) => {}, + siweValidityStatus: SiweValidityStatus.TO_BE_INITIATED, + setSiweValidityStatus: (status: SiweValidityStatus) => {}, + validateSiweCredentials: (data: Siwe) => {}, + }; + + return { ...defaultValue, ...override }; }; export const DEFAULT_DM3_CONFIGURATION = { diff --git a/packages/messenger-widget/src/context/testHelper/getMockedMessageContext.ts b/packages/messenger-widget/src/context/testHelper/getMockedMessageContext.ts new file mode 100644 index 000000000..54a305941 --- /dev/null +++ b/packages/messenger-widget/src/context/testHelper/getMockedMessageContext.ts @@ -0,0 +1,24 @@ +import { MessageContextType } from '../MessageContext'; + +//Provide a mocked Message context +//Override the default values with the provided values +export const getMockedMessageContext = ( + override?: Partial, +) => { + const defaultValues = { + getMessages: (contact: string) => [], + getUnreadMessageCount: (contact: string) => 0, + addMessage: (contact: string, message: any) => + new Promise(() => { + isSuccess: true; + }), + loadMoreMessages: (contact: string) => + new Promise(() => { + return 0; + }), + contactIsLoading: (contact: string) => false, + messages: {}, + }; + + return { ...defaultValues, ...override }; +}; diff --git a/packages/messenger-widget/src/context/testHelper/getMockedModalContext.ts b/packages/messenger-widget/src/context/testHelper/getMockedModalContext.ts new file mode 100644 index 000000000..419f15651 --- /dev/null +++ b/packages/messenger-widget/src/context/testHelper/getMockedModalContext.ts @@ -0,0 +1,103 @@ +import { ModalContextType } from '../ModalContext'; +import { NewContact } from './../../interfaces/utils'; +import { + MessageActionType, + ProfileScreenType, + ProfileType, +} from './../../utils/enum-type-utils'; +import { + IConfigureProfileModal, + IOpenEmojiPopup, + PreferencesOptionType, +} from './../../hooks/modals/useModal'; +import { PREFERENCES_ITEMS } from './../../components/Preferences/bl'; + +//Provide a mocked Modal context +//Override the default values with the provided values +export const getMockedModalContext = (override?: Partial) => { + const defaultValues = { + loaderContent: '', + setLoaderContent: (content: string) => { + throw new Error('Function not implemented.'); + }, + contactToHide: undefined, + setContactToHide: (action: string | undefined) => { + throw new Error('Function not implemented.'); + }, + addConversation: { + active: false, + ensName: undefined, + processed: false, + }, + setAddConversation: (contact: NewContact) => { + throw new Error('Function not implemented.'); + }, + openEmojiPopup: { action: false, data: undefined }, + setOpenEmojiPopup: (action: IOpenEmojiPopup) => { + throw new Error('Function not implemented.'); + }, + lastMessageAction: MessageActionType.NONE, + setLastMessageAction: (action: MessageActionType) => { + throw new Error('Function not implemented.'); + }, + showProfileConfigurationModal: false, + setShowProfileConfigurationModal: (show: boolean) => { + throw new Error('Function not implemented.'); + }, + showPreferencesModal: false, + setShowPreferencesModal: (show: boolean) => { + throw new Error('Function not implemented.'); + }, + showAboutModal: false, + setShowAboutModal: (show: boolean) => { + throw new Error('Function not implemented.'); + }, + showAddConversationModal: false, + setShowAddConversationModal: (show: boolean) => { + throw new Error('Function not implemented.'); + }, + configureProfileModal: { + profileOptionSelected: ProfileType.DM3_NAME, + onScreen: ProfileScreenType.NONE, + }, + setConfigureProfileModal: (modal: IConfigureProfileModal) => { + throw new Error('Function not implemented.'); + }, + resetConfigureProfileModal: () => { + throw new Error('Function not implemented.'); + }, + resetModalStates: () => { + throw new Error('Function not implemented.'); + }, + preferencesOptionSelected: null, + setPreferencesOptionSelected: (item: PreferencesOptionType | null) => { + throw new Error('Function not implemented.'); + }, + preferencesOptions: [], + updatePreferenceSelected: (ticker: PREFERENCES_ITEMS | null) => { + throw new Error('Function not implemented.'); + }, + disabledOptions: { + notification: { + email: false, + push: false, + }, + profile: { + dm3: [ + { key: 'dm3', value: false }, + { key: 'optimism', value: false }, + ], + own: [ + { key: 'ens', value: false }, + { key: 'gnosis', value: false }, + ], + }, + settings: { + messageView: false, + }, + }, + isProfileDialogDisabled: () => false, + }; + + return { ...defaultValues, ...override }; +}; diff --git a/packages/messenger-widget/src/context/testHelper/getMockedUiViewContext.ts b/packages/messenger-widget/src/context/testHelper/getMockedUiViewContext.ts new file mode 100644 index 000000000..c96573ccd --- /dev/null +++ b/packages/messenger-widget/src/context/testHelper/getMockedUiViewContext.ts @@ -0,0 +1,36 @@ +import { UiViewContextType } from '../UiViewContext'; +import { MessageAction } from '../../interfaces/props'; +import { + LeftViewSelected, + MessageActionType, + RightViewSelected, +} from '../../utils/enum-type-utils'; + +//Provide a mocked UiView context +//Override the default values with the provided values +export const getMockedUiViewContext = ( + override?: Partial, +) => { + const defaultValues = { + selectedLeftView: LeftViewSelected.Contacts, + setSelectedLeftView: (view: LeftViewSelected) => { + throw new Error('Function not implemented.'); + }, + selectedRightView: RightViewSelected.Default, + setSelectedRightView: (view: RightViewSelected) => { + throw new Error('Function not implemented.'); + }, + messageView: { + messageData: undefined, + actionType: MessageActionType.NONE, + }, + setMessageView: (view: MessageAction) => { + throw new Error('Function not implemented.'); + }, + resetViewStates: () => { + throw new Error('Function not implemented.'); + }, + }; + + return { ...defaultValues, ...override }; +};