mirror of
https://github.com/n8n-io/n8n.git
synced 2025-02-02 07:01:30 -08:00
fix(editor): Fix workflows filter resetting (#8411)
This commit is contained in:
parent
caab97e667
commit
ad4b298be3
|
@ -6,6 +6,8 @@ import { routesForVariables } from './variable';
|
|||
import { routesForSettings } from './settings';
|
||||
import { routesForSSO } from './sso';
|
||||
import { routesForSourceControl } from './sourceControl';
|
||||
import { routesForWorkflows } from './workflow';
|
||||
import { routesForTags } from './tag';
|
||||
|
||||
const endpoints: Array<(server: Server) => void> = [
|
||||
routesForCredentials,
|
||||
|
@ -15,6 +17,8 @@ const endpoints: Array<(server: Server) => void> = [
|
|||
routesForSettings,
|
||||
routesForSSO,
|
||||
routesForSourceControl,
|
||||
routesForWorkflows,
|
||||
routesForTags,
|
||||
];
|
||||
|
||||
export { endpoints };
|
||||
|
|
11
packages/editor-ui/src/__tests__/server/endpoints/tag.ts
Normal file
11
packages/editor-ui/src/__tests__/server/endpoints/tag.ts
Normal file
|
@ -0,0 +1,11 @@
|
|||
import type { Server } from 'miragejs';
|
||||
import { Response } from 'miragejs';
|
||||
import type { AppSchema } from '../types';
|
||||
|
||||
export function routesForTags(server: Server) {
|
||||
server.get('/rest/tags', (schema: AppSchema) => {
|
||||
const { models: data } = schema.all('tag');
|
||||
|
||||
return new Response(200, {}, { data });
|
||||
});
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
import type { Server } from 'miragejs';
|
||||
import { Response } from 'miragejs';
|
||||
import type { AppSchema } from '../types';
|
||||
|
||||
export function routesForWorkflows(server: Server) {
|
||||
server.get('/rest/workflows', (schema: AppSchema) => {
|
||||
const { models: data } = schema.all('workflow');
|
||||
|
||||
return new Response(200, {}, { data });
|
||||
});
|
||||
server.get('/rest/active-workflows', (schema: AppSchema) => {
|
||||
const { models: data } = schema.all('workflow');
|
||||
|
||||
return new Response(200, {}, { data });
|
||||
});
|
||||
}
|
|
@ -2,6 +2,8 @@ import { userFactory } from './user';
|
|||
import { credentialFactory } from './credential';
|
||||
import { credentialTypeFactory } from './credentialType';
|
||||
import { variableFactory } from './variable';
|
||||
import { workflowFactory } from './workflow';
|
||||
import { tagFactory } from './tag';
|
||||
|
||||
export * from './user';
|
||||
export * from './credential';
|
||||
|
@ -13,4 +15,6 @@ export const factories = {
|
|||
credentialType: credentialTypeFactory,
|
||||
user: userFactory,
|
||||
variable: variableFactory,
|
||||
workflow: workflowFactory,
|
||||
tag: tagFactory,
|
||||
};
|
||||
|
|
12
packages/editor-ui/src/__tests__/server/factories/tag.ts
Normal file
12
packages/editor-ui/src/__tests__/server/factories/tag.ts
Normal file
|
@ -0,0 +1,12 @@
|
|||
import { Factory } from 'miragejs';
|
||||
import type { ITag } from '@/Interface';
|
||||
import { faker } from '@faker-js/faker';
|
||||
|
||||
export const tagFactory = Factory.extend<ITag>({
|
||||
id(i: string) {
|
||||
return i;
|
||||
},
|
||||
name() {
|
||||
return faker.lorem.word();
|
||||
},
|
||||
});
|
|
@ -0,0 +1,18 @@
|
|||
import { Factory } from 'miragejs';
|
||||
import type { IWorkflowDb } from '@/Interface';
|
||||
import { faker } from '@faker-js/faker';
|
||||
|
||||
export const workflowFactory = Factory.extend<IWorkflowDb>({
|
||||
id(i: string) {
|
||||
return i;
|
||||
},
|
||||
name() {
|
||||
return faker.lorem.word();
|
||||
},
|
||||
createdAt() {
|
||||
return faker.date.recent().toISOString();
|
||||
},
|
||||
tags() {
|
||||
return faker.lorem.words(2.5).split(' ');
|
||||
},
|
||||
});
|
|
@ -0,0 +1,7 @@
|
|||
import { tags } from './tags';
|
||||
import { workflows } from './workflows';
|
||||
|
||||
export const fixtures = {
|
||||
tags,
|
||||
workflows,
|
||||
};
|
15
packages/editor-ui/src/__tests__/server/fixtures/tags.ts
Normal file
15
packages/editor-ui/src/__tests__/server/fixtures/tags.ts
Normal file
|
@ -0,0 +1,15 @@
|
|||
import type { ITag } from '@/Interface';
|
||||
export const tags: ITag[] = [
|
||||
{
|
||||
id: '1',
|
||||
name: 'tag1',
|
||||
},
|
||||
{
|
||||
id: '2',
|
||||
name: 'tag2',
|
||||
},
|
||||
{
|
||||
id: '3',
|
||||
name: 'tag3',
|
||||
},
|
||||
];
|
|
@ -0,0 +1,47 @@
|
|||
import type { IWorkflowDb } from '@/Interface';
|
||||
import { faker } from '@faker-js/faker';
|
||||
|
||||
export const workflows = [
|
||||
{
|
||||
id: '1',
|
||||
name: 'workflow1',
|
||||
tags: [],
|
||||
},
|
||||
{
|
||||
id: '2',
|
||||
name: 'workflow2',
|
||||
tags: [
|
||||
{ id: '1', name: 'tag1' },
|
||||
{ id: '2', name: 'tag2' },
|
||||
],
|
||||
},
|
||||
{
|
||||
id: '3',
|
||||
name: 'workflow3',
|
||||
tags: [
|
||||
{ id: '1', name: 'tag1' },
|
||||
{ id: '3', name: 'tag3' },
|
||||
],
|
||||
},
|
||||
{
|
||||
id: '4',
|
||||
name: 'workflow4',
|
||||
tags: [
|
||||
{ id: '2', name: 'tag2' },
|
||||
{ id: '3', name: 'tag3' },
|
||||
],
|
||||
},
|
||||
{
|
||||
id: '5',
|
||||
name: 'workflow5',
|
||||
tags: [
|
||||
{ id: '1', name: 'tag1' },
|
||||
{ id: '2', name: 'tag2' },
|
||||
{ id: '3', name: 'tag3' },
|
||||
],
|
||||
},
|
||||
].map((wf, idx) => ({
|
||||
...wf,
|
||||
createdAt: faker.date.recent().toISOString(),
|
||||
updatedAt: new Date(`2024-1-${idx + 1}`).toISOString(),
|
||||
})) as IWorkflowDb[];
|
|
@ -2,12 +2,15 @@ import { createServer } from 'miragejs';
|
|||
import { endpoints } from './endpoints';
|
||||
import { models } from './models';
|
||||
import { factories } from './factories';
|
||||
import { fixtures } from './fixtures';
|
||||
|
||||
export function setupServer() {
|
||||
const server = createServer({
|
||||
models,
|
||||
factories,
|
||||
fixtures,
|
||||
seeds(server) {
|
||||
server.loadFixtures('tags', 'workflows');
|
||||
server.createList('credentialType', 8);
|
||||
server.create('user', {
|
||||
firstName: 'Nathan',
|
||||
|
|
|
@ -2,10 +2,14 @@ import { UserModel } from './user';
|
|||
import { CredentialModel } from './credential';
|
||||
import { CredentialTypeModel } from './credentialType';
|
||||
import { VariableModel } from './variable';
|
||||
import { WorkflowModel } from './workflow';
|
||||
import { TagModel } from './tag';
|
||||
|
||||
export const models = {
|
||||
credential: CredentialModel,
|
||||
credentialType: CredentialTypeModel,
|
||||
user: UserModel,
|
||||
variable: VariableModel,
|
||||
workflow: WorkflowModel,
|
||||
tag: TagModel,
|
||||
};
|
||||
|
|
5
packages/editor-ui/src/__tests__/server/models/tag.ts
Normal file
5
packages/editor-ui/src/__tests__/server/models/tag.ts
Normal file
|
@ -0,0 +1,5 @@
|
|||
import type { ITag } from '@/Interface';
|
||||
import { Model } from 'miragejs';
|
||||
import type { ModelDefinition } from 'miragejs/-types';
|
||||
|
||||
export const TagModel: ModelDefinition<ITag> = Model.extend({});
|
|
@ -0,0 +1,5 @@
|
|||
import type { IWorkflowDb } from '@/Interface';
|
||||
import { Model } from 'miragejs';
|
||||
import type { ModelDefinition } from 'miragejs/-types';
|
||||
|
||||
export const WorkflowModel: ModelDefinition<IWorkflowDb> = Model.extend({});
|
|
@ -454,6 +454,7 @@ export default defineComponent({
|
|||
|
||||
this.resettingFilters = true;
|
||||
this.sendFiltersTelemetry('reset');
|
||||
this.$emit('update:filters', this.filtersModel);
|
||||
},
|
||||
focusSearchInput() {
|
||||
if (this.$refs.search) {
|
||||
|
|
99
packages/editor-ui/src/views/__tests__/WorkflowsView.test.ts
Normal file
99
packages/editor-ui/src/views/__tests__/WorkflowsView.test.ts
Normal file
|
@ -0,0 +1,99 @@
|
|||
import { afterAll, beforeAll } from 'vitest';
|
||||
import { setActivePinia, createPinia } from 'pinia';
|
||||
import { waitFor } from '@testing-library/vue';
|
||||
import userEvent from '@testing-library/user-event';
|
||||
import { setupServer } from '@/__tests__/server';
|
||||
import WorkflowsView from '@/views/WorkflowsView.vue';
|
||||
import { useSettingsStore } from '@/stores/settings.store';
|
||||
import { useUsersStore } from '@/stores/users.store';
|
||||
import { createComponentRenderer } from '@/__tests__/render';
|
||||
|
||||
const originalOffsetHeight = Object.getOwnPropertyDescriptor(
|
||||
HTMLElement.prototype,
|
||||
'offsetHeight',
|
||||
) as PropertyDescriptor;
|
||||
|
||||
describe('WorkflowsView', () => {
|
||||
let server: ReturnType<typeof setupServer>;
|
||||
let pinia: ReturnType<typeof createPinia>;
|
||||
let settingsStore: ReturnType<typeof useSettingsStore>;
|
||||
let usersStore: ReturnType<typeof useUsersStore>;
|
||||
|
||||
const renderComponent = createComponentRenderer(WorkflowsView, {
|
||||
global: {
|
||||
mocks: {
|
||||
$route: {
|
||||
query: {},
|
||||
},
|
||||
$router: {
|
||||
replace: vi.fn(),
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
beforeAll(() => {
|
||||
Object.defineProperties(HTMLElement.prototype, {
|
||||
offsetHeight: {
|
||||
get() {
|
||||
return this.getAttribute('data-test-id') === 'resources-list' ? 1000 : 100;
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
server = setupServer();
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
Object.defineProperty(HTMLElement.prototype, 'offsetHeight', originalOffsetHeight);
|
||||
});
|
||||
|
||||
beforeEach(async () => {
|
||||
pinia = createPinia();
|
||||
setActivePinia(pinia);
|
||||
|
||||
settingsStore = useSettingsStore();
|
||||
usersStore = useUsersStore();
|
||||
await settingsStore.getSettings();
|
||||
await usersStore.fetchUsers();
|
||||
await usersStore.loginWithCookie();
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
server.shutdown();
|
||||
});
|
||||
|
||||
it('should filter workflows by tags', async () => {
|
||||
const { container, getByTestId, getAllByTestId, queryByTestId } = renderComponent({
|
||||
pinia,
|
||||
});
|
||||
|
||||
expect(container.querySelectorAll('.n8n-loading')).toHaveLength(3);
|
||||
expect(queryByTestId('resources-list')).not.toBeInTheDocument();
|
||||
|
||||
await waitFor(() => {
|
||||
expect(container.querySelectorAll('.n8n-loading')).toHaveLength(0);
|
||||
// There are 5 workflows defined in server fixtures
|
||||
expect(getAllByTestId('resources-list-item')).toHaveLength(5);
|
||||
});
|
||||
|
||||
await userEvent.click(
|
||||
getAllByTestId('resources-list-item')[0].querySelector('.n8n-tag') as HTMLElement,
|
||||
);
|
||||
await waitFor(() => {
|
||||
expect(getAllByTestId('resources-list-item').length).toBeLessThan(5);
|
||||
});
|
||||
|
||||
await userEvent.click(getByTestId('workflows-filter-reset'));
|
||||
await waitFor(() => {
|
||||
expect(getAllByTestId('resources-list-item')).toHaveLength(5);
|
||||
});
|
||||
|
||||
await userEvent.click(
|
||||
getAllByTestId('resources-list-item')[3].querySelector('.n8n-tag') as HTMLElement,
|
||||
);
|
||||
await waitFor(() => {
|
||||
expect(getAllByTestId('resources-list-item').length).toBeLessThan(5);
|
||||
});
|
||||
});
|
||||
});
|
Loading…
Reference in a new issue