<|start_filename|>packages/theme/test-utils/mocks/useUser.js<|end_filename|>
export const useUserMock = (userData = {}) => ({
  load: jest.fn(),
  loading: {
    value: false,
  },
  isAuthenticated: {
    value: false,
  },
  error: {
    value: {
      register: null,
    },
  },
  ...userData,
});

export default useUserMock;


<|start_filename|>packages/theme/test-utils/mocks/index.js<|end_filename|>
export * from './useGuestUser';
export * from './useUser';


<|start_filename|>packages/theme/test-utils.js<|end_filename|>
import { render } from '@testing-library/vue';

const $t = (text) => text;

// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
const customRender = (component, options = {}, callback = null) => render(component, {
  mocks: {
    $t,
    ...options?.mocks,
  },
  ...options,
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
}, callback);

export * from '@testing-library/vue';
export * from '~/test-utils/mocks';
export { customRender as render };


<|start_filename|>packages/theme/pages/Checkout/__tests__/UserAccount.spec.js<|end_filename|>
/* eslint-disable @typescript-eslint/no-unsafe-argument */
import userEvent from '@testing-library/user-event';
import { waitFor } from '@testing-library/vue';
import { useRouter } from '@nuxtjs/composition-api';
import { useGuestUser, useUser } from '@vue-storefront/magento';
import { render, useUserMock, useGuestUserMock } from '~/test-utils';

import UserAccount from '../UserAccount';

jest.mock('@vue-storefront/magento', () => ({
  useGuestUser: jest.fn(),
  useUser: jest.fn(),
}));

jest.mock('@nuxtjs/composition-api', () => {
  // Require the original module to not be mocked...
  const originalModule = jest.requireActual('@nuxtjs/composition-api');

  return {
    ...originalModule,
    useRouter: jest.fn(),
  };
});

describe('<UserAccount/>', () => {
  it('Form fields are rendered and validated', async () => {
    useUser.mockReturnValue(useUserMock());
    useGuestUser.mockReturnValue(useGuestUserMock());

    const { getByRole, findAllByText } = render(UserAccount);

    // First name, last name and email fields should be rendered and required

    const firstNameInput = getByRole('textbox', { name: /first name/i });
    expect(firstNameInput).toBeRequired();

    const lastNameInput = getByRole('textbox', { name: /last name/i });
    expect(lastNameInput).toBeRequired();

    const emailInput = getByRole('textbox', { name: /e-mail/i });
    expect(emailInput).toBeRequired();

    const continueButton = getByRole('button', { name: /continue to shipping/i });
    userEvent.click(continueButton);

    // should display form errors when field are not filled
    const errors = await findAllByText('This field is required');
    expect(errors).toHaveLength(3);
  });

  it('Email should be validated', async () => {
    useUser.mockReturnValue(useUserMock());
    useGuestUser.mockReturnValue(useGuestUserMock());

    const { getByRole, findByText } = render(UserAccount);

    const emailInput = getByRole('textbox', { name: /e-mail/i });
    const continueButton = getByRole('button', { name: /continue to shipping/i });

    userEvent.type(emailInput, 'invalid email value');
    userEvent.click(continueButton);

    const validationMessage = await findByText('Invalid email');
    expect(validationMessage).toBeInTheDocument();
  });

  it('User can go ahead as guest user', async () => {
    const attachToCartMock = jest.fn();
    const routerPushMock = jest.fn();

    useUser.mockReturnValue(useUserMock());
    useGuestUser.mockReturnValue(useGuestUserMock({
      attachToCart: attachToCartMock,
    }));
    useRouter.mockReturnValue({
      push: routerPushMock,
    });

    const { getByRole } = render(UserAccount);

    const firstNameInput = getByRole('textbox', { name: /first name/i });
    const lastNameInput = getByRole('textbox', { name: /last name/i });
    const emailInput = getByRole('textbox', { name: /e-mail/i });
    const continueButton = getByRole('button', { name: /continue to shipping/i });

    // fill the form
    userEvent.type(firstNameInput, 'James');
    userEvent.type(lastNameInput, 'Bond');
    userEvent.type(emailInput, '<EMAIL>');

    // click the continue button
    userEvent.click(continueButton);

    await waitFor(() => {
      expect(attachToCartMock).toHaveBeenCalledTimes(1);
      expect(attachToCartMock).toHaveBeenCalledWith({
        user: {
          email: '<EMAIL>',
          firstname: 'James',
          lastname: 'Bond',
          password: '',
          is_subscribed: false,
        },
      });
    });
    expect(routerPushMock).toHaveBeenCalledTimes(1);
    expect(routerPushMock).toHaveBeenCalledWith('/checkout/shipping');
  });

  test.todo('User cannot move to the next step if data is loading');

  test.todo('User can log-in to the store');

  test.todo('User can create an account');

  test.todo('User can subscribe to the newsletter during account creation');
});


<|start_filename|>packages/theme/middleware.config.js<|end_filename|>
const config = require('./config.js');
const cookieNames = require('./enums/cookieNameEnum');

module.exports = {
  integrations: {
    magento: {
      location: '@vue-storefront/magento-api/server',
      configuration: {
        api: config.get('magentoGraphQl'),
        cookies: {
          ...cookieNames,
        },
        defaultStore: 'default',
        externalCheckout: {
          enable: config.get('enableMagentoExternalCheckout'),
          cmsUrl: config.get('externalCheckoutUrl'),
          syncUrlPath: config.get('externalCheckoutSyncPath'),
          stores: {
            default: config.get('enableMagentoExternalCheckout'),
          },
        },
        facets: {
          available: ['color', 'size', 'price'],
        },
        customApolloHttpLinkOptions: {
          useGETForQueries: false,
        },
      },
    },
  },
};


<|start_filename|>packages/theme/config/example.json<|end_filename|>
{
  "storeUrl": "http://localhost:3000",
  "nuxtAppEnvironment": "development",
  "nuxtAppPort": 3000,
  "magentoGraphQl": "https://{YOUR_SITE_FRONT_URL}/graphql",
  "enableMagentoExternalCheckout": false,
  "externalCheckoutUrl": "https://{YOUR_SITE_FRONT_URL}",
  "externalCheckoutSyncPath": "/vue/cart/sync"
}


<|start_filename|>.vuestorefrontcloud/docker/Dockerfile<|end_filename|>
FROM node:16

ARG COMMIT
ARG NPM_USER
ARG NPM_PASS
ARG NPM_EMAIL
ARG NPM_REGISTRY
ARG MAGENTO_GRAPHQL
ARG MAGENTO_EXTERNAL_CHECKOUT_URL
ARG MAGENTO_EXTERNAL_CHECKOUT
ARG MAGENTO_EXTERNAL_CHECKOUT_SYNC_PATH
ARG STORE_URL

ENV MAGENTO_GRAPHQL=${MAGENTO_GRAPHQL}
ENV MAGENTO_EXTERNAL_CHECKOUT_URL=${MAGENTO_EXTERNAL_CHECKOUT_URL}
ENV MAGENTO_EXTERNAL_CHECKOUT=${MAGENTO_EXTERNAL_CHECKOUT}
ENV MAGENTO_EXTERNAL_CHECKOUT_SYNC_PATH=${MAGENTO_EXTERNAL_CHECKOUT_SYNC_PATH}
ENV STORE_URL=${STORE_URL}
ENV LAST_COMMIT=${COMMIT}
ENV STORE_ENV=production
ENV NUXT_APP_ENV=production
ENV NUXT_APP_PORT=3000


RUN npm install -g npm-cli-login \
  && npm-cli-login

WORKDIR /var/www

COPY . .

RUN yarn install && yarn build && yarn cache clean --all

COPY .vuestorefrontcloud/docker/vue-storefront.sh /usr/local/bin/

RUN chmod a+x /usr/local/bin/vue-storefront.sh

ENTRYPOINT ["vue-storefront.sh"]
