tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

observable-finally.any.js (6947B)


      1 // Because we test that the global error handler is called at various times.
      2 setup({allow_uncaught_exception: true});
      3 
      4 test(() => {
      5  const source = new Observable((subscriber) => {
      6    subscriber.next(1);
      7    subscriber.next(2);
      8    subscriber.next(3);
      9    subscriber.complete();
     10  });
     11 
     12  const results = [];
     13 
     14  source
     15    .finally(() => {
     16      results.push("finally called");
     17    })
     18    .subscribe({
     19      next: (value) => results.push(value),
     20      error: (e) => results.push(e.message),
     21      complete: () => results.push("complete"),
     22    });
     23 
     24  assert_array_equals(results, [1, 2, 3, "finally called", "complete"],
     25      "finally is called with teardown timing, before complete() is forwarded");
     26 }, "finally(): Mirrors all values and completions from source");
     27 
     28 test(() => {
     29  const source = new Observable((subscriber) => {
     30    subscriber.next(1);
     31    subscriber.next(2);
     32    subscriber.next(3);
     33    subscriber.error(new Error("error from source"));
     34  });
     35 
     36  const results = [];
     37 
     38  source
     39    .finally(() => {
     40      results.push("finally called");
     41    })
     42    .subscribe({
     43      next: (value) => results.push(value),
     44      error: (e) => results.push(e.message),
     45      complete: () => results.push("complete"),
     46    });
     47 
     48  assert_array_equals(results, [1, 2, 3, "finally called", "error from source"],
     49      "finally is called with teardown timing, before complete() is forwarded");
     50 }, "finally(): Mirrors all values and errors from the source");
     51 
     52 test(() => {
     53  const results = [];
     54 
     55  const source = new Observable((subscriber) => {
     56    results.push("source subscribe");
     57    subscriber.addTeardown(() => results.push("source teardown"));
     58    results.push("source send complete");
     59    subscriber.complete();
     60  });
     61 
     62  const result = source.finally(() => {
     63    results.push("finally handler");
     64  });
     65 
     66  result.subscribe({
     67    complete: () => results.push("result complete"),
     68  });
     69 
     70  assert_array_equals(results, [
     71    "source subscribe",
     72    "source send complete",
     73    "source teardown",
     74    "finally handler",
     75    "result complete",
     76  ]);
     77 }, "finally(): Callback handler fires BEFORE the source observable completes");
     78 
     79 test(() => {
     80  const results = [];
     81 
     82  const source = new Observable((subscriber) => {
     83    results.push("source subscribe");
     84    subscriber.addTeardown(() => results.push("source teardown"));
     85    results.push("source send error");
     86    subscriber.error(new Error("error from source"));
     87  });
     88 
     89  const result = source.finally(() => {
     90    results.push("finally handler");
     91  });
     92 
     93  result.subscribe({
     94    error: (e) => results.push(e.message),
     95  });
     96 
     97  assert_array_equals(results, [
     98    "source subscribe",
     99    "source send error",
    100    "source teardown",
    101    "finally handler",
    102    "error from source",
    103  ]);
    104 }, "finally(): Callback handler fires BEFORE the source observable errors");
    105 
    106 test(() => {
    107  const results = [];
    108 
    109  const source = new Observable((subscriber) => {
    110    subscriber.complete();
    111  });
    112 
    113  const result = source
    114    .finally(() => {
    115      results.push("finally handler 1");
    116    })
    117    .finally(() => {
    118      results.push("finally handler 2");
    119    });
    120 
    121  result.subscribe({ complete: () => results.push("result complete") });
    122 
    123  assert_array_equals(results,
    124    ["finally handler 1", "finally handler 2", "result complete"]);
    125 }, "finally(): Handlers run in composition order");
    126 
    127 test(() => {
    128  const source = new Observable(subscriber => {
    129    subscriber.error("producer error");
    130  });
    131 
    132  const results = [];
    133 
    134  self.addEventListener('error', e => results.push(e.error.message), {once: true});
    135 
    136  source
    137    .finally(() => {
    138      throw new Error("error from finally");
    139    })
    140    .subscribe({
    141      next: () => results.push("next"),
    142      error: (e) => results.push(e),
    143      complete: () => results.push("complete"),
    144    });
    145 
    146  assert_array_equals(results, ["error from finally", "producer error"]);
    147 }, "finally(): Errors thrown in the finally handler " +
    148   "(during Subscriber#error()) are reported to the global immediately");
    149 
    150 test(() => {
    151  const source = new Observable((subscriber) => {
    152    subscriber.complete();
    153  });
    154 
    155  const results = [];
    156 
    157  self.addEventListener('error', e => results.push(e.error.message), {once: true});
    158 
    159  source
    160    .finally(() => {
    161      throw new Error("error from finally");
    162    })
    163    .subscribe({
    164      next: () => results.push("next"),
    165      error: (e) => results.push("unreached"),
    166      complete: () => results.push("complete"),
    167    });
    168 
    169  assert_array_equals(results, ["error from finally", "complete"]);
    170 }, "finally(): Errors thrown in the finally handler " +
    171   "(during Subscriber#complete()) are reported to the global immediately");
    172 
    173 test(() => {
    174  const results = [];
    175 
    176  const source = new Observable((subscriber) => {
    177    subscriber.addTeardown(() => results.push("source teardown"));
    178  });
    179 
    180  const controller = new AbortController();
    181 
    182  source
    183    .finally(() => results.push("downstream finally handler"))
    184    .subscribe({}, { signal: controller.signal });
    185 
    186  controller.abort();
    187 
    188  assert_array_equals(results, ["source teardown", "downstream finally handler"]);
    189 }, "finally(): Callback is run if consumer aborts the subscription");
    190 
    191 test(() => {
    192  const results = [];
    193  const result = new Observable((subscriber) => {
    194    subscriber.next(1);
    195    subscriber.next(2);
    196    subscriber.complete();
    197  }).flatMap((value) => {
    198    results.push(`flatMap ${value}`);
    199    return new Observable((subscriber) => {
    200      subscriber.next(value);
    201      subscriber.next(value);
    202      subscriber.next(value);
    203      subscriber.complete();
    204    }).finally(() => {
    205      results.push(`finally ${value}`);
    206    });
    207  });
    208 
    209  result.subscribe({
    210    next: (value) => results.push(`result ${value}`),
    211    complete: () => results.push("result complete"),
    212  });
    213 
    214  assert_array_equals(results, [
    215    "flatMap 1",
    216    "result 1",
    217    "result 1",
    218    "result 1",
    219    "finally 1",
    220    "flatMap 2",
    221    "result 2",
    222    "result 2",
    223    "result 2",
    224    "finally 2",
    225    "result complete",
    226  ]);
    227 }, "finally(): Callback is run before next inner subscription in flatMap()");
    228 
    229 test(() => {
    230  const results = [];
    231  const result = new Observable((subscriber) => {
    232    subscriber.next(1);
    233    subscriber.next(2);
    234    subscriber.complete();
    235  }).switchMap((value) => {
    236    results.push(`switchMap ${value}`);
    237    return new Observable((subscriber) => {
    238      subscriber.next(value);
    239      subscriber.next(value);
    240      subscriber.next(value);
    241      subscriber.complete();
    242    }).finally(() => {
    243      results.push(`finally ${value}`);
    244    });
    245  });
    246 
    247  result.subscribe({
    248    next: (value) => results.push(`result ${value}`),
    249    complete: () => results.push("result complete"),
    250  });
    251 
    252  assert_array_equals(results, [
    253    "switchMap 1",
    254    "result 1",
    255    "result 1",
    256    "result 1",
    257    "finally 1",
    258    "switchMap 2",
    259    "result 2",
    260    "result 2",
    261    "result 2",
    262    "finally 2",
    263    "result complete",
    264  ]);
    265 }, "finally(): Callback is run before next inner subscription in switchMap()");