...

Text file src/edge-infra.dev/third_party/gopherage/cmd/html/ts/utils_test.ts

Documentation: edge-infra.dev/third_party/gopherage/cmd/html/ts

     1import "jasmine";
     2import {enumerate, filter, map, reduce} from './utils';
     3
     4describe('map', () => {
     5  it('should map over an array', () => {
     6    expect(Array.from(map([1, 3, 5], (x) => 2 * x))).toEqual([2, 6, 10]);
     7  });
     8
     9  it('should call the function lazily', () => {
    10    const spy = jasmine.createSpy('mapper').and.callFake((x: number) => 2 * x);
    11
    12    const [generatorSpy, input] = iterableSpy([1, 3]);
    13    const iterable = map(input, spy);
    14    const iterator = iterable[Symbol.iterator]();
    15    expect(generatorSpy).not.toHaveBeenCalled();
    16    expect(spy).not.toHaveBeenCalled();
    17
    18    let next = iterator.next();
    19    expect(next.value).toBe(2);
    20    expect(spy).toHaveBeenCalledTimes(1);
    21    expect(spy).toHaveBeenCalledWith(1);
    22    expect(generatorSpy).toHaveBeenCalledTimes(1);
    23
    24    next = iterator.next();
    25    expect(next.value).toBe(6);
    26    expect(spy).toHaveBeenCalledTimes(2);
    27    expect(spy).toHaveBeenCalledWith(3);
    28    expect(generatorSpy).toHaveBeenCalledTimes(2);
    29
    30    next = iterator.next();
    31    expect(next.done).toBe(true);
    32    expect(spy).toHaveBeenCalledTimes(2);
    33    expect(generatorSpy).toHaveBeenCalledTimes(3);
    34  });
    35
    36  it('should accept non-array iterables', () => {
    37    function* generator(): Iterable<number> {
    38      yield 1;
    39      yield 3;
    40    }
    41    expect(Array.from(map(generator(), (x) => x * 2))).toEqual([2, 6]);
    42  });
    43
    44  it('should do nothing with empty input', () => {
    45    expect(Array.from(map([], (x) => x))).toEqual([]);
    46  });
    47});
    48
    49describe('reduce', () => {
    50  it('should reduce non-array iterators', () => {
    51    function* generator(): Iterable<number> {
    52      yield 1;
    53      yield 2;
    54    }
    55    expect(reduce(generator(), (acc, x) => acc + x, 0)).toBe(3);
    56  });
    57});
    58
    59describe('filter', () => {
    60  it('should accept and produce iterables', () => {
    61    const [inputSpy, input] = iterableSpy([1, 2, 3, 4]);
    62
    63    const f = jasmine.createSpy('f').and.callFake((x: number) => x % 2 === 0);
    64    const iterable = filter(input, f);
    65    const iterator = iterable[Symbol.iterator]();
    66
    67    expect(f).not.toHaveBeenCalled();
    68    let value = iterator.next();
    69    expect(value.value).toBe(2);
    70    expect(f).toHaveBeenCalledTimes(2);
    71    expect(inputSpy).toHaveBeenCalledTimes(2);
    72
    73    value = iterator.next();
    74    expect(value.value).toBe(4);
    75    expect(f).toHaveBeenCalledTimes(4);
    76    expect(inputSpy).toHaveBeenCalledTimes(4);
    77
    78    value = iterator.next();
    79    expect(value.done).toBe(true);
    80    expect(f).toHaveBeenCalledTimes(4);
    81  });
    82});
    83
    84describe('enumerate', () => {
    85  it('should count up', () => {
    86    expect(Array.from(enumerate(['hello', 'world']))).toEqual([
    87      [0, 'hello'], [1, 'world'],
    88    ]);
    89  });
    90
    91  it('should accept and produce iterables', () => {
    92    const [inputSpy, input] = iterableSpy(['hello', 'world']);
    93
    94    const iterable = enumerate(input);
    95    const iterator = iterable[Symbol.iterator]();
    96
    97    expect(inputSpy).not.toHaveBeenCalled();
    98
    99    let value = iterator.next();
   100    expect(value.value).toEqual([0, 'hello']);
   101    expect(inputSpy).toHaveBeenCalledTimes(1);
   102
   103    value = iterator.next();
   104    expect(value.value).toEqual([1, 'world']);
   105    expect(inputSpy).toHaveBeenCalledTimes(2);
   106
   107    value = iterator.next();
   108    expect(value.done).toBe(true);
   109    expect(inputSpy).toHaveBeenCalledTimes(3);
   110  });
   111});
   112
   113// Given an array, returns an iterable that yields the values one at a time,
   114// and also a Spy that lets you observe the usage of that iterable.
   115function iterableSpy<T>(output: T[]): [jasmine.Spy, Iterable<T>] {
   116  const iterator = {
   117    next(): IteratorResult<T> {
   118      if (output.length > 0) {
   119        return {value: output.shift()!, done: false};
   120      } else {
   121        // IteratorResult<T> is incorrect for finished iterators, apparently.
   122        return {done: true} as IteratorResult<T>;
   123      }
   124    },
   125  };
   126
   127  const iterable = {
   128    [Symbol.iterator]() {
   129      return iterator;
   130    },
   131  };
   132
   133  const spy = spyOn(iterator, 'next').and.callThrough();
   134  return [spy, iterable];
   135}

View as plain text