Browse Source

add happiness manager subject and tests

content-update
Louise Foussat 3 years ago committed by Clément
parent
commit
cea85c2ace
  1. 402
      js/tests/happiness-manager_test.mjs
  2. 52
      subjects/happiness-manager/README.md

402
js/tests/happiness-manager_test.mjs

@ -0,0 +1,402 @@
import * as cp from 'child_process'
import fs from 'fs/promises'
import { tmpdir } from 'os'
import { promisify } from 'util'
const mkdir = fs.mkdir
const writeFile = fs.writeFile
const readFile = fs.readFile
const exec = promisify(cp.exec)
export const tests = []
export const setup = async ({ path }) => {
const tmpPath = `${tmpdir()}/happiness-manager`
await mkdir(tmpPath)
await mkdir(`${tmpPath}/guests`)
const run = async (folder, file) => {
const output = await exec(
`node ${path} ${tmpPath}/${folder} ${tmpPath}/${file}`,
)
const fileContent = await readFile(`${tmpPath}/${file}`, 'utf8').catch(
(err) => (err.code === 'ENOENT' ? 'output file not found' : err),
)
return {
data:
fileContent === 'output file not found'
? fileContent
: JSON.parse(fileContent),
stdout: output.stdout.trim(),
stderr: output.stderr.trim(),
}
}
const resetAnswersIn = async ({ folder }) => {
const dir = await fs.readdir(`${tmpPath}/${folder}`)
await Promise.all(dir.map((file) => fs.rm(`${tmpPath}/${folder}/${file}`)))
}
const createAnswers = (nb, elem) => [...Array(nb).keys()].map(() => elem)
const setAnswersIn = async ({ answers, folder }) => {
await resetAnswersIn({ folder })
await Promise.all(
answers.map(
async (content, idx) =>
await writeFile(
`${tmpPath}/${folder}/${idx}.json`,
JSON.stringify(content, null, '\t'),
'utf8',
),
),
)
}
return { run, tmpPath, createAnswers, resetAnswersIn, setAnswersIn }
}
tests.push(async ({ path, eq, ctx }) => {
// test with no vips (no {answer: yes})
// no file should be created, a special message should appear in console
const answers = ctx.createAnswers(2, { answer: 'no' })
await ctx.setAnswersIn({ folder: 'guests', answers })
const { stdout, data } = await ctx.run('guests', 'happy-list.json')
return eq(
{ stdout, data },
{ stdout: 'No one is coming.', data: 'output file not found' },
)
})
tests.push(async ({ path, eq, ctx }) => {
// test when vips answer { food: 'carnivores' }
// should create a list with burgers and potatoes
const answers = ctx.createAnswers(2, { answer: 'yes', food: 'carnivore' })
await ctx.setAnswersIn({ folder: 'guests', answers })
const { data } = await ctx.run('guests', 'happy-carn-list.json')
return eq(data, { burgers: 2, potatoes: 2 })
})
tests.push(async ({ path, eq, ctx }) => {
// test when vips answer { food: 'fish' }
// should create a list with sardines and potatoes
const answers = [
{ answer: 'no', food: 'fish' },
...ctx.createAnswers(3, { answer: 'yes', food: 'fish' }),
]
await ctx.setAnswersIn({ folder: 'guests', answers })
const { data } = await ctx.run('guests', 'happy-fish-list.json')
return eq(data, { potatoes: 3, sardines: 3 })
})
tests.push(async ({ path, eq, ctx }) => {
// test when vips answer { food: 'everything' }
// should create a list with kebabs and potatoes
const answers = [
{ answer: 'no', food: 'everything' },
...ctx.createAnswers(3, { answer: 'yes', food: 'everything' }),
]
await ctx.setAnswersIn({ folder: 'guests', answers })
const { data } = await ctx.run('guests', 'happy-omni-list.json')
return eq(data, { potatoes: 3, kebabs: 3 })
})
tests.push(async ({ path, eq, ctx }) => {
// test when vips answer { drink: 'beer' }
// should create a list with 6-packs-beers and potatoes
const answers = [
{ answer: 'no', drink: 'beer' },
...ctx.createAnswers(1, { answer: 'yes', drink: 'beer' }),
]
await ctx.setAnswersIn({ folder: 'guests', answers })
const { data } = await ctx.run('guests', 'happy-beer-list.json')
return eq(data, { potatoes: 1, '6-packs-beers': 1 })
})
tests.push(async ({ path, eq, ctx }) => {
// test when vips answer { drink: 'beer' }
// should create a list with 6-packs-beers and potatoes
const answers = [
{ answer: 'no', drink: 'beer' },
...ctx.createAnswers(6, { answer: 'yes', drink: 'beer' }),
]
await ctx.setAnswersIn({ folder: 'guests', answers })
const { data } = await ctx.run('guests', 'happy-beer-pack-list.json')
return eq(data, { potatoes: 6, '6-packs-beers': 1 })
})
tests.push(async ({ path, eq, ctx }) => {
// test when vips answer { drink: 'wine' }
// should create a list with wine-bottles and potatoes
const answers = [
...ctx.createAnswers(3, { answer: 'no', drink: 'wine' }),
...ctx.createAnswers(5, { answer: 'yes', drink: 'wine' }),
]
await ctx.setAnswersIn({ folder: 'guests', answers })
const { data } = await ctx.run('guests', 'happy-wine-list.json')
return eq(data, { potatoes: 5, 'wine-bottles': 2 })
})
tests.push(async ({ path, eq, ctx }) => {
// test when vips answer { drink: 'wine' }
// should create a list with wine-bottles and potatoes
const answers = ctx.createAnswers(8, { answer: 'yes', drink: 'wine' })
await ctx.setAnswersIn({ folder: 'guests', answers })
const { data } = await ctx.run('guests', 'happy-wine-bottle-list.json')
return eq(data, { potatoes: 8, 'wine-bottles': 2 })
})
tests.push(async ({ path, eq, ctx }) => {
// test when vips answer { drink: 'water' }
// should create a list with water-bottles and potatoes
const answers = [
...ctx.createAnswers(2, { answer: 'no', drink: 'water' }),
...ctx.createAnswers(2, { answer: 'yes', drink: 'water' }),
]
await ctx.setAnswersIn({ folder: 'guests', answers })
const { data } = await ctx.run('guests', 'happy-water-list.json')
return eq(data, { potatoes: 2, 'water-bottles': 1 })
})
tests.push(async ({ path, eq, ctx }) => {
// test when vips answer { drink: 'water' }
// should create a list with water-bottles and potatoes
const answers = ctx.createAnswers(7, { answer: 'yes', drink: 'water' })
await ctx.setAnswersIn({ folder: 'guests', answers })
const { data } = await ctx.run('guests', 'happy-water-bottle-list.json')
return eq(data, { potatoes: 7, 'water-bottles': 2 })
})
tests.push(async ({ path, eq, ctx }) => {
// test when vips answer { drink: 'soft' }
// should create a list with soft-bottles and potatoes
const answers = [
...ctx.createAnswers(8, { answer: 'no', drink: 'soft' }),
...ctx.createAnswers(12, { answer: 'yes', drink: 'soft' }),
]
await ctx.setAnswersIn({ folder: 'guests', answers })
const { data } = await ctx.run('guests', 'happy-soft-list.json')
return eq(data, { potatoes: 12, 'soft-bottles': 3 })
})
tests.push(async ({ path, eq, ctx }) => {
// test when vips answer { drink: 'soft' }
// should create a list with soft-bottles and potatoes
const answers = ctx.createAnswers(13, { answer: 'yes', drink: 'soft' })
await ctx.setAnswersIn({ folder: 'guests', answers })
const { data } = await ctx.run('guests', 'happy-soft-bottle-list.json')
return eq(data, { potatoes: 13, 'soft-bottles': 4 })
})
// tests with veggstuff
// 1) vegan but no veggie
tests.push(async ({ path, eq, ctx }) => {
// test when vips answer { food: 'vegan' }
// should create a list with eggplants, mushrooms, courgettes and potatoes
const answers = [
...ctx.createAnswers(2, { answer: 'no', food: 'vegan' }),
...ctx.createAnswers(4, { answer: 'yes', food: 'vegan' }),
]
await ctx.setAnswersIn({ folder: 'guests', answers })
const { data } = await ctx.run('guests', 'happy-vegan-list.json')
return eq(data, {
potatoes: 4,
mushrooms: 4,
eggplants: 2,
courgettes: 2,
hummus: 2,
})
})
tests.push(async ({ path, eq, ctx }) => {
// test when vips answer { food: 'vegan' }
// should create a list with eggplants, mushrooms, hummus, courgettes and potatoes
const answers = ctx.createAnswers(6, { answer: 'yes', food: 'vegan' })
await ctx.setAnswersIn({ folder: 'guests', answers })
const { data } = await ctx.run('guests', 'happy-vegan-list.json')
return eq(data, {
potatoes: 6,
mushrooms: 6,
eggplants: 2,
courgettes: 2,
hummus: 2,
})
})
// 2) veggie but no vegan
tests.push(async ({ path, eq, ctx }) => {
// test when vips answer { food: 'veggie' }
// should create a list with eggplants, mushrooms, courgettes and potatoes
const answers = [
...ctx.createAnswers(2, { answer: 'no', food: 'veggie' }),
...ctx.createAnswers(4, { answer: 'yes', food: 'veggie' }),
]
await ctx.setAnswersIn({ folder: 'guests', answers })
const { data } = await ctx.run('guests', 'happy-veggie-list.json')
return eq(data, {
potatoes: 4,
mushrooms: 4,
eggplants: 2,
courgettes: 2,
hummus: 2,
})
})
tests.push(async ({ path, eq, ctx }) => {
// test when vips answer { food: 'veggie' }
// should create a list with eggplants, mushrooms, hummus, courgettes and potatoes
const answers = ctx.createAnswers(6, { answer: 'yes', food: 'veggie' })
await ctx.setAnswersIn({ folder: 'guests', answers })
const { data } = await ctx.run('guests', 'happy-veggie-list.json')
return eq(data, {
potatoes: 6,
mushrooms: 6,
eggplants: 2,
courgettes: 2,
hummus: 2,
})
})
// 3) both
tests.push(async ({ path, eq, ctx }) => {
// test when vips answer { food: 'vegan' } and { food: 'veggie' }
// should create a list with eggplants, mushrooms, courgettes and potatoes
const answers = [
...ctx.createAnswers(4, { answer: 'yes', food: 'vegan' }),
...ctx.createAnswers(2, { answer: 'yes', food: 'veggie' }),
]
await ctx.setAnswersIn({ folder: 'guests', answers })
const { data } = await ctx.run('guests', 'happy-vegg-list.json')
return eq(data, {
potatoes: 6,
mushrooms: 6,
eggplants: 2,
courgettes: 2,
hummus: 2,
})
})
tests.push(async ({ path, eq, ctx }) => {
// test when vips answer { food: 'vegan' } and { food: 'veggie' }
// should create a list with eggplants, mushrooms, hummus, courgettes and potatoes
const answers = [
...ctx.createAnswers(6, { answer: 'yes', food: 'vegan' }),
...ctx.createAnswers(1, { answer: 'yes', food: 'veggie' }),
]
await ctx.setAnswersIn({ folder: 'guests', answers })
const { data } = await ctx.run('guests', 'happy-vegg-list.json')
return eq(data, {
potatoes: 7,
mushrooms: 7,
eggplants: 3,
courgettes: 3,
hummus: 3,
})
})
// test with existing file
tests.push(async ({ path, eq, ctx }) => {
// test with an existing file
// should add elems to the existing list
await writeFile(
`${ctx.tmpPath}/old-happy-list.json`,
JSON.stringify({ candies: 2000 }),
)
const answers = ctx.createAnswers(1, { answer: 'yes', food: 'vegan' })
await ctx.setAnswersIn({ folder: 'guests', answers })
const { data } = await ctx.run('guests', 'old-happy-list.json')
return eq(data, {
candies: 2000,
potatoes: 1,
mushrooms: 1,
eggplants: 1,
courgettes: 1,
hummus: 1,
})
})
tests.push(async ({ path, eq, ctx }) => {
// test with an existing file
// should replace elems in the existing list (if already there)
await writeFile(
`${ctx.tmpPath}/old-happy-list.json`,
JSON.stringify({ candies: 2000, potatoes: 32 }),
)
const answers = ctx.createAnswers(1, { answer: 'yes', food: 'vegan' })
await ctx.setAnswersIn({ folder: 'guests', answers })
const { data } = await ctx.run('guests', 'old-happy-list.json')
return eq(data, {
candies: 2000,
potatoes: 1,
mushrooms: 1,
eggplants: 1,
courgettes: 1,
hummus: 1,
})
})
// test with a little bit of everything
tests.push(async ({ path, eq, ctx }) => {
// test with mix of everything
await writeFile(
`${ctx.tmpPath}/party.json`,
JSON.stringify({ 'super-gift': 1, balloons: 100, 'flower-bouquet': 7 }),
)
const answers = [
...ctx.createAnswers(7, { answer: 'no', food: 'vegan', drink: 'water' }),
...ctx.createAnswers(2, {
answer: 'yes',
food: 'carnivore',
drink: 'soft',
}),
...ctx.createAnswers(6, { answer: 'yes', food: 'vegan', drink: 'water' }),
...ctx.createAnswers(2, { answer: 'yes', food: 'veggie', drink: 'water' }),
...ctx.createAnswers(3, { answer: 'yes', food: 'veggie', drink: 'beer' }),
...ctx.createAnswers(11, { answer: 'yes', food: 'fish', drink: 'wine' }),
...ctx.createAnswers(4, {
answer: 'yes',
food: 'everything',
drink: 'beer',
}),
]
await ctx.setAnswersIn({ folder: 'guests', answers })
const { data } = await ctx.run('guests', 'party.json')
return eq(data, {
'super-gift': 1,
balloons: 100,
'flower-bouquet': 7,
potatoes: 28,
mushrooms: 11,
eggplants: 4,
courgettes: 4,
hummus: 4,
sardines: 11,
burgers: 2,
kebabs: 4,
'6-packs-beers': 2,
'wine-bottles': 3,
'water-bottles': 2,
'soft-bottles': 1,
})
})
Object.freeze(tests)

52
subjects/happiness-manager/README.md

@ -0,0 +1,52 @@
## happiness-manager
### Instructions
<3 Your pleasure? 💖 That of others Ɛ>
As you're smart, you asked every guest of the party to precise in their answer the kind of drink they would enjoy and the kind of food they would die for.
Create a `happiness-manager.mjs` script that sort, in the vips, who wants to drink what and who wants to eat what and integrate that in your barbecue's shopping list!
The script must:
- Take a folder as first argument (the `guest` folder)
- Take a file `.json` as second argument:
- If the file already exists, it will add the informations to it.
- If it doesn't, the script must handle the creation of the file.
- Handle case when no one answered yes to the invitation:
- `No one is coming.` has to appear in console.
- No file is updated/created.
- Handle cases when answers contains no "food" information, or no "drink" information
- Handle cases when no one has chosen a cotagory (for example: no one chose to drink softs). This category should not appear in the final list.
You have to handle the info like this:
- Drinks:
- Beers: 1 pack / 6 vips (rounded up). Expected key: `6-packs-beers`.
- Water, wine, softs: 1 bottle / 4 vips in each category (rounded up). Expected keys: `wine-bottles`, `water-bottles`, `soft-bottles`.
- Food:
- Veggies and vegans: 1 eggplant, 1 courgette, 3 mushrooms and 1 hummus / 3 vips in these categories put together. Expected keys: `eggplants`, `mushrooms`, `hummus`, `courgettes`.
- Carnivores: 1 burger per person. Expected key: `burgers`.
- Fish lovers: 1 sardine per person. Expected key: `sardines`.
- Omnivores: 1 chicken+shrimps+pepper kebab / person. Expected key: `kebabs`.
- Bonus: you'll add 1 potatoe per person (all categories put together). Expected key: `potatoes`.
The infos have to be formated like this in the `.json` file:
```json
{
"key": 1 // according to actual number associated to the elem
}
```
### Notions
- [`for...of`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...of)
- [`Array.prototype.map()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Map)
- [`Math.ceil()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/ceil)
- [Node file system: `stats`](https://nodejs.org/api/fs.html#fs_fspromises_stat_path_options)
- [Node file system: `readdir`](https://nodejs.org/api/fs.html#fs_fspromises_readdir_path_options)
- [Node file system: `readFile`](https://nodejs.org/api/fs.html#fs_fspromises_readfile_path_options)
- [Node file system: `writeFile`](https://nodejs.org/api/fs.html#fs_fspromises_writefile_file_data_options)
- [`JSON.parse()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse)
- [`JSON.stringify()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify)
- [Node process: `exit`](https://nodejs.org/api/process.html#process_process_exit_code)
Loading…
Cancel
Save