Skip to content
This repository has been archived by the owner on Feb 20, 2019. It is now read-only.

Commit

Permalink
feat: add clone method (#238)
Browse files Browse the repository at this point in the history
Closes #237

There seem to be lint fixes for other files as well. Hope won't be a problem.
  • Loading branch information
Tolsee authored and Kent C. Dodds committed Feb 9, 2019
1 parent 53137c5 commit 38869bd
Show file tree
Hide file tree
Showing 38 changed files with 355 additions and 235 deletions.
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,13 @@ This repository exists as a resource for people to learn how to contribute to op
## Usage

```javascript
import {flatten, snakeToCamel} from 'stack-overflow-copy-paste'
import {flatten, snakeToCamel, clone} from 'stack-overflow-copy-paste'

flatten([[1, 2,], 3]) // [1, 2, 3]
snakeToCamel('snake-case-string') // 'snakeCaseString'

const testObj = {a: 1, b: 2}
const copyObj = clone(testObj)
```

## LICENSE
Expand Down
60 changes: 60 additions & 0 deletions src/clone.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/**
* Handler functions
*/
const handlers = {
handleDate: date => {
// Handle Date
const copy = new Date()
copy.setTime(date.getTime())
return copy
},
handleArray: array => {
const {length} = array

// Init array
const copy = array.constructor(length)

for (let i = 0; i < length; i++) {
copy[i] = clone(array[i])
}

return copy
},
handleObject: object => {
// Also copy prototypes
const copy = Object.create(Object.getPrototypeOf(object))

for (const attr in object) {
if (object.hasOwnProperty(attr)) {
copy[attr] = clone(object[attr])
}
}
return copy
},
handle(object) {
if (object instanceof Date) {
return this.handleDate(object)
} else if (object instanceof Array) {
return this.handleArray(object)
} else {
return this.handleObject(object)
}
},
}

/**
* Original StackOverflow answer https://stackoverflow.com/a/728694/6880789
* This function will return cloned value
* It can handle primitive data-type, Date, Array and Object
* @param {null|undefined|number|string|function|object} object - any type
* @return {null|undefined|number|string|function|object} - any type
*/
function clone(object) {
// Handle primitive data-types, null and undefined
if (typeof object !== 'object' || object === null || typeof object === 'function') {
return object
}
return handlers.handle(object)
}

export default clone
2 changes: 2 additions & 0 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ import toPower from './to-power'
import truncate from './truncate'
import validateEmail from './validateEmail'
import removeElementByIndex from './removeElementByIndex'
import clone from './clone'

export {
reverseArrayInPlace,
Expand Down Expand Up @@ -182,4 +183,5 @@ export {
largest,
hex2hsl,
removeElementByIndex,
clone,
}
6 changes: 3 additions & 3 deletions test/BitwiseAnd.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ import test from 'ava'
import {BitwiseAnd} from '../src'

test('Returns the Bitwise And of all the Array Elements', t => {
const name1=[1,3,5]
const actual = BitwiseAnd(name1)
const expected=1
const name1 = [1, 3, 5]
const actual = BitwiseAnd(name1)
const expected = 1
t.deepEqual(actual, expected)
})

Expand Down
4 changes: 2 additions & 2 deletions test/array-average.test.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import test from 'ava'
import {
arrayAverage
arrayAverage,
} from '../src'

test('Calculates the average of an array', t => {
const array = [1, 2, 3, 4]
const expected = 2.5
const actual = arrayAverage(array)
t.deepEqual(actual, expected)
})
})
34 changes: 17 additions & 17 deletions test/array-median.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,36 +2,36 @@ import test from 'ava'
import {median} from '../src'

test('accepts only typeof array param', t => {
const array = {}
const expected = `${array} is not an array.`
const actual = median(array)
t.deepEqual(actual, expected)
const array = {}
const expected = `${array} is not an array.`
const actual = median(array)
t.deepEqual(actual, expected)
})

test('accepts only arrays with numeric items', t => {
const array = ['hello', 'world', 5, false]
const expected = `${array} contains non-numeric items.`
const actual = median(array)
t.deepEqual(actual, expected)
const array = ['hello', 'world', 5, false]
const expected = `${array} contains non-numeric items.`
const actual = median(array)
t.deepEqual(actual, expected)
})

test('accepts only nonempty arrays', t => {
const array = []
const expected = `${array} has no items.`
const actual = median(array)
t.deepEqual(actual, expected)
const array = []
const expected = `${array} has no items.`
const actual = median(array)
t.deepEqual(actual, expected)
})

test('finds the median of an array with odd number of items', t => {
const array = [13, 2, 5]
const expected = 5
const actual = median(array)
t.deepEqual(actual, expected)
const array = [13, 2, 5]
const expected = 5
const actual = median(array)
t.deepEqual(actual, expected)
})

test('finds the median of an array with even number of items', t => {
const array = [9, 25, 4, 1]
const expected = 6.5
const actual = median(array)
t.deepEqual(actual, expected)
})
})
55 changes: 55 additions & 0 deletions test/clone.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import test from 'ava'
import {clone} from '../src'

test('Clone number', t => {
const original = 1
const cloned = clone(original)
t.deepEqual(cloned, original)
})

test('Clone string', t => {
const original = 'test string'
const cloned = clone(original)
t.deepEqual(cloned, original)
})

test('Clone array', t => {
const original = [1, 2, 3]
const cloned = clone(original)
t.deepEqual(cloned, original)
})

test('Date', t => {
const original = new Date()
const cloned = clone(original)
t.deepEqual(cloned.getTime(), original.getTime())
})

test('Clone object', t => {
const original = {a: 'test', b: 'test'}
const cloned = clone(original)
t.deepEqual(cloned, original)
})

test('Clone object with prototype', t => {
const original = {a: 'test'}
Object.setPrototypeOf(original, {testprop: 4})
const cloned = clone(original)
t.deepEqual(cloned.testprop, original.testprop)
})

test('Clone function', t => {
function original() {
return 1
}
const cloned = clone(original)
t.deepEqual(cloned(), original())
})

test('Clone Map', t => {
const original = new Map([['key', 'test'], ['a', 'b']])
const cloned = clone(original)
t.deepEqual(cloned, original)
})


2 changes: 1 addition & 1 deletion test/convertToRoman.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@ test('convert to roman numeral', t => {
const expected = 'XXIV'
const actual = convertToRoman(object)
t.deepEqual(actual, expected)
})
})
2 changes: 1 addition & 1 deletion test/cube.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@ test('Cube a number ', t => {
const expected = 5 * 5 * 5
const actual = cube(number)
t.deepEqual(actual, expected)
})
})
2 changes: 1 addition & 1 deletion test/dec2bin.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ test('throws error if number is less than zero', t => {
//const actual = dec2bin(original)
const error = t.throws(() => {
dec2bin(original)
},RangeError)
}, RangeError)
t.is(error.message, 'Input must be a positive integer')
})

Expand Down
2 changes: 1 addition & 1 deletion test/divide-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {divide} from '../src'
test('divide two numbers ', t => {
const number1 = 7
const number2 = 2
const expected = 7/2
const expected = 7 / 2
const actual = divide(number1, number2)
t.deepEqual(actual, expected)
})
10 changes: 5 additions & 5 deletions test/find.test.js
Original file line number Diff line number Diff line change
@@ -1,24 +1,24 @@
import test from 'ava'
import { find } from '../src'
import {find} from '../src'

test('find returns undefined if the input is not an instance of Array', t => {
const original = { prop: 'test' }
const original = {prop: 'test'}
const predicate = element => 'does nothing'
const expected = undefined
const actual = find(original, element => predicate(element))
t.deepEqual(actual, expected)
})

test('find returns the first element that matches the given predicate', t => {
const original = [{ a: 1, b: 2 }, { c: 3 }, { a: 1, c: 4 }]
const original = [{a: 1, b: 2}, {c: 3}, {a: 1, c: 4}]
const predicate = element => element.a === 1
const expected = { a: 1, b: 2 }
const expected = {a: 1, b: 2}
const actual = find(original, element => predicate(element))
t.deepEqual(actual, expected)
})

test('find returns undefined if nothing matches the given predicate', t => {
const original = [{ a: 1, b: 2 }, { c: 3 }, { a: 1, c: 4 }]
const original = [{a: 1, b: 2}, {c: 3}, {a: 1, c: 4}]
const predicate = element => element.d === 1
const expected = undefined
const actual = find(original, element => predicate(element))
Expand Down
14 changes: 7 additions & 7 deletions test/gcd.test.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import test from 'ava'
import {gcd} from '../src'

test("Get gcd for two integers", t => {
const a = 4;
const b = 64;
const expected = 4;
const actual = gcd(a, b);
t.deepEqual(actual, expected)
})
test('Get gcd for two integers', t => {
const a = 4
const b = 64
const expected = 4
const actual = gcd(a, b)
t.deepEqual(actual, expected)
})
52 changes: 26 additions & 26 deletions test/get-object-size.test.js
Original file line number Diff line number Diff line change
@@ -1,34 +1,34 @@
import test from 'ava';
import { getObjectSize } from '../src'
import test from 'ava'
import {getObjectSize} from '../src'

test('returns zero for empty object', t=> {
const testObject = {}
const expected = 0
const actual = getObjectSize(testObject)
t.deepEqual(actual, expected)
test('returns zero for empty object', t => {
const testObject = {}
const expected = 0
const actual = getObjectSize(testObject)
t.deepEqual(actual, expected)
})
test('returns 5 for object with 5 keys', t=> {
const testObject = {
prop1: 'prop1',
prop2: 'prop2',
prop3: 'prop3',
prop4: 'prop4',
prop5: 'prop5',
}
const expected = 5
const actual = getObjectSize(testObject)
t.deepEqual(actual, expected)
test('returns 5 for object with 5 keys', t => {
const testObject = {
prop1: 'prop1',
prop2: 'prop2',
prop3: 'prop3',
prop4: 'prop4',
prop5: 'prop5',
}
const expected = 5
const actual = getObjectSize(testObject)
t.deepEqual(actual, expected)
})
test('returns size of empty array', t => {
const testArray = []
const expected = 0
const actual = getObjectSize(testArray)
t.deepEqual(actual, expected)
const testArray = []
const expected = 0
const actual = getObjectSize(testArray)
t.deepEqual(actual, expected)
})
test('returns size of array with items', t => {
const testArray = ['test', 'test2']
const expected = 2
const actual = getObjectSize(testArray)
t.deepEqual(actual, expected)
const testArray = ['test', 'test2']
const expected = 2
const actual = getObjectSize(testArray)
t.deepEqual(actual, expected)
})

2 changes: 1 addition & 1 deletion test/getMiddle.test.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import test from 'ava'
import { getMiddle } from '../src'
import {getMiddle} from '../src'

test('Gets middle character of given string with a length of uneven number of characters ', t => {
const string = 'rumpelstiltskin'
Expand Down
Loading

0 comments on commit 38869bd

Please sign in to comment.