Files
n8n-enterprise-unlocked/packages/frontend/editor-ui/src/components/ApiKeyCreateOrEditModal.test.ts

236 lines
6.6 KiB
TypeScript

import { createComponentRenderer } from '@/__tests__/render';
import { createTestingPinia } from '@pinia/testing';
import { API_KEY_CREATE_OR_EDIT_MODAL_KEY, STORES } from '@/constants';
import { cleanupAppModals, createAppModals, mockedStore, retry } from '@/__tests__/utils';
import ApiKeyEditModal from './ApiKeyCreateOrEditModal.vue';
import { fireEvent } from '@testing-library/vue';
import { useApiKeysStore } from '@/stores/apiKeys.store';
import { DateTime } from 'luxon';
import type { ApiKeyWithRawValue } from '@n8n/api-types';
const renderComponent = createComponentRenderer(ApiKeyEditModal, {
pinia: createTestingPinia({
initialState: {
[STORES.UI]: {
modalsById: {
[API_KEY_CREATE_OR_EDIT_MODAL_KEY]: { open: true },
},
},
},
}),
});
const testApiKey: ApiKeyWithRawValue = {
id: '123',
label: 'new api key',
apiKey: '123456***',
createdAt: new Date().toString(),
updatedAt: new Date().toString(),
rawApiKey: '123456',
expiresAt: 0,
};
const apiKeysStore = mockedStore(useApiKeysStore);
describe('ApiKeyCreateOrEditModal', () => {
beforeEach(() => {
createAppModals();
});
afterEach(() => {
cleanupAppModals();
vi.clearAllMocks();
});
test('should allow creating API key with default expiration (30 days)', async () => {
apiKeysStore.createApiKey.mockResolvedValue(testApiKey);
const { getByText, getByPlaceholderText } = renderComponent({
props: {
mode: 'new',
},
});
await retry(() => expect(getByText('Create API Key')).toBeInTheDocument());
expect(getByText('Label')).toBeInTheDocument();
const inputLabel = getByPlaceholderText('e.g Internal Project');
const saveButton = getByText('Save');
expect(inputLabel).toBeInTheDocument();
expect(saveButton).toBeInTheDocument();
await fireEvent.update(inputLabel, 'new label');
await fireEvent.click(saveButton);
expect(getByText('API Key Created')).toBeInTheDocument();
expect(getByText('Done')).toBeInTheDocument();
expect(
getByText('Make sure to copy your API key now as you will not be able to see this again.'),
).toBeInTheDocument();
expect(getByText('You can find more details in')).toBeInTheDocument();
expect(getByText('the API documentation')).toBeInTheDocument();
expect(getByText('Click to copy')).toBeInTheDocument();
expect(getByText('new api key')).toBeInTheDocument();
});
test('should allow creating API key with custom expiration', async () => {
apiKeysStore.createApiKey.mockResolvedValue({
id: '123',
label: 'new api key',
apiKey: '123456',
createdAt: new Date().toString(),
updatedAt: new Date().toString(),
rawApiKey: '***456',
expiresAt: 0,
});
const { getByText, getByPlaceholderText, getByTestId } = renderComponent({
props: {
mode: 'new',
},
});
await retry(() => expect(getByText('Create API Key')).toBeInTheDocument());
expect(getByText('Label')).toBeInTheDocument();
const inputLabel = getByPlaceholderText('e.g Internal Project');
const saveButton = getByText('Save');
const expirationSelect = getByTestId('expiration-select');
expect(inputLabel).toBeInTheDocument();
expect(saveButton).toBeInTheDocument();
expect(expirationSelect).toBeInTheDocument();
await fireEvent.update(inputLabel, 'new label');
await fireEvent.click(expirationSelect);
const customOption = getByText('Custom');
expect(customOption).toBeInTheDocument();
await fireEvent.click(customOption);
const customExpirationInput = getByPlaceholderText('yyyy-mm-dd');
expect(customExpirationInput).toBeInTheDocument();
await fireEvent.input(customExpirationInput, '2029-12-31');
await fireEvent.click(saveButton);
expect(getByText('***456')).toBeInTheDocument();
expect(getByText('API Key Created')).toBeInTheDocument();
expect(getByText('Done')).toBeInTheDocument();
expect(
getByText('Make sure to copy your API key now as you will not be able to see this again.'),
).toBeInTheDocument();
expect(getByText('You can find more details in')).toBeInTheDocument();
expect(getByText('the API documentation')).toBeInTheDocument();
expect(getByText('Click to copy')).toBeInTheDocument();
expect(getByText('new api key')).toBeInTheDocument();
});
test('should allow creating API key with no expiration', async () => {
apiKeysStore.createApiKey.mockResolvedValue(testApiKey);
const { getByText, getByPlaceholderText, getByTestId } = renderComponent({
props: {
mode: 'new',
},
});
await retry(() => expect(getByText('Create API Key')).toBeInTheDocument());
expect(getByText('Label')).toBeInTheDocument();
const inputLabel = getByPlaceholderText('e.g Internal Project');
const saveButton = getByText('Save');
const expirationSelect = getByTestId('expiration-select');
expect(inputLabel).toBeInTheDocument();
expect(saveButton).toBeInTheDocument();
expect(expirationSelect).toBeInTheDocument();
await fireEvent.update(inputLabel, 'new label');
await fireEvent.click(expirationSelect);
const noExpirationOption = getByText('No Expiration');
expect(noExpirationOption).toBeInTheDocument();
await fireEvent.click(noExpirationOption);
await fireEvent.click(saveButton);
expect(getByText('API Key Created')).toBeInTheDocument();
expect(getByText('Done')).toBeInTheDocument();
expect(
getByText('Make sure to copy your API key now as you will not be able to see this again.'),
).toBeInTheDocument();
expect(getByText('You can find more details in')).toBeInTheDocument();
expect(getByText('the API documentation')).toBeInTheDocument();
expect(getByText('Click to copy')).toBeInTheDocument();
expect(getByText('new api key')).toBeInTheDocument();
});
test('should allow editing API key label', async () => {
apiKeysStore.apiKeys = [testApiKey];
apiKeysStore.updateApiKey.mockResolvedValue();
const { getByText, getByTestId } = renderComponent({
props: {
mode: 'edit',
activeId: '123',
},
});
await retry(() => expect(getByText('Edit API Key')).toBeInTheDocument());
expect(getByText('Label')).toBeInTheDocument();
const formattedDate = DateTime.fromMillis(Date.parse(testApiKey.createdAt)).toFormat(
'ccc, MMM d yyyy',
);
expect(getByText(`API key was created on ${formattedDate}`)).toBeInTheDocument();
const labelInput = getByTestId('api-key-label');
expect((labelInput as unknown as HTMLInputElement).value).toBe('new api key');
await fireEvent.update(labelInput, 'updated api key');
const editButton = getByText('Edit');
expect(editButton).toBeInTheDocument();
await fireEvent.click(editButton);
expect(apiKeysStore.updateApiKey).toHaveBeenCalledWith('123', { label: 'updated api key' });
});
});