2017-02-17 55 views
2

我意识到可能有更好的方式使用周期/时间,但我只是想了解基础知识。不知何故,我的行动$流似乎并没有运行;我试图用xs.periodic构造多个模拟dom。测试框架是摩卡。如何使用mockDOMSource测试Cycle.js中的操作流?

import 'mocha'; 
import {expect} from 'chai'; 
import xs from 'xstream'; 
import Stream from 'xstream'; 
import {mockDOMSource, DOMSource} from '@cycle/dom'; 
import {HTTPSource} from '@cycle/http'; 
import XStreamAdapter from '@cycle/xstream-adapter'; 

export interface Props { 
    displayAbs: boolean 
} 

export interface ISources { 
    DOM: DOMSource; 
    http: HTTPSource; 
} 

function testIntent(sources: ISources):Stream<Props> { 
    return xs.merge<Props>(
     sources.DOM 
      .select('.absShow').events('click') 
      .mapTo({ displayAbs: true }), 
     sources.DOM 
      .select('.absHide').events('click') 
      .mapTo({ displayAbs: false }) 
).startWith({displayAbs: false }); 
} 

describe('Test',()=>{ 

    describe('intent()',()=>{ 

    it('should change on click to shows and hides',() => { 
     let listenerGotEnd = false; 

     const mDOM$: Stream<DOMSource> = xs.periodic(1000).take(6).map(ii => { 
     if (ii % 2 == 0) { 
      return mockDOMSource(XStreamAdapter, { 
      '.absShow': {'click': xs.of({target: {}})} 
      }) 
     } 
     else { 
      return mockDOMSource(XStreamAdapter, { 
      '.absHide': {'click': xs.of({target: {}})} 
      }) 
     } 
     }); 

     const action$ = mDOM$.map(mDOM => testIntent({ 
     DOM: mDOM, 
     http: {} as HTTPSource, 
     })).flatten(); 


     action$.addListener({ 
     next: (x) => { 
      console.log("x is " + x.displayAbs); 
     }, 
     error: (err) => { 
      console.log("error is:" + err); 
      throw err; 
     }, 
     complete:() => { listenerGotEnd = true; } 
     }); 
     expect(listenerGotEnd).to.equal(true); 
    }); 

    });/* end of describe intent */ 

}); 

回答

4

测试不运行的主要原因是因为它是异步的,所以在摩卡我们需要在done回调,然后调用它,当我们的测试已经完成。

不使用@cycle/time,这是我怎么会写这样的测试:

import 'mocha'; 
import {expect} from 'chai'; 
import xs, {Stream} from 'xstream'; 
import {mockDOMSource, DOMSource} from '@cycle/dom'; 
import XStreamAdapter from '@cycle/xstream-adapter'; 

export interface Props { 
    displayAbs: boolean 
} 

export interface ISources { 
    DOM: DOMSource; 
} 

function testIntent(sources: ISources):Stream<Props> { 
    return xs.merge<Props>(
     sources.DOM 
      .select('.absShow').events('click') 
      .mapTo({ displayAbs: true }), 
     sources.DOM 
      .select('.absHide').events('click') 
      .mapTo({ displayAbs: false }) 
).startWith({displayAbs: false }); 
} 

describe('Test',() => { 
    describe('intent()',() => { 
    it('should change on click to shows and hides', (done) => { 
     const show$ = xs.create(); 
     const hide$ = xs.create(); 

     const DOM = mockDOMSource(XStreamAdapter, { 
     '.absShow': { 
      'click': show$ 
     }, 

     '.absHide': { 
      'click': hide$ 
     } 
     }); 

     const intent$ = testIntent({DOM}); 

     const expectedValues = [ 
     {displayAbs: false}, 
     {displayAbs: true}, 
     {displayAbs: false}, 
     ] 

     intent$.take(expectedValues.length).addListener({ 
     next: (x) => { 
      expect(x).to.deep.equal(expectedValues.shift()); 
     }, 
     error: done, 
     complete: done 
     }); 

     show$.shamefullySendNext({}); 
     hide$.shamefullySendNext({}); 
    }); 
    }); 
}); 

该测试在11毫秒运行,这比使用xs.periodic(1000).take(6)

为了比较的公平快一点,这里是如何我会写它@cycle/time

import {mockTimeSource} from '@cycle/time' 

describe('Test',() => { 
    describe('intent()',() => { 
    it('should change on click to shows and hides', (done) => { 
     const Time = mockTimeSource(); 

     const show$  = Time.diagram('---x-----'); 
     const hide$  = Time.diagram('------x--'); 
     const expected$ = Time.diagram('f--t--f--', {f: false, t: true}); 

     const DOM = mockDOMSource({ 
     '.absShow': { 
      'click': show$ 
     }, 

     '.absHide': { 
      'click': hide$ 
     } 
     }); 

     const intent$ = testIntent({DOM}).map(intent => intent.displayAbs); 

     Time.assertEqual(intent$, expected$); 

     Time.run(done); 
    }); 
    }); 
}); 

第一个版本是有效的@循环/时间为你做的事unde引擎盖,这只是一个稍微好一点的写作方式。有更好的错误信息也很好。

相关问题