k8s.io/test-infra@v0.0.0-20240520184403-27c6b4c223d8/gopherage/cmd/html/static/utils_test.ts (about)

     1  import "jasmine";
     2  import {enumerate, filter, map, reduce} from './utils';
     3  
     4  describe('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  
    49  describe('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  
    59  describe('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  
    84  describe('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.
   115  function 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  }