import { Evt, VoidEvt, EvtError } from "../lib"; import { id, assert } from "../tools/typeSafety"; import { every } from "../tools/reducers"; import { getPromiseAssertionApi } from "../tools/testing/getPromiseAssertionApi"; //const { mustReject, mustResolve } = getPromiseAssertionApi(); const { mustResolve, mustReject } = getPromiseAssertionApi({ "takeIntoAccountArraysOrdering": true }); //import { Operator } from "../lib/types/Operator"; const MESSAGE_TOO_MUCH_BYTES = "Received to much data"; const MESSAGE_CANCEL = "Download canceled by user"; const concatTypedArray = ( chunks: Uint8Array[], totalSize: number ): Uint8Array => { return chunks.reduce( ({ out, n }, chunk) => { out.set( chunk.slice( 0, Math.min(chunk.byteLength, totalSize - n) ), n ); return { out, "n": n + chunk.length }; }, { "out": new Uint8Array(totalSize), "n": 0 } ).out ; } function downloadFile( { fileSize, evtChunk, evtBtnCancelClick, evtSocketError, timeout }: { fileSize: number; evtChunk: Evt; evtBtnCancelClick: VoidEvt; evtSocketError: Evt; timeout: number; } ): Promise { const ctxDl = Evt.newCtx(); evtSocketError.attachOnce( ctxDl, error => ctxDl.abort(error) ); evtBtnCancelClick.attachOnce( ctxDl, () => ctxDl.abort(new Error(MESSAGE_CANCEL)) ); evtChunk .pipe(ctxDl) .pipe([ (chunk, { byteLength, chunks }) => [{ "byteLength": byteLength + chunk.length, "chunks": [...chunks, chunk] }], { "byteLength": 0, "chunks": id([]) } ]) .pipe(({ byteLength }) => byteLength >= fileSize) .pipe(({ byteLength, chunks }) => byteLength > fileSize ? { "DETACH": ctxDl, "err": new Error(MESSAGE_TOO_MUCH_BYTES) } : [chunks] ) .pipe(chunks => [concatTypedArray(chunks, fileSize)]) .attach(rawFile => ctxDl.done(rawFile)) ; return ctxDl.getPrDone(timeout); } const evtChunk = new Evt(); const evtBtnCancelClick = new VoidEvt(); const evtSocketError = new Evt(); (async () => { await (async () => { const prDl = downloadFile({ evtChunk, evtBtnCancelClick, evtSocketError, "fileSize": 9, "timeout": 100 }) evtChunk.post(new Uint8Array([1, 2, 3])); evtChunk.post(new Uint8Array([4, 5, 6])); evtChunk.post(new Uint8Array([7, 0, 1])); assert( [ evtChunk, evtBtnCancelClick, evtSocketError ].reduce(...every>(evt => evt.getHandlers().length === 0)) ); await mustResolve({ "promise": prDl, "expectedData": new Uint8Array([1, 2, 3, 4, 5, 6, 7, 0, 1]) }); })(); await (async () => { const prDl = downloadFile({ evtChunk, evtBtnCancelClick, evtSocketError, "fileSize": 7, "timeout": 100 }) evtChunk.post(new Uint8Array([1, 2, 3])); evtChunk.post(new Uint8Array([4, 5, 6])); evtChunk.post(new Uint8Array([7, 0, 1])); assert( [ evtChunk, evtBtnCancelClick, evtSocketError ].reduce(...every>(evt => evt.getHandlers().length === 0)) ); await mustReject({ "promise": prDl.catch(error => { throw error.message; }), "expectedRejectedValue": MESSAGE_TOO_MUCH_BYTES }); })(); await (async () => { const prDl = downloadFile({ evtChunk, evtBtnCancelClick, evtSocketError, "fileSize": 9, "timeout": 100 }) evtChunk.post(new Uint8Array([1, 2, 3])); evtChunk.post(new Uint8Array([4, 5, 6])); evtBtnCancelClick.post(); assert( [ evtChunk, evtBtnCancelClick, evtSocketError ].reduce(...every>(evt => evt.getHandlers().length === 0)) ); await mustReject({ "promise": prDl.catch(error => { throw error.message; }), "expectedRejectedValue": MESSAGE_CANCEL }); })(); await (async () => { const prDl = downloadFile({ evtChunk, evtBtnCancelClick, evtSocketError, "fileSize": 9, "timeout": 100 }) evtChunk.post(new Uint8Array([1, 2, 3])); evtChunk.post(new Uint8Array([4, 5, 6])); const m = "socket error"; evtSocketError.post(new Error(m)); assert( [ evtChunk, evtBtnCancelClick, evtSocketError ].reduce(...every>(evt => evt.getHandlers().length === 0)) ); await mustReject({ "promise": prDl.catch(error => { throw error.message; }), "expectedRejectedValue": m }); })(); await (async () => { const prDl = downloadFile({ evtChunk, evtBtnCancelClick, evtSocketError, "fileSize": 9, "timeout": 100 }) evtChunk.post(new Uint8Array([1, 2, 3])); evtChunk.post(new Uint8Array([4, 5, 6])); await mustReject({ "promise": prDl.catch(error => { assert(error instanceof EvtError.Timeout); throw ""; }), "expectedRejectedValue": "", "delay": 150 }); assert( [ evtChunk, evtBtnCancelClick, evtSocketError ].reduce(...every>(evt => evt.getHandlers().length === 0)) ); })(); console.log("PASS".green); })();