import './setup'; // tslint:disable-line import * as assert from 'assert'; import {Observable, of, never, interval, empty} from 'rxjs'; import { map, mergeMap, switchMap, publishReplay, refCount, take, delay, mergeAll, } from 'rxjs/operators'; import {setup, run as globalRun} from '@cycle/rxjs-run'; import {HTTPSource, makeHTTPDriver} from '../../src/rxjs'; import {runTests as runCommon} from './common'; const uri = '//' + window.location.host; runCommon(uri); (global as any).mocha.globals(['Cyclejs']); describe('HTTP Driver in the browser', function() { it('should be able to emit progress events on the response stream', function(done) { function main(_sources: {HTTP: HTTPSource}) { return { HTTP: of({ url: uri + '/querystring', method: 'GET', progress: true, query: {foo: 102030, bar: 'Pub'}, }), }; } const {sources, run} = setup(main, {HTTP: makeHTTPDriver()}); const response$$ = sources.HTTP.select(); response$$.subscribe({ next: function(response$) { assert.strictEqual(response$.request.url, uri + '/querystring'); assert.strictEqual(response$.request.method, 'GET'); assert.strictEqual((response$.request.query as any).foo, 102030); assert.strictEqual((response$.request.query as any).bar, 'Pub'); let progressEventHappened = false; response$.subscribe(function(response) { if (response.type === 'progress') { assert.strictEqual(typeof response.total, 'number'); progressEventHappened = true; } else { assert.strictEqual(progressEventHappened, true); assert.strictEqual(response.status, 200); assert.strictEqual(response.body.foo, '102030'); assert.strictEqual(response.body.bar, 'Pub'); done(); } }); }, }); run(); }); it('should return binary response when responseType option is arraybuffer', function(done) { function main(_sources: {HTTP: HTTPSource}) { return { HTTP: of({ url: uri + '/binary', method: 'GET', responseType: 'arraybuffer', }), }; } const {sources, run} = setup(main, {HTTP: makeHTTPDriver()}); const response$$ = sources.HTTP.select(); response$$.subscribe(function(response$) { assert.strictEqual(response$.request.url, uri + '/binary'); assert.strictEqual(response$.request.method, 'GET'); assert.strictEqual(response$.request.responseType, 'arraybuffer'); response$.subscribe(function(response) { assert.strictEqual(response.status, 200); assert.deepStrictEqual( new Uint8Array(response.body), new Uint8Array([1, 2, 3]) ); done(); }); }); run(); }); it('should return binary response when responseType option is blob', function(done) { function main(_sources: {HTTP: HTTPSource}) { return { HTTP: of({ url: uri + '/binary', method: 'GET', responseType: 'blob', }), }; } const {sources, run} = setup(main, {HTTP: makeHTTPDriver()}); const response$$ = sources.HTTP.select(); response$$.subscribe(function(response$) { assert.strictEqual(response$.request.url, uri + '/binary'); assert.strictEqual(response$.request.method, 'GET'); assert.strictEqual(response$.request.responseType, 'blob'); response$.subscribe(function(response) { assert.strictEqual(response.status, 200); const fr = new FileReader(); fr.onload = ev => { assert.deepStrictEqual( new Uint8Array(fr.result as ArrayBuffer), new Uint8Array([1, 2, 3]) ); done(); }; fr.onerror = ev => { done('should not be called'); }; fr.readAsArrayBuffer(response.body); }); }); run(); }); it('should not have cross-driver race conditions, A (#592)', function(done) { this.timeout(10000); function child(_sources: any, num: any) { const vdom$ = _sources.HTTP.select('cat').pipe( mergeAll(), map((res: any) => 'My name is ' + res.text) ); const request$ = num === 1 ? of({ category: 'cat', url: uri + '/hello', }) : never(); return { HTTP: request$, DOM: vdom$, }; } function mainHTTPThenDOM(_sources: any) { const sinks$ = interval(1000).pipe( take(6), map(i => { if (i % 2 === 1) { return child(_sources, i); } else { return { HTTP: empty(), DOM: of(''), }; } }), publishReplay(1), refCount() ); // order of sinks is important return { HTTP: sinks$.pipe(switchMap(sinks => sinks.HTTP)), DOM: sinks$.pipe(switchMap(sinks => sinks.DOM)), }; } const expectedDOMSinks = [ /* HTTP then DOM: */ '', 'My name is Hello World', '', '', ]; function domDriver(sink: any) { sink.addListener({ next: (s: any) => { assert.strictEqual(s, expectedDOMSinks.shift()); }, error: (err: any) => {}, }); } // HTTP then DOM: globalRun(mainHTTPThenDOM, { HTTP: makeHTTPDriver(), DOM: domDriver, }); setTimeout(() => { assert.strictEqual(expectedDOMSinks.length, 0); done(); }, 8500); }); it('should not have cross-driver race conditions, B (#592)', function(done) { this.timeout(10000); function child(_sources: any, num: any) { const vdom$ = _sources.HTTP.select('cat').pipe( mergeAll(), map((res: any) => 'My name is ' + res.text) ); const request$ = num === 1 ? of({ category: 'cat', url: uri + '/hello', }) : never(); return { HTTP: request$, DOM: vdom$, }; } function mainDOMThenHTTP(_sources: any) { const sinks$ = interval(1000).pipe( take(6), map(i => { if (i % 2 === 1) { return child(_sources, i); } else { return { HTTP: empty(), DOM: of(''), }; } }), publishReplay(1), refCount() ); // order of sinks is important return { DOM: sinks$.pipe(switchMap(sinks => sinks.DOM)), HTTP: sinks$.pipe(switchMap(sinks => sinks.HTTP)), }; } const expectedDOMSinks = [ /* DOM then HTTP: */ '', 'My name is Hello World', '', '', ]; function domDriver(sink: any) { sink.addListener({ next: (s: any) => { assert.strictEqual(s, expectedDOMSinks.shift()); }, error: (err: any) => {}, }); } // HTTP then DOM: globalRun(mainDOMThenHTTP, { HTTP: makeHTTPDriver(), DOM: domDriver, }); setTimeout(() => { assert.strictEqual(expectedDOMSinks.length, 0); done(); }, 8500); }); it('should not remember past responses when selecting', function(done) { this.timeout(4000); function main(_sources: any) { const test$ = of(null).pipe( delay(1000), mergeMap(() => _sources.HTTP.select('cat').pipe( mergeAll(), map((res: any) => 'I should not show this, ' + res.text) ) ) ); const request$ = of({ category: 'cat', url: uri + '/hello', }); return { HTTP: request$, Test: test$, }; } function testDriver(sink: any) { sink.addListener({ next: (s: any) => { console.log(s); done('No data should come through the Test sink'); }, error: (err: any) => { done(err); }, }); } globalRun(main, { HTTP: makeHTTPDriver(), Test: testDriver, }); setTimeout(() => { done(); }, 2000); }); });