2016-05-25 18 views
6

Làm thế nào để viết một bài kiểm tra Jasmine để kiểm tra có thể quan sát được với toán tử debounce? Tôi đã theo dõi this blog post và hiểu các nguyên tắc về cách thử nghiệm, nhưng nó dường như không hoạt động.Làm cách nào để kiểm tra có thể quan sát có chứa toán tử thoát?

Dưới đây là nhà máy mà tôi đang sử dụng để tạo ra các quan sát:

import Rx from "rx/dist/rx.all"; 
import DOMFactory from "../utils/dom-factory"; 
import usernameService from "./username.service"; 

function createUsernameComponent(config) { 
    const element = DOMFactory(config); 

    const username = Rx.Observable 
    .fromEvent(element.find('input'), 'input') 
    .pluck('target', 'value') 
    .startWith(config.value); 

    const isAvailable = username 
    .debounce(500) 
    .tap(() => console.info('I am never called!')) 
    .flatMapLatest(usernameService.isAvailable) 
    .startWith(false); 

    const usernameStream = Rx.Observable.combineLatest(username, isAvailable) 
    .map((results) => { 
     const [username, isAvailable] = results; 
     return isAvailable ? username : '' 
    }) 
    .distinctUntilChanged(); 

    return Object.freeze({ 
    stream: usernameStream, 
    view: element 
    }); 
} 

export default createUsernameComponent; 

Lưu ý rằng tap điều hành không bao giờ được gọi bằng các thử nghiệm. Tuy nhiên, nó sẽ được thực hiện đúng nếu tôi chạy mã này trên trình duyệt.

Dưới đây là nỗ lực của tôi lúc kiểm tra:

import Rx from "rx/dist/rx.all"; 
import Username from "./username.component"; 
import DataItemBuilder from "../../../test/js/utils/c+j-builders"; 
import usernameService from "./username.service" 

describe('Username Component',() => { 
    let input, username; 

    beforeEach(() => { 
    const usernameConfig = DataItemBuilder.withName('foo') 
     .withPrompt('label').withType('text').build(); 

    const usernameComponent = Username(usernameConfig); 
    usernameComponent.stream.subscribe(value => username = value); 

    input = usernameComponent.view.find('input'); 
    }); 

    it('should set to a valid username after debounce',() => { 
    const scheduler = injectTestSchedulerIntoDebounce(); 
    scheduler.scheduleRelative(null, 1000,() => { 
     doKeyUpTest('abcddd', 'abcdd'); 
     scheduler.stop(); 
    }); 
    scheduler.start(); 
    scheduler.advanceTo(1000); 
    }); 

    function injectTestSchedulerIntoDebounce() { 
    const originalOperator = Rx.Observable.prototype.debounce; 
    const scheduler = new Rx.TestScheduler(); 

    spyOn(Rx.Observable.prototype, 'debounce').and.callFake((dueTime) => { 
     console.info('The mocked debounce is never called!'); 
     if (typeof dueTime === 'number') { 
     return originalOperator.call(this, dueTime, scheduler); 
     } 
     return originalOperator.call(this, dueTime); 
    }); 

    return scheduler; 
    } 

    function doKeyUpTest(inputValue, expectation) { 
    input.val(inputValue); 
    input.trigger('input'); 
    expect(username).toBe(expectation); 
    } 
}); 

Khi tôi chạy thử nghiệm, các giả debounce không bao giờ được gọi. Tôi dự định thử dịch vụ username sau khi tôi có thể vượt qua số debounce.

Trả lời

1

Trong mã thử nghiệm của bạn, bạn đang kích hoạt sự kiện nhập bên trong hàm scheduleRelative. Điều này không hiệu quả vì bạn đang tiến lên 1000ms trước khi thực hiện thay đổi. Các debouncer sau đó chờ đợi 500ms để debounce các cuộc gọi isAvailable nhưng bạn đã ngừng lập lịch để thời gian không được tiến sau đó.

gì bạn cần làm là: kích hoạt các sự kiện đầu vào trước khi thúc đẩy thời gian lên lịch hoặc thậm chí tốt hơn trong một hàm scheduleRelative trong một thời gian < = 500ms trong một và sau đó bên trong scheduleRelative chức năng cho 1000ms bạn phải gọi expect chức năng với đầu ra dự kiến ​​và sau đó dừng bộ lập lịch biểu.

Nó sẽ giống như thế này:

it('should set to a valid username after debounce',() => { 
    const scheduler = injectTestSchedulerIntoDebounce(); 

    scheduler.scheduleRelative(null, 500,() => { 
     input.val(inputValue); 
     input.trigger('input'); 
    }); 

    scheduler.scheduleRelative(null, 1000,() => { 
     expect(username).toBe(expectation); 
     scheduler.stop(); 
    }); 

    scheduler.start(); 
    scheduler.advanceTo(1000); 
    }); 

Bên cạnh đó tôi có kinh nghiệm tốt hơn với scheduleAbsolute thay vì scheduleRelative vì nó ít gây nhầm lẫn.

1

Như mỗi câu trả lời Simon Jentsch của, dưới đây là câu trả lời bằng scheduleAbsolute thay vì scheduleRelative:

import Rx from "rx/dist/rx.all"; 
import Username from "./username.component"; 
import DataItemBuilder from "../../../test/js/utils/c+j-builders"; 
import usernameService from "./username.service" 

describe('Username Component',() => { 
    let input, username, promiseHelper; 

    const scheduler = new Rx.TestScheduler(0); 

    beforeEach(() => { 
    spyOn(usernameService, 'isAvailable').and.callFake(() => { 
     return Rx.Observable.just(true); 
    }); 
    }); 

    beforeEach(() => { 
    const usernameConfig = DataItemBuilder.withName('foo') 
     .withPrompt('label').withType('text').build(); 

    const usernameComponent = Username(usernameConfig, scheduler); 
    usernameComponent.stream.subscribe(value => username = value); 

    input = usernameComponent.view.find('input'); 
    }); 

    it('should set the username for valid input after debounce', (done) => { 
    doKeyUpTest('abcddd', ''); 
    scheduler.scheduleAbsolute(null, 100,() => { 
     expect(usernameService.isAvailable).not.toHaveBeenCalled(); 
     expect(username).toBe(''); 
    }); 
    scheduler.scheduleAbsolute(null, 1000,() => { 
     expect(usernameService.isAvailable).toHaveBeenCalled(); 
     expect(username).toBe('abcddd'); 
     scheduler.stop(); 
     done(); 
    }); 
    scheduler.start(); 
    }); 

    function doKeyUpTest(inputValue, expectation) { 
    input.val(inputValue); 
    input.trigger('input'); 
    expect(username).toBe(expectation); 
    } 

}); 
Các vấn đề liên quan