refactor: Remove skipped tests (no-changelog) (#9497)

This commit is contained in:
Iván Ovejero 2024-05-23 12:29:20 +02:00 committed by GitHub
parent 70948ec71b
commit 75408b0113
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 0 additions and 569 deletions

View file

@ -42,39 +42,6 @@ describe('Credentials', () => {
credentialsPage.getters.credentialCards().should('have.length', 1);
});
it.skip('should create a new credential using Add Credential button', () => {
credentialsPage.getters.createCredentialButton().click();
credentialsModal.getters.newCredentialModal().should('be.visible');
credentialsModal.getters.newCredentialTypeSelect().should('be.visible');
credentialsModal.getters.newCredentialTypeOption('Airtable API').click();
credentialsModal.getters.newCredentialTypeButton().click();
credentialsModal.getters.editCredentialModal().should('be.visible');
credentialsModal.getters.connectionParameter('API Key').type('1234567890');
credentialsModal.actions.setName('Airtable Account');
credentialsModal.actions.save();
credentialsModal.actions.close();
credentialsPage.getters.credentialCards().should('have.length', 2);
});
it.skip('should search credentials', () => {
// Search by name
credentialsPage.actions.search('Notion');
credentialsPage.getters.credentialCards().should('have.length', 1);
// Search by Credential type
credentialsPage.actions.search('Airtable API');
credentialsPage.getters.credentialCards().should('have.length', 1);
// No results
credentialsPage.actions.search('Google');
credentialsPage.getters.credentialCards().should('have.length', 0);
credentialsPage.getters.emptyList().should('be.visible');
});
it('should sort credentials', () => {
credentialsPage.actions.search('');
credentialsPage.actions.sortBy('nameDesc');

View file

@ -1,118 +0,0 @@
import { WorkflowsPage as WorkflowsPageClass } from '../pages/workflows';
import { WorkflowPage as WorkflowPageClass } from '../pages/workflow';
import { MainSidebar } from '../pages';
import { INSTANCE_OWNER } from '../constants';
const WorkflowsPage = new WorkflowsPageClass();
const WorkflowPages = new WorkflowPageClass();
const mainSidebar = new MainSidebar();
describe.skip('Workflow filters', () => {
before(() => {
cy.enableFeature('sharing', true);
});
beforeEach(() => {
cy.visit(WorkflowsPage.url);
});
it('Should filter by tags', () => {
cy.visit(WorkflowsPage.url);
WorkflowsPage.getters.newWorkflowButtonCard().click();
cy.createFixtureWorkflow('Test_workflow_1.json', `Workflow 1`);
cy.visit(WorkflowsPage.url);
WorkflowsPage.getters.createWorkflowButton().click();
cy.createFixtureWorkflow('Test_workflow_2.json', `Workflow 2`);
cy.visit(WorkflowsPage.url);
WorkflowsPage.getters.workflowFilterButton().click();
WorkflowsPage.getters.workflowTagsDropdown().click();
WorkflowsPage.getters.workflowTagItem('other-tag-1').click();
cy.get('body').click(0, 0);
WorkflowsPage.getters.workflowCards().should('have.length', 1);
WorkflowsPage.getters.workflowCard('Workflow 2').should('contain.text', 'Workflow 2');
mainSidebar.actions.goToSettings();
cy.go('back');
WorkflowsPage.getters.workflowCards().should('have.length', 1);
WorkflowsPage.getters.workflowCard('Workflow 2').should('contain.text', 'Workflow 2');
WorkflowsPage.getters.workflowResetFilters().click();
WorkflowsPage.getters.workflowCards().each(($el) => {
const workflowName = $el.find('[data-test-id="workflow-card-name"]').text();
WorkflowsPage.getters.workflowCardActions(workflowName).click();
WorkflowsPage.getters.workflowDeleteButton().click();
cy.get('button').contains('delete').click();
});
});
it('Should filter by status', () => {
cy.visit(WorkflowsPage.url);
WorkflowsPage.getters.newWorkflowButtonCard().click();
cy.createFixtureWorkflow('Test_workflow_1.json', `Workflow 1`);
cy.visit(WorkflowsPage.url);
WorkflowsPage.getters.createWorkflowButton().click();
cy.createFixtureWorkflow('Test_workflow_3.json', `Workflow 3`);
WorkflowPages.getters.activatorSwitch().click();
cy.visit(WorkflowsPage.url);
WorkflowsPage.getters.workflowFilterButton().click();
WorkflowsPage.getters.workflowStatusDropdown().click();
WorkflowsPage.getters.workflowStatusItem('Active').click();
cy.get('body').click(0, 0);
WorkflowsPage.getters.workflowCards().should('have.length', 1);
WorkflowsPage.getters.workflowCard('Workflow 3').should('contain.text', 'Workflow 3');
mainSidebar.actions.goToSettings();
cy.go('back');
WorkflowsPage.getters.workflowCards().should('have.length', 1);
WorkflowsPage.getters.workflowCard('Workflow 3').should('contain.text', 'Workflow 3');
WorkflowsPage.getters.workflowResetFilters().click();
WorkflowsPage.getters.workflowCards().each(($el) => {
const workflowName = $el.find('[data-test-id="workflow-card-name"]').text();
WorkflowsPage.getters.workflowCardActions(workflowName).click();
WorkflowsPage.getters.workflowDeleteButton().click();
cy.get('button').contains('delete').click();
});
});
it('Should filter by owned by', () => {
cy.visit(WorkflowsPage.url);
WorkflowsPage.getters.newWorkflowButtonCard().click();
cy.createFixtureWorkflow('Test_workflow_1.json', `Workflow 1`);
cy.visit(WorkflowsPage.url);
WorkflowsPage.getters.createWorkflowButton().click();
cy.createFixtureWorkflow('Test_workflow_3.json', `Workflow 3`);
WorkflowPages.getters.activatorSwitch().click();
cy.visit(WorkflowsPage.url);
WorkflowsPage.getters.workflowFilterButton().click();
WorkflowsPage.getters.workflowOwnershipDropdown().realClick();
WorkflowsPage.getters.workflowOwner(INSTANCE_OWNER.email).click();
cy.get('body').click(0, 0);
WorkflowsPage.getters.workflowCards().should('have.length', 2);
mainSidebar.actions.goToSettings();
cy.go('back');
WorkflowsPage.getters.workflowResetFilters().click();
WorkflowsPage.getters.workflowCards().each(($el) => {
const workflowName = $el.find('[data-test-id="workflow-card-name"]').text();
WorkflowsPage.getters.workflowCardActions(workflowName).click();
WorkflowsPage.getters.workflowDeleteButton().click();
cy.get('button').contains('delete').click();
});
});
});

View file

@ -1,147 +0,0 @@
import { TemplatesPage } from '../pages/templates';
import { WorkflowPage } from '../pages/workflow';
import { TemplateWorkflowPage } from '../pages/template-workflow';
import OnboardingWorkflow from '../fixtures/Onboarding_workflow.json';
import WorkflowTemplate from '../fixtures/Workflow_template_write_http_query.json';
const templatesPage = new TemplatesPage();
const workflowPage = new WorkflowPage();
const templateWorkflowPage = new TemplateWorkflowPage();
describe.skip('In-app templates repository', () => {
beforeEach(() => {
cy.intercept('GET', '**/api/templates/search?page=1&rows=20&category=&search=', { fixture: 'templates_search/all_templates_search_response.json' }).as('searchRequest');
cy.intercept('GET', '**/api/templates/search?page=1&rows=20&category=Sales*', { fixture: 'templates_search/sales_templates_search_response.json' }).as('categorySearchRequest');
cy.intercept('GET', '**/api/templates/workflows/*', { fixture: 'templates_search/test_template_preview.json' }).as('singleTemplateRequest');
cy.intercept('GET', '**/api/workflows/templates/*', { fixture: 'templates_search/test_template_import.json' }).as('singleTemplateRequest');
cy.intercept('GET', '**/rest/settings', (req) => {
// Disable cache
delete req.headers['if-none-match']
req.reply((res) => {
if (res.body.data) {
// Enable in-app templates by setting a custom host
res.body.data.templates = { enabled: true, host: 'https://api-staging.n8n.io/api/' };
}
});
}).as('settingsRequest');
});
it('can open onboarding flow', () => {
templatesPage.actions.openOnboardingFlow(1, OnboardingWorkflow.name, OnboardingWorkflow, 'https://api-staging.n8n.io');
cy.url().then(($url) => {
expect($url).to.match(/.*\/workflow\/.*?onboardingId=1$/);
})
workflowPage.actions.shouldHaveWorkflowName(`Demo: ${name}`);
workflowPage.getters.canvasNodes().should('have.length', 4);
workflowPage.getters.stickies().should('have.length', 1);
workflowPage.getters.canvasNodes().first().should('have.descendants', '.node-pin-data-icon');
});
it('can import template', () => {
templatesPage.actions.importTemplate(1, OnboardingWorkflow.name, OnboardingWorkflow, 'https://api-staging.n8n.io');
cy.url().then(($url) => {
expect($url).to.include('/workflow/new?templateId=1');
});
workflowPage.getters.canvasNodes().should('have.length', 4);
workflowPage.getters.stickies().should('have.length', 1);
workflowPage.actions.shouldHaveWorkflowName(OnboardingWorkflow.name);
});
it('should save template id with the workflow', () => {
cy.visit(templatesPage.url);
cy.get('.el-skeleton.n8n-loading').should('not.exist');
templatesPage.getters.firstTemplateCard().should('exist');
templatesPage.getters.templatesLoadingContainer().should('not.exist');
templatesPage.getters.firstTemplateCard().click();
cy.url().should('include', '/templates/');
cy.url().then(($url) => {
const templateId = $url.split('/').pop();
templatesPage.getters.useTemplateButton().click();
cy.url().should('include', '/workflow/new');
workflowPage.actions.saveWorkflowOnButtonClick();
workflowPage.actions.selectAll();
workflowPage.actions.hitCopy();
cy.grantBrowserPermissions('clipboardReadWrite', 'clipboardSanitizedWrite');
// Check workflow JSON by copying it to clipboard
cy.readClipboard().then((workflowJSON) => {
expect(workflowJSON).to.contain(`"templateId": "${templateId}"`);
});
});
});
it('can open template with images and hides workflow screenshots', () => {
templateWorkflowPage.actions.openTemplate(WorkflowTemplate, 'https://api-staging.n8n.io');
templateWorkflowPage.getters.description().find('img').should('have.length', 1);
});
it('renders search elements correctly', () => {
cy.visit(templatesPage.url);
templatesPage.getters.searchInput().should('exist');
templatesPage.getters.allCategoriesFilter().should('exist');
templatesPage.getters.categoryFilters().should('have.length.greaterThan', 1);
templatesPage.getters.templateCards().should('have.length.greaterThan', 0);
});
it('can filter templates by category', () => {
cy.visit(templatesPage.url);
templatesPage.getters.templatesLoadingContainer().should('not.exist');
templatesPage.getters.categoryFilter('sales').should('exist');
let initialTemplateCount = 0;
let initialCollectionCount = 0;
templatesPage.getters.templateCountLabel().then(($el) => {
initialTemplateCount = parseInt($el.text().replace(/\D/g, ''), 10);
templatesPage.getters.collectionCountLabel().then(($el) => {
initialCollectionCount = parseInt($el.text().replace(/\D/g, ''), 10);
templatesPage.getters.categoryFilter('sales').click();
templatesPage.getters.templatesLoadingContainer().should('not.exist');
// Should have less templates and collections after selecting a category
templatesPage.getters.templateCountLabel().should(($el) => {
expect(parseInt($el.text().replace(/\D/g, ''), 10)).to.be.lessThan(initialTemplateCount);
});
templatesPage.getters.collectionCountLabel().should(($el) => {
expect(parseInt($el.text().replace(/\D/g, ''), 10)).to.be.lessThan(initialCollectionCount);
});
});
});
});
it('should preserve search query in URL', () => {
cy.visit(templatesPage.url);
templatesPage.getters.templatesLoadingContainer().should('not.exist');
templatesPage.getters.categoryFilter('sales').should('exist');
templatesPage.getters.categoryFilter('sales').click();
templatesPage.getters.searchInput().type('auto');
cy.url().should('include', '?categories=');
cy.url().should('include', '&search=');
cy.reload();
// Should preserve search query in URL
cy.url().should('include', '?categories=');
cy.url().should('include', '&search=');
// Sales category should still be selected
templatesPage.getters.categoryFilter('sales').find('label').should('have.class', 'is-checked');
// Search input should still have the search query
templatesPage.getters.searchInput().should('have.value', 'auto');
// Sales checkbox should be pushed to the top
templatesPage.getters.categoryFilters().eq(1).then(($el) => {
expect($el.text()).to.equal('Sales');
});
});
});

View file

@ -23,8 +23,6 @@ import type { MessageEventBusDestinationWebhook } from '@/eventbus/MessageEventB
import type { MessageEventBusDestinationSentry } from '@/eventbus/MessageEventBusDestination/MessageEventBusDestinationSentry.ee';
import { EventMessageAudit } from '@/eventbus/EventMessageClasses/EventMessageAudit';
import type { EventNamesTypes } from '@/eventbus/EventMessageClasses';
import { EventMessageWorkflow } from '@/eventbus/EventMessageClasses/EventMessageWorkflow';
import { EventMessageNode } from '@/eventbus/EventMessageClasses/EventMessageNode';
import { ExecutionDataRecoveryService } from '@/eventbus/executionDataRecovery.service';
import * as utils from './shared/utils';
@ -170,80 +168,6 @@ describe('POST /eventbus/destination', () => {
});
});
// this test (presumably the mocking) is causing the test suite to randomly fail
// eslint-disable-next-line n8n-local-rules/no-skipped-tests
test.skip('should send message to syslog', async () => {
const testMessage = new EventMessageGeneric({
eventName: 'n8n.test.message' as EventNamesTypes,
id: uuid(),
});
const syslogDestination = eventBus.destinations[
testSyslogDestination.id!
] as MessageEventBusDestinationSyslog;
syslogDestination.enable();
const mockedSyslogClientLog = jest.spyOn(syslogDestination.client, 'log');
mockedSyslogClientLog.mockImplementation((_m, _options, _cb) => {
eventBus.confirmSent(testMessage, {
id: syslogDestination.id,
name: syslogDestination.label,
});
return syslogDestination.client;
});
await eventBus.send(testMessage);
await new Promise((resolve) => {
eventBus.logWriter.worker?.on(
'message',
async function handler001(msg: { command: string; data: any }) {
if (msg.command === 'appendMessageToLog') {
await confirmIdInAll(testMessage.id);
} else if (msg.command === 'confirmMessageSent') {
await confirmIdSent(testMessage.id);
expect(mockedSyslogClientLog).toHaveBeenCalled();
syslogDestination.disable();
eventBus.logWriter.worker?.removeListener('message', handler001);
resolve(true);
}
},
);
});
});
// eslint-disable-next-line n8n-local-rules/no-skipped-tests
test.skip('should confirm send message if there are no subscribers', async () => {
const testMessageUnsubscribed = new EventMessageGeneric({
eventName: 'n8n.test.unsub' as EventNamesTypes,
id: uuid(),
});
const syslogDestination = eventBus.destinations[
testSyslogDestination.id!
] as MessageEventBusDestinationSyslog;
syslogDestination.enable();
await eventBus.send(testMessageUnsubscribed);
await new Promise((resolve) => {
eventBus.logWriter.worker?.on(
'message',
async function handler002(msg: { command: string; data: any }) {
if (msg.command === 'appendMessageToLog') {
await confirmIdInAll(testMessageUnsubscribed.id);
} else if (msg.command === 'confirmMessageSent') {
await confirmIdSent(testMessageUnsubscribed.id);
syslogDestination.disable();
eventBus.logWriter.worker?.removeListener('message', handler002);
resolve(true);
}
},
);
});
});
test('should anonymize audit message to syslog ', async () => {
const testAuditMessage = new EventMessageAudit({
eventName: 'n8n.audit.user.updated',
@ -395,57 +319,3 @@ test('DELETE /eventbus/destination delete all destinations by id', async () => {
expect(Object.keys(eventBus.destinations).length).toBe(0);
});
// These two tests are running very flaky on CI due to the logwriter working in a worker
// Mocking everything on the other would defeat the purpose of even testing them... so, skipping in CI for now.
// eslint-disable-next-line n8n-local-rules/no-skipped-tests
test.skip('should not find unfinished executions in recovery process', async () => {
eventBus.logWriter?.putMessage(
new EventMessageWorkflow({
eventName: 'n8n.workflow.started',
payload: { executionId: '509', isManual: false },
}),
);
eventBus.logWriter?.putMessage(
new EventMessageNode({
eventName: 'n8n.node.started',
payload: { executionId: '509', nodeName: 'Set', workflowName: 'test' },
}),
);
eventBus.logWriter?.putMessage(
new EventMessageNode({
eventName: 'n8n.node.finished',
payload: { executionId: '509', nodeName: 'Set', workflowName: 'test' },
}),
);
eventBus.logWriter?.putMessage(
new EventMessageWorkflow({
eventName: 'n8n.workflow.success',
payload: { executionId: '509', success: true },
}),
);
const unfinishedExecutions = await eventBus.getUnfinishedExecutions();
expect(Object.keys(unfinishedExecutions)).toHaveLength(0);
});
// eslint-disable-next-line n8n-local-rules/no-skipped-tests
test.skip('should not find unfinished executions in recovery process', async () => {
eventBus.logWriter?.putMessage(
new EventMessageWorkflow({
eventName: 'n8n.workflow.started',
payload: { executionId: '510', isManual: false },
}),
);
eventBus.logWriter?.putMessage(
new EventMessageNode({
eventName: 'n8n.node.started',
payload: { executionId: '510', nodeName: 'Set', workflowName: 'test' },
}),
);
const unfinishedExecutions = await eventBus.getUnfinishedExecutions();
expect(Object.keys(unfinishedExecutions)).toHaveLength(1);
expect(Object.keys(unfinishedExecutions)).toContain('510');
});

View file

@ -227,64 +227,6 @@ describe('GET /executions', () => {
expect(waitTill).toBeNull();
});
// failing on Postgres and MySQL - ref: https://github.com/n8n-io/n8n/pull/3834
// eslint-disable-next-line n8n-local-rules/no-skipped-tests
test.skip('should paginate two executions', async () => {
const workflow = await createWorkflow({}, owner);
const firstSuccessfulExecution = await createSuccessfulExecution(workflow);
const secondSuccessfulExecution = await createSuccessfulExecution(workflow);
await createErrorExecution(workflow);
const firstExecutionResponse = await authOwnerAgent.get('/executions').query({
status: 'success',
limit: 1,
});
expect(firstExecutionResponse.statusCode).toBe(200);
expect(firstExecutionResponse.body.data.length).toBe(1);
expect(firstExecutionResponse.body.nextCursor).toBeDefined();
const secondExecutionResponse = await authOwnerAgent.get('/executions').query({
status: 'success',
limit: 1,
cursor: firstExecutionResponse.body.nextCursor,
});
expect(secondExecutionResponse.statusCode).toBe(200);
expect(secondExecutionResponse.body.data.length).toBe(1);
expect(secondExecutionResponse.body.nextCursor).toBeNull();
const successfulExecutions = [firstSuccessfulExecution, secondSuccessfulExecution];
const executions = [...firstExecutionResponse.body.data, ...secondExecutionResponse.body.data];
for (let i = 0; i < executions.length; i++) {
const {
id,
finished,
mode,
retryOf,
retrySuccessId,
startedAt,
stoppedAt,
workflowId,
waitTill,
} = executions[i];
expect(id).toBeDefined();
expect(finished).toBe(true);
expect(mode).toEqual(successfulExecutions[i].mode);
expect(retrySuccessId).toBeNull();
expect(retryOf).toBeNull();
expect(startedAt).not.toBeNull();
expect(stoppedAt).not.toBeNull();
expect(workflowId).toBe(successfulExecutions[i].workflowId);
expect(waitTill).toBeNull();
}
});
test('should retrieve all error executions', async () => {
const workflow = await createWorkflow({}, owner);

View file

@ -54,46 +54,4 @@ describe('RedisService', () => {
await sub.destroy();
await pub.destroy();
});
// NOTE: This test is failing because the mock Redis client does not support streams apparently
// eslint-disable-next-line n8n-local-rules/no-skipped-tests
test.skip('should create stream producer and consumer', async () => {
const consumer = await redisService.getStreamConsumer();
const producer = await redisService.getStreamProducer();
expect(consumer).toBeDefined();
expect(producer).toBeDefined();
const mockHandler = jest.fn();
mockHandler.mockImplementation((stream: string, id: string, message: string[]) => {
Container.get(Logger).info('Received message', { stream, id, message });
});
consumer.addMessageHandler('some handler', mockHandler);
await consumer.setPollingInterval(STREAM_CHANNEL, 50);
await consumer.listenToStream(STREAM_CHANNEL);
let timeout;
await new Promise((resolve) => {
timeout = setTimeout(async () => {
await producer.add(STREAM_CHANNEL, ['message', 'testMessage', 'event', 'testEveny']);
resolve(0);
}, 50);
});
await new Promise((resolve) =>
setTimeout(async () => {
resolve(0);
}, 100),
);
clearInterval(timeout);
consumer.stopListeningToStream(STREAM_CHANNEL);
expect(mockHandler).toHaveBeenCalled();
await consumer.destroy();
await producer.destroy();
});
});

View file

@ -87,45 +87,4 @@ describe('SettingsSso', () => {
expect(getByRole('switch')).toBeEnabled();
expect(getByTestId('sso-test')).toBeEnabled();
});
// eslint-disable-next-line n8n-local-rules/no-skipped-tests
it.skip('should enable activation checkbox after data is saved', async () => {
await ssoStore.saveSamlConfig({ metadata: '' });
settingsStore.settings.enterprise[EnterpriseEditionFeature.Saml] = true;
await nextTick();
const saveSpy = vi.spyOn(ssoStore, 'saveSamlConfig');
const getSpy = vi.spyOn(ssoStore, 'getSamlConfig');
const { container, getByRole, getByTestId } = renderComponent({
pinia,
});
const checkbox = getByRole('switch');
const btnSave = getByTestId('sso-save');
const btnTest = getByTestId('sso-test');
expect(checkbox).toBeDisabled();
[btnSave, btnTest].forEach((el) => {
expect(el).toBeDisabled();
});
const xmlRadioButton = getByTestId('radio-button-xml');
await userEvent.click(xmlRadioButton);
await retry(() => expect(container.querySelector('textarea[name="metadata"]')).toBeVisible());
await userEvent.type(
container.querySelector('textarea[name="metadata"]')!,
'<?xml version="1.0"?>',
);
expect(checkbox).toBeDisabled();
expect(btnTest).toBeDisabled();
expect(btnSave).toBeEnabled();
await userEvent.click(btnSave);
expect(saveSpy).toHaveBeenCalled();
expect(getSpy).toHaveBeenCalled();
});
});