import { render, screen, waitFor } from '@testing-library/react' import { userEvent } from '@testing-library/user-event' import React from 'react' import apiFetch from '@wordpress/api-fetch' import ActivationKeyForm from '../ActivationKeyForm' jest.mock('@wordpress/api-fetch') const mockApiFetch = apiFetch as jest.MockedFunction const WEBSHOP_ID = '0f8fad5b-d9cb-469f-a165-70867728950e' const API_KEY = 'c2VjcmV0' const ACTIVATION_KEY = `${WEBSHOP_ID}:${API_KEY}` const onConnected = jest.fn() const renderForm = (prominent = true, focusOnOpen = false) => render( ) const keyField = () => screen.getByLabelText('Activation key') const activateButton = () => screen.getByRole('button', { name: 'Activate' }) const enterKey = (key: string) => userEvent.type(keyField(), key) const mybringAnswers = (accessToWebshop: boolean) => mockApiFetch.mockResolvedValue({ validCredentials: true, validWebshopId: true, accessToWebshop, } as never) describe('ActivationKeyForm', () => { beforeEach(() => { jest.clearAllMocks() }) it('asks for the activation key from Mybring, masked as it is a secret', () => { renderForm() expect(keyField()).toHaveAttribute('type', 'password') }) it('holds back activating until a key has been entered', () => { renderForm() expect(activateButton()).toBeDisabled() }) it('points out a key that does not look like an activation key', async () => { renderForm() await enterKey('not a key') expect(keyField()).toHaveAttribute('aria-invalid', 'true') expect( screen.getByText( "This doesn't look like an activation key from Mybring. Copy the whole key and try again." ) ).toBeInTheDocument() expect(activateButton()).toBeDisabled() }) it('accepts a key with surrounding white space', async () => { renderForm() await enterKey(` ${ACTIVATION_KEY} `) expect(keyField()).toHaveAttribute('aria-invalid', 'false') expect(activateButton()).toBeEnabled() }) it('activates the plugin with the webshop ID and API key from the key', async () => { mybringAnswers(true) renderForm() await enterKey(ACTIVATION_KEY) await userEvent.click(activateButton()) await waitFor(() => expect(onConnected).toHaveBeenCalled()) expect(mockApiFetch).toHaveBeenCalledWith( expect.objectContaining({ method: 'POST', data: { apikey: API_KEY, webshop_id: WEBSHOP_ID }, }) ) }) it('does not use a form, so the browser is less inclined to save the key as a password', () => { const { container } = renderForm() expect(container.querySelector('form')).toBeNull() }) it('activates when the merchant presses Enter in the key field', async () => { mybringAnswers(true) renderForm() await enterKey(`${ACTIVATION_KEY}{Enter}`) await waitFor(() => expect(onConnected).toHaveBeenCalled()) }) it('does not activate on Enter before the key looks right', async () => { renderForm() await enterKey('not a key{Enter}') expect(mockApiFetch).not.toHaveBeenCalled() }) it('tells the merchant when Mybring does not accept the key', async () => { mybringAnswers(false) renderForm() await enterKey(ACTIVATION_KEY) await userEvent.click(activateButton()) expect( await screen.findByText("The key wasn't accepted") ).toBeInTheDocument() expect(onConnected).not.toHaveBeenCalled() }) it('tells the merchant to try again later when the key could not be checked', async () => { mockApiFetch.mockRejectedValue(new Error('Internal Server Error')) renderForm() await enterKey(ACTIVATION_KEY) await userEvent.click(activateButton()) expect( await screen.findByText("The key couldn't be checked right now") ).toBeInTheDocument() expect(screen.getByText('Try again in a few minutes.')).toBeInTheDocument() expect( screen.queryByText("The key wasn't accepted") ).not.toBeInTheDocument() expect(onConnected).not.toHaveBeenCalled() }) it('clears an earlier failure once the merchant tries again', async () => { mockApiFetch.mockRejectedValueOnce(new Error('Internal Server Error')) mybringAnswers(false) renderForm() await enterKey(ACTIVATION_KEY) await userEvent.click(activateButton()) await screen.findByText("The key couldn't be checked right now") await userEvent.click(activateButton()) expect( await screen.findByText("The key wasn't accepted") ).toBeInTheDocument() expect( screen.queryByText("The key couldn't be checked right now") ).not.toBeInTheDocument() }) it('makes activating the main action only when the step is the one to do', async () => { renderForm(false) expect(activateButton()).toHaveAttribute('data-variant', 'outline') }) it('moves focus into the key field when the merchant opened it', () => { renderForm(true, true) expect(keyField()).toHaveFocus() }) it('leaves focus alone when the field opened by itself', () => { renderForm(true, false) expect(keyField()).not.toHaveFocus() }) })