Created
May 7, 2019 22:05
-
-
Save lamchau/242b4220adeb60fee581b9a0b57699e4 to your computer and use it in GitHub Desktop.
OneMedical Phone Screen (Refactoring Exercise)
This file contains hidden or 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
const Mocha = require('mocha'); | |
const expect = require('chai').expect; | |
const mocha = new Mocha(); | |
/** | |
Welcome to the One Medical Lab! We have a number of items in stock to make sure | |
we can keep our patients happy and healthy. | |
In our lab, our items degrade in quality as they approach their expiration | |
date. In order to keep track of this, we have a service that updates our | |
inventory for us. This was built by one of our past employees a few years back | |
and is beginning to look dusty. | |
Basic Parameters for all items: | |
- All items have a useIn value, which denotes the number of days we have to | |
use the item before the expiration date | |
- All items have a quality value, which is never negative and never greater | |
than 50 | |
Daily updates for normal items: | |
- The useIn and quality values decrease by 1 | |
- Once the expiration date has passed, the quality value decreases twice as | |
fast | |
Daily updates for special items: | |
- For "Thermometer" items, since they are nonperishable, the quality and | |
useIn value are not changed | |
- For "Bacterial Culture" items, the useIn value decreases by 1, while the | |
quality value increases by 1. If the bacterial culture item has expired, | |
then the quality increases twice as fast. | |
- For "Flu Vaccine" items, the useIn value decreases by 1, and the quality | |
value is updated according to the following rules: | |
- Quality increases by 1 when there are more than 10 days before | |
expiration | |
- Quality increases by 2 when there are 6 to 10 days before expiration | |
- Quality increases by 3 when there are 5 days or fewer before expiration | |
- Quality drops to 0 when the flu vaccine has expired | |
We have recently decided to stock a number of refrigerated medications. This | |
requires an update to our system, as we sometimes have power outages. | |
NEW functionality - Daily updates for refrigerated items: | |
- During a power outage, refrigerated normal items decrease in quality twice | |
as fast as non-refrigerated items | |
- The quality of a refrigerated “Bacterial Culture” does not increase. If | |
there is a power outage, the quality of the refrigerated bacterial culture | |
increases by 1 if it has not expired, and by 2 if it has expired. | |
The new updating functionality applies only to refrigerated items. | |
Non-refrigerated items should continue being updated as before. | |
In order to add these new features, feel free to make any changes to the | |
update_quality method and add any new code. However, please do not alter the | |
Item class. Keep in mind that your team will eventually have to add more | |
functionality to this, therefore refactoring for readability is important. | |
**/ | |
class LabInventoryService { | |
static updateQuality(items, powerOutage = false) { | |
for (var i = 0; i < items.length; i++) { | |
if ( | |
items[i].name !== 'Bacterial Culture' && | |
items[i].name !== 'Flu Vaccine' | |
) { | |
if (items[i].quality > 0) { | |
if (items[i].name !== 'Thermometer') { | |
items[i].quality = items[i].quality - 1; | |
} | |
} | |
} else { | |
if (items[i].quality < 50) { | |
items[i].quality = items[i].quality + 1; | |
if (items[i].name === 'Flu Vaccine') { | |
if (items[i].useIn < 11) { | |
if (items[i].quality < 50) { | |
items[i].quality = items[i].quality + 1; | |
} | |
} | |
if (items[i].useIn < 6) { | |
if (items[i].quality < 50) { | |
items[i].quality = items[i].quality + 1; | |
} | |
} | |
} | |
} | |
} | |
if (items[i].name !== 'Thermometer') { | |
items[i].useIn = items[i].useIn - 1; | |
} | |
if (items[i].useIn < 0) { | |
if (items[i].name !== 'Bacterial Culture') { | |
if (items[i].name !== 'Flu Vaccine') { | |
if (items[i].quality > 0) { | |
if (items[i].name !== 'Thermometer') { | |
items[i].quality = items[i].quality - 1; | |
} | |
} | |
} else { | |
items[i].quality = items[i].quality - items[i].quality; | |
} | |
} else { | |
if (items[i].quality < 50) { | |
items[i].quality = items[i].quality + 1; | |
} | |
} | |
} | |
} | |
return items; | |
} | |
} | |
/** Item Class ****************************************************************/ | |
class Item { | |
constructor(name, useIn, quality, refrigerated) { | |
this.name = name; | |
this.useIn = useIn; | |
this.quality = quality; | |
this.refrigerated = refrigerated; | |
} | |
} | |
/** Specs *********************************************************************/ | |
// Required to function correctly within CoderPad | |
mocha.suite.emit('pre-require', this, 'solution', mocha); | |
const items = itemDetails => { | |
return [ | |
new Item( | |
itemDetails.name, | |
itemDetails.useIn, | |
itemDetails.quality, | |
itemDetails.refrigerated || false | |
) | |
]; | |
}; | |
const subject = (items, outage = false) => { | |
return LabInventoryService.updateQuality(items, outage)[0]; | |
}; | |
describe('LabInventoryService', () => { | |
describe('updateQuality', () => { | |
describe('normal items', () => { | |
var itemDetails = { | |
name: 'Normal Item', | |
useIn: 10, | |
quality: 25 | |
}; | |
it('decrements useIn by 1', () => { | |
expect(subject(items(itemDetails)).useIn).to.equal(9); | |
}); | |
it('decrements quality by 1', () => { | |
expect(subject(items(itemDetails)).quality).to.equal(24); | |
}); | |
context('when the useIn date has passed', () => { | |
before(() => (itemDetails.useIn = 0)); | |
it('decrements quality by 2', () => { | |
expect(subject(items(itemDetails)).quality).to.equal(23); | |
}); | |
}); | |
context('when the quality is 0', () => { | |
before(() => (itemDetails.quality = 0)); | |
it('does not decrement quality', () => { | |
expect(subject(items(itemDetails)).quality).to.equal(0); | |
}); | |
}); | |
}); | |
describe('bacterial cultures', () => { | |
var itemDetails; | |
beforeEach(() => { | |
itemDetails = { | |
name: 'Bacterial Culture', | |
useIn: 10, | |
quality: 25, | |
}; | |
}); | |
it('decrements useIn by 1', () => { | |
expect(subject(items(itemDetails)).useIn).to.equal(9); | |
}); | |
it('increments quality by 1', () => { | |
expect(subject(items(itemDetails)).quality).to.equal(26); | |
}); | |
context('when the quality is 50', () => { | |
beforeEach(() => (itemDetails.quality = 50)); | |
it('does not increment quality', () => { | |
expect(subject(items(itemDetails)).quality).to.equal(50); | |
}); | |
}); | |
context('when the bacterial culture is expired', () => { | |
beforeEach(() => (itemDetails.useIn = 0)); | |
it('increases quality by 2', () => { | |
expect(subject(items(itemDetails)).quality).to.equal(27); | |
}) | |
context('when the quality is 49', () => { | |
beforeEach(() => (itemDetails.quality = 49)); | |
it('does not increase quality above 50', () => { | |
expect(subject(items(itemDetails)).quality).to.equal(50); | |
}); | |
}); | |
}); | |
}); | |
describe('thermometers', () => { | |
var itemDetails; | |
beforeEach(() => { | |
itemDetails = { | |
name: 'Thermometer', | |
useIn: 10, | |
quality: 25, | |
}; | |
}); | |
it('does not change useIn', () => { | |
expect(subject(items(itemDetails)).useIn).to.equal(10); | |
}); | |
it('does not change quality', () => { | |
expect(subject(items(itemDetails)).quality).to.equal(25); | |
}); | |
}); | |
describe('flu vaccines', () => { | |
var itemDetails; | |
beforeEach(() => { | |
itemDetails = { | |
name: 'Flu Vaccine', | |
useIn: 11, | |
quality: 25, | |
}; | |
}); | |
it('decrements useIn by 1', () => { | |
expect(subject(items(itemDetails)).useIn).to.equal(10); | |
}); | |
it('increments quality by 1', () => { | |
expect(subject(items(itemDetails)).quality).to.equal(26); | |
}); | |
context('when the quality is 50', () => { | |
beforeEach(() => (itemDetails.quality = 50)); | |
it('does not increment quality', () => { | |
expect(subject(items(itemDetails)).quality).to.equal(50); | |
}); | |
}); | |
context('when there are 6 to 10 days remaining in flu season', () => { | |
beforeEach(() => (itemDetails.useIn = 10)); | |
it('increments quality by 2', () => { | |
expect(subject(items(itemDetails)).quality).to.equal(27); | |
}); | |
context('when the quality is 49', () => { | |
beforeEach(() => (itemDetails.quality = 49)); | |
it('does not increment quality above 50', () => { | |
expect(subject(items(itemDetails)).quality).to.equal(50); | |
}); | |
}); | |
}); | |
context('when there are 1 to 5 days remaining in flu season', () => { | |
beforeEach(() => (itemDetails.useIn = 5)); | |
it('increments quality by 3', () => { | |
expect(subject(items(itemDetails)).quality).to.equal(28); | |
}); | |
context('when the quality is 48', () => { | |
beforeEach(() => (itemDetails.quality = 48)); | |
it('does not increment quality above 50', () => { | |
expect(subject(items(itemDetails)).quality).to.equal(50); | |
}); | |
}); | |
}); | |
context('when flu season is over', () => { | |
beforeEach(() => (itemDetails.useIn = 0)); | |
it('sets quality to 0', () => { | |
expect(subject(items(itemDetails)).quality).to.equal(0); | |
}); | |
}); | |
}); | |
// Remove `.skip` below to unmark these tests as "pending" | |
describe.skip('refrigerated items', () => { | |
var itemDetails; | |
beforeEach(() => { | |
itemDetails = { | |
name: 'Normal Item', | |
useIn: 10, | |
quality: 25, | |
refrigerated: true | |
}; | |
}); | |
context('if the item is a bacterial culture', () => { | |
beforeEach(() => (itemDetails.name = 'Bacterial Culture')); | |
it('does not change quality', () => { | |
expect(subject(items(itemDetails)).quality).to.equal(25); | |
}); | |
after(() => { | |
itemDetails.name = 'Normal Item'; | |
}); | |
}); | |
context('if there was a power outage', () => { | |
it('decrements quality by 2', () => { | |
expect(subject(items(itemDetails), true).quality).to.equal(23); | |
}); | |
context('if useIn is 0', () => { | |
beforeEach(() => (itemDetails.useIn = 0)); | |
it('decrements quality by 4', () => { | |
expect(subject(items(itemDetails), true).quality).to.equal(21); | |
}); | |
after(() => { | |
itemDetails.useIn = 10; | |
}); | |
}); | |
context('if the item is a bacterial culture', () => { | |
beforeEach(() => (itemDetails.name = 'Bacterial Culture')); | |
it('increments quality by 1', () => { | |
expect(subject(items(itemDetails), true).quality).to.equal(26); | |
}); | |
}); | |
}); | |
}); | |
}); | |
}); | |
mocha.run(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment