1
exercism fetch javascript list-ops

list-ops.spec.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
var List = require('./list-ops');

describe('List', function () {
  // predicates to filter by & functions to map
  var isOdd = function (x) {
    return x % 2 === 1;
  };

  var plusOne = function (x) {
    return x + 1;
  };

  var divide = function (x, acc) {
    return x / acc;
  };

  describe('append', function () {
    it('appends two empty lists', function () {
      var emptyList = new List();
      expect(emptyList.append(emptyList).values).toEqual([]);
    });

    xit('appends an empty list to a non-empty list', function () {
      var emptyList = new List();
      var nonEmptyList = new List([1, 2, 3, 4]);
      expect(emptyList.append(nonEmptyList).values).toEqual([1, 2, 3, 4]);
    });

    xit('appends two non-empty lists', function () {
      var list1 = new List([1, 2]);
      var list2 = new List([2, 3, 4, 5]);
      expect(list1.append(list2).values).toEqual([1, 2, 2, 3, 4, 5]);
    });
  });

  describe('concat', function () {
    xit('concatenates an empty list', function () {
      var emptyList = new List();
      expect(emptyList.concat(emptyList).values).toEqual([]);
    });

    xit('concatenates a list of lists', function () {
      var list1 = new List([1, 2]);
      var list2 = new List([3]);
      var list3 = new List([]);
      var list4 = new List([4, 5, 6]);
      expect(list1
        .concat(list2)
        .concat(list3)
        .concat(list4).values
      ).toEqual([1, 2, 3, 4, 5, 6]);
    });
  });

  describe('filter', function () {
    xit('filters an empty list by a function', function () {
      var list = new List();
      expect(list.filter(isOdd).values).toEqual([]);
    });

    xit('filters a non-empty list by a function', function () {
      var list = new List([1, 2, 3, 5]);
      expect(list.filter(isOdd).values).toEqual([1, 3, 5]);
    });
  });

  describe('length', function () {
    xit('finds the length of a empty list', function () {
      var list = new List();
      expect(list.length()).toEqual(0);
    });

    xit('finds the length of a non-empty list', function () {
      var list = new List([1, 2, 3, 4]);
      expect(list.length()).toEqual(4);
    });
  });

  describe('map', function () {
    xit('maps a function over an empty list', function () {
      var list = new List([]);
      expect(list.map(plusOne).values).toEqual([]);
    });

    xit('maps a function over a non-empty list', function () {
      var list = new List([1, 3, 5, 7]);
      expect(list.map(plusOne).values).toEqual([2, 4, 6, 8]);
    });
  });

  describe('foldl', function () {
    xit('folds an empty list from the left with the given function', function () {
      var list = new List([]);
      expect(list.foldl(divide, 2)).toEqual(2);
    });

    xit('folds a non-empty list from the left with the given function', function () {
      var list = new List([1, 2, 3, 4]);
      expect(list.foldl(divide, 24)).toEqual(64);
    });
  });

  describe('foldr', function () {
    xit('folds an empty list from the right with the given function', function () {
      var list = new List([]);
      expect(list.foldr(divide, 2)).toEqual(2);
    });

    xit('folds a non-empty list from the right with the given function', function () {
      var list = new List([1, 2, 3, 4]);
      expect(list.foldr(divide, 24)).toEqual(9);
    });
  });

  describe('reverse', function () {
    xit('reverses an empty list', function () {
      var list = new List([]);
      expect(list.reverse().values).toEqual([]);
    });

    xit('reverses a non-empty list', function () {
      var list = new List([1, 3, 5, 7]);
      expect(list.reverse().values).toEqual([7, 5, 3, 1]);
    });
  });

  describe('must not call native Array function', function () {
    var list = new List([1, 2, 3, 4]);
    var list2 = new List([5, 1]);

    beforeAll(function () {
      spyOn(list.values, 'map').and.callThrough();
      spyOn(list.values, 'filter').and.callThrough();
      spyOn(list.values, 'reduce').and.callThrough();
      spyOn(list.values, 'reduceRight').and.callThrough();
      spyOn(list.values, 'reverse').and.callThrough();
      spyOn(list.values, 'concat').and.callThrough();

      list.length();
      list.append(list2);
      list.concat(list2);
      list.reverse();
      list.filter(isOdd);
      list.map(plusOne);
      list.foldl(divide, 24);
      list.foldr(divide, 24);
    });

    xit('Array.prototype.map()', function () {
      expect(list.values.map).not.toHaveBeenCalled();
    });
    xit('Array.prototype.filter()', function () {
      expect(list.values.filter).not.toHaveBeenCalled();
    });
    xit('Array.prototype.reduce()', function () {
      expect(list.values.reduce).not.toHaveBeenCalled();
    });
    xit('Array.prototype.reduceRight()', function () {
      expect(list.values.reduceRight).not.toHaveBeenCalled();
    });
    xit('Array.prototype.concat()', function () {
      expect(list.values.concat).not.toHaveBeenCalled();
    });
    xit('Array.prototype.reverse()', function () {
      expect(list.values.reverse).not.toHaveBeenCalled();
    });
  });
});