[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 add-to-cart-button/react/__fixtures__/runtime.ts from the add-to-cart-button VTEX app.

[Assistant]
Here's the implementation:

```typescript
/**
 * This mock runtime does not include fields:
 * - blocks
 * - blocksTree
 * - cacheHints
 * - components
 * - contentMap
 * - emitter
 * - introspectionResult
 * - workspaceCookie
 *
 * The following fields are set to = {}
 * - extensions
 * - messages
 */

export const runtime = {
  account: 'storecomponents',
  accountId: 'eade3d41847e4226b1c4e2fa592bcfad',
  amp: false,
  appsEtag: 'remove',
  assetServerLinkedHost: 'storecomponents.myvtex.com',
  assetServerLinkedPath: '/_v/private/assets/v1/linked/',
  assetServerPublishedHost: 'storecomponents.vtexassets.com',
  assetServerPublishedPath: '/_v/public/assets/v1/published/',
  binding: {
    id: 'aacb06b3-a8fa-4bab-b5bd-2d654d20dcd8',
    canonicalBaseAddress: 'storetheme.vtex.com/',
  },
  bindingChanged: false,
  culture: {
    availableLocales: [],
    country: 'USA',
    currency: 'USD',
    language: 'en',
    locale: 'en-US',
    customCurrencyDecimalDigits: null,
    customCurrencySymbol: '$',
  },
  disableSSQ: false,
  disableSSR: false,
  exposeBindingAddress: false,
  extensions: {},
  hints: {
    desktop: true,
    mobile: false,
    phone: false,
    tablet: false,
    unknown: false,
  },
  messages: {},
  page: 'store.home',
  pages: {
    'store.home': {
      allowConditions: true,
      context: null,
      declarer: 'vtex.store@2.x',
      path: '/',
      routeId: 'store.home',
      blockId: 'vtex.store-theme@3.x:store.home',
      map: [],
    },
    'store.account': {
      allowConditions: true,
      context: null,
      declarer: 'vtex.store@2.x',
      path: '/account',
      routeId: 'store.account',
      blockId: 'vtex.store-theme@3.x:store.account',
      map: [],
    },
    'store.login': {
      allowConditions: true,
      context: null,
      declarer: 'vtex.store@2.x',
      path: '/login',
      routeId: 'store.login',
      blockId: 'vtex.store-theme@3.x:store.login',
      map: [],
    },
    'store.product': {
      allowConditions: true,
      context: 'vtex.store@2.x/ProductContext',
      declarer: 'vtex.store@2.x',
      path: '/_v/segment/routing/vtex.store@2.x/product/:id/:slug/p',
      routeId: 'store.product',
      blockId: 'vtex.store-theme@3.x:store.product',
      canonical: '/:slug/p',
      map: [],
    },
    'store.search': {
      allowConditions: true,
      context: 'vtex.store@2.x/SearchContext',
      declarer: 'vtex.store@2.x',
      path: '/:term/s',
      routeId: 'store.search',
      blockId: 'vtex.store-theme@3.x:store.search',
      canonical: '/:term',
      map: [],
    },
    'store.search#brand': {
      allowConditions: true,
      context: 'vtex.store@2.x/SearchContext',
      declarer: 'vtex.store@2.x',
      path: '/_v/segment/routing/vtex.store@2.x/brand/:id/:brand(/*terms)',
      routeId: 'store.search#brand',
      blockId: 'vtex.store-theme@3.x:store.search#brand',
      canonical: '/:brand',
      map: ['b'],
    },
    'store.search#department': {
      allowConditions: true,
      context: 'vtex.store@2.x/SearchContext',
      declarer: 'vtex.store@2.x',
      path:
        '/_v/segment/routing/vtex.store@2.x/department/:id/:department(/*terms)',
      routeId: 'store.search#department',
      blockId: 'vtex.store-theme@3.x:store.search#department',
      canonical: '/:department',
      map: ['c'],
    },
    'store.search#category': {
      allowConditions: true,
      context: 'vtex.store@2.x/SearchContext',
      declarer: 'vtex.store@2.x',
      path:
        '/_v/segment/routing/vtex.store@2.x/category/:id/:department/:category(/*terms)',
      routeId: 'store.search#category',
      blockId: 'vtex.store-theme@3.x:store.search#category',
      canonical: '/:department/:category',
      map: ['c', 'c'],
    },
    'store.search#subcategory': {
      allowConditions: true,
      context: 'vtex.store@2.x/SearchContext',
      declarer: 'vtex.store@2.x',
      path:
        '/_v/segment/routing/vtex.store@2.x/subcategory/:id/:department/:category/:subcategory(/*terms)',
      routeId: 'store.search#subcategory',
      blockId: 'vtex.store-theme@3.x:store.search#subcategory',
      canonical: '/:department/:category/:subcategory(/*terms)',
      map: ['c', 'c', 'c'],
    },
    'store.search#configurable': {
      allowConditions: true,
      context: 'vtex.store@2.x/SearchContext',
      declarer: 'vtex.store@2.x',
      path: '/s/*terms',
      routeId: 'store.search#configurable',
      blockId: 'vtex.store-theme@3.x:store.search',
      map: [],
    },
    'store.orderplaced': {
      allowConditions: true,
      context: null,
      declarer: 'vtex.store@2.x',
      path: '/checkout/orderPlaced',
      routeId: 'store.orderplaced',
      blockId: 'vtex.store-theme@3.x:store.orderplaced',
      map: [],
    },
    'store.offline': {
      allowConditions: true,
      context: null,
      declarer: 'vtex.store@2.x',
      path: '/_v/offline',
      routeId: 'store.offline',
      blockId: 'vtex.store@2.x:store.offline',
      map: [],
    },
    'store.not-found#product': {
      allowConditions: true,
      context: null,
      declarer: 'vtex.store@2.x',
      path: '/_v/segment/routing/vtex.store@2.x/notFoundProduct/:id/:slug/p',
      routeId: 'store.not-found#product',
      blockId: 'vtex.store-theme@3.x:store.not-found#product',
      canonical: '/:slug/p',
      map: [],
    },
    'store.not-found#search': {
      allowConditions: true,
      context: null,
      declarer: 'vtex.store@2.x',
      path: '/_v/segment/routing/vtex.store@2.x/notFoundSearch/:id/*terms',
      routeId: 'store.not-found#search',
      blockId: 'vtex.store-theme@3.x:store.not-found#search',
      canonical: '/*terms',
      map: [],
    },
    'store.custom#about-us': {
      allowConditions: true,
      context: null,
      declarer: 'vtex.store-theme@3.x',
      path: '/about-us',
      routeId: 'store.custom#about-us',
      blockId: 'vtex.store-theme@3.x:store.custom#about-us',
      map: [],
    },
    'vtex.store@2.x:store.custom#scheduled-page': {
      allowConditions: true,
      context: null,
      declarer: null,
      auth: false,
      path: '/scheduled-page',
      routeId: 'vtex.store@2.x:store.custom#scheduled-page',
      blockId: 'vtex.store@2.x:store.custom',
      map: [],
    },
  },
  platform: 'vtex',
  production: false,
  publicEndpoint: 'myvtex.com',
  query: {},
  renderMajor: 8,
  route: {
    domain: 'store',
    id: 'store.home',
    pageContext: {
      id: 'store.home',
      type: 'route',
    },
    params: {},
    path: '/',
    pathId: '/',
    queryString: {},
    fonts:
      '/_v/public/vtex.styles-graphql/v1/fonts/763084e2070c87d114459f42f07894b40143cfcc',
    overrides: [
      '/_v/public/vtex.styles-graphql/v1/overrides/vtex.product-list@0.19.0$overrides.css',
      '/_v/public/vtex.styles-graphql/v1/overrides/vtex.minicart@2.44.0$overrides.css',
      '/_v/public/vtex.styles-graphql/v1/overrides/vtex.store-theme@3.30.1$overrides.css',
    ],
    rootName: 'store.home',
    ssr: true,
    style:
      '/_v/public/vtex.styles-graphql/v1/style/vtex.store-theme@3.21.2$style.min.css',
    styleMeta: {
      fontsHash: '763084e2070c87d114459f42f07894b40143cfcc',
      overridesIds: [
        {
          id: 'vtex.product-list@0.19.0$overrides.css',
        },
        {
          id: 'vtex.minicart@2.44.0$overrides.css',
        },
        {
          id: 'vtex.store-theme@3.30.1$overrides.css',
        },
      ],
      themeId: 'vtex.store-theme@3.21.2$style.min.css',
    },
    blockId: 'vtex.store-theme@3.x:store.home',
    canonicalPath: '/',
    metaTags: null,
    routeId: 'store.home',
    title: null,
    varyContentById: false,
  },
  runtimeMeta: {
    config: null,
    version: '8.95.1',
  },
  segmentToken: '12345abcde',
  settings: {
    'vtex.store': {
      storeName: 'Store Theme - VTEX Base Store',
      titleTag: 'Store Theme - VTEX Base Store',
      metaTagDescription: 'Store Theme - VTEX Base Store',
      metaTagKeywords: 'store theme, vtex, store, vtex io, base store, vtex',
    },
  },
  start: true,
  workspace: 'addtocartbutton',
}

```


[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 add-to-cart-button/react/__fixtures__/session.ts from the add-to-cart-button VTEX app.

[Assistant]
Here's the implementation:

```typescript
export const sessionWithEmptyPublicFields = {
  id: '1a2b3c4d-a12b-12a3-123a-ab123cd4efg5',
  namespaces: {
    account: {
      id: {
        value: '1a2b3c4d-a12b-12a3-123a-ab123cd4efg5',
        keepAlive: true,
      },
      accountName: {
        value: 'storecomponents',
      },
    },
    store: {
      channel: {
        value: '1',
      },
      countryCode: {
        value: 'USA',
      },
      cultureInfo: {
        value: 'en-US',
      },
      currencyCode: {
        value: 'USD',
      },
      currencySymbol: {
        value: '$',
      },
      admin_cultureInfo: {
        value: 'en-US',
      },
    },
    public: {},
    creditControl: {
      creditAccounts: {
        value: {
          accounts: [],
        },
      },
      deadlines: {
        value: {
          deadlines: [],
        },
      },
      minimumInstallmentValue: {
        value: 0,
      },
    },
    authentication: {},
    profile: {
      isAuthenticated: {
        value: 'false',
      },
    },
  },
}

export const sessionWithOnlyUtmiFields = {
  ...sessionWithEmptyPublicFields,
  namespaces: {
    ...sessionWithEmptyPublicFields.namespaces,
    public: {
      utmi_cp: { value: 'test_utmi_field' },
      utmi_p: { value: 'test_utmi_field' },
      utmi_pc: { value: 'test_utmi_field' },
    },
  },
}

export const sessionWithOnlyUtmFields = {
  ...sessionWithEmptyPublicFields,
  namespaces: {
    ...sessionWithEmptyPublicFields.namespaces,
    public: {
      utm_source: { value: 'test_utm_field' },
      utm_medium: { value: 'test_utm_field' },
      utm_campaign: { value: 'test_utm_field' },
    },
  },
}

export const sessionWithAllMarketingFields = {
  ...sessionWithEmptyPublicFields,
  namespaces: {
    ...sessionWithEmptyPublicFields.namespaces,
    public: {
      utm_source: { value: 'test_utm_field' },
      utm_medium: { value: 'test_utm_field' },
      utm_campaign: { value: 'test_utm_field' },
      utmi_cp: { value: 'test_utmi_field' },
      utmi_p: { value: 'test_utmi_field' },
      utmi_pc: { value: 'test_utmi_field' },
    },
  },
}

```


[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 add-to-cart-button/react/__fixtures__/render8Session.ts from the add-to-cart-button VTEX app.

[Assistant]
Here's the implementation:

```typescript
export function mockedRenderSession(session?: any) {
  return {
    __RENDER_8_SESSION__: {
      sessionPromise: new Promise((resolve, reject) => {
        process.nextTick(() => {
          session || session === null
            ? resolve({ response: session })
            : reject('could not find session info')
        })
      }),
    },
  }
}

```


[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 add-to-cart-button/react/__fixtures__/assemblyOptions.ts from the add-to-cart-button VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { AssemblyOptions } from '../modules/assemblyOptions'

export const customBell: AssemblyOptions = {
  items: {
    'add-on_Add-on': [
      {
        name: 'Bells add-ons Logo small',
        id: '2000588',
        initialQuantity: 0,
        quantity: 1,
        seller: '1',
        price: 75,
        choiceType: 'TOGGLE',
        children: null,
      },
      {
        name: 'Bells add-ons Logo big',
        id: '2000589',
        initialQuantity: 0,
        quantity: 1,
        seller: '1',
        price: 90,
        choiceType: 'TOGGLE',
        children: null,
      },
      {
        name: 'Bells add-ons Plaque',
        id: '2000590',
        initialQuantity: 0,
        quantity: 0,
        seller: '1',
        price: 60,
        choiceType: 'TOGGLE',
        children: null,
      },
    ],
    'text_style_Text Style': [
      {
        name: 'Bells add-ons Roman',
        id: '2000591',
        initialQuantity: 1,
        quantity: 0,
        seller: '1',
        price: 0,
        choiceType: 'SINGLE',
        children: null,
      },
      {
        name: 'Bells add-ons Script',
        id: '2000592',
        initialQuantity: 0,
        quantity: 1,
        seller: '1',
        price: 15,
        choiceType: 'SINGLE',
        children: null,
      },
    ],
    engraving_Engraving: [
      {
        name: 'Bells add-ons 1-3 lines',
        id: '2000586',
        initialQuantity: 0,
        quantity: 1,
        seller: '1',
        price: 26,
        choiceType: 'SINGLE',
        children: {
          '1-3-lines': [],
        },
      },
      {
        name: 'Bells add-ons 4 lines',
        id: '2000587',
        initialQuantity: 0,
        quantity: 0,
        seller: '1',
        price: 30,
        choiceType: 'SINGLE',
        children: {
          '4-lines': [],
        },
      },
    ],
  },
  inputValues: {
    '1-3-lines': {
      'Line 1': 'First line',
      'Line 2': 'Second line',
      'Line 3': 'Third line',
    },
  },
  areGroupsValid: {
    'add-on_Add-on': true,
    'text_style_Text Style': true,
    engraving_Engraving: true,
  },
}

export const starColor = {
  items: {
    Customization: [],
  },
  inputValues: {
    Customization: {
      Font: 'Sans serif',
      'Front text': 'Frente',
      'Back text': 'Verso',
      'Glossy print': true,
    },
  },
  areGroupsValid: {
    Customization: true,
  },
}

export const comboPizza: AssemblyOptions = {
  items: {
    'pizza_composition_Pizza flavor': [
      {
        name: 'Pizza Monster promo',
        id: '5101',
        initialQuantity: 1,
        quantity: 1,
        seller: '1',
        price: 0,
        choiceType: 'SINGLE',
        children: {
          pizza_extra_ingredients_Extra: [
            {
              name: 'Ingredients bacon',
              id: '602',
              initialQuantity: 0,
              quantity: 0,
              seller: '1',
              price: 1,
              choiceType: 'MULTIPLE',
              children: null,
            },
            {
              name: 'Ingredients herb',
              id: '603',
              initialQuantity: 0,
              quantity: 1,
              seller: '1',
              price: 1,
              choiceType: 'MULTIPLE',
              children: null,
            },
            {
              name: 'Ingredients mushroom',
              id: '605',
              initialQuantity: 0,
              quantity: 0,
              seller: '1',
              price: 1,
              choiceType: 'MULTIPLE',
              children: null,
            },
            {
              name: 'Ingredients onion',
              id: '606',
              initialQuantity: 0,
              quantity: 0,
              seller: '1',
              price: 1,
              choiceType: 'MULTIPLE',
              children: null,
            },
            {
              name: 'Ingredients pepper',
              id: '607',
              initialQuantity: 0,
              quantity: 0,
              seller: '1',
              price: 1,
              choiceType: 'MULTIPLE',
              children: null,
            },
            {
              name: 'Ingredients tomato',
              id: '609',
              initialQuantity: 0,
              quantity: 1,
              seller: '1',
              price: 1,
              choiceType: 'MULTIPLE',
              children: null,
            },
          ],
          pizza_basic_ingredients_pizza_basic_ingredients: [
            {
              name: 'Ingredients bacon',
              id: '602',
              initialQuantity: 1,
              quantity: 0,
              seller: '1',
              price: 0,
              choiceType: 'TOGGLE',
              children: null,
            },
            {
              name: 'Ingredients onion',
              id: '606',
              initialQuantity: 1,
              quantity: 1,
              seller: '1',
              price: 0,
              choiceType: 'TOGGLE',
              children: null,
            },
            {
              name: 'Ingredients tomato',
              id: '609',
              initialQuantity: 1,
              quantity: 1,
              seller: '1',
              price: 0,
              choiceType: 'TOGGLE',
              children: null,
            },
          ],
        },
      },
    ],
    'drinks_size_double_Choose 2 drinks': [
      {
        name: 'Cola 600ml',
        id: '110',
        initialQuantity: 2,
        quantity: 1,
        seller: '1',
        price: 0,
        choiceType: 'MULTIPLE',
        children: null,
      },
      {
        name: 'Cola diet 600ml',
        id: '120',
        initialQuantity: 0,
        quantity: 0,
        seller: '1',
        price: 0,
        choiceType: 'MULTIPLE',
        children: null,
      },
      {
        name: 'Orange Juice 600ml',
        id: '180',
        initialQuantity: 0,
        quantity: 0,
        seller: '1',
        price: 3,
        choiceType: 'MULTIPLE',
        children: null,
      },
    ],
  },
  inputValues: {},
  areGroupsValid: {
    'pizza_composition_Pizza flavor': true,
    'drinks_size_double_Choose 2 drinks': false,
  },
}

```


[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 add-to-cart-button/react/typings/vtex.shipping-option-components.d.ts from the add-to-cart-button VTEX app.

[Assistant]
Here's the implementation:

```typescript
declare module 'vtex.shipping-option-components'
declare module 'vtex.shipping-option-components/ShippingOptionContext' {
  export type ShippingMethod = 'delivery' | 'pickup-in-point'

  export function useShippingOptionState(): {
    shippingOption?: ShippingMethod
  }
}

```


[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 add-to-cart-button/react/typings/vtex.order-manager.d.ts from the add-to-cart-button VTEX app.

[Assistant]
Here's the implementation:

```typescript
declare module 'vtex.order-manager'
declare module 'vtex.order-manager/*'

```


[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 add-to-cart-button/react/typings/vtex.order-items.d.ts from the add-to-cart-button VTEX app.

[Assistant]
Here's the implementation:

```typescript
declare module 'vtex.order-items'
declare module 'vtex.order-items/*'

```


[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 add-to-cart-button/react/__tests__/hooks.test.tsx from the add-to-cart-button VTEX app.

[Assistant]
Here's the implementation:

```tsx
import { renderHook, act } from '@vtex/test-tools/react'
import wait from 'waait'

import useMarketingSessionParams from '../hooks/useMarketingSessionParams'
import { mockedRenderSession } from '../__fixtures__/render8Session'
import {
  sessionWithEmptyPublicFields,
  sessionWithOnlyUtmiFields,
  sessionWithOnlyUtmFields,
  sessionWithAllMarketingFields,
} from '../__fixtures__/session'

describe('useMarketingSessionParams', () => {
  const originalWindow = { ...window }
  let windowSpy: jest.SpyInstance

  beforeEach(() => {
    windowSpy = jest.spyOn(global as NodeJS.Global & Window, 'window', 'get')
  })
  afterEach(() => windowSpy.mockRestore())

  it('should return empty utmParams and utmiParams if no publicFields are found in sessionPromise', async () => {
    windowSpy.mockImplementation(() => ({
      ...originalWindow,
      ...mockedRenderSession(sessionWithEmptyPublicFields),
    }))

    const { result } = renderHook(() => useMarketingSessionParams())

    await act(async () => {
      await wait(1)
    })

    expect(result.current).toEqual({ utmParams: {}, utmiParams: {} })
  })

  it('should return empty objects if sessionPromise is nullish', async () => {
    windowSpy.mockImplementation(() => ({
      ...originalWindow,
      ...mockedRenderSession(null),
    }))

    const { result } = renderHook(() => useMarketingSessionParams())

    await act(async () => {
      await wait(1)
    })

    expect(result.current).toEqual({ utmParams: {}, utmiParams: {} })
  })

  it('should return empty strings for utmParams if there are no utm fields', async () => {
    windowSpy.mockImplementation(() => ({
      ...originalWindow,
      ...mockedRenderSession(sessionWithOnlyUtmiFields),
    }))

    const { result } = renderHook(() => useMarketingSessionParams())

    await act(async () => {
      await wait(1)
    })

    expect(result.current).toEqual({
      utmParams: {
        utmSource: '',
        utmMedium: '',
        utmCampaign: '',
      },
      utmiParams: {
        utmiCampaign: 'test_utmi_field',
        utmiPage: 'test_utmi_field',
        utmiPart: 'test_utmi_field',
      },
    })
  })

  it('should return empty utmiParams if there are no utmi fields', async () => {
    windowSpy.mockImplementation(() => ({
      ...originalWindow,
      ...mockedRenderSession(sessionWithOnlyUtmFields),
    }))

    const { result } = renderHook(() => useMarketingSessionParams())

    await act(async () => {
      await wait(1)
    })

    expect(result.current).toEqual({
      utmParams: {
        utmSource: 'test_utm_field',
        utmMedium: 'test_utm_field',
        utmCampaign: 'test_utm_field',
      },
      utmiParams: {
        utmiCampaign: '',
        utmiPage: '',
        utmiPart: '',
      },
    })
  })

  it('should correctly return all utm and utmi parameters', async () => {
    windowSpy.mockImplementation(() => ({
      ...originalWindow,
      ...mockedRenderSession(sessionWithAllMarketingFields),
    }))

    const { result } = renderHook(() => useMarketingSessionParams())

    await act(async () => {
      await wait(1)
    })

    expect(result.current).toEqual({
      utmParams: {
        utmSource: 'test_utm_field',
        utmMedium: 'test_utm_field',
        utmCampaign: 'test_utm_field',
      },
      utmiParams: {
        utmiCampaign: 'test_utmi_field',
        utmiPage: 'test_utmi_field',
        utmiPart: 'test_utmi_field',
      },
    })
  })
})

```


[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 add-to-cart-button/react/__tests__/CSSHandles.test.tsx from the add-to-cart-button VTEX app.

[Assistant]
Here's the implementation:

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

import { findCSSHandles } from '../modules/testUtils'
import AddToCartButton from '../AddToCartButton'

const CSS_HANDLES_API = [
  'buttonText',
  'buttonDataContainer',
  'tooltipLabelText',
]

/**
 * It is not good practice to test the CSS and it goes against
 * the philosophy behind react-testing-library, but it is useful in our
 * case because our CSS handles are a public API.
 */
describe('CSS handles API', () => {
  it('should have all expected CSS handles', () => {
    const { container } = render(
      <AddToCartButton
        isOneClickBuy
        customOneClickBuyLink=""
        available
        disabled={false}
        skuItems={[]}
        customToastUrl={''}
        showToast={() => {}}
        allSkuVariationsSelected={false}
      />
    )

    const foundHandles = findCSSHandles(container, CSS_HANDLES_API)
    expect(foundHandles).toEqual(CSS_HANDLES_API)
  })
})

```


[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 add-to-cart-button/react/__tests__/modules.test.ts from the add-to-cart-button VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { compareObjects } from '../modules/compareObjects'
import { StarColorTop } from '../__fixtures__/productContext'
import {
  customBell,
  comboPizza,
  starColor,
} from '../__fixtures__/assemblyOptions'
import {
  sumAssembliesPrice,
  transformAssemblyOptions,
  ItemOption,
} from '../modules/assemblyOptions'
import { mapCatalogItemToCart } from '../modules/catalogItemToCart'

describe('compareObjects module', () => {
  const obj1 = {
    key1: 'a',
    key2: {
      keyInsideKey: 'a',
      anotherKeyInsideAKey: 'b',
    },
    key3: 'c',
    key4: 'd',
    key5: 'e',
  }

  const obj2 = {
    key1: 'a',
    key2: {
      keyInsideKey: 'a',
      anotherKeyInsideAKey: 'b',
    },
    key3: 'c',
    key4: 'd',
    key5: 'e',
  }

  const obj3 = {
    key1: 'a',
    key2: {
      keyInsideKey: 'something different',
      anotherKeyInsideAKey: 'something different',
    },
    key3: 'c',
    key4: 'd',
    key5: 'e',
  }

  const obj4 = {
    key1: 'a',
    key2: 'a',
  }

  it('should return true for distinct objects with the same keys and values', () => {
    expect(compareObjects(obj1, obj2)).toBeTruthy()
  })
  it('should return true for the exact same object', () => {
    expect(compareObjects(obj1, obj1)).toBeTruthy()
  })
  it('should return false for objects with same keys but different values', () => {
    expect(compareObjects(obj1, obj3)).toBeFalsy()
  })
  it('should return false for objects with different keys', () => {
    expect(compareObjects(obj1, obj4)).toBeFalsy()
  })
})

describe('assemblyOptions module', () => {
  describe('sumAssembliesPrice function', () => {
    it('should return the correct total price for a set of assembly items', () => {
      const totalPriceFromCustomBellAssemblies = 75 + 90 + 15 + 26
      expect(sumAssembliesPrice(customBell.items as any)).toBe(
        totalPriceFromCustomBellAssemblies
      )
    })
    it('should return 0 if there are no assemblies for item', () => {
      expect(sumAssembliesPrice(starColor.items)).toBe(0)
    })
  })

  describe('transformAssemblyOptions function', () => {
    it('should transform assemblyOptions', () => {
      const parentPrice = 450
      const parentQuantity = 1

      const resultBell = transformAssemblyOptions({
        assemblyOptionsItems: customBell.items,
        inputValues: {},
        parentPrice,
        parentQuantity,
      })

      expect(resultBell.options).toHaveLength(7)
      const addonOption = resultBell.options[0] as ItemOption
      expect(addonOption.assemblyId).toBe('add-on_Add-on')
      expect(addonOption.id).toBe('2000588')
      expect(addonOption.quantity).toBe(1)
      expect(addonOption.seller).toBe('1')

      const resultPizza = transformAssemblyOptions({
        assemblyOptionsItems: comboPizza.items,
        inputValues: {},
        parentPrice,
        parentQuantity,
      })

      expect(resultPizza.options).toHaveLength(4)
      const pizzaOption = resultPizza.options[0] as ItemOption
      expect(pizzaOption.assemblyId).toBe('pizza_composition_Pizza flavor')
      expect(pizzaOption.id).toBe('5101')
      expect(pizzaOption.quantity).toBe(1)
      expect(pizzaOption.seller).toBe('1')
      expect(pizzaOption.options).toHaveLength(9)

      const drinksOptions = resultPizza.options[1] as ItemOption
      expect(drinksOptions.options).toBeUndefined()
    })

    it('input values', () => {
      const parentPrice = 450
      const parentQuantity = 1

      const resultStar = transformAssemblyOptions({
        assemblyOptionsItems: starColor.items,
        inputValues: starColor.inputValues,
        parentPrice,
        parentQuantity,
      })

      expect(resultStar.options).toHaveLength(1)
      const customization = resultStar.options[0] as ItemOption
      expect(customization.assemblyId).toBe('Customization')
      expect(customization.inputValues).toMatchObject({
        Font: 'Sans serif',
        'Front text': 'Frente',
        'Back text': 'Verso',
        'Glossy print': true,
      })
      expect(resultStar).toMatchInlineSnapshot(`
        Object {
          "assemblyOptions": Object {
            "added": Array [],
            "parentPrice": 450,
            "removed": Array [],
          },
          "options": Array [
            Object {
              "assemblyId": "Customization",
              "inputValues": Object {
                "Back text": "Verso",
                "Font": "Sans serif",
                "Front text": "Frente",
                "Glossy print": true,
              },
            },
          ],
        }
      `)
    })

    it('recursive input values', () => {
      const parentPrice = 450
      const parentQuantity = 1

      const resultBell = transformAssemblyOptions({
        assemblyOptionsItems: customBell.items,
        inputValues: customBell.inputValues,
        parentPrice,
        parentQuantity,
      })

      expect(resultBell.options).toHaveLength(7)

      const engraving = resultBell.options[5] as ItemOption
      expect(engraving.options).toHaveLength(1)

      const recursiveInputValue = engraving.options![0] as ItemOption
      expect(recursiveInputValue.assemblyId).toBe('1-3-lines')
      expect(recursiveInputValue.inputValues).toBe(
        customBell.inputValues['1-3-lines']
      )
      expect(resultBell).toMatchInlineSnapshot(`
        Object {
          "assemblyOptions": Object {
            "added": Array [
              Object {
                "choiceType": "TOGGLE",
                "extraQuantity": 1,
                "item": Object {
                  "id": "2000588",
                  "name": "Bells add-ons Logo small",
                  "quantity": 1,
                  "sellingPrice": 75,
                  "sellingPriceWithAssemblies": 75,
                },
                "normalizedQuantity": 1,
              },
              Object {
                "choiceType": "TOGGLE",
                "extraQuantity": 1,
                "item": Object {
                  "id": "2000589",
                  "name": "Bells add-ons Logo big",
                  "quantity": 1,
                  "sellingPrice": 90,
                  "sellingPriceWithAssemblies": 90,
                },
                "normalizedQuantity": 1,
              },
              Object {
                "choiceType": "SINGLE",
                "extraQuantity": 1,
                "item": Object {
                  "id": "2000592",
                  "name": "Bells add-ons Script",
                  "quantity": 1,
                  "sellingPrice": 15,
                  "sellingPriceWithAssemblies": 15,
                },
                "normalizedQuantity": 1,
              },
              Object {
                "choiceType": "SINGLE",
                "extraQuantity": 1,
                "item": Object {
                  "assemblyOptions": Object {
                    "added": Array [],
                    "parentPrice": 26,
                    "removed": Array [],
                  },
                  "id": "2000586",
                  "name": "Bells add-ons 1-3 lines",
                  "quantity": 1,
                  "sellingPrice": 26,
                  "sellingPriceWithAssemblies": 26,
                },
                "normalizedQuantity": 1,
              },
            ],
            "parentPrice": 450,
            "removed": Array [],
          },
          "options": Array [
            Object {
              "assemblyId": "add-on_Add-on",
              "id": "2000588",
              "quantity": 1,
              "seller": "1",
            },
            Object {
              "assemblyId": "add-on_Add-on",
              "id": "2000589",
              "quantity": 1,
              "seller": "1",
            },
            Object {
              "assemblyId": "add-on_Add-on",
              "id": "2000590",
              "quantity": 0,
              "seller": "1",
            },
            Object {
              "assemblyId": "text_style_Text Style",
              "id": "2000591",
              "quantity": 0,
              "seller": "1",
            },
            Object {
              "assemblyId": "text_style_Text Style",
              "id": "2000592",
              "quantity": 1,
              "seller": "1",
            },
            Object {
              "assemblyId": "engraving_Engraving",
              "id": "2000586",
              "options": Array [
                Object {
                  "assemblyId": "1-3-lines",
                  "inputValues": Object {
                    "Line 1": "First line",
                    "Line 2": "Second line",
                    "Line 3": "Third line",
                  },
                },
              ],
              "quantity": 1,
              "seller": "1",
            },
            Object {
              "assemblyId": "engraving_Engraving",
              "id": "2000587",
              "quantity": 0,
              "seller": "1",
            },
          ],
        }
      `)
    })

    it('empty input values should result in empty options', () => {
      const parentPrice = 450
      const parentQuantity = 1

      const resultStar = transformAssemblyOptions({
        assemblyOptionsItems: starColor.items,
        inputValues: {
          Customization: {},
        },
        parentPrice,
        parentQuantity,
      })
      expect(resultStar.options).toHaveLength(0)
    })
  })
})

describe('catalogToCart module', () => {
  it('should return [] if there are missing arguments', () => {
    expect(mapCatalogItemToCart({} as any)).toStrictEqual([])
  })
  it('should return expected skuItem for the minicart', () => {
    const { product } = StarColorTop
    const { selectedItem } = StarColorTop
    const { assemblyOptions } = StarColorTop
    const [selectedSeller] = StarColorTop.selectedItem.sellers
    const selectedQuantity =
      StarColorTop.selectedQuantity != null ? StarColorTop.selectedQuantity : 1

    const expectedOutput = [
      {
        index: 0,
        id: '2000564',
        ean: '123456',
        productId: '2000024',
        quantity: 1,
        uniqueId: '',
        detailUrl: '/star-color-top/p',
        name: 'Top Star Color Shirt',
        brand: 'Kawasaki',
        category: '/Apparel & Accessories/Clothing/Tops/',
        productRefId: '998765',
        seller: '1',
        sellerName: 'VTEX',
        variant: 'Red star',
        skuName: 'Red star',
        price: 3500,
        listPrice: 3500,
        sellingPrice: 3500,
        sellingPriceWithAssemblies: 3500,
        measurementUnit: 'un',
        skuSpecifications: [],
        imageUrl:
          'https://storecomponents.vtexassets.com/arquivos/ids/155518/download--40-.png?v=636942495289870000',
        options: [],
        assemblyOptions: {
          added: [],
          parentPrice: 35,
          removed: [],
        },
        referenceId: [
          { Key: 'RefId', Value: '987134', __typename: 'Reference' },
        ],
      },
    ]

    expect(
      mapCatalogItemToCart({
        product: product as any,
        selectedItem,
        selectedQuantity,
        selectedSeller,
        assemblyOptions,
      })
    ).toStrictEqual(expectedOutput)
  })
})

```


[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 add-to-cart-button/react/__tests__/AddToCartButton.test.tsx from the add-to-cart-button VTEX app.

[Assistant]
Here's the implementation:

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

import AddToCartButton from '../AddToCartButton'

const mockSKUItems = [
  {
    index: 0,
    id: '2000564',
    productId: '2000024',
    quantity: 1,
    uniqueId: '',
    detailUrl: '/star-color-top/p',
    name: 'Top Star Color Shirt',
    brand: 'Kawasaki',
    category: '/Apparel & Accessories/Clothing/Tops/',
    productRefId: '998765',
    seller: '1',
    sellerName: 'VTEX',
    variant: 'Red star',
    skuName: 'Red star',
    price: 3500,
    listPrice: 3500,
    sellingPrice: 3500,
    sellingPriceWithAssemblies: 3500,
    measurementUnit: 'un',
    skuSpecifications: [],
    imageUrl:
      'https://storecomponents.vtexassets.com/arquivos/ids/155518/download--40-.png?v=636942495289870000',
    options: [],
    assemblyOptions: {
      added: [],
      parentPrice: 35,
      removed: [],
    },
    referenceId: [{ Key: 'Reference', Value: 'red star' }],
  },
  {
    id: '2000535',
    productId: '2000004',
    quantity: 1,
    uniqueId: '',
    detailUrl: '/st-tropez-shorts/p',
    name: 'St Tropez Top Shorts',
    brand: 'Samsung',
    category: '/Apparel & Accessories/Clothing/Bottoms/',
    productRefId: '01212',
    seller: '1',
    sellerName: 'VTEX',
    variant: 'Navy Blue',
    skuName: 'Navy Blue',
    price: 303000,
    listPrice: 303000,
    sellingPrice: 303000,
    sellingPriceWithAssemblies: 303000,
    measurementUnit: 'un',
    skuSpecifications: [],
    imageUrl:
      'https://storecomponents.vtexassets.com/arquivos/ids/155488-500-auto?width=500&height=auto&aspect=true',
    options: [],
    assemblyOptions: { added: [], removed: [], parentPrice: 3030 },
    referenceId: null,
  },
]

const mockMarketingData = {
  utmSource: 'testing utmSource',
  utmMedium: 'testing utmMedium',
  utmCampaign: 'testing utmCampaign',
  utmiCampaign: 'testing utmiCampaign',
  utmiPage: 'testing utmiPage',
  utmiPart: 'testing utmiPart',
}

const mockProductLink = {
  linkText: 'mock-product',
  productId: '2000024',
}

const mockAllowedOutdatedData = {
  allowedOutdatedData: ['paymentData'],
}

const mockAddItem = jest.fn()
const mockPixelEventPush = jest.fn()
const mockNavigate = jest.fn()
const mockUseShippingOptionState = jest.fn()

jest.mock('../hooks/useMarketingSessionParams', () => {
  return () => ({
    utmParams: {
      utmSource: mockMarketingData.utmSource,
      utmMedium: mockMarketingData.utmMedium,
      utmCampaign: mockMarketingData.utmCampaign,
    },
    utmiParams: {
      utmiCampaign: mockMarketingData.utmiCampaign,
      utmiPage: mockMarketingData.utmiPage,
      utmiPart: mockMarketingData.utmiPart,
    },
  })
})

jest.mock('vtex.order-items/OrderItems', () => ({
  useOrderItems: () => ({
    addItems: mockAddItem,
  }),
}))

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

jest.mock('vtex.render-runtime', () => ({
  useRuntime: () => ({
    rootPath: '',
    navigate: mockNavigate,
  }),
}))

jest.mock('vtex.shipping-option-components/ShippingOptionContext', () => ({
  useShippingOptionState: () => ({
    shippingOption: undefined,
  }),
}))

afterEach(() => {
  mockAddItem.mockClear()
  mockPixelEventPush.mockClear()
  mockNavigate.mockClear()
  cleanup()
})

describe('AddToCartButton component', () => {
  it('should render correct message for unavailable button', () => {
    const { queryByText } = render(
      <AddToCartButton
        isOneClickBuy
        customOneClickBuyLink=""
        available={false}
        disabled={false}
        skuItems={mockSKUItems}
        customToastUrl=""
        showToast={() => {}}
        allSkuVariationsSelected
        productLink={mockProductLink}
        onClickBehavior="add-to-cart"
        multipleAvailableSKUs={false}
      />
    )

    expect(queryByText('Unavailable')).toBeTruthy()
  })

  it('should render correct message for available item', () => {
    const { queryByText } = render(
      <AddToCartButton
        isOneClickBuy
        customOneClickBuyLink=""
        available
        disabled={false}
        skuItems={mockSKUItems}
        customToastUrl=""
        showToast={() => {}}
        allSkuVariationsSelected
        productLink={mockProductLink}
        onClickBehavior="add-to-cart"
        multipleAvailableSKUs={false}
      />
    )

    expect(queryByText('Add to Cart')).toBeTruthy()
  })

  it('should render tooltip with correct message when not all SKU variations are selected', () => {
    const { queryByTestId, queryByText } = render(
      <AddToCartButton
        isOneClickBuy
        customOneClickBuyLink=""
        available
        disabled={false}
        skuItems={mockSKUItems}
        customToastUrl=""
        showToast={() => {}}
        allSkuVariationsSelected={false}
        productLink={mockProductLink}
        onClickBehavior="add-to-cart"
        multipleAvailableSKUs={false}
      />
    )

    const tooltip = queryByTestId('Tooltip')
    const label = queryByText('Please select an option for each variation')

    expect(tooltip).toBeTruthy()
    expect(label).toBeTruthy()
  })

  it('should not render with tooltip if all SKU variations are selected', () => {
    const { queryByTestId } = render(
      <AddToCartButton
        isOneClickBuy
        customOneClickBuyLink=""
        available
        disabled={false}
        skuItems={mockSKUItems}
        customToastUrl=""
        showToast={() => {}}
        allSkuVariationsSelected
        productLink={mockProductLink}
        onClickBehavior="add-to-cart"
        multipleAvailableSKUs={false}
      />
    )

    expect(queryByTestId('Tooltip')).toBeNull()
  })

  it('should pass correct skuItem object to addItem when user clicks on it', () => {
    const { queryByTestId } = render(
      <AddToCartButton
        isOneClickBuy
        customOneClickBuyLink=""
        available={false}
        disabled={false}
        skuItems={mockSKUItems}
        customToastUrl=""
        showToast={() => {}}
        allSkuVariationsSelected
        productLink={mockProductLink}
        onClickBehavior="add-to-cart"
        multipleAvailableSKUs={false}
      />
    )

    const button = queryByTestId('styleguide-button')

    expect(button).toBeTruthy()

    act(() => {
      if (button) {
        fireEvent.click(button)
      }
    })

    expect(mockAddItem).toBeCalledWith(mockSKUItems, {
      marketingData: mockMarketingData,
      ...mockAllowedOutdatedData,
    })
  })

  it('should pass correct marketing data info to addItem function', () => {
    const { queryByTestId } = render(
      <AddToCartButton
        isOneClickBuy
        customOneClickBuyLink=""
        available={false}
        disabled={false}
        skuItems={mockSKUItems}
        customToastUrl=""
        showToast={() => {}}
        allSkuVariationsSelected
        productLink={mockProductLink}
        onClickBehavior="add-to-cart"
        multipleAvailableSKUs={false}
      />
    )

    const button = queryByTestId('styleguide-button')

    expect(button).toBeTruthy()

    act(() => {
      if (button) {
        fireEvent.click(button)
      }
    })

    expect(mockAddItem).toBeCalledWith(mockSKUItems, {
      marketingData: mockMarketingData,
      ...mockAllowedOutdatedData,
    })
  })

  it('should sent correct information about SKU items to pixel event', () => {
    const { queryByTestId } = render(
      <AddToCartButton
        isOneClickBuy
        customOneClickBuyLink=""
        available={false}
        disabled={false}
        skuItems={mockSKUItems}
        customToastUrl=""
        showToast={() => {}}
        allSkuVariationsSelected
        productLink={mockProductLink}
        onClickBehavior="add-to-cart"
        multipleAvailableSKUs={false}
      />
    )

    const button = queryByTestId('styleguide-button')

    expect(button).toBeTruthy()

    act(() => {
      if (button) {
        fireEvent.click(button)
      }
    })

    const expectedPixelEvent = {
      event: 'addToCart',
      items: [
        {
          skuId: '2000564',
          variant: 'Red star',
          price: 3500,
          sellingPrice: 3500,
          priceIsInt: true,
          ean: undefined,
          name: 'Top Star Color Shirt',
          quantity: 1,
          productId: '2000024',
          productRefId: '998765',
          brand: 'Kawasaki',
          category: 'Apparel & Accessories/Clothing/Tops',
          detailUrl: '/star-color-top/p',
          imageUrl:
            'https://storecomponents.vtexassets.com/arquivos/ids/155518/download--40-.png?v=636942495289870000',
          referenceId: 'red star',
          seller: '1',
          sellerName: 'VTEX',
        },
        {
          skuId: '2000535',
          variant: 'Navy Blue',
          price: 303000,
          sellingPrice: 303000,
          priceIsInt: true,
          ean: undefined,
          name: 'St Tropez Top Shorts',
          quantity: 1,
          productId: '2000004',
          productRefId: '01212',
          brand: 'Samsung',
          category: 'Apparel & Accessories/Clothing/Bottoms',
          detailUrl: '/st-tropez-shorts/p',
          imageUrl:
            'https://storecomponents.vtexassets.com/arquivos/ids/155488-500-auto?width=500&height=auto&aspect=true',
          referenceId: undefined,
          seller: '1',
          sellerName: 'VTEX',
        },
      ],
    }

    expect(mockPixelEventPush).toBeCalledWith(expectedPixelEvent)
  })

  it('should not add item to the cart if not all SKU variations are selected', () => {
    const { queryByTestId } = render(
      <AddToCartButton
        isOneClickBuy
        customOneClickBuyLink=""
        available={false}
        disabled={false}
        skuItems={mockSKUItems}
        customToastUrl=""
        showToast={() => {}}
        allSkuVariationsSelected={false}
        productLink={mockProductLink}
        onClickBehavior="add-to-cart"
        multipleAvailableSKUs={false}
      />
    )

    const button = queryByTestId('styleguide-button')

    expect(button).toBeTruthy()

    act(() => {
      if (button) {
        fireEvent.click(button)
      }
    })

    expect(mockAddItem).toHaveBeenCalledTimes(0)
  })

  it("should navigate to product page if onClickBehavior is set to 'go-to-product-page'", () => {
    const { queryByTestId } = render(
      <AddToCartButton
        isOneClickBuy={false}
        available
        customOneClickBuyLink=""
        disabled={false}
        skuItems={mockSKUItems}
        customToastUrl=""
        showToast={() => {}}
        allSkuVariationsSelected
        productLink={mockProductLink}
        onClickBehavior="go-to-product-page"
        multipleAvailableSKUs={false}
      />
    )

    const button = queryByTestId('styleguide-button')

    expect(button).toBeTruthy()

    act(() => {
      if (button) {
        fireEvent.click(button)
      }
    })

    expect(mockAddItem).toHaveBeenCalledTimes(0)
    expect(mockNavigate).toHaveBeenCalledWith({
      page: 'store.product',
      params: {
        slug: 'mock-product',
        id: '2000024',
      },
    })
  })

  it("should navigate to product page if onClickBehavior is set to 'ensure-sku-selection' and product has multiple SKUs", () => {
    const { queryByTestId } = render(
      <AddToCartButton
        isOneClickBuy={false}
        available
        customOneClickBuyLink=""
        disabled={false}
        skuItems={mockSKUItems}
        customToastUrl=""
        showToast={() => {}}
        allSkuVariationsSelected
        productLink={mockProductLink}
        onClickBehavior="ensure-sku-selection"
        multipleAvailableSKUs
      />
    )

    const button = queryByTestId('styleguide-button')

    expect(button).toBeTruthy()

    act(() => {
      if (button) {
        fireEvent.click(button)
      }
    })

    expect(mockAddItem).toHaveBeenCalledTimes(0)
    expect(mockNavigate).toHaveBeenCalledWith({
      page: 'store.product',
      params: {
        slug: 'mock-product',
        id: '2000024',
      },
    })
  })

  it("should send an 'item-added-to-cart-shipping-modal' event if onClickBehavior is set to 'add-to-cart-and-trigger-shipping-modal' and there is no 'shippingOption' selected", () => {
    mockUseShippingOptionState.mockImplementation(() => ({
      shippingOption: undefined,
    }))

    const { queryByTestId } = render(
      <AddToCartButton
        isOneClickBuy={false}
        available
        customOneClickBuyLink=""
        disabled={false}
        skuItems={mockSKUItems}
        customToastUrl=""
        showToast={() => {}}
        allSkuVariationsSelected
        productLink={mockProductLink}
        onClickBehavior="add-to-cart-and-trigger-shipping-modal"
        multipleAvailableSKUs
      />
    )

    const button = queryByTestId('styleguide-button')

    expect(button).toBeTruthy()

    act(() => {
      if (button) {
        fireEvent.click(button)
      }
    })

    expect(mockAddItem).toHaveBeenCalledTimes(0)
    expect(mockNavigate).toHaveBeenCalledTimes(0)

    const expectedPixelEvent = {
      id: 'item-added-to-cart-shipping-modal',
      addToCartInfo: {
        skuItems: [
          {
            index: 0,
            id: '2000564',
            productId: '2000024',
            quantity: 1,
            uniqueId: '',
            detailUrl: '/star-color-top/p',
            name: 'Top Star Color Shirt',
            brand: 'Kawasaki',
            category: '/Apparel & Accessories/Clothing/Tops/',
            productRefId: '998765',
            seller: '1',
            sellerName: 'VTEX',
            variant: 'Red star',
            skuName: 'Red star',
            price: 3500,
            listPrice: 3500,
            sellingPrice: 3500,
            sellingPriceWithAssemblies: 3500,
            measurementUnit: 'un',
            skuSpecifications: [],
            imageUrl:
              'https://storecomponents.vtexassets.com/arquivos/ids/155518/download--40-.png?v=636942495289870000',
            options: [],
            assemblyOptions: { added: [], parentPrice: 35, removed: [] },
            referenceId: [{ Key: 'Reference', Value: 'red star' }],
          },
          {
            id: '2000535',
            productId: '2000004',
            quantity: 1,
            uniqueId: '',
            detailUrl: '/st-tropez-shorts/p',
            name: 'St Tropez Top Shorts',
            brand: 'Samsung',
            category: '/Apparel & Accessories/Clothing/Bottoms/',
            productRefId: '01212',
            seller: '1',
            sellerName: 'VTEX',
            variant: 'Navy Blue',
            skuName: 'Navy Blue',
            price: 303000,
            listPrice: 303000,
            sellingPrice: 303000,
            sellingPriceWithAssemblies: 303000,
            measurementUnit: 'un',
            skuSpecifications: [],
            imageUrl:
              'https://storecomponents.vtexassets.com/arquivos/ids/155488-500-auto?width=500&height=auto&aspect=true',
            options: [],
            assemblyOptions: { added: [], removed: [], parentPrice: 3030 },
            referenceId: null,
          },
        ],
        options: {
          marketingData: {
            utmSource: 'testing utmSource',
            utmMedium: 'testing utmMedium',
            utmCampaign: 'testing utmCampaign',
            utmiCampaign: 'testing utmiCampaign',
            utmiPage: 'testing utmiPage',
            utmiPart: 'testing utmiPart',
          },
          allowedOutdatedData: ['paymentData'],
        },
      },
    }

    expect(mockPixelEventPush).toBeCalledWith(expectedPixelEvent)
  })

  it("should add to cart normally if onClickBehavior is set to 'add-to-cart-and-trigger-shipping-modal' and there is a 'shippingOption' selected", () => {
    mockUseShippingOptionState.mockImplementation(() => ({
      shippingOption: 'delivery',
    }))

    const { queryByTestId } = render(
      <AddToCartButton
        isOneClickBuy
        customOneClickBuyLink=""
        available={false}
        disabled={false}
        skuItems={mockSKUItems}
        customToastUrl=""
        showToast={() => {}}
        allSkuVariationsSelected
        productLink={mockProductLink}
        onClickBehavior="add-to-cart"
        multipleAvailableSKUs={false}
      />
    )

    const button = queryByTestId('styleguide-button')

    expect(button).toBeTruthy()

    act(() => {
      if (button) {
        fireEvent.click(button)
      }
    })

    expect(mockAddItem).toBeCalledWith(mockSKUItems, {
      marketingData: mockMarketingData,
      ...mockAllowedOutdatedData,
    })
  })
})

```


[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 add-to-cart-button/react/__tests__/Wrapper.test.tsx from the add-to-cart-button VTEX app.

[Assistant]
Here's the implementation:

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

import Wrapper from '../Wrapper'
import AddToCartButton from '../AddToCartButton'
import { renderWithProductContext } from '../modules/testUtils'
import {
  StarColorTop,
  ProductOutOfStock,
  ProductWithInvalidAssemblies,
} from '../__fixtures__/productContext'

jest.mock('../AddToCartButton.tsx', () => ({
  __esModule: true,
  namedExport: jest.fn(),
  default: jest.fn(),
}))

const MockAddToCartButton = jest.fn(() => {
  return <button>Add to Cart</button>
})

beforeAll(() => {
  ;(AddToCartButton as typeof AddToCartButton & {
    mockImplementation: Function
  }).mockImplementation(MockAddToCartButton)
})

afterEach(() => {
  cleanup()
  MockAddToCartButton.mockClear()
})

describe('Wrapper component', () => {
  it('should pass all props received via blocks.json to AddToCart button correctly', () => {
    renderWithProductContext(
      <Wrapper
        isOneClickBuy={false}
        customToastUrl="customToastUrl"
        customOneClickBuyLink="customOneClickBuyLink"
      />,
      {}
    )

    expect(MockAddToCartButton).toBeCalledWith(
      expect.objectContaining({
        isOneClickBuy: false,
        customToastUrl: 'customToastUrl',
        customOneClickBuyLink: 'customOneClickBuyLink',
      }),
      {}
    )
  })

  it('should not crash if productContext is empty', () => {
    const { container } = renderWithProductContext(
      <Wrapper
        isOneClickBuy={false}
        customToastUrl="customToastUrl"
        customOneClickBuyLink="customOneClickBuyLink"
      />,
      {}
    )

    expect(container.children).toBeDefined()
  })

  it('should evaluate isAvailable to false if product is out of stock', () => {
    renderWithProductContext(<Wrapper />, ProductOutOfStock)

    expect(MockAddToCartButton).toBeCalledWith(
      expect.objectContaining({
        available: false,
      }),
      {}
    )
  })

  it('should evaluate isAvailable to false when productContext is empty', () => {
    renderWithProductContext(<Wrapper />, {})

    expect(MockAddToCartButton).toBeCalledWith(
      expect.objectContaining({
        available: false,
      }),
      {}
    )
  })

  it("should evaluate isAvailable to true when product's available quantity is greater than 0", () => {
    renderWithProductContext(<Wrapper />, StarColorTop)

    expect(MockAddToCartButton).toBeCalledWith(
      expect.objectContaining({
        available: true,
      }),
      {}
    )
  })

  it('should evaluate isDisabled to true when product has invalid assembly options', () => {
    renderWithProductContext(<Wrapper />, ProductWithInvalidAssemblies)

    expect(MockAddToCartButton).toBeCalledWith(
      expect.objectContaining({
        disabled: true,
      }),
      {}
    )
  })

  it('should evaluate isDisabled to false when product does not have invalid assembly options', () => {
    renderWithProductContext(<Wrapper />, StarColorTop)

    expect(MockAddToCartButton).toBeCalledWith(
      expect.objectContaining({
        disabled: false,
      }),
      {}
    )
  })

  it('should pass correct skuItems to AddToCartButton', () => {
    renderWithProductContext(<Wrapper />, StarColorTop)

    const expectedSkuItems = [
      {
        index: 0,
        id: '2000564',
        ean: '123456',
        productId: '2000024',
        quantity: 1,
        uniqueId: '',
        detailUrl: '/star-color-top/p',
        name: 'Top Star Color Shirt',
        brand: 'Kawasaki',
        category: '/Apparel & Accessories/Clothing/Tops/',
        productRefId: '998765',
        seller: '1',
        sellerName: 'VTEX',
        variant: 'Red star',
        skuName: 'Red star',
        price: 3500,
        listPrice: 3500,
        sellingPrice: 3500,
        sellingPriceWithAssemblies: 3500,
        measurementUnit: 'un',
        skuSpecifications: [],
        imageUrl:
          'https://storecomponents.vtexassets.com/arquivos/ids/155518/download--40-.png?v=636942495289870000',
        options: [],
        assemblyOptions: {
          added: [],
          parentPrice: 35,
          removed: [],
        },
        referenceId: [
          { Key: 'RefId', Value: '987134', __typename: 'Reference' },
        ],
      },
    ]

    expect(MockAddToCartButton).toBeCalledWith(
      expect.objectContaining({
        skuItems: expectedSkuItems,
      }),
      {}
    )
  })

  it('should pass correct skuItems received from props to AddToCartButton', () => {
    const mockSKUItems = [
      {
        index: 0,
        id: '2000564',
        productId: '2000024',
        quantity: 1,
        uniqueId: '',
        detailUrl: '/star-color-top/p',
        name: 'Top Star Color Shirt',
        brand: 'Kawasaki',
        category: '/Apparel & Accessories/Clothing/Tops/',
        productRefId: '998765',
        seller: '1',
        variant: 'Red star',
        skuName: 'Red star',
        price: 3500,
        listPrice: 3500,
        sellingPrice: 3500,
        sellingPriceWithAssemblies: 3500,
        measurementUnit: 'un',
        skuSpecifications: [],
        imageUrl:
          'https://storecomponents.vtexassets.com/arquivos/ids/155518/download--40-.png?v=636942495289870000',
        options: [],
        assemblyOptions: {
          added: [],
          parentPrice: 35,
          removed: [],
        },
        referenceId: [{ Key: 'Reference', Value: 'red star' }],
      },
      {
        id: '2000535',
        productId: '2000004',
        quantity: 1,
        uniqueId: '',
        detailUrl: '/st-tropez-shorts/p',
        name: 'St Tropez Top Shorts',
        brand: 'Samsung',
        category: '/Apparel & Accessories/Clothing/Bottoms/',
        productRefId: '01212',
        seller: '1',
        variant: 'Navy Blue',
        skuName: 'Navy Blue',
        price: 303000,
        listPrice: 303000,
        sellingPrice: 303000,
        sellingPriceWithAssemblies: 303000,
        measurementUnit: 'un',
        skuSpecifications: [],
        imageUrl:
          'https://storecomponents.vtexassets.com/arquivos/ids/155488-500-auto?width=500&height=auto&aspect=true',
        options: [],
        assemblyOptions: { added: [], removed: [], parentPrice: 3030 },
        referenceId: { Value: '' },
      },
    ]

    renderWithProductContext(<Wrapper skuItems={mockSKUItems} />, {})

    expect(MockAddToCartButton).toBeCalledWith(
      expect.objectContaining({
        skuItems: mockSKUItems,
      }),
      {}
    )
  })
})

```


[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 add-to-cart-button/react/hooks/useMarketingSessionParams.ts from the add-to-cart-button VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { useEffect, useState } from 'react'

type PublicSessionField =
  | 'utm_source'
  | 'utm_medium'
  | 'utm_campaign'
  | 'utmi_cp'
  | 'utmi_p'
  | 'utmi_pc'

interface SessionPromiseFieldValue {
  value: string
}

interface UtmParams {
  utmSource?: string
  utmMedium?: string
  utmCampaign?: string
}

interface UtmiParams {
  utmiCampaign?: string
  utmiPage?: string
  utmiPart?: string
}

interface SessionPromiseResponse {
  response?: {
    id: string
    namespaces?: {
      account: {
        id: SessionPromiseFieldValue & { keepAlive: boolean }
        accountName: SessionPromiseFieldValue
      }
      store: {
        channel: SessionPromiseFieldValue
        countryCode: SessionPromiseFieldValue
        cultureInfo: SessionPromiseFieldValue
        currencyCode: SessionPromiseFieldValue
        currencySymbol: SessionPromiseFieldValue
        admin_cultureInfo: SessionPromiseFieldValue
      }
      public: Record<PublicSessionField, SessionPromiseFieldValue>
      creditControl: Record<string, SessionPromiseFieldValue>
      authentication: Record<string, any>
      profile: {
        isAuthenticated: SessionPromiseFieldValue
      }
    }
  }
}

const getUtmParams = (
  publicFields: Record<PublicSessionField, SessionPromiseFieldValue>
) => ({
  utmSource: publicFields.utm_source?.value ?? '',
  utmMedium: publicFields.utm_medium?.value ?? '',
  utmCampaign: publicFields.utm_campaign?.value ?? '',
})

const getUtmiParams = (
  publicFields: Record<PublicSessionField, SessionPromiseFieldValue>
) => ({
  utmiPage: publicFields.utmi_p?.value ?? '',
  utmiPart: publicFields.utmi_pc?.value ?? '',
  utmiCampaign: publicFields.utmi_cp?.value ?? '',
})

const getSessionPromiseFromWindow = () => {
  const runtimeSessionPromise = (window as Window & {
    ['__RENDER_8_SESSION__']?: {
      sessionPromise?: Promise<SessionPromiseResponse>
    }
  }).__RENDER_8_SESSION__?.sessionPromise

  return runtimeSessionPromise
}

const useMarketingSessionParams = () => {
  const [utmParams, setUtmParams] = useState<UtmParams>({})
  const [utmiParams, setUtmiParams] = useState<UtmiParams>({})

  useEffect(() => {
    getSessionPromiseFromWindow()
      ?.then(data => {
        const publicFields = data?.response?.namespaces?.public ?? {}
        if (Object.keys(publicFields).length === 0) {
          return
        }

        setUtmParams(
          getUtmParams(
            publicFields as Record<PublicSessionField, SessionPromiseFieldValue>
          )
        )
        setUtmiParams(
          getUtmiParams(
            publicFields as Record<PublicSessionField, SessionPromiseFieldValue>
          )
        )
      })
      .catch(() => {
        // Do nothing
      })
  }, [])

  return { utmParams, utmiParams }
}

export default useMarketingSessionParams

```


[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 add-to-cart-button/react/modules/testUtils.tsx from the add-to-cart-button VTEX app.

[Assistant]
Here's the implementation:

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

import { ProductContextProvider } from '../__mocks__/vtex.product-context'

export function renderWithProductContext(Component: ReactElement, value: any) {
  return render(
    <ProductContextProvider value={value}>{Component}</ProductContextProvider>
  )
}

export function findCSSHandles(container: HTMLElement, handles: string[]) {
  const foundNodes = handles
    .map(handle => {
      const foundNodesInner = container.getElementsByClassName(handle)
      return foundNodesInner.length > 0 ? handle : ''
    })
    .filter(result => result !== '')

  return foundNodes
}

```


[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 add-to-cart-button/react/modules/compareObjects.ts from the add-to-cart-button VTEX app.

[Assistant]
Here's the implementation:

```typescript
/* eslint-disable eqeqeq */
export function compareObjects(
  obj1: Record<string, any>,
  obj2: Record<string, any>
) {
  // Loop through properties in object 1
  for (const p in obj1) {
    // Check property exists on both objects
    if (
      Object.prototype.hasOwnProperty.call(obj1, 'p') !==
      Object.prototype.hasOwnProperty.call(obj2, 'p')
    )
      return false

    switch (typeof obj1[p]) {
      // Deep compare objects
      case 'object':
        if (!compareObjects(obj1[p], obj2[p])) return false
        break
      // Compare function code
      case 'function':
        if (
          typeof obj2[p] === 'undefined' ||
          (p != 'compare' && obj1[p].toString() != obj2[p].toString())
        )
          return false
        break
      // Compare values
      default:
        if (obj1[p] != obj2[p]) return false
    }
  }

  // Check object 2 for any extra properties
  for (const p in obj2) {
    if (typeof obj1[p] === 'undefined') return false
  }
  return true
}

```


[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 add-to-cart-button/react/modules/catalogItemToCart.ts from the add-to-cart-button VTEX app.

[Assistant]
Here's the implementation:

```typescript
import type { ProductTypes } from 'vtex.product-context'

import {
  transformAssemblyOptions,
  sumAssembliesPrice,
  ParsedAssemblyOptionsMeta,
  Option,
} from './assemblyOptions'

interface SKUSpecification {
  fieldName: string
  fieldValues: string[]
}

export interface CartItem {
  detailUrl: string
  id: string
  ean: string
  imageUrl: string
  index?: number
  listPrice: number
  measurementUnit: string
  name: string
  price: number
  productId: string
  quantity: number
  seller: string
  sellerName: string
  sellingPrice: number
  productRefId: string
  brand: string
  variant: string
  category: string
  skuName: string
  skuSpecifications: SKUSpecification[]
  uniqueId: string
  sellingPriceWithAssemblies: number
  options: Option[]
  assemblyOptions: ParsedAssemblyOptionsMeta
  referenceId: Array<{
    Key: string
    Value: string
  }> | null
}

interface MapCatalogItemToCartArgs {
  product?: ProductTypes.ProductContextState['product']
  selectedItem: ProductTypes.ProductContextState['selectedItem']
  selectedQuantity: ProductTypes.ProductContextState['selectedQuantity']
  selectedSeller?: ProductTypes.Seller
  assemblyOptions?: ProductTypes.ProductContextState['assemblyOptions']
}

export function mapCatalogItemToCart({
  product,
  selectedItem,
  selectedQuantity,
  selectedSeller,
  assemblyOptions,
}: MapCatalogItemToCartArgs): CartItem[] {
  if (
    !product ||
    !selectedItem ||
    !selectedSeller ||
    !selectedSeller.commertialOffer
  ) {
    return []
  }

  return [
    {
      index: 0,
      id: selectedItem.itemId,
      ean: selectedItem.ean,
      productId: product.productId ?? '',
      quantity: selectedQuantity,
      uniqueId: '',
      detailUrl: `/${product.linkText}/p`,
      name: product.productName ?? '',
      brand: product.brand ?? '',
      category:
        product.categories && product.categories.length > 0
          ? product.categories[0]
          : '',
      productRefId: product.productReference ?? '',
      seller: selectedSeller.sellerId,
      sellerName: selectedSeller.sellerName,
      variant: selectedItem.name,
      skuName: selectedItem.name,
      price: selectedSeller.commertialOffer.PriceWithoutDiscount * 100,
      listPrice: selectedSeller.commertialOffer.ListPrice * 100,
      sellingPrice: selectedSeller.commertialOffer.Price * 100,
      sellingPriceWithAssemblies:
        ((selectedSeller.commertialOffer.Price as number) +
          sumAssembliesPrice(assemblyOptions?.items ?? {})) *
        100,
      measurementUnit: selectedItem.measurementUnit,
      skuSpecifications: [],
      imageUrl: selectedItem.images[0]?.imageUrl,
      ...transformAssemblyOptions({
        assemblyOptionsItems: assemblyOptions?.items,
        inputValues: assemblyOptions?.inputValues,
        parentPrice: selectedSeller.commertialOffer.Price,
        parentQuantity: selectedQuantity,
      }),
      referenceId: selectedItem.referenceId,
    },
  ]
}

```


[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 add-to-cart-button/react/modules/assemblyOptions.ts from the add-to-cart-button VTEX app.

[Assistant]
Here's the implementation:

```typescript
import type { ProductTypes } from 'vtex.product-context'

type GroupId = string
type GroupTypes = 'SINGLE' | 'TOGGLE' | 'MULTIPLE'

type InputValue = Record<string, string | boolean>

export interface AssemblyOptions {
  items: Record<GroupId, ProductTypes.AssemblyOptionItem[]>
  inputValues: Record<GroupId, InputValue>
  areGroupsValid: Record<string, boolean>
}

export type Option = ItemOption

export interface ItemOption {
  assemblyId: string
  id?: string
  quantity?: number
  seller?: string
  options?: Option[]
  inputValues?: InputValue
}

interface AddedItem {
  id: string
  name: string
  quantity: number
  sellingPrice: number
  sellingPriceWithAssemblies: number
  assemblyOptions?: ParsedAssemblyOptionsMeta
}

interface CartAddedOption {
  normalizedQuantity: number
  extraQuantity: number
  choiceType: GroupTypes
  item: AddedItem
}

interface CartRemovedOption {
  name: string
  initialQuantity: number
  removedQuantity: number
}

export interface ParsedAssemblyOptionsMeta {
  added: CartAddedOption[]
  removed: CartRemovedOption[]
  parentPrice: number
}

interface ParsedAssemblyOptions {
  options: Option[]
  assemblyOptions: ParsedAssemblyOptionsMeta
}

interface TransformAssemblyOptionsArgs {
  assemblyOptionsItems?: Record<GroupId, ProductTypes.AssemblyOptionItem[]>
  inputValues?: Record<GroupId, InputValue>
  parentPrice: number
  parentQuantity: number
}

export function sumAssembliesPrice(
  assemblyOptions: Record<GroupId, ProductTypes.AssemblyOptionItem[]>
): number {
  const cleanAssemblies = assemblyOptions || {}
  const assembliesGroupItems = Object.values(cleanAssemblies)
  return assembliesGroupItems.reduce((sum, groupItems) => {
    const groupPrice = groupItems.reduce<number>((groupSum, item) => {
      const childrenPrice: number = item.children
        ? sumAssembliesPrice(item.children)
        : 0
      const itemCost = item.price * item.quantity
      return groupSum + itemCost + childrenPrice * item.quantity
    }, 0)
    return groupPrice + sum
  }, 0)
}

export function transformAssemblyOptions({
  assemblyOptionsItems = {},
  inputValues = {},
  parentPrice,
  parentQuantity,
}: TransformAssemblyOptionsArgs): ParsedAssemblyOptions {
  // contains options sent as arguments to graphql mutation
  const options: Option[] = []

  // array with added assemblies data to show in minicart optimistic preview
  const added: CartAddedOption[] = []

  // array with removed assemblies data to show in minicart optimistic preview
  const removed: CartRemovedOption[] = []

  let assemblyInputValuesKeys: GroupId[] = Object.keys(inputValues)

  const assemblyItemsKeys: GroupId[] = Object.keys(assemblyOptionsItems)

  for (const groupId of assemblyItemsKeys) {
    const items = assemblyOptionsItems[groupId]
    for (const item of items) {
      let childrenAddedData = null

      if (item.children) {
        const childInputValues: Record<GroupId, InputValue> = {}
        for (const key in item.children) {
          childInputValues[key] = inputValues[key]
        }
        const handledInputValues = Object.keys(childInputValues)
        assemblyInputValuesKeys = assemblyInputValuesKeys.filter(
          inputValueKey => handledInputValues.includes(inputValueKey)
        )

        childrenAddedData = transformAssemblyOptions({
          assemblyOptionsItems: item.children,
          inputValues: childInputValues,
          parentPrice: item.price,
          parentQuantity: item.quantity * parentQuantity,
        })
      }

      const {
        options: childrenOptions,
        assemblyOptions: childrenAssemblyOptions,
      } = childrenAddedData ?? {
        options: undefined,
        assemblyOptions: undefined,
      }

      const { quantity, initialQuantity } = item

      if (quantity >= initialQuantity && quantity > 0) {
        added.push({
          normalizedQuantity: quantity,
          extraQuantity: quantity - initialQuantity,
          choiceType: item.choiceType as GroupTypes,
          item: {
            name: item.name,
            sellingPrice: item.price,
            quantity,
            sellingPriceWithAssemblies:
              (item.price as number) + sumAssembliesPrice(item.children ?? {}),
            id: item.id,
            ...(childrenAssemblyOptions
              ? { assemblyOptions: childrenAssemblyOptions }
              : {}),
          },
        })
      }

      if (quantity < initialQuantity && item.choiceType === 'TOGGLE') {
        removed.push({
          name: item.name,
          initialQuantity,
          removedQuantity: initialQuantity - quantity,
        })
      }

      // push all items to options array regardless of quantity
      // this solves KI 743529
      options.push({
        assemblyId: groupId,
        id: item.id,
        quantity: quantity * parentQuantity,
        seller: item.seller,
        ...(childrenOptions && childrenOptions.length > 0
          ? { options: childrenOptions }
          : {}),
      })
    }
  }

  for (const groupId of assemblyInputValuesKeys) {
    const inputValuesObject = inputValues[groupId] || {}
    if (Object.keys(inputValuesObject).length > 0) {
      options.push({
        assemblyId: groupId,
        inputValues: inputValues[groupId],
      })
    }
  }

  return {
    options,
    assemblyOptions: {
      added,
      removed,
      parentPrice,
    },
  }
}

```


[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 smarthint/docs/README.md from the smarthint VTEX app.

[Assistant]
Here's the implementation:

```markdown
# smarthint

VTEX SmartHint first-party app

## How to install

Open the VTEX App Store and install this app on your store.

Now, open the app settings on your admin and fill in the your SmartHint key.
```


[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 voxus/docs/README.md from the voxus VTEX app.

[Assistant]
Here's the implementation:

```markdown
# Voxus

Through data processing and segmentation algorithms, Voxus displays banners for people who are likely to convert to portals and applications.
For more information please visit, [voxus](https://www.voxus.com.br/) website.

## App Installation
Open the VTEX APP Store and install the voxus app on your store.

or

Run the following command:

```sh
vtex install vtex.voxus@0.x
```

Now, open the app settings on your admin and fill in the Voxus options.
```


[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 voxus/react/index.tsx from the voxus VTEX app.

[Assistant]
Here's the implementation:

```tsx
import { canUseDOM } from 'vtex.render-runtime'
import { PixelMessage } from './typings/events'

export function handleEvents(e: PixelMessage) {
  switch (e.data.eventName) {
    case 'vtex:pageView': {

    }
    default: {
      return
    }
  }
}

if (canUseDOM) {
  window.addEventListener('message', handleEvents)
}

```


[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 voxus/react/package.json from the voxus VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "scripts": {
    "test": "vtex-test-tools test"
  },
  "dependencies": {
    "ramda": "^0.26.1"
  },
  "devDependencies": {
    "@types/graphql": "^14.2.0",
    "@types/jest": "^24.0.11",
    "@types/node": "^11.13.0",
    "@types/ramda": "^0.26.5",
    "@vtex/test-tools": "^1.1.0",
    "eslint": "^5.16.0",
    "eslint-config-vtex-react": "^4.1.0",
    "prettier": "^1.18.2",
    "tslint-eslint-rules": "^5.4.0",
    "typescript": "3.5.2"
  },
  "version": "0.0.2"
}

```


[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 voxus/store/interfaces.json from the voxus VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "pixel.voxus": {
    "component": "index"
  }
}

```


[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 voxus/react/typings/events.d.ts from the voxus VTEX app.

[Assistant]
Here's the implementation:

```typescript
export interface PixelMessage extends MessageEvent {
  data:
    | ProductViewData
    | ProductClickData
    | OrderPlacedData
    | PageViewData
    | ProductImpressionData
    | AddToCartData
    | RemoveToCartData
}

export interface EventData {
  event: string
  eventName: string
  currency: string
}

export interface PageViewData extends EventData {
  event: 'pageView'
  eventName: 'vtex:pageView'
  pageTitle: string
  pageUrl: string
  referrer: string
}

export interface AddToCartData extends EventData {
  event: 'addToCart'
  eventName: 'vtex:addToCart'
  items: CartItem[]
}

export interface RemoveToCartData extends EventData {
  event: 'removeFromCart'
  eventName: 'vtex:removeFromCart'
  items: CartItem[]
}

export interface OrderPlacedData extends Order, EventData {
  event: 'orderPlaced'
  eventName: 'vtex:orderPlaced'
}

export interface ProductViewData extends EventData {
  event: 'productView'
  eventName: 'vtex:productView'
  product: Product
}

export interface ProductClickData extends EventData {
  event: 'productClick'
  eventName: 'vtex:productClick'
  product: Product
}

export interface ProductImpressionData extends EventData {
  event: 'productImpression'
  eventName: 'vtex:productImpression'
  impressions: Impression[]
  product?: Product // deprecated, use impressions list!
  position?: number // deprecated, use impressions list!
  list: string
}

interface CartItem {
  skuId: string
  variant: string
  price: number
  name: string
  quantity: number
  productRefId: string
  brand: string
  category: string
}

export interface Order {
  currency: string
  accountName: string
  orderGroup: string
  salesChannel: string
  coupon: string
  visitorType: string
  visitorContactInfo: string[]
  visitorAddressState: string
  visitorAddressCountry: string
  visitorAddressPostalCode: string
  transactionId: string
  transactionDate: string
  transactionAffiliation: string
  transactionTotal: number
  transactionShipping: number
  transactionSubtotal: number
  transactionDiscounts: number
  transactionTax: number
  transactionCurrency: string
  transactionPaymentType: PaymentType[]
  transactionShippingMethod: ShippingMethod[]
  transactionProducts: ProductOrder[]
  transactionPayment: {
    id: string
  }
}

export interface Impression {
  product: Product
  position: number
}

interface PaymentType {
  group: string
  paymentSystemName: string
  installments: number
  value: number
}

interface ShippingMethod {
  itemId: string
  selectedSla: string
}

interface ProductOrder {
  id: string
  name: string
  sku: string
  skuRefId: string
  skuName: string
  productRefId: string
  ean: string
  slug: string
  brand: string
  brandId: string
  seller: string
  sellerId: string
  category: string
  categoryId: string
  categoryTree: string[]
  categoryIdTree: string[]
  priceTags: PriceTag[]
  originalPrice: number
  price: number
  sellingPrice: number
  tax: number
  quantity: number
  components: any[]
  measurementUnit: string
  unitMultiplier: number
}

interface PriceTag {
  identifier: string
  isPercentual: boolean
  value: number
}

interface Product {
  brand: string
  categoryId?: string // inconsistency
  categories: string[]
  productId: string
  productName: string
  selectedSku?: string // inconsistency
  items: Item[]
  sku: Item
  [key: string]: any
}

interface Item {
  itemId: string
  name: string
  seller?: Seller
  [key: string]: any
}

interface Seller {
  commertialOffer: CommertialOffer
  [key: string]: any
}

interface CommertialOffer {
  Price: number
  [key: string]: any
}

```


[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 voxus/react/typings/vtex.render-runtime.d.ts from the voxus VTEX app.

[Assistant]
Here's the implementation:

```typescript
declare module 'vtex.render-runtime' {
  export const canUseDOM: boolean
}

```


[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 voxus/react/typings/global.d.ts from the voxus VTEX app.

[Assistant]
Here's the implementation:

```typescript
interface Window extends Window {
  dataLayer: any[]
}

```


[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 order-coupon/docs/README.md from the order-coupon VTEX app.

[Assistant]
Here's the implementation:

```markdown
# Order Coupon

> Centralizes all coupon related requests to the Checkout API.

Any kind of coupon query or manipulation should be made through this component. This ensures that each interaction with the Checkout API happens in succession, avoiding concurrency issues.

```


[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 order-coupon/react/OrderCoupon.tsx from the order-coupon VTEX app.

[Assistant]
Here's the implementation:

```tsx
import React, { createContext, ReactNode, useContext, useCallback } from 'react'
import { compose, graphql } from 'react-apollo'
import {
  QueueStatus,
  useOrderQueue,
  useQueueStatus,
} from 'vtex.order-manager/OrderQueue'
import { useOrderForm } from 'vtex.order-manager/OrderForm'

import InsertCoupon from 'vtex.checkout-resources/MutationInsertCoupon'

interface InsertCouponResult {
  success: boolean
  errorKey: string
}

interface Context {
  insertCoupon: (coupon: string) => Promise<InsertCouponResult>
}

interface OrderCouponProviderProps {
  children: ReactNode
  InsertCoupon: any
}

const couponKey = 'coupon'
const TASK_CANCELLED = 'TASK_CANCELLED'

const OrderCouponContext = createContext<Context | undefined>(undefined)

export const OrderCouponProvider = compose(
  graphql(InsertCoupon, { name: 'InsertCoupon' })
)(({ children, InsertCoupon }: OrderCouponProviderProps) => {
  const { enqueue, listen } = useOrderQueue()
  const { setOrderForm } = useOrderForm()

  const queueStatusRef = useQueueStatus(listen)

  const insertCoupon = useCallback(
    async (coupon: string) => {
      const task = async () => {
        const {
          data: { insertCoupon: newOrderForm },
        } = await InsertCoupon({
          variables: {
            text: coupon,
          },
        })

        return newOrderForm
      }

      try {
        const newOrderForm = await enqueue(task, couponKey)
        let errorKey = ''
        if (queueStatusRef.current === QueueStatus.FULFILLED) {
          setOrderForm(newOrderForm)
        }

        if (newOrderForm.messages.couponMessages.length) {
          const [couponMessage] = newOrderForm.messages.couponMessages
          errorKey = couponMessage.code
        }

        return {
          success: !!(
            newOrderForm.marketingData && newOrderForm.marketingData.coupon
          ),
          errorKey,
        }
      } catch (error) {
        if (!error || error.code !== TASK_CANCELLED) {
          throw error
        }
        return { success: false, errorKey: '' }
      }
    },
    [InsertCoupon, enqueue, queueStatusRef, setOrderForm]
  )

  return (
    <OrderCouponContext.Provider
      value={{
        insertCoupon,
      }}
    >
      {children}
    </OrderCouponContext.Provider>
  )
})

export const useOrderCoupon = () => {
  const context = useContext(OrderCouponContext)
  if (context === undefined) {
    throw new Error('useOrderCoupon must be used within a OrderCouponProvider')
  }

  return context
}

export default { OrderCouponProvider, useOrderCoupon }

```


[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 order-coupon/react/package.json from the order-coupon VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "scripts": {
    "test": "vtex-test-tools test",
    "lint": "tsc --noEmit && eslint --ext ts,tsx ."
  },
  "dependencies": {
    "@vtex/css-handles": "^1.0.0",
    "classnames": "^2.2.6",
    "ramda": "^0.26.1",
    "react": "^16.8.3",
    "react-dom": "^16.8.3",
    "react-intl": "^2.7.2"
  },
  "devDependencies": {
    "@apollo/react-testing": "^3.1.3",
    "@types/classnames": "^2.2.7",
    "@types/graphql": "^14.2.0",
    "@types/jest": "^24.0.11",
    "@types/node": "^11.13.0",
    "@types/prop-types": "^15.7.0",
    "@types/ramda": "^0.26.5",
    "@types/react": "^16.8.10",
    "@types/react-intl": "^2.3.17",
    "@vtex/test-tools": "^1.1.0",
    "apollo-client": "^2.5.1",
    "eslint": "^5.16.0",
    "eslint-config-vtex-react": "^4.1.0",
    "prettier": "^1.18.2",
    "tslint-eslint-rules": "^5.4.0",
    "typescript": "3.7.3",
    "vtex.render-runtime": "http://vtex.vteximg.com.br/_v/public/typings/v1/vtex.render-runtime@8.91.2/public/@types/vtex.render-runtime",
    "vtex.checkout-resources": "http://vtex.vteximg.com.br/_v/public/typings/v1/vtex.checkout-resources@0.18.0/public/@types/vtex.checkout-resources",
    "vtex.order-manager": "http://vtex.vteximg.com.br/_v/public/typings/v1/vtex.order-manager@0.7.1/public/@types/vtex.order-manager"
  },
  "version": "0.7.2"
}

```


[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 order-coupon/react/typings/storefront.d.ts from the order-coupon VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { FunctionComponent } from 'react'

declare global {
  interface StorefrontFunctionComponent<P = {}> extends FunctionComponent<P> {
    getSchema?(props: P): object
    schema?: object
  }

  interface StorefrontComponent<P = {}, S = {}> extends Component<P, S> {
    getSchema?(props: P): object
    schema: object
  }
}

```


[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 order-coupon/react/typings/globals.d.ts from the order-coupon VTEX app.

[Assistant]
Here's the implementation:

```typescript
interface OrderForm {
  items: Item[]
  marketingData: MarketingData | null
  totalizers: Totalizer[]
  value: number
  messages: OrderFormMessages
}

interface Item {
  additionalInfo: ItemAdditionalInfo
  detailUrl: string
  id: string
  imageUrl: string
  listPrice: number
  measurementUnit: string
  name: string
  price: number
  productId: string
  quantity: number
  sellingPrice: number
  skuName: string
  skuSpecifications: SKUSpecification[]
}

interface ItemAdditionalInfo {
  brandName: string
}

interface MarketingData {
  coupon: string
}

interface SKUSpecification {
  fieldName: string
  fieldValues: string[]
}

interface Totalizer {
  id: string
  name: string
  value: number
}

interface OrderFormMessages {
  couponMessages: Message[]
}

interface Message {
  code: string
  status: string
  text: string
}

```


[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 order-coupon/react/typings/vtex.render-runtime.d.ts from the order-coupon VTEX app.

[Assistant]
Here's the implementation:

```typescript
/* Typings for `render-runtime` */
declare module 'vtex.render-runtime' {
  import { Component, ComponentType, ReactElement, ReactType } from 'react'

  export interface NavigationOptions {
    page: string
    params?: any
  }

  export interface RenderContextProps {
    runtime: {
      navigate: (options: NavigationOptions) => void
    }
  }

  interface ExtensionPointProps {
    id: string
    [key: string]: any
  }

  export const ExtensionPoint: ComponentType<ExtensionPointProps>

  interface ChildBlockProps {
    id: string
  }

  export const ChildBlock: ComponentType<ChildBlockProps>
  export const useChildBlock = function({ id: string }): object {}

  export const Helmet: ReactElement
  export const Link: ReactType
  export const NoSSR: ReactElement
  export const RenderContextConsumer: ReactElement
  export const canUseDOM: boolean
  export const withRuntimeContext: <TOriginalProps extends {}>(
    Component: ComponentType<TOriginalProps & RenderContextProps>
  ) => ComponentType<TOriginalProps>
}

```


[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 order-coupon/react/typings/vtex.checkout-resources.ts from the order-coupon VTEX app.

[Assistant]
Here's the implementation:

```typescript
declare module 'vtex.checkout-resources/*' {
  import { DocumentNode } from 'graphql'

  const value: DocumentNode
  export default value
}

```


[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 order-coupon/react/typings/css.d.ts from the order-coupon VTEX app.

[Assistant]
Here's the implementation:

```typescript
declare module '*.css' {
  const css: any
  export default css
}

```


[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 order-coupon/react/typings/vtex.order-manager.ts from the order-coupon VTEX app.

[Assistant]
Here's the implementation:

```typescript
declare module 'vtex.order-manager/OrderForm'
declare module 'vtex.order-manager/OrderQueue'

```


[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 order-coupon/react/typings/graphql.d.ts from the order-coupon VTEX app.

[Assistant]
Here's the implementation:

```typescript
declare module '*.graphql' {
  import { DocumentNode } from 'graphql'

  const value: DocumentNode
  export default value
}

```


[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 order-coupon/react/typings/vtex.styleguide.d.ts from the order-coupon VTEX app.

[Assistant]
Here's the implementation:

```typescript
declare module 'vtex.styleguide' {
  import { ComponentType } from 'react'

  export const Input: ComponentType<InputProps>

  interface InputProps {
    [key: string]: any
  }
}

```


[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 order-coupon/react/__tests__/OrderCoupon.test.tsx from the order-coupon VTEX app.

[Assistant]
Here's the implementation:

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

import InsertCoupon from 'vtex.checkout-resources/MutationInsertCoupon'
import { OrderFormProvider, useOrderForm } from 'vtex.order-manager/OrderForm'
import { OrderQueueProvider } from 'vtex.order-manager/OrderQueue'
import { OrderCouponProvider, useOrderCoupon } from '../OrderCoupon'
import { mockOrderForm } from '../__mocks__/mockOrderForm'

const mockedMarketingData = {
  coupon: 'newCoupon',
}

const mockInsertCouponMutation = (args: string, result: MarketingData) => ({
  request: {
    query: InsertCoupon,
    variables: {
      text: args,
    },
  },
  result: {
    data: {
      insertCoupon: {
        ...mockOrderForm,
        marketingData: result,
      },
    },
  },
})

describe('OrderCoupon', () => {
  it('should throw when useOrderCoupon is used outside a OrderCouponProvider', () => {
    const oldConsoleError = console.error
    console.error = () => {}
    const Component: FunctionComponent = () => {
      useOrderCoupon()
      return <div>foo</div>
    }

    expect(() => render(<Component />)).toThrow(
      'useOrderCoupon must be used within a OrderCouponProvider'
    )

    console.error = oldConsoleError
  })

  it('should insert a coupon', async () => {
    const Component: FunctionComponent = () => {
      const {
        orderForm: {
          marketingData: { coupon },
        },
      } = useOrderForm()
      const { insertCoupon } = useOrderCoupon()

      return (
        <div>
          {coupon}
          <button onClick={() => insertCoupon('newCoupon')}>mutate</button>
        </div>
      )
    }

    const mockInsertCoupon = mockInsertCouponMutation(
      'newCoupon',
      mockedMarketingData
    )

    const { getByText } = render(
      <OrderQueueProvider>
        <OrderFormProvider>
          <OrderCouponProvider>
            <Component />
          </OrderCouponProvider>
        </OrderFormProvider>
      </OrderQueueProvider>,
      { graphql: { mocks: [mockInsertCoupon] } }
    )

    const button = getByText('mutate')
    act(() => {
      fireEvent.click(button)
    })

    await act(() => new Promise(resolve => setTimeout(() => resolve())))
    expect(getByText('newCoupon')).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 doc-prop/messages/pt.json from the doc-prop VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "docProp.table.title": "Name",
  "docProp.table.type": "Type",
  "docProp.table.description": "Description",
  "docProp.table.defaultValue": "Default Value",
  "docProp.arrayTable.title": "These are the list items ",
  "docProp.objectTable.title": "These are the object properties ",
  "docProp.enumTable.title": "These are the enum values  "
}

```


[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 doc-prop/messages/en.json from the doc-prop VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "docProp.table.title": "Name",
  "docProp.table.type": "Type",
  "docProp.table.description": "Description",
  "docProp.table.defaultValue": "Default Value",
  "docProp.arrayTable.title": "Here are the items/properties of the array ",
  "docProp.objectTable.title": "Here are the properties of the object ",
  "docProp.enumTable.title": "Here are the values of the enum "
}

```


[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 doc-prop/messages/context.json from the doc-prop VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "docProp.table.title": "Name",
  "docProp.table.type": "Type",
  "docProp.table.description": "Description",
  "docProp.table.defaultValue": "Default Value",
  "docProp.arrayTable.title": "Here are the items/properties of the array ",
  "docProp.objectTable.title": "Here are the properties of the object ",
  "docProp.enumTable.title": "Here are the values of the enum "
}

```


[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 doc-prop/docs/README.md from the doc-prop VTEX app.

[Assistant]
Here's the implementation:

```markdown
# Doc Prop

This is the autodocumentator for VTEX IO Store Framework components

```


[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 doc-prop/pages/interfaces.json from the doc-prop VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "doc-prop": {
    "around": []
  },
  "doc-prop.table": {
    "component": "DocProp"
  }
}

```


[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 doc-prop/pages/routes.json from the doc-prop VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "doc-prop.table": {
    "path": "/docs/props/app/:appId/:interfaceId"
  }
}

```