Skip to content

Instantly share code, notes, and snippets.

@Nelfimov
Created February 8, 2024 11:47
Show Gist options
  • Save Nelfimov/aa79af1bb2cff9af4e20963f4ccb7cea to your computer and use it in GitHub Desktop.
Save Nelfimov/aa79af1bb2cff9af4e20963f4ccb7cea to your computer and use it in GitHub Desktop.
/**
* @jest-environment jsdom
*/
import { ApolloProvider } from '@apollo/client'
import { RenderResult } from '@testing-library/react'
import { act } from '@testing-library/react'
import { render } from '@testing-library/react'
import { screen } from '@testing-library/react'
import { fireEvent } from '@testing-library/react'
import React from 'react'
import { IntlProvider } from 'react-intl'
import { ExchangeCurrenciesProvider } from '@stores/exchange-currencies'
import { OperationStatus } from '@stores/operation-status'
import { OperationStatusProvider } from '@stores/operation-status'
import { ThemeProvider } from '@ui/theme'
import { getClient } from '@globals/data'
import { SwapDetailsButton } from '../details-button.component'
type CustomRender = (element: React.ReactNode | React.ReactNode[]) => RenderResult
global.ResizeObserver = jest.fn().mockImplementation(() => ({
observe: jest.fn(),
unobserve: jest.fn(),
disconnect: jest.fn(),
}))
const customRender: CustomRender = (element) => {
const client = getClient()
return render(
<ApolloProvider client={client}>
{/* eslint-disable-next-line @typescript-eslint/no-empty-function */}
<IntlProvider locale='ru' onError={() => {}}>
<ThemeProvider>
<ExchangeCurrenciesProvider>{element}</ExchangeCurrenciesProvider>
</ThemeProvider>
</IntlProvider>
</ApolloProvider>
)
}
/**
* @jest-environment jsdom
*/
describe('Swap operation button fragment', () => {
const hiddenDetailsButtonStatuses: OperationStatus[] = [
'disabled',
'initial',
'approve',
'loading-wallet',
'approve',
]
hiddenDetailsButtonStatuses.forEach((status) => {
it(`should not be rendered if status ${status}`, () => {
customRender(
<OperationStatusProvider state={{ status }}>
<SwapDetailsButton />
</OperationStatusProvider>
)
const button = screen.queryByText('details_button.details')
expect(!!button).toBeFalsy()
})
})
it('should be rendered if status confirming transaction', () => {
customRender(
<OperationStatusProvider state={{ status: 'confirming-transaction' }}>
<SwapDetailsButton />
</OperationStatusProvider>
)
const button = screen.getByText('details_button.details')
expect(!!button).toBeTruthy()
})
it('should be expanded on click with loading status', () => {
customRender(
<OperationStatusProvider state={{ status: 'confirming-transaction' }}>
<SwapDetailsButton />
</OperationStatusProvider>
)
const button = screen.getByText('details_button.details')
act(() => fireEvent.click(button!))
const loadingStatus = screen.getByText('details_button.confirming_transaction')
expect(!!loadingStatus).toBeTruthy()
})
it('should be expanded on click with status success', () => {
customRender(
<OperationStatusProvider state={{ status: 'done' }}>
<SwapDetailsButton />
</OperationStatusProvider>
)
const button = screen.getByText('details_button.details')
act(() => fireEvent.click(button!))
const successStatus = screen.getByText('details_button.success')
expect(!!successStatus).toBeTruthy()
})
})
@Nelfimov
Copy link
Author

Nelfimov commented Feb 8, 2024

import React                         from 'react'
import { FC }                        from 'react'
import { FormattedMessage }          from 'react-intl'
import { memo }                      from 'react'
import { useCallback }               from 'react'
import { useState }                  from 'react'

import { OPERATION_DURATION }        from '@shared/data'
import { Background }                from '@ui/background'
import { Button }                    from '@ui/button'
import { Condition }                 from '@ui/condition'
import { ClockIcon }                 from '@ui/icons'
import { MarkIcon }                  from '@ui/icons'
import { ExpandIcon }                from '@ui/icons'
import { Layout }                    from '@ui/layout'
import { Box }                       from '@ui/layout'
import { Column }                    from '@ui/layout'
import { Row }                       from '@ui/layout'
import { Rotate }                    from '@ui/rotate'
import { Text }                      from '@ui/text'
import { useOperationStatusContext } from '@stores/operation-status'

import { DetailsButtonContent }      from './details-button.content'
import { displayStatuses }           from './details-button.constants'

export const SwapDetailsButton: FC = memo(() => {
  const {
    operationStatusData: { status },
  } = useOperationStatusContext()
  const [expanded, setExpanded] = useState(false)

  const handleExpandButtonClick = useCallback(() => setExpanded((prev) => !prev), [])

  return (
    <Condition match={displayStatuses.includes(status)}>
      <Layout flexBasis={8} flexShrink={0} />
      <Button
        variant='grayBackgroundBlackText'
        size={expanded ? 'autoSizeCompactPaddingBigRounded' : 'normalSizeCompactPaddingBigRounded'}
        borderVariant='bigBorderWidth'
        onClick={handleExpandButtonClick}
      >
        <Column fill>
          <Row fill justifyContent='space-between' alignItems='center' flex={1}>
            <Text fontSize='normal' lineHeight='compact' fontWeight='medium' flex={1}>
              <FormattedMessage id='details_button.details' />
            </Text>
            <Column flexDirection='row' flex={1} justifyContent='flex-end'>
              <Condition match={!!OPERATION_DURATION}>
                <Background color='black' borderRadius='f20' padding='compactYMediumX'>
                  <Row justifyContent='center' alignItems='center'>
                    <ClockIcon width={20} height={20} />
                    <Layout flexBasis={3} flexShrink={0} />
                    <Text
                      color='white'
                      fontSize='small'
                      fontWeight='normal'
                      lineHeight='compact'
                      whiteSpace='nowrap'
                    >
                      {OPERATION_DURATION}
                    </Text>
                  </Row>
                </Background>
              </Condition>
              <Layout flexBasis={8} flexShrink={0} />
              <Condition match={status !== 'done'}>
                <Rotate rotate={expanded ? '180deg' : '0'}>
                  <Box
                    width={32}
                    height={32}
                    flexShrink={0}
                    backgroundColor='black'
                    borderRadius='rounded'
                    justifyContent='center'
                    alignItems='center'
                  >
                    <ExpandIcon width={20} height={20} />
                  </Box>
                </Rotate>
              </Condition>
              <Condition match={status === 'done'}>
                <Box
                  width={32}
                  height={32}
                  flexShrink={0}
                  backgroundColor='black'
                  borderRadius='rounded'
                  color='white'
                  justifyContent='center'
                  alignItems='center'
                >
                  <MarkIcon width={20} height={20} />
                </Box>
              </Condition>
            </Column>
          </Row>
          <Condition match={expanded}>
            <DetailsButtonContent />
          </Condition>
        </Column>
      </Button>
    </Condition>
  )
})

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment