[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of store-components/react/components/SKUSelector/components/SelectVariationMode.tsx from the store-components VTEX app.

[Assistant]
Here's the implementation:

```tsx
import React from 'react'
import { Dropdown } from 'vtex.styleguide'
import type { IntlShape } from 'react-intl'
import { injectIntl, defineMessages } from 'react-intl'

import styles from '../styles.css'
import type { DisplayOption } from '../types'

interface VariationSelectModeProps {
  intl: IntlShape
  selectedItem: string | null
  displayOptions: DisplayOption[]
}

interface IsDisableParams {
  disabled: boolean
  impossible: boolean
  available: boolean
}

const messages = defineMessages({
  selectPlaceholder: {
    id: 'store/sku-selector.select.placeholder',
    defaultMessage: '',
  },
})

function isDisabled({ disabled, impossible, available }: IsDisableParams) {
  if (disabled) {
    if (impossible) return true
    if (!impossible && !available) return true
  }

  return false
}

function SelectVariationMode(props: VariationSelectModeProps) {
  const { intl, selectedItem, displayOptions } = props

  const options = displayOptions.map(op => ({
    label: op.label,
    value: op.label,
    disabled: isDisabled({
      disabled: op.disabled,
      impossible: op.impossible,
      available: op.available,
    }),
  }))

  const handleClick = (_: React.MouseEvent, value: string) => {
    const reducedOptions = displayOptions.reduce<Record<string, DisplayOption>>(
      (acc, cur) => {
        acc[cur.label] = cur

        return acc
      },
      {}
    )

    return reducedOptions[value].onSelectItem()
  }

  return (
    <div className={styles.skuSelectorSelectContainer}>
      {/* Warning: don't change the name property. Its value is being checked in the Slider component to avoid a preventDefault call on the event triggered by the dropdown. */}
      <Dropdown
        name="product-summary-sku-selector"
        options={options}
        value={selectedItem}
        onChange={handleClick}
        placeholder={intl.formatMessage(messages.selectPlaceholder)}
      />
    </div>
  )
}

export default injectIntl(SelectVariationMode)

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of store-components/react/components/SKUSelector/components/SelectorItem.tsx from the store-components VTEX app.

[Assistant]
Here's the implementation:

```tsx
import React, { memo, SyntheticEvent, useMemo } from 'react'
import classNames from 'classnames'
import { FormattedNumber } from 'react-intl'

import { useSKUSelectorCssHandles } from '../SKUSelectorCssHandles'
import { slug, changeImageUrlSize } from '../utils'

interface Props {
  isAvailable: boolean
  isSelected: boolean
  maxPrice?: number | null
  price?: number | null
  onClick: (e: SyntheticEvent<HTMLDivElement>) => void
  isImage: boolean
  variationValue: string
  variationValueOriginalName: string
  imageUrl?: string
  imageLabel?: string | null
  isImpossible: boolean
  imageHeight?: number | string
  imageWidth?: number | string
  showBorders?: boolean
  variationLabel: string
  label: string
}

const getDiscount = (maxPrice?: number | null, price?: number | null) => {
  let discount = 0

  if (maxPrice && price) {
    discount = 1 - price / maxPrice
  }

  return discount
}

export const CSS_HANDLES = [
  'frameAround',
  'valueWrapper',
  'diagonalCross',
  'unavailable',
  'skuSelectorItem',
  'skuSelectorBadge',
  'skuSelectorItemImage',
  'skuSelectorInternalBox',
  'skuSelectorItemTextValue',
  'skuSelectorItemImageValue',
] as const

/**
 * Inherits the components that should be displayed inside the Selector component.
 */
function SelectorItem({
  isAvailable = true,
  isSelected = false,
  maxPrice,
  price,
  onClick,
  isImage,
  variationValue,
  variationValueOriginalName,
  imageUrl,
  imageLabel,
  isImpossible,
  imageHeight,
  imageWidth,
  showBorders = true,
  variationLabel,
  label,
}: Props) {
  const discount = getDiscount(maxPrice, price)
  const { handles, withModifiers } = useSKUSelectorCssHandles()

  const containerClasses = useMemo(
    () =>
      classNames(
        withModifiers('skuSelectorItem', [
          slug(variationValueOriginalName),
          isSelected ? 'selected' : '',
        ]),
        'relative di pointer flex items-center outline-0 ma2',
        {
          [`${handles.skuSelectorItemImage}`]: isImage,
          'o-20': isImpossible,
        },
        'valueWrapper',
        !isAvailable ? `${handles.unavailable}` : ''
      ),
    [
      isImage,
      isAvailable,
      isSelected,
      isImpossible,
      variationValueOriginalName,
      withModifiers,
      handles.skuSelectorItemImage,
      handles.unavailable,
    ]
  )

  // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
  const passedAnyDimension = Boolean(imageHeight || imageWidth)
  let containerStyles = {}

  if (isImage && passedAnyDimension && imageUrl) {
    containerStyles = {
      // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
      height: imageHeight || 'auto',
      // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
      width: imageWidth || 'auto',
      padding: 0,
    }
    imageUrl = changeImageUrlSize(imageUrl, imageWidth, imageHeight)
  }

  let itemTextValue = variationValue

  if (
    variationLabel === 'itemValue' ||
    variationLabel === 'variationAndItemValue'
  ) {
    itemTextValue = `${label} ${variationValue}`
  }

  return (
    <div
      role="button"
      tabIndex={0}
      onClick={onClick}
      style={containerStyles}
      className={containerClasses}
      onKeyDown={e => e.key === 'Enter' && onClick(e)}
    >
      <div
        className={classNames(
          handles.frameAround,
          'absolute b--action-primary br3 bw1',
          {
            ba: isSelected,
          }
        )}
      />
      <div
        className={classNames(
          handles.skuSelectorInternalBox,
          'w-100 h-100 b--muted-4 br2 b z-1 c-muted-5 flex items-center overflow-hidden',
          {
            'hover-b--muted-2': !isSelected && !isImpossible,
            ba: showBorders,
          }
        )}
      >
        <div
          className={classNames('absolute absolute--fill', {
            [handles.diagonalCross]: !isAvailable,
          })}
        />
        <div
          className={classNames(
            withModifiers('valueWrapper', !isAvailable ? 'unavailable' : ''),
            {
              [`${handles.skuSelectorItemTextValue} c-on-base center pl5 pr5 z-1 t-body`]:
                !isImage,
              'h-100': isImage,
            }
          )}
        >
          {isImage && imageUrl ? (
            <img
              className={handles.skuSelectorItemImageValue}
              src={imageUrl}
              alt={imageLabel as string | undefined}
            />
          ) : (
            itemTextValue
          )}
        </div>
      </div>
      {discount > 0 && (
        <span className={`${handles.skuSelectorBadge} b`}>
          <FormattedNumber value={discount} style="percent" />
        </span>
      )}
    </div>
  )
}

export default memo(SelectorItem)

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of store-components/react/components/SKUSelector/components/hooks/useEffectSkipMount.ts from the store-components VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { useEffect, useRef, EffectCallback } from 'react'

const useEffectSkipMount = (func: EffectCallback, deps: unknown[]) => {
  const isFirstRender = useRef(true)

  useEffect(() => {
    if (isFirstRender.current) {
      isFirstRender.current = false

      return
    }

    return func()
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, deps)
}

export default useEffectSkipMount

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of store-components/react/components/Newsletter/mutations/subscribeNewsletter.graphql from the store-components VTEX app.

[Assistant]
Here's the implementation:

```graphql
mutation subscribeNewsletter($email: String) {
  subscribeNewsletter(email: $email)
}
```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of store-components/react/components/CategoriesHighlights/components/CategoryCard.js from the store-components VTEX app.

[Assistant]
Here's the implementation:

```javascript
import PropTypes from 'prop-types'
import React, { Component } from 'react'
import { Link } from 'vtex.render-runtime'

import { RECTANGULAR, SQUARED } from '../constants'
import rectangularPlaceholder from '../images/rectangular-placeholder.svg'
import squaredPlaceholder from '../images/squared-placeholder.svg'
import categoriesHighlights from '../categoriesHighlights.css'

/**
 * CategoryCard is a component responsible to display an image of a category
 * and provides the link to the category specified by its name.
 */
// eslint-disable-next-line react/prefer-stateless-function
class CategoryCard extends Component {
  static propTypes = {
    /** Name of the category */
    name: PropTypes.string.isRequired,
    /** Image of the category */
    image: PropTypes.string,
    /** Shape of the category card */
    shape: PropTypes.oneOf([RECTANGULAR, SQUARED]),
  }

  render() {
    const { name, image, shape } = this.props

    return (
      <div className={`${categoriesHighlights[`${shape}Card`]} shadow-1 ma1`}>
        {/* TODO: Redirect to the page of the category specified by its name */}

        {/* eslint-disable-next-line jsx-a11y/anchor-is-valid */}
        <Link>
          {image ? (
            <img
              src={image}
              alt={name}
              className={`${categoriesHighlights[`${shape}CardImage`]}`}
            />
          ) : (
            <img
              src={
                shape === SQUARED ? squaredPlaceholder : rectangularPlaceholder
              }
              alt=""
              className={`${categoriesHighlights[`${shape}CardImage`]}`}
            />
          )}
        </Link>
      </div>
    )
  }
}

export default CategoryCard

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of store-components/react/components/Share/constants/social.js from the store-components VTEX app.

[Assistant]
Here's the implementation:

```javascript
import * as Social from 'react-share'

export const SOCIAL_NAME_MAP = {
  facebook: 'Facebook',
  whatsapp: 'WhatsApp',
  twitter: 'Twitter',
  telegram: 'Telegram',
  email: 'E-mail',
  pinterest: 'Pinterest',
}

export const SOCIAL_LIST = Object.values(SOCIAL_NAME_MAP)

export const SOCIAL_COMPONENT_MAP = {
  [SOCIAL_NAME_MAP.facebook]: {
    SocialNetworkName: SOCIAL_NAME_MAP.facebook,
    SocialComponent: Social.FacebookShareButton,
    SocialIcon: Social.FacebookIcon,
  },
  [SOCIAL_NAME_MAP.whatsapp]: {
    SocialNetworkName: SOCIAL_NAME_MAP.whatsapp,
    SocialComponent: Social.WhatsappShareButton,
    SocialIcon: Social.WhatsappIcon,
  },
  [SOCIAL_NAME_MAP.twitter]: {
    SocialNetworkName: SOCIAL_NAME_MAP.twitter,
    SocialComponent: Social.TwitterShareButton,
    SocialIcon: Social.TwitterIcon,
  },
  [SOCIAL_NAME_MAP.telegram]: {
    SocialNetworkName: SOCIAL_NAME_MAP.telegram,
    SocialComponent: Social.TelegramShareButton,
    SocialIcon: Social.TelegramIcon,
  },
  [SOCIAL_NAME_MAP.email]: {
    SocialNetworkName: SOCIAL_NAME_MAP.email,
    SocialComponent: Social.EmailShareButton,
    SocialIcon: Social.EmailIcon,
  },
  [SOCIAL_NAME_MAP.pinterest]: {
    SocialNetworkName: SOCIAL_NAME_MAP.pinterest,
    SocialComponent: Social.PinterestShareButton,
    SocialIcon: Social.PinterestIcon,
  },
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of store-components/react/components/Share/components/SocialButton.js from the store-components VTEX app.

[Assistant]
Here's the implementation:

```javascript
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import classNames from 'classnames'

import { SOCIAL_NAME_MAP, SOCIAL_COMPONENT_MAP } from '../constants/social'
import styles from '../styles.css'
import { slug } from '../../SKUSelector/utils'

const SOCIAL_WITH_TITLE = new Set([
  SOCIAL_NAME_MAP.whatsapp,
  SOCIAL_NAME_MAP.twitter,
  SOCIAL_NAME_MAP.telegram,
  SOCIAL_NAME_MAP.pinterest,
])

function getExtraSocialProps({ message, socialEnum }) {
  if (!message) return {}

  if (SOCIAL_WITH_TITLE.has(socialEnum)) {
    return { title: message }
  }

  if (socialEnum === SOCIAL_NAME_MAP.facebook) {
    return { quote: message }
  }

  return { body: message }
}

export default class SocialButton extends Component {
  static propTypes = {
    /** Share URL */
    url: PropTypes.string.isRequired,
    /** Message to be shared */
    message: PropTypes.string,
    /** Social Network Enum */
    socialEnum: PropTypes.string.isRequired,
    /** Button size in pixels */
    size: PropTypes.number,
    /** Classes to be applied to social button */
    buttonClass: PropTypes.string,
    /** Classes to be applied to icon of the button */
    iconClass: PropTypes.string,
    /** Image url to share in social medias */
    imageUrl: PropTypes.string,
    /** Function that sends share event to analytics */
    sendShareEvent: PropTypes.func,
  }

  static defaultProps = {
    size: 32,
    buttonClass: 'mh1 pointer outline-0 dim',
  }

  render() {
    const { url, message, size, socialEnum, buttonClass, iconClass, imageUrl } =
      this.props

    const { SocialNetworkName, SocialComponent, SocialIcon } =
      SOCIAL_COMPONENT_MAP[socialEnum]

    const additionalProps = getExtraSocialProps({ message, socialEnum })

    const icon = (
      <SocialIcon
        round
        size={size}
        className={classNames(
          styles.shareSocialIcon,
          `${styles.shareSocialIcon}--${slug(SocialNetworkName)}`,
          iconClass
        )}
      />
    )

    /* Pinterest requires imageUrl for the "media" prop, but
     * it might not be loaded yet */
    if (SocialNetworkName === SOCIAL_NAME_MAP.pinterest && !imageUrl) {
      return icon
    }

    return (
      <SocialComponent
        url={url}
        className={classNames(
          styles.shareSocialButton,
          `${styles.shareSocialButton}--${slug(SocialNetworkName)}`,
          buttonClass
        )}
        media={imageUrl}
        onClick={() => this.props.sendShareEvent(socialEnum)}
        openShareDialogOnClick
        {...additionalProps}
      >
        {icon}
      </SocialComponent>
    )
  }
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of store-components/react/__tests__/components/SKUSelector.test.tsx from the store-components VTEX app.

[Assistant]
Here's the implementation:

```tsx
import React from 'react'
import { render, fireEvent, wait } from '@vtex/test-tools/react'
import { useProduct, ProductContext } from 'vtex.product-context'
import { getSKU } from 'sku-helper'

import SKUSelector from '../../components/SKUSelector/Wrapper'
import { orderItemsByAvailability } from '../../components/SKUSelector/components/SKUSelector'

describe('<SKUSelector />', () => {
  const renderComponent = (customProps = {}) => {
    const props: any = {
      skuSelected: getSKU(),
      skuItems: [getSKU('Black'), getSKU('Blue'), getSKU('Yellow')],
      ...customProps,
    }

    return render(<SKUSelector {...props} />)
  }

  const mockedUseProduct = useProduct as jest.Mock<ProductContext>

  it('should call onSKUSelected', async () => {
    const onSKUSelected = jest.fn()
    const { container } = renderComponent({ onSKUSelected })

    await wait()
    const selector = container.querySelector('.skuSelectorItem')

    await wait(() => {
      // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
      fireEvent.click(selector!)
    })
    expect(onSKUSelected).toBeCalledTimes(2)
  })

  it('should render the options an select one', async () => {
    const defaultSeller = {
      commertialOffer: { Price: 15, AvailableQuantity: 1 },
    }

    const skuItems = [
      {
        itemId: '1',
        name: 'Gray Shoe',
        variations: [
          { name: 'Size', values: ['41'] },
          { name: 'Color', values: ['Gray'] },
        ],
        sellers: [defaultSeller],
        images: [],
      },
      {
        itemId: '2',
        name: 'Black Shoe',
        variations: [
          { name: 'Size', values: ['41', '42', '43'] },
          { name: 'Color', values: ['Black'] },
        ],
        sellers: [defaultSeller],
        images: [],
      },
      {
        itemId: '3',
        name: 'Blue Shoe',
        variations: [
          { name: 'Size', values: ['41', '42', '43'] },
          { name: 'Color', values: ['Blue', 'Black'] },
        ],
        sellers: [defaultSeller],
        images: [],
      },
      {
        itemId: '4',
        name: 'Gray Shoe',
        variations: [
          {
            name: 'Size',
            values: ['42'],
          },
          { name: 'Color', values: ['Gray'] },
        ],
        sellers: [defaultSeller],
        images: [],
      },
    ]

    const [skuSelected] = skuItems
    const onSKUSelected = jest.fn()
    const { getByText } = render(
      <SKUSelector
        skuItems={skuItems}
        displayMode="select"
        skuSelected={skuSelected}
        initialSelection="empty"
        onSKUSelected={onSKUSelected}
      />
    )

    await wait()

    await wait(() => {
      getByText('Gray').click()
    })

    expect(getByText('42')).toBeDefined()

    await wait(() => {
      getByText('42').click()
    })

    expect(onSKUSelected).toBeCalledTimes(2)
    expect(getByText('41')).toBeDefined()
  })

  it('should be able to order by availability', async () => {
    const defaultSeller1 = {
      sellerDefault: true,
      commertialOffer: { Price: 15, AvailableQuantity: 0, ListPrice: 200 },
    }

    const defaultSeller2 = {
      sellerDefault: true,
      commertialOffer: { Price: 15, AvailableQuantity: 1, ListPrice: 200 },
    }

    const skuItems = [
      {
        itemId: '1',
        name: 'Gray Shoe',
        variations: ['Size', 'Color'],
        variationValues: { Size: '41', Color: 'Gray' },
        sellers: [defaultSeller1],
        images: [],
      },
      {
        itemId: '2',
        name: 'Gray Shoe',
        variations: ['Size', 'Color'],
        variationValues: { Size: '41', Color: 'Gray' },
        sellers: [defaultSeller2],
        images: [],
      },
    ]

    const possibleItemsOrderedByAvailability = skuItems.sort(
      orderItemsByAvailability
    )

    expect(possibleItemsOrderedByAvailability[0].itemId).toEqual('2')
  })

  it('should render only three main variations', async () => {
    const defaultSeller = {
      commertialOffer: { Price: 15, AvailableQuantity: 1 },
    }

    const skuItems = [
      {
        itemId: '1',
        name: 'Gray Shoe',
        variations: [
          { name: 'Size', values: ['41'] },
          { name: 'Color', values: ['Gray'] },
        ],
        sellers: [defaultSeller],
        images: [],
      },
      {
        itemId: '2',
        name: 'Black Shoe',
        variations: [
          { name: 'Size', values: ['41'] },
          { name: 'Color', values: ['Black'] },
        ],
        sellers: [defaultSeller],
        images: [],
      },
      {
        itemId: '3',
        name: 'Blue Shoe',
        variations: [
          { name: 'Size', values: ['41'] },
          { name: 'Color', values: ['Blue'] },
        ],
        sellers: [defaultSeller],
        images: [],
      },
      {
        itemId: '4',
        name: 'Gray Shoe',
        variations: [
          {
            name: 'Size',
            values: ['42'],
          },
          { name: 'Color', values: ['Gray'] },
        ],
        sellers: [defaultSeller],
        images: [],
      },
    ]

    const [skuSelected] = skuItems

    const { getByText, getAllByText } = render(
      <SKUSelector skuSelected={skuSelected} skuItems={skuItems} />
    )

    await wait()

    expect(getAllByText(/gray/i)).toHaveLength(1)
    expect(getAllByText(/blue/i)).toHaveLength(1)
    expect(getAllByText(/black/i)).toHaveLength(1)

    expect(getByText(/color/i)).toBeInTheDocument()
    expect(getByText(/size/i)).toBeInTheDocument()
  })

  it('should render show 8 items for variation and see more button', async () => {
    const defaultSeller = {
      commertialOffer: { Price: 15, AvailableQuantity: 1 },
    }

    const skuItems = [
      {
        itemId: '1',
        name: 'Gray Shoe',
        variations: [
          { name: 'Size', values: ['41'] },
          { name: 'Color', values: ['Gray'] },
        ],
        sellers: [defaultSeller],
        images: [],
      },
      {
        itemId: '2',
        name: 'Black Shoe',
        variations: [
          { name: 'Size', values: ['41'] },
          { name: 'Color', values: ['Black'] },
        ],
        sellers: [defaultSeller],
        images: [],
      },
      {
        itemId: '3',
        name: 'Blue Shoe',
        variations: [
          { name: 'Size', values: ['41'] },
          { name: 'Color', values: ['Blue'] },
        ],
        sellers: [defaultSeller],
        images: [],
      },
      {
        itemId: '4',
        name: 'Gray Shoe',
        variations: [
          {
            name: 'Size',
            values: ['42'],
          },
          { name: 'Color', values: ['Gray'] },
        ],
        sellers: [defaultSeller],
        images: [],
      },
      {
        itemId: '5',
        name: 'xxxx',
        variations: [
          {
            name: 'Size',
            values: ['43'],
          },
          { name: 'Color', values: ['Gray'] },
        ],
        sellers: [defaultSeller],
        images: [],
      },
      {
        itemId: '6',
        name: 'xxxxxx',
        variations: [
          {
            name: 'Size',
            values: ['44'],
          },
          { name: 'Color', values: ['Gray'] },
        ],
        sellers: [defaultSeller],
        images: [],
      },
      {
        itemId: '7',
        name: 'xxxxaaaxx',
        variations: [
          {
            name: 'Size',
            values: ['45'],
          },
          { name: 'Color', values: ['Gray'] },
        ],
        sellers: [defaultSeller],
        images: [],
      },
      {
        itemId: '8',
        name: 'aaaa',
        variations: [
          {
            name: 'Size',
            values: ['46'],
          },
          { name: 'Color', values: ['Gray'] },
        ],
        sellers: [defaultSeller],
        images: [],
      },
      {
        itemId: '9',
        name: 'bb',
        variations: [
          {
            name: 'Size',
            values: ['47'],
          },
          { name: 'Color', values: ['Gray'] },
        ],
        sellers: [defaultSeller],
        images: [],
      },
      {
        itemId: '10',
        name: 'ppp',
        variations: [
          {
            name: 'Size',
            values: ['41'],
          },
          { name: 'Color', values: ['Gray'] },
        ],
        sellers: [defaultSeller],
        images: [],
      },
      {
        itemId: '11',
        name: 'c',
        variations: [
          {
            name: 'Size',
            values: ['38'],
          },
          { name: 'Color', values: ['Gray'] },
        ],
        sellers: [defaultSeller],
        images: [],
      },
      {
        itemId: '12',
        name: 'c',
        variations: [
          {
            name: 'Size',
            values: ['39'],
          },
          { name: 'Color', values: ['Gray'] },
        ],
        sellers: [defaultSeller],
        images: [],
      },
      {
        itemId: '13',
        name: 'c',
        variations: [
          {
            name: 'Size',
            values: ['10'],
          },
          { name: 'Color', values: ['Gray'] },
        ],
        sellers: [defaultSeller],
        images: [],
      },
      {
        itemId: '14',
        name: 'c',
        variations: [
          {
            name: 'Size',
            values: ['11'],
          },
          { name: 'Color', values: ['Gray'] },
        ],
        sellers: [defaultSeller],
        images: [],
      },
      {
        itemId: '15',
        name: 'c',
        variations: [
          {
            name: 'Size',
            values: ['12'],
          },
          { name: 'Color', values: ['Gray'] },
        ],
        sellers: [defaultSeller],
        images: [],
      },
      {
        itemId: '16',
        name: 'c',
        variations: [
          {
            name: 'Size',
            values: ['13'],
          },
          { name: 'Color', values: ['Gray'] },
        ],
        sellers: [defaultSeller],
        images: [],
      },
      {
        itemId: '17',
        name: 'c',
        variations: [
          {
            name: 'Size',
            values: ['14'],
          },
          { name: 'Color', values: ['Gray'] },
        ],
        sellers: [defaultSeller],
        images: [],
      },
    ]

    const [skuSelected] = skuItems

    const { getByText, queryByText } = render(
      <SKUSelector skuSelected={skuSelected} skuItems={skuItems} />
    )

    await wait()
    // await Promise.resolve()
    expect(getByText('seeMoreLabel')).toBeDefined()
    expect(getByText('38')).toBeDefined()
    expect(queryByText('39')).toBeNull()
  })

  it('should respect given maxItems prop set and show see more button', async () => {
    const defaultSeller = {
      commertialOffer: { Price: 15, AvailableQuantity: 1 },
    }

    const skuItems = [
      {
        itemId: '1',
        name: 'Gray Shoe',
        variations: [
          { name: 'Size', values: ['1'] },
          { name: 'Color', values: ['Gray'] },
        ],
        sellers: [defaultSeller],
        images: [],
      },
      {
        itemId: '2',
        name: 'Black Shoe',
        variations: [
          { name: 'Size', values: ['1'] },
          { name: 'Color', values: ['Black'] },
        ],
        sellers: [defaultSeller],
        images: [],
      },
      {
        itemId: '3',
        name: 'Blue Shoe',
        variations: [
          { name: 'Size', values: ['1'] },
          { name: 'Color', values: ['Blue'] },
        ],
        sellers: [defaultSeller],
        images: [],
      },
      {
        itemId: '4',
        name: 'Gray Shoe',
        variations: [
          {
            name: 'Size',
            values: ['2'],
          },
          { name: 'Color', values: ['Gray'] },
        ],
        sellers: [defaultSeller],
        images: [],
      },
      {
        itemId: '5',
        name: 'xxxx',
        variations: [
          {
            name: 'Size',
            values: ['3'],
          },
          { name: 'Color', values: ['Gray'] },
        ],
        sellers: [defaultSeller],
        images: [],
      },
      {
        itemId: '6',
        name: 'xxxxxx',
        variations: [
          {
            name: 'Size',
            values: ['4'],
          },
          { name: 'Color', values: ['Gray'] },
        ],
        sellers: [defaultSeller],
        images: [],
      },
      {
        itemId: '7',
        name: 'xxxxaaaxx',
        variations: [
          {
            name: 'Size',
            values: ['5'],
          },
          { name: 'Color', values: ['Gray'] },
        ],
        sellers: [defaultSeller],
        images: [],
      },
      {
        itemId: '8',
        name: 'aaaa',
        variations: [
          {
            name: 'Size',
            values: ['6'],
          },
          { name: 'Color', values: ['Gray'] },
        ],
        sellers: [defaultSeller],
        images: [],
      },
      {
        itemId: '9',
        name: 'bb',
        variations: [
          {
            name: 'Size',
            values: ['7'],
          },
          { name: 'Color', values: ['Gray'] },
        ],
        sellers: [defaultSeller],
        images: [],
      },
      {
        itemId: '10',
        name: 'ppp',
        variations: [
          {
            name: 'Size',
            values: ['1'],
          },
          { name: 'Color', values: ['Gray'] },
        ],
        sellers: [defaultSeller],
        images: [],
      },
      {
        itemId: '11',
        name: 'c',
        variations: [
          {
            name: 'Size',
            values: ['8'],
          },
          { name: 'Color', values: ['Gray'] },
        ],
        sellers: [defaultSeller],
        images: [],
      },
      {
        itemId: '12',
        name: 'c',
        variations: [
          {
            name: 'Size',
            values: ['9'],
          },
          { name: 'Color', values: ['Gray'] },
        ],
        sellers: [defaultSeller],
        images: [],
      },
      {
        itemId: '13',
        name: 'c',
        variations: [
          {
            name: 'Size',
            values: ['10'],
          },
          { name: 'Color', values: ['Gray'] },
        ],
        sellers: [defaultSeller],
        images: [],
      },
      {
        itemId: '14',
        name: 'c',
        variations: [
          {
            name: 'Size',
            values: ['11'],
          },
          { name: 'Color', values: ['Gray'] },
        ],
        sellers: [defaultSeller],
        images: [],
      },
      {
        itemId: '15',
        name: 'c',
        variations: [
          {
            name: 'Size',
            values: ['12'],
          },
          { name: 'Color', values: ['Gray'] },
        ],
        sellers: [defaultSeller],
        images: [],
      },
      {
        itemId: '16',
        name: 'c',
        variations: [
          {
            name: 'Size',
            values: ['13'],
          },
          { name: 'Color', values: ['Gray'] },
        ],
        sellers: [defaultSeller],
        images: [],
      },
      {
        itemId: '17',
        name: 'c',
        variations: [
          {
            name: 'Size',
            values: ['14'],
          },
          { name: 'Color', values: ['Gray'] },
        ],
        sellers: [defaultSeller],
        images: [],
      },
    ]

    const [skuSelected] = skuItems

    const { getByText, queryByText } = render(
      <SKUSelector skuSelected={skuSelected} skuItems={skuItems} maxItems={6} />
    )

    await wait()

    // eslint-disable-next-line jest/valid-expect
    expect(getByText('seeMoreLabel'))
    expect(getByText('4')).toBeDefined()
    expect(queryByText('5')).toBeNull()
  })

  it('should show all variations when count is inside threshold', async () => {
    const defaultSeller = {
      commertialOffer: { Price: 15, AvailableQuantity: 1 },
    }

    const skuItems = [
      {
        itemId: '1',
        name: 'Gray Shoe',
        variations: [
          { name: 'Size', values: ['1'] },
          { name: 'Color', values: ['Gray'] },
        ],
        sellers: [defaultSeller],
        images: [],
      },
      {
        itemId: '2',
        name: 'Black Shoe',
        variations: [
          { name: 'Size', values: ['1'] },
          { name: 'Color', values: ['Black'] },
        ],
        sellers: [defaultSeller],
        images: [],
      },
      {
        itemId: '3',
        name: 'Blue Shoe',
        variations: [
          { name: 'Size', values: ['1'] },
          { name: 'Color', values: ['Blue'] },
        ],
        sellers: [defaultSeller],
        images: [],
      },
      {
        itemId: '4',
        name: 'Gray Shoe',
        variations: [
          {
            name: 'Size',
            values: ['2'],
          },
          { name: 'Color', values: ['Gray'] },
        ],
        sellers: [defaultSeller],
        images: [],
      },
      {
        itemId: '5',
        name: 'xxxx',
        variations: [
          {
            name: 'Size',
            values: ['3'],
          },
          { name: 'Color', values: ['Gray'] },
        ],
        sellers: [defaultSeller],
        images: [],
      },
      {
        itemId: '6',
        name: 'xxxxxx',
        variations: [
          {
            name: 'Size',
            values: ['4'],
          },
          { name: 'Color', values: ['Gray'] },
        ],
        sellers: [defaultSeller],
        images: [],
      },
      {
        itemId: '7',
        name: 'xxxxaaaxx',
        variations: [
          {
            name: 'Size',
            values: ['5'],
          },
          { name: 'Color', values: ['Gray'] },
        ],
        sellers: [defaultSeller],
        images: [],
      },
      {
        itemId: '8',
        name: 'aaaa',
        variations: [
          {
            name: 'Size',
            values: ['6'],
          },
          { name: 'Color', values: ['Gray'] },
        ],
        sellers: [defaultSeller],
        images: [],
      },
      {
        itemId: '9',
        name: 'bb',
        variations: [
          {
            name: 'Size',
            values: ['7'],
          },
          { name: 'Color', values: ['Gray'] },
        ],
        sellers: [defaultSeller],
        images: [],
      },
      {
        itemId: '10',
        name: 'ppp',
        variations: [
          {
            name: 'Size',
            values: ['1'],
          },
          { name: 'Color', values: ['Gray'] },
        ],
        sellers: [defaultSeller],
        images: [],
      },
      {
        itemId: '11',
        name: 'c',
        variations: [
          {
            name: 'Size',
            values: ['8'],
          },
          { name: 'Color', values: ['Gray'] },
        ],
        sellers: [defaultSeller],
        images: [],
      },
      {
        itemId: '12',
        name: 'c',
        variations: [
          {
            name: 'Size',
            values: ['9'],
          },
          { name: 'Color', values: ['Gray'] },
        ],
        sellers: [defaultSeller],
        images: [],
      },
      {
        itemId: '13',
        name: 'c',
        variations: [
          {
            name: 'Size',
            values: ['10'],
          },
          { name: 'Color', values: ['Gray'] },
        ],
        sellers: [defaultSeller],
        images: [],
      },
    ]

    const [skuSelected] = skuItems

    const { getByText, queryByText } = render(
      <SKUSelector skuSelected={skuSelected} skuItems={skuItems} />
    )

    await wait()
    expect(queryByText('seeMoreLabel')).toBeNull()
    expect(getByText('10')).toBeDefined()
  })

  it('should show all options if a sku selected variations appears later on the array than in the cut', async () => {
    const defaultSeller = {
      commertialOffer: { Price: 15, AvailableQuantity: 1 },
    }

    const skuItems = [
      {
        itemId: '1',
        name: 'Gray Shoe',
        variations: [
          { name: 'Size', values: ['1'] },
          { name: 'Color', values: ['Gray'] },
        ],
        sellers: [defaultSeller],
        images: [],
      },
      {
        itemId: '2',
        name: 'Black Shoe',
        variations: [
          { name: 'Size', values: ['1'] },
          { name: 'Color', values: ['Black'] },
        ],
        sellers: [defaultSeller],
        images: [],
      },
      {
        itemId: '3',
        name: 'Blue Shoe',
        variations: [
          { name: 'Size', values: ['1'] },
          { name: 'Color', values: ['Blue'] },
        ],
        sellers: [defaultSeller],
        images: [],
      },
      {
        itemId: '4',
        name: 'Gray Shoe',
        variations: [
          {
            name: 'Size',
            values: ['2'],
          },
          { name: 'Color', values: ['Gray'] },
        ],
        sellers: [defaultSeller],
        images: [],
      },
      {
        itemId: '5',
        name: 'xxxx',
        variations: [
          {
            name: 'Size',
            values: ['3'],
          },
          { name: 'Color', values: ['Gray'] },
        ],
        sellers: [defaultSeller],
        images: [],
      },
      {
        itemId: '6',
        name: 'xxxxxx',
        variations: [
          {
            name: 'Size',
            values: ['4'],
          },
          { name: 'Color', values: ['Gray'] },
        ],
        sellers: [defaultSeller],
        images: [],
      },
      {
        itemId: '7',
        name: 'xxxxaaaxx',
        variations: [
          {
            name: 'Size',
            values: ['5'],
          },
          { name: 'Color', values: ['Gray'] },
        ],
        sellers: [defaultSeller],
        images: [],
      },
      {
        itemId: '8',
        name: 'aaaa',
        variations: [
          {
            name: 'Size',
            values: ['6'],
          },
          { name: 'Color', values: ['Gray'] },
        ],
        sellers: [defaultSeller],
        images: [],
      },
      {
        itemId: '9',
        name: 'bb',
        variations: [
          {
            name: 'Size',
            values: ['7'],
          },
          { name: 'Color', values: ['Gray'] },
        ],
        sellers: [defaultSeller],
        images: [],
      },
      {
        itemId: '10',
        name: 'ppp',
        variations: [
          {
            name: 'Size',
            values: ['1'],
          },
          { name: 'Color', values: ['Gray'] },
        ],
        sellers: [defaultSeller],
        images: [],
      },
      {
        itemId: '11',
        name: 'c',
        variations: [
          {
            name: 'Size',
            values: ['8'],
          },
          { name: 'Color', values: ['Gray'] },
        ],
        sellers: [defaultSeller],
        images: [],
      },
      {
        itemId: '12',
        name: 'c',
        variations: [
          {
            name: 'Size',
            values: ['9'],
          },
          { name: 'Color', values: ['Gray'] },
        ],
        sellers: [defaultSeller],
        images: [],
      },
      {
        itemId: '13',
        name: 'c',
        variations: [
          {
            name: 'Size',
            values: ['10'],
          },
          { name: 'Color', values: ['Gray'] },
        ],
        sellers: [defaultSeller],
        images: [],
      },
      {
        itemId: '14',
        name: 'c',
        variations: [
          {
            name: 'Size',
            values: ['11'],
          },
          { name: 'Color', values: ['Gray'] },
        ],
        sellers: [defaultSeller],
        images: [],
      },
      {
        itemId: '15',
        name: 'c',
        variations: [
          {
            name: 'Size',
            values: ['12'],
          },
          { name: 'Color', values: ['Gray'] },
        ],
        sellers: [defaultSeller],
        images: [],
      },
      {
        itemId: '16',
        name: 'c',
        variations: [
          {
            name: 'Size',
            values: ['13'],
          },
          { name: 'Color', values: ['Gray'] },
        ],
        sellers: [defaultSeller],
        images: [],
      },
      {
        itemId: '17',
        name: 'c',
        variations: [
          {
            name: 'Size',
            values: ['14'],
          },
          { name: 'Color', values: ['Gray'] },
        ],
        sellers: [defaultSeller],
        images: [],
      },
    ]

    const skuSelected = skuItems.find(({ itemId }) => itemId === '15')

    const { getByText } = render(
      <SKUSelector skuSelected={skuSelected} skuItems={skuItems} maxItems={6} />
    )

    await wait()

    expect(getByText('4')).toBeDefined()
    expect(getByText('12')).toBeDefined()
  })

  it('remove accent from names on slugify methods', async () => {
    const defaultSeller = {
      commertialOffer: { Price: 15, AvailableQuantity: 1 },
    }

    const skuItems = [
      {
        itemId: '1',
        name: 'Gray Shoe',
        variations: [
          { name: 'Size', values: ['[Square Brackets]'] },
          { name: 'Color', values: ['Jácó'] },
        ],
        sellers: [defaultSeller],
        images: [],
      },
      {
        itemId: '2',
        name: 'Black Shoe',
        variations: [
          { name: 'Size', values: ['[Square Brackets]'] },
          { name: 'Color', values: ['@@Testing&&'] },
        ],
        sellers: [defaultSeller],
        images: [],
      },
      {
        itemId: '3',
        name: 'Black Shoe',
        variations: [
          { name: 'Size', values: ['[Square Brackets]'] },
          { name: 'Color', values: ["John's"] },
        ],
        sellers: [defaultSeller],
        images: [],
      },
      {
        itemId: '4',
        name: 'Black Shoe',
        variations: [
          { name: 'Size', values: ['[Square Brackets]'] },
          { name: 'Color', values: ['Feijão'] },
        ],
        sellers: [defaultSeller],
        images: [],
      },
    ]

    const { queryByText } = render(
      <SKUSelector skuSelected={skuItems[0]} skuItems={skuItems} maxItems={6} />
    )

    await wait()
    expect(queryByText('skuSelectorItem--feijao')).toBeDefined()
    expect(queryByText('skuSelectorItem--square-brackets')).toBeDefined()
    expect(queryByText('skuSelectorItem--johns')).toBeDefined()
    expect(queryByText('skuSelectorItem--testing')).toBeDefined()
    expect(queryByText('skuSelectorItem--jaco')).toBeDefined()
  })

  it('should show the selected variation name', async () => {
    const defaultSeller = {
      commertialOffer: { Price: 15, AvailableQuantity: 1 },
    }

    const skuItems = [
      {
        itemId: '1',
        name: 'Gray Shoe',
        variations: [
          { name: 'Size', values: ['41'] },
          { name: 'Color', values: ['Gray'] },
        ],
        sellers: [defaultSeller],
        images: [],
      },
      {
        itemId: '2',
        name: 'Black Shoe',
        variations: [
          { name: 'Size', values: ['41'] },
          { name: 'Color', values: ['Black'] },
        ],
        sellers: [defaultSeller],
        images: [],
      },
    ]

    const { container } = render(
      <SKUSelector
        skuSelected={skuItems[0]}
        skuItems={skuItems}
        maxItems={6}
        showValueNameForImageVariation
      />
    )

    await wait()

    const separator = container.querySelector('.skuSelectorNameSeparator')
    const variationValue = container.querySelector(
      '.skuSelectorSelectorImageValue'
    )

    expect(separator).toHaveTextContent(':')
    expect(variationValue).toHaveTextContent('Gray')
  })

  /* Order of the color variations should be: Black, Gray, Blue.
   * Order of the Size variations should be: 42, 41
   * The snapshot should validate if the values are coming correctly  */
  it('should consider order from skuSpecifications', async () => {
    const defaultSeller = {
      commertialOffer: { Price: 15, ListPrice: 20, AvailableQuantity: 10 },
    }

    const firstSku = {
      itemId: '1',
      name: 'Gray Shoe',
      variations: [
        { name: 'Size', values: ['41'] },
        { name: 'Color', values: ['Gray'] },
      ],
      sellers: [defaultSeller],
      images: [],
    }

    mockedUseProduct.mockImplementation(
      function getProductContext(): ProductContext {
        return {
          product: {
            buyButton: {
              clicked: false,
            },
            skuSelector: {
              isVisible: true,
              areAllVariationsSelected: true,
            },
            selectedItem: firstSku,
            selectedQuantity: 1,
            assemblyOptions: {
              items: {},
              areGroupsValid: {},
              inputValues: {},
            },
            skuSpecifications: [
              {
                field: {
                  name: 'Color',
                  originalName: 'Color',
                },
                values: [
                  {
                    name: 'Black',
                    originalName: 'Black',
                  },
                  {
                    name: 'Gray',
                    originalName: 'Gray',
                  },
                  {
                    name: 'Blue',
                    originalName: 'Blue',
                  },
                ],
              },
              {
                field: {
                  name: 'Size',
                  originalName: 'Size',
                },
                values: [
                  {
                    name: '43',
                    originalName: '43',
                  },
                  {
                    name: '42',
                    originalName: '42',
                  },
                  {
                    name: '41',
                    originalName: '41',
                  },
                ],
              },
            ],
          },
        }
      }
    )
    const skuItems = [
      firstSku,
      {
        itemId: '2',
        name: 'Black Shoe',
        variations: [
          { name: 'Size', values: ['41', '42', '43'] },
          { name: 'Color', values: ['Black'] },
        ],
        sellers: [defaultSeller],
        images: [],
      },
      {
        itemId: '3',
        name: 'Blue Shoe',
        variations: [
          { name: 'Size', values: ['41', '42', '43'] },
          { name: 'Color', values: ['Blue', 'Black'] },
        ],
        sellers: [defaultSeller],
        images: [],
      },
      {
        itemId: '4',
        name: 'Gray Shoe',
        variations: [
          {
            name: 'Size',
            values: ['42'],
          },
          { name: 'Color', values: ['Gray'] },
        ],
        sellers: [defaultSeller],
        images: [],
      },
    ]

    const { asFragment } = render(
      <SKUSelector skuSelected={skuItems[0]} skuItems={skuItems} maxItems={6} />
    )

    // check comment above the 'it' description
    expect(asFragment()).toMatchSnapshot()
  })

  it('should not show the Yellow variation since there is no items with the Yellow variation', async () => {
    const defaultSeller = {
      commertialOffer: { Price: 15, ListPrice: 20, AvailableQuantity: 10 },
    }

    const firstSku = {
      itemId: '1',
      name: 'Gray Shoe',
      variations: [
        { name: 'Size', values: ['41'] },
        { name: 'Color', values: ['Gray'] },
      ],
      sellers: [defaultSeller],
      images: [],
    }

    mockedUseProduct.mockImplementation(
      function getProductContext(): ProductContext {
        return {
          product: {
            buyButton: {
              clicked: false,
            },
            skuSelector: {
              isVisible: true,
              areAllVariationsSelected: true,
            },
            selectedItem: firstSku,
            selectedQuantity: 1,
            assemblyOptions: {
              items: {},
              areGroupsValid: {},
              inputValues: {},
            },
            skuSpecifications: [
              {
                field: {
                  name: 'Color',
                  originalName: 'Color',
                },
                values: [
                  {
                    name: 'Yellow',
                    originalName: 'Yellow',
                  },
                  {
                    name: 'Black',
                    originalName: 'Black',
                  },
                  {
                    name: 'Gray',
                    originalName: 'Gray',
                  },
                  {
                    name: 'Blue',
                    originalName: 'Blue',
                  },
                ],
              },
              {
                field: {
                  name: 'Size',
                  originalName: 'Size',
                },
                values: [
                  {
                    name: '43',
                    originalName: '43',
                  },
                  {
                    name: '42',
                    originalName: '42',
                  },
                  {
                    name: '41',
                    originalName: '41',
                  },
                ],
              },
            ],
          },
        }
      }
    )

    const skuItems = [
      firstSku,
      {
        itemId: '2',
        name: 'Black Shoe',
        variations: [
          { name: 'Size', values: ['41', '42', '43'] },
          { name: 'Color', values: ['Black'] },
        ],
        sellers: [defaultSeller],
        images: [],
      },
      {
        itemId: '3',
        name: 'Blue Shoe',
        variations: [
          { name: 'Size', values: ['41', '42', '43'] },
          { name: 'Color', values: ['Blue', 'Black'] },
        ],
        sellers: [defaultSeller],
        images: [],
      },
      {
        itemId: '4',
        name: 'Gray Shoe',
        variations: [
          {
            name: 'Size',
            values: ['42'],
          },
          { name: 'Color', values: ['Gray'] },
        ],
        sellers: [defaultSeller],
        images: [],
      },
    ]

    const { queryByText } = render(
      <SKUSelector skuSelected={skuItems[0]} skuItems={skuItems} maxItems={6} />
    )

    expect(queryByText('Yellow')).toBeFalsy()
  })

  it('must order sku specification to be sorted in alphabetical order', async () => {
    const defaultSeller = {
      commertialOffer: { Price: 15, AvailableQuantity: 1 },
    }

    const skuItems = [
      {
        itemId: '1',
        name: 'Gray Shoe',
        variations: [
          { name: 'Size', values: ['43'] },
          { name: 'Color', values: ['Gray'] },
        ],
        images: [],
        sellers: [defaultSeller],
      },
      {
        itemId: '4',
        name: 'Gray Shoe',
        variations: [
          {
            name: 'Size',
            values: ['42'],
          },
          { name: 'Color', values: ['Gray'] },
        ],
        images: [],
        sellers: [defaultSeller],
      },
      {
        itemId: '4',
        name: 'Gray Shoe',
        variations: [
          {
            name: 'Size',
            values: ['41'],
          },
          { name: 'Color', values: ['Gray'] },
        ],
        images: [],
        sellers: [defaultSeller],
      },
    ]

    const { container } = renderComponent({
      sortVariationsByLabel: true,
      skuSelected: skuItems[0],
      skuItems,
    })

    const options = container.querySelectorAll('.skuSelectorItemTextValue')

    expect(options[0]).toHaveTextContent('41')
    expect(options[1]).toHaveTextContent('42')
    expect(options[2]).toHaveTextContent('43')
  })
})

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of store-components/react/__tests__/components/ProductImages.test.jsx from the store-components VTEX app.

[Assistant]
Here's the implementation:

```jsx
import React from 'react'
import { render, fireEvent } from '@vtex/test-tools/react'
import useProduct from 'vtex.product-context/useProduct'
import { Modal } from 'vtex.modal-layout'

import ProductImages from '../../ProductImages'
// eslint-disable-next-line jest/no-mocks-import
import { createItem } from '../../__mocks__/productMock'
import HighQualityProductImage from '../../HighQualityProductImage'

const mockUseProduct = useProduct

// This works just like a slot passed to product-iamges
function ModalLayout() {
  return (
    <Modal>
      <HighQualityProductImage />
    </Modal>
  )
}

jest.mock('swiper/react', () => {
  return {
    Swiper({ children }) {
      return <div>{children}</div>
    },
    SwiperSlide({ children }) {
      return <div>{children}</div>
    },
  }
})

// This Image mock only call set onload function after user sets the src property in object
class FakeImage {
  onload = null
  set src(newSrc) {
    this.onload && this.onload()
  }
}

beforeEach(() => {
  window.Image = FakeImage
})

describe('<ProductImages />', () => {
  const renderComponent = customProps => {
    return render(<ProductImages {...customProps} />)
  }

  it('should render two images (thumb and main image) for each product image', () => {
    const props = {
      images: [
        {
          imageUrls: ['url'],
          thresholds: [1],
          thumbnailUrl: 'url',
          imageText: 'imageText',
          imageLabel: 'imageLabel',
        },
        {
          imageUrls: ['url2'],
          thresholds: [1],
          thumbnailUrl: 'url2',
          imageText: 'imageText2',
          imageLabel: 'imageLabel2',
        },
      ],
    }

    const { getAllByAltText } = renderComponent(props)

    expect(getAllByAltText('imageLabel')).toHaveLength(2)
    expect(getAllByAltText('imageLabel2')).toHaveLength(2)
  })
  it('should show thumbs when there is more than one image', () => {
    const props = {
      images: [
        {
          imageUrls: ['url'],
          thresholds: [1],
          thumbnailUrl: 'url',
          imageText: 'imageText',
          imageLabel: 'imageLabel',
        },
        {
          imageUrls: ['url2'],
          thresholds: [1],
          thumbnailUrl: 'url2',
          imageText: 'imageText2',
          imageLabel: 'imageLabel2',
        },
      ],
    }

    const { queryByTestId, getAllByAltText } = renderComponent(props)
    const swiper = queryByTestId('thumbnail-swiper')

    expect(swiper.className.includes('db-ns')).toBeTruthy()
    getAllByAltText('imageLabel')
    getAllByAltText('imageLabel2')
  })
  it('should show default placeholder when there is NO image', () => {
    const props = {
      images: [],
    }

    const { queryByTestId } = renderComponent(props)

    const defaultPlaceholder = queryByTestId('default-image-placeholder')

    expect(defaultPlaceholder).toBeVisible()
  })

  it('should show custom placeholder when provided and there is NO image', () => {
    const props = {
      images: [],
      placeholder: 'url',
    }

    const { queryByAltText } = renderComponent(props)

    const defaultPlaceholder = queryByAltText('Product image placeholder')

    expect(defaultPlaceholder).toBeVisible()
  })

  it('should NOT show thumbs when there is one image', () => {
    const props = {
      images: [
        {
          imageUrls: ['url'],
          thresholds: [1],
          thumbnailUrl: 'url',
          imageText: 'imageText',
        },
      ],
    }

    const { queryByTestId } = renderComponent(props)

    const swiper = queryByTestId('thumbnail-swiper')

    expect(swiper).toHaveClass('dn')
  })

  describe('test logic to thumbnail orientation', () => {
    it('should render with correct classes when vertical', () => {
      const props = {
        thumbnailsOrientation: 'vertical',
        images: [
          {
            imageUrls: ['url'],
            thresholds: [1],
            thumbnailUrl: 'url',
            imageText: 'imageText',
          },
          {
            imageUrls: ['url2'],
            thresholds: [1],
            thumbnailUrl: 'url2',
            imageText: 'imageText2',
          },
        ],
      }

      const { queryByTestId } = renderComponent(props)

      const swiper = queryByTestId('thumbnail-swiper')

      expect(swiper.className.includes('absolute')).toBeTruthy()
      expect(swiper.className.includes('w-20')).toBeTruthy()
    })
    it('default orientation should be vertical', () => {
      const props = {
        images: [
          {
            imageUrls: ['url'],
            thresholds: [1],
            thumbnailUrl: 'url',
            imageText: 'imageText',
          },
          {
            imageUrls: ['url2'],
            thresholds: [1],
            thumbnailUrl: 'url2',
            imageText: 'imageText2',
          },
        ],
      }

      const { queryByTestId } = renderComponent(props)

      const swiper = queryByTestId('thumbnail-swiper')

      expect(swiper.className.includes('absolute')).toBeTruthy()
      expect(swiper.className.includes('w-20')).toBeTruthy()
    })
    it('should render with correct classes when horizontal', () => {
      const props = {
        thumbnailsOrientation: 'horizontal',
        images: [
          {
            imageUrls: ['url'],
            thresholds: [1],
            thumbnailUrl: 'url',
            imageText: 'imageText',
          },
          {
            imageUrls: ['url2'],
            thresholds: [1],
            thumbnailUrl: 'url2',
            imageText: 'imageText2',
          },
        ],
      }

      const { queryByTestId } = renderComponent(props)

      const swiper = queryByTestId('thumbnail-swiper')

      expect(swiper.className.includes('absolute')).toBeFalsy()
      expect(swiper.className.includes('w-20')).toBeFalsy()
    })
    it('should render with correct classes when vertical and position left', () => {
      const props = {
        thumbnailsOrientation: 'vertical',
        position: 'left',
        images: [
          {
            imageUrls: ['url'],
            thresholds: [1],
            thumbnailUrl: 'url',
            imageText: 'imageText',
          },
          {
            imageUrls: ['url2'],
            thresholds: [1],
            thumbnailUrl: 'url2',
            imageText: 'imageText2',
          },
        ],
      }

      const { queryByTestId } = renderComponent(props)

      const swiper = queryByTestId('thumbnail-swiper')

      expect(swiper.className.includes('absolute')).toBeTruthy()
      expect(swiper.className.includes('w-20')).toBeTruthy()
      expect(swiper.className.includes('left')).toBeTruthy()
      expect(swiper.className.includes('right')).toBeFalsy()
    })
    it('should render with correct classes when vertical and position right', () => {
      const props = {
        thumbnailsOrientation: 'vertical',
        position: 'right',
        images: [
          {
            imageUrls: ['url'],
            thresholds: [1],
            thumbnailUrl: 'url',
            imageText: 'imageText',
          },
          {
            imageUrls: ['url2'],
            thresholds: [1],
            thumbnailUrl: 'url2',
            imageText: 'imageText2',
          },
        ],
      }

      const { queryByTestId } = renderComponent(props)

      const swiper = queryByTestId('thumbnail-swiper')

      expect(swiper.className.includes('absolute')).toBeTruthy()
      expect(swiper.className.includes('w-20')).toBeTruthy()
      expect(swiper.className.includes('left')).toBeFalsy()
      expect(swiper.className.includes('right')).toBeTruthy()
    })
  })

  describe('test with product context', () => {
    it('render properly with product in context', () => {
      mockUseProduct.mockImplementation(() => ({
        selectedItem: createItem({ id: 'potato' }),
      }))
      const { queryAllByAltText } = renderComponent({})

      expect(queryAllByAltText('potato-Color')).toHaveLength(6)
    })

    it('gives priority to selected image variation sku', () => {
      mockUseProduct.mockImplementation(() => ({
        product: {
          items: [createItem({ id: '123' }), createItem({ id: '456' })],
        },
        skuSelector: {
          selectedImageVariationSKU: '456',
        },
      }))
      const { queryAllByAltText } = renderComponent({})

      expect(queryAllByAltText('456-Color')).toHaveLength(6)
    })

    it('give priority to prop items if product in context', () => {
      mockUseProduct.mockImplementation(() => ({
        selectedItem: createItem({}),
      }))
      const props = {
        images: [
          {
            imageUrls: ['url'],
            thresholds: [1],
            thumbnailUrl: 'url',
            imageText: 'propImageText',
            imageLabel: 'propImageLabel',
          },
          {
            imageUrls: ['url2'],
            thresholds: [1],
            thumbnailUrl: 'url2',
            imageText: 'propImageText2',
            imageLabel: 'propImageLabel2',
          },
        ],
      }

      const { queryAllByAltText } = renderComponent(props)

      expect(queryAllByAltText('propImageLabel')).toHaveLength(2)
      expect(queryAllByAltText('propImageLabel2')).toHaveLength(2)
    })
  })

  describe('<HighQualityProductImage />', () => {
    it('should render if the modal-trigger is clicked', () => {
      const props = {
        zoomMode: 'open-modal',
        ModalZoom: ModalLayout,
        images: [
          {
            imageUrls: ['url2'],
            thresholds: [1],
            thumbnailUrl: 'url2',
            imageText: 'imageText2',
            imageLabel: 'imageLabel2',
          },
        ],
      }

      const { getAllByAltText, getByTestId } = render(
        <ProductImages {...props} />
      )

      const images = getAllByAltText('imageLabel2')

      // 2 for thumb + main image
      expect(images).toHaveLength(2)
      fireEvent.click(getByTestId('modal-trigger'), {
        bubbles: true,
        cancelable: true,
      })

      // 3 for thumb + main image + modal image
      expect(getAllByAltText('imageLabel2')).toHaveLength(3)
    })

    it('should render 2 img[alt="imageLabel2"] if img2 trigger is clicked', () => {
      const props = {
        zoomMode: 'open-modal',
        ModalZoom: ModalLayout,
        images: [
          {
            imageUrls: ['url'],
            thresholds: [1],
            thumbnailUrl: 'url',
            imageText: 'imageText',
            imageLabel: 'imageLabel',
          },
          {
            imageUrls: ['url2'],
            thresholds: [1],
            thumbnailUrl: 'url2',
            imageText: 'imageText2',
            imageLabel: 'imageLabel2',
          },
        ],
      }

      const { getAllByAltText, getAllByTestId } = render(
        <ProductImages {...props} />
      )

      const images = getAllByAltText('imageLabel2')

      expect(images).toHaveLength(2)
      fireEvent.click(getAllByTestId('modal-trigger')[1], {
        bubbles: true,
        cancelable: true,
      })

      // 3 images with the alt because is one image of the trigger,
      // one image of the thumbs and the image of HighQualityProductImage
      expect(getAllByAltText('imageLabel2')).toHaveLength(3)
    })
  })
})

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of store-components/react/__tests__/components/CategoriesHighlights.test.js from the store-components VTEX app.

[Assistant]
Here's the implementation:

```javascript
import React from 'react'
import { render } from '@vtex/test-tools/react'

import CategoriesHighlights from '../../CategoriesHighlights'

describe('<CategoriesHighlights />', () => {
  const renderComponent = customProps => {
    const props = {
      cardShape: 'squared',
      showCategoriesHighlighted: true,
      ...customProps,
    }

    return render(<CategoriesHighlights {...props} />)
  }

  it('should be rendered', () => {
    const { asFragment } = renderComponent()

    expect(asFragment()).toBeDefined()
    expect(asFragment()).toBeTruthy()
  })

  it('should match snapshot Squared', () => {
    const { asFragment } = renderComponent()

    expect(asFragment()).toMatchSnapshot()
  })

  it('should match snapshot Rectangular', () => {
    const { asFragment } = renderComponent({ cardShape: 'rectangular' })

    expect(asFragment()).toMatchSnapshot()
  })
})

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of store-components/react/__tests__/components/Share.test.js from the store-components VTEX app.

[Assistant]
Here's the implementation:

```javascript
import React from 'react'
import { render, fireEvent, screen } from '@vtex/test-tools/react'

import Share from '../../Share'

const mockedUsePixelPush = jest.fn()

jest.mock('vtex.pixel-manager', () => ({
  usePixel: () => ({ push: mockedUsePixelPush }),
}))

describe('<Share />', () => {
  beforeEach(() => {
    jest.useFakeTimers()
  })

  const renderComponent = props => {
    return render(<Share imageUrl="" {...props} />)
  }

  it('should be mounted', () => {
    const { asFragment } = renderComponent()

    expect(asFragment()).toBeDefined()
  })

  it('should match the snapshot with Facebook', () => {
    const { asFragment } = renderComponent({
      social: {
        Facebook: true,
      },
    })

    expect(asFragment()).toMatchSnapshot()
  })

  it('should match the snapshot with Twitter', () => {
    const { asFragment } = renderComponent({
      social: {
        Twitter: true,
      },
    })

    expect(asFragment()).toMatchSnapshot()
  })

  it('should match the snapshot with WhatsApp', () => {
    const { asFragment } = renderComponent({
      social: {
        WhatsApp: true,
      },
    })

    expect(asFragment()).toMatchSnapshot()
  })

  it('should match the snapshot with Telegram', () => {
    const { asFragment } = renderComponent({
      social: {
        Telegram: true,
      },
    })

    expect(asFragment()).toMatchSnapshot()
  })

  it('should match the snapshot with E-mail', () => {
    const { asFragment } = renderComponent({
      social: {
        'E-mail': true,
      },
    })

    expect(asFragment()).toMatchSnapshot()
  })

  it('should match the snapshot with multiples Socials', () => {
    const { asFragment } = renderComponent({
      social: {
        'E-mail': true,
        Twitter: true,
        Telegram: true,
      },
    })

    expect(asFragment()).toMatchSnapshot()
  })

  it('should match snapshot Loader', () => {
    const { asFragment } = renderComponent({ loading: true })

    expect(asFragment()).toMatchSnapshot()
  })

  it('should send vtex:share with Facebook method when is clicked', async () => {
    await renderComponent({
      social: {
        Facebook: true,
      },
      loading: false,
    })

    const btn = screen.getByLabelText('facebook')

    fireEvent.click(btn)

    const expectedPixelEvent = {
      event: 'share',
      method: 'Facebook',
      contentType: 'product',
      itemId: '23087',
    }

    expect(mockedUsePixelPush).toHaveBeenCalledWith(expectedPixelEvent)
  })

  it('should send vtex:share with WhatsApp method when is clicked', async () => {
    await renderComponent({
      social: {
        WhatsApp: true,
      },
      loading: false,
    })

    const btn = screen.getByLabelText('whatsapp')

    fireEvent.click(btn)

    const expectedPixelEvent = {
      event: 'share',
      method: 'WhatsApp',
      contentType: 'product',
      itemId: '23087',
    }

    expect(mockedUsePixelPush).toHaveBeenCalledWith(expectedPixelEvent)
  })

  it('should send vtex:share with Twitter method when is clicked', async () => {
    await renderComponent({
      social: {
        Twitter: true,
      },
      loading: false,
    })

    const btn = screen.getByLabelText('twitter')

    fireEvent.click(btn)

    const expectedPixelEvent = {
      event: 'share',
      method: 'Twitter',
      contentType: 'product',
      itemId: '23087',
    }

    expect(mockedUsePixelPush).toHaveBeenCalledWith(expectedPixelEvent)
  })

  it('should send vtex:share with Telegram method when is clicked', async () => {
    await renderComponent({
      social: {
        Telegram: true,
      },
      loading: false,
    })

    const btn = screen.getByLabelText('telegram')

    fireEvent.click(btn)

    const expectedPixelEvent = {
      event: 'share',
      method: 'Telegram',
      contentType: 'product',
      itemId: '23087',
    }

    expect(mockedUsePixelPush).toHaveBeenCalledWith(expectedPixelEvent)
  })

  it('should send vtex:share with E-mail method when is clicked', async () => {
    await renderComponent({
      social: {
        'E-mail': true,
      },
      loading: false,
    })

    const btn = screen.getByLabelText('email')

    fireEvent.click(btn)

    const expectedPixelEvent = {
      event: 'share',
      method: 'E-mail',
      contentType: 'product',
      itemId: '23087',
    }

    expect(mockedUsePixelPush).toHaveBeenCalledWith(expectedPixelEvent)
  })
})

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of store-components/react/__tests__/components/SearchBar.test.js from the store-components VTEX app.

[Assistant]
Here's the implementation:

```javascript
import React from 'react'
import { render, fireEvent, screen } from '@vtex/test-tools/react'

import SearchBar from '../../SearchBar'
import autocomplete from '../../graphql/autocomplete.gql'

const mockedUsePixelPush = jest.fn()

jest.mock('vtex.pixel-manager', () => ({
  usePixel: () => ({ push: mockedUsePixelPush }),
}))

describe('<SearchBar />', () => {
  beforeEach(() => {
    jest.useFakeTimers()
  })

  const mockedResult = {
    request: {
      query: autocomplete,
    },
    result: {
      data: {
        loading: false,
        autocomplete: {
          itemsReturned: [{ thumb: 'thumb', name: 'name', href: 'href' }],
        },
      },
    },
  }

  const renderComponent = (customProps = {}) => {
    return render(<SearchBar {...customProps} />, {
      graphql: { mocks: [mockedResult] },
    })
  }

  it('should be able to mount and not break', () => {
    const { asFragment } = renderComponent()

    expect(asFragment()).toBeTruthy()
  })

  it('should match snapshot', () => {
    const { asFragment } = renderComponent()

    expect(asFragment()).toMatchSnapshot()
  })

  it('should have CSS handle searchBarIcon', () => {
    const { container } = renderComponent()
    const element = container.querySelector('.searchBarIcon')

    expect(element).toBeTruthy()
  })

  it('should display internal search icon button', () => {
    const { container } = renderComponent({
      displayMode: 'search-button',
    })

    expect(container.querySelector('.searchBarIcon--search')).toBeTruthy()
  })

  it('should display internal clear icon button when a value is typed', () => {
    const { container } = renderComponent({
      displayMode: 'search-button',
      value: 'foo',
    })

    expect(container.querySelector('.searchBarIcon--search')).toBeTruthy()
  })

  it('should display external search icon button', () => {
    const { container } = renderComponent({
      displayMode: 'search-and-clear-buttons',
    })

    expect(
      container.querySelector('.searchBarIcon--external-search')
    ).toBeTruthy()
  })

  it('should display interal clear icon button when a value is typed', () => {
    const { container } = renderComponent({
      displayMode: 'search-and-clear-buttons',
      value: 'foo',
    })

    expect(container.querySelector('.searchBarIcon--clear')).toBeTruthy()
  })

  it('should trigger vtex:search when a value is typed', async () => {
    const { container } = renderComponent({
      displayMode: 'search-and-clear-buttons',
      submitOnIconClick: true,
    })

    const [searchButton] = container.getElementsByClassName('searchBarIcon')
    const inputNode = screen.getByPlaceholderText('Search')

    fireEvent.change(inputNode, { target: { value: 'foo' } })

    fireEvent.click(searchButton)

    const expectedPixelEvent = {
      event: 'search',
      term: 'foo',
    }

    expect(mockedUsePixelPush).toHaveBeenCalledWith(expectedPixelEvent)
  })
})

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of store-components/react/__tests__/components/ProductDescription.test.tsx from the store-components VTEX app.

[Assistant]
Here's the implementation:

```tsx
import React from 'react'
import { render } from '@vtex/test-tools/react'

import ProductDescription from '../../ProductDescription'

describe('<ProductDescription />', () => {
  const renderComponent = (customProps?: any) => {
    const props = {
      description: 'Test description',
      ...customProps,
    }

    return render(<ProductDescription {...props} />)
  }

  it('should be mounted', () => {
    const { asFragment } = renderComponent()

    expect(asFragment()).toBeDefined()
  })

  it('should match the snapshot with description', () => {
    const { asFragment, queryByText } = renderComponent()

    expect(asFragment()).toMatchSnapshot()
    expect(queryByText('Show more')).toBeInTheDocument()
  })

  it('should not show show more button', () => {
    const { queryByText } = renderComponent({ collapseContent: false })

    expect(queryByText('Show more')).toBeNull()
  })
})

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of store-components/react/__tests__/components/ProductPrice.test.js from the store-components VTEX app.

[Assistant]
Here's the implementation:

```javascript
import React from 'react'
import { render } from '@vtex/test-tools/react'

import ProductPrice from '../../ProductPrice'

describe('<ProductPrice />', () => {
  const defaultProps = {
    loaderClass: '',
    showListPrice: false,
    sellingPrice: 40,
  }

  const renderComponent = customProps => {
    const props = {
      ...defaultProps,
      ...customProps,
    }

    return render(<ProductPrice {...props} />)
  }

  it('should be mount', () => {
    const { asFragment } = renderComponent()

    expect(asFragment()).toBeDefined()
  })

  it('should match snapshot', () => {
    const { asFragment } = renderComponent()

    expect(asFragment()).toMatchSnapshot()
  })

  it('should match snapshot Loader', () => {
    const { asFragment } = renderComponent({ showListPrice: true })

    expect(asFragment()).toMatchSnapshot()
  })

  it('should show selling price and list price (with labels)', () => {
    const customProps = {
      listPrice: 50,
      showLabels: true,
      showListPrice: true,
      labelSellingPrice: 'To',
      labelListPrice: 'From',
    }

    const { getByText } = renderComponent(customProps)

    expect(getByText('From')).toBeDefined()
    expect(getByText('To')).toBeDefined()
    expect(getByText('$40.00')).toBeDefined()
    expect(getByText('$50.00')).toBeDefined()
  })

  it('should show selling price and list price but with NO labels', () => {
    const customProps = {
      listPrice: 50,
      showLabels: false,
      showListPrice: true,
      labelSellingPrice: 'To',
      labelListPrice: 'From',
    }

    const { getByText, queryByText } = renderComponent(customProps)

    expect(queryByText('From')).toBeNull()
    expect(queryByText('To')).toBeNull()
    expect(getByText('$40.00')).toBeDefined()
    expect(getByText('$50.00')).toBeDefined()
  })

  // eslint-disable-next-line jest/no-identical-title
  it('should show selling price and list price but with NO labels', () => {
    const customProps = {
      listPrice: 50,
      showLabels: false,
      showListPrice: true,
    }

    const { getByText, queryByText } = renderComponent(customProps)

    expect(queryByText('From')).toBeNull()
    expect(queryByText('To')).toBeNull()
    expect(getByText('$40.00')).toBeDefined()
    expect(getByText('$50.00')).toBeDefined()
  })

  it('should show selling price and list price but with custom labels', () => {
    const customProps = {
      listPrice: 50,
      showLabels: true,
      showListPrice: true,
      labelSellingPrice: 'Now',
      labelListPrice: 'Was',
    }

    const { getByText } = renderComponent(customProps)

    expect(getByText('Was')).toBeDefined()
    expect(getByText('Now')).toBeDefined()
    expect(getByText('$40.00')).toBeDefined()
    expect(getByText('$50.00')).toBeDefined()
  })

  it('should show range selling price (not list price)', () => {
    const customProps = {
      listPrice: 50,
      showLabels: true,
      showListPrice: false,
      labelSellingPrice: 'Now',
      labelListPrice: 'Was',
      sellingPriceList: [30, 50, 20, 55],
      showSellingPriceRange: true,
    }

    const { getByText, queryByText } = renderComponent(customProps)

    // dont show labels
    expect(queryByText('Now')).toBeNull()
    expect(queryByText('Was')).toBeNull()
    // dont show selling price
    expect(queryByText('$40.00')).toBeNull()

    expect(getByText('$20.00 - $55.00')).toBeDefined()
  })

  it('show list price range and selling price range (no labels)', () => {
    const customProps = {
      listPrice: 50,
      showLabels: false,
      showListPrice: true,
      showListPriceRange: true,
      labelSellingPrice: 'Now',
      labelListPrice: 'Was',
      sellingPriceList: [30, 50, 20, 55],
      listPriceList: [100, 200, 300, 400],
      showSellingPriceRange: true,
    }

    const { getByText, queryByText } = renderComponent(customProps)

    // dont show labels
    expect(queryByText('Now')).toBeNull()
    expect(queryByText('Was')).toBeNull()
    // dont show selling price
    expect(queryByText('$40.00')).toBeNull()
    expect(queryByText('$50.00')).toBeNull()

    expect(getByText('$20.00 - $55.00')).toBeDefined()
    expect(getByText('$100.00 - $400.00')).toBeDefined()
  })

  it('show list price range and selling price range (with labels)', () => {
    const customProps = {
      listPrice: 50,
      showLabels: true,
      showListPrice: true,
      showListPriceRange: true,
      labelSellingPrice: 'Now',
      labelListPrice: 'Was',
      sellingPriceList: [30, 50, 20, 55],
      listPriceList: [100, 200, 300, 400],
      showSellingPriceRange: true,
    }

    const { getByText, queryByText } = renderComponent(customProps)

    // show labels
    expect(getByText('Now')).toBeDefined()
    expect(getByText('Was')).toBeDefined()
    // dont show selling price
    expect(queryByText('$40.00')).toBeNull()
    expect(queryByText('$50.00')).toBeNull()

    expect(getByText('$20.00 - $55.00')).toBeDefined()
    expect(getByText('$100.00 - $400.00')).toBeDefined()
  })
})

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of store-components/react/__tests__/components/GradientCollapse.test.js from the store-components VTEX app.

[Assistant]
Here's the implementation:

```javascript
import React from 'react'
import { render } from '@vtex/test-tools/react'

import GradientCollapse from '../../GradientCollapse'

describe('<GradientCollapse /> component', () => {
  function renderComponent(customProps = {}) {
    const props = {
      collapseHeight: 50,
      ...customProps,
    }

    const component = <GradientCollapse {...props}>Test</GradientCollapse>

    return render(component)
  }

  it('should be able to mount and not break', () => {
    const { asFragment } = renderComponent()

    expect(asFragment()).toBeTruthy()
  })

  it('should match snapshot', () => {
    const { asFragment } = renderComponent()

    expect(asFragment()).toMatchSnapshot()
  })
})

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of store-components/react/__tests__/components/Container.test.js from the store-components VTEX app.

[Assistant]
Here's the implementation:

```javascript
import React from 'react'
import { render } from '@vtex/test-tools/react'

import Container from '../../Container'

describe('<Container /> component', () => {
  const renderComponent = customProps => {
    const comp = <Container {...customProps}> Test </Container>

    return render(comp)
  }

  it('should be rendered', () => {
    const { asFragment } = renderComponent()

    expect(asFragment()).toBeTruthy()
  })

  it('should match snapshot', () => {
    const { asFragment } = renderComponent()

    expect(asFragment()).toMatchSnapshot()
  })
})

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of store-components/react/__tests__/components/ProductBrand.test.tsx from the store-components VTEX app.

[Assistant]
Here's the implementation:

```tsx
import React from 'react'
import { render, wait } from '@vtex/test-tools/react'

import ProductBrand from '../../ProductBrand'
import type { ProductBrandProps } from '../../ProductBrand'
import brandLogoQuery from '../../graphql/productBrand.gql'

const mocks = [
  {
    request: {
      query: brandLogoQuery,
      variables: {
        id: 2000850,
      },
    },
    result: {
      data: {
        brand: {
          slug: 'billabong',
          imageUrl: '/220310/billabong.jpg',
        },
      },
    },
  },
]

const mocksWithoutImage = [
  {
    request: {
      query: brandLogoQuery,
      variables: {
        id: 2000850,
      },
    },
    result: {
      data: {
        brand: {
          slug: 'billabong',
        },
      },
    },
  },
]

describe('<ProductBrand /> component', () => {
  const renderComponent = (props: ProductBrandProps) => {
    const comp = <ProductBrand {...props} loadingPlaceholder="logo" />

    return render(comp, { graphql: { mocks } })
  }

  const renderComponentWithoutImage = (props: ProductBrandProps) => {
    const comp = <ProductBrand {...props} loadingPlaceholder="logo" />

    return render(comp, { graphql: { mocks: mocksWithoutImage } })
  }

  beforeEach(() => {
    jest.useFakeTimers()
  })

  it('brand image should not have a link', async () => {
    const { queryByTestId } = renderComponent({})

    await wait(() => {
      jest.runAllTimers()
    })

    expect(queryByTestId('logo-redirect')).toBeNull()
    expect(queryByTestId('name-redirect')).toBeNull()
  })

  it('brand image should be backwards compatible and have a link', async () => {
    const { queryByTestId } = renderComponent({
      logoWithLink: true,
    })

    await wait(() => {
      jest.runAllTimers()
    })

    expect(queryByTestId('logo-redirect')).toBeDefined()
    expect(queryByTestId('name-redirect')).toBeNull()
  })

  it('brand text should have a link', async () => {
    const { queryByTestId } = renderComponent({
      withLink: 'text',
      displayMode: 'text',
    })

    await wait(() => {
      jest.runAllTimers()
    })

    expect(queryByTestId('logo-redirect')).toBeNull()
    expect(queryByTestId('name-redirect')).toBeDefined()
  })

  it('brand text should have a link when withLink equals logoAndText', async () => {
    const { queryByTestId } = renderComponent({
      withLink: 'logoAndText',
      displayMode: 'text',
    })

    await wait(() => {
      jest.runAllTimers()
    })

    expect(queryByTestId('logo-redirect')).toBeNull()
    expect(queryByTestId('name-redirect')).toBeDefined()
  })

  it('brand image should have a link when withLink equals logoAndText', async () => {
    const { queryByTestId } = renderComponent({
      withLink: 'logoAndText',
    })

    await wait(() => {
      jest.runAllTimers()
    })

    expect(queryByTestId('logo-redirect')).toBeDefined()
    expect(queryByTestId('name-redirect')).toBeNull()
  })

  it('brand should fallback to text and not have a link when withLinks equals logo', async () => {
    const { queryByTestId } = renderComponentWithoutImage({
      withLink: 'logo',
    })

    await wait(() => {
      jest.runAllTimers()
    })

    expect(queryByTestId('logo-redirect')).toBeNull()
    expect(queryByTestId('name-redirect')).toBeNull()
  })

  it('brand should fallback to text and have a link when withLinks equals text', async () => {
    const { queryByTestId } = renderComponentWithoutImage({
      withLink: 'text',
    })

    await wait(() => {
      jest.runAllTimers()
    })

    expect(queryByTestId('logo-redirect')).toBeNull()
    expect(queryByTestId('name-redirect')).toBeDefined()
  })

  it('brand should fallback to text and have a text link when withLink equals logoAndText', async () => {
    const { queryByTestId } = renderComponentWithoutImage({
      withLink: 'logoAndText',
    })

    await wait(() => {
      jest.runAllTimers()
    })

    expect(queryByTestId('logo-redirect')).toBeNull()
    expect(queryByTestId('name-redirect')).toBeDefined()
  })
})

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of store-components/react/__tests__/components/Newsletter.test.js from the store-components VTEX app.

[Assistant]
Here's the implementation:

```javascript
import React from 'react'
import { fireEvent, render } from '@vtex/test-tools/react'

import Newsletter from '../../components/Newsletter'
import subscribeNewsletter from '../../components/Newsletter/mutations/subscribeNewsletter.graphql'

const placeholderTextId = 'store/newsletter.placeholder'
const labelTextId = 'store/newsletter.label'
const submitTextId = 'store/newsletter.submit'
const thanksTextId = 'store/newsletter.confirmationTitle'
const errorTextId = 'store/newsletter.error'

test('should have label, input and submit', () => {
  const { getByLabelText, getByText } = render(
    <Newsletter
      placeholder={placeholderTextId}
      label={labelTextId}
      submit={submitTextId}
    />
  )

  const input = getByLabelText(labelTextId)
  const submit = getByText(submitTextId)

  expect(input).toBeTruthy()
  expect(submit).toBeTruthy()
})

test('should add error message when user types wrong email', () => {
  const { getByLabelText, getByText } = render(
    <Newsletter
      placeholder={placeholderTextId}
      label={labelTextId}
      submit={submitTextId}
    />
  )

  const mockedInput = getByLabelText(labelTextId)
  const submit = getByText(submitTextId)

  const wrongEmail = 'foobar'

  fireEvent.change(mockedInput, { target: { value: wrongEmail } })
  fireEvent.click(submit)

  expect(mockedInput).toHaveAttribute('data-errormessage')
})

test('should call mutation', async () => {
  const email = 'breno@mailinator.com'
  const mocks = [
    {
      request: {
        query: subscribeNewsletter,
        variables: { email },
      },
      result: {
        data: {
          subscribeNewsletter: {},
        },
      },
    },
  ]

  const { getByLabelText, getByText, findByText } = render(
    <Newsletter
      placeholder={placeholderTextId}
      label={labelTextId}
      submit={submitTextId}
    />,
    {
      graphql: { mocks, addTypename: false },
    }
  )

  const input = getByLabelText(labelTextId)
  const submit = getByText(submitTextId)

  fireEvent.change(input, { target: { value: email } })
  fireEvent.click(submit)

  const thanks = await findByText(thanksTextId)

  expect(thanks).toBeTruthy()
})

test('should handle mutation error', async () => {
  const email = 'breno@mailinator.com'
  const mocks = [
    {
      request: {
        query: subscribeNewsletter,
        variables: { email },
      },
      error: new Error('ops'),
    },
  ]

  const { getByLabelText, getByText, findByText } = render(
    <Newsletter
      placeholder={placeholderTextId}
      label={labelTextId}
      submit={submitTextId}
    />,
    {
      graphql: { mocks, addTypename: false },
    }
  )

  const input = getByLabelText(labelTextId)
  const submit = getByText(submitTextId)

  fireEvent.change(input, { target: { value: email } })
  fireEvent.click(submit)

  const error = await findByText(errorTextId)

  expect(error).toBeTruthy()
})

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of store-components/react/__tests__/components/Greeting.test.js from the store-components VTEX app.

[Assistant]
Here's the implementation:

```javascript
import React from 'react'
import { render, waitFor } from '@vtex/test-tools/react'

import orderFormQuery from '../../components/Greeting/queries/orderForm.gql'
import Greeting from '../../Greeting'

const mocks = [
  {
    request: {
      query: orderFormQuery,
    },
    result: {
      data: {
        minicart: {
          orderForm: '{ "clientProfileData": { "firstName": "Adam" } }',
        },
      },
    },
  },
]

describe('<Greeting /> component', () => {
  beforeEach(() => {
    jest.useFakeTimers()
  })

  const renderComponent = customProps => {
    const props = {
      ...customProps,
    }

    return render(<Greeting {...props} />, { graphql: { mocks } })
  }

  it('should render name in orderForm', async () => {
    const { queryByText } = renderComponent()

    await waitFor(() => {
      jest.runAllTimers()
    })

    expect(queryByText('Adam')).not.toBeFalsy()
  })

  // eslint-disable-next-line jest/no-identical-title
  it('should render name in orderForm', async () => {
    const { queryByTestId } = renderComponent({ loading: true })

    await waitFor(() => {
      jest.runAllTimers()
    })

    expect(queryByTestId('greeting-loader')).not.toBeFalsy()
  })
})

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of store-components/react/__tests__/components/ProductSpecifications.test.js from the store-components VTEX app.

[Assistant]
Here's the implementation:

```javascript
import React from 'react'
import { render } from '@vtex/test-tools/react'

import ProductSpecifications from '../../ProductSpecifications'

describe('<ProductSpecifications /> component', () => {
  const renderComponent = customProps => {
    const props = {
      ...customProps,
    }

    const comp = <ProductSpecifications {...props} />

    return render(comp)
  }

  it('should be rendered', () => {
    const { asFragment } = renderComponent()

    expect(asFragment()).toBeTruthy()
  })

  it('should match snapshot with table view and no specifications', () => {
    const { asFragment } = renderComponent()

    expect(asFragment()).toMatchSnapshot()
  })

  it('should match snapshot with table view and with specification', () => {
    const { asFragment } = renderComponent({
      specifications: [{ name: 'test', values: ['value'] }],
    })

    expect(asFragment()).toMatchSnapshot()
  })

  it('should match snapshot with tabs view', () => {
    const { asFragment } = renderComponent({
      specifications: [{ name: 'test', values: ['value'] }],
      tabsMode: true,
    })

    expect(asFragment()).toMatchSnapshot()
  })
})

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of store-components/react/__tests__/components/DiscountBadge.test.js from the store-components VTEX app.

[Assistant]
Here's the implementation:

```javascript
import React from 'react'
import { render } from '@vtex/test-tools/react'

import DiscountBadge from '../../DiscountBadge'

describe('<DiscountBadge /> component', () => {
  function renderComponent(customProps = {}) {
    const props = {
      listPrice: 100,
      sellingPrice: 90,
      ...customProps,
    }

    const component = <DiscountBadge {...props}>Test</DiscountBadge>

    return render(component)
  }

  it('should be able to mount and not break', () => {
    const { asFragment } = renderComponent()

    expect(asFragment()).toBeTruthy()
  })

  it('should match snapshot without label', () => {
    const { asFragment } = renderComponent()

    expect(asFragment()).toMatchSnapshot()
  })

  it('should match snapshot with label', () => {
    const { asFragment } = renderComponent({ label: 'LABEL' })

    expect(asFragment()).toMatchSnapshot()
  })
})

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of store-components/react/__tests__/components/ShippingSimulator.test.js from the store-components VTEX app.

[Assistant]
Here's the implementation:

```javascript
import React from 'react'
import { render } from '@vtex/test-tools/react'

import ShippingSimulator from '../../ShippingSimulator'

describe('<ShippingSimulator /> component', () => {
  const renderComponent = (customProps = {}) => {
    const props = {
      country: 'brazil',
      ...customProps,
    }

    return render(<ShippingSimulator {...props} />)
  }

  it('should be able to mount and not break', () => {
    const { asFragment } = renderComponent()

    expect(asFragment()).toBeTruthy()
  })

  it('should match snapshot without skuId and seller', () => {
    const { asFragment } = renderComponent()

    expect(asFragment()).toMatchSnapshot()
  })

  it('should match snapshot with skuId and seller', () => {
    const props = {
      skuId: 'skuId',
      seller: '1',
    }

    const { asFragment } = renderComponent(props)

    expect(asFragment()).toMatchSnapshot()
  })
})

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of store-components/react/__tests__/components/InfoCard.test.js from the store-components VTEX app.

[Assistant]
Here's the implementation:

```javascript
import React from 'react'
import { render } from '@vtex/test-tools/react'

import InfoCard from '../../InfoCard'

describe('<InfoCard />', () => {
  const renderComponent = props => {
    const defaultProps = {
      isFullModeStyle: false,
      headline: 'MY HEADLINE',
      subhead: 'MY SUBHEAD',
      imageUrl: 'my-image.com/image.png',
      callToActionText: 'CLICK HERE',
      callToActionUrl: 'classic-shoes/p',
    }

    return render(<InfoCard {...defaultProps} {...props} />)
  }

  it('should render with full mode style', () => {
    const { asFragment, getByTestId } = renderComponent({
      isFullModeStyle: true,
    })

    expect(asFragment()).toBeDefined()
    const container = getByTestId('container')

    expect(container.style['background-image']).toBeDefined()
    expect(asFragment()).toMatchSnapshot()
  })
  it('should render with image and text side by side', () => {
    const { asFragment, getByTestId } = renderComponent()

    expect(asFragment()).toBeDefined()
    const halfImage = getByTestId('half-image')

    expect(halfImage).toBeDefined()
    expect(asFragment()).toMatchSnapshot()
  })
  it('should render without a call to action', () => {
    const { asFragment } = renderComponent({
      isFullModeStyle: true,
      callToActionMode: 'none',
    })

    expect(asFragment()).toBeDefined()
    expect(asFragment()).toMatchSnapshot()
  })
  it('should wrap half image in a link with imageActionUrl', () => {
    const { asFragment } = renderComponent({
      isFullModeStyle: false,
      callToActionMode: 'none',
      imageActionUrl: 'classic-shoes/p',
    })

    expect(asFragment()).toBeDefined()
    expect(asFragment()).toMatchSnapshot()
  })
  it('should wrap whole container in a link with imageActionUrl', () => {
    const { asFragment } = renderComponent({
      isFullModeStyle: true,
      callToActionMode: 'none',
      imageActionUrl: 'classic-shoes/p',
      textAlignment: 'right',
      textPosition: 'center',
    })

    expect(asFragment()).toBeDefined()
    expect(asFragment()).toMatchSnapshot()
  })
  it('should insert span with class on headline', () => {
    const { asFragment } = renderComponent({
      isFullModeStyle: true,
      callToActionMode: 'none',
      textAlignment: 'right',
      textPosition: 'center',
      headline:
        'HEADLINE <span class="my-custom-class">THIS IS BOOOLD AND BLUE</span> HEADLINE STILL',
    })

    expect(asFragment()).toBeDefined()
    expect(asFragment()).toMatchSnapshot()
  })
  it('should not render subhead', () => {
    const { asFragment } = renderComponent({
      isFullModeStyle: true,
      callToActionMode: 'none',
      textAlignment: 'right',
      textPosition: 'center',
      headline:
        'HEADLINE <span class="my-custom-class">THIS IS BOOOLD AND BLUE</span> HEADLINE STILL',
      subhead: '',
    })

    expect(asFragment()).toBeDefined()
    expect(asFragment()).toMatchSnapshot()
  })
  it("should render subhead and headline using the RichText component when textMode is set to 'rich-text'", () => {
    const { asFragment } = renderComponent({
      isFullModeStyle: true,
      callToActionMode: 'none',
      textAlignment: 'right',
      textPosition: 'center',
      textMode: 'rich-text',
      headline: 'This is a headline, and should be inside a rich-text.',
      subhead: 'This is a subhead, and should be inside a rich-text.',
    })

    expect(asFragment()).toBeDefined()
    expect(asFragment()).toMatchSnapshot()
  })
  it('should not render bodyText', () => {
    const { asFragment } = renderComponent({
      isFullModeStyle: true,
      callToActionMode: 'none',
      textAlignment: 'right',
      textPosition: 'center',
      headline:
        'HEADLINE <span class="my-custom-class">THIS IS BOOOLD AND BLUE</span> HEADLINE STILL',
      subhead: '',
      bodyText: '',
    })

    expect(asFragment()).toBeDefined()
    expect(asFragment()).toMatchSnapshot()
  })
  it("should render bodyText, subhead and headline using the RichText component when textMode is set to 'rich-text'", () => {
    const { asFragment } = renderComponent({
      isFullModeStyle: true,
      callToActionMode: 'none',
      textAlignment: 'right',
      textPosition: 'center',
      textMode: 'rich-text',
      headline: 'This is a headline, and should be inside a rich-text.',
      subhead: 'This is a subhead, and should be inside a rich-text.',
      bodyText: 'This is a bodyText, and should be inside a rich-text.',
    })

    expect(asFragment()).toBeDefined()
    expect(asFragment()).toMatchSnapshot()
  })
})

```