@@ -7,7 +7,9 @@ import { expect } from 'chai';
77import  {  Uri  }  from  'vscode' ; 
88import  {  Resource  }  from  '../../../client/common/types' ; 
99import  {  clearCache  }  from  '../../../client/common/utils/cacheUtils' ; 
10- import  {  cacheResourceSpecificInterpreterData  }  from  '../../../client/common/utils/decorators' ; 
10+ import  { 
11+  cacheResourceSpecificInterpreterData ,  makeDebounceDecorator 
12+ }  from  '../../../client/common/utils/decorators' ; 
1113import  {  sleep  }  from  '../../core' ; 
1214
1315// tslint:disable:no-any max-func-body-length no-unnecessary-class 
@@ -97,6 +99,117 @@ suite('Common Utils - Decorators', () => {
9799
98100 expect ( result ) . to . equal ( 3 ) ; 
99101 expect ( cls . invoked ) . to . equal ( true ,  'Must be invoked' ) ; 
102+  } ) ; 
103+ 
104+  // debounce() 
105+  class  Base  { 
106+  public  created : number ; 
107+  public  calls : string [ ] ; 
108+  public  timestamps : number [ ] ; 
109+  constructor ( )  { 
110+  this . created  =  Date . now ( ) ; 
111+  this . calls  =  [ ] ; 
112+  this . timestamps  =  [ ] ; 
113+  } 
114+  protected  _addCall ( funcname : string ,  timestamp ?: number ) : void { 
115+  if  ( ! timestamp )  { 
116+  timestamp  =  Date . now ( ) ; 
117+  } 
118+  this . calls . push ( funcname ) ; 
119+  this . timestamps . push ( timestamp ) ; 
120+  } 
121+  } 
122+  async  function  waitForCalls ( timestamps : number [ ] ,  count : number ,  delay  =  10 ,  timeout  =  1000 )  { 
123+  const  steps  =  timeout  /  delay ; 
124+  for  ( let  i  =  0 ;  i  <  steps ;  i  +=  1 )  { 
125+  if  ( timestamps . length  >=  count )  { 
126+  return ; 
127+  } 
128+  await  sleep ( delay ) ; 
129+  } 
130+  if  ( timestamps . length  <  count )  { 
131+  throw  Error ( `timed out after ${ timeout }  ) ; 
132+  } 
133+  } 
134+  test ( 'Debounce: one sync call' ,  async  ( )  =>  { 
135+  const  wait  =  100 ; 
136+  // tslint:disable-next-line:max-classes-per-file 
137+  class  One  extends  Base  { 
138+  @makeDebounceDecorator ( wait ) 
139+  public  run ( ) : void { 
140+  this . _addCall ( 'run' ) ; 
141+  } 
142+  } 
143+  const  one  =  new  One ( ) ; 
144+ 
145+  const  start  =  Date . now ( ) ; 
146+  one . run ( ) ; 
147+  await  waitForCalls ( one . timestamps ,  1 ) ; 
148+  const  delay  =  one . timestamps [ 0 ]  -  start ; 
149+ 
150+  expect ( delay ) . to . be . at . least ( wait ) ; 
151+  expect ( one . calls ) . to . deep . equal ( [ 'run' ] ) ; 
152+  expect ( one . timestamps ) . to . have . lengthOf ( one . calls . length ) ; 
153+  } ) ; 
154+  test ( 'Debounce: one async call' ,  async  ( )  =>  { 
155+  const  wait  =  100 ; 
156+  // tslint:disable-next-line:max-classes-per-file 
157+  class  One  extends  Base  { 
158+  @makeDebounceDecorator ( wait ) 
159+  public  async  run ( ) : Promise < void >  { 
160+  this . _addCall ( 'run' ) ; 
161+  } 
162+  } 
163+  const  one  =  new  One ( ) ; 
164+ 
165+  const  start  =  Date . now ( ) ; 
166+  await  one . run ( ) ; 
167+  await  waitForCalls ( one . timestamps ,  1 ) ; 
168+  const  delay  =  one . timestamps [ 0 ]  -  start ; 
169+ 
170+  expect ( delay ) . to . be . at . least ( wait ) ; 
171+  expect ( one . calls ) . to . deep . equal ( [ 'run' ] ) ; 
172+  expect ( one . timestamps ) . to . have . lengthOf ( one . calls . length ) ; 
173+  } ) ; 
174+  test ( 'Debounce: multiple calls grouped' ,  async  ( )  =>  { 
175+  const  wait  =  100 ; 
176+  // tslint:disable-next-line:max-classes-per-file 
177+  class  One  extends  Base  { 
178+  @makeDebounceDecorator ( wait ) 
179+  public  run ( ) : void { 
180+  this . _addCall ( 'run' ) ; 
181+  } 
182+  } 
183+  const  one  =  new  One ( ) ; 
184+ 
185+  const  start  =  Date . now ( ) ; 
186+  one . run ( ) ; 
187+  one . run ( ) ; 
188+  one . run ( ) ; 
189+  await  waitForCalls ( one . timestamps ,  1 ) ; 
190+  const  delay  =  one . timestamps [ 0 ]  -  start ; 
191+ 
192+  expect ( delay ) . to . be . at . least ( wait ) ; 
193+  expect ( one . calls ) . to . deep . equal ( [ 'run' ] ) ; 
194+  expect ( one . timestamps ) . to . have . lengthOf ( one . calls . length ) ; 
195+  } ) ; 
196+  test ( 'Debounce: multiple calls spread' ,  async  ( )  =>  { 
197+  const  wait  =  100 ; 
198+  // tslint:disable-next-line:max-classes-per-file 
199+  class  One  extends  Base  { 
200+  @makeDebounceDecorator ( wait ) 
201+  public  run ( ) : void { 
202+  this . _addCall ( 'run' ) ; 
203+  } 
204+  } 
205+  const  one  =  new  One ( ) ; 
206+ 
207+  one . run ( ) ; 
208+  await  sleep ( wait ) ; 
209+  one . run ( ) ; 
210+  await  waitForCalls ( one . timestamps ,  2 ) ; 
100211
212+  expect ( one . calls ) . to . deep . equal ( [ 'run' ,  'run' ] ) ; 
213+  expect ( one . timestamps ) . to . have . lengthOf ( one . calls . length ) ; 
101214 } ) ; 
102215} ) ; 
0 commit comments