about summary refs log tree commit diff
path: root/__tests__/view/com
diff options
context:
space:
mode:
Diffstat (limited to '__tests__/view/com')
-rw-r--r--__tests__/view/com/composer/Autocomplete.test.tsx43
-rw-r--r--__tests__/view/com/composer/ComposePost.test.tsx117
-rw-r--r--__tests__/view/com/composer/PhotoCarouselPicker.test.tsx92
-rw-r--r--__tests__/view/com/composer/SelectedPhoto.test.tsx70
-rw-r--r--__tests__/view/com/login/CreateAccount.test.tsx60
-rw-r--r--__tests__/view/com/login/Signin.test.tsx128
-rw-r--r--__tests__/view/com/profile/ProfileHeader.test.tsx109
7 files changed, 619 insertions, 0 deletions
diff --git a/__tests__/view/com/composer/Autocomplete.test.tsx b/__tests__/view/com/composer/Autocomplete.test.tsx
new file mode 100644
index 000000000..57539b75e
--- /dev/null
+++ b/__tests__/view/com/composer/Autocomplete.test.tsx
@@ -0,0 +1,43 @@
+import React from 'react'
+import {Autocomplete} from '../../../../src/view/com/composer/Autocomplete'
+import {cleanup, fireEvent, render} from '../../../../jest/test-utils'
+
+describe('Autocomplete', () => {
+  const onSelectMock = jest.fn()
+  const mockedProps = {
+    active: true,
+    items: [
+      {
+        handle: 'handle.test',
+        displayName: 'Test Display',
+      },
+      {
+        handle: 'handle2.test',
+        displayName: 'Test Display 2',
+      },
+    ],
+    onSelect: onSelectMock,
+  }
+
+  afterAll(() => {
+    jest.clearAllMocks()
+    cleanup()
+  })
+
+  it('renders a button for each user', async () => {
+    const {findAllByTestId} = render(<Autocomplete {...mockedProps} />)
+    const autocompleteButton = await findAllByTestId('autocompleteButton')
+    expect(autocompleteButton.length).toBe(2)
+  })
+
+  it('triggers onSelect by pressing the button', async () => {
+    const {findAllByTestId} = render(<Autocomplete {...mockedProps} />)
+    const autocompleteButton = await findAllByTestId('autocompleteButton')
+
+    fireEvent.press(autocompleteButton[0])
+    expect(onSelectMock).toHaveBeenCalledWith('handle.test')
+
+    fireEvent.press(autocompleteButton[1])
+    expect(onSelectMock).toHaveBeenCalledWith('handle2.test')
+  })
+})
diff --git a/__tests__/view/com/composer/ComposePost.test.tsx b/__tests__/view/com/composer/ComposePost.test.tsx
new file mode 100644
index 000000000..84377f62f
--- /dev/null
+++ b/__tests__/view/com/composer/ComposePost.test.tsx
@@ -0,0 +1,117 @@
+import React from 'react'
+import {ComposePost} from '../../../../src/view/com/composer/ComposePost'
+import {cleanup, fireEvent, render, waitFor} from '../../../../jest/test-utils'
+import * as apilib from '../../../../src/state/lib/api'
+import {
+  mockedAutocompleteViewStore,
+  mockedRootStore,
+} from '../../../../__mocks__/state-mock'
+import Toast from 'react-native-root-toast'
+
+describe('ComposePost', () => {
+  const mockedProps = {
+    replyTo: {
+      uri: 'testUri',
+      cid: 'testCid',
+      text: 'testText',
+      author: {
+        handle: 'test.handle',
+        displayName: 'test name',
+        avatar: '',
+      },
+    },
+    onPost: jest.fn(),
+    onClose: jest.fn(),
+  }
+
+  afterAll(() => {
+    jest.clearAllMocks()
+    cleanup()
+  })
+
+  it('renders post composer', async () => {
+    const {findByTestId} = render(<ComposePost {...mockedProps} />)
+    const composePostView = await findByTestId('composePostView')
+    expect(composePostView).toBeTruthy()
+  })
+
+  it('closes composer', async () => {
+    const {findByTestId} = render(<ComposePost {...mockedProps} />)
+    const composerCancelButton = await findByTestId('composerCancelButton')
+    fireEvent.press(composerCancelButton)
+    expect(mockedProps.onClose).toHaveBeenCalled()
+  })
+
+  it('changes text and publishes post', async () => {
+    const postSpy = jest.spyOn(apilib, 'post').mockResolvedValue({
+      uri: '',
+      cid: '',
+    })
+    const toastSpy = jest.spyOn(Toast, 'show')
+
+    const wrapper = render(<ComposePost {...mockedProps} />)
+
+    const composerTextInput = await wrapper.findByTestId('composerTextInput')
+    fireEvent.changeText(composerTextInput, 'testing publish')
+
+    const composerPublishButton = await wrapper.findByTestId(
+      'composerPublishButton',
+    )
+    fireEvent.press(composerPublishButton)
+
+    expect(postSpy).toHaveBeenCalledWith(
+      mockedRootStore,
+      'testing publish',
+      'testUri',
+      [],
+      new Set<string>(),
+      expect.anything(),
+    )
+
+    // Waits for request to be resolved
+    await waitFor(() => {
+      expect(mockedProps.onPost).toHaveBeenCalled()
+      expect(mockedProps.onClose).toHaveBeenCalled()
+      expect(toastSpy).toHaveBeenCalledWith('Your reply has been published', {
+        animation: true,
+        duration: 3500,
+        hideOnPress: true,
+        position: 50,
+        shadow: true,
+      })
+    })
+  })
+
+  it('selects autocomplete item', async () => {
+    jest
+      .spyOn(React, 'useMemo')
+      .mockReturnValueOnce(mockedAutocompleteViewStore)
+
+    const {findAllByTestId} = render(<ComposePost {...mockedProps} />)
+    const autocompleteButton = await findAllByTestId('autocompleteButton')
+
+    fireEvent.press(autocompleteButton[0])
+    expect(mockedAutocompleteViewStore.setActive).toHaveBeenCalledWith(false)
+  })
+
+  it('selects photos', async () => {
+    const {findByTestId, queryByTestId} = render(
+      <ComposePost {...mockedProps} />,
+    )
+    let photoCarouselPickerView = queryByTestId('photoCarouselPickerView')
+    expect(photoCarouselPickerView).toBeFalsy()
+
+    const composerSelectPhotosButton = await findByTestId(
+      'composerSelectPhotosButton',
+    )
+    fireEvent.press(composerSelectPhotosButton)
+
+    photoCarouselPickerView = await findByTestId('photoCarouselPickerView')
+    expect(photoCarouselPickerView).toBeTruthy()
+
+    fireEvent.press(composerSelectPhotosButton)
+
+    photoCarouselPickerView = queryByTestId('photoCarouselPickerView')
+    expect(photoCarouselPickerView).toBeFalsy()
+  })
+})
diff --git a/__tests__/view/com/composer/PhotoCarouselPicker.test.tsx b/__tests__/view/com/composer/PhotoCarouselPicker.test.tsx
new file mode 100644
index 000000000..ef8477652
--- /dev/null
+++ b/__tests__/view/com/composer/PhotoCarouselPicker.test.tsx
@@ -0,0 +1,92 @@
+import React from 'react'
+import {PhotoCarouselPicker} from '../../../../src/view/com/composer/PhotoCarouselPicker'
+import {cleanup, fireEvent, render} from '../../../../jest/test-utils'
+import {
+  openCamera,
+  openCropper,
+  openPicker,
+} from 'react-native-image-crop-picker'
+
+describe('PhotoCarouselPicker', () => {
+  const mockedProps = {
+    selectedPhotos: ['mock-uri', 'mock-uri-2'],
+    onSelectPhotos: jest.fn(),
+    localPhotos: {
+      photos: [
+        {
+          node: {
+            image: {
+              uri: 'mock-uri',
+            },
+          },
+        },
+      ],
+    },
+  }
+
+  afterAll(() => {
+    jest.clearAllMocks()
+    cleanup()
+  })
+
+  it('renders carousel picker', async () => {
+    const {findByTestId} = render(<PhotoCarouselPicker {...mockedProps} />)
+    const photoCarouselPickerView = await findByTestId(
+      'photoCarouselPickerView',
+    )
+    expect(photoCarouselPickerView).toBeTruthy()
+  })
+
+  it('triggers openCamera', async () => {
+    const {findByTestId} = render(<PhotoCarouselPicker {...mockedProps} />)
+    const openCameraButton = await findByTestId('openCameraButton')
+    fireEvent.press(openCameraButton)
+
+    expect(openCamera).toHaveBeenCalledWith({
+      compressImageQuality: 1,
+      cropping: true,
+      forceJpg: true,
+      freeStyleCropEnabled: true,
+      height: 1000,
+      mediaType: 'photo',
+      width: 1000,
+    })
+  })
+
+  it('triggers openCropper', async () => {
+    const {findByTestId} = render(<PhotoCarouselPicker {...mockedProps} />)
+    const openSelectPhotoButton = await findByTestId('openSelectPhotoButton')
+    fireEvent.press(openSelectPhotoButton)
+
+    expect(openCropper).toHaveBeenCalledWith({
+      compressImageQuality: 1,
+      forceJpg: true,
+      freeStyleCropEnabled: true,
+      height: 1000,
+      mediaType: 'photo',
+      path: 'mock-uri',
+      width: 1000,
+    })
+  })
+
+  it('triggers openPicker', async () => {
+    const {findByTestId} = render(<PhotoCarouselPicker {...mockedProps} />)
+    const openGalleryButton = await findByTestId('openGalleryButton')
+    fireEvent.press(openGalleryButton)
+
+    expect(openPicker).toHaveBeenCalledWith({
+      maxFiles: 2,
+      mediaType: 'photo',
+      multiple: true,
+    })
+    expect(openCropper).toHaveBeenCalledWith({
+      compressImageQuality: 1,
+      forceJpg: true,
+      freeStyleCropEnabled: true,
+      height: 1000,
+      mediaType: 'photo',
+      path: 'mock-uri',
+      width: 1000,
+    })
+  })
+})
diff --git a/__tests__/view/com/composer/SelectedPhoto.test.tsx b/__tests__/view/com/composer/SelectedPhoto.test.tsx
new file mode 100644
index 000000000..26059ae30
--- /dev/null
+++ b/__tests__/view/com/composer/SelectedPhoto.test.tsx
@@ -0,0 +1,70 @@
+import React from 'react'
+import {SelectedPhoto} from '../../../../src/view/com/composer/SelectedPhoto'
+import {cleanup, fireEvent, render} from '../../../../jest/test-utils'
+
+describe('SelectedPhoto', () => {
+  const mockedProps = {
+    selectedPhotos: ['mock-uri', 'mock-uri-2'],
+    onSelectPhotos: jest.fn(),
+  }
+
+  afterAll(() => {
+    jest.clearAllMocks()
+    cleanup()
+  })
+
+  it('has no photos to render', () => {
+    const {queryByTestId} = render(
+      <SelectedPhoto selectedPhotos={[]} onSelectPhotos={jest.fn()} />,
+    )
+    const selectedPhotosView = queryByTestId('selectedPhotosView')
+    expect(selectedPhotosView).toBeNull()
+
+    const selectedPhotoImage = queryByTestId('selectedPhotoImage')
+    expect(selectedPhotoImage).toBeNull()
+  })
+
+  it('has 1 photos to render', async () => {
+    const {findByTestId} = render(
+      <SelectedPhoto
+        selectedPhotos={['mock-uri']}
+        onSelectPhotos={jest.fn()}
+      />,
+    )
+    const selectedPhotosView = await findByTestId('selectedPhotosView')
+    expect(selectedPhotosView).toBeTruthy()
+
+    const selectedPhotoImage = await findByTestId('selectedPhotoImage')
+    expect(selectedPhotoImage).toBeTruthy()
+    // @ts-expect-error
+    expect(selectedPhotoImage).toHaveStyle({width: 250})
+  })
+
+  it('has 2 photos to render', async () => {
+    const {findAllByTestId} = render(<SelectedPhoto {...mockedProps} />)
+    const selectedPhotoImage = await findAllByTestId('selectedPhotoImage')
+    expect(selectedPhotoImage[0]).toBeTruthy()
+    // @ts-expect-error
+    expect(selectedPhotoImage[0]).toHaveStyle({width: 175})
+  })
+
+  it('has 3 photos to render', async () => {
+    const {findAllByTestId} = render(
+      <SelectedPhoto
+        selectedPhotos={['mock-uri', 'mock-uri-2', 'mock-uri-3']}
+        onSelectPhotos={jest.fn()}
+      />,
+    )
+    const selectedPhotoImage = await findAllByTestId('selectedPhotoImage')
+    expect(selectedPhotoImage[0]).toBeTruthy()
+    // @ts-expect-error
+    expect(selectedPhotoImage[0]).toHaveStyle({width: 85})
+  })
+
+  it('removes a photo', async () => {
+    const {findAllByTestId} = render(<SelectedPhoto {...mockedProps} />)
+    const removePhotoButton = await findAllByTestId('removePhotoButton')
+    fireEvent.press(removePhotoButton[0])
+    expect(mockedProps.onSelectPhotos).toHaveBeenCalledWith(['mock-uri-2'])
+  })
+})
diff --git a/__tests__/view/com/login/CreateAccount.test.tsx b/__tests__/view/com/login/CreateAccount.test.tsx
new file mode 100644
index 000000000..2de99b2a3
--- /dev/null
+++ b/__tests__/view/com/login/CreateAccount.test.tsx
@@ -0,0 +1,60 @@
+import React from 'react'
+import {Keyboard} from 'react-native'
+import {CreateAccount} from '../../../../src/view/com/login/CreateAccount'
+import {cleanup, fireEvent, render} from '../../../../jest/test-utils'
+import {
+  mockedLogStore,
+  mockedRootStore,
+  mockedSessionStore,
+  mockedShellStore,
+} from '../../../../__mocks__/state-mock'
+
+describe('CreateAccount', () => {
+  const mockedProps = {
+    onPressBack: jest.fn(),
+  }
+  afterAll(() => {
+    jest.clearAllMocks()
+    cleanup()
+  })
+
+  it('renders form and creates new account', async () => {
+    const {findByTestId} = render(<CreateAccount {...mockedProps} />)
+
+    const registerEmailInput = await findByTestId('registerEmailInput')
+    expect(registerEmailInput).toBeTruthy()
+    fireEvent.changeText(registerEmailInput, 'test@email.com')
+
+    const registerHandleInput = await findByTestId('registerHandleInput')
+    expect(registerHandleInput).toBeTruthy()
+    fireEvent.changeText(registerHandleInput, 'test.handle')
+
+    const registerPasswordInput = await findByTestId('registerPasswordInput')
+    expect(registerPasswordInput).toBeTruthy()
+    fireEvent.changeText(registerPasswordInput, 'testpass')
+
+    const registerIs13Input = await findByTestId('registerIs13Input')
+    expect(registerIs13Input).toBeTruthy()
+    fireEvent.press(registerIs13Input)
+
+    const createAccountButton = await findByTestId('createAccountButton')
+    expect(createAccountButton).toBeTruthy()
+    fireEvent.press(createAccountButton)
+
+    expect(mockedSessionStore.createAccount).toHaveBeenCalled()
+  })
+
+  it('renders and selects service', async () => {
+    const keyboardSpy = jest.spyOn(Keyboard, 'dismiss')
+    const {findByTestId} = render(<CreateAccount {...mockedProps} />)
+
+    const registerSelectServiceButton = await findByTestId(
+      'registerSelectServiceButton',
+    )
+    expect(registerSelectServiceButton).toBeTruthy()
+    fireEvent.press(registerSelectServiceButton)
+
+    expect(mockedShellStore.openModal).toHaveBeenCalled()
+    expect(keyboardSpy).toHaveBeenCalled()
+  })
+})
diff --git a/__tests__/view/com/login/Signin.test.tsx b/__tests__/view/com/login/Signin.test.tsx
new file mode 100644
index 000000000..51b411836
--- /dev/null
+++ b/__tests__/view/com/login/Signin.test.tsx
@@ -0,0 +1,128 @@
+import React from 'react'
+import {Signin} from '../../../../src/view/com/login/Signin'
+import {cleanup, fireEvent, render} from '../../../../jest/test-utils'
+import {SessionServiceClient, sessionClient as AtpApi} from '@atproto/api'
+import {
+  mockedLogStore,
+  mockedRootStore,
+  mockedSessionStore,
+  mockedShellStore,
+} from '../../../../__mocks__/state-mock'
+import {Keyboard} from 'react-native'
+
+describe('Signin', () => {
+  const requestPasswordResetMock = jest.fn()
+  const resetPasswordMock = jest.fn()
+  jest.spyOn(AtpApi, 'service').mockReturnValue({
+    com: {
+      atproto: {
+        account: {
+          requestPasswordReset: requestPasswordResetMock,
+          resetPassword: resetPasswordMock,
+        },
+      },
+    },
+  } as unknown as SessionServiceClient)
+  const mockedProps = {
+    onPressBack: jest.fn(),
+  }
+  afterAll(() => {
+    jest.clearAllMocks()
+    cleanup()
+  })
+
+  it('renders logs in form', async () => {
+    const {findByTestId} = render(<Signin {...mockedProps} />)
+
+    const loginFormView = await findByTestId('loginFormView')
+    expect(loginFormView).toBeTruthy()
+
+    const loginUsernameInput = await findByTestId('loginUsernameInput')
+    expect(loginUsernameInput).toBeTruthy()
+
+    fireEvent.changeText(loginUsernameInput, 'testusername')
+
+    const loginPasswordInput = await findByTestId('loginPasswordInput')
+    expect(loginPasswordInput).toBeTruthy()
+
+    fireEvent.changeText(loginPasswordInput, 'test pass')
+
+    const loginNextButton = await findByTestId('loginNextButton')
+    expect(loginNextButton).toBeTruthy()
+
+    fireEvent.press(loginNextButton)
+
+    expect(mockedSessionStore.login).toHaveBeenCalled()
+  })
+
+  it('renders selects service from login form', async () => {
+    const keyboardSpy = jest.spyOn(Keyboard, 'dismiss')
+    const {findByTestId} = render(<Signin {...mockedProps} />)
+
+    const loginSelectServiceButton = await findByTestId(
+      'loginSelectServiceButton',
+    )
+    expect(loginSelectServiceButton).toBeTruthy()
+
+    fireEvent.press(loginSelectServiceButton)
+
+    expect(mockedShellStore.openModal).toHaveBeenCalled()
+    expect(keyboardSpy).toHaveBeenCalled()
+  })
+
+  it('renders new password form', async () => {
+    const {findByTestId} = render(<Signin {...mockedProps} />)
+
+    const forgotPasswordButton = await findByTestId('forgotPasswordButton')
+    expect(forgotPasswordButton).toBeTruthy()
+
+    fireEvent.press(forgotPasswordButton)
+    const forgotPasswordView = await findByTestId('forgotPasswordView')
+    expect(forgotPasswordView).toBeTruthy()
+
+    const forgotPasswordEmail = await findByTestId('forgotPasswordEmail')
+    expect(forgotPasswordEmail).toBeTruthy()
+    fireEvent.changeText(forgotPasswordEmail, 'test@email.com')
+
+    const newPasswordButton = await findByTestId('newPasswordButton')
+    expect(newPasswordButton).toBeTruthy()
+    fireEvent.press(newPasswordButton)
+
+    expect(requestPasswordResetMock).toHaveBeenCalled()
+
+    const newPasswordView = await findByTestId('newPasswordView')
+    expect(newPasswordView).toBeTruthy()
+
+    const newPasswordInput = await findByTestId('newPasswordInput')
+    expect(newPasswordInput).toBeTruthy()
+    const resetCodeInput = await findByTestId('resetCodeInput')
+    expect(resetCodeInput).toBeTruthy()
+
+    fireEvent.changeText(newPasswordInput, 'test pass')
+    fireEvent.changeText(resetCodeInput, 'test reset code')
+
+    const setNewPasswordButton = await findByTestId('setNewPasswordButton')
+    expect(setNewPasswordButton).toBeTruthy()
+
+    fireEvent.press(setNewPasswordButton)
+
+    expect(resetPasswordMock).toHaveBeenCalled()
+  })
+
+  it('renders forgot password form', async () => {
+    const {findByTestId} = render(<Signin {...mockedProps} />)
+
+    const forgotPasswordButton = await findByTestId('forgotPasswordButton')
+    expect(forgotPasswordButton).toBeTruthy()
+
+    fireEvent.press(forgotPasswordButton)
+    const forgotPasswordSelectServiceButton = await findByTestId(
+      'forgotPasswordSelectServiceButton',
+    )
+    expect(forgotPasswordSelectServiceButton).toBeTruthy()
+
+    fireEvent.press(forgotPasswordSelectServiceButton)
+
+    expect(mockedShellStore.openModal).toHaveBeenCalled()
+  })
+})
diff --git a/__tests__/view/com/profile/ProfileHeader.test.tsx b/__tests__/view/com/profile/ProfileHeader.test.tsx
new file mode 100644
index 000000000..52b04e649
--- /dev/null
+++ b/__tests__/view/com/profile/ProfileHeader.test.tsx
@@ -0,0 +1,109 @@
+import React from 'react'
+import {cleanup, fireEvent, render} from '../../../../jest/test-utils'
+import {ProfileViewModel} from '../../../../src/state/models/profile-view'
+import {ProfileHeader} from '../../../../src/view/com/profile/ProfileHeader'
+import {
+  mockedNavigationStore,
+  mockedProfileStore,
+  mockedShellStore,
+} from '../../../../__mocks__/state-mock'
+
+describe('ProfileHeader', () => {
+  const mockedProps = {
+    view: mockedProfileStore,
+    onRefreshAll: jest.fn(),
+  }
+  afterAll(() => {
+    jest.clearAllMocks()
+    cleanup()
+  })
+
+  it('renders ErrorMessage on error', async () => {
+    const {findByTestId} = render(
+      <ProfileHeader
+        {...{
+          view: {
+            ...mockedProfileStore,
+            hasError: true,
+          } as ProfileViewModel,
+          onRefreshAll: jest.fn(),
+        }}
+      />,
+    )
+
+    const profileHeaderHasError = await findByTestId('profileHeaderHasError')
+    expect(profileHeaderHasError).toBeTruthy()
+  })
+
+  it('presses and opens edit profile', async () => {
+    const {findByTestId} = render(<ProfileHeader {...mockedProps} />)
+
+    const profileHeaderEditProfileButton = await findByTestId(
+      'profileHeaderEditProfileButton',
+    )
+    expect(profileHeaderEditProfileButton).toBeTruthy()
+    fireEvent.press(profileHeaderEditProfileButton)
+
+    expect(mockedShellStore.openModal).toHaveBeenCalled()
+  })
+
+  it('presses and opens followers page', async () => {
+    const {findByTestId} = render(<ProfileHeader {...mockedProps} />)
+
+    const profileHeaderFollowersButton = await findByTestId(
+      'profileHeaderFollowersButton',
+    )
+    expect(profileHeaderFollowersButton).toBeTruthy()
+    fireEvent.press(profileHeaderFollowersButton)
+
+    expect(mockedNavigationStore.navigate).toHaveBeenCalledWith(
+      '/profile/testhandle/followers',
+    )
+  })
+
+  it('presses and opens avatar modal', async () => {
+    const {findByTestId} = render(<ProfileHeader {...mockedProps} />)
+
+    const profileHeaderAviButton = await findByTestId('profileHeaderAviButton')
+    expect(profileHeaderAviButton).toBeTruthy()
+    fireEvent.press(profileHeaderAviButton)
+
+    expect(mockedShellStore.openLightbox).toHaveBeenCalled()
+  })
+
+  it('presses and opens follows page', async () => {
+    const {findByTestId} = render(<ProfileHeader {...mockedProps} />)
+
+    const profileHeaderFollowsButton = await findByTestId(
+      'profileHeaderFollowsButton',
+    )
+    expect(profileHeaderFollowsButton).toBeTruthy()
+    fireEvent.press(profileHeaderFollowsButton)
+
+    expect(mockedNavigationStore.navigate).toHaveBeenCalledWith(
+      '/profile/testhandle/follows',
+    )
+  })
+
+  it('toggles following', async () => {
+    const {findByTestId} = render(
+      <ProfileHeader
+        {...{
+          view: {
+            ...mockedProfileStore,
+            did: 'test did 2',
+          } as ProfileViewModel,
+          onRefreshAll: jest.fn(),
+        }}
+      />,
+    )
+
+    const profileHeaderToggleFollowButton = await findByTestId(
+      'profileHeaderToggleFollowButton',
+    )
+    expect(profileHeaderToggleFollowButton).toBeTruthy()
+    fireEvent.press(profileHeaderToggleFollowButton)
+
+    expect(mockedProps.view.toggleFollowing).toHaveBeenCalled()
+  })
+})