mirror of
https://github.com/n8n-io/n8n.git
synced 2026-09-01 15:47:41 +08:00
feat: Track n8n Connect credential toggle in telemetry (no-changelog) (#30245)
This commit is contained in:
+76
@@ -26,6 +26,12 @@ import {
|
||||
createWorkflowDocumentId,
|
||||
} from '@/app/stores/workflowDocument.store';
|
||||
|
||||
const trackMock = vi.hoisted(() => vi.fn());
|
||||
|
||||
vi.mock('@/app/composables/useTelemetry', () => ({
|
||||
useTelemetry: () => ({ track: trackMock }),
|
||||
}));
|
||||
|
||||
vi.mock('@/app/composables/useAiGateway', () => ({
|
||||
useAiGateway: vi.fn(() => ({
|
||||
isEnabled: ref(false),
|
||||
@@ -1289,6 +1295,76 @@ describe('NodeCredentials', () => {
|
||||
expect((payload.properties.credentials['googlePalmApi'] as { id: string }).id).toBe('cred-1');
|
||||
});
|
||||
|
||||
describe('telemetry', () => {
|
||||
const toggleOnStub = {
|
||||
template: '<button data-test-id="ai-gateway-toggle-on" @click="$emit(\'toggle\', true)" />',
|
||||
props: ['aiGatewayEnabled'],
|
||||
emits: ['toggle'],
|
||||
};
|
||||
|
||||
const toggleOffStub = {
|
||||
template:
|
||||
'<button data-test-id="ai-gateway-toggle-off" @click="$emit(\'toggle\', false)" />',
|
||||
props: ['aiGatewayEnabled'],
|
||||
emits: ['toggle'],
|
||||
};
|
||||
|
||||
it('should track telemetry with mode "n8n_connect" when toggled ON by user', async () => {
|
||||
ndvStore.activeNode = googleAiNode;
|
||||
|
||||
renderComponent({
|
||||
props: { node: googleAiNode, overrideCredType: 'googlePalmApi' },
|
||||
global: { stubs: { AiGatewaySelector: toggleOnStub } },
|
||||
});
|
||||
|
||||
await userEvent.click(screen.getByTestId('ai-gateway-toggle-on'));
|
||||
|
||||
expect(trackMock).toHaveBeenCalledWith('User toggled n8n connect credential', {
|
||||
credential_type: 'googlePalmApi',
|
||||
node_type: googleAiNode.type,
|
||||
mode: 'n8n_connect',
|
||||
workflow_id: expect.any(String),
|
||||
});
|
||||
});
|
||||
|
||||
it('should track telemetry with mode "own" when toggled OFF by user', async () => {
|
||||
const nodeWithGateway: INodeUi = {
|
||||
...googleAiNode,
|
||||
credentials: { googlePalmApi: { id: null, name: '', __aiGatewayManaged: true } },
|
||||
};
|
||||
ndvStore.activeNode = nodeWithGateway;
|
||||
|
||||
renderComponent({
|
||||
props: { node: nodeWithGateway, overrideCredType: 'googlePalmApi' },
|
||||
global: { stubs: { AiGatewaySelector: toggleOffStub } },
|
||||
});
|
||||
|
||||
await userEvent.click(screen.getByTestId('ai-gateway-toggle-off'));
|
||||
|
||||
expect(trackMock).toHaveBeenCalledWith('User toggled n8n connect credential', {
|
||||
credential_type: 'googlePalmApi',
|
||||
node_type: googleAiNode.type,
|
||||
mode: 'own',
|
||||
workflow_id: expect.any(String),
|
||||
});
|
||||
});
|
||||
|
||||
it('should not track telemetry when toggled ON automatically on mount', () => {
|
||||
// No credentials — auto-select path calls onAiGatewaySelector with isUserAction=false
|
||||
ndvStore.activeNode = googleAiNode;
|
||||
|
||||
renderComponent({
|
||||
props: { node: googleAiNode, overrideCredType: 'googlePalmApi' },
|
||||
global: { stubs: { AiGatewaySelector: toggleOnStub } },
|
||||
});
|
||||
|
||||
expect(trackMock).not.toHaveBeenCalledWith(
|
||||
'User toggled n8n connect credential',
|
||||
expect.anything(),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
it('should emit credentialSelected removing credentials when toggled OFF with no available credentials', async () => {
|
||||
credentialsStore.state.credentials = {};
|
||||
|
||||
|
||||
+11
-2
@@ -224,7 +224,7 @@ watch(
|
||||
if (aiGateway.isEnabled.value) {
|
||||
for (const { type } of types) {
|
||||
if (aiGateway.isCredentialTypeSupported(type.name)) {
|
||||
onAiGatewaySelector(type.name, true);
|
||||
onAiGatewaySelector(type.name, true, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -542,7 +542,7 @@ function showAiGatewaySelector(credentialType: string): boolean {
|
||||
return true;
|
||||
}
|
||||
|
||||
function onAiGatewaySelector(credentialType: string, enable: boolean): void {
|
||||
function onAiGatewaySelector(credentialType: string, enable: boolean, isUserAction = true): void {
|
||||
const credentials = { ...(props.node.credentials ?? {}) };
|
||||
|
||||
if (enable) {
|
||||
@@ -564,6 +564,15 @@ function onAiGatewaySelector(credentialType: string, enable: boolean): void {
|
||||
}
|
||||
}
|
||||
|
||||
if (isUserAction) {
|
||||
telemetry.track('User toggled n8n connect credential', {
|
||||
credential_type: credentialType,
|
||||
node_type: props.node.type,
|
||||
mode: enable ? 'n8n_connect' : 'own',
|
||||
workflow_id: props.standalone ? '' : workflowsStore.workflowId,
|
||||
});
|
||||
}
|
||||
|
||||
emit('credentialSelected', {
|
||||
name: props.node.name,
|
||||
properties: { credentials },
|
||||
|
||||
Reference in New Issue
Block a user