Skip to content

Commit efe4227

Browse files
committed
move code to this repo
1 parent 21eb2ed commit efe4227

20 files changed

+537
-1
lines changed

.eslintrc.js

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
module.exports = {
2+
"env": {
3+
"es6": true,
4+
"node": true
5+
},
6+
"extends": "eslint:recommended",
7+
"rules": {
8+
"indent": [
9+
"error",
10+
2
11+
],
12+
"linebreak-style": [
13+
"error",
14+
"unix"
15+
],
16+
"quotes": [
17+
"error",
18+
"single"
19+
],
20+
"semi": [
21+
"error",
22+
"always"
23+
]
24+
},
25+
"globals": {
26+
"describe": false,
27+
"expect": false,
28+
"it": false
29+
}
30+
};

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
node_modules

README.md

+30-1
Original file line numberDiff line numberDiff line change
@@ -1 +1,30 @@
1-
# underbar
1+
# Underbar
2+
3+
This repo is a clone of the open-source project called Underscore.
4+
5+
[Underscore](http://underscorejs.org/) is a popular JavaScript library that supplies utility functions that facilitates programming in a more functional style.
6+
7+
Underscore has been around for nearly 8 years, and in that time, a lot of its facilities [have been subsumed into ES6](https://www.reindex.io/blog/you-might-not-need-underscore/).
8+
9+
However, we think there's considerable learning value to you closely examining a simplified implementation of Underscore.
10+
11+
This is a complete implementation, including tests.
12+
13+
## Running individual tests
14+
15+
Note that the `jest-cli` package was also installed into this repo, with the command:
16+
17+
```
18+
npm install --save-dev jest-cli
19+
```
20+
21+
This should allow you to use this syntax to just run one test file:
22+
23+
```
24+
npm test isArrayLike
25+
```
26+
27+
That will do a partial match on the string and find the matching test and run it.
28+
29+
This can save you some time as you are writing the tests, as opposed to executing the entire test suite on every run.
30+

package.json

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
{
2+
"name": "underbar",
3+
"version": "1.0.0",
4+
"description": "",
5+
"scripts": {
6+
"test": "jest"
7+
},
8+
"repository": {
9+
"type": "git",
10+
"url": "git+https://github.com/tim-hr/underbar.git"
11+
},
12+
"author": "manzoid <manzoid@gmail.com>",
13+
"license": "ISC",
14+
"bugs": {
15+
"url": "https://github.com/tim-hr/underbar/issues"
16+
},
17+
"homepage": "https://github.com/tim-hr/underbar#readme",
18+
"devDependencies": {
19+
"jest": "^19.0.2",
20+
"jest-cli": "^19.0.2"
21+
}
22+
}

test/contains.test.js

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
const _ = require('../underbar');
2+
3+
describe('contains()', () => {
4+
it('returns true if an array contains the target', () => {
5+
const nums = [1, 2, 3, 4, 5];
6+
expect(_.contains(nums, 4)).toBe(true);
7+
});
8+
9+
it('returns false if an array does not contain the target', () => {
10+
const nums = [1, 2, 3, 4, 5];
11+
expect(_.contains(nums, 7)).toBe(false);
12+
});
13+
14+
it('returns true if the target value is among the values of an object', () => {
15+
const ponies = {
16+
'pony1': 'Fluttershy',
17+
'pony2': 'Pinkie Pie',
18+
'pony3': 'Rainbow Dash',
19+
'pony4': 'Rarity'
20+
};
21+
expect(_.contains(ponies, 'Rarity')).toBe(true);
22+
});
23+
24+
it('returns false if the target value is not among the values of an object', () => {
25+
const ponies = {
26+
'pony1': 'Fluttershy',
27+
'pony2': 'Pinkie Pie',
28+
'pony3': 'Rainbow Dash',
29+
'pony4': 'Rarity'
30+
};
31+
expect(_.contains(ponies, 'Applejack')).toBe(false);
32+
});
33+
34+
});

test/each.test.js

+43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
const _ = require('../underbar');
2+
3+
describe('each()', () => {
4+
it('iterates every element of an array, passing that element, its corresponding index, and the entire array to the callback', () => {
5+
const arr = ['a', 'b', 'c'];
6+
let count = 0;
7+
_.each(arr, function(element, index, array) {
8+
expect(element).toEqual(array[index]);
9+
count += 1;
10+
});
11+
expect(count).toBe(3);
12+
});
13+
14+
it('iterates every element of an array-like object, passing that element, its corresponding index, and the entire array to the callback', () => {
15+
const arrayLikeObj = {
16+
length: 3,
17+
1: 'a',
18+
2: 'b',
19+
3: 'c'
20+
};
21+
let count = 0;
22+
_.each(arrayLikeObj, function(element, index, iteratedArrayLikeObj) {
23+
expect(element).toEqual(iteratedArrayLikeObj[index]);
24+
count += 1;
25+
});
26+
expect(count).toBe(3);
27+
});
28+
29+
it('iterates every property of an object, passing the value, the corresponding key, and the entire object to the callback', () => {
30+
const obj = {
31+
name: 'Calvin',
32+
age: 6,
33+
occupation: 'student'
34+
};
35+
let count = 0;
36+
_.each(obj, function(value, key, iteratedObj) {
37+
expect(value).toEqual(iteratedObj[key]);
38+
count += 1;
39+
});
40+
expect(count).toBe(3);
41+
});
42+
});
43+

test/every.test.js

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
const _ = require('../underbar');
2+
3+
describe('every()', () => {
4+
describe('processing an array of numbers', () => {
5+
it('will return true if no callback is supplied', () => {
6+
const nums = [1, 3, 5, 7];
7+
expect(_.every(nums)).toBe(true);
8+
});
9+
10+
it('returns true if all numbers in an array are odd and we test for odd numbers', () => {
11+
const nums = [1, 3, 5, 7];
12+
expect(_.every(nums, num => num % 2 === 1)).toBe(true);
13+
});
14+
15+
it('returns false if not all numbers in an array are odd and we test for odd numbers', () => {
16+
const nums = [1, 3, 5, 6, 7];
17+
expect(_.every(nums, num => num % 2 === 1)).toBe(false);
18+
});
19+
20+
});
21+
});

test/filter.test.js

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
const _ = require('../underbar');
2+
3+
describe('filter()', () => {
4+
it('filters an array to odd numbers', () => {
5+
const nums = [2, 4, 5, 6, 7, 8, 10, 11];
6+
expect(_.filter(nums, num => num % 2 === 1)).toEqual([5, 7, 11]);
7+
});
8+
9+
it('filters an object to only numeric values', () => {
10+
const characterAttributes = {
11+
name: 'Thokul Mongothsbeard',
12+
honorific: 'Lord Thokul Mongothsbeard the Arcane',
13+
race: 'human',
14+
class: 'druid',
15+
strength: 4,
16+
constitution: 7,
17+
dexterity: 10,
18+
intelligence: 16,
19+
wisdom: 5,
20+
charisma: 4
21+
};
22+
23+
const abilityScores = _.filter(characterAttributes, (value) => !isNaN(value));
24+
expect(abilityScores).toEqual([4, 7, 10, 16, 5, 4]);
25+
});
26+
});

test/first.test.js

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
const _ = require('../underbar');
2+
3+
describe('first()', () => {
4+
it('returns the first element of an array', () => {
5+
expect(_.first(['a', 'b', 'c'])).toEqual('a');
6+
});
7+
8+
it('returns the first 2 elements of an array', () => {
9+
expect(_.first(['a', 'b', 'c'], 2)).toEqual(['a', 'b']);
10+
});
11+
12+
it('returns the whole array if you ask for more elements than it has', () => {
13+
expect(_.first(['a', 'b', 'c'], 5)).toEqual(['a', 'b', 'c']);
14+
});
15+
});

test/identity.test.js

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
const _ = require('../underbar');
2+
3+
describe('identity()', () => {
4+
it('returns null if given null', () => {
5+
expect(_.identity(null)).toBe(null);
6+
});
7+
8+
it('returns the number if given a number', () => {
9+
expect(_.identity(5)).toBe(5);
10+
});
11+
12+
it('returns the same array if given an array', () => {
13+
const val = [1, 2, 3];
14+
expect(_.identity(val)).toBe(val);
15+
});
16+
17+
it('returns the same object if given an object', () => {
18+
const val = {
19+
'foo': 'bar'
20+
};
21+
expect(_.identity(val)).toBe(val);
22+
});
23+
});

test/indexOf.test.js

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
const _ = require('../underbar');
2+
3+
describe('indexOf()', () => {
4+
it('returns the index of a value at the beginning of an array', () => {
5+
const arr = ['foo', 'bar', 'baz'];
6+
expect(_.indexOf(arr, 'foo')).toBe(0);
7+
});
8+
9+
it('returns the index of a value at the end of an array', () => {
10+
const arr = ['foo', 'bar', 'baz'];
11+
expect(_.indexOf(arr, 'baz')).toBe(2);
12+
});
13+
14+
it('returns -1 for a missing value', () => {
15+
const arr = ['foo', 'bar', 'baz'];
16+
expect(_.indexOf(arr, 'quux')).toBe(-1);
17+
});
18+
19+
it('returns the first matching index when multiple matches in array', () => {
20+
const arr = ['foo', 'bar', 'baz', 'bar', 'bar'];
21+
expect(_.indexOf(arr, 'bar')).toBe(1);
22+
});
23+
24+
it('starts searching at the given offset', () => {
25+
const arr = ['foo', 'bar', 'baz', 'bar', 'bar'];
26+
expect(_.indexOf(arr, 'bar', 2)).toBe(3);
27+
});
28+
29+
});

test/isArrayLike.test.js

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
const _ = require('../underbar');
2+
3+
describe('isArrayLike()', () => {
4+
it('returns true for an actual array', () => {
5+
expect(_.isArrayLike([1, 2, 3])).toBe(true);
6+
});
7+
8+
it('returns true for an array-like object', () => {
9+
const arrayLikeObj = {
10+
length: 10
11+
};
12+
expect(_.isArrayLike(arrayLikeObj)).toBe(true);
13+
});
14+
15+
it('returns false for a non-array-like object', () => {
16+
const nonArrayLikeObj = {
17+
'foo': 'bar'
18+
};
19+
expect(_.isArrayLike(nonArrayLikeObj)).toBe(false);
20+
});
21+
});

test/last.test.js

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
const _ = require('../underbar');
2+
3+
describe('last()', () => {
4+
it('returns the last element of an array', () => {
5+
expect(_.last(['a', 'b', 'c'])).toEqual('c');
6+
});
7+
8+
it('returns the last 2 elements of an array', () => {
9+
expect(_.last(['a', 'b', 'c'], 2)).toEqual(['b', 'c']);
10+
});
11+
12+
it('returns the whole array if you ask for more elements than it has', () => {
13+
expect(_.last(['a', 'b', 'c'], 5)).toEqual(['a', 'b', 'c']);
14+
});
15+
});

test/map.test.js

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
_ = require('../underbar');
2+
3+
describe('map()', () => {
4+
it('maps every numbers in an array of numbers to their square', () => {
5+
const arr = [1, 2, 3, 4, 5];
6+
const mappedArr = _.map(arr, (el) => el * el);
7+
expect(mappedArr).toEqual([1, 4, 9, 16, 25]);
8+
});
9+
});

test/pluck.test.js

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
const _ = require('../underbar');
2+
3+
describe('pluck()', () => {
4+
it('returns an array of just ages, given an array of people objects', () => {
5+
const people = [
6+
{ name: 'Harriet', age: 12},
7+
{ name: 'Lazarus', age: 999},
8+
{ name: 'Bethany', age: 14}
9+
];
10+
const result = _.pluck(people, 'age');
11+
expect(result).toEqual([12, 999, 14]);
12+
});
13+
14+
});

test/reduce.test.js

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
const _ = require('../underbar');
2+
3+
describe('reduce()', () => {
4+
it('reduces an array of numbers to a sum, *with* an explicit initial value for the accumulator', () => {
5+
const nums = [1, 2, 3, 4, 5];
6+
const result = _.reduce(nums, (acc, num) => acc + num, 0);
7+
expect(result).toEqual(15);
8+
});
9+
10+
it('reduces an array of numbers to a sum, *without* an explicit initial value for the accumulator', () => {
11+
const nums = [1, 2, 3, 4, 5];
12+
const result = _.reduce(nums, (a, b) => a + b);
13+
expect(result).toEqual(15);
14+
});
15+
16+
});

0 commit comments

Comments
 (0)