mirror of
https://github.com/n8n-io/n8n.git
synced 2025-03-05 20:50:17 -08:00
test: fix most unit tests
This commit is contained in:
parent
964811243c
commit
206289a7b0
|
@ -1,6 +1,6 @@
|
|||
<script lang="ts" setup>
|
||||
import { computed, ref } from 'vue';
|
||||
import { uid } from '@/utils';
|
||||
import { uid } from '../../utils';
|
||||
import { ElColorPicker } from 'element-plus';
|
||||
import N8nInput from '../N8nInput';
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
<slot name="prepend" />
|
||||
</div>
|
||||
<el-select
|
||||
v-bind="{ ...$props, ...$attrs }"
|
||||
v-bind="{ ...$props, ...listeners }"
|
||||
:modelValue="modelValue"
|
||||
:size="computedSize"
|
||||
:class="$style[classes]"
|
||||
|
@ -92,6 +92,15 @@ export default defineComponent({
|
|||
},
|
||||
},
|
||||
computed: {
|
||||
listeners() {
|
||||
return Object.entries(this.$attrs).reduce<Record<string, () => {}>>((acc, [key, value]) => {
|
||||
if (/^on[A-Z]/.test(key)) {
|
||||
acc[key] = value;
|
||||
}
|
||||
|
||||
return acc;
|
||||
}, {});
|
||||
},
|
||||
computedSize(): string | undefined {
|
||||
if (this.size === 'medium') {
|
||||
return 'default';
|
||||
|
|
85
packages/editor-ui/src/__tests__/render.ts
Normal file
85
packages/editor-ui/src/__tests__/render.ts
Normal file
|
@ -0,0 +1,85 @@
|
|||
import type { Plugin } from 'vue';
|
||||
import { render } from '@testing-library/vue';
|
||||
import { i18nInstance, I18nPlugin } from '@/plugins/i18n';
|
||||
import { GlobalComponentsPlugin } from '@/plugins/components';
|
||||
import { GlobalDirectivesPlugin } from '@/plugins/directives';
|
||||
import { FontAwesomePlugin } from '@/plugins/icons';
|
||||
import { PiniaVuePlugin } from 'pinia';
|
||||
import type { Telemetry } from '@/plugins/telemetry';
|
||||
import vueJsonPretty from 'vue-json-pretty';
|
||||
import { merge } from 'lodash-es';
|
||||
import type { TestingPinia } from '@pinia/testing';
|
||||
|
||||
export type RenderComponent = Parameters<typeof render>[0];
|
||||
export type RenderOptions = Parameters<typeof render>[1] & {
|
||||
pinia?: TestingPinia;
|
||||
};
|
||||
|
||||
const TelemetryPlugin: Plugin<{}> = {
|
||||
install(app) {
|
||||
app.config.globalProperties.$telemetry = {
|
||||
track(event: string, properties?: object) {},
|
||||
} as Telemetry;
|
||||
},
|
||||
};
|
||||
|
||||
const defaultOptions = {
|
||||
global: {
|
||||
stubs: {
|
||||
'router-link': true,
|
||||
'vue-json-pretty': vueJsonPretty,
|
||||
},
|
||||
plugins: [
|
||||
I18nPlugin,
|
||||
i18nInstance,
|
||||
PiniaVuePlugin,
|
||||
FontAwesomePlugin,
|
||||
GlobalComponentsPlugin,
|
||||
GlobalDirectivesPlugin,
|
||||
TelemetryPlugin,
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
export function renderComponent(component: RenderComponent, options: RenderOptions = {}) {
|
||||
const { pinia, ...renderOptions } = options;
|
||||
|
||||
return render(component, {
|
||||
...defaultOptions,
|
||||
...renderOptions,
|
||||
global: {
|
||||
...defaultOptions.global,
|
||||
...renderOptions.global,
|
||||
stubs: { ...defaultOptions.global.stubs, ...(renderOptions.global?.stubs ?? {}) },
|
||||
plugins: [
|
||||
...defaultOptions.global.plugins,
|
||||
...(renderOptions.global?.plugins ?? []),
|
||||
...(pinia ? [pinia] : []),
|
||||
],
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export function createComponentRenderer(
|
||||
component: RenderComponent,
|
||||
defaultOptions: RenderOptions = {},
|
||||
) {
|
||||
return (options: RenderOptions = {}, rendererOptions: { merge?: boolean } = {}) =>
|
||||
renderComponent(
|
||||
component,
|
||||
rendererOptions.merge
|
||||
? merge(defaultOptions, options)
|
||||
: {
|
||||
...defaultOptions,
|
||||
...options,
|
||||
props: {
|
||||
...defaultOptions.props,
|
||||
...options.props,
|
||||
},
|
||||
global: {
|
||||
...defaultOptions.global,
|
||||
...options.global,
|
||||
},
|
||||
},
|
||||
);
|
||||
}
|
|
@ -1,27 +1,8 @@
|
|||
import '@testing-library/jest-dom';
|
||||
import { configure } from '@testing-library/vue';
|
||||
import '../plugins';
|
||||
import { I18nPlugin } from '@/plugins/i18n';
|
||||
import { config } from '@vue/test-utils';
|
||||
import { GlobalComponentsPlugin } from '@/plugins/components';
|
||||
import { GlobalDirectivesPlugin } from '@/plugins/directives';
|
||||
import { FontAwesomePlugin } from '@/plugins/icons';
|
||||
|
||||
configure({ testIdAttribute: 'data-test-id' });
|
||||
|
||||
// Vue.config.productionTip = false;
|
||||
// Vue.config.devtools = false;
|
||||
|
||||
config.plugins.VueWrapper.install(I18nPlugin);
|
||||
config.plugins.VueWrapper.install(FontAwesomePlugin);
|
||||
config.plugins.VueWrapper.install(GlobalComponentsPlugin);
|
||||
config.plugins.VueWrapper.install(GlobalDirectivesPlugin);
|
||||
|
||||
// TODO: Investigate why this is needed
|
||||
// Without having this 3rd party library imported like this, any component test using 'vue-json-pretty' fail with:
|
||||
// [Vue warn]: Failed to mount component: template or render function not defined.
|
||||
config.stubs['vue-json-pretty'] = require('vue-json-pretty').default;
|
||||
|
||||
window.ResizeObserver =
|
||||
window.ResizeObserver ||
|
||||
vi.fn().mockImplementation(() => ({
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import type { ISettingsState } from '@/Interface';
|
||||
import { UserManagementAuthenticationMethod } from '@/Interface';
|
||||
import { render } from '@testing-library/vue';
|
||||
import { PiniaVuePlugin } from 'pinia';
|
||||
|
||||
export const retry = async (assertion: () => any, { interval = 20, timeout = 1000 } = {}) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
|
@ -23,9 +22,7 @@ export const retry = async (assertion: () => any, { interval = 20, timeout = 100
|
|||
|
||||
type RenderParams = Parameters<typeof render>;
|
||||
export const renderComponent = (Component: RenderParams[0], renderOptions: RenderParams[1] = {}) =>
|
||||
render(Component, renderOptions, (vue) => {
|
||||
vue.use(PiniaVuePlugin);
|
||||
});
|
||||
render(Component, renderOptions);
|
||||
|
||||
export const waitAllPromises = async () => new Promise((resolve) => setTimeout(resolve));
|
||||
|
||||
|
|
|
@ -56,7 +56,7 @@
|
|||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
import { mapStores } from 'pinia';
|
||||
import { createEventBus } from 'n8n-design-system';
|
||||
import { createEventBus } from 'n8n-design-system/utils';
|
||||
import Modal from './Modal.vue';
|
||||
import { ABOUT_MODAL_KEY } from '../constants';
|
||||
import { useSettingsStore } from '@/stores/settings.store';
|
||||
|
|
|
@ -37,7 +37,7 @@
|
|||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
import { mapStores } from 'pinia';
|
||||
import { createEventBus } from 'n8n-design-system';
|
||||
import { createEventBus } from 'n8n-design-system/utils';
|
||||
|
||||
import Modal from '@/components/Modal.vue';
|
||||
import {
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
import { defineComponent } from 'vue';
|
||||
import Modal from './Modal.vue';
|
||||
import { ASK_AI_MODAL_KEY, ASK_AI_WAITLIST_URL } from '../constants';
|
||||
import { createEventBus } from 'n8n-design-system';
|
||||
import { createEventBus } from 'n8n-design-system/utils';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'AskAI',
|
||||
|
|
|
@ -37,7 +37,7 @@ import type { IFormInputs } from '@/Interface';
|
|||
import { CHANGE_PASSWORD_MODAL_KEY } from '@/constants';
|
||||
import { mapStores } from 'pinia';
|
||||
import { useUsersStore } from '@/stores/users.store';
|
||||
import { createEventBus } from 'n8n-design-system';
|
||||
import { createEventBus } from 'n8n-design-system/utils';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'ChangePasswordModal',
|
||||
|
|
|
@ -91,7 +91,7 @@
|
|||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
import { mapStores } from 'pinia';
|
||||
import { createEventBus } from 'n8n-design-system';
|
||||
import { createEventBus } from 'n8n-design-system/utils';
|
||||
import Modal from '@/components/Modal.vue';
|
||||
import {
|
||||
COMMUNITY_PACKAGE_INSTALL_MODAL_KEY,
|
||||
|
|
|
@ -39,7 +39,7 @@ import { COMMUNITY_PACKAGE_CONFIRM_MODAL_KEY, COMMUNITY_PACKAGE_MANAGE_ACTIONS }
|
|||
import { useToast } from '@/composables';
|
||||
import { mapStores } from 'pinia';
|
||||
import { useCommunityNodesStore } from '@/stores/communityNodes.store';
|
||||
import { createEventBus } from 'n8n-design-system';
|
||||
import { createEventBus } from 'n8n-design-system/utils';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'CommunityPackageManageConfirmModal',
|
||||
|
|
|
@ -41,7 +41,7 @@ import { workflowHelpers } from '@/mixins/workflowHelpers';
|
|||
import Modal from '@/components/Modal.vue';
|
||||
import { useSettingsStore } from '@/stores/settings.store';
|
||||
import { useRootStore } from '@/stores/n8nRoot.store';
|
||||
import { createEventBus } from 'n8n-design-system';
|
||||
import { createEventBus } from 'n8n-design-system/utils';
|
||||
import { useToast } from '@/composables';
|
||||
|
||||
export default defineComponent({
|
||||
|
|
|
@ -144,7 +144,7 @@ import FeatureComingSoon from '@/components/FeatureComingSoon.vue';
|
|||
import type { IPermissions } from '@/permissions';
|
||||
import { getCredentialPermissions } from '@/permissions';
|
||||
import type { IMenuItem } from 'n8n-design-system';
|
||||
import { createEventBus } from 'n8n-design-system';
|
||||
import { createEventBus } from 'n8n-design-system/utils';
|
||||
import { useUIStore } from '@/stores/ui.store';
|
||||
import { useSettingsStore } from '@/stores/settings.store';
|
||||
import { useUsersStore } from '@/stores/users.store';
|
||||
|
|
|
@ -66,7 +66,7 @@ import { mapStores } from 'pinia';
|
|||
import { useUIStore } from '@/stores/ui.store';
|
||||
import { useWorkflowsStore } from '@/stores/workflows.store';
|
||||
import { useCredentialsStore } from '@/stores/credentials.store';
|
||||
import { createEventBus } from 'n8n-design-system';
|
||||
import { createEventBus } from 'n8n-design-system/utils';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'CredentialsSelectModal',
|
||||
|
|
|
@ -84,7 +84,7 @@ import Modal from '@/components/Modal.vue';
|
|||
import type { IUser } from '@/Interface';
|
||||
import { mapStores } from 'pinia';
|
||||
import { useUsersStore } from '@/stores/users.store';
|
||||
import { createEventBus } from 'n8n-design-system';
|
||||
import { createEventBus } from 'n8n-design-system/utils';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'DeleteUserModal',
|
||||
|
|
|
@ -62,7 +62,7 @@ import type { IWorkflowDataUpdate } from '@/Interface';
|
|||
import type { IPermissions } from '@/permissions';
|
||||
import { getWorkflowPermissions } from '@/permissions';
|
||||
import { useUsersStore } from '@/stores/users.store';
|
||||
import { createEventBus } from 'n8n-design-system';
|
||||
import { createEventBus } from 'n8n-design-system/utils';
|
||||
import { useCredentialsStore } from '@/stores';
|
||||
|
||||
export default defineComponent({
|
||||
|
|
|
@ -19,6 +19,7 @@ import type { Placement } from '@floating-ui/core';
|
|||
export type ExecutionFilterProps = {
|
||||
workflows?: IWorkflowShortResponse[];
|
||||
popoverPlacement?: Placement;
|
||||
teleported?: boolean;
|
||||
};
|
||||
|
||||
const DATE_TIME_MASK = 'YYYY-MM-DD HH:mm';
|
||||
|
@ -31,6 +32,7 @@ const telemetry = useTelemetry();
|
|||
|
||||
const props = withDefaults(defineProps<ExecutionFilterProps>(), {
|
||||
popoverPlacement: 'bottom' as Placement,
|
||||
teleported: true,
|
||||
});
|
||||
const emit = defineEmits<{
|
||||
(event: 'filterChanged', value: ExecutionFilterType): void;
|
||||
|
@ -165,7 +167,7 @@ onBeforeMount(() => {
|
|||
</n8n-button>
|
||||
</template>
|
||||
<div data-test-id="execution-filter-form">
|
||||
<div v-if="workflows?.length" :class="$style.group">
|
||||
<div v-if="workflows && workflows.length > 0" :class="$style.group">
|
||||
<label for="execution-filter-workflows">{{ locale.baseText('workflows.heading') }}</label>
|
||||
<n8n-select
|
||||
id="execution-filter-workflows"
|
||||
|
@ -173,6 +175,7 @@ onBeforeMount(() => {
|
|||
:placeholder="locale.baseText('executionsFilter.selectWorkflow')"
|
||||
filterable
|
||||
data-test-id="executions-filter-workflows-select"
|
||||
:teleported="teleported"
|
||||
>
|
||||
<div class="ph-no-capture">
|
||||
<n8n-option
|
||||
|
@ -205,6 +208,7 @@ onBeforeMount(() => {
|
|||
:placeholder="locale.baseText('executionsFilter.selectStatus')"
|
||||
filterable
|
||||
data-test-id="executions-filter-status-select"
|
||||
:teleported="teleported"
|
||||
>
|
||||
<n8n-option
|
||||
v-for="(item, idx) in statuses"
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
@update:modelValue="handleAutoRefreshToggle"
|
||||
data-test-id="execution-auto-refresh-checkbox"
|
||||
>
|
||||
{{ $locale.baseText('executionsList.autoRefresh') }}
|
||||
{{ i18n.baseText('executionsList.autoRefresh') }}
|
||||
</el-checkbox>
|
||||
<execution-filter
|
||||
v-show="!isMounting"
|
||||
|
@ -26,7 +26,7 @@
|
|||
v-if="allVisibleSelected && finishedExecutionsCount > 0"
|
||||
:class="$style.selectAll"
|
||||
:label="
|
||||
$locale.baseText('executionsList.selectAll', {
|
||||
i18n.baseText('executionsList.selectAll', {
|
||||
adjustToNumber: finishedExecutionsCount,
|
||||
interpolate: { executionNum: finishedExecutionsCount },
|
||||
})
|
||||
|
@ -53,10 +53,10 @@
|
|||
data-test-id="select-visible-executions-checkbox"
|
||||
/>
|
||||
</th>
|
||||
<th>{{ $locale.baseText('executionsList.name') }}</th>
|
||||
<th>{{ $locale.baseText('executionsList.startedAt') }}</th>
|
||||
<th>{{ $locale.baseText('executionsList.status') }}</th>
|
||||
<th>{{ $locale.baseText('executionsList.id') }}</th>
|
||||
<th>{{ i18n.baseText('executionsList.name') }}</th>
|
||||
<th>{{ i18n.baseText('executionsList.startedAt') }}</th>
|
||||
<th>{{ i18n.baseText('executionsList.status') }}</th>
|
||||
<th>{{ i18n.baseText('executionsList.id') }}</th>
|
||||
<th></th>
|
||||
<th></th>
|
||||
<th></th>
|
||||
|
@ -81,7 +81,7 @@
|
|||
<td>
|
||||
<span class="ph-no-capture" @click.stop="displayExecution(execution)"
|
||||
><a href="#" :class="$style.link">{{
|
||||
execution.workflowName || $locale.baseText('executionsList.unsavedWorkflow')
|
||||
execution.workflowName || i18n.baseText('executionsList.unsavedWorkflow')
|
||||
}}</a></span
|
||||
>
|
||||
</td>
|
||||
|
@ -130,13 +130,13 @@
|
|||
<span v-if="execution.retryOf">
|
||||
<br />
|
||||
<small>
|
||||
({{ $locale.baseText('executionsList.retryOf') }} #{{ execution.retryOf }})
|
||||
({{ i18n.baseText('executionsList.retryOf') }} #{{ execution.retryOf }})
|
||||
</small>
|
||||
</span>
|
||||
<span v-else-if="execution.retrySuccessId">
|
||||
<br />
|
||||
<small>
|
||||
({{ $locale.baseText('executionsList.successRetry') }} #{{
|
||||
({{ i18n.baseText('executionsList.successRetry') }} #{{
|
||||
execution.retrySuccessId
|
||||
}})
|
||||
</small>
|
||||
|
@ -145,7 +145,7 @@
|
|||
<td>
|
||||
<n8n-tooltip v-if="execution.mode === 'manual'" placement="top">
|
||||
<template #content>
|
||||
<span>{{ $locale.baseText('executionsList.test') }}</span>
|
||||
<span>{{ i18n.baseText('executionsList.test') }}</span>
|
||||
</template>
|
||||
<font-awesome-icon icon="flask" />
|
||||
</n8n-tooltip>
|
||||
|
@ -156,7 +156,7 @@
|
|||
v-if="execution.stoppedAt !== undefined && execution.id"
|
||||
size="small"
|
||||
outline
|
||||
:label="$locale.baseText('executionsList.view')"
|
||||
:label="i18n.baseText('executionsList.view')"
|
||||
@click.stop="displayExecution(execution)"
|
||||
/>
|
||||
</div>
|
||||
|
@ -167,7 +167,7 @@
|
|||
v-if="execution.stoppedAt === undefined || execution.waitTill"
|
||||
size="small"
|
||||
outline
|
||||
:label="$locale.baseText('executionsList.stop')"
|
||||
:label="i18n.baseText('executionsList.stop')"
|
||||
@click.stop="stopExecution(execution.id)"
|
||||
:loading="stoppingExecutions.includes(execution.id)"
|
||||
/>
|
||||
|
@ -184,7 +184,7 @@
|
|||
text
|
||||
type="tertiary"
|
||||
size="mini"
|
||||
:title="$locale.baseText('executionsList.retryExecution')"
|
||||
:title="i18n.baseText('executionsList.retryExecution')"
|
||||
icon="ellipsis-v"
|
||||
/>
|
||||
</span>
|
||||
|
@ -200,20 +200,20 @@
|
|||
:class="$style.retryAction"
|
||||
:command="{ command: 'currentlySaved', execution }"
|
||||
>
|
||||
{{ $locale.baseText('executionsList.retryWithCurrentlySavedWorkflow') }}
|
||||
{{ i18n.baseText('executionsList.retryWithCurrentlySavedWorkflow') }}
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item
|
||||
v-if="isExecutionRetriable(execution)"
|
||||
:class="$style.retryAction"
|
||||
:command="{ command: 'original', execution }"
|
||||
>
|
||||
{{ $locale.baseText('executionsList.retryWithOriginalWorkflow') }}
|
||||
{{ i18n.baseText('executionsList.retryWithOriginalWorkflow') }}
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item
|
||||
:class="$style.deleteAction"
|
||||
:command="{ command: 'delete', execution }"
|
||||
>
|
||||
{{ $locale.baseText('generic.delete') }}
|
||||
{{ i18n.baseText('generic.delete') }}
|
||||
</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
|
@ -228,7 +228,7 @@
|
|||
:class="$style.loadedAll"
|
||||
data-test-id="execution-list-empty"
|
||||
>
|
||||
{{ $locale.baseText('executionsList.empty') }}
|
||||
{{ i18n.baseText('executionsList.empty') }}
|
||||
</div>
|
||||
<div
|
||||
:class="$style.loadMore"
|
||||
|
@ -238,8 +238,8 @@
|
|||
>
|
||||
<n8n-button
|
||||
icon="sync"
|
||||
:title="$locale.baseText('executionsList.loadMore')"
|
||||
:label="$locale.baseText('executionsList.loadMore')"
|
||||
:title="i18n.baseText('executionsList.loadMore')"
|
||||
:label="i18n.baseText('executionsList.loadMore')"
|
||||
@click="loadMore()"
|
||||
:loading="isDataLoading"
|
||||
data-test-id="load-more-button"
|
||||
|
@ -250,7 +250,7 @@
|
|||
:class="$style.loadedAll"
|
||||
data-test-id="execution-all-loaded"
|
||||
>
|
||||
{{ $locale.baseText('executionsList.loadedAll') }}
|
||||
{{ i18n.baseText('executionsList.loadedAll') }}
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
|
@ -260,20 +260,20 @@
|
|||
>
|
||||
<span>
|
||||
{{
|
||||
$locale.baseText('executionsList.selected', {
|
||||
i18n.baseText('executionsList.selected', {
|
||||
adjustToNumber: numSelected,
|
||||
interpolate: { numSelected },
|
||||
})
|
||||
}}
|
||||
</span>
|
||||
<n8n-button
|
||||
:label="$locale.baseText('generic.delete')"
|
||||
:label="i18n.baseText('generic.delete')"
|
||||
type="tertiary"
|
||||
@click="handleDeleteSelected"
|
||||
data-test-id="delete-selected-button"
|
||||
/>
|
||||
<n8n-button
|
||||
:label="$locale.baseText('executionsList.clearSelection')"
|
||||
:label="i18n.baseText('executionsList.clearSelection')"
|
||||
type="tertiary"
|
||||
@click="handleClearSelection"
|
||||
data-test-id="clear-selection-button"
|
||||
|
@ -291,7 +291,7 @@ import { externalHooks } from '@/mixins/externalHooks';
|
|||
import { MODAL_CONFIRM, VIEWS, WAIT_TIME_UNLIMITED } from '@/constants';
|
||||
import { genericHelpers } from '@/mixins/genericHelpers';
|
||||
import { executionHelpers } from '@/mixins/executionsHelpers';
|
||||
import { useToast, useMessage } from '@/composables';
|
||||
import { useToast, useMessage, useI18n, useTelemetry } from '@/composables';
|
||||
import type {
|
||||
IExecutionsCurrentSummaryExtended,
|
||||
IExecutionDeleteFilter,
|
||||
|
@ -321,7 +321,12 @@ export default defineComponent({
|
|||
},
|
||||
},
|
||||
setup() {
|
||||
const i18n = useI18n();
|
||||
const telemetry = useTelemetry();
|
||||
|
||||
return {
|
||||
i18n,
|
||||
telemetry,
|
||||
...useToast(),
|
||||
...useMessage(),
|
||||
};
|
||||
|
@ -360,7 +365,7 @@ export default defineComponent({
|
|||
await this.loadWorkflows();
|
||||
|
||||
void this.$externalHooks().run('executionsList.openDialog');
|
||||
this.$telemetry.track('User opened Executions log', {
|
||||
this.telemetry.track('User opened Executions log', {
|
||||
workflow_id: this.workflowsStore.workflowId,
|
||||
});
|
||||
},
|
||||
|
@ -406,7 +411,7 @@ export default defineComponent({
|
|||
return executionFilterToQueryFilter(this.filter);
|
||||
},
|
||||
pageTitle() {
|
||||
return this.$locale.baseText('executionsList.workflowExecutions');
|
||||
return this.i18n.baseText('executionsList.workflowExecutions');
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
|
@ -456,16 +461,14 @@ export default defineComponent({
|
|||
},
|
||||
async handleDeleteSelected() {
|
||||
const deleteExecutions = await this.confirm(
|
||||
this.$locale.baseText('executionsList.confirmMessage.message', {
|
||||
this.i18n.baseText('executionsList.confirmMessage.message', {
|
||||
interpolate: { numSelected: this.numSelected.toString() },
|
||||
}),
|
||||
this.$locale.baseText('executionsList.confirmMessage.headline'),
|
||||
this.i18n.baseText('executionsList.confirmMessage.headline'),
|
||||
{
|
||||
type: 'warning',
|
||||
confirmButtonText: this.$locale.baseText(
|
||||
'executionsList.confirmMessage.confirmButtonText',
|
||||
),
|
||||
cancelButtonText: this.$locale.baseText('executionsList.confirmMessage.cancelButtonText'),
|
||||
confirmButtonText: this.i18n.baseText('executionsList.confirmMessage.confirmButtonText'),
|
||||
cancelButtonText: this.i18n.baseText('executionsList.confirmMessage.cancelButtonText'),
|
||||
},
|
||||
);
|
||||
|
||||
|
@ -490,7 +493,7 @@ export default defineComponent({
|
|||
this.isDataLoading = false;
|
||||
this.showError(
|
||||
error,
|
||||
this.$locale.baseText('executionsList.showError.handleDeleteSelected.title'),
|
||||
this.i18n.baseText('executionsList.showError.handleDeleteSelected.title'),
|
||||
);
|
||||
|
||||
return;
|
||||
|
@ -498,7 +501,7 @@ export default defineComponent({
|
|||
this.isDataLoading = false;
|
||||
|
||||
this.showMessage({
|
||||
title: this.$locale.baseText('executionsList.showMessage.handleDeleteSelected.title'),
|
||||
title: this.i18n.baseText('executionsList.showMessage.handleDeleteSelected.title'),
|
||||
type: 'success',
|
||||
});
|
||||
|
||||
|
@ -525,7 +528,7 @@ export default defineComponent({
|
|||
|
||||
await this.retryExecution(commandData.execution, loadWorkflow);
|
||||
|
||||
this.$telemetry.track('User clicked retry execution button', {
|
||||
this.telemetry.track('User clicked retry execution button', {
|
||||
workflow_id: this.workflowsStore.workflowId,
|
||||
execution_id: commandData.execution.id,
|
||||
retry_type: loadWorkflow ? 'current' : 'original',
|
||||
|
@ -691,7 +694,7 @@ export default defineComponent({
|
|||
);
|
||||
} catch (error) {
|
||||
this.isDataLoading = false;
|
||||
this.showError(error, this.$locale.baseText('executionsList.showError.loadMore.title'));
|
||||
this.showError(error, this.i18n.baseText('executionsList.showError.loadMore.title'));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -726,15 +729,12 @@ export default defineComponent({
|
|||
|
||||
workflows.unshift({
|
||||
id: 'all',
|
||||
name: this.$locale.baseText('executionsList.allWorkflows'),
|
||||
name: this.i18n.baseText('executionsList.allWorkflows'),
|
||||
} as IWorkflowShortResponse);
|
||||
|
||||
this.workflows = workflows;
|
||||
} catch (error) {
|
||||
this.showError(
|
||||
error,
|
||||
this.$locale.baseText('executionsList.showError.loadWorkflows.title'),
|
||||
);
|
||||
this.showError(error, this.i18n.baseText('executionsList.showError.loadWorkflows.title'));
|
||||
}
|
||||
},
|
||||
async retryExecution(execution: IExecutionsSummary, loadWorkflow?: boolean) {
|
||||
|
@ -748,22 +748,19 @@ export default defineComponent({
|
|||
|
||||
if (retrySuccessful) {
|
||||
this.showMessage({
|
||||
title: this.$locale.baseText('executionsList.showMessage.retrySuccessfulTrue.title'),
|
||||
title: this.i18n.baseText('executionsList.showMessage.retrySuccessfulTrue.title'),
|
||||
type: 'success',
|
||||
});
|
||||
} else {
|
||||
this.showMessage({
|
||||
title: this.$locale.baseText('executionsList.showMessage.retrySuccessfulFalse.title'),
|
||||
title: this.i18n.baseText('executionsList.showMessage.retrySuccessfulFalse.title'),
|
||||
type: 'error',
|
||||
});
|
||||
}
|
||||
|
||||
this.isDataLoading = false;
|
||||
} catch (error) {
|
||||
this.showError(
|
||||
error,
|
||||
this.$locale.baseText('executionsList.showError.retryExecution.title'),
|
||||
);
|
||||
this.showError(error, this.i18n.baseText('executionsList.showError.retryExecution.title'));
|
||||
|
||||
this.isDataLoading = false;
|
||||
}
|
||||
|
@ -774,7 +771,7 @@ export default defineComponent({
|
|||
try {
|
||||
await Promise.all([this.loadActiveExecutions(), this.loadFinishedExecutions()]);
|
||||
} catch (error) {
|
||||
this.showError(error, this.$locale.baseText('executionsList.showError.refreshData.title'));
|
||||
this.showError(error, this.i18n.baseText('executionsList.showError.refreshData.title'));
|
||||
}
|
||||
|
||||
this.isDataLoading = false;
|
||||
|
@ -807,21 +804,21 @@ export default defineComponent({
|
|||
let text = '';
|
||||
|
||||
if (status === 'waiting') {
|
||||
text = this.$locale.baseText('executionsList.waiting');
|
||||
text = this.i18n.baseText('executionsList.waiting');
|
||||
} else if (status === 'canceled') {
|
||||
text = this.$locale.baseText('executionsList.canceled');
|
||||
text = this.i18n.baseText('executionsList.canceled');
|
||||
} else if (status === 'crashed') {
|
||||
text = this.$locale.baseText('executionsList.error');
|
||||
text = this.i18n.baseText('executionsList.error');
|
||||
} else if (status === 'new') {
|
||||
text = this.$locale.baseText('executionsList.running');
|
||||
text = this.i18n.baseText('executionsList.running');
|
||||
} else if (status === 'running') {
|
||||
text = this.$locale.baseText('executionsList.running');
|
||||
text = this.i18n.baseText('executionsList.running');
|
||||
} else if (status === 'success') {
|
||||
text = this.$locale.baseText('executionsList.succeeded');
|
||||
text = this.i18n.baseText('executionsList.succeeded');
|
||||
} else if (status === 'failed') {
|
||||
text = this.$locale.baseText('executionsList.error');
|
||||
text = this.i18n.baseText('executionsList.error');
|
||||
} else {
|
||||
text = this.$locale.baseText('executionsList.unknown');
|
||||
text = this.i18n.baseText('executionsList.unknown');
|
||||
}
|
||||
|
||||
return text;
|
||||
|
@ -855,7 +852,7 @@ export default defineComponent({
|
|||
let text = '';
|
||||
|
||||
if (status === 'waiting' && this.isWaitTillIndefinite(entry)) {
|
||||
text = this.$locale.baseText(
|
||||
text = this.i18n.baseText(
|
||||
'executionsList.statusTooltipText.theWorkflowIsWaitingIndefinitely',
|
||||
);
|
||||
}
|
||||
|
@ -875,8 +872,8 @@ export default defineComponent({
|
|||
this.stoppingExecutions.splice(index, 1);
|
||||
|
||||
this.showMessage({
|
||||
title: this.$locale.baseText('executionsList.showMessage.stopExecution.title'),
|
||||
message: this.$locale.baseText('executionsList.showMessage.stopExecution.message', {
|
||||
title: this.i18n.baseText('executionsList.showMessage.stopExecution.title'),
|
||||
message: this.i18n.baseText('executionsList.showMessage.stopExecution.message', {
|
||||
interpolate: { activeExecutionId },
|
||||
}),
|
||||
type: 'success',
|
||||
|
@ -884,10 +881,7 @@ export default defineComponent({
|
|||
|
||||
await this.refreshData();
|
||||
} catch (error) {
|
||||
this.showError(
|
||||
error,
|
||||
this.$locale.baseText('executionsList.showError.stopExecution.title'),
|
||||
);
|
||||
this.showError(error, this.i18n.baseText('executionsList.showError.stopExecution.title'));
|
||||
}
|
||||
},
|
||||
isExecutionRetriable(execution: IExecutionsSummary): boolean {
|
||||
|
@ -912,7 +906,7 @@ export default defineComponent({
|
|||
} catch (error) {
|
||||
this.showError(
|
||||
error,
|
||||
this.$locale.baseText('executionsList.showError.handleDeleteSelected.title'),
|
||||
this.i18n.baseText('executionsList.showError.handleDeleteSelected.title'),
|
||||
);
|
||||
}
|
||||
this.isDataLoading = true;
|
||||
|
|
|
@ -11,7 +11,7 @@ import { defineComponent } from 'vue';
|
|||
import ExecutionsList from '@/components/ExecutionsList.vue';
|
||||
import Modal from '@/components/Modal.vue';
|
||||
import { EXECUTIONS_MODAL_KEY } from '@/constants';
|
||||
import { createEventBus } from 'n8n-design-system';
|
||||
import { createEventBus } from 'n8n-design-system/utils';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'ExecutionsModal',
|
||||
|
|
|
@ -52,7 +52,7 @@ import type { INodeUi } from '@/Interface';
|
|||
import { mapStores } from 'pinia';
|
||||
import { useUIStore } from '@/stores/ui.store';
|
||||
import { useNDVStore } from '@/stores/ndv.store';
|
||||
import { createEventBus } from 'n8n-design-system';
|
||||
import { createEventBus } from 'n8n-design-system/utils';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'ImportCurlModal',
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
<template>
|
||||
<div :class="visible ? $style.dropdown : $style.hidden">
|
||||
<n8n-text size="small" compact :class="$style.header">
|
||||
{{ $locale.baseText('parameterInput.resultForItem') }} {{ hoveringItemNumber }}
|
||||
{{ i18n.baseText('parameterInput.resultForItem') }} {{ hoveringItemNumber }}
|
||||
</n8n-text>
|
||||
<n8n-text :class="$style.body">
|
||||
<div ref="root" class="ph-no-capture" data-test-id="inline-expression-editor-output"></div>
|
||||
</n8n-text>
|
||||
<div :class="$style.footer">
|
||||
<n8n-text size="small" compact>
|
||||
{{ $locale.baseText('parameterInput.anythingInside') }}
|
||||
{{ i18n.baseText('parameterInput.anythingInside') }}
|
||||
</n8n-text>
|
||||
<div :class="$style['expression-syntax-example']" v-text="`{{ }}`"></div>
|
||||
<n8n-text size="small" compact>
|
||||
{{ $locale.baseText('parameterInput.isJavaScript') }}
|
||||
{{ i18n.baseText('parameterInput.isJavaScript') }}
|
||||
</n8n-text>
|
||||
{{ ' ' }}
|
||||
<n8n-link
|
||||
|
@ -22,7 +22,7 @@
|
|||
theme="text"
|
||||
:to="expressionsDocsUrl"
|
||||
>
|
||||
{{ $locale.baseText('parameterInput.learnMore') }}
|
||||
{{ i18n.baseText('parameterInput.learnMore') }}
|
||||
</n8n-link>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -40,6 +40,7 @@ import { outputTheme } from './theme';
|
|||
|
||||
import type { Plaintext, Resolved, Segment } from '@/types/expressions';
|
||||
import { EXPRESSIONS_DOCS_URL } from '@/constants';
|
||||
import { useI18n } from '@/composables';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'InlineExpressionEditorOutput',
|
||||
|
@ -73,6 +74,13 @@ export default defineComponent({
|
|||
highlighter.removeColor(this.editor, this.plaintextSegments);
|
||||
},
|
||||
},
|
||||
setup() {
|
||||
const i18n = useI18n();
|
||||
|
||||
return {
|
||||
i18n,
|
||||
};
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
editor: null as EditorView | null,
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
import { defineComponent } from 'vue';
|
||||
import ExpandableInputEdit from '@/components/ExpandableInput/ExpandableInputEdit.vue';
|
||||
import ExpandableInputPreview from '@/components/ExpandableInput/ExpandableInputPreview.vue';
|
||||
import { createEventBus } from 'n8n-design-system';
|
||||
import { createEventBus } from 'n8n-design-system/utils';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'InlineTextEdit',
|
||||
|
|
|
@ -62,7 +62,7 @@ import { VALID_EMAIL_REGEX, INVITE_USER_MODAL_KEY } from '@/constants';
|
|||
import { ROLE } from '@/utils';
|
||||
import { useUsersStore } from '@/stores/users.store';
|
||||
import { useSettingsStore } from '@/stores/settings.store';
|
||||
import { createEventBus } from 'n8n-design-system';
|
||||
import { createEventBus } from 'n8n-design-system/utils';
|
||||
|
||||
const NAME_EMAIL_FORMAT_REGEX = /^.* <(.*)>$/;
|
||||
|
||||
|
|
|
@ -164,7 +164,7 @@ import {
|
|||
} from '@/stores';
|
||||
import type { IPermissions } from '@/permissions';
|
||||
import { getWorkflowPermissions } from '@/permissions';
|
||||
import { createEventBus } from 'n8n-design-system';
|
||||
import { createEventBus } from 'n8n-design-system/utils';
|
||||
import { useCloudPlanStore } from '@/stores';
|
||||
import { nodeViewEventBus } from '@/event-bus';
|
||||
|
||||
|
|
|
@ -3,7 +3,8 @@ import { computed, ref } from 'vue';
|
|||
import { useRouter } from 'vue-router';
|
||||
import { createEventBus } from 'n8n-design-system/utils';
|
||||
import { useI18n, useLoadingService, useMessage, useToast } from '@/composables';
|
||||
import { useUIStore, useSourceControlStore } from '@/stores';
|
||||
import { useUIStore } from '@/stores/ui.store';
|
||||
import { useSourceControlStore } from '@/stores/sourceControl.store';
|
||||
import { SOURCE_CONTROL_PULL_MODAL_KEY, SOURCE_CONTROL_PUSH_MODAL_KEY, VIEWS } from '@/constants';
|
||||
|
||||
const props = defineProps<{
|
||||
|
@ -20,7 +21,7 @@ const uiStore = useUIStore();
|
|||
const sourceControlStore = useSourceControlStore();
|
||||
const message = useMessage();
|
||||
const toast = useToast();
|
||||
const { i18n } = useI18n();
|
||||
const i18n = useI18n();
|
||||
|
||||
const eventBus = createEventBus();
|
||||
const tooltipOpenDelay = ref(300);
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
<p
|
||||
:class="$style.communityNodeIcon"
|
||||
v-html="
|
||||
$locale.baseText('generic.communityNode.tooltip', {
|
||||
i18n.baseText('generic.communityNode.tooltip', {
|
||||
interpolate: {
|
||||
packageName: nodeType.name.split('.')[0],
|
||||
docURL: COMMUNITY_NODES_INSTALLATION_DOCS_URL,
|
||||
|
@ -38,7 +38,7 @@
|
|||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed, ref, getCurrentInstance } from 'vue';
|
||||
import { computed, ref } from 'vue';
|
||||
import type { SimplifiedNodeType } from '@/Interface';
|
||||
import { COMMUNITY_NODES_INSTALLATION_DOCS_URL, DEFAULT_SUBCATEGORY } from '@/constants';
|
||||
|
||||
|
@ -48,6 +48,7 @@ import { useNodeCreatorStore } from '@/stores/nodeCreator.store';
|
|||
import NodeIcon from '@/components/NodeIcon.vue';
|
||||
|
||||
import { useActions } from '../composables/useActions';
|
||||
import { useI18n, useTelemetry } from '@/composables';
|
||||
|
||||
export interface Props {
|
||||
nodeType: SimplifiedNodeType;
|
||||
|
@ -59,16 +60,18 @@ const props = withDefaults(defineProps<Props>(), {
|
|||
active: false,
|
||||
});
|
||||
|
||||
const i18n = useI18n();
|
||||
const telemetry = useTelemetry();
|
||||
|
||||
const { actions } = useNodeCreatorStore();
|
||||
const { getNodeTypesWithManualTrigger } = useActions();
|
||||
const instance = getCurrentInstance();
|
||||
|
||||
const dragging = ref(false);
|
||||
const draggablePosition = ref({ x: -100, y: -100 });
|
||||
const draggableDataTransfer = ref(null as Element | null);
|
||||
|
||||
const description = computed<string>(() => {
|
||||
return instance?.proxy.$locale.headerText({
|
||||
return i18n.headerText({
|
||||
key: `headers.${shortNodeType.value}.description`,
|
||||
fallback: props.nodeType.description,
|
||||
}) as string;
|
||||
|
@ -84,9 +87,7 @@ const nodeActions = computed(() => {
|
|||
return nodeActions;
|
||||
});
|
||||
|
||||
const shortNodeType = computed<string>(
|
||||
() => instance?.proxy.$locale.shortNodeType(props.nodeType.name) || '',
|
||||
);
|
||||
const shortNodeType = computed<string>(() => i18n.shortNodeType(props.nodeType.name) || '');
|
||||
|
||||
const draggableStyle = computed<{ top: string; left: string }>(() => ({
|
||||
top: `${draggablePosition.value.y}px`,
|
||||
|
@ -99,7 +100,7 @@ const isCommunityNode = computed<boolean>(() => isCommunityPackageName(props.nod
|
|||
const displayName = computed<any>(() => {
|
||||
const displayName = props.nodeType.displayName.trimEnd();
|
||||
|
||||
return instance?.proxy.$locale.headerText({
|
||||
return i18n.headerText({
|
||||
key: `headers.${shortNodeType.value}.displayName`,
|
||||
fallback: hasActions.value ? displayName.replace('Trigger', '') : displayName,
|
||||
});
|
||||
|
@ -153,7 +154,7 @@ function onDragEnd(event: DragEvent): void {
|
|||
|
||||
function onCommunityNodeTooltipClick(event: MouseEvent) {
|
||||
if ((event.target as Element).localName === 'a') {
|
||||
instance?.proxy.$telemetry.track('user clicked cnr docs link', { source: 'nodes panel node' });
|
||||
telemetry.track('user clicked cnr docs link', { source: 'nodes panel node' });
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
<template>
|
||||
<n8n-node-creator-node
|
||||
:class="$style.subCategory"
|
||||
:title="$locale.baseText(`nodeCreator.subcategoryNames.${subcategoryName}`)"
|
||||
:title="i18n.baseText(`nodeCreator.subcategoryNames.${subcategoryName}`)"
|
||||
:isTrigger="false"
|
||||
:description="$locale.baseText(`nodeCreator.subcategoryDescriptions.${subcategoryName}`)"
|
||||
:description="i18n.baseText(`nodeCreator.subcategoryDescriptions.${subcategoryName}`)"
|
||||
:showActionArrow="true"
|
||||
>
|
||||
<template #icon>
|
||||
|
@ -16,11 +16,14 @@
|
|||
import type { SubcategoryItemProps } from '@/Interface';
|
||||
import { camelCase } from 'lodash-es';
|
||||
import { computed } from 'vue';
|
||||
import { useI18n } from '@/composables';
|
||||
|
||||
export interface Props {
|
||||
item: SubcategoryItemProps;
|
||||
}
|
||||
|
||||
const props = defineProps<Props>();
|
||||
const i18n = useI18n();
|
||||
const subcategoryName = computed(() => camelCase(props.item.subcategory || props.item.title));
|
||||
</script>
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<script setup lang="ts">
|
||||
import { camelCase } from 'lodash-es';
|
||||
import { getCurrentInstance, computed } from 'vue';
|
||||
import { computed } from 'vue';
|
||||
import type { INodeCreateElement, NodeFilterType } from '@/Interface';
|
||||
import { TRIGGER_NODE_CREATOR_VIEW, HTTP_REQUEST_NODE_TYPE, WEBHOOK_NODE_TYPE } from '@/constants';
|
||||
|
||||
|
@ -16,6 +16,7 @@ import { useKeyboardNavigation } from '../composables/useKeyboardNavigation';
|
|||
import ItemsRenderer from '../Renderers/ItemsRenderer.vue';
|
||||
import CategorizedItemsRenderer from '../Renderers/CategorizedItemsRenderer.vue';
|
||||
import NoResults from '../Panel/NoResults.vue';
|
||||
import { useI18n, useTelemetry } from '@/composables';
|
||||
|
||||
export interface Props {
|
||||
rootView: 'trigger' | 'action';
|
||||
|
@ -25,7 +26,9 @@ const emit = defineEmits({
|
|||
nodeTypeSelected: (nodeTypes: string[]) => true,
|
||||
});
|
||||
|
||||
const instance = getCurrentInstance();
|
||||
const i18n = useI18n();
|
||||
const telemetry = useTelemetry();
|
||||
|
||||
const { mergedNodes, actions } = useNodeCreatorStore();
|
||||
const { baseUrl } = useRootStore();
|
||||
const { getNodeTypesWithManualTrigger } = useActions();
|
||||
|
@ -45,7 +48,7 @@ function selectNodeType(nodeTypes: string[]) {
|
|||
|
||||
function onSelected(item: INodeCreateElement) {
|
||||
if (item.type === 'subcategory') {
|
||||
const title = instance?.proxy.$locale.baseText(
|
||||
const title = i18n.baseText(
|
||||
`nodeCreator.subcategoryNames.${camelCase(item.properties.title)}` as BaseTextKey,
|
||||
);
|
||||
|
||||
|
@ -59,7 +62,7 @@ function onSelected(item: INodeCreateElement) {
|
|||
itemsMapper: subcategoriesMapper,
|
||||
});
|
||||
|
||||
instance?.proxy.$telemetry.trackNodesPanel('nodeCreateList.onSubcategorySelected', {
|
||||
telemetry.trackNodesPanel('nodeCreateList.onSubcategorySelected', {
|
||||
subcategory: item.key,
|
||||
});
|
||||
}
|
||||
|
@ -96,10 +99,7 @@ function onSelected(item: INodeCreateElement) {
|
|||
}
|
||||
|
||||
if (item.type === 'view') {
|
||||
const view =
|
||||
item.key === TRIGGER_NODE_CREATOR_VIEW
|
||||
? TriggerView(instance?.proxy?.$locale)
|
||||
: RegularView(instance?.proxy?.$locale);
|
||||
const view = item.key === TRIGGER_NODE_CREATOR_VIEW ? TriggerView() : RegularView();
|
||||
|
||||
pushViewStack({
|
||||
title: view.title,
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<script setup lang="ts">
|
||||
import { getCurrentInstance, computed, onMounted, onUnmounted, watch } from 'vue';
|
||||
import { computed, onMounted, onUnmounted, watch } from 'vue';
|
||||
import type { INodeCreateElement } from '@/Interface';
|
||||
import { TRIGGER_NODE_CREATOR_VIEW } from '@/constants';
|
||||
|
||||
|
@ -11,8 +11,9 @@ import { useKeyboardNavigation } from '../composables/useKeyboardNavigation';
|
|||
import SearchBar from './SearchBar.vue';
|
||||
import ActionsRenderer from '../Modes/ActionsMode.vue';
|
||||
import NodesRenderer from '../Modes/NodesMode.vue';
|
||||
import { useI18n } from '@/composables';
|
||||
|
||||
const instance = getCurrentInstance();
|
||||
const i18n = useI18n();
|
||||
|
||||
const { mergedNodes } = useNodeCreatorStore();
|
||||
const { pushViewStack, popViewStack, updateCurrentViewStack } = useViewStacks();
|
||||
|
@ -25,10 +26,10 @@ const viewStacks = computed(() => useViewStacks().viewStacks);
|
|||
const isActionsMode = computed(() => useViewStacks().activeViewStackMode === 'actions');
|
||||
const searchPlaceholder = computed(() =>
|
||||
isActionsMode.value
|
||||
? instance?.proxy?.$locale.baseText('nodeCreator.actionsCategory.searchActions', {
|
||||
? i18n.baseText('nodeCreator.actionsCategory.searchActions', {
|
||||
interpolate: { node: activeViewStack.value.title as string },
|
||||
})
|
||||
: instance?.proxy?.$locale.baseText('nodeCreator.searchBar.searchNodes'),
|
||||
: i18n.baseText('nodeCreator.searchBar.searchNodes'),
|
||||
);
|
||||
|
||||
const nodeCreatorView = computed(() => useNodeCreatorStore().selectedView);
|
||||
|
@ -58,10 +59,7 @@ onUnmounted(() => {
|
|||
watch(
|
||||
() => nodeCreatorView.value,
|
||||
(selectedView) => {
|
||||
const view =
|
||||
selectedView === TRIGGER_NODE_CREATOR_VIEW
|
||||
? TriggerView(instance?.proxy?.$locale)
|
||||
: RegularView(instance?.proxy?.$locale);
|
||||
const view = selectedView === TRIGGER_NODE_CREATOR_VIEW ? TriggerView() : RegularView();
|
||||
|
||||
pushViewStack({
|
||||
title: view.title,
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import Vue from 'vue';
|
||||
import { PiniaVuePlugin } from 'pinia';
|
||||
import { nextTick } from 'vue';
|
||||
import { createTestingPinia } from '@pinia/testing';
|
||||
import { render, fireEvent } from '@testing-library/vue';
|
||||
import {
|
||||
|
@ -24,18 +23,16 @@ describe('ItemsRenderer', () => {
|
|||
mockNodeCreateElement('subcategory', { displayName: 'Node 3', name: 'node3' }),
|
||||
mockSubcategoryCreateElement({ title: 'Subcategory 2' }),
|
||||
];
|
||||
const { container } = render(
|
||||
ItemsRenderer,
|
||||
{
|
||||
pinia: createTestingPinia(),
|
||||
props: { elements: items },
|
||||
|
||||
const { container } = render(ItemsRenderer, {
|
||||
store: createTestingPinia(),
|
||||
props: { elements: items },
|
||||
global: {
|
||||
stubs: ['n8n-loading'],
|
||||
},
|
||||
(vue) => {
|
||||
vue.use(PiniaVuePlugin);
|
||||
},
|
||||
);
|
||||
//
|
||||
await Vue.nextTick();
|
||||
});
|
||||
|
||||
await nextTick();
|
||||
|
||||
const nodeItems = container.querySelectorAll('.iteratorItem .nodeItem');
|
||||
const labels = container.querySelectorAll('.iteratorItem .label');
|
||||
|
@ -53,18 +50,12 @@ describe('ItemsRenderer', () => {
|
|||
mockActionCreateElement(),
|
||||
mockViewCreateElement(),
|
||||
];
|
||||
const { container, emitted } = render(
|
||||
ItemsRenderer,
|
||||
{
|
||||
pinia: createTestingPinia(),
|
||||
props: { elements: items },
|
||||
},
|
||||
(vue) => {
|
||||
vue.use(PiniaVuePlugin);
|
||||
},
|
||||
);
|
||||
const { container, emitted } = render(ItemsRenderer, {
|
||||
pinia: createTestingPinia(),
|
||||
props: { elements: items },
|
||||
});
|
||||
//
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
|
||||
const itemTypes = {
|
||||
node: container.querySelector('.iteratorItem .nodeItem'),
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import Vue, { defineComponent, watch } from 'vue';
|
||||
import { defineComponent, nextTick, watch } from 'vue';
|
||||
import type { PropType } from 'vue';
|
||||
import { PiniaVuePlugin, createPinia } from 'pinia';
|
||||
import { createPinia } from 'pinia';
|
||||
import { render, screen, fireEvent } from '@testing-library/vue';
|
||||
import type { INodeTypeDescription } from 'n8n-workflow';
|
||||
import { useNodeCreatorStore } from '@/stores/nodeCreator.store';
|
||||
|
@ -9,23 +9,6 @@ import NodesListPanel from '../Panel/NodesListPanel.vue';
|
|||
import { REGULAR_NODE_CREATOR_VIEW } from '@/constants';
|
||||
import type { NodeFilterType } from '@/Interface';
|
||||
|
||||
function TelemetryPlugin(vue: typeof Vue): void {
|
||||
Object.defineProperty(vue, '$telemetry', {
|
||||
get() {
|
||||
return {
|
||||
trackNodesPanel: () => {},
|
||||
};
|
||||
},
|
||||
});
|
||||
Object.defineProperty(vue.prototype, '$telemetry', {
|
||||
get() {
|
||||
return {
|
||||
trackNodesPanel: () => {},
|
||||
};
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
function getWrapperComponent(setup: () => void) {
|
||||
const wrapperComponent = defineComponent({
|
||||
props: {
|
||||
|
@ -41,16 +24,11 @@ function getWrapperComponent(setup: () => void) {
|
|||
template: '<NodesListPanel @nodeTypeSelected="e => $emit(\'nodeTypeSelected\', e)" />',
|
||||
});
|
||||
|
||||
return render(
|
||||
wrapperComponent,
|
||||
{
|
||||
pinia: createPinia(),
|
||||
return render(wrapperComponent, {
|
||||
global: {
|
||||
plugins: [createPinia()],
|
||||
},
|
||||
(vue) => {
|
||||
vue.use(PiniaVuePlugin);
|
||||
vue.use(TelemetryPlugin);
|
||||
},
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
describe('NodesListPanel', () => {
|
||||
|
@ -78,11 +56,11 @@ describe('NodesListPanel', () => {
|
|||
return {};
|
||||
});
|
||||
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
expect(screen.getByText('Select a trigger')).toBeInTheDocument();
|
||||
expect(screen.queryByTestId('node-creator-search-bar')).toBeInTheDocument();
|
||||
screen.getByText('On app event').click();
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
expect(screen.queryByTestId('node-creator-search-bar')).not.toBeInTheDocument();
|
||||
mockedTriggerNodes.forEach((n) => {
|
||||
expect(screen.queryByText(n.name)).toBeInTheDocument();
|
||||
|
@ -95,7 +73,7 @@ describe('NodesListPanel', () => {
|
|||
expect(container.querySelector('.backButton')).toBeInTheDocument();
|
||||
|
||||
await fireEvent.click(container.querySelector('.backButton')!);
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
|
||||
expect(screen.queryAllByTestId('item-iterator-item')).toHaveLength(6);
|
||||
});
|
||||
|
@ -145,27 +123,20 @@ describe('NodesListPanel', () => {
|
|||
template: '<NodesListPanel @nodeTypeSelected="e => $emit(\'nodeTypeSelected\', e)" />',
|
||||
});
|
||||
|
||||
render(
|
||||
wrapperComponent,
|
||||
{
|
||||
pinia: createPinia(),
|
||||
props: {
|
||||
nodeTypes: mockedNodes,
|
||||
selectedView: REGULAR_NODE_CREATOR_VIEW,
|
||||
},
|
||||
render(wrapperComponent, {
|
||||
pinia: createPinia(),
|
||||
props: {
|
||||
nodeTypes: mockedNodes,
|
||||
selectedView: REGULAR_NODE_CREATOR_VIEW,
|
||||
},
|
||||
(vue) => {
|
||||
vue.use(PiniaVuePlugin);
|
||||
vue.use(TelemetryPlugin);
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
expect(screen.getByText('What happens next?')).toBeInTheDocument();
|
||||
expect(screen.queryAllByTestId('item-iterator-item')).toHaveLength(6);
|
||||
|
||||
screen.getByText('Action in an app').click();
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
mockedNodes.forEach((n) => {
|
||||
expect(screen.queryByText(n.displayName)).toBeInTheDocument();
|
||||
});
|
||||
|
@ -206,39 +177,32 @@ describe('NodesListPanel', () => {
|
|||
});
|
||||
|
||||
function renderComponent() {
|
||||
return render(
|
||||
wrapperComponent,
|
||||
{
|
||||
pinia: createPinia(),
|
||||
props: {
|
||||
nodeTypes: mockedNodes,
|
||||
},
|
||||
return render(wrapperComponent, {
|
||||
pinia: createPinia(),
|
||||
props: {
|
||||
nodeTypes: mockedNodes,
|
||||
},
|
||||
(vue) => {
|
||||
vue.use(PiniaVuePlugin);
|
||||
vue.use(TelemetryPlugin);
|
||||
},
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
it('should be visible in the root view', async () => {
|
||||
renderComponent();
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
|
||||
expect(screen.queryByTestId('node-creator-search-bar')).toBeInTheDocument();
|
||||
});
|
||||
it('should not be visible if subcategory contains less than 9 items', async () => {
|
||||
renderComponent();
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
|
||||
screen.getByText('On app event').click();
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
expect(screen.queryByTestId('node-creator-search-bar')).not.toBeInTheDocument();
|
||||
expect(screen.queryAllByTestId('item-iterator-item')).toHaveLength(8);
|
||||
});
|
||||
it('should be visible if subcategory contains 9 or more items', async () => {
|
||||
const { updateProps } = renderComponent();
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
|
||||
mockedNodes.push(
|
||||
mockSimplifiedNodeType({
|
||||
|
@ -249,10 +213,10 @@ describe('NodesListPanel', () => {
|
|||
);
|
||||
|
||||
await updateProps({ nodeTypes: [...mockedNodes] });
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
|
||||
screen.getByText('On app event').click();
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
|
||||
expect(screen.queryAllByTestId('item-iterator-item')).toHaveLength(9);
|
||||
expect(screen.queryByTestId('node-creator-search-bar')).toBeInTheDocument();
|
||||
|
@ -260,26 +224,26 @@ describe('NodesListPanel', () => {
|
|||
|
||||
it('should correctly handle search', async () => {
|
||||
const { container } = renderComponent();
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
|
||||
screen.getByText('On app event').click();
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
|
||||
await fireEvent.input(screen.getByTestId('node-creator-search-bar'), {
|
||||
target: { value: 'Ninth' },
|
||||
});
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
expect(screen.queryAllByTestId('item-iterator-item')).toHaveLength(1);
|
||||
|
||||
await fireEvent.input(screen.getByTestId('node-creator-search-bar'), {
|
||||
target: { value: 'Non sense' },
|
||||
});
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
expect(screen.queryAllByTestId('item-iterator-item')).toHaveLength(0);
|
||||
expect(screen.queryByText("We didn't make that... yet")).toBeInTheDocument();
|
||||
|
||||
await fireEvent.click(container.querySelector('.clear')!);
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
expect(screen.queryAllByTestId('item-iterator-item')).toHaveLength(9);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -2,7 +2,7 @@ import { render } from '@testing-library/vue';
|
|||
import userEvent from '@testing-library/user-event';
|
||||
import { defineComponent, computed } from 'vue';
|
||||
import { useKeyboardNavigation } from '../composables/useKeyboardNavigation';
|
||||
import { PiniaVuePlugin, createPinia } from 'pinia';
|
||||
import { createPinia } from 'pinia';
|
||||
|
||||
const eventHookSpy = vi.fn();
|
||||
describe('useKeyboardNavigation', () => {
|
||||
|
@ -39,9 +39,7 @@ describe('useKeyboardNavigation', () => {
|
|||
});
|
||||
|
||||
const renderTestComponent = () => {
|
||||
return render(TestComponent, { pinia: createPinia() }, (vue) => {
|
||||
vue.use(PiniaVuePlugin);
|
||||
});
|
||||
return render(TestComponent, { pinia: createPinia() });
|
||||
};
|
||||
|
||||
afterAll(() => {
|
||||
|
|
|
@ -14,12 +14,15 @@ import {
|
|||
EMAIL_IMAP_NODE_TYPE,
|
||||
DEFAULT_SUBCATEGORY,
|
||||
} from '@/constants';
|
||||
import { useI18n } from '@/composables';
|
||||
|
||||
export function TriggerView() {
|
||||
const i18n = useI18n();
|
||||
|
||||
export function TriggerView($locale: any) {
|
||||
return {
|
||||
value: TRIGGER_NODE_CREATOR_VIEW,
|
||||
title: $locale.baseText('nodeCreator.triggerHelperPanel.selectATrigger'),
|
||||
subtitle: $locale.baseText('nodeCreator.triggerHelperPanel.selectATriggerDescription'),
|
||||
title: i18n.baseText('nodeCreator.triggerHelperPanel.selectATrigger'),
|
||||
subtitle: i18n.baseText('nodeCreator.triggerHelperPanel.selectATriggerDescription'),
|
||||
items: [
|
||||
{
|
||||
key: DEFAULT_SUBCATEGORY,
|
||||
|
@ -37,12 +40,8 @@ export function TriggerView($locale: any) {
|
|||
properties: {
|
||||
group: [],
|
||||
name: SCHEDULE_TRIGGER_NODE_TYPE,
|
||||
displayName: $locale.baseText(
|
||||
'nodeCreator.triggerHelperPanel.scheduleTriggerDisplayName',
|
||||
),
|
||||
description: $locale.baseText(
|
||||
'nodeCreator.triggerHelperPanel.scheduleTriggerDescription',
|
||||
),
|
||||
displayName: i18n.baseText('nodeCreator.triggerHelperPanel.scheduleTriggerDisplayName'),
|
||||
description: i18n.baseText('nodeCreator.triggerHelperPanel.scheduleTriggerDescription'),
|
||||
icon: 'fa:clock',
|
||||
},
|
||||
},
|
||||
|
@ -53,8 +52,8 @@ export function TriggerView($locale: any) {
|
|||
properties: {
|
||||
group: [],
|
||||
name: WEBHOOK_NODE_TYPE,
|
||||
displayName: $locale.baseText('nodeCreator.triggerHelperPanel.webhookTriggerDisplayName'),
|
||||
description: $locale.baseText('nodeCreator.triggerHelperPanel.webhookTriggerDescription'),
|
||||
displayName: i18n.baseText('nodeCreator.triggerHelperPanel.webhookTriggerDisplayName'),
|
||||
description: i18n.baseText('nodeCreator.triggerHelperPanel.webhookTriggerDescription'),
|
||||
iconData: {
|
||||
type: 'file',
|
||||
icon: 'webhook',
|
||||
|
@ -69,8 +68,8 @@ export function TriggerView($locale: any) {
|
|||
properties: {
|
||||
group: [],
|
||||
name: MANUAL_TRIGGER_NODE_TYPE,
|
||||
displayName: $locale.baseText('nodeCreator.triggerHelperPanel.manualTriggerDisplayName'),
|
||||
description: $locale.baseText('nodeCreator.triggerHelperPanel.manualTriggerDescription'),
|
||||
displayName: i18n.baseText('nodeCreator.triggerHelperPanel.manualTriggerDisplayName'),
|
||||
description: i18n.baseText('nodeCreator.triggerHelperPanel.manualTriggerDescription'),
|
||||
icon: 'fa:mouse-pointer',
|
||||
},
|
||||
},
|
||||
|
@ -81,12 +80,8 @@ export function TriggerView($locale: any) {
|
|||
properties: {
|
||||
group: [],
|
||||
name: EXECUTE_WORKFLOW_TRIGGER_NODE_TYPE,
|
||||
displayName: $locale.baseText(
|
||||
'nodeCreator.triggerHelperPanel.workflowTriggerDisplayName',
|
||||
),
|
||||
description: $locale.baseText(
|
||||
'nodeCreator.triggerHelperPanel.workflowTriggerDescription',
|
||||
),
|
||||
displayName: i18n.baseText('nodeCreator.triggerHelperPanel.workflowTriggerDisplayName'),
|
||||
description: i18n.baseText('nodeCreator.triggerHelperPanel.workflowTriggerDescription'),
|
||||
icon: 'fa:sign-out-alt',
|
||||
},
|
||||
},
|
||||
|
@ -103,10 +98,12 @@ export function TriggerView($locale: any) {
|
|||
};
|
||||
}
|
||||
|
||||
export function RegularView($locale: any) {
|
||||
export function RegularView() {
|
||||
const i18n = useI18n();
|
||||
|
||||
return {
|
||||
value: REGULAR_NODE_CREATOR_VIEW,
|
||||
title: $locale.baseText('nodeCreator.triggerHelperPanel.whatHappensNext'),
|
||||
title: i18n.baseText('nodeCreator.triggerHelperPanel.whatHappensNext'),
|
||||
items: [
|
||||
{
|
||||
key: DEFAULT_SUBCATEGORY,
|
||||
|
@ -156,11 +153,9 @@ export function RegularView($locale: any) {
|
|||
key: TRIGGER_NODE_CREATOR_VIEW,
|
||||
type: 'view',
|
||||
properties: {
|
||||
title: $locale.baseText('nodeCreator.triggerHelperPanel.addAnotherTrigger'),
|
||||
title: i18n.baseText('nodeCreator.triggerHelperPanel.addAnotherTrigger'),
|
||||
icon: 'bolt',
|
||||
description: $locale.baseText(
|
||||
'nodeCreator.triggerHelperPanel.addAnotherTriggerDescription',
|
||||
),
|
||||
description: i18n.baseText('nodeCreator.triggerHelperPanel.addAnotherTriggerDescription'),
|
||||
},
|
||||
},
|
||||
],
|
||||
|
|
|
@ -126,7 +126,7 @@
|
|||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
import { mapStores } from 'pinia';
|
||||
import { createEventBus } from 'n8n-design-system';
|
||||
import { createEventBus } from 'n8n-design-system/utils';
|
||||
import type {
|
||||
INodeConnections,
|
||||
INodeTypeDescription,
|
||||
|
|
|
@ -525,7 +525,7 @@ export default defineComponent({
|
|||
}
|
||||
}
|
||||
|
||||
// Set the value via Vue.set that everything updates correctly in the UI
|
||||
// Set the value so that everything updates correctly in the UI
|
||||
if (nameParts.length === 0) {
|
||||
// Data is on top level
|
||||
if (value === null) {
|
||||
|
|
|
@ -53,7 +53,7 @@ import { defineComponent } from 'vue';
|
|||
import { useToast } from '@/composables';
|
||||
import { mapStores } from 'pinia';
|
||||
import { useUIStore } from '@/stores/ui.store';
|
||||
import { createEventBus } from 'n8n-design-system';
|
||||
import { createEventBus } from 'n8n-design-system/utils';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'OnboardingCallSignupModal',
|
||||
|
|
|
@ -63,7 +63,7 @@
|
|||
append-to-body
|
||||
:close-on-click-modal="false"
|
||||
width="80%"
|
||||
:title="`${$locale.baseText('codeEdit.edit')} ${$locale
|
||||
:title="`${i18n.baseText('codeEdit.edit')} ${$locale
|
||||
.nodeText()
|
||||
.inputLabelDisplayName(parameter, path)}`"
|
||||
:before-close="closeCodeEditDialog"
|
||||
|
@ -157,7 +157,7 @@
|
|||
focused: isFocused,
|
||||
invalid: !isFocused && getIssues.length > 0 && !isValueExpression,
|
||||
}"
|
||||
:title="$locale.baseText('parameterInput.openEditWindow')"
|
||||
:title="i18n.baseText('parameterInput.openEditWindow')"
|
||||
@click="displayEditDialog()"
|
||||
@focus="setFocus"
|
||||
/>
|
||||
|
@ -201,7 +201,7 @@
|
|||
:placeholder="
|
||||
parameter.placeholder
|
||||
? getPlaceholder()
|
||||
: $locale.baseText('parameterInput.selectDateAndTime')
|
||||
: i18n.baseText('parameterInput.selectDateAndTime')
|
||||
"
|
||||
:picker-options="dateTimePickerOptions"
|
||||
@update:modelValue="valueChanged"
|
||||
|
@ -255,7 +255,7 @@
|
|||
filterable
|
||||
:modelValue="displayValue"
|
||||
:placeholder="
|
||||
parameter.placeholder ? getPlaceholder() : $locale.baseText('parameterInput.select')
|
||||
parameter.placeholder ? getPlaceholder() : i18n.baseText('parameterInput.select')
|
||||
"
|
||||
:loading="remoteParameterOptionsLoading"
|
||||
:disabled="isReadOnly || remoteParameterOptionsLoading"
|
||||
|
@ -297,7 +297,7 @@
|
|||
:loading="remoteParameterOptionsLoading"
|
||||
:disabled="isReadOnly || remoteParameterOptionsLoading"
|
||||
:title="displayTitle"
|
||||
:placeholder="$locale.baseText('parameterInput.select')"
|
||||
:placeholder="i18n.baseText('parameterInput.select')"
|
||||
@update:modelValue="valueChanged"
|
||||
@keydown.stop
|
||||
@focus="setFocus"
|
||||
|
@ -392,6 +392,7 @@ import { useSettingsStore } from '@/stores/settings.store';
|
|||
import { htmlEditorEventBus } from '@/event-bus';
|
||||
import type { EventBus } from 'n8n-design-system/utils';
|
||||
import { createEventBus } from 'n8n-design-system/utils';
|
||||
import { useI18n } from '@/composables';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'parameter-input',
|
||||
|
@ -467,6 +468,13 @@ export default defineComponent({
|
|||
default: () => createEventBus(),
|
||||
},
|
||||
},
|
||||
setup() {
|
||||
const i18n = useI18n();
|
||||
|
||||
return {
|
||||
i18n,
|
||||
};
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
codeEditDialogVisible: false,
|
||||
|
@ -586,17 +594,14 @@ export default defineComponent({
|
|||
const interpolation = { interpolate: { shortPath: this.shortPath } };
|
||||
|
||||
if (this.getIssues.length && this.isValueExpression) {
|
||||
return this.$locale.baseText(
|
||||
'parameterInput.parameterHasIssuesAndExpression',
|
||||
interpolation,
|
||||
);
|
||||
return this.i18n.baseText('parameterInput.parameterHasIssuesAndExpression', interpolation);
|
||||
} else if (this.getIssues.length && !this.isValueExpression) {
|
||||
return this.$locale.baseText('parameterInput.parameterHasIssues', interpolation);
|
||||
return this.i18n.baseText('parameterInput.parameterHasIssues', interpolation);
|
||||
} else if (!this.getIssues.length && this.isValueExpression) {
|
||||
return this.$locale.baseText('parameterInput.parameterHasExpression', interpolation);
|
||||
return this.i18n.baseText('parameterInput.parameterHasExpression', interpolation);
|
||||
}
|
||||
|
||||
return this.$locale.baseText('parameterInput.parameter', interpolation);
|
||||
return this.i18n.baseText('parameterInput.parameter', interpolation);
|
||||
},
|
||||
displayValue(): string | number | boolean | null {
|
||||
if (this.remoteParameterOptionsLoading === true) {
|
||||
|
@ -604,7 +609,7 @@ export default defineComponent({
|
|||
// to user that the data is loading. If not it would
|
||||
// display the user the key instead of the value it
|
||||
// represents
|
||||
return this.$locale.baseText('parameterInput.loadingOptions');
|
||||
return this.i18n.baseText('parameterInput.loadingOptions');
|
||||
}
|
||||
|
||||
// if the value is marked as empty return empty string, to prevent displaying the asterisks
|
||||
|
@ -690,7 +695,7 @@ export default defineComponent({
|
|||
if (this.parameter.type === 'credentialsSelect' && this.displayValue === '') {
|
||||
issues.parameters = issues.parameters || {};
|
||||
|
||||
const issue = this.$locale.baseText('parameterInput.selectACredentialTypeFromTheDropdown');
|
||||
const issue = this.i18n.baseText('parameterInput.selectACredentialTypeFromTheDropdown');
|
||||
|
||||
issues.parameters[this.parameter.name] = [issue];
|
||||
} else if (
|
||||
|
@ -723,7 +728,7 @@ export default defineComponent({
|
|||
issues.parameters = {};
|
||||
}
|
||||
|
||||
const issue = this.$locale.baseText('parameterInput.theValueIsNotSupported', {
|
||||
const issue = this.i18n.baseText('parameterInput.theValueIsNotSupported', {
|
||||
interpolate: { checkValue },
|
||||
});
|
||||
|
||||
|
@ -856,18 +861,18 @@ export default defineComponent({
|
|||
},
|
||||
getPlaceholder(): string {
|
||||
return this.isForCredential
|
||||
? this.$locale.credText().placeholder(this.parameter)
|
||||
: this.$locale.nodeText().placeholder(this.parameter, this.path);
|
||||
? this.i18n.credText().placeholder(this.parameter)
|
||||
: this.i18n.nodeText().placeholder(this.parameter, this.path);
|
||||
},
|
||||
getOptionsOptionDisplayName(option: INodePropertyOptions): string {
|
||||
return this.isForCredential
|
||||
? this.$locale.credText().optionsOptionDisplayName(this.parameter, option)
|
||||
: this.$locale.nodeText().optionsOptionDisplayName(this.parameter, option, this.path);
|
||||
? this.i18n.credText().optionsOptionDisplayName(this.parameter, option)
|
||||
: this.i18n.nodeText().optionsOptionDisplayName(this.parameter, option, this.path);
|
||||
},
|
||||
getOptionsOptionDescription(option: INodePropertyOptions): string {
|
||||
return this.isForCredential
|
||||
? this.$locale.credText().optionsOptionDescription(this.parameter, option)
|
||||
: this.$locale.nodeText().optionsOptionDescription(this.parameter, option, this.path);
|
||||
? this.i18n.credText().optionsOptionDescription(this.parameter, option)
|
||||
: this.i18n.nodeText().optionsOptionDescription(this.parameter, option, this.path);
|
||||
},
|
||||
|
||||
async loadRemoteParameterOptions() {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<template>
|
||||
<n8n-input-label
|
||||
:label="hideLabel ? '' : $locale.nodeText().inputLabelDisplayName(parameter, path)"
|
||||
:tooltipText="hideLabel ? '' : $locale.nodeText().inputLabelDescription(parameter, path)"
|
||||
:label="hideLabel ? '' : i18n.nodeText().inputLabelDisplayName(parameter, path)"
|
||||
:tooltipText="hideLabel ? '' : i18n.nodeText().inputLabelDescription(parameter, path)"
|
||||
:showTooltip="focused"
|
||||
:showOptions="menuExpanded || focused || forceShowExpression"
|
||||
:bold="false"
|
||||
|
@ -36,7 +36,7 @@
|
|||
<template #content>
|
||||
<span
|
||||
v-html="
|
||||
$locale.baseText(`dataMapping.${displayMode}Hint`, {
|
||||
i18n.baseText(`dataMapping.${displayMode}Hint`, {
|
||||
interpolate: { name: parameter.displayName },
|
||||
})
|
||||
"
|
||||
|
@ -77,7 +77,7 @@ import type { IN8nButton, INodeUi, IRunDataDisplayMode, IUpdateInformation } fro
|
|||
|
||||
import ParameterOptions from '@/components/ParameterOptions.vue';
|
||||
import DraggableTarget from '@/components/DraggableTarget.vue';
|
||||
import { useToast } from '@/composables';
|
||||
import { useI18n, useToast } from '@/composables';
|
||||
import {
|
||||
hasExpressionMapping,
|
||||
isResourceLocatorValue,
|
||||
|
@ -110,8 +110,10 @@ export default defineComponent({
|
|||
},
|
||||
setup() {
|
||||
const eventBus = createEventBus();
|
||||
const i18n = useI18n();
|
||||
|
||||
return {
|
||||
i18n,
|
||||
eventBus,
|
||||
...useToast(),
|
||||
};
|
||||
|
@ -158,12 +160,12 @@ export default defineComponent({
|
|||
}),
|
||||
},
|
||||
},
|
||||
created() {
|
||||
mounted() {
|
||||
const mappingTooltipDismissHandler = this.onMappingTooltipDismissed.bind(this);
|
||||
this.dataMappingTooltipButtons = [
|
||||
{
|
||||
attrs: {
|
||||
label: this.$locale.baseText('_reusableBaseText.dismiss' as BaseTextKey),
|
||||
label: this.i18n.baseText('_reusableBaseText.dismiss' as BaseTextKey),
|
||||
'data-test-id': 'dismiss-mapping-tooltip',
|
||||
},
|
||||
listeners: {
|
||||
|
@ -178,7 +180,7 @@ export default defineComponent({
|
|||
return this.ndvStore.activeNode;
|
||||
},
|
||||
hint(): string | null {
|
||||
return this.$locale.nodeText().hint(this.parameter, this.path);
|
||||
return this.i18n.nodeText().hint(this.parameter, this.path);
|
||||
},
|
||||
isInputTypeString(): boolean {
|
||||
return this.parameter.type === 'string';
|
||||
|
@ -300,8 +302,8 @@ export default defineComponent({
|
|||
|
||||
if (!this.ndvStore.isMappingOnboarded) {
|
||||
this.showMessage({
|
||||
title: this.$locale.baseText('dataMapping.success.title'),
|
||||
message: this.$locale.baseText('dataMapping.success.moreInfo'),
|
||||
title: this.i18n.baseText('dataMapping.success.title'),
|
||||
message: this.i18n.baseText('dataMapping.success.moreInfo'),
|
||||
type: 'success',
|
||||
dangerouslyUseHTMLString: true,
|
||||
});
|
||||
|
|
|
@ -135,7 +135,7 @@ import { useUIStore } from '@/stores/ui.store';
|
|||
import { useSettingsStore } from '@/stores/settings.store';
|
||||
import { useRootStore } from '@/stores/n8nRoot.store';
|
||||
import { useUsersStore } from '@/stores/users.store';
|
||||
import { createEventBus } from 'n8n-design-system';
|
||||
import { createEventBus } from 'n8n-design-system/utils';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'PersonalizationModal',
|
||||
|
|
|
@ -13,6 +13,7 @@ interface Props {
|
|||
serviceName: string;
|
||||
loading: boolean;
|
||||
loadingError: boolean;
|
||||
teleported?: boolean;
|
||||
}
|
||||
|
||||
const props = defineProps<Props>();
|
||||
|
@ -112,6 +113,7 @@ defineExpose({
|
|||
<div class="mt-5xs">
|
||||
<n8n-select
|
||||
:modelValue="selected"
|
||||
:teleported="teleported"
|
||||
:size="props.inputSize"
|
||||
@update:modelValue="onModeChanged"
|
||||
>
|
||||
|
|
|
@ -16,6 +16,7 @@ interface Props {
|
|||
inputSize: string;
|
||||
loading: boolean;
|
||||
serviceName: string;
|
||||
teleported?: boolean;
|
||||
}
|
||||
|
||||
const props = defineProps<Props>();
|
||||
|
@ -134,6 +135,7 @@ defineExpose({
|
|||
:modelValue="state.selected"
|
||||
:size="props.inputSize"
|
||||
:disabled="loading"
|
||||
:teleported="teleported"
|
||||
@update:modelValue="onSelectionChange"
|
||||
>
|
||||
<n8n-option v-for="field in availableMatchingFields" :key="field.id" :value="field.id">
|
||||
|
|
|
@ -26,6 +26,7 @@ type Props = {
|
|||
inputSize: string;
|
||||
labelSize: string;
|
||||
dependentParametersValues?: string | null;
|
||||
teleported: boolean;
|
||||
};
|
||||
|
||||
const nodeTypesStore = useNodeTypesStore();
|
||||
|
@ -445,6 +446,7 @@ defineExpose({
|
|||
:loading="state.loading"
|
||||
:loadingError="state.loadingError"
|
||||
:fieldsToMap="state.paramValue.schema"
|
||||
:teleported="teleported"
|
||||
@modeChanged="onModeChanged"
|
||||
@retryFetch="initFetching"
|
||||
/>
|
||||
|
@ -457,6 +459,7 @@ defineExpose({
|
|||
:loading="state.loading"
|
||||
:initialValue="matchingColumns"
|
||||
:serviceName="nodeType?.displayName || locale.baseText('generic.service')"
|
||||
:teleported="teleported"
|
||||
@matchingColumnsChanged="onMatchingColumnsChanged"
|
||||
/>
|
||||
<n8n-text v-if="!showMappingModeSelect && state.loading" size="small">
|
||||
|
|
|
@ -69,7 +69,7 @@
|
|||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineAsyncComponent, defineComponent } from 'vue';
|
||||
import { defineAsyncComponent, defineComponent, ref } from 'vue';
|
||||
import type { PropType } from 'vue';
|
||||
import VueJsonPretty from 'vue-json-pretty';
|
||||
import type { IDataObject, INodeExecutionData } from 'n8n-workflow';
|
||||
|
@ -82,7 +82,7 @@ import { useNDVStore } from '@/stores/ndv.store';
|
|||
import MappingPill from './MappingPill.vue';
|
||||
import { getMappedExpression } from '@/utils/mappingUtils';
|
||||
import { useWorkflowsStore } from '@/stores/workflows.store';
|
||||
import { nonExistingJsonPath } from '@/components/RunDataJsonActions.vue';
|
||||
import { nonExistingJsonPath } from '@/constants';
|
||||
|
||||
const RunDataJsonActions = defineAsyncComponent(
|
||||
async () => import('@/components/RunDataJsonActions.vue'),
|
||||
|
@ -126,11 +126,15 @@ export default defineComponent({
|
|||
type: Number,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
setup() {
|
||||
const selectedJsonPath = ref(nonExistingJsonPath);
|
||||
const draggingPath = ref<null | string>(null);
|
||||
const displayMode = ref('json');
|
||||
|
||||
return {
|
||||
selectedJsonPath: nonExistingJsonPath,
|
||||
draggingPath: null as null | string,
|
||||
displayMode: 'json',
|
||||
selectedJsonPath,
|
||||
draggingPath,
|
||||
displayMode,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<div :class="$style.actionsGroup">
|
||||
<n8n-icon-button
|
||||
v-if="noSelection"
|
||||
:title="$locale.baseText('runData.copyToClipboard')"
|
||||
:title="i18n.baseText('runData.copyToClipboard')"
|
||||
icon="copy"
|
||||
type="tertiary"
|
||||
:circle="false"
|
||||
|
@ -11,7 +11,7 @@
|
|||
<el-dropdown v-else trigger="click" @command="handleCopyClick">
|
||||
<span class="el-dropdown-link">
|
||||
<n8n-icon-button
|
||||
:title="$locale.baseText('runData.copyToClipboard')"
|
||||
:title="i18n.baseText('runData.copyToClipboard')"
|
||||
icon="copy"
|
||||
type="tertiary"
|
||||
:circle="false"
|
||||
|
@ -20,13 +20,13 @@
|
|||
<template #dropdown>
|
||||
<el-dropdown-menu>
|
||||
<el-dropdown-item :command="{ command: 'value' }">
|
||||
{{ $locale.baseText('runData.copyValue') }}
|
||||
{{ i18n.baseText('runData.copyValue') }}
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item :command="{ command: 'itemPath' }" divided>
|
||||
{{ $locale.baseText('runData.copyItemPath') }}
|
||||
{{ i18n.baseText('runData.copyItemPath') }}
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item :command="{ command: 'parameterPath' }">
|
||||
{{ $locale.baseText('runData.copyParameterPath') }}
|
||||
{{ i18n.baseText('runData.copyParameterPath') }}
|
||||
</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
|
@ -48,16 +48,14 @@ import { genericHelpers } from '@/mixins/genericHelpers';
|
|||
import { clearJsonKey, convertPath, executionDataToJson } from '@/utils';
|
||||
import { useWorkflowsStore } from '@/stores/workflows.store';
|
||||
import { useNDVStore } from '@/stores/ndv.store';
|
||||
import { useToast } from '@/composables';
|
||||
import { useI18n, useToast } from '@/composables';
|
||||
import { nonExistingJsonPath } from '@/constants';
|
||||
|
||||
type JsonPathData = {
|
||||
path: string;
|
||||
startPath: string;
|
||||
};
|
||||
|
||||
// A path that does not exist so that nothing is selected by default
|
||||
export const nonExistingJsonPath = '_!^&*';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'run-data-json-actions',
|
||||
mixins: [genericHelpers, nodeHelpers, pinData, copyPaste],
|
||||
|
@ -94,7 +92,10 @@ export default defineComponent({
|
|||
},
|
||||
},
|
||||
setup() {
|
||||
const i18n = useI18n();
|
||||
|
||||
return {
|
||||
i18n,
|
||||
...useToast(),
|
||||
};
|
||||
},
|
||||
|
@ -161,7 +162,7 @@ export default defineComponent({
|
|||
value = this.getJsonValue();
|
||||
|
||||
this.showToast({
|
||||
title: this.$locale.baseText('runData.copyValue.toast'),
|
||||
title: this.i18n.baseText('runData.copyValue.toast'),
|
||||
message: '',
|
||||
type: 'success',
|
||||
duration: 2000,
|
||||
|
@ -175,7 +176,7 @@ export default defineComponent({
|
|||
path = jsonItemPath.path;
|
||||
|
||||
this.showToast({
|
||||
title: this.$locale.baseText('runData.copyItemPath.toast'),
|
||||
title: this.i18n.baseText('runData.copyItemPath.toast'),
|
||||
message: '',
|
||||
type: 'success',
|
||||
duration: 2000,
|
||||
|
@ -186,7 +187,7 @@ export default defineComponent({
|
|||
path = jsonParameterPath.path;
|
||||
|
||||
this.showToast({
|
||||
title: this.$locale.baseText('runData.copyParameterPath.toast'),
|
||||
title: this.i18n.baseText('runData.copyParameterPath.toast'),
|
||||
message: '',
|
||||
type: 'success',
|
||||
duration: 2000,
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
<script lang="ts" setup>
|
||||
import { useSSOStore } from '@/stores/sso.store';
|
||||
import { useToast } from '@/composables';
|
||||
import { useI18n, useToast } from '@/composables';
|
||||
|
||||
const i18n = useI18n();
|
||||
const ssoStore = useSSOStore();
|
||||
const toast = useToast();
|
||||
|
||||
|
@ -17,14 +18,14 @@ const onSSOLogin = async () => {
|
|||
<template>
|
||||
<div v-if="ssoStore.showSsoLoginButton" :class="$style.ssoLogin">
|
||||
<div :class="$style.divider">
|
||||
<span>{{ $locale.baseText('sso.login.divider') }}</span>
|
||||
<span>{{ i18n.baseText('sso.login.divider') }}</span>
|
||||
</div>
|
||||
<n8n-button
|
||||
@click="onSSOLogin"
|
||||
size="large"
|
||||
type="primary"
|
||||
outline
|
||||
:label="$locale.baseText('sso.login.button')"
|
||||
:label="i18n.baseText('sso.login.button')"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
@ -206,7 +206,7 @@ import InlineNameEdit from '@/components/InlineNameEdit.vue';
|
|||
import SaveButton from '@/components/SaveButton.vue';
|
||||
import EventSelection from '@/components/SettingsLogStreaming/EventSelection.ee.vue';
|
||||
import type { EventBus } from 'n8n-design-system';
|
||||
import { createEventBus } from 'n8n-design-system';
|
||||
import { createEventBus } from 'n8n-design-system/utils';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'event-destination-settings-modal',
|
||||
|
|
|
@ -21,7 +21,7 @@ const defaultStagedFileTypes = ['tags', 'variables', 'credential'];
|
|||
const loadingService = useLoadingService();
|
||||
const uiStore = useUIStore();
|
||||
const toast = useToast();
|
||||
const { i18n } = useI18n();
|
||||
const i18n = useI18n();
|
||||
const sourceControlStore = useSourceControlStore();
|
||||
const route = useRoute();
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@ const defaultStagedFileTypes = ['tags', 'variables', 'credential'];
|
|||
const loadingService = useLoadingService();
|
||||
const uiStore = useUIStore();
|
||||
const toast = useToast();
|
||||
const { i18n } = useI18n();
|
||||
const i18n = useI18n();
|
||||
const sourceControlStore = useSourceControlStore();
|
||||
const route = useRoute();
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<div :class="$style.sqlEditor" v-click-outside="onBlur">
|
||||
<div :class="$style.sqlEditor" v-on-click-outside="onBlur">
|
||||
<div ref="sqlEditor" data-test-id="sql-editor-container" class="ph-no-capture"></div>
|
||||
<InlineExpressionEditorOutput
|
||||
:segments="segments"
|
||||
|
|
|
@ -39,7 +39,7 @@ import Modal from '@/components/Modal.vue';
|
|||
import { TAGS_MANAGER_MODAL_KEY } from '@/constants';
|
||||
import { mapStores } from 'pinia';
|
||||
import { useTagsStore } from '@/stores/tags.store';
|
||||
import { createEventBus } from 'n8n-design-system';
|
||||
import { createEventBus } from 'n8n-design-system/utils';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'TagsManager',
|
||||
|
|
|
@ -119,7 +119,7 @@ import { useWorkflowsStore } from '@/stores/workflows.store';
|
|||
import { useNDVStore } from '@/stores/ndv.store';
|
||||
import { useNodeTypesStore } from '@/stores/nodeTypes.store';
|
||||
import type { N8nInfoAccordion } from 'n8n-design-system';
|
||||
import { createEventBus } from 'n8n-design-system';
|
||||
import { createEventBus } from 'n8n-design-system/utils';
|
||||
|
||||
type HelpRef = InstanceType<typeof N8nInfoAccordion>;
|
||||
|
||||
|
|
|
@ -65,7 +65,7 @@ import ModalDrawer from '@/components/ModalDrawer.vue';
|
|||
import { workflowHelpers } from '@/mixins/workflowHelpers';
|
||||
import { useSettingsStore } from '@/stores/settings.store';
|
||||
import { useRootStore } from '@/stores/n8nRoot.store';
|
||||
import { createEventBus } from 'n8n-design-system';
|
||||
import { createEventBus } from 'n8n-design-system/utils';
|
||||
import { useToast } from '@/composables';
|
||||
|
||||
const DEFAULT_TITLE = 'How likely are you to recommend n8n to a friend or colleague?';
|
||||
|
|
|
@ -7,7 +7,7 @@ import { EnterpriseEditionFeature } from '@/constants';
|
|||
import { useSettingsStore, useUsersStore } from '@/stores';
|
||||
import { getVariablesPermissions } from '@/permissions';
|
||||
|
||||
const { i18n } = useI18n();
|
||||
const i18n = useI18n();
|
||||
const copyToClipboard = useCopyToClipboard();
|
||||
const { showMessage } = useToast();
|
||||
const settingsStore = useSettingsStore();
|
||||
|
|
|
@ -381,7 +381,7 @@ import {
|
|||
useWorkflowsEEStore,
|
||||
useUsersStore,
|
||||
} from '@/stores';
|
||||
import { createEventBus } from 'n8n-design-system';
|
||||
import { createEventBus } from 'n8n-design-system/utils';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'WorkflowSettings',
|
||||
|
|
|
@ -124,7 +124,7 @@
|
|||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
import { mapStores } from 'pinia';
|
||||
import { createEventBus } from 'n8n-design-system';
|
||||
import { createEventBus } from 'n8n-design-system/utils';
|
||||
|
||||
import Modal from './Modal.vue';
|
||||
import {
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import { PiniaVuePlugin } from 'pinia';
|
||||
import { render, within } from '@testing-library/vue';
|
||||
import { within } from '@testing-library/vue';
|
||||
import { merge } from 'lodash-es';
|
||||
import userEvent from '@testing-library/user-event';
|
||||
|
||||
|
@ -10,53 +9,51 @@ import { createTestingPinia } from '@pinia/testing';
|
|||
import BannerStack from '@/components/banners/BannerStack.vue';
|
||||
import { useUIStore } from '@/stores/ui.store';
|
||||
import { useUsersStore } from '@/stores/users.store';
|
||||
import { createComponentRenderer, RenderOptions } from '@/__tests__/render';
|
||||
|
||||
let uiStore: ReturnType<typeof useUIStore>;
|
||||
let usersStore: ReturnType<typeof useUsersStore>;
|
||||
|
||||
const DEFAULT_SETUP = {
|
||||
pinia: createTestingPinia({
|
||||
initialState: {
|
||||
[STORES.SETTINGS]: {
|
||||
settings: merge({}, SETTINGS_STORE_DEFAULT_STATE.settings),
|
||||
},
|
||||
[STORES.UI]: {
|
||||
banners: {
|
||||
V1: { dismissed: false },
|
||||
TRIAL: { dismissed: false },
|
||||
TRIAL_OVER: { dismissed: false },
|
||||
const initialState = {
|
||||
[STORES.SETTINGS]: {
|
||||
settings: merge({}, SETTINGS_STORE_DEFAULT_STATE.settings),
|
||||
},
|
||||
[STORES.UI]: {
|
||||
banners: {
|
||||
V1: { dismissed: false },
|
||||
TRIAL: { dismissed: false },
|
||||
TRIAL_OVER: { dismissed: false },
|
||||
},
|
||||
},
|
||||
[STORES.USERS]: {
|
||||
currentUserId: 'aaa-bbb',
|
||||
users: {
|
||||
'aaa-bbb': {
|
||||
id: 'aaa-bbb',
|
||||
globalRole: {
|
||||
id: '1',
|
||||
name: 'owner',
|
||||
scope: 'global',
|
||||
},
|
||||
},
|
||||
[STORES.USERS]: {
|
||||
currentUserId: 'aaa-bbb',
|
||||
users: {
|
||||
'aaa-bbb': {
|
||||
id: 'aaa-bbb',
|
||||
globalRole: {
|
||||
id: '1',
|
||||
name: 'owner',
|
||||
scope: 'global',
|
||||
},
|
||||
},
|
||||
'bbb-bbb': {
|
||||
id: 'bbb-bbb',
|
||||
globalRoleId: 2,
|
||||
globalRole: {
|
||||
id: '2',
|
||||
name: 'member',
|
||||
scope: 'global',
|
||||
},
|
||||
},
|
||||
'bbb-bbb': {
|
||||
id: 'bbb-bbb',
|
||||
globalRoleId: 2,
|
||||
globalRole: {
|
||||
id: '2',
|
||||
name: 'member',
|
||||
scope: 'global',
|
||||
},
|
||||
},
|
||||
},
|
||||
}),
|
||||
},
|
||||
};
|
||||
|
||||
const renderComponent = (renderOptions: Parameters<typeof render>[1] = {}) =>
|
||||
render(BannerStack, merge(DEFAULT_SETUP, renderOptions), (vue) => {
|
||||
vue.use(PiniaVuePlugin);
|
||||
});
|
||||
const defaultRenderOptions: RenderOptions = {
|
||||
pinia: createTestingPinia({ initialState }),
|
||||
};
|
||||
|
||||
const renderComponent = createComponentRenderer(BannerStack, defaultRenderOptions);
|
||||
|
||||
describe('BannerStack', () => {
|
||||
beforeEach(() => {
|
||||
|
@ -82,19 +79,17 @@ describe('BannerStack', () => {
|
|||
it('should not render dismissed banners', async () => {
|
||||
const { getByTestId } = renderComponent({
|
||||
pinia: createTestingPinia({
|
||||
initialState: merge(
|
||||
{
|
||||
[STORES.UI]: {
|
||||
banners: {
|
||||
V1: { dismissed: true },
|
||||
TRIAL: { dismissed: true },
|
||||
},
|
||||
initialState: merge(initialState, {
|
||||
[STORES.UI]: {
|
||||
banners: {
|
||||
V1: { dismissed: true },
|
||||
TRIAL: { dismissed: true },
|
||||
},
|
||||
},
|
||||
DEFAULT_SETUP.pinia,
|
||||
),
|
||||
}),
|
||||
}),
|
||||
});
|
||||
|
||||
const bannerStack = getByTestId('banner-stack');
|
||||
expect(bannerStack).toBeInTheDocument();
|
||||
|
||||
|
@ -117,7 +112,7 @@ describe('BannerStack', () => {
|
|||
it('should permanently dismiss banner on click', async () => {
|
||||
const { getByTestId } = renderComponent({
|
||||
pinia: createTestingPinia({
|
||||
initialState: merge(DEFAULT_SETUP.pinia, {
|
||||
initialState: merge(initialState, {
|
||||
[STORES.UI]: {
|
||||
banners: {
|
||||
V1: { dismissed: false },
|
||||
|
@ -139,7 +134,7 @@ describe('BannerStack', () => {
|
|||
it('should not render permanent dismiss link if user is not owner', async () => {
|
||||
const { queryByTestId } = renderComponent({
|
||||
pinia: createTestingPinia({
|
||||
initialState: merge(DEFAULT_SETUP.pinia, {
|
||||
initialState: merge(initialState, {
|
||||
[STORES.USERS]: {
|
||||
currentUserId: 'bbb-bbb',
|
||||
},
|
||||
|
|
|
@ -1,29 +1,15 @@
|
|||
import { describe, test, expect } from 'vitest';
|
||||
import Vue from 'vue';
|
||||
import { PiniaVuePlugin } from 'pinia';
|
||||
import { createTestingPinia } from '@pinia/testing';
|
||||
import type { RenderOptions } from '@testing-library/vue';
|
||||
import { render } from '@testing-library/vue';
|
||||
import userEvent from '@testing-library/user-event';
|
||||
import { faker } from '@faker-js/faker';
|
||||
import ExecutionFilter from '@/components/ExecutionFilter.vue';
|
||||
import { STORES } from '@/constants';
|
||||
import { i18nInstance } from '@/plugins/i18n';
|
||||
import type { IWorkflowShortResponse, ExecutionFilterType } from '@/Interface';
|
||||
import { useTelemetry } from '@/composables';
|
||||
|
||||
vi.mock('@/composables', () => {
|
||||
const track = vi.fn();
|
||||
return {
|
||||
useTelemetry: () => ({
|
||||
track,
|
||||
}),
|
||||
};
|
||||
});
|
||||
|
||||
let telemetry: ReturnType<typeof useTelemetry>;
|
||||
|
||||
Vue.use(PiniaVuePlugin);
|
||||
import { createComponentRenderer } from '@/__tests__/render';
|
||||
import * as telemetryModule from '@/composables/useTelemetry';
|
||||
import type { Telemetry } from '@/plugins/telemetry';
|
||||
import { merge } from 'lodash-es';
|
||||
import { nextTick } from 'vue';
|
||||
|
||||
const defaultFilterState: ExecutionFilterType = {
|
||||
status: 'all',
|
||||
|
@ -65,13 +51,36 @@ const initialState = {
|
|||
},
|
||||
};
|
||||
|
||||
const renderOptions: RenderOptions<ExecutionFilter> = {
|
||||
i18n: i18nInstance,
|
||||
};
|
||||
const renderComponent = createComponentRenderer(ExecutionFilter, {
|
||||
props: {
|
||||
teleported: false,
|
||||
},
|
||||
});
|
||||
|
||||
describe('ExecutionFilter', () => {
|
||||
beforeEach(() => {
|
||||
telemetry = useTelemetry();
|
||||
afterAll(() => {
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
|
||||
test('telemetry sent only once after component is mounted', async () => {
|
||||
const track = vi.fn();
|
||||
const spy = vi.spyOn(telemetryModule, 'useTelemetry');
|
||||
spy.mockImplementation(
|
||||
() =>
|
||||
({
|
||||
track,
|
||||
} as unknown as Telemetry),
|
||||
);
|
||||
|
||||
const { getByTestId } = renderComponent({
|
||||
pinia: createTestingPinia({ initialState }),
|
||||
});
|
||||
const customDataKeyInput = getByTestId('execution-filter-saved-data-key-input');
|
||||
|
||||
await userEvent.type(customDataKeyInput, 'test');
|
||||
await userEvent.type(customDataKeyInput, 'key');
|
||||
|
||||
expect(track).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
test.each([
|
||||
|
@ -86,30 +95,49 @@ describe('ExecutionFilter', () => {
|
|||
])(
|
||||
'renders in %s environment on %s deployment with advancedExecutionFilters %s and workflows %s',
|
||||
async (environment, deployment, advancedExecutionFilters, workflows) => {
|
||||
initialState[STORES.SETTINGS].settings.license.environment = environment;
|
||||
initialState[STORES.SETTINGS].settings.deployment.type = deployment;
|
||||
initialState[STORES.SETTINGS].settings.enterprise.advancedExecutionFilters =
|
||||
advancedExecutionFilters;
|
||||
|
||||
renderOptions.pinia = createTestingPinia({ initialState });
|
||||
renderOptions.props = { workflows };
|
||||
|
||||
const { getByTestId, queryByTestId } = render(ExecutionFilter, renderOptions);
|
||||
const { html, getByTestId, queryByTestId, queryAllByTestId } = renderComponent({
|
||||
props: { workflows },
|
||||
pinia: createTestingPinia({
|
||||
initialState: merge(initialState, {
|
||||
[STORES.SETTINGS]: {
|
||||
settings: {
|
||||
license: {
|
||||
environment,
|
||||
},
|
||||
deployment: {
|
||||
type: deployment,
|
||||
},
|
||||
enterprise: {
|
||||
advancedExecutionFilters,
|
||||
},
|
||||
},
|
||||
},
|
||||
}),
|
||||
}),
|
||||
});
|
||||
|
||||
await userEvent.click(getByTestId('executions-filter-button'));
|
||||
await userEvent.hover(getByTestId('execution-filter-saved-data-key-input'));
|
||||
|
||||
if (advancedExecutionFilters) {
|
||||
expect(queryByTestId('executions-filter-view-plans-link')).not.toBeInTheDocument();
|
||||
expect(queryByTestId('executions-filter-view-plans-link')).not.toBeVisible();
|
||||
}
|
||||
|
||||
expect(queryByTestId('executions-filter-reset-button')).not.toBeInTheDocument();
|
||||
expect(!!queryByTestId('executions-filter-workflows-select')).toBe(!!workflows?.length);
|
||||
|
||||
const select = queryByTestId('executions-filter-workflows-select');
|
||||
if (workflows && workflows.length > 0) {
|
||||
expect(select).toBeVisible();
|
||||
} else {
|
||||
expect(select).not.toBeInTheDocument();
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
test('state change', async () => {
|
||||
const { getByTestId, queryByTestId, emitted } = render(ExecutionFilter, renderOptions);
|
||||
const { html, getByTestId, queryByTestId, emitted } = renderComponent({
|
||||
pinia: createTestingPinia({ initialState }),
|
||||
});
|
||||
|
||||
const filterChangedEvent = emitted().filterChanged;
|
||||
expect(filterChangedEvent).toHaveLength(1);
|
||||
|
@ -123,6 +151,7 @@ describe('ExecutionFilter', () => {
|
|||
expect(getByTestId('execution-filter-form')).toBeVisible();
|
||||
|
||||
await userEvent.click(getByTestId('executions-filter-status-select'));
|
||||
|
||||
await userEvent.click(getByTestId('executions-filter-status-select').querySelectorAll('li')[1]);
|
||||
|
||||
expect(emitted().filterChanged).toHaveLength(2);
|
||||
|
@ -136,14 +165,4 @@ describe('ExecutionFilter', () => {
|
|||
expect(queryByTestId('executions-filter-reset-button')).not.toBeInTheDocument();
|
||||
expect(queryByTestId('execution-filter-badge')).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
test('telemetry sent only once after component is mounted', async () => {
|
||||
const { getByTestId } = render(ExecutionFilter, renderOptions);
|
||||
const customDataKeyInput = getByTestId('execution-filter-saved-data-key-input');
|
||||
|
||||
await userEvent.type(customDataKeyInput, 'test');
|
||||
await userEvent.type(customDataKeyInput, 'key');
|
||||
|
||||
expect(telemetry.track).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,17 +1,15 @@
|
|||
import { vi, describe, it, expect } from 'vitest';
|
||||
import { merge } from 'lodash-es';
|
||||
import { PiniaVuePlugin } from 'pinia';
|
||||
import { createTestingPinia } from '@pinia/testing';
|
||||
import { render } from '@testing-library/vue';
|
||||
import userEvent from '@testing-library/user-event';
|
||||
import { faker } from '@faker-js/faker';
|
||||
import { STORES } from '@/constants';
|
||||
import ExecutionsList from '@/components/ExecutionsList.vue';
|
||||
import { i18nInstance } from '@/plugins/i18n';
|
||||
import type { IWorkflowDb } from '@/Interface';
|
||||
import type { IExecutionsSummary } from 'n8n-workflow';
|
||||
import { retry, SETTINGS_STORE_DEFAULT_STATE, waitAllPromises } from '@/__tests__/utils';
|
||||
import { useWorkflowsStore } from '@/stores';
|
||||
import { RenderOptions, createComponentRenderer } from '@/__tests__/render';
|
||||
|
||||
let pinia: ReturnType<typeof createTestingPinia>;
|
||||
|
||||
|
@ -65,28 +63,19 @@ const generateExecutionsData = () =>
|
|||
estimated: false,
|
||||
}));
|
||||
|
||||
const renderComponent = async () => {
|
||||
const renderResult = render(
|
||||
ExecutionsList,
|
||||
{
|
||||
pinia,
|
||||
propsData: {
|
||||
autoRefreshEnabled: false,
|
||||
},
|
||||
i18n: i18nInstance,
|
||||
const defaultRenderOptions: RenderOptions = {
|
||||
props: {
|
||||
autoRefreshEnabled: false,
|
||||
},
|
||||
global: {
|
||||
stubs: {
|
||||
stubs: ['font-awesome-icon'],
|
||||
},
|
||||
(vue) => {
|
||||
vue.use(PiniaVuePlugin);
|
||||
vue.prototype.$telemetry = {
|
||||
track: () => {},
|
||||
};
|
||||
},
|
||||
);
|
||||
await waitAllPromises();
|
||||
return renderResult;
|
||||
},
|
||||
};
|
||||
|
||||
const renderComponent = createComponentRenderer(ExecutionsList, defaultRenderOptions);
|
||||
|
||||
describe('ExecutionsList.vue', () => {
|
||||
let workflowsStore: ReturnType<typeof useWorkflowsStore>;
|
||||
let workflowsData: IWorkflowDb[];
|
||||
|
@ -123,7 +112,13 @@ describe('ExecutionsList.vue', () => {
|
|||
results: [],
|
||||
estimated: false,
|
||||
});
|
||||
const { queryAllByTestId, queryByTestId, getByTestId } = await renderComponent();
|
||||
const { queryAllByTestId, queryByTestId, getByTestId } = renderComponent({
|
||||
global: {
|
||||
plugins: [pinia],
|
||||
},
|
||||
});
|
||||
await waitAllPromises();
|
||||
|
||||
await userEvent.click(getByTestId('execution-auto-refresh-checkbox'));
|
||||
|
||||
expect(queryAllByTestId('select-execution-checkbox').length).toBe(0);
|
||||
|
@ -138,7 +133,12 @@ describe('ExecutionsList.vue', () => {
|
|||
.mockResolvedValueOnce(executionsData[0])
|
||||
.mockResolvedValueOnce(executionsData[1]);
|
||||
|
||||
const { getByTestId, getAllByTestId, queryByTestId } = await renderComponent();
|
||||
const { getByTestId, getAllByTestId, queryByTestId } = renderComponent({
|
||||
global: {
|
||||
plugins: [pinia],
|
||||
},
|
||||
});
|
||||
await waitAllPromises();
|
||||
|
||||
expect(storeSpy).toHaveBeenCalledTimes(1);
|
||||
|
||||
|
@ -192,7 +192,12 @@ describe('ExecutionsList.vue', () => {
|
|||
(execution) => !execution.retryOf && execution.retrySuccessId,
|
||||
);
|
||||
|
||||
const { queryAllByText } = await renderComponent();
|
||||
const { queryAllByText } = renderComponent({
|
||||
global: {
|
||||
plugins: [pinia],
|
||||
},
|
||||
});
|
||||
await waitAllPromises();
|
||||
|
||||
expect(queryAllByText(/Retry of/).length).toBe(retryOf.length);
|
||||
expect(queryAllByText(/Success retry/).length).toBe(retrySuccessId.length);
|
||||
|
|
|
@ -1,32 +1,20 @@
|
|||
import { describe, it, expect, vi } from 'vitest';
|
||||
import { render, waitFor } from '@testing-library/vue';
|
||||
import { waitFor } from '@testing-library/vue';
|
||||
import userEvent from '@testing-library/user-event';
|
||||
import { PiniaVuePlugin } from 'pinia';
|
||||
import { createTestingPinia } from '@pinia/testing';
|
||||
import { merge } from 'lodash-es';
|
||||
import { SOURCE_CONTROL_PULL_MODAL_KEY, STORES } from '@/constants';
|
||||
import { i18nInstance } from '@/plugins/i18n';
|
||||
import { SETTINGS_STORE_DEFAULT_STATE } from '@/__tests__/utils';
|
||||
import MainSidebarSourceControl from '@/components/MainSidebarSourceControl.vue';
|
||||
import { useSourceControlStore, useUIStore } from '@/stores';
|
||||
import { useSourceControlStore } from '@/stores/sourceControl.store';
|
||||
import { useUIStore } from '@/stores/ui.store';
|
||||
import { createComponentRenderer } from '@/__tests__/render';
|
||||
|
||||
let pinia: ReturnType<typeof createTestingPinia>;
|
||||
let sourceControlStore: ReturnType<typeof useSourceControlStore>;
|
||||
let uiStore: ReturnType<typeof useUIStore>;
|
||||
|
||||
const renderComponent = (renderOptions: Parameters<typeof render>[1] = {}) => {
|
||||
return render(
|
||||
MainSidebarSourceControl,
|
||||
{
|
||||
pinia,
|
||||
i18n: i18nInstance,
|
||||
...renderOptions,
|
||||
},
|
||||
(vue) => {
|
||||
vue.use(PiniaVuePlugin);
|
||||
},
|
||||
);
|
||||
};
|
||||
const renderComponent = createComponentRenderer(MainSidebarSourceControl);
|
||||
|
||||
describe('MainSidebarSourceControl', () => {
|
||||
const getItemSpy = vi.spyOn(Storage.prototype, 'getItem');
|
||||
|
@ -47,12 +35,22 @@ describe('MainSidebarSourceControl', () => {
|
|||
|
||||
it('should render nothing', async () => {
|
||||
getItemSpy.mockReturnValue(null);
|
||||
const { container } = renderComponent({ props: { isCollapsed: false } });
|
||||
const { container } = renderComponent({
|
||||
props: { isCollapsed: false },
|
||||
global: {
|
||||
plugins: [pinia],
|
||||
},
|
||||
});
|
||||
expect(container).toBeEmptyDOMElement();
|
||||
});
|
||||
|
||||
it('should render empty content', async () => {
|
||||
const { getByTestId } = renderComponent({ props: { isCollapsed: false } });
|
||||
const { getByTestId } = renderComponent({
|
||||
props: { isCollapsed: false },
|
||||
global: {
|
||||
plugins: [pinia],
|
||||
},
|
||||
});
|
||||
expect(getByTestId('main-sidebar-source-control')).toBeInTheDocument();
|
||||
expect(getByTestId('main-sidebar-source-control')).toBeEmptyDOMElement();
|
||||
});
|
||||
|
@ -73,7 +71,12 @@ describe('MainSidebarSourceControl', () => {
|
|||
});
|
||||
|
||||
it('should render the appropriate content', async () => {
|
||||
const { getByTestId, queryByTestId } = renderComponent({ props: { isCollapsed: false } });
|
||||
const { getByTestId, queryByTestId } = renderComponent({
|
||||
props: { isCollapsed: false },
|
||||
global: {
|
||||
plugins: [pinia],
|
||||
},
|
||||
});
|
||||
expect(getByTestId('main-sidebar-source-control-connected')).toBeInTheDocument();
|
||||
expect(queryByTestId('main-sidebar-source-control-setup')).not.toBeInTheDocument();
|
||||
});
|
||||
|
@ -82,7 +85,12 @@ describe('MainSidebarSourceControl', () => {
|
|||
vi.spyOn(sourceControlStore, 'pullWorkfolder').mockRejectedValueOnce({
|
||||
response: { status: 400 },
|
||||
});
|
||||
const { getAllByRole, getByRole } = renderComponent({ props: { isCollapsed: false } });
|
||||
const { getAllByRole, getByRole } = renderComponent({
|
||||
props: { isCollapsed: false },
|
||||
global: {
|
||||
plugins: [pinia],
|
||||
},
|
||||
});
|
||||
|
||||
await userEvent.click(getAllByRole('button')[0]);
|
||||
await waitFor(() => expect(getByRole('alert')).toBeInTheDocument());
|
||||
|
@ -95,7 +103,12 @@ describe('MainSidebarSourceControl', () => {
|
|||
});
|
||||
const openModalSpy = vi.spyOn(uiStore, 'openModalWithData');
|
||||
|
||||
const { getAllByRole, getByRole } = renderComponent({ props: { isCollapsed: false } });
|
||||
const { getAllByRole, getByRole } = renderComponent({
|
||||
props: { isCollapsed: false },
|
||||
global: {
|
||||
plugins: [pinia],
|
||||
},
|
||||
});
|
||||
|
||||
await userEvent.click(getAllByRole('button')[0]);
|
||||
await waitFor(() =>
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
import { PiniaVuePlugin } from 'pinia';
|
||||
import { createLocalVue, mount } from '@vue/test-utils';
|
||||
import PersonalizationModal from '@/components/PersonalizationModal.vue';
|
||||
import { createTestingPinia } from '@pinia/testing';
|
||||
import { PERSONALIZATION_MODAL_KEY } from '@/constants';
|
||||
import { retry } from '@/__tests__/utils';
|
||||
import { createComponentRenderer } from '@/__tests__/render';
|
||||
import { fireEvent } from '@testing-library/vue';
|
||||
|
||||
describe('PersonalizationModal.vue', () => {
|
||||
const pinia = createTestingPinia({
|
||||
const renderComponent = createComponentRenderer(PersonalizationModal, {
|
||||
pinia: createTestingPinia({
|
||||
initialState: {
|
||||
ui: {
|
||||
modals: {
|
||||
|
@ -21,41 +21,42 @@ describe('PersonalizationModal.vue', () => {
|
|||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
const localVue = createLocalVue();
|
||||
localVue.use(PiniaVuePlugin);
|
||||
}),
|
||||
});
|
||||
|
||||
describe('PersonalizationModal.vue', () => {
|
||||
it('should render correctly', async () => {
|
||||
const wrapper = mount(PersonalizationModal, {
|
||||
localVue,
|
||||
pinia,
|
||||
});
|
||||
const wrapper = renderComponent();
|
||||
|
||||
await retry(() => expect(wrapper.find('.modal-content').exists()).toBe(true));
|
||||
await retry(() =>
|
||||
expect(wrapper.container.querySelector('.modal-content')).toBeInTheDocument(),
|
||||
);
|
||||
|
||||
expect(wrapper.findAll('.n8n-select').length).toEqual(5);
|
||||
expect(wrapper.container.querySelectorAll('.n8n-select').length).toEqual(5);
|
||||
expect(wrapper.html()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should display new option when role is "Devops", "Engineering", "IT", or "Sales and marketing"', async () => {
|
||||
const wrapper = mount(PersonalizationModal, {
|
||||
localVue,
|
||||
pinia,
|
||||
});
|
||||
const wrapper = renderComponent();
|
||||
|
||||
await retry(() => expect(wrapper.find('.modal-content').exists()).toBe(true));
|
||||
await retry(() =>
|
||||
expect(wrapper.container.querySelector('.modal-content')).toBeInTheDocument(),
|
||||
);
|
||||
|
||||
for (const index of [3, 4, 5, 6]) {
|
||||
await wrapper.find('.n8n-select[name="role"]').trigger('click');
|
||||
await wrapper
|
||||
.find('.n8n-select[name="role"]')
|
||||
.findAll('.el-select-dropdown__item')
|
||||
.at(index)
|
||||
.trigger('click');
|
||||
const select = wrapper.container.querySelector('.n8n-select[name="role"]')!;
|
||||
|
||||
await fireEvent.click(select);
|
||||
|
||||
const item = select.querySelectorAll('.el-select-dropdown__item')[index];
|
||||
|
||||
await fireEvent.click(item);
|
||||
|
||||
await retry(() => {
|
||||
expect(wrapper.findAll('.n8n-select').length).toEqual(6);
|
||||
expect(wrapper.find('.n8n-select[name^="automationGoal"]').exists()).toBe(true);
|
||||
expect(wrapper.container.querySelectorAll('.n8n-select').length).toEqual(6);
|
||||
expect(
|
||||
wrapper.container.querySelector('.n8n-select[name^="automationGoal"]'),
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
}
|
||||
});
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
import { PiniaVuePlugin } from 'pinia';
|
||||
import { render, within } from '@testing-library/vue';
|
||||
import { merge } from 'lodash-es';
|
||||
import {
|
||||
DEFAULT_SETUP,
|
||||
MAPPING_COLUMNS_RESPONSE,
|
||||
|
@ -12,13 +10,11 @@ import { waitAllPromises } from '@/__tests__/utils';
|
|||
import * as workflowHelpers from '@/mixins/workflowHelpers';
|
||||
import ResourceMapper from '@/components/ResourceMapper/ResourceMapper.vue';
|
||||
import userEvent from '@testing-library/user-event';
|
||||
import { createComponentRenderer } from '@/__tests__/render';
|
||||
|
||||
let nodeTypeStore: ReturnType<typeof useNodeTypesStore>;
|
||||
|
||||
const renderComponent = (renderOptions: Parameters<typeof render>[1] = {}) =>
|
||||
render(ResourceMapper, merge(DEFAULT_SETUP, renderOptions), (vue) => {
|
||||
vue.use(PiniaVuePlugin);
|
||||
});
|
||||
const renderComponent = createComponentRenderer(ResourceMapper, DEFAULT_SETUP);
|
||||
|
||||
describe('ResourceMapper.vue', () => {
|
||||
beforeEach(() => {
|
||||
|
@ -44,18 +40,21 @@ describe('ResourceMapper.vue', () => {
|
|||
).toBe(MAPPING_COLUMNS_RESPONSE.fields.length);
|
||||
});
|
||||
|
||||
it('renders add mode properly', async () => {
|
||||
const { getByTestId, queryByTestId } = renderComponent({
|
||||
props: {
|
||||
parameter: {
|
||||
typeOptions: {
|
||||
resourceMapper: {
|
||||
mode: 'add',
|
||||
it('renders add mode properly', async () => {
|
||||
const { getByTestId, queryByTestId } = renderComponent(
|
||||
{
|
||||
props: {
|
||||
parameter: {
|
||||
typeOptions: {
|
||||
resourceMapper: {
|
||||
mode: 'add',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
{ merge: true },
|
||||
);
|
||||
await waitAllPromises();
|
||||
expect(getByTestId('resource-mapper-container')).toBeInTheDocument();
|
||||
// This mode doesn't render matching column selector
|
||||
|
@ -63,54 +62,63 @@ describe('ResourceMapper.vue', () => {
|
|||
});
|
||||
|
||||
it('renders multi-key match selector properly', async () => {
|
||||
const { container, getByTestId } = renderComponent({
|
||||
props: {
|
||||
parameter: {
|
||||
typeOptions: {
|
||||
resourceMapper: {
|
||||
mode: 'upsert',
|
||||
multiKeyMatch: true,
|
||||
const { container, getByTestId } = renderComponent(
|
||||
{
|
||||
props: {
|
||||
parameter: {
|
||||
typeOptions: {
|
||||
resourceMapper: {
|
||||
mode: 'upsert',
|
||||
multiKeyMatch: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
{ merge: true },
|
||||
);
|
||||
await waitAllPromises();
|
||||
expect(getByTestId('resource-mapper-container')).toBeInTheDocument();
|
||||
expect(container.querySelector('.el-select__tags')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('does not render mapping mode selector if it is disabled', async () => {
|
||||
const { getByTestId, queryByTestId } = renderComponent({
|
||||
props: {
|
||||
parameter: {
|
||||
typeOptions: {
|
||||
resourceMapper: {
|
||||
supportAutoMap: false,
|
||||
const { getByTestId, queryByTestId } = renderComponent(
|
||||
{
|
||||
props: {
|
||||
parameter: {
|
||||
typeOptions: {
|
||||
resourceMapper: {
|
||||
supportAutoMap: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
{ merge: true },
|
||||
);
|
||||
await waitAllPromises();
|
||||
expect(getByTestId('resource-mapper-container')).toBeInTheDocument();
|
||||
expect(queryByTestId('mapping-mode-select')).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('renders field on top of the list when they are selected for matching', async () => {
|
||||
const { container, getByTestId } = renderComponent({
|
||||
props: {
|
||||
parameter: {
|
||||
typeOptions: {
|
||||
resourceMapper: {
|
||||
supportAutoMap: true,
|
||||
mode: 'upsert',
|
||||
multiKeyMatch: false,
|
||||
const { container, getByTestId } = renderComponent(
|
||||
{
|
||||
props: {
|
||||
parameter: {
|
||||
typeOptions: {
|
||||
resourceMapper: {
|
||||
supportAutoMap: true,
|
||||
mode: 'upsert',
|
||||
multiKeyMatch: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
{ merge: true },
|
||||
);
|
||||
await waitAllPromises();
|
||||
expect(getByTestId('resource-mapper-container')).toBeInTheDocument();
|
||||
// Id should be the first field in the list
|
||||
|
@ -124,19 +132,22 @@ describe('ResourceMapper.vue', () => {
|
|||
});
|
||||
|
||||
it('renders selected matching columns properly when multiple key matching is enabled', async () => {
|
||||
const { getByTestId, getByText, queryByText } = renderComponent({
|
||||
props: {
|
||||
parameter: {
|
||||
typeOptions: {
|
||||
resourceMapper: {
|
||||
supportAutoMap: true,
|
||||
mode: 'upsert',
|
||||
multiKeyMatch: true,
|
||||
const { getByTestId, getByText, queryByText } = renderComponent(
|
||||
{
|
||||
props: {
|
||||
parameter: {
|
||||
typeOptions: {
|
||||
resourceMapper: {
|
||||
supportAutoMap: true,
|
||||
mode: 'upsert',
|
||||
multiKeyMatch: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
{ merge: true },
|
||||
);
|
||||
await waitAllPromises();
|
||||
expect(getByTestId('resource-mapper-container')).toBeInTheDocument();
|
||||
const matchingColumnDropdown = getByTestId('matching-column-select');
|
||||
|
@ -156,20 +167,23 @@ describe('ResourceMapper.vue', () => {
|
|||
});
|
||||
|
||||
it('uses field words defined in node definition', async () => {
|
||||
const { getByText } = renderComponent({
|
||||
props: {
|
||||
parameter: {
|
||||
typeOptions: {
|
||||
resourceMapper: {
|
||||
fieldWords: {
|
||||
singular: 'foo',
|
||||
plural: 'foos',
|
||||
const { getByText } = renderComponent(
|
||||
{
|
||||
props: {
|
||||
parameter: {
|
||||
typeOptions: {
|
||||
resourceMapper: {
|
||||
fieldWords: {
|
||||
singular: 'foo',
|
||||
plural: 'foos',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
{ merge: true },
|
||||
);
|
||||
await waitAllPromises();
|
||||
expect(getByText('Set the value for each foo')).toBeInTheDocument();
|
||||
expect(
|
||||
|
@ -180,24 +194,27 @@ describe('ResourceMapper.vue', () => {
|
|||
});
|
||||
|
||||
it('should render correct fields based on saved schema', async () => {
|
||||
const { getByTestId, queryAllByTestId } = renderComponent({
|
||||
props: {
|
||||
node: {
|
||||
parameters: {
|
||||
columns: {
|
||||
schema: UPDATED_SCHEMA,
|
||||
const { getByTestId, queryAllByTestId } = renderComponent(
|
||||
{
|
||||
props: {
|
||||
node: {
|
||||
parameters: {
|
||||
columns: {
|
||||
schema: UPDATED_SCHEMA,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
parameter: {
|
||||
typeOptions: {
|
||||
resourceMapper: {
|
||||
mode: 'add',
|
||||
parameter: {
|
||||
typeOptions: {
|
||||
resourceMapper: {
|
||||
mode: 'add',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
{ merge: true },
|
||||
);
|
||||
await waitAllPromises();
|
||||
// There should be 5 fields rendered and only 2 of them should have remove button
|
||||
expect(
|
||||
|
@ -207,24 +224,27 @@ describe('ResourceMapper.vue', () => {
|
|||
});
|
||||
|
||||
it('should render correct options based on saved schema', async () => {
|
||||
const { getByTestId } = renderComponent({
|
||||
props: {
|
||||
node: {
|
||||
parameters: {
|
||||
columns: {
|
||||
schema: UPDATED_SCHEMA,
|
||||
const { getByTestId } = renderComponent(
|
||||
{
|
||||
props: {
|
||||
node: {
|
||||
parameters: {
|
||||
columns: {
|
||||
schema: UPDATED_SCHEMA,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
parameter: {
|
||||
typeOptions: {
|
||||
resourceMapper: {
|
||||
mode: 'add',
|
||||
parameter: {
|
||||
typeOptions: {
|
||||
resourceMapper: {
|
||||
mode: 'add',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
{ merge: true },
|
||||
);
|
||||
await waitAllPromises();
|
||||
// Should have one option in the bottom dropdown for one removed field
|
||||
expect(getByTestId('add-fields-select').querySelectorAll('li').length).toBe(1);
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
import type Vue from 'vue';
|
||||
import { defineComponent } from 'vue';
|
||||
import { PiniaVuePlugin } from 'pinia';
|
||||
import { render, waitFor } from '@testing-library/vue';
|
||||
import { waitFor } from '@testing-library/vue';
|
||||
import userEvent from '@testing-library/user-event';
|
||||
import { createTestingPinia } from '@pinia/testing';
|
||||
import { merge } from 'lodash-es';
|
||||
|
@ -9,142 +7,41 @@ import RunData from '@/components/RunData.vue';
|
|||
import { STORES, VIEWS } from '@/constants';
|
||||
import { useSSOStore } from '@/stores/sso.store';
|
||||
import { SETTINGS_STORE_DEFAULT_STATE } from '@/__tests__/utils';
|
||||
import { externalHooks } from '@/mixins/externalHooks';
|
||||
import { genericHelpers } from '@/mixins/genericHelpers';
|
||||
import { pinData } from '@/mixins/pinData';
|
||||
import { useNDVStore, useWorkflowsStore } from '@/stores';
|
||||
import { createComponentRenderer } from '@/__tests__/render';
|
||||
|
||||
let pinia: ReturnType<typeof createTestingPinia>;
|
||||
let ssoStore: ReturnType<typeof useSSOStore>;
|
||||
let workflowsStore: ReturnType<typeof useWorkflowsStore>;
|
||||
let ndvStore: ReturnType<typeof useNDVStore>;
|
||||
|
||||
function TelemetryPlugin(vue: typeof Vue): void {
|
||||
Object.defineProperty(vue, '$telemetry', {
|
||||
get() {
|
||||
return {
|
||||
track: () => {},
|
||||
};
|
||||
},
|
||||
});
|
||||
Object.defineProperty(vue.prototype, '$telemetry', {
|
||||
get() {
|
||||
return {
|
||||
track: () => {},
|
||||
};
|
||||
},
|
||||
});
|
||||
}
|
||||
// const nodeHelpers = defineComponent({
|
||||
// methods: {
|
||||
// getNodeInputData: vi.fn().mockReturnValue(),
|
||||
// },
|
||||
// });
|
||||
|
||||
const nodeHelpers = defineComponent({
|
||||
methods: {
|
||||
getNodeInputData: vi.fn().mockReturnValue([
|
||||
{
|
||||
json: {
|
||||
id: 1,
|
||||
name: 'Test 1',
|
||||
json: {
|
||||
data: 'Json data 1',
|
||||
},
|
||||
},
|
||||
const renderComponent = createComponentRenderer(RunData, {
|
||||
props: {
|
||||
nodeUi: {
|
||||
name: 'Test Node',
|
||||
},
|
||||
},
|
||||
global: {
|
||||
mocks: {
|
||||
$route: {
|
||||
name: VIEWS.WORKFLOW,
|
||||
},
|
||||
{
|
||||
json: {
|
||||
id: 2,
|
||||
name: 'Test 2',
|
||||
json: {
|
||||
data: 'Json data 2',
|
||||
},
|
||||
},
|
||||
},
|
||||
]),
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const renderComponent = (renderOptions: Parameters<typeof render>[1] = {}) =>
|
||||
render(
|
||||
RunData,
|
||||
merge(
|
||||
{
|
||||
pinia,
|
||||
mocks: {
|
||||
$route: {
|
||||
name: VIEWS.WORKFLOW,
|
||||
},
|
||||
},
|
||||
mixins: [externalHooks, genericHelpers, nodeHelpers, pinData],
|
||||
},
|
||||
renderOptions,
|
||||
),
|
||||
(vue) => {
|
||||
vue.use(TelemetryPlugin);
|
||||
vue.use(PiniaVuePlugin);
|
||||
},
|
||||
);
|
||||
|
||||
describe('RunData', () => {
|
||||
beforeEach(() => {
|
||||
pinia = createTestingPinia({
|
||||
initialState: {
|
||||
[STORES.SETTINGS]: {
|
||||
settings: merge({}, SETTINGS_STORE_DEFAULT_STATE.settings),
|
||||
},
|
||||
},
|
||||
});
|
||||
ssoStore = useSSOStore();
|
||||
workflowsStore = useWorkflowsStore();
|
||||
ndvStore = useNDVStore();
|
||||
|
||||
vi.spyOn(workflowsStore, 'getWorkflowExecution', 'get').mockReturnValue({
|
||||
id: '1',
|
||||
finished: true,
|
||||
mode: 'trigger',
|
||||
startedAt: new Date(),
|
||||
workflowData: {
|
||||
id: '1',
|
||||
name: 'Test Workflow',
|
||||
versionId: '1',
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
active: false,
|
||||
nodes: [],
|
||||
connections: {},
|
||||
},
|
||||
data: {
|
||||
resultData: {
|
||||
runData: {
|
||||
'Test Node': [
|
||||
{
|
||||
startTime: new Date().getTime(),
|
||||
executionTime: new Date().getTime(),
|
||||
data: {},
|
||||
source: [null],
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
|
||||
it('should render data correctly even when "item.json" has another "json" key', async () => {
|
||||
vi.spyOn(ndvStore, 'getPanelDisplayMode').mockReturnValue('schema');
|
||||
vi.spyOn(ndvStore, 'activeNode', 'get').mockReturnValue({
|
||||
id: '1',
|
||||
typeVersion: 1,
|
||||
name: 'Test Node',
|
||||
position: [0, 0],
|
||||
type: 'test',
|
||||
parameters: {},
|
||||
});
|
||||
|
||||
const { getByText, getAllByTestId, getByTestId } = renderComponent({
|
||||
const { html, getByText, getAllByTestId, getByTestId } = renderComponent({
|
||||
props: {
|
||||
nodeUi: {
|
||||
id: '1',
|
||||
name: 'Test Node',
|
||||
position: [0, 0],
|
||||
},
|
||||
|
@ -154,10 +51,90 @@ describe('RunData', () => {
|
|||
mappingEnabled: true,
|
||||
distanceFromActive: 0,
|
||||
},
|
||||
pinia: createTestingPinia({
|
||||
initialState: {
|
||||
[STORES.SETTINGS]: {
|
||||
settings: merge({}, SETTINGS_STORE_DEFAULT_STATE.settings),
|
||||
},
|
||||
[STORES.NDV]: {
|
||||
output: {
|
||||
displayMode: 'schema',
|
||||
},
|
||||
activeNodeName: 'Test Node',
|
||||
},
|
||||
[STORES.WORKFLOWS]: {
|
||||
workflow: {
|
||||
nodes: [
|
||||
{
|
||||
id: '1',
|
||||
typeVersion: 1,
|
||||
name: 'Test Node',
|
||||
position: [0, 0],
|
||||
type: 'test',
|
||||
parameters: {},
|
||||
},
|
||||
],
|
||||
},
|
||||
workflowExecutionData: {
|
||||
id: '1',
|
||||
finished: true,
|
||||
mode: 'trigger',
|
||||
startedAt: new Date(),
|
||||
workflowData: {
|
||||
id: '1',
|
||||
name: 'Test Workflow',
|
||||
versionId: '1',
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
active: false,
|
||||
nodes: [],
|
||||
connections: {},
|
||||
},
|
||||
data: {
|
||||
resultData: {
|
||||
runData: {
|
||||
'Test Node': [
|
||||
{
|
||||
startTime: new Date().getTime(),
|
||||
executionTime: new Date().getTime(),
|
||||
data: {
|
||||
main: [
|
||||
[
|
||||
{
|
||||
json: {
|
||||
id: 1,
|
||||
name: 'Test 1',
|
||||
json: {
|
||||
data: 'Json data 1',
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
json: {
|
||||
id: 2,
|
||||
name: 'Test 2',
|
||||
json: {
|
||||
data: 'Json data 2',
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
],
|
||||
},
|
||||
source: [null],
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}),
|
||||
});
|
||||
|
||||
await userEvent.click(getByTestId('ndv-pin-data'));
|
||||
await waitFor(() => getAllByTestId('run-data-schema-item'));
|
||||
await waitFor(() => getAllByTestId('run-data-schema-item'), { timeout: 1000 });
|
||||
expect(getByText('Test 1')).toBeInTheDocument();
|
||||
expect(getByText('Json data 1')).toBeInTheDocument();
|
||||
});
|
||||
|
|
|
@ -1,44 +1,40 @@
|
|||
import Vue from 'vue';
|
||||
import { PiniaVuePlugin } from 'pinia';
|
||||
import { createTestingPinia } from '@pinia/testing';
|
||||
import { render, screen, cleanup } from '@testing-library/vue';
|
||||
import { screen, cleanup } from '@testing-library/vue';
|
||||
import RunDataJson from '@/components/RunDataJson.vue';
|
||||
import { createComponentRenderer } from '@/__tests__/render';
|
||||
|
||||
Vue.use(PiniaVuePlugin);
|
||||
|
||||
describe('RunDataJson.vue', () => {
|
||||
const DEFAULT_SETUP = {
|
||||
pinia: createTestingPinia(),
|
||||
props: {
|
||||
mappingEnabled: true,
|
||||
editMode: { enabled: false },
|
||||
inputData: [
|
||||
{
|
||||
json: {
|
||||
list: [1, 2, 3],
|
||||
record: { name: 'Joe' },
|
||||
myNumber: 123,
|
||||
myStringNumber: '456',
|
||||
myStringText: 'abc',
|
||||
nil: null,
|
||||
d: undefined,
|
||||
},
|
||||
const renderComponent = createComponentRenderer(RunDataJson, {
|
||||
props: {
|
||||
mappingEnabled: true,
|
||||
editMode: { enabled: false },
|
||||
inputData: [
|
||||
{
|
||||
json: {
|
||||
list: [1, 2, 3],
|
||||
record: { name: 'Joe' },
|
||||
myNumber: 123,
|
||||
myStringNumber: '456',
|
||||
myStringText: 'abc',
|
||||
nil: null,
|
||||
d: undefined,
|
||||
},
|
||||
],
|
||||
node: {
|
||||
parameters: {
|
||||
keepOnlySet: false,
|
||||
values: {},
|
||||
options: {},
|
||||
},
|
||||
id: '820ea733-d8a6-4379-8e73-88a2347ea003',
|
||||
name: 'Set',
|
||||
type: 'n8n-nodes-base.set',
|
||||
typeVersion: 1,
|
||||
position: [380, 1060],
|
||||
disabled: false,
|
||||
},
|
||||
],
|
||||
node: {
|
||||
parameters: {
|
||||
keepOnlySet: false,
|
||||
values: {},
|
||||
options: {},
|
||||
},
|
||||
id: '820ea733-d8a6-4379-8e73-88a2347ea003',
|
||||
name: 'Set',
|
||||
type: 'n8n-nodes-base.set',
|
||||
typeVersion: 1,
|
||||
position: [380, 1060],
|
||||
disabled: false,
|
||||
},
|
||||
},
|
||||
global: {
|
||||
mocks: {
|
||||
$locale: {
|
||||
baseText() {
|
||||
|
@ -49,13 +45,17 @@ describe('RunDataJson.vue', () => {
|
|||
getters: {},
|
||||
},
|
||||
},
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
describe('RunDataJson.vue', () => {
|
||||
beforeEach(cleanup);
|
||||
|
||||
it('renders json values properly', () => {
|
||||
const { container } = render(RunDataJson, DEFAULT_SETUP, (vue) => {
|
||||
vue.use(PiniaVuePlugin);
|
||||
const { container } = renderComponent({
|
||||
global: {
|
||||
plugins: [createTestingPinia()],
|
||||
},
|
||||
});
|
||||
expect(container).toMatchSnapshot();
|
||||
|
||||
|
@ -67,7 +67,11 @@ describe('RunDataJson.vue', () => {
|
|||
});
|
||||
|
||||
it('sets ph-no-capture class correctly', () => {
|
||||
render(RunDataJson, DEFAULT_SETUP);
|
||||
renderComponent({
|
||||
global: {
|
||||
plugins: [createTestingPinia()],
|
||||
},
|
||||
});
|
||||
|
||||
expect(screen.getByText('"list"')).not.toHaveClass('ph-no-capture');
|
||||
expect(screen.getByText('"record"')).not.toHaveClass('ph-no-capture');
|
||||
|
|
|
@ -1,82 +1,86 @@
|
|||
import { PiniaVuePlugin } from 'pinia';
|
||||
import { createTestingPinia } from '@pinia/testing';
|
||||
import { render, cleanup } from '@testing-library/vue';
|
||||
import RunDataJsonSchema from '@/components/RunDataSchema.vue';
|
||||
import { STORES } from '@/constants';
|
||||
import { createComponentRenderer } from '@/__tests__/render';
|
||||
|
||||
describe('RunDataJsonSchema.vue', () => {
|
||||
const renderOptions = {
|
||||
pinia: createTestingPinia({
|
||||
initialState: {
|
||||
[STORES.SETTINGS]: {
|
||||
settings: {
|
||||
templates: {
|
||||
enabled: true,
|
||||
host: 'https://api.n8n.io/api/',
|
||||
const renderComponent = createComponentRenderer(RunDataJsonSchema, {
|
||||
global: {
|
||||
stubs: ['font-awesome-icon'],
|
||||
plugins: [
|
||||
createTestingPinia({
|
||||
initialState: {
|
||||
[STORES.SETTINGS]: {
|
||||
settings: {
|
||||
templates: {
|
||||
enabled: true,
|
||||
host: 'https://api.n8n.io/api/',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}),
|
||||
],
|
||||
},
|
||||
props: {
|
||||
mappingEnabled: true,
|
||||
distanceFromActive: 1,
|
||||
runIndex: 1,
|
||||
totalRuns: 2,
|
||||
paneType: 'input',
|
||||
node: {
|
||||
parameters: {
|
||||
keepOnlySet: false,
|
||||
values: {},
|
||||
options: {},
|
||||
},
|
||||
}),
|
||||
stubs: ['font-awesome-icon'],
|
||||
props: {
|
||||
mappingEnabled: true,
|
||||
distanceFromActive: 1,
|
||||
runIndex: 1,
|
||||
totalRuns: 2,
|
||||
paneType: 'input',
|
||||
node: {
|
||||
parameters: {
|
||||
keepOnlySet: false,
|
||||
values: {},
|
||||
options: {},
|
||||
},
|
||||
id: '820ea733-d8a6-4379-8e73-88a2347ea003',
|
||||
name: 'Set',
|
||||
type: 'n8n-nodes-base.set',
|
||||
typeVersion: 1,
|
||||
position: [380, 1060],
|
||||
disabled: false,
|
||||
},
|
||||
data: [{}],
|
||||
id: '820ea733-d8a6-4379-8e73-88a2347ea003',
|
||||
name: 'Set',
|
||||
type: 'n8n-nodes-base.set',
|
||||
typeVersion: 1,
|
||||
position: [380, 1060],
|
||||
disabled: false,
|
||||
},
|
||||
};
|
||||
data: [{}],
|
||||
},
|
||||
});
|
||||
|
||||
describe('RunDataJsonSchema.vue', () => {
|
||||
beforeEach(cleanup);
|
||||
|
||||
it('renders schema for empty data', () => {
|
||||
const { container } = render(RunDataJsonSchema, renderOptions, (vue) => {
|
||||
vue.use(PiniaVuePlugin);
|
||||
});
|
||||
const { container } = renderComponent();
|
||||
expect(container).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('renders schema for data', () => {
|
||||
renderOptions.props.data = [
|
||||
{ name: 'John', age: 22, hobbies: ['surfing', 'traveling'] },
|
||||
{ name: 'Joe', age: 33, hobbies: ['skateboarding', 'gaming'] },
|
||||
];
|
||||
const { container } = render(RunDataJsonSchema, renderOptions, (vue) => {
|
||||
vue.use(PiniaVuePlugin);
|
||||
const { container } = renderComponent({
|
||||
props: {
|
||||
data: [
|
||||
{ name: 'John', age: 22, hobbies: ['surfing', 'traveling'] },
|
||||
{ name: 'Joe', age: 33, hobbies: ['skateboarding', 'gaming'] },
|
||||
],
|
||||
},
|
||||
});
|
||||
expect(container).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('renders schema with spaces and dots', () => {
|
||||
renderOptions.props.data = [
|
||||
{
|
||||
'hello world': [
|
||||
const { container } = renderComponent({
|
||||
props: {
|
||||
data: [
|
||||
{
|
||||
test: {
|
||||
'more to think about': 1,
|
||||
},
|
||||
'test.how': 'ignore',
|
||||
'hello world': [
|
||||
{
|
||||
test: {
|
||||
'more to think about': 1,
|
||||
},
|
||||
'test.how': 'ignore',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
const { container } = render(RunDataJsonSchema, renderOptions, (vue) => {
|
||||
vue.use(PiniaVuePlugin);
|
||||
});
|
||||
expect(container).toMatchSnapshot();
|
||||
});
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
import { render } from '@testing-library/vue';
|
||||
import { PiniaVuePlugin } from 'pinia';
|
||||
import { SETTINGS_STORE_DEFAULT_STATE, waitAllPromises } from '@/__tests__/utils';
|
||||
import { STORES } from '@/constants';
|
||||
import { createTestingPinia } from '@pinia/testing';
|
||||
|
@ -7,6 +5,10 @@ import { createTestingPinia } from '@pinia/testing';
|
|||
import SqlEditor from '@/components/SqlEditor/SqlEditor.vue';
|
||||
import { expressionManager } from '@/mixins/expressionManager';
|
||||
import type { TargetItem } from '@/Interface';
|
||||
import { N8nPlugin } from 'n8n-design-system/plugin';
|
||||
import { PiniaVuePlugin } from 'pinia';
|
||||
import { GlobalDirectivesPlugin } from '@/plugins/directives';
|
||||
import { renderComponent } from '@/__tests__/render';
|
||||
|
||||
const EXPRESSION_OUTPUT_TEST_ID = 'inline-expression-editor-output';
|
||||
|
||||
|
@ -19,24 +21,23 @@ const RESOLVABLES: { [key: string]: string | number | boolean } = {
|
|||
};
|
||||
|
||||
const DEFAULT_SETUP = {
|
||||
pinia: createTestingPinia({
|
||||
initialState: {
|
||||
[STORES.SETTINGS]: {
|
||||
settings: SETTINGS_STORE_DEFAULT_STATE.settings,
|
||||
},
|
||||
},
|
||||
}),
|
||||
props: {
|
||||
dialect: 'PostgreSQL',
|
||||
isReadOnly: false,
|
||||
},
|
||||
global: {
|
||||
plugins: [
|
||||
createTestingPinia({
|
||||
initialState: {
|
||||
[STORES.SETTINGS]: {
|
||||
settings: SETTINGS_STORE_DEFAULT_STATE.settings,
|
||||
},
|
||||
},
|
||||
}),
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
const renderComponent = (renderOptions: Parameters<typeof render>[1] = {}) =>
|
||||
render(SqlEditor, { ...DEFAULT_SETUP, ...renderOptions }, (vue) => {
|
||||
vue.use(PiniaVuePlugin);
|
||||
});
|
||||
|
||||
describe('SQL Editor Preview Tests', () => {
|
||||
beforeEach(() => {
|
||||
vi.spyOn(expressionManager.methods, 'resolve').mockImplementation(
|
||||
|
@ -51,9 +52,11 @@ describe('SQL Editor Preview Tests', () => {
|
|||
});
|
||||
|
||||
it('renders basic query', async () => {
|
||||
const { getByTestId } = renderComponent({
|
||||
const { getByTestId } = renderComponent(SqlEditor, {
|
||||
...DEFAULT_SETUP,
|
||||
props: {
|
||||
query: 'SELECT * FROM users',
|
||||
...DEFAULT_SETUP.props,
|
||||
modelValue: 'SELECT * FROM users',
|
||||
},
|
||||
});
|
||||
await waitAllPromises();
|
||||
|
@ -61,9 +64,11 @@ describe('SQL Editor Preview Tests', () => {
|
|||
});
|
||||
|
||||
it('renders basic query with expression', async () => {
|
||||
const { getByTestId } = renderComponent({
|
||||
const { getByTestId } = renderComponent(SqlEditor, {
|
||||
...DEFAULT_SETUP,
|
||||
props: {
|
||||
query: 'SELECT * FROM {{ $json.table }}',
|
||||
...DEFAULT_SETUP.props,
|
||||
modelValue: 'SELECT * FROM {{ $json.table }}',
|
||||
},
|
||||
});
|
||||
await waitAllPromises();
|
||||
|
@ -71,9 +76,11 @@ describe('SQL Editor Preview Tests', () => {
|
|||
});
|
||||
|
||||
it('renders resolved expressions with dot between resolvables', async () => {
|
||||
const { getByTestId } = renderComponent({
|
||||
const { getByTestId } = renderComponent(SqlEditor, {
|
||||
...DEFAULT_SETUP,
|
||||
props: {
|
||||
query: 'SELECT * FROM {{ $json.schema }}.{{ $json.table }}',
|
||||
...DEFAULT_SETUP.props,
|
||||
modelValue: 'SELECT * FROM {{ $json.schema }}.{{ $json.table }}',
|
||||
},
|
||||
});
|
||||
await waitAllPromises();
|
||||
|
@ -81,9 +88,11 @@ describe('SQL Editor Preview Tests', () => {
|
|||
});
|
||||
|
||||
it('renders resolved expressions which resolve to 0', async () => {
|
||||
const { getByTestId } = renderComponent({
|
||||
const { getByTestId } = renderComponent(SqlEditor, {
|
||||
...DEFAULT_SETUP,
|
||||
props: {
|
||||
query:
|
||||
...DEFAULT_SETUP.props,
|
||||
modelValue:
|
||||
'SELECT * FROM {{ $json.schema }}.{{ $json.table }} WHERE {{ $json.id }} > {{ $json.limit - 10 }}',
|
||||
},
|
||||
});
|
||||
|
@ -94,9 +103,11 @@ describe('SQL Editor Preview Tests', () => {
|
|||
});
|
||||
|
||||
it('keeps query formatting in rendered output', async () => {
|
||||
const { getByTestId } = renderComponent({
|
||||
const { getByTestId } = renderComponent(SqlEditor, {
|
||||
...DEFAULT_SETUP,
|
||||
props: {
|
||||
query:
|
||||
...DEFAULT_SETUP.props,
|
||||
modelValue:
|
||||
'SELECT * FROM {{ $json.schema }}.{{ $json.table }}\n WHERE id > {{ $json.limit - 10 }}\n AND active = {{ $json.active }};',
|
||||
},
|
||||
});
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
import { PiniaVuePlugin } from 'pinia';
|
||||
import { render } from '@testing-library/vue';
|
||||
import { createTestingPinia } from '@pinia/testing';
|
||||
import { merge } from 'lodash-es';
|
||||
|
@ -16,18 +15,17 @@ const renderComponent = (renderOptions: Parameters<typeof render>[1] = {}) =>
|
|||
SSOLogin,
|
||||
merge(
|
||||
{
|
||||
pinia,
|
||||
stubs: {
|
||||
'n8n-button': {
|
||||
template: '<button data-test-id="sso-button"></button>',
|
||||
store: pinia,
|
||||
global: {
|
||||
stubs: {
|
||||
'n8n-button': {
|
||||
template: '<button data-test-id="sso-button"></button>',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
renderOptions,
|
||||
),
|
||||
(vue) => {
|
||||
vue.use(PiniaVuePlugin);
|
||||
},
|
||||
);
|
||||
|
||||
describe('SSOLogin', () => {
|
||||
|
|
|
@ -1,24 +1,38 @@
|
|||
import VariablesRow from '../VariablesRow.vue';
|
||||
import type { EnvironmentVariable } from '@/Interface';
|
||||
import { fireEvent } from '@testing-library/vue';
|
||||
import { createPinia, setActivePinia } from 'pinia';
|
||||
import { setupServer } from '@/__tests__/server';
|
||||
import { afterAll, beforeAll } from 'vitest';
|
||||
import { useSettingsStore, useUsersStore } from '@/stores';
|
||||
import { renderComponent } from '@/__tests__/utils';
|
||||
import { createComponentRenderer } from '@/__tests__/render';
|
||||
import { createTestingPinia } from '@pinia/testing';
|
||||
import { STORES } from '@/constants';
|
||||
|
||||
const renderComponent = createComponentRenderer(VariablesRow, {
|
||||
pinia: createTestingPinia({
|
||||
initialState: {
|
||||
[STORES.SETTINGS]: {
|
||||
settings: {
|
||||
enterprise: {
|
||||
variables: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}),
|
||||
global: {
|
||||
stubs: ['n8n-tooltip'],
|
||||
},
|
||||
});
|
||||
|
||||
describe('VariablesRow', () => {
|
||||
let server: ReturnType<typeof setupServer>;
|
||||
let pinia: ReturnType<typeof createPinia>;
|
||||
|
||||
beforeAll(() => {
|
||||
server = setupServer();
|
||||
});
|
||||
|
||||
beforeEach(async () => {
|
||||
pinia = createPinia();
|
||||
setActivePinia(pinia);
|
||||
|
||||
await useSettingsStore().getSettings();
|
||||
await useUsersStore().loginWithCookie();
|
||||
});
|
||||
|
@ -27,8 +41,6 @@ describe('VariablesRow', () => {
|
|||
server.shutdown();
|
||||
});
|
||||
|
||||
const stubs = ['n8n-tooltip'];
|
||||
|
||||
const environmentVariable: EnvironmentVariable = {
|
||||
id: 1,
|
||||
key: 'key',
|
||||
|
@ -36,12 +48,10 @@ describe('VariablesRow', () => {
|
|||
};
|
||||
|
||||
it('should render correctly', () => {
|
||||
const wrapper = renderComponent(VariablesRow, {
|
||||
const wrapper = renderComponent({
|
||||
props: {
|
||||
data: environmentVariable,
|
||||
},
|
||||
stubs,
|
||||
pinia,
|
||||
});
|
||||
|
||||
expect(wrapper.html()).toMatchSnapshot();
|
||||
|
@ -49,12 +59,10 @@ describe('VariablesRow', () => {
|
|||
});
|
||||
|
||||
it('should show edit and delete buttons on hover', async () => {
|
||||
const wrapper = renderComponent(VariablesRow, {
|
||||
const wrapper = renderComponent({
|
||||
props: {
|
||||
data: environmentVariable,
|
||||
},
|
||||
stubs,
|
||||
pinia,
|
||||
});
|
||||
|
||||
await fireEvent.mouseEnter(wrapper.container);
|
||||
|
@ -64,13 +72,11 @@ describe('VariablesRow', () => {
|
|||
});
|
||||
|
||||
it('should show key and value inputs in edit mode', async () => {
|
||||
const wrapper = renderComponent(VariablesRow, {
|
||||
const wrapper = renderComponent({
|
||||
props: {
|
||||
data: environmentVariable,
|
||||
editing: true,
|
||||
},
|
||||
stubs,
|
||||
pinia,
|
||||
});
|
||||
|
||||
await fireEvent.mouseEnter(wrapper.container);
|
||||
|
@ -88,13 +94,11 @@ describe('VariablesRow', () => {
|
|||
});
|
||||
|
||||
it('should show cancel and save buttons in edit mode', async () => {
|
||||
const wrapper = renderComponent(VariablesRow, {
|
||||
const wrapper = renderComponent({
|
||||
props: {
|
||||
data: environmentVariable,
|
||||
editing: true,
|
||||
},
|
||||
stubs,
|
||||
pinia,
|
||||
});
|
||||
|
||||
await fireEvent.mouseEnter(wrapper.container);
|
||||
|
|
|
@ -1,284 +0,0 @@
|
|||
// Vitest Snapshot v1
|
||||
|
||||
exports[`PersonalizationModal.vue > should render correctly 1`] = `
|
||||
"<transition-stub name=\\"dialog-fade\\" data-test-id=\\"personalization-form\\" class=\\"dialog-wrapper\\" style=\\"z-index: 2001;\\">
|
||||
<div class=\\"el-dialog__wrapper\\">
|
||||
<div role=\\"dialog\\" aria-modal=\\"true\\" aria-label=\\"dialog\\" class=\\"el-dialog\\" style=\\"margin-top: 15vh; width: 460px;\\">
|
||||
<div class=\\"el-dialog__header\\">
|
||||
<div class=\\"centerTitle\\">
|
||||
<div>
|
||||
<h1 class=\\"n8n-heading size-xlarge regular\\">Customize n8n to you</h1>
|
||||
</div>
|
||||
<div class=\\"subtitle\\">
|
||||
<h3 class=\\"n8n-heading text-light size-small regular\\">These questions help us tailor n8n to you</h3>
|
||||
</div>
|
||||
</div>
|
||||
<!---->
|
||||
</div>
|
||||
<div class=\\"el-dialog__body\\">
|
||||
<div class=\\"modal-content\\">
|
||||
<div class=\\"container\\">
|
||||
<div>
|
||||
<div class=\\"grid\\">
|
||||
<div class=\\"\\">
|
||||
<div class=\\"container\\" data-test-id=\\"companyType\\"><label for=\\"companyType\\" class=\\"n8n-input-label inputLabel heading medium\\">
|
||||
<div class=\\"title\\"><span class=\\"n8n-text size-medium bold\\"> What best describes your company? <!----></span></div>
|
||||
<!---->
|
||||
<!---->
|
||||
<!---->
|
||||
</label>
|
||||
<div class=\\"\\">
|
||||
<div class=\\"n8n-select container\\" name=\\"companyType\\">
|
||||
<!---->
|
||||
<div class=\\"el-select el-select--large\\">
|
||||
<!---->
|
||||
<div class=\\"el-input el-input--large el-input--suffix\\">
|
||||
<!----><input type=\\"text\\" readonly=\\"readonly\\" autocomplete=\\"off\\" placeholder=\\"Select...\\" class=\\"el-input__inner\\">
|
||||
<!----><span class=\\"el-input__suffix\\"><span class=\\"el-input__suffix-inner\\"><i class=\\"el-select__caret el-input__icon el-icon-arrow-up\\"></i><!----><!----><!----><!----><!----></span>
|
||||
<!----></span>
|
||||
<!---->
|
||||
<!---->
|
||||
</div>
|
||||
<transition-stub name=\\"el-zoom-in-top\\">
|
||||
<div class=\\"el-select-dropdown el-popper\\" style=\\"display: none;\\">
|
||||
<div class=\\"el-scrollbar\\" style=\\"\\">
|
||||
<div class=\\"el-select-dropdown__wrap el-scrollbar__wrap el-scrollbar__wrap--hidden-default\\">
|
||||
<ul class=\\"el-scrollbar__view el-select-dropdown__list\\">
|
||||
<!---->
|
||||
<li class=\\"el-select-dropdown__item\\"><span>Software as a service</span></li>
|
||||
<li class=\\"el-select-dropdown__item\\"><span>Ecommerce</span></li>
|
||||
<li class=\\"el-select-dropdown__item\\"><span>Marketing agency / consultancy</span></li>
|
||||
<li class=\\"el-select-dropdown__item\\"><span>Systems integrator / Automation agency</span></li>
|
||||
<li class=\\"el-select-dropdown__item\\"><span>Education</span></li>
|
||||
<li class=\\"el-select-dropdown__item\\"><span>Other</span></li>
|
||||
<li class=\\"el-select-dropdown__item\\"><span>I'm not using n8n for work</span></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class=\\"el-scrollbar__bar is-horizontal\\">
|
||||
<div class=\\"el-scrollbar__thumb\\" style=\\"transform: translateX(0%); webkit-transform: translateX(0%);\\"></div>
|
||||
</div>
|
||||
<div class=\\"el-scrollbar__bar is-vertical\\">
|
||||
<div class=\\"el-scrollbar__thumb\\" style=\\"transform: translateY(0%); webkit-transform: translateY(0%);\\"></div>
|
||||
</div>
|
||||
</div>
|
||||
<!---->
|
||||
</div>
|
||||
</transition-stub>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!---->
|
||||
</div>
|
||||
</div>
|
||||
<div class=\\"\\">
|
||||
<div class=\\"container\\" data-test-id=\\"role\\"><label for=\\"role\\" class=\\"n8n-input-label inputLabel heading medium\\">
|
||||
<div class=\\"title\\"><span class=\\"n8n-text size-medium bold\\"> Which role best describes you? <!----></span></div>
|
||||
<!---->
|
||||
<!---->
|
||||
<!---->
|
||||
</label>
|
||||
<div class=\\"\\">
|
||||
<div class=\\"n8n-select container\\" name=\\"role\\">
|
||||
<!---->
|
||||
<div class=\\"el-select el-select--large\\">
|
||||
<!---->
|
||||
<div class=\\"el-input el-input--large el-input--suffix\\">
|
||||
<!----><input type=\\"text\\" readonly=\\"readonly\\" autocomplete=\\"off\\" placeholder=\\"Select...\\" class=\\"el-input__inner\\">
|
||||
<!----><span class=\\"el-input__suffix\\"><span class=\\"el-input__suffix-inner\\"><i class=\\"el-select__caret el-input__icon el-icon-arrow-up\\"></i><!----><!----><!----><!----><!----></span>
|
||||
<!----></span>
|
||||
<!---->
|
||||
<!---->
|
||||
</div>
|
||||
<transition-stub name=\\"el-zoom-in-top\\">
|
||||
<div class=\\"el-select-dropdown el-popper\\" style=\\"display: none;\\">
|
||||
<div class=\\"el-scrollbar\\" style=\\"\\">
|
||||
<div class=\\"el-select-dropdown__wrap el-scrollbar__wrap el-scrollbar__wrap--hidden-default\\">
|
||||
<ul class=\\"el-scrollbar__view el-select-dropdown__list\\">
|
||||
<!---->
|
||||
<li class=\\"el-select-dropdown__item\\"><span>Business Owner</span></li>
|
||||
<li class=\\"el-select-dropdown__item\\"><span>Customer support</span></li>
|
||||
<li class=\\"el-select-dropdown__item\\"><span>Data Science</span></li>
|
||||
<li class=\\"el-select-dropdown__item\\"><span>Devops</span></li>
|
||||
<li class=\\"el-select-dropdown__item\\"><span>IT</span></li>
|
||||
<li class=\\"el-select-dropdown__item\\"><span>Engineering</span></li>
|
||||
<li class=\\"el-select-dropdown__item\\"><span>Sales and Marketing</span></li>
|
||||
<li class=\\"el-select-dropdown__item\\"><span>Security</span></li>
|
||||
<li class=\\"el-select-dropdown__item\\"><span>Other (please specify)</span></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class=\\"el-scrollbar__bar is-horizontal\\">
|
||||
<div class=\\"el-scrollbar__thumb\\" style=\\"transform: translateX(0%); webkit-transform: translateX(0%);\\"></div>
|
||||
</div>
|
||||
<div class=\\"el-scrollbar__bar is-vertical\\">
|
||||
<div class=\\"el-scrollbar__thumb\\" style=\\"transform: translateY(0%); webkit-transform: translateY(0%);\\"></div>
|
||||
</div>
|
||||
</div>
|
||||
<!---->
|
||||
</div>
|
||||
</transition-stub>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!---->
|
||||
</div>
|
||||
</div>
|
||||
<div class=\\"\\">
|
||||
<div class=\\"container\\" data-test-id=\\"automationBeneficiary\\"><label for=\\"automationBeneficiary\\" class=\\"n8n-input-label inputLabel heading medium\\">
|
||||
<div class=\\"title\\"><span class=\\"n8n-text size-medium bold\\"> Who will your automations mainly be for? <!----></span></div>
|
||||
<!---->
|
||||
<!---->
|
||||
<!---->
|
||||
</label>
|
||||
<div class=\\"\\">
|
||||
<div class=\\"n8n-select container\\" name=\\"automationBeneficiary\\">
|
||||
<!---->
|
||||
<div class=\\"el-select el-select--large\\">
|
||||
<!---->
|
||||
<div class=\\"el-input el-input--large el-input--suffix\\">
|
||||
<!----><input type=\\"text\\" readonly=\\"readonly\\" autocomplete=\\"off\\" placeholder=\\"Select...\\" class=\\"el-input__inner\\">
|
||||
<!----><span class=\\"el-input__suffix\\"><span class=\\"el-input__suffix-inner\\"><i class=\\"el-select__caret el-input__icon el-icon-arrow-up\\"></i><!----><!----><!----><!----><!----></span>
|
||||
<!----></span>
|
||||
<!---->
|
||||
<!---->
|
||||
</div>
|
||||
<transition-stub name=\\"el-zoom-in-top\\">
|
||||
<div class=\\"el-select-dropdown el-popper\\" style=\\"display: none;\\">
|
||||
<div class=\\"el-scrollbar\\" style=\\"\\">
|
||||
<div class=\\"el-select-dropdown__wrap el-scrollbar__wrap el-scrollbar__wrap--hidden-default\\">
|
||||
<ul class=\\"el-scrollbar__view el-select-dropdown__list\\">
|
||||
<!---->
|
||||
<li class=\\"el-select-dropdown__item\\"><span>Myself</span></li>
|
||||
<li class=\\"el-select-dropdown__item\\"><span>My team</span></li>
|
||||
<li class=\\"el-select-dropdown__item\\"><span>Other teams</span></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class=\\"el-scrollbar__bar is-horizontal\\">
|
||||
<div class=\\"el-scrollbar__thumb\\" style=\\"transform: translateX(0%); webkit-transform: translateX(0%);\\"></div>
|
||||
</div>
|
||||
<div class=\\"el-scrollbar__bar is-vertical\\">
|
||||
<div class=\\"el-scrollbar__thumb\\" style=\\"transform: translateY(0%); webkit-transform: translateY(0%);\\"></div>
|
||||
</div>
|
||||
</div>
|
||||
<!---->
|
||||
</div>
|
||||
</transition-stub>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!---->
|
||||
</div>
|
||||
</div>
|
||||
<div class=\\"\\">
|
||||
<div class=\\"container\\" data-test-id=\\"companySize\\"><label for=\\"companySize\\" class=\\"n8n-input-label inputLabel heading medium\\">
|
||||
<div class=\\"title\\"><span class=\\"n8n-text size-medium bold\\"> How big is your company? <!----></span></div>
|
||||
<!---->
|
||||
<!---->
|
||||
<!---->
|
||||
</label>
|
||||
<div class=\\"\\">
|
||||
<div class=\\"n8n-select container\\" name=\\"companySize\\">
|
||||
<!---->
|
||||
<div class=\\"el-select el-select--large\\">
|
||||
<!---->
|
||||
<div class=\\"el-input el-input--large el-input--suffix\\">
|
||||
<!----><input type=\\"text\\" readonly=\\"readonly\\" autocomplete=\\"off\\" placeholder=\\"Select...\\" class=\\"el-input__inner\\">
|
||||
<!----><span class=\\"el-input__suffix\\"><span class=\\"el-input__suffix-inner\\"><i class=\\"el-select__caret el-input__icon el-icon-arrow-up\\"></i><!----><!----><!----><!----><!----></span>
|
||||
<!----></span>
|
||||
<!---->
|
||||
<!---->
|
||||
</div>
|
||||
<transition-stub name=\\"el-zoom-in-top\\">
|
||||
<div class=\\"el-select-dropdown el-popper\\" style=\\"display: none;\\">
|
||||
<div class=\\"el-scrollbar\\" style=\\"\\">
|
||||
<div class=\\"el-select-dropdown__wrap el-scrollbar__wrap el-scrollbar__wrap--hidden-default\\">
|
||||
<ul class=\\"el-scrollbar__view el-select-dropdown__list\\">
|
||||
<!---->
|
||||
<li class=\\"el-select-dropdown__item\\"><span>Less than 20 people</span></li>
|
||||
<li class=\\"el-select-dropdown__item\\"><span>20-99 people</span></li>
|
||||
<li class=\\"el-select-dropdown__item\\"><span>100-499 people</span></li>
|
||||
<li class=\\"el-select-dropdown__item\\"><span>500-999 people</span></li>
|
||||
<li class=\\"el-select-dropdown__item\\"><span>1000+ people</span></li>
|
||||
<li class=\\"el-select-dropdown__item\\"><span>I'm not using n8n for work</span></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class=\\"el-scrollbar__bar is-horizontal\\">
|
||||
<div class=\\"el-scrollbar__thumb\\" style=\\"transform: translateX(0%); webkit-transform: translateX(0%);\\"></div>
|
||||
</div>
|
||||
<div class=\\"el-scrollbar__bar is-vertical\\">
|
||||
<div class=\\"el-scrollbar__thumb\\" style=\\"transform: translateY(0%); webkit-transform: translateY(0%);\\"></div>
|
||||
</div>
|
||||
</div>
|
||||
<!---->
|
||||
</div>
|
||||
</transition-stub>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!---->
|
||||
</div>
|
||||
</div>
|
||||
<div class=\\"\\">
|
||||
<div class=\\"container\\" data-test-id=\\"reportedSource\\"><label for=\\"reportedSource\\" class=\\"n8n-input-label inputLabel heading medium\\">
|
||||
<div class=\\"title\\"><span class=\\"n8n-text size-medium bold\\"> How did you hear about n8n? <!----></span></div>
|
||||
<!---->
|
||||
<!---->
|
||||
<!---->
|
||||
</label>
|
||||
<div class=\\"\\">
|
||||
<div class=\\"n8n-select container\\" name=\\"reportedSource\\">
|
||||
<!---->
|
||||
<div class=\\"el-select el-select--large\\">
|
||||
<!---->
|
||||
<div class=\\"el-input el-input--large el-input--suffix\\">
|
||||
<!----><input type=\\"text\\" readonly=\\"readonly\\" autocomplete=\\"off\\" placeholder=\\"Select...\\" class=\\"el-input__inner\\">
|
||||
<!----><span class=\\"el-input__suffix\\"><span class=\\"el-input__suffix-inner\\"><i class=\\"el-select__caret el-input__icon el-icon-arrow-up\\"></i><!----><!----><!----><!----><!----></span>
|
||||
<!----></span>
|
||||
<!---->
|
||||
<!---->
|
||||
</div>
|
||||
<transition-stub name=\\"el-zoom-in-top\\">
|
||||
<div class=\\"el-select-dropdown el-popper\\" style=\\"display: none;\\">
|
||||
<div class=\\"el-scrollbar\\" style=\\"\\">
|
||||
<div class=\\"el-select-dropdown__wrap el-scrollbar__wrap el-scrollbar__wrap--hidden-default\\">
|
||||
<ul class=\\"el-scrollbar__view el-select-dropdown__list\\">
|
||||
<!---->
|
||||
<li class=\\"el-select-dropdown__item\\"><span>Google</span></li>
|
||||
<li class=\\"el-select-dropdown__item\\"><span>Twitter</span></li>
|
||||
<li class=\\"el-select-dropdown__item\\"><span>LinkedIn</span></li>
|
||||
<li class=\\"el-select-dropdown__item\\"><span>YouTube</span></li>
|
||||
<li class=\\"el-select-dropdown__item\\"><span>Friend / Word of mouth</span></li>
|
||||
<li class=\\"el-select-dropdown__item\\"><span>Podcast</span></li>
|
||||
<li class=\\"el-select-dropdown__item\\"><span>Event</span></li>
|
||||
<li class=\\"el-select-dropdown__item\\"><span>Other (please specify)</span></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class=\\"el-scrollbar__bar is-horizontal\\">
|
||||
<div class=\\"el-scrollbar__thumb\\" style=\\"transform: translateX(0%); webkit-transform: translateX(0%);\\"></div>
|
||||
</div>
|
||||
<div class=\\"el-scrollbar__bar is-vertical\\">
|
||||
<div class=\\"el-scrollbar__thumb\\" style=\\"transform: translateY(0%); webkit-transform: translateY(0%);\\"></div>
|
||||
</div>
|
||||
</div>
|
||||
<!---->
|
||||
</div>
|
||||
</transition-stub>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!---->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class=\\"footer\\">
|
||||
<div><button aria-live=\\"polite\\" class=\\"button button primary medium float-right\\">
|
||||
<!----><span>Get started</span></button></div>
|
||||
</div>
|
||||
</div>
|
||||
<!---->
|
||||
</div>
|
||||
</div>
|
||||
</transition-stub>"
|
||||
`;
|
File diff suppressed because it is too large
Load diff
|
@ -8,6 +8,7 @@ exports[`RunDataJsonSchema.vue > renders schema for data 1`] = `
|
|||
<div
|
||||
class=""
|
||||
>
|
||||
|
||||
<div
|
||||
class="schema"
|
||||
>
|
||||
|
@ -15,13 +16,14 @@ exports[`RunDataJsonSchema.vue > renders schema for data 1`] = `
|
|||
class="item"
|
||||
data-test-id="run-data-schema-item"
|
||||
>
|
||||
<!---->
|
||||
<!---->
|
||||
<!---->
|
||||
<!---->
|
||||
<!--v-if-->
|
||||
<!--v-if-->
|
||||
<!--v-if-->
|
||||
<!--v-if-->
|
||||
<div
|
||||
class="sub"
|
||||
>
|
||||
|
||||
<div
|
||||
class="item"
|
||||
data-test-id="run-data-schema-item"
|
||||
|
@ -39,11 +41,23 @@ exports[`RunDataJsonSchema.vue > renders schema for data 1`] = `
|
|||
data-target="mappable"
|
||||
data-value="{{ $json.name }}"
|
||||
>
|
||||
<font-awesome-icon-stub
|
||||
icon="font"
|
||||
size="sm"
|
||||
/>
|
||||
<!---->
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class="svg-inline--fa fa-font fa-w-14 fa-sm"
|
||||
data-icon="font"
|
||||
data-prefix="fas"
|
||||
focusable="false"
|
||||
role="img"
|
||||
viewBox="0 0 448 512"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
class=""
|
||||
d="M432 416h-23.41L277.88 53.69A32 32 0 0 0 247.58 32h-47.16a32 32 0 0 0-30.3 21.69L39.41 416H16a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h128a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16h-19.58l23.3-64h152.56l23.3 64H304a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h128a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16zM176.85 272L224 142.51 271.15 272z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
</svg>
|
||||
<!--v-if-->
|
||||
<span
|
||||
class=""
|
||||
>
|
||||
|
@ -52,13 +66,13 @@ exports[`RunDataJsonSchema.vue > renders schema for data 1`] = `
|
|||
</span>
|
||||
</div>
|
||||
<span
|
||||
class="ph-no-capture text"
|
||||
class="text ph-no-capture"
|
||||
>
|
||||
John
|
||||
</span>
|
||||
<!---->
|
||||
<!---->
|
||||
<!---->
|
||||
<!--v-if-->
|
||||
<!--v-if-->
|
||||
<!--v-if-->
|
||||
</div>
|
||||
<div
|
||||
class="item"
|
||||
|
@ -77,11 +91,23 @@ exports[`RunDataJsonSchema.vue > renders schema for data 1`] = `
|
|||
data-target="mappable"
|
||||
data-value="{{ $json.age }}"
|
||||
>
|
||||
<font-awesome-icon-stub
|
||||
icon="hashtag"
|
||||
size="sm"
|
||||
/>
|
||||
<!---->
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class="svg-inline--fa fa-hashtag fa-w-14 fa-sm"
|
||||
data-icon="hashtag"
|
||||
data-prefix="fas"
|
||||
focusable="false"
|
||||
role="img"
|
||||
viewBox="0 0 448 512"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
class=""
|
||||
d="M440.667 182.109l7.143-40c1.313-7.355-4.342-14.109-11.813-14.109h-74.81l14.623-81.891C377.123 38.754 371.468 32 363.997 32h-40.632a12 12 0 0 0-11.813 9.891L296.175 128H197.54l14.623-81.891C213.477 38.754 207.822 32 200.35 32h-40.632a12 12 0 0 0-11.813 9.891L132.528 128H53.432a12 12 0 0 0-11.813 9.891l-7.143 40C33.163 185.246 38.818 192 46.289 192h74.81L98.242 320H19.146a12 12 0 0 0-11.813 9.891l-7.143 40C-1.123 377.246 4.532 384 12.003 384h74.81L72.19 465.891C70.877 473.246 76.532 480 84.003 480h40.632a12 12 0 0 0 11.813-9.891L151.826 384h98.634l-14.623 81.891C234.523 473.246 240.178 480 247.65 480h40.632a12 12 0 0 0 11.813-9.891L315.472 384h79.096a12 12 0 0 0 11.813-9.891l7.143-40c1.313-7.355-4.342-14.109-11.813-14.109h-74.81l22.857-128h79.096a12 12 0 0 0 11.813-9.891zM261.889 320h-98.634l22.857-128h98.634l-22.857 128z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
</svg>
|
||||
<!--v-if-->
|
||||
<span
|
||||
class=""
|
||||
>
|
||||
|
@ -90,13 +116,13 @@ exports[`RunDataJsonSchema.vue > renders schema for data 1`] = `
|
|||
</span>
|
||||
</div>
|
||||
<span
|
||||
class="ph-no-capture text"
|
||||
class="text ph-no-capture"
|
||||
>
|
||||
22
|
||||
</span>
|
||||
<!---->
|
||||
<!---->
|
||||
<!---->
|
||||
<!--v-if-->
|
||||
<!--v-if-->
|
||||
<!--v-if-->
|
||||
</div>
|
||||
<div
|
||||
class="item"
|
||||
|
@ -115,11 +141,23 @@ exports[`RunDataJsonSchema.vue > renders schema for data 1`] = `
|
|||
data-target="mappable"
|
||||
data-value="{{ $json.hobbies }}"
|
||||
>
|
||||
<font-awesome-icon-stub
|
||||
icon="list"
|
||||
size="sm"
|
||||
/>
|
||||
<!---->
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class="svg-inline--fa fa-list fa-w-16 fa-sm"
|
||||
data-icon="list"
|
||||
data-prefix="fas"
|
||||
focusable="false"
|
||||
role="img"
|
||||
viewBox="0 0 512 512"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
class=""
|
||||
d="M80 368H16a16 16 0 0 0-16 16v64a16 16 0 0 0 16 16h64a16 16 0 0 0 16-16v-64a16 16 0 0 0-16-16zm0-320H16A16 16 0 0 0 0 64v64a16 16 0 0 0 16 16h64a16 16 0 0 0 16-16V64a16 16 0 0 0-16-16zm0 160H16a16 16 0 0 0-16 16v64a16 16 0 0 0 16 16h64a16 16 0 0 0 16-16v-64a16 16 0 0 0-16-16zm416 176H176a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h320a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16zm0-320H176a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h320a16 16 0 0 0 16-16V80a16 16 0 0 0-16-16zm0 160H176a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h320a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
</svg>
|
||||
<!--v-if-->
|
||||
<span
|
||||
class=""
|
||||
>
|
||||
|
@ -127,9 +165,8 @@ exports[`RunDataJsonSchema.vue > renders schema for data 1`] = `
|
|||
</span>
|
||||
</span>
|
||||
</div>
|
||||
<!---->
|
||||
<!--v-if-->
|
||||
<input
|
||||
checked="checked"
|
||||
id="input_array-0-2"
|
||||
type="checkbox"
|
||||
/>
|
||||
|
@ -137,13 +174,27 @@ exports[`RunDataJsonSchema.vue > renders schema for data 1`] = `
|
|||
class="toggle"
|
||||
for="input_array-0-2"
|
||||
>
|
||||
<font-awesome-icon-stub
|
||||
icon="angle-up"
|
||||
/>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class="svg-inline--fa fa-angle-up fa-w-10"
|
||||
data-icon="angle-up"
|
||||
data-prefix="fas"
|
||||
focusable="false"
|
||||
role="img"
|
||||
viewBox="0 0 320 512"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
class=""
|
||||
d="M177 159.7l136 136c9.4 9.4 9.4 24.6 0 33.9l-22.6 22.6c-9.4 9.4-24.6 9.4-33.9 0L160 255.9l-96.4 96.4c-9.4 9.4-24.6 9.4-33.9 0L7 329.7c-9.4-9.4-9.4-24.6 0-33.9l136-136c9.4-9.5 24.6-9.5 34-.1z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
</svg>
|
||||
</label>
|
||||
<div
|
||||
class="sub"
|
||||
>
|
||||
|
||||
<div
|
||||
class="item"
|
||||
data-test-id="run-data-schema-item"
|
||||
|
@ -161,10 +212,22 @@ exports[`RunDataJsonSchema.vue > renders schema for data 1`] = `
|
|||
data-target="mappable"
|
||||
data-value="{{ $json.hobbies[0] }}"
|
||||
>
|
||||
<font-awesome-icon-stub
|
||||
icon="font"
|
||||
size="sm"
|
||||
/>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class="svg-inline--fa fa-font fa-w-14 fa-sm"
|
||||
data-icon="font"
|
||||
data-prefix="fas"
|
||||
focusable="false"
|
||||
role="img"
|
||||
viewBox="0 0 448 512"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
class=""
|
||||
d="M432 416h-23.41L277.88 53.69A32 32 0 0 0 247.58 32h-47.16a32 32 0 0 0-30.3 21.69L39.41 416H16a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h128a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16h-19.58l23.3-64h152.56l23.3 64H304a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h128a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16zM176.85 272L224 142.51 271.15 272z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
</svg>
|
||||
<span>
|
||||
hobbies
|
||||
</span>
|
||||
|
@ -176,13 +239,13 @@ exports[`RunDataJsonSchema.vue > renders schema for data 1`] = `
|
|||
</span>
|
||||
</div>
|
||||
<span
|
||||
class="ph-no-capture text"
|
||||
class="text ph-no-capture"
|
||||
>
|
||||
surfing
|
||||
</span>
|
||||
<!---->
|
||||
<!---->
|
||||
<!---->
|
||||
<!--v-if-->
|
||||
<!--v-if-->
|
||||
<!--v-if-->
|
||||
</div>
|
||||
<div
|
||||
class="item"
|
||||
|
@ -201,10 +264,22 @@ exports[`RunDataJsonSchema.vue > renders schema for data 1`] = `
|
|||
data-target="mappable"
|
||||
data-value="{{ $json.hobbies[1] }}"
|
||||
>
|
||||
<font-awesome-icon-stub
|
||||
icon="font"
|
||||
size="sm"
|
||||
/>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class="svg-inline--fa fa-font fa-w-14 fa-sm"
|
||||
data-icon="font"
|
||||
data-prefix="fas"
|
||||
focusable="false"
|
||||
role="img"
|
||||
viewBox="0 0 448 512"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
class=""
|
||||
d="M432 416h-23.41L277.88 53.69A32 32 0 0 0 247.58 32h-47.16a32 32 0 0 0-30.3 21.69L39.41 416H16a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h128a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16h-19.58l23.3-64h152.56l23.3 64H304a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h128a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16zM176.85 272L224 142.51 271.15 272z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
</svg>
|
||||
<span>
|
||||
hobbies
|
||||
</span>
|
||||
|
@ -216,23 +291,24 @@ exports[`RunDataJsonSchema.vue > renders schema for data 1`] = `
|
|||
</span>
|
||||
</div>
|
||||
<span
|
||||
class="ph-no-capture text"
|
||||
class="text ph-no-capture"
|
||||
>
|
||||
traveling
|
||||
</span>
|
||||
<!---->
|
||||
<!---->
|
||||
<!---->
|
||||
<!--v-if-->
|
||||
<!--v-if-->
|
||||
<!--v-if-->
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="teleporter hidden"
|
||||
data-v-d4e6e290=""
|
||||
/>
|
||||
|
||||
<!--teleport start-->
|
||||
<!--teleport end-->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -250,15 +326,31 @@ exports[`RunDataJsonSchema.vue > renders schema for empty data 1`] = `
|
|||
class="iconText"
|
||||
>
|
||||
<span
|
||||
class="n8n-icon n8n-text compact size-medium regular"
|
||||
class="n8n-text compact size-medium regular n8n-icon n8n-icon"
|
||||
>
|
||||
<font-awesome-icon-stub
|
||||
class="medium"
|
||||
icon="info-circle"
|
||||
/>
|
||||
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class="svg-inline--fa fa-info-circle fa-w-16 medium"
|
||||
data-icon="info-circle"
|
||||
data-prefix="fas"
|
||||
focusable="false"
|
||||
role="img"
|
||||
viewBox="0 0 512 512"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
class=""
|
||||
d="M256 8C119.043 8 8 119.083 8 256c0 136.997 111.043 248 248 248s248-111.003 248-248C504 119.083 392.957 8 256 8zm0 110c23.196 0 42 18.804 42 42s-18.804 42-42 42-42-18.804-42-42 18.804-42 42-42zm56 254c0 6.627-5.373 12-12 12h-88c-6.627 0-12-5.373-12-12v-24c0-6.627 5.373-12 12-12h12v-64h-12c-6.627 0-12-5.373-12-12v-24c0-6.627 5.373-12 12-12h64c6.627 0 12 5.373 12 12v100h12c6.627 0 12 5.373 12 12v24z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
</svg>
|
||||
|
||||
</span>
|
||||
<span>
|
||||
|
||||
No data to show - item(s) exist, but they’re empty
|
||||
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
|
@ -274,6 +366,7 @@ exports[`RunDataJsonSchema.vue > renders schema with spaces and dots 1`] = `
|
|||
<div
|
||||
class=""
|
||||
>
|
||||
|
||||
<div
|
||||
class="schema"
|
||||
>
|
||||
|
@ -281,13 +374,14 @@ exports[`RunDataJsonSchema.vue > renders schema with spaces and dots 1`] = `
|
|||
class="item"
|
||||
data-test-id="run-data-schema-item"
|
||||
>
|
||||
<!---->
|
||||
<!---->
|
||||
<!---->
|
||||
<!---->
|
||||
<!--v-if-->
|
||||
<!--v-if-->
|
||||
<!--v-if-->
|
||||
<!--v-if-->
|
||||
<div
|
||||
class="sub"
|
||||
>
|
||||
|
||||
<div
|
||||
class="item"
|
||||
data-test-id="run-data-schema-item"
|
||||
|
@ -305,11 +399,23 @@ exports[`RunDataJsonSchema.vue > renders schema with spaces and dots 1`] = `
|
|||
data-target="mappable"
|
||||
data-value="{{ $json['hello world'] }}"
|
||||
>
|
||||
<font-awesome-icon-stub
|
||||
icon="list"
|
||||
size="sm"
|
||||
/>
|
||||
<!---->
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class="svg-inline--fa fa-list fa-w-16 fa-sm"
|
||||
data-icon="list"
|
||||
data-prefix="fas"
|
||||
focusable="false"
|
||||
role="img"
|
||||
viewBox="0 0 512 512"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
class=""
|
||||
d="M80 368H16a16 16 0 0 0-16 16v64a16 16 0 0 0 16 16h64a16 16 0 0 0 16-16v-64a16 16 0 0 0-16-16zm0-320H16A16 16 0 0 0 0 64v64a16 16 0 0 0 16 16h64a16 16 0 0 0 16-16V64a16 16 0 0 0-16-16zm0 160H16a16 16 0 0 0-16 16v64a16 16 0 0 0 16 16h64a16 16 0 0 0 16-16v-64a16 16 0 0 0-16-16zm416 176H176a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h320a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16zm0-320H176a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h320a16 16 0 0 0 16-16V80a16 16 0 0 0-16-16zm0 160H176a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h320a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
</svg>
|
||||
<!--v-if-->
|
||||
<span
|
||||
class=""
|
||||
>
|
||||
|
@ -317,9 +423,8 @@ exports[`RunDataJsonSchema.vue > renders schema with spaces and dots 1`] = `
|
|||
</span>
|
||||
</span>
|
||||
</div>
|
||||
<!---->
|
||||
<!--v-if-->
|
||||
<input
|
||||
checked="checked"
|
||||
id="input_array-0-0"
|
||||
type="checkbox"
|
||||
/>
|
||||
|
@ -327,13 +432,27 @@ exports[`RunDataJsonSchema.vue > renders schema with spaces and dots 1`] = `
|
|||
class="toggle"
|
||||
for="input_array-0-0"
|
||||
>
|
||||
<font-awesome-icon-stub
|
||||
icon="angle-up"
|
||||
/>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class="svg-inline--fa fa-angle-up fa-w-10"
|
||||
data-icon="angle-up"
|
||||
data-prefix="fas"
|
||||
focusable="false"
|
||||
role="img"
|
||||
viewBox="0 0 320 512"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
class=""
|
||||
d="M177 159.7l136 136c9.4 9.4 9.4 24.6 0 33.9l-22.6 22.6c-9.4 9.4-24.6 9.4-33.9 0L160 255.9l-96.4 96.4c-9.4 9.4-24.6 9.4-33.9 0L7 329.7c-9.4-9.4-9.4-24.6 0-33.9l136-136c9.4-9.5 24.6-9.5 34-.1z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
</svg>
|
||||
</label>
|
||||
<div
|
||||
class="sub"
|
||||
>
|
||||
|
||||
<div
|
||||
class="item"
|
||||
data-test-id="run-data-schema-item"
|
||||
|
@ -351,10 +470,22 @@ exports[`RunDataJsonSchema.vue > renders schema with spaces and dots 1`] = `
|
|||
data-target="mappable"
|
||||
data-value="{{ $json['hello world'][0] }}"
|
||||
>
|
||||
<font-awesome-icon-stub
|
||||
icon="cube"
|
||||
size="sm"
|
||||
/>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class="svg-inline--fa fa-cube fa-w-16 fa-sm"
|
||||
data-icon="cube"
|
||||
data-prefix="fas"
|
||||
focusable="false"
|
||||
role="img"
|
||||
viewBox="0 0 512 512"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
class=""
|
||||
d="M239.1 6.3l-208 78c-18.7 7-31.1 25-31.1 45v225.1c0 18.2 10.3 34.8 26.5 42.9l208 104c13.5 6.8 29.4 6.8 42.9 0l208-104c16.3-8.1 26.5-24.8 26.5-42.9V129.3c0-20-12.4-37.9-31.1-44.9l-208-78C262 2.2 250 2.2 239.1 6.3zM256 68.4l192 72v1.1l-192 78-192-78v-1.1l192-72zm32 356V275.5l160-65v133.9l-160 80z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
</svg>
|
||||
<span>
|
||||
hello world
|
||||
</span>
|
||||
|
@ -365,9 +496,8 @@ exports[`RunDataJsonSchema.vue > renders schema with spaces and dots 1`] = `
|
|||
</span>
|
||||
</span>
|
||||
</div>
|
||||
<!---->
|
||||
<!--v-if-->
|
||||
<input
|
||||
checked="checked"
|
||||
id="input_object-1-0"
|
||||
type="checkbox"
|
||||
/>
|
||||
|
@ -375,13 +505,27 @@ exports[`RunDataJsonSchema.vue > renders schema with spaces and dots 1`] = `
|
|||
class="toggle"
|
||||
for="input_object-1-0"
|
||||
>
|
||||
<font-awesome-icon-stub
|
||||
icon="angle-up"
|
||||
/>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class="svg-inline--fa fa-angle-up fa-w-10"
|
||||
data-icon="angle-up"
|
||||
data-prefix="fas"
|
||||
focusable="false"
|
||||
role="img"
|
||||
viewBox="0 0 320 512"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
class=""
|
||||
d="M177 159.7l136 136c9.4 9.4 9.4 24.6 0 33.9l-22.6 22.6c-9.4 9.4-24.6 9.4-33.9 0L160 255.9l-96.4 96.4c-9.4 9.4-24.6 9.4-33.9 0L7 329.7c-9.4-9.4-9.4-24.6 0-33.9l136-136c9.4-9.5 24.6-9.5 34-.1z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
</svg>
|
||||
</label>
|
||||
<div
|
||||
class="sub"
|
||||
>
|
||||
|
||||
<div
|
||||
class="item"
|
||||
data-test-id="run-data-schema-item"
|
||||
|
@ -399,11 +543,23 @@ exports[`RunDataJsonSchema.vue > renders schema with spaces and dots 1`] = `
|
|||
data-target="mappable"
|
||||
data-value="{{ $json['hello world'][0].test }}"
|
||||
>
|
||||
<font-awesome-icon-stub
|
||||
icon="cube"
|
||||
size="sm"
|
||||
/>
|
||||
<!---->
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class="svg-inline--fa fa-cube fa-w-16 fa-sm"
|
||||
data-icon="cube"
|
||||
data-prefix="fas"
|
||||
focusable="false"
|
||||
role="img"
|
||||
viewBox="0 0 512 512"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
class=""
|
||||
d="M239.1 6.3l-208 78c-18.7 7-31.1 25-31.1 45v225.1c0 18.2 10.3 34.8 26.5 42.9l208 104c13.5 6.8 29.4 6.8 42.9 0l208-104c16.3-8.1 26.5-24.8 26.5-42.9V129.3c0-20-12.4-37.9-31.1-44.9l-208-78C262 2.2 250 2.2 239.1 6.3zM256 68.4l192 72v1.1l-192 78-192-78v-1.1l192-72zm32 356V275.5l160-65v133.9l-160 80z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
</svg>
|
||||
<!--v-if-->
|
||||
<span
|
||||
class=""
|
||||
>
|
||||
|
@ -411,9 +567,8 @@ exports[`RunDataJsonSchema.vue > renders schema with spaces and dots 1`] = `
|
|||
</span>
|
||||
</span>
|
||||
</div>
|
||||
<!---->
|
||||
<!--v-if-->
|
||||
<input
|
||||
checked="checked"
|
||||
id="input_object-2-0"
|
||||
type="checkbox"
|
||||
/>
|
||||
|
@ -421,13 +576,27 @@ exports[`RunDataJsonSchema.vue > renders schema with spaces and dots 1`] = `
|
|||
class="toggle"
|
||||
for="input_object-2-0"
|
||||
>
|
||||
<font-awesome-icon-stub
|
||||
icon="angle-up"
|
||||
/>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class="svg-inline--fa fa-angle-up fa-w-10"
|
||||
data-icon="angle-up"
|
||||
data-prefix="fas"
|
||||
focusable="false"
|
||||
role="img"
|
||||
viewBox="0 0 320 512"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
class=""
|
||||
d="M177 159.7l136 136c9.4 9.4 9.4 24.6 0 33.9l-22.6 22.6c-9.4 9.4-24.6 9.4-33.9 0L160 255.9l-96.4 96.4c-9.4 9.4-24.6 9.4-33.9 0L7 329.7c-9.4-9.4-9.4-24.6 0-33.9l136-136c9.4-9.5 24.6-9.5 34-.1z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
</svg>
|
||||
</label>
|
||||
<div
|
||||
class="sub"
|
||||
>
|
||||
|
||||
<div
|
||||
class="item"
|
||||
data-test-id="run-data-schema-item"
|
||||
|
@ -445,11 +614,23 @@ exports[`RunDataJsonSchema.vue > renders schema with spaces and dots 1`] = `
|
|||
data-target="mappable"
|
||||
data-value="{{ $json['hello world'][0].test['more to think about'] }}"
|
||||
>
|
||||
<font-awesome-icon-stub
|
||||
icon="hashtag"
|
||||
size="sm"
|
||||
/>
|
||||
<!---->
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class="svg-inline--fa fa-hashtag fa-w-14 fa-sm"
|
||||
data-icon="hashtag"
|
||||
data-prefix="fas"
|
||||
focusable="false"
|
||||
role="img"
|
||||
viewBox="0 0 448 512"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
class=""
|
||||
d="M440.667 182.109l7.143-40c1.313-7.355-4.342-14.109-11.813-14.109h-74.81l14.623-81.891C377.123 38.754 371.468 32 363.997 32h-40.632a12 12 0 0 0-11.813 9.891L296.175 128H197.54l14.623-81.891C213.477 38.754 207.822 32 200.35 32h-40.632a12 12 0 0 0-11.813 9.891L132.528 128H53.432a12 12 0 0 0-11.813 9.891l-7.143 40C33.163 185.246 38.818 192 46.289 192h74.81L98.242 320H19.146a12 12 0 0 0-11.813 9.891l-7.143 40C-1.123 377.246 4.532 384 12.003 384h74.81L72.19 465.891C70.877 473.246 76.532 480 84.003 480h40.632a12 12 0 0 0 11.813-9.891L151.826 384h98.634l-14.623 81.891C234.523 473.246 240.178 480 247.65 480h40.632a12 12 0 0 0 11.813-9.891L315.472 384h79.096a12 12 0 0 0 11.813-9.891l7.143-40c1.313-7.355-4.342-14.109-11.813-14.109h-74.81l22.857-128h79.096a12 12 0 0 0 11.813-9.891zM261.889 320h-98.634l22.857-128h98.634l-22.857 128z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
</svg>
|
||||
<!--v-if-->
|
||||
<span
|
||||
class=""
|
||||
>
|
||||
|
@ -458,14 +639,15 @@ exports[`RunDataJsonSchema.vue > renders schema with spaces and dots 1`] = `
|
|||
</span>
|
||||
</div>
|
||||
<span
|
||||
class="ph-no-capture text"
|
||||
class="text ph-no-capture"
|
||||
>
|
||||
1
|
||||
</span>
|
||||
<!---->
|
||||
<!---->
|
||||
<!---->
|
||||
<!--v-if-->
|
||||
<!--v-if-->
|
||||
<!--v-if-->
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
|
@ -485,11 +667,23 @@ exports[`RunDataJsonSchema.vue > renders schema with spaces and dots 1`] = `
|
|||
data-target="mappable"
|
||||
data-value="{{ $json['hello world'][0]['test.how'] }}"
|
||||
>
|
||||
<font-awesome-icon-stub
|
||||
icon="font"
|
||||
size="sm"
|
||||
/>
|
||||
<!---->
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class="svg-inline--fa fa-font fa-w-14 fa-sm"
|
||||
data-icon="font"
|
||||
data-prefix="fas"
|
||||
focusable="false"
|
||||
role="img"
|
||||
viewBox="0 0 448 512"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
class=""
|
||||
d="M432 416h-23.41L277.88 53.69A32 32 0 0 0 247.58 32h-47.16a32 32 0 0 0-30.3 21.69L39.41 416H16a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h128a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16h-19.58l23.3-64h152.56l23.3 64H304a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h128a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16zM176.85 272L224 142.51 271.15 272z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
</svg>
|
||||
<!--v-if-->
|
||||
<span
|
||||
class=""
|
||||
>
|
||||
|
@ -498,25 +692,27 @@ exports[`RunDataJsonSchema.vue > renders schema with spaces and dots 1`] = `
|
|||
</span>
|
||||
</div>
|
||||
<span
|
||||
class="ph-no-capture text"
|
||||
class="text ph-no-capture"
|
||||
>
|
||||
ignore
|
||||
</span>
|
||||
<!---->
|
||||
<!---->
|
||||
<!---->
|
||||
<!--v-if-->
|
||||
<!--v-if-->
|
||||
<!--v-if-->
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="teleporter hidden"
|
||||
data-v-d4e6e290=""
|
||||
/>
|
||||
|
||||
<!--teleport start-->
|
||||
<!--teleport end-->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// Vitest Snapshot v1
|
||||
|
||||
exports[`VariablesRow > should render correctly 1`] = `
|
||||
"<tr data-test-id=\\"variables-row\\" class=\\"variablesRow\\">
|
||||
"<tr class=\\"variablesRow\\" data-test-id=\\"variables-row\\">
|
||||
<td class=\\"variables-key-column\\">
|
||||
<div><span>key</span></div>
|
||||
</td>
|
||||
|
@ -9,70 +9,84 @@ exports[`VariablesRow > should render correctly 1`] = `
|
|||
<div><span>value</span></div>
|
||||
</td>
|
||||
<td class=\\"variables-usage-column\\">
|
||||
<div>
|
||||
<n8n-tooltip-stub justifybuttons=\\"flex-end\\" buttons=\\"\\" placement=\\"top\\"><span class=\\"usageSyntax\\">$vars.key</span></n8n-tooltip-stub>
|
||||
<div><span class=\\"usageSyntax el-tooltip__trigger el-tooltip__trigger\\">$vars.key</span>
|
||||
<!--teleport start-->
|
||||
<!--teleport end-->
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<div class=\\"buttons hoverButtons\\">
|
||||
<n8n-tooltip-stub justifybuttons=\\"flex-end\\" buttons=\\"\\" placement=\\"top\\">
|
||||
<div><button disabled=\\"disabled\\" aria-disabled=\\"true\\" aria-live=\\"polite\\" class=\\"mr-xs button button tertiary medium disabled\\" data-test-id=\\"variable-row-edit-button\\">
|
||||
<!----><span> Edit </span></button></div>
|
||||
</n8n-tooltip-stub>
|
||||
<n8n-tooltip-stub justifybuttons=\\"flex-end\\" buttons=\\"\\" placement=\\"top\\">
|
||||
<div><button disabled=\\"disabled\\" aria-disabled=\\"true\\" aria-live=\\"polite\\" class=\\"button button tertiary medium disabled\\" data-test-id=\\"variable-row-delete-button\\">
|
||||
<!----><span> Delete </span></button></div>
|
||||
</n8n-tooltip-stub>
|
||||
<div class=\\"el-tooltip__trigger\\"><button class=\\"button button tertiary medium disabled mr-xs mr-xs\\" disabled=\\"\\" aria-disabled=\\"true\\" aria-live=\\"polite\\" data-test-id=\\"variable-row-edit-button\\">
|
||||
<!--v-if--><span>Edit</span>
|
||||
</button></div>
|
||||
<!--teleport start-->
|
||||
<!--teleport end-->
|
||||
<div class=\\"el-tooltip__trigger\\"><button class=\\"button button tertiary medium disabled\\" disabled=\\"\\" aria-disabled=\\"true\\" aria-live=\\"polite\\" data-test-id=\\"variable-row-delete-button\\">
|
||||
<!--v-if--><span>Delete</span>
|
||||
</button></div>
|
||||
<!--teleport start-->
|
||||
<!--teleport end-->
|
||||
</div>
|
||||
</td>
|
||||
</tr>"
|
||||
`;
|
||||
|
||||
exports[`VariablesRow > should show key and value inputs in edit mode 1`] = `
|
||||
"<tr data-test-id=\\"variables-row\\" class=\\"variablesRow\\">
|
||||
"<tr class=\\"variablesRow\\" data-test-id=\\"variables-row\\">
|
||||
<td class=\\"variables-key-column\\">
|
||||
<div>
|
||||
<div class=\\"container\\" data-test-id=\\"variable-row-key-input\\">
|
||||
<!---->
|
||||
<!--v-if-->
|
||||
<div class=\\"\\">
|
||||
<div class=\\"el-input el-input--large n8n-input\\">
|
||||
<!----><input type=\\"text\\" autocomplete=\\"off\\" name=\\"key\\" placeholder=\\"Enter a name\\" class=\\"el-input__inner\\">
|
||||
<!---->
|
||||
<!---->
|
||||
<!---->
|
||||
<!---->
|
||||
<!-- input -->
|
||||
<!-- prepend slot -->
|
||||
<!--v-if-->
|
||||
<div class=\\"el-input__wrapper is-focus\\">
|
||||
<!-- prefix slot -->
|
||||
<!--v-if--><input class=\\"el-input__inner\\" autocomplete=\\"off\\" name=\\"key\\" rows=\\"2\\" maxlength=\\"Infinity\\" title=\\"\\" type=\\"text\\" tabindex=\\"0\\" placeholder=\\"Enter a name\\" id=\\"el-id-5581-7\\"><!-- suffix slot -->
|
||||
<!--v-if-->
|
||||
</div><!-- append slot -->
|
||||
<!--v-if-->
|
||||
</div>
|
||||
</div>
|
||||
<!---->
|
||||
<!--v-if-->
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
<td class=\\"variables-value-column\\">
|
||||
<div>
|
||||
<div class=\\"container\\" data-test-id=\\"variable-row-value-input\\">
|
||||
<!---->
|
||||
<!--v-if-->
|
||||
<div class=\\"\\">
|
||||
<div class=\\"el-input el-input--large n8n-input\\">
|
||||
<!----><input type=\\"text\\" autocomplete=\\"off\\" name=\\"value\\" placeholder=\\"Enter a value\\" class=\\"el-input__inner\\">
|
||||
<!---->
|
||||
<!---->
|
||||
<!---->
|
||||
<!---->
|
||||
<!-- input -->
|
||||
<!-- prepend slot -->
|
||||
<!--v-if-->
|
||||
<div class=\\"el-input__wrapper\\">
|
||||
<!-- prefix slot -->
|
||||
<!--v-if--><input class=\\"el-input__inner\\" autocomplete=\\"off\\" name=\\"value\\" rows=\\"2\\" maxlength=\\"Infinity\\" title=\\"\\" type=\\"text\\" tabindex=\\"0\\" placeholder=\\"Enter a value\\" id=\\"el-id-5581-8\\"><!-- suffix slot -->
|
||||
<!--v-if-->
|
||||
</div><!-- append slot -->
|
||||
<!--v-if-->
|
||||
</div>
|
||||
</div>
|
||||
<!---->
|
||||
<!--v-if-->
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
<td class=\\"variables-usage-column\\">
|
||||
<div>
|
||||
<n8n-tooltip-stub justifybuttons=\\"flex-end\\" buttons=\\"\\" placement=\\"top\\"><span class=\\"usageSyntax\\">$vars.key</span></n8n-tooltip-stub>
|
||||
<div><span class=\\"usageSyntax el-tooltip__trigger el-tooltip__trigger\\">$vars.key</span>
|
||||
<!--teleport start-->
|
||||
<!--teleport end-->
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<div class=\\"buttons\\"><button aria-live=\\"polite\\" class=\\"mr-xs button button tertiary medium\\" data-test-id=\\"variable-row-cancel-button\\">
|
||||
<!----><span> Cancel </span></button><button aria-live=\\"polite\\" class=\\"button button primary medium\\" data-test-id=\\"variable-row-save-button\\">
|
||||
<!----><span> Save </span></button></div>
|
||||
<div class=\\"buttons\\"><button class=\\"button button tertiary medium mr-xs mr-xs\\" aria-live=\\"polite\\" data-test-id=\\"variable-row-cancel-button\\">
|
||||
<!--v-if--><span>Cancel</span>
|
||||
</button><button class=\\"button button primary medium\\" aria-live=\\"polite\\" data-test-id=\\"variable-row-save-button\\">
|
||||
<!--v-if--><span>Save</span>
|
||||
</button></div>
|
||||
</td>
|
||||
</tr>"
|
||||
`;
|
||||
|
|
|
@ -101,6 +101,7 @@ export const DEFAULT_SETUP = {
|
|||
dependentParametersValues: 'gid=0',
|
||||
inputSize: 'small',
|
||||
labelSize: 'small',
|
||||
teleported: false,
|
||||
node: {
|
||||
parameters: NODE_PARAMETER_VALUES,
|
||||
id: 'f63efb2d-3cc5-4500-89f9-b39aab19baf5',
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
<template #aside v-if="showAside">
|
||||
<div :class="[$style['heading-wrapper'], 'mb-xs']">
|
||||
<n8n-heading size="2xlarge">
|
||||
{{ $locale.baseText(`${resourceKey}.heading`) }}
|
||||
{{ i18n.baseText(`${resourceKey}.heading`) }}
|
||||
</n8n-heading>
|
||||
</div>
|
||||
|
||||
|
@ -16,7 +16,7 @@
|
|||
@click="$emit('click:add', $event)"
|
||||
data-test-id="resources-list-add"
|
||||
>
|
||||
{{ $locale.baseText(`${resourceKey}.add`) }}
|
||||
{{ i18n.baseText(`${resourceKey}.add`) }}
|
||||
</n8n-button>
|
||||
</slot>
|
||||
</div>
|
||||
|
@ -24,8 +24,8 @@
|
|||
<enterprise-edition :features="[EnterpriseEditionFeature.Sharing]" v-if="shareable">
|
||||
<resource-ownership-select
|
||||
v-model="isOwnerSubview"
|
||||
:my-resources-label="$locale.baseText(`${resourceKey}.menu.my`)"
|
||||
:all-resources-label="$locale.baseText(`${resourceKey}.menu.all`)"
|
||||
:my-resources-label="i18n.baseText(`${resourceKey}.menu.my`)"
|
||||
:all-resources-label="i18n.baseText(`${resourceKey}.menu.all`)"
|
||||
/>
|
||||
</enterprise-edition>
|
||||
</template>
|
||||
|
@ -42,7 +42,7 @@
|
|||
data-test-id="empty-resources-list"
|
||||
emoji="👋"
|
||||
:heading="
|
||||
$locale.baseText(
|
||||
i18n.baseText(
|
||||
usersStore.currentUser.firstName
|
||||
? `${resourceKey}.empty.heading`
|
||||
: `${resourceKey}.empty.heading.userNotSetup`,
|
||||
|
@ -51,8 +51,8 @@
|
|||
},
|
||||
)
|
||||
"
|
||||
:description="$locale.baseText(`${resourceKey}.empty.description`)"
|
||||
:buttonText="$locale.baseText(`${resourceKey}.empty.button`)"
|
||||
:description="i18n.baseText(`${resourceKey}.empty.description`)"
|
||||
:buttonText="i18n.baseText(`${resourceKey}.empty.button`)"
|
||||
buttonType="secondary"
|
||||
@click:button="$emit('click:add', $event)"
|
||||
/>
|
||||
|
@ -65,7 +65,7 @@
|
|||
<n8n-input
|
||||
:modelValue="filtersModel.search"
|
||||
:class="[$style['search'], 'mr-2xs']"
|
||||
:placeholder="$locale.baseText(`${resourceKey}.search.placeholder`)"
|
||||
:placeholder="i18n.baseText(`${resourceKey}.search.placeholder`)"
|
||||
clearable
|
||||
ref="search"
|
||||
data-test-id="resources-list-search"
|
||||
|
@ -82,7 +82,7 @@
|
|||
data-test-id="resources-list-sort-item"
|
||||
:key="sortOption"
|
||||
:value="sortOption"
|
||||
:label="$locale.baseText(`${resourceKey}.sort.${sortOption}`)"
|
||||
:label="i18n.baseText(`${resourceKey}.sort.${sortOption}`)"
|
||||
/>
|
||||
</n8n-select>
|
||||
<resource-filters-dropdown
|
||||
|
@ -106,9 +106,9 @@
|
|||
|
||||
<div v-if="showFiltersDropdown" v-show="hasFilters" class="mt-xs">
|
||||
<n8n-info-tip :bold="false">
|
||||
{{ $locale.baseText(`${resourceKey}.filters.active`) }}
|
||||
{{ i18n.baseText(`${resourceKey}.filters.active`) }}
|
||||
<n8n-link @click="resetFilters" size="small">
|
||||
{{ $locale.baseText(`${resourceKey}.filters.active.reset`) }}
|
||||
{{ i18n.baseText(`${resourceKey}.filters.active.reset`) }}
|
||||
</n8n-link>
|
||||
</n8n-info-tip>
|
||||
</div>
|
||||
|
@ -153,22 +153,20 @@
|
|||
</div>
|
||||
|
||||
<n8n-text color="text-base" size="medium" data-test-id="resources-list-empty" v-else>
|
||||
{{ $locale.baseText(`${resourceKey}.noResults`) }}
|
||||
{{ i18n.baseText(`${resourceKey}.noResults`) }}
|
||||
<template v-if="shouldSwitchToAllSubview">
|
||||
<span v-if="!filtersModel.search">
|
||||
({{ $locale.baseText(`${resourceKey}.noResults.switchToShared.preamble`) }}
|
||||
({{ i18n.baseText(`${resourceKey}.noResults.switchToShared.preamble`) }}
|
||||
<n8n-link @click="setOwnerSubview(false)">
|
||||
{{ $locale.baseText(`${resourceKey}.noResults.switchToShared.link`) }} </n8n-link
|
||||
{{ i18n.baseText(`${resourceKey}.noResults.switchToShared.link`) }} </n8n-link
|
||||
>)
|
||||
</span>
|
||||
|
||||
<span v-else>
|
||||
({{
|
||||
$locale.baseText(`${resourceKey}.noResults.withSearch.switchToShared.preamble`)
|
||||
}}
|
||||
({{ i18n.baseText(`${resourceKey}.noResults.withSearch.switchToShared.preamble`) }}
|
||||
<n8n-link @click="setOwnerSubview(false)">
|
||||
{{
|
||||
$locale.baseText(`${resourceKey}.noResults.withSearch.switchToShared.link`)
|
||||
i18n.baseText(`${resourceKey}.noResults.withSearch.switchToShared.link`)
|
||||
}} </n8n-link
|
||||
>)
|
||||
</span>
|
||||
|
@ -197,6 +195,7 @@ import { useSettingsStore } from '@/stores/settings.store';
|
|||
import { useUsersStore } from '@/stores/users.store';
|
||||
import type { N8nInput } from 'n8n-design-system';
|
||||
import type { DatatableColumn } from 'n8n-design-system';
|
||||
import { useI18n } from '@/composables';
|
||||
|
||||
export interface IResource {
|
||||
id: string;
|
||||
|
@ -286,6 +285,13 @@ export default defineComponent({
|
|||
}),
|
||||
},
|
||||
},
|
||||
setup() {
|
||||
const i18n = useI18n();
|
||||
|
||||
return {
|
||||
i18n,
|
||||
};
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
loading: true,
|
||||
|
@ -413,7 +419,7 @@ export default defineComponent({
|
|||
this.isOwnerSubview = active;
|
||||
},
|
||||
getTelemetrySubview(): string {
|
||||
return this.$locale.baseText(
|
||||
return this.i18n.baseText(
|
||||
`${this.resourceKey as IResourceKeyType}.menu.${this.isOwnerSubview ? 'my' : 'all'}`,
|
||||
);
|
||||
},
|
||||
|
|
|
@ -1,19 +1,5 @@
|
|||
import { i18n } from '@/plugins/i18n';
|
||||
import { useRootStore } from '@/stores/n8nRoot.store';
|
||||
|
||||
export function useI18n() {
|
||||
const isEnglishLocale = useRootStore().defaultLocale === 'en';
|
||||
|
||||
function localizeNodeName(nodeName: string, type: string) {
|
||||
if (isEnglishLocale) return nodeName;
|
||||
|
||||
const nodeTypeName = i18n.shortNodeType(type);
|
||||
|
||||
return i18n.headerText({
|
||||
key: `headers.${nodeTypeName}.displayName`,
|
||||
fallback: nodeName,
|
||||
});
|
||||
}
|
||||
|
||||
return { i18n, localizeNodeName };
|
||||
return i18n;
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ interface LoadingService {
|
|||
}
|
||||
|
||||
export function useLoadingService() {
|
||||
const { i18n } = useI18n();
|
||||
const i18n = useI18n();
|
||||
const loadingService = ref<LoadingService | null>(null);
|
||||
|
||||
function startLoading(text?: string) {
|
||||
|
|
|
@ -17,7 +17,7 @@ export function useToast() {
|
|||
const telemetry = useTelemetry();
|
||||
const workflowsStore = useWorkflowsStore();
|
||||
const externalHooks = useExternalHooks();
|
||||
const { i18n } = useI18n();
|
||||
const i18n = useI18n();
|
||||
|
||||
function showMessage(
|
||||
messageData: Omit<NotificationOptions, 'message'> & { message?: string },
|
||||
|
|
|
@ -568,3 +568,6 @@ export const CLOUD_BASE_URL_STAGING = 'https://stage-api.n8n.cloud';
|
|||
export const CLOUD_BASE_URL_PRODUCTION = 'https://api.n8n.cloud';
|
||||
|
||||
export const CLOUD_TRIAL_CHECK_INTERVAL = 5000;
|
||||
|
||||
// A path that does not exist so that nothing is selected by default
|
||||
export const nonExistingJsonPath = '_!^&*';
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
import { createEventBus } from 'n8n-design-system';
|
||||
import { createEventBus } from 'n8n-design-system/utils';
|
||||
|
||||
export const codeNodeEditorEventBus = createEventBus();
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
import { createEventBus } from 'n8n-design-system';
|
||||
import { createEventBus } from 'n8n-design-system/utils';
|
||||
|
||||
export const dataPinningEventBus = createEventBus();
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
import { createEventBus } from 'n8n-design-system';
|
||||
import { createEventBus } from 'n8n-design-system/utils';
|
||||
|
||||
export const htmlEditorEventBus = createEventBus();
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
import { createEventBus } from 'n8n-design-system';
|
||||
import { createEventBus } from 'n8n-design-system/utils';
|
||||
|
||||
export const globalLinkActionsEventBus = createEventBus();
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
import { createEventBus } from 'n8n-design-system';
|
||||
import { createEventBus } from 'n8n-design-system/utils';
|
||||
|
||||
export const nodeViewEventBus = createEventBus();
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
// The Vue build version to load with the `import` command
|
||||
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
|
||||
import { createApp } from 'vue';
|
||||
|
||||
import 'vue-json-pretty/lib/styles.css';
|
||||
|
@ -30,8 +28,6 @@ const pinia = createPinia();
|
|||
|
||||
const app = createApp(App);
|
||||
|
||||
// Vue.config.productionTip = false;
|
||||
|
||||
app.use(TelemetryPlugin);
|
||||
app.use(PiniaVuePlugin);
|
||||
app.use(I18nPlugin);
|
||||
|
@ -44,13 +40,6 @@ app.use(i18nInstance);
|
|||
|
||||
app.mount('#app');
|
||||
|
||||
// new Vue({
|
||||
// i18n: i18nInstance,
|
||||
// router,
|
||||
// pinia,
|
||||
// render: (h) => h(App),
|
||||
// }).$mount('#app');
|
||||
|
||||
router.afterEach((to, from) => {
|
||||
void runExternalHook('main.routeChange', useWebhooksStore(), { from, to });
|
||||
});
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import type { INodeUi } from '@/Interface';
|
||||
import type { IConnection } from 'n8n-workflow';
|
||||
import type { XYPosition } from '../Interface';
|
||||
import { createEventBus } from 'n8n-design-system';
|
||||
import { createEventBus } from 'n8n-design-system/utils';
|
||||
|
||||
// Command names don't serve any particular purpose in the app
|
||||
// but they make it easier to identify each command on stack
|
||||
|
|
|
@ -3,10 +3,10 @@ import type { Plugin } from 'vue';
|
|||
import 'regenerator-runtime/runtime';
|
||||
|
||||
import ElementPlus from 'element-plus';
|
||||
import { ElLoading, ElMessageBox, ElNotification } from 'element-plus';
|
||||
import { ElLoading, ElMessageBox } from 'element-plus';
|
||||
import { N8nPlugin } from 'n8n-design-system';
|
||||
import EnterpriseEdition from '@/components/EnterpriseEdition.ee.vue';
|
||||
import { useMessage } from '@/composables/useMessage';
|
||||
import EnterpriseEdition from '@/components/EnterpriseEdition.ee.vue';
|
||||
|
||||
export const GlobalComponentsPlugin: Plugin<{}> = {
|
||||
install(app) {
|
||||
|
@ -17,8 +17,8 @@ export const GlobalComponentsPlugin: Plugin<{}> = {
|
|||
app.use(ElementPlus);
|
||||
app.use(N8nPlugin);
|
||||
|
||||
app.use(ElLoading);
|
||||
app.use(ElNotification);
|
||||
// app.use(ElLoading);
|
||||
// app.use(ElNotification);
|
||||
|
||||
app.config.globalProperties.$loading = ElLoading.service;
|
||||
app.config.globalProperties.$msgbox = ElMessageBox;
|
||||
|
|
|
@ -14,6 +14,7 @@ import englishBaseText from './locales/en.json';
|
|||
import { useUIStore } from '@/stores/ui.store';
|
||||
import { useNDVStore } from '@/stores/ndv.store';
|
||||
import type { INodeProperties, INodePropertyCollection, INodePropertyOptions } from 'n8n-workflow';
|
||||
import { useRootStore } from '@/stores';
|
||||
|
||||
export const i18nInstance = createI18n({
|
||||
locale: 'en',
|
||||
|
@ -311,6 +312,19 @@ export class I18nClass {
|
|||
};
|
||||
}
|
||||
|
||||
localizeNodeName(nodeName: string, type: string) {
|
||||
const isEnglishLocale = useRootStore().defaultLocale === 'en';
|
||||
|
||||
if (isEnglishLocale) return nodeName;
|
||||
|
||||
const nodeTypeName = this.shortNodeType(type);
|
||||
|
||||
return this.headerText({
|
||||
key: `headers.${nodeTypeName}.displayName`,
|
||||
fallback: nodeName,
|
||||
});
|
||||
}
|
||||
|
||||
rootVars: Record<string, string | undefined> = {
|
||||
$binary: this.baseText('codeNodeEditor.completer.binary'),
|
||||
$execution: this.baseText('codeNodeEditor.completer.$execution'),
|
||||
|
@ -595,13 +609,13 @@ export const i18n: I18nClass = new I18nClass();
|
|||
|
||||
export const I18nPlugin: Plugin<{}> = {
|
||||
async install(app) {
|
||||
await locale.use('en');
|
||||
|
||||
locale.i18n((key: string, options?: { interpolate: Record<string, unknown> }) =>
|
||||
i18nInstance.global.t(key, options?.interpolate || {}),
|
||||
);
|
||||
|
||||
app.config.globalProperties.$locale = i18n;
|
||||
|
||||
await locale.use('en');
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -609,12 +623,6 @@ export const I18nPlugin: Plugin<{}> = {
|
|||
// typings
|
||||
// ----------------------------------
|
||||
|
||||
declare module '@vue/runtime-core' {
|
||||
interface ComponentCustomProperties {
|
||||
$locale: I18nClass;
|
||||
}
|
||||
}
|
||||
|
||||
type GetBaseTextKey<T> = T extends `_${string}` ? never : T;
|
||||
|
||||
export type BaseTextKey = GetBaseTextKey<keyof typeof englishBaseText>;
|
||||
|
|
|
@ -1,11 +1,3 @@
|
|||
import type { Telemetry } from '.';
|
||||
|
||||
declare module 'vue/types/vue' {
|
||||
interface Vue {
|
||||
$telemetry: Telemetry;
|
||||
}
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface Window {
|
||||
rudderanalytics: RudderStack;
|
||||
|
@ -60,3 +52,5 @@ interface RudderStack extends Array<unknown> {
|
|||
|
||||
reset(): void;
|
||||
}
|
||||
|
||||
export {};
|
||||
|
|
24
packages/editor-ui/src/shims-vue.d.ts
vendored
24
packages/editor-ui/src/shims-vue.d.ts
vendored
|
@ -1,12 +1,22 @@
|
|||
declare module '*.vue' {
|
||||
import type { DefineComponent } from 'vue';
|
||||
const component: DefineComponent<{}, {}, any>;
|
||||
export default component;
|
||||
}
|
||||
import type { I18nClass } from '@/plugins/i18n';
|
||||
import type { Route } from 'vue-router';
|
||||
import type { Telemetry } from '@/plugins/telemetry';
|
||||
|
||||
declare module 'vue' {
|
||||
interface ComponentCustomOptions {
|
||||
beforeRouteEnter?(to: Route, from: Route, next: () => void): void;
|
||||
beforeRouteLeave?(to: Route, from: Route, next: () => void): void;
|
||||
beforeRouteUpdate?(to: Route, from: Route, next: () => void): void;
|
||||
}
|
||||
|
||||
// @TODO Check if still needed
|
||||
declare module '@vue/runtime-core' {
|
||||
interface ComponentCustomProperties {
|
||||
$style: Record<string, string>;
|
||||
$locale: I18nClass;
|
||||
$telemetry: Telemetry;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @docs https://vuejs.org/guide/typescript/options-api.html#augmenting-global-properties
|
||||
*/
|
||||
export {};
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
import { computed, reactive } from 'vue';
|
||||
import { defineStore } from 'pinia';
|
||||
import { EnterpriseEditionFeature } from '@/constants';
|
||||
import { useSettingsStore, useRootStore, useUsersStore } from '@/stores';
|
||||
import { useSettingsStore } from '@/stores/settings.store';
|
||||
import { useRootStore } from '@/stores/n8nRoot.store';
|
||||
import { useUsersStore } from '@/stores/users.store';
|
||||
import * as vcApi from '@/api/sourceControl';
|
||||
import type { SourceControlPreferences } from '@/Interface';
|
||||
|
||||
|
|
|
@ -348,14 +348,16 @@ export default defineComponent({
|
|||
CanvasControls,
|
||||
},
|
||||
setup(props) {
|
||||
const locale = useI18n();
|
||||
|
||||
return {
|
||||
locale,
|
||||
...useCanvasMouseSelect(),
|
||||
...useGlobalLinkActions(),
|
||||
...useTitleChange(),
|
||||
...useToast(),
|
||||
...useMessage(),
|
||||
...useUniqueNodeName(),
|
||||
...useI18n(),
|
||||
...workflowRun.setup?.(props),
|
||||
};
|
||||
},
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
import { useI18n } from '@/composables';
|
||||
import { useUIStore, useAuditLogsStore } from '@/stores';
|
||||
|
||||
const { i18n: locale } = useI18n();
|
||||
const locale = useI18n();
|
||||
const uiStore = useUIStore();
|
||||
const auditLogsStore = useAuditLogsStore();
|
||||
|
||||
|
|
|
@ -162,7 +162,7 @@ import { mapStores } from 'pinia';
|
|||
import { useUsersStore } from '@/stores/users.store';
|
||||
import { useSettingsStore } from '@/stores/settings.store';
|
||||
import { useUIStore } from '@/stores';
|
||||
import { createEventBus } from 'n8n-design-system';
|
||||
import { createEventBus } from 'n8n-design-system/utils';
|
||||
import type { N8nFormInputs } from 'n8n-design-system';
|
||||
import type { CellStyle } from 'element-plus';
|
||||
|
||||
|
|
|
@ -88,7 +88,7 @@ import { LOG_STREAM_MODAL_KEY, EnterpriseEditionFeature } from '../constants';
|
|||
import type { MessageEventBusDestinationOptions } from 'n8n-workflow';
|
||||
import { deepCopy, defaultMessageEventBusDestinationOptions } from 'n8n-workflow';
|
||||
import EventDestinationCard from '@/components/SettingsLogStreaming/EventDestinationCard.ee.vue';
|
||||
import { createEventBus } from 'n8n-design-system';
|
||||
import { createEventBus } from 'n8n-design-system/utils';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'SettingsLogStreamingView',
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<div :class="$style.container" data-test-id="personal-settings-container">
|
||||
<div :class="$style.header">
|
||||
<n8n-heading size="2xlarge">{{
|
||||
$locale.baseText('settings.personal.personalSettings')
|
||||
i18n.baseText('settings.personal.personalSettings')
|
||||
}}</n8n-heading>
|
||||
<div class="ph-no-capture" :class="$style.user">
|
||||
<span :class="$style.username" data-test-id="current-user-name">
|
||||
|
@ -18,7 +18,7 @@
|
|||
<div>
|
||||
<div :class="$style.sectionHeader">
|
||||
<n8n-heading size="large">{{
|
||||
$locale.baseText('settings.personal.basicInformation')
|
||||
i18n.baseText('settings.personal.basicInformation')
|
||||
}}</n8n-heading>
|
||||
</div>
|
||||
<div data-test-id="personal-data-form">
|
||||
|
@ -34,12 +34,12 @@
|
|||
</div>
|
||||
<div v-if="!signInWithLdap && !signInWithSaml">
|
||||
<div :class="$style.sectionHeader">
|
||||
<n8n-heading size="large">{{ $locale.baseText('settings.personal.security') }}</n8n-heading>
|
||||
<n8n-heading size="large">{{ i18n.baseText('settings.personal.security') }}</n8n-heading>
|
||||
</div>
|
||||
<div>
|
||||
<n8n-input-label :label="$locale.baseText('auth.password')">
|
||||
<n8n-input-label :label="i18n.baseText('auth.password')">
|
||||
<n8n-link @click="openPasswordModal" data-test-id="change-password-link">{{
|
||||
$locale.baseText('auth.changePassword')
|
||||
i18n.baseText('auth.changePassword')
|
||||
}}</n8n-link>
|
||||
</n8n-input-label>
|
||||
</div>
|
||||
|
@ -47,7 +47,7 @@
|
|||
<div>
|
||||
<n8n-button
|
||||
float="right"
|
||||
:label="$locale.baseText('settings.personal.save')"
|
||||
:label="i18n.baseText('settings.personal.save')"
|
||||
size="large"
|
||||
:disabled="!hasAnyChanges || !readyToSubmit"
|
||||
data-test-id="save-settings-button"
|
||||
|
@ -58,7 +58,7 @@
|
|||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { useToast } from '@/composables';
|
||||
import { useI18n, useToast } from '@/composables';
|
||||
import { CHANGE_PASSWORD_MODAL_KEY } from '@/constants';
|
||||
import type { IFormInputs, IUser } from '@/Interface';
|
||||
import { useUIStore } from '@/stores/ui.store';
|
||||
|
@ -66,12 +66,15 @@ import { useUsersStore } from '@/stores/users.store';
|
|||
import { useSettingsStore } from '@/stores/settings.store';
|
||||
import { mapStores } from 'pinia';
|
||||
import { defineComponent } from 'vue';
|
||||
import { createEventBus } from 'n8n-design-system';
|
||||
import { createEventBus } from 'n8n-design-system/utils';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'SettingsPersonalView',
|
||||
setup() {
|
||||
const i18n = useI18n();
|
||||
|
||||
return {
|
||||
i18n,
|
||||
...useToast(),
|
||||
};
|
||||
},
|
||||
|
@ -89,7 +92,7 @@ export default defineComponent({
|
|||
name: 'firstName',
|
||||
initialValue: this.currentUser?.firstName,
|
||||
properties: {
|
||||
label: this.$locale.baseText('auth.firstName'),
|
||||
label: this.i18n.baseText('auth.firstName'),
|
||||
maxlength: 32,
|
||||
required: true,
|
||||
autocomplete: 'given-name',
|
||||
|
@ -101,7 +104,7 @@ export default defineComponent({
|
|||
name: 'lastName',
|
||||
initialValue: this.currentUser?.lastName,
|
||||
properties: {
|
||||
label: this.$locale.baseText('auth.lastName'),
|
||||
label: this.i18n.baseText('auth.lastName'),
|
||||
maxlength: 32,
|
||||
required: true,
|
||||
autocomplete: 'family-name',
|
||||
|
@ -113,7 +116,7 @@ export default defineComponent({
|
|||
name: 'email',
|
||||
initialValue: this.currentUser?.email,
|
||||
properties: {
|
||||
label: this.$locale.baseText('auth.email'),
|
||||
label: this.i18n.baseText('auth.email'),
|
||||
type: 'email',
|
||||
required: true,
|
||||
validationRules: [{ name: 'VALID_EMAIL' }],
|
||||
|
@ -160,13 +163,13 @@ export default defineComponent({
|
|||
email: form.email,
|
||||
});
|
||||
this.showToast({
|
||||
title: this.$locale.baseText('settings.personal.personalSettingsUpdated'),
|
||||
title: this.i18n.baseText('settings.personal.personalSettingsUpdated'),
|
||||
message: '',
|
||||
type: 'success',
|
||||
});
|
||||
this.hasAnyChanges = false;
|
||||
} catch (e) {
|
||||
this.showError(e, this.$locale.baseText('settings.personal.personalSettingsUpdatedError'));
|
||||
this.showError(e, this.i18n.baseText('settings.personal.personalSettingsUpdatedError'));
|
||||
}
|
||||
},
|
||||
onSaveClick() {
|
||||
|
|
|
@ -6,7 +6,7 @@ import { useUIStore, useSourceControlStore } from '@/stores';
|
|||
import { useToast, useMessage, useLoadingService, useI18n } from '@/composables';
|
||||
import CopyInput from '@/components/CopyInput.vue';
|
||||
|
||||
const { i18n: locale } = useI18n();
|
||||
const locale = useI18n();
|
||||
const sourceControlStore = useSourceControlStore();
|
||||
const uiStore = useUIStore();
|
||||
const toast = useToast();
|
||||
|
|
|
@ -10,7 +10,7 @@ const IdentityProviderSettingsType = {
|
|||
XML: 'xml',
|
||||
};
|
||||
|
||||
const { i18n } = useI18n();
|
||||
const i18n = useI18n();
|
||||
const ssoStore = useSSOStore();
|
||||
const uiStore = useUIStore();
|
||||
const message = useMessage();
|
||||
|
|
|
@ -26,7 +26,7 @@ const environmentsStore = useEnvironmentsStore();
|
|||
const usersStore = useUsersStore();
|
||||
const uiStore = useUIStore();
|
||||
const telemetry = useTelemetry();
|
||||
const { i18n } = useI18n();
|
||||
const i18n = useI18n();
|
||||
const message = useMessage();
|
||||
const sourceControlStore = useSourceControlStore();
|
||||
let sourceControlStoreUnsubscribe = () => {};
|
||||
|
|
|
@ -10,17 +10,16 @@ const renderComponent = (renderOptions: Parameters<typeof render>[1] = {}) =>
|
|||
merge(
|
||||
{
|
||||
pinia: createTestingPinia(),
|
||||
stubs: {
|
||||
SSOLogin: {
|
||||
template: '<div data-test-id="sso-login"></div>',
|
||||
global: {
|
||||
stubs: {
|
||||
SSOLogin: {
|
||||
template: '<div data-test-id="sso-login"></div>',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
renderOptions,
|
||||
),
|
||||
(vue) => {
|
||||
vue.use(PiniaVuePlugin);
|
||||
},
|
||||
);
|
||||
|
||||
describe('AuthView', () => {
|
||||
|
|
|
@ -33,9 +33,6 @@ const renderComponent = (renderOptions: Parameters<typeof render>[1] = {}) =>
|
|||
},
|
||||
renderOptions,
|
||||
),
|
||||
(vue) => {
|
||||
vue.use(PiniaVuePlugin);
|
||||
},
|
||||
);
|
||||
|
||||
describe('SamlOnboarding', () => {
|
||||
|
|
|
@ -20,9 +20,6 @@ const renderComponent = (renderOptions: Parameters<typeof render>[1] = {}) =>
|
|||
},
|
||||
renderOptions,
|
||||
),
|
||||
(vue) => {
|
||||
vue.use(PiniaVuePlugin);
|
||||
},
|
||||
);
|
||||
|
||||
describe('SettingsAuditLogs', () => {
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue