Last active
August 29, 2015 14:23
-
-
Save aemkei/892f83935a3c28bdcfdf to your computer and use it in GitHub Desktop.
TDD Bin
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Item: Unit price Special Price | |
// it should return the price for a single item | |
// it shold fail it item does not exist | |
// it should sum up all prices | |
// it should apply special price (3 for 130) for A | |
// it should apply special price (2 for 45) for B | |
describe('cart should accept products', () => { | |
let cart; | |
beforeEach(function(){ | |
cart = new Cart(checkout); | |
}); | |
it('should be possible to add an item', () => { | |
cart.addProduct('a'); | |
assert.equal(cart.size, 1); | |
}) | |
it('should be possible to add more than one item', () => { | |
cart.addProduct('a'); | |
cart.addProduct('b'); | |
assert.equal(cart.size, 2); | |
}) | |
it('should be possible to add multiple item of the same product', () => { | |
cart.addProduct('a', 3); | |
assert.equal(cart.size, 3); | |
assert.deepEqual(cart.items, ['a', 'a', 'a']); | |
}) | |
}); | |
describe('cart checkout', function() { | |
let cart; | |
beforeEach(function(){ | |
cart = new Cart(checkout); | |
}); | |
it('should return price', function() { | |
cart.addProduct('a'); | |
assert.equal(cart.checkout(), 50) | |
}) | |
}) | |
describe('checkout process', function() { | |
describe('should return price', () => { | |
it ('50 for A', () => | |
assert.equal(checkout('a'), 50) | |
); | |
it ('30 for B', () => | |
assert.equal(checkout('b'), 30) | |
); | |
}); | |
describe('should sum up', () => { | |
it ('A+B', () => | |
assert.equal(checkout('a', 'b'), 80) | |
); | |
it ('A+A+C+C', () => | |
assert.equal(checkout('a', 'a', 'b', 'c', 'c', 'd'), 185) | |
); | |
}); | |
describe('sho uld apply special price', () => { | |
it ('if A+A+A', () => | |
assert.equal(checkout('a', 'a', 'a'), 130) | |
); | |
it ('if B+B', () => | |
assert.equal(checkout('b', 'b'), 45) | |
); | |
it ('if B+B + B', () => | |
assert.equal(checkout('b', 'b', 'b'), 75) | |
); | |
it ('if B+B + B+B + B+B + B', () => | |
assert.equal(checkout('b', 'b', 'b', 'b', 'b', 'b', 'b'), 165) | |
); | |
}); | |
describe('should apply special price', () => { | |
describe('should be possible to mix', () => { | |
it('specials', () => { | |
assert.equal(checkout('a', 'a', 'a', 'b', 'b'), 175) | |
}) | |
}) | |
}); | |
describe('should fail if', () => { | |
it ('item does not exist', () => { | |
assert.throws(() => checkout('e'), NotExistError) | |
}); | |
it ('one item of many does not exist', () => { | |
assert.throws(() => checkout('a', 'e'), NotExistError) | |
}); | |
it ('one item of many does not exist', () => { | |
assert.throws(() => checkout('c', 'e'), NotExistError) | |
}); | |
}); | |
}); | |
class Product { | |
constructor(price, special){ | |
this.price = price; | |
this.special = special; | |
} | |
} | |
const products = { | |
a: new Product(50, { count: 3, value: 130 }), | |
b: new Product(30, { count: 2, value: 45 }), | |
c: new Product(20), | |
d: new Product(15) | |
}; | |
class Cart { | |
constructor (checkoutCallback) { | |
this.checkoutCallback = checkoutCallback; | |
this.items = []; | |
} | |
addProduct(productName, count=1){ | |
while (count--) { | |
this.items.push(productName) | |
} | |
} | |
get size () { | |
return this.items.length; | |
} | |
checkout () { | |
return this.checkoutCallback(...this.items); | |
} | |
} | |
class NotExistError {} | |
class Checkout { | |
constructor (...items) { | |
this.items = items; | |
} | |
get sum () { | |
let sum = 0, | |
counts = this.count(this.items); | |
Object.keys(counts).forEach(key => { | |
const count = counts[key]; | |
if (typeof products[key] == 'undefined'){ | |
throw new NotExistError(); | |
} | |
if (products[key].special){ | |
sum += this.special(key, count); | |
} else { | |
sum += products[key].price * count; | |
} | |
}); | |
return sum; | |
} | |
count(items){ | |
let counter = {}; | |
items.forEach(i => { | |
counter[i] = counter[i] || 0; | |
counter[i]++; | |
}); | |
return counter; //items.length; | |
} | |
special(item, count) { | |
const special = products[item].special, | |
modulo = count % special.count; | |
count = Math.floor(count / special.count); | |
return special.value * count + | |
products[item].price * modulo; | |
} | |
} | |
function checkout(...items) { | |
return new Checkout(...items).sum; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment