mirror of
https://github.com/n8n-io/n8n.git
synced 2026-09-24 23:22:38 +08:00
chore(ai-builder): Telemetry updates for pinned data (#22625)
This commit is contained in:
@@ -384,6 +384,64 @@ describe('Telemetry', () => {
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
test('should include instance_id, version_cli, and user_id in track properties', () => {
|
||||
const eventName = 'Test Event';
|
||||
const properties = { user_id: '1234', custom_prop: 'value' };
|
||||
|
||||
telemetry.track(eventName, properties);
|
||||
|
||||
expect(mockRudderStack.track).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
event: eventName,
|
||||
properties: expect.objectContaining({
|
||||
instance_id: instanceId,
|
||||
user_id: '1234',
|
||||
version_cli: expect.any(String),
|
||||
custom_prop: 'value',
|
||||
}),
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
test('should format userId with user_id when provided', () => {
|
||||
const eventName = 'Test Event';
|
||||
const properties = { user_id: '5678' };
|
||||
|
||||
telemetry.track(eventName, properties);
|
||||
|
||||
expect(mockRudderStack.track).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
userId: `${instanceId}#5678`,
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
test('should format userId without user_id when not provided', () => {
|
||||
const eventName = 'Test Event';
|
||||
|
||||
telemetry.track(eventName, {});
|
||||
|
||||
expect(mockRudderStack.track).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
userId: instanceId,
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
test('should set user_id to undefined when not provided in properties', () => {
|
||||
const eventName = 'Test Event';
|
||||
|
||||
telemetry.track(eventName, {});
|
||||
|
||||
expect(mockRudderStack.track).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
properties: expect.objectContaining({
|
||||
user_id: undefined,
|
||||
}),
|
||||
}),
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -225,6 +225,7 @@ export class Telemetry {
|
||||
const updatedProperties = {
|
||||
...properties,
|
||||
instance_id: instanceId,
|
||||
user_id: user_id ?? undefined,
|
||||
version_cli: N8N_VERSION,
|
||||
};
|
||||
|
||||
|
||||
@@ -102,16 +102,35 @@ describe('usePinnedData', () => {
|
||||
});
|
||||
|
||||
describe('onSetDataSuccess()', () => {
|
||||
it('should trigger telemetry on successful data setting', async () => {
|
||||
it('should trigger telemetry on successful data setting with correct payload values', async () => {
|
||||
const workflowsStore = useWorkflowsStore();
|
||||
workflowsStore.workflow.id = 'test-workflow-id';
|
||||
|
||||
const telemetry = useTelemetry();
|
||||
const spy = vi.spyOn(telemetry, 'track');
|
||||
const pinnedData = usePinnedData(ref({ name: 'testNode', type: 'someType' } as INodeUi), {
|
||||
const node = ref({
|
||||
name: 'testNode',
|
||||
type: 'n8n-nodes-base.httpRequest',
|
||||
id: 'test-node-id',
|
||||
} as INodeUi);
|
||||
const pinnedData = usePinnedData(node, {
|
||||
displayMode: ref('json'),
|
||||
runIndex: ref(0),
|
||||
runIndex: ref(2),
|
||||
});
|
||||
|
||||
pinnedData.onSetDataSuccess({ source: 'pin-icon-click' });
|
||||
expect(spy).toHaveBeenCalled();
|
||||
|
||||
expect(spy).toHaveBeenCalledWith(
|
||||
'Ndv data pinning success',
|
||||
expect.objectContaining({
|
||||
pinning_source: 'pin-icon-click',
|
||||
node_type: 'n8n-nodes-base.httpRequest',
|
||||
view: 'json',
|
||||
run_index: 2,
|
||||
workflow_id: 'test-workflow-id',
|
||||
node_id: 'test-node-id',
|
||||
}),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -215,6 +215,8 @@ export function usePinnedData(
|
||||
data_size: stringSizeInBytes(data.value),
|
||||
view: displayMode,
|
||||
run_index: runIndex,
|
||||
workflow_id: workflowsStore.workflowId,
|
||||
node_id: targetNode?.id,
|
||||
};
|
||||
|
||||
void externalHooks.run('runData.onDataPinningSuccess', telemetryPayload);
|
||||
|
||||
@@ -95,6 +95,7 @@ import {
|
||||
N8nTooltip,
|
||||
} from '@n8n/design-system';
|
||||
import { injectWorkflowState } from '@/app/composables/useWorkflowState';
|
||||
|
||||
const LazyRunDataTable = defineAsyncComponent(async () => await import('./RunDataTable.vue'));
|
||||
const LazyRunDataJson = defineAsyncComponent(async () => await import('./RunDataJson.vue'));
|
||||
|
||||
@@ -807,6 +808,7 @@ function getResolvedNodeOutputs() {
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
function shouldHintBeDisplayed(hint: NodeHint): boolean {
|
||||
const { location, whenToDisplay } = hint;
|
||||
|
||||
@@ -963,6 +965,8 @@ function enterEditMode({ origin }: EnterEditModeArgs) {
|
||||
is_output_present: hasNodeRun.value || pinnedData.hasData.value,
|
||||
view: !hasNodeRun.value && !pinnedData.hasData.value ? 'undefined' : props.displayMode,
|
||||
is_data_pinned: pinnedData.hasData.value,
|
||||
workflow_id: workflowsStore.workflowId,
|
||||
node_id: activeNode.value?.id,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1038,6 +1042,8 @@ async function onTogglePinData({ source }: { source: PinDataSource | UnpinDataSo
|
||||
push_ref: props.pushRef,
|
||||
run_index: props.runIndex,
|
||||
view: !hasNodeRun.value && !pinnedData.hasData.value ? 'none' : props.displayMode,
|
||||
workflow_id: workflowsStore.workflowId,
|
||||
node_id: activeNode.value?.id,
|
||||
};
|
||||
|
||||
void externalHooks.run('runData.onTogglePinData', telemetryPayload);
|
||||
@@ -1725,9 +1731,9 @@ defineExpose({ enterEditMode });
|
||||
</div>
|
||||
|
||||
<div v-else-if="editMode.enabled" :class="$style.editMode">
|
||||
<N8nText v-if="previousExecutionDataUsedInEditMode" class="mb-2xs" size="small">{{
|
||||
i18n.baseText('runData.pinData.insertedExecutionData')
|
||||
}}</N8nText>
|
||||
<N8nText v-if="previousExecutionDataUsedInEditMode" class="mb-2xs" size="small"
|
||||
>{{ i18n.baseText('runData.pinData.insertedExecutionData') }}
|
||||
</N8nText>
|
||||
<div :class="[$style.editModeBody, 'ignore-key-press-canvas']">
|
||||
<JsonEditor
|
||||
:model-value="editMode.value"
|
||||
|
||||
Reference in New Issue
Block a user