import { customAlphabet } from 'nanoid'; import { test, expect } from '../../../../fixtures/base'; const generateValidId = customAlphabet( 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_', 8, ); test.describe('Variables', { annotation: [ { type: 'owner', description: 'Lifecycle & Governance' }, ], }, () => { // These tests are serial since it's at an instance level and they interact with the same variables test.describe.configure({ mode: 'serial' }); test.describe('unlicensed', () => { test('should show the unlicensed action box when the feature is disabled', async ({ n8n }) => { await n8n.api.disableFeature('variables'); await n8n.navigate.toVariables(); await expect(n8n.variables.getUnavailableResourcesList()).toBeVisible(); await expect(n8n.variables.getResourcesList()).toBeHidden(); }); }); test.describe('licensed', () => { test.beforeEach(async ({ n8n }) => { await n8n.api.enableFeature('variables'); await n8n.api.variables.deleteAllVariables(); await n8n.navigate.toVariables(); }); test('should create a new variable using empty state', async ({ n8n }) => { const key = `ENV_VAR_${generateValidId()}`; const value = 'test_value'; await n8n.variables.createVariableFromEmptyState(key, value); const variableRow = n8n.variables.getVariableRow(key); await expect(variableRow).toContainText(value); await expect(variableRow).toBeVisible(); await expect(n8n.variables.getVariablesRows()).toHaveCount(1); }); test('should create multiple variables', async ({ n8n }) => { const key1 = `ENV_VAR_NEW_${generateValidId()}`; const value1 = 'test_value_1'; await n8n.variables.createVariableFromEmptyState(key1, value1); await expect(n8n.variables.getVariablesRows()).toHaveCount(1); const key2 = `ENV_EXAMPLE_${generateValidId()}`; const value2 = 'test_value_2'; await n8n.variables.createVariable(key2, value2); await expect(n8n.variables.getVariablesRows()).toHaveCount(2); const variableRow1 = n8n.variables.getVariableRow(key1); await expect(variableRow1).toContainText(value1); await expect(variableRow1).toBeVisible(); const variableRow2 = n8n.variables.getVariableRow(key2); await expect(variableRow2).toContainText(value2); await expect(variableRow2).toBeVisible(); }); test('should get validation errors and cancel variable creation', async ({ n8n }) => { await n8n.variables.createVariableFromEmptyState( `ENV_BASE_${generateValidId()}`, 'base_value', ); await expect(n8n.variables.getVariablesRows()).toHaveCount(1); const initialCount = await n8n.variables.getVariablesRows().count(); const key = `ENV_VAR_INVALID_${generateValidId()}$`; // Invalid key with special character const value = 'test_value'; await n8n.variables.createVariable(key, value, { shouldSave: false }); const saveButton = n8n.variables.variableModal.getSaveButton(); await expect(saveButton).toBeDisabled(); await n8n.variables.variableModal.close(); await expect(n8n.variables.getVariablesRows()).toHaveCount(initialCount); }); test('should edit a variable', async ({ n8n }) => { const key = `ENV_VAR_EDIT_${generateValidId()}`; const initialValue = 'initial_value'; await n8n.variables.createVariableFromEmptyState(key, initialValue); const newValue = 'updated_value'; await n8n.variables.editVariable(key, newValue, { shouldSave: true }); const variableRow = n8n.variables.getVariableRow(key); await expect(variableRow).toContainText(newValue); await expect(variableRow).toBeVisible(); }); test('should delete a variable', async ({ n8n }) => { const key = `TO_DELETE_${generateValidId()}`; const value = 'delete_test_value'; await n8n.variables.createVariableFromEmptyState(key, value); await expect(n8n.variables.getVariablesRows()).toHaveCount(1); const initialCount = await n8n.variables.getVariablesRows().count(); await n8n.variables.deleteVariable(key); await expect(n8n.variables.getVariablesRows()).toHaveCount(initialCount - 1); await expect(n8n.variables.getVariableRow(key)).toBeHidden(); }); test('should search for a variable', async ({ n8n }) => { const uniqueId = generateValidId(); const key1 = `SEARCH_VAR_${uniqueId}`; const key2 = `SEARCH_VAR_NEW_${uniqueId}`; const key3 = `SEARCH_EXAMPLE_${uniqueId}`; await n8n.variables.createVariableFromEmptyState(key1, 'search_value_1'); await n8n.variables.createVariable(key2, 'search_value_2'); await n8n.variables.createVariable(key3, 'search_value_3'); await n8n.variables.getSearchBar().fill('NEW_'); await n8n.variables.getSearchBar().press('Enter'); await expect(n8n.variables.getVariablesRows()).toHaveCount(1); await expect(n8n.variables.getVariableRow(key2)).toBeVisible(); await expect(n8n.page).toHaveURL(new RegExp('search=NEW_')); await n8n.variables.getSearchBar().clear(); await n8n.variables.getSearchBar().fill('SEARCH_VAR_'); await n8n.variables.getSearchBar().press('Enter'); await expect(n8n.variables.getVariablesRows()).toHaveCount(2); await expect(n8n.variables.getVariableRow(key1)).toBeVisible(); await expect(n8n.variables.getVariableRow(key2)).toBeVisible(); await expect(n8n.page).toHaveURL(new RegExp('search=SEARCH_VAR_')); await n8n.variables.getSearchBar().clear(); await n8n.variables.getSearchBar().fill('SEARCH_'); await n8n.variables.getSearchBar().press('Enter'); await expect(n8n.variables.getVariablesRows()).toHaveCount(3); await expect(n8n.variables.getVariableRow(key1)).toBeVisible(); await expect(n8n.variables.getVariableRow(key2)).toBeVisible(); await expect(n8n.variables.getVariableRow(key3)).toBeVisible(); await expect(n8n.page).toHaveURL(new RegExp('search=SEARCH_')); await n8n.variables.getSearchBar().clear(); await n8n.variables.getSearchBar().fill(`NonExistent_${generateValidId()}`); await n8n.variables.getSearchBar().press('Enter'); await expect(n8n.variables.getVariablesRows()).toBeHidden(); await expect(n8n.page).toHaveURL(/search=NonExistent_/); await expect(n8n.variables.getNoVariablesFoundMessage()).toBeVisible(); }); }); });