@@ -8,13 +8,15 @@ import { SpyRuleViewer } from '../../stubs/SpyRuleViewer';
88import { SpyRuleWriter } from '../../stubs/SpyRuleWriter' ;
99import { StubDefaultConfigFactory } from '../../stubs/StubCodeAnalyzerConfigFactories' ;
1010import * as StubEnginePluginFactories from '../../stubs/StubEnginePluginsFactories' ;
11+ import { CapturedTelemetryEmission , SpyTelemetryEmitter } from '../../stubs/SpyTelemetryEmitter' ;
1112
1213const PATH_TO_GOLDFILES = path . join ( __dirname , '..' , '..' , 'fixtures' , 'comparison-files' , 'lib' , 'actions' , 'RulesAction.test.ts' ) ;
1314
1415describe ( 'RulesAction tests' , ( ) => {
1516 let viewer : SpyRuleViewer ;
1617 let writer : SpyRuleWriter ;
1718 let spyDisplay : SpyDisplay ;
19+ let spyTelemetryEmitter : SpyTelemetryEmitter ;
1820 let actionSummaryViewer : RulesActionSummaryViewer ;
1921 let defaultDependencies : RulesDependencies ;
2022
@@ -23,11 +25,13 @@ describe('RulesAction tests', () => {
2325 writer = new SpyRuleWriter ( ) ;
2426 spyDisplay = new SpyDisplay ( ) ;
2527 actionSummaryViewer = new RulesActionSummaryViewer ( spyDisplay ) ;
28+ spyTelemetryEmitter = new SpyTelemetryEmitter ( ) ;
2629 defaultDependencies = {
2730 configFactory : new StubDefaultConfigFactory ( ) ,
2831 pluginsFactory : new StubEnginePluginFactories . StubEnginePluginsFactory_withFunctionalStubEngine ( ) ,
2932 logEventListeners : [ ] ,
3033 progressListeners : [ ] ,
34+ telemetryEmitter : spyTelemetryEmitter ,
3135 actionSummaryViewer,
3236 viewer,
3337 writer
@@ -123,14 +127,8 @@ describe('RulesAction tests', () => {
123127 }
124128 ] ) ( 'When $case, only the relevant rules are returned' , async ( { workspace, target} ) => {
125129 const dependencies : RulesDependencies = {
126- configFactory : new StubDefaultConfigFactory ( ) ,
127- // The engine we're using here will synthesize one rule per target.
130+ ...defaultDependencies ,
128131 pluginsFactory : new StubEnginePluginFactories . StubEnginePluginsFactory_withTargetDependentStubEngine ( ) ,
129- logEventListeners : [ ] ,
130- progressListeners : [ ] ,
131- actionSummaryViewer,
132- viewer,
133- writer
134132 } ;
135133 const action = RulesAction . createAction ( dependencies ) ;
136134 const input : RulesInput = {
@@ -161,13 +159,8 @@ describe('RulesAction tests', () => {
161159 */
162160 it ( 'When no engines are registered, empty results are displayed' , async ( ) => {
163161 const dependencies : RulesDependencies = {
164- configFactory : new StubDefaultConfigFactory ( ) ,
162+ ... defaultDependencies ,
165163 pluginsFactory : new StubEnginePluginFactories . StubEnginePluginsFactory_withNoPlugins ( ) ,
166- logEventListeners : [ ] ,
167- progressListeners : [ ] ,
168- actionSummaryViewer,
169- viewer,
170- writer
171164 } ;
172165 const action = RulesAction . createAction ( dependencies ) ;
173166 const input : RulesInput = {
@@ -183,13 +176,8 @@ describe('RulesAction tests', () => {
183176
184177 it ( 'Throws an error when an engine throws an error' , async ( ) => {
185178 const dependencies : RulesDependencies = {
186- configFactory : new StubDefaultConfigFactory ( ) ,
179+ ... defaultDependencies ,
187180 pluginsFactory : new StubEnginePluginFactories . StubEnginePluginsFactory_withThrowingStubPlugin ( ) ,
188- logEventListeners : [ ] ,
189- progressListeners : [ ] ,
190- actionSummaryViewer,
191- viewer,
192- writer
193181 } ;
194182 const action = RulesAction . createAction ( dependencies ) ;
195183 const input : RulesInput = {
@@ -214,13 +202,9 @@ describe('RulesAction tests', () => {
214202 ] ) ( 'When $quantifier rules are returned, $expectation' , async ( { selector, goldfile} ) => {
215203 const goldfilePath : string = path . join ( PATH_TO_GOLDFILES , 'action-summaries' , goldfile ) ;
216204 const dependencies : RulesDependencies = {
217- configFactory : new StubDefaultConfigFactory ( ) ,
205+ ... defaultDependencies ,
218206 pluginsFactory : new StubEnginePluginFactories . StubEnginePluginsFactory_withFunctionalStubEngine ( ) ,
219- logEventListeners : [ ] ,
220- progressListeners : [ ] ,
221- actionSummaryViewer,
222- viewer,
223- writer
207+ viewer
224208 } ;
225209 const action = RulesAction . createAction ( dependencies ) ;
226210 const input : RulesInput = {
@@ -266,6 +250,62 @@ describe('RulesAction tests', () => {
266250 expect ( displayedLogEvents ) . toContain ( goldfileContents ) ;
267251 } ) ;
268252 } ) ;
253+
254+ describe ( 'Telemetry Emission' , ( ) => {
255+ it ( 'When a telemetry emitter is provided, it is used' , async ( ) => {
256+
257+ defaultDependencies . pluginsFactory = new StubEnginePluginFactories . StubEnginePluginsFactory_withFunctionalStubEngine ( ) ;
258+ const action = RulesAction . createAction ( defaultDependencies ) ;
259+ // Create the input.
260+ const input : RulesInput = {
261+ 'rule-selector' : [ 'all' ]
262+ } ;
263+ // ==== TESTED BEHAVIOR ====
264+ await action . execute ( input ) ;
265+
266+ // ==== ASSERTIONS ====
267+ const allTelemEvents : CapturedTelemetryEmission [ ] = spyTelemetryEmitter . getCapturedTelemetry ( ) ;
268+ const ruleSelectionTelemEvents : CapturedTelemetryEmission [ ] = allTelemEvents . filter (
269+ e => e . data . sfcaEvent === 'engine_selection' ) ;
270+
271+ expect ( ruleSelectionTelemEvents ) . toHaveLength ( 2 ) ;
272+ expect ( ruleSelectionTelemEvents [ 0 ] ) . toEqual ( {
273+ "data" : {
274+ "engine" : "stubEngine1" ,
275+ "ruleCount" : 5 ,
276+ "sfcaEvent" : "engine_selection"
277+ } ,
278+ "eventName" : "plugin-code-analyzer" ,
279+ "source" : "CLI" // NOTE: We might move these events to Core in the future instead of the CLI
280+ } ) ;
281+ expect ( ruleSelectionTelemEvents [ 1 ] ) . toEqual ( {
282+ "data" : {
283+ "engine" : "stubEngine2" ,
284+ "ruleCount" : 3 ,
285+ "sfcaEvent" : "engine_selection"
286+ } ,
287+ "eventName" : "plugin-code-analyzer" ,
288+ "source" : "CLI" // NOTE: We might move these events to Core in the future instead of the CLI
289+ } ) ;
290+
291+ const engineSpecificTelemEvents : CapturedTelemetryEmission [ ] = allTelemEvents . filter (
292+ e => e . data . sfcaEvent === 'engine1DescribeTelemetry' ) ;
293+ expect ( engineSpecificTelemEvents ) . toHaveLength ( 1 ) ;
294+ const customEvent : CapturedTelemetryEmission = engineSpecificTelemEvents [ 0 ] ;
295+ customEvent . data [ "timestamp" ] = 0 ; // fix for deterministic testing
296+ customEvent . data [ "uuid" ] = "someUUID" ; // fix for deterministic testing
297+ expect ( customEvent ) . toEqual ( {
298+ "data" : {
299+ "someArg" : true , // argument set by engine
300+ "sfcaEvent" : "engine1DescribeTelemetry" ,
301+ "timestamp" : 0 ,
302+ "uuid" : "someUUID"
303+ } ,
304+ "eventName" : "plugin-code-analyzer" ,
305+ "source" : "stubEngine1"
306+ } ) ;
307+ } ) ;
308+ } )
269309} ) ;
270310
271311// TODO: Whenever we decide to document the custom_engine_plugin_modules flag in our configuration file, then we'll want
0 commit comments