Browse Source

adding more javascript subjects (+fixes)

pull/540/head
Clement Denis 4 years ago
parent
commit
52adf5c8fd
  1. 56
      js/tests/date-is_test.js
  2. 485
      js/tests/filter_test.js
  3. 33
      js/tests/for-each_test.js
  4. 70
      js/tests/get-json_test.js
  5. 14
      js/tests/get-some-time_test.js
  6. 60
      js/tests/gougle-search_test.js
  7. 85
      js/tests/interpolation_test.js
  8. 120
      js/tests/is-winner_test.js
  9. 34
      js/tests/keep-trying-or-giveup_test.js
  10. 142
      js/tests/mapper_test.js
  11. 23
      js/tests/match-cron_test.js
  12. 4
      js/tests/nested_test.js
  13. 71
      js/tests/race_test.js
  14. 33
      js/tests/rebecca-black_test.js
  15. 293
      js/tests/using-filter_test.js
  16. 197
      js/tests/using-map_test.js
  17. 4
      subjects/abs.en.md
  18. 2
      subjects/capitalizer.en.md
  19. 4
      subjects/chunky.en.md
  20. 4
      subjects/curry-entries.en.md
  21. 2
      subjects/cut-corners.en.md
  22. 19
      subjects/date-is.en.md
  23. 2
      subjects/day-of-the-year.en.md
  24. 5
      subjects/debounce.en.md
  25. 2
      subjects/deep-copy.en.md
  26. 25
      subjects/filter.en.md
  27. 4
      subjects/find-expression.en.md
  28. 4
      subjects/flagger.en.md
  29. 17
      subjects/for-each.en.md
  30. 2
      subjects/fusion.en.md
  31. 28
      subjects/get-json.en.md
  32. 7
      subjects/get-some-time.en.md
  33. 42
      subjects/gougle-search.en.md
  34. 4
      subjects/greedy-url.en.md
  35. 2
      subjects/has-city.en.md
  36. 45
      subjects/interpolation.en.md
  37. 2
      subjects/ion-out.en.md
  38. 83
      subjects/is-winner.en.md
  39. 4
      subjects/its-a-match.en.md
  40. 30
      subjects/keep-trying-or-giveup.en.md
  41. 2
      subjects/letter-space-number.en.md
  42. 2
      subjects/manipulate-entries.en.md
  43. 2
      subjects/manipulate-keys.en.md
  44. 2
      subjects/manipulate-values.en.md
  45. 23
      subjects/mapper.en.md
  46. 32
      subjects/match-cron.en.md
  47. 4
      subjects/molecules-cells.en.md
  48. 2
      subjects/more-or-less.en.md
  49. 4
      subjects/mutability.en.md
  50. 2
      subjects/nasa.en.md
  51. 2
      subjects/neuron.en.md
  52. 2
      subjects/pick-omit.en.md
  53. 2
      subjects/primitives.en.md
  54. 4
      subjects/pronoun.en.md
  55. 2
      subjects/pyramid.en.md
  56. 21
      subjects/race.en.md
  57. 16
      subjects/rebecca-black.en.md
  58. 2
      subjects/replica.en.md
  59. 2
      subjects/reverser.en.md
  60. 4
      subjects/same-amount.en.md
  61. 2
      subjects/series.en.md
  62. 2
      subjects/sweet-curry.en.md
  63. 2
      subjects/throttle.en.md
  64. 2
      subjects/triangle.en.md
  65. 6
      subjects/unbreakable.en.md
  66. 46
      subjects/using-filter.en.md
  67. 102
      subjects/using-map.en.md
  68. 2
      subjects/using-reduce.en.md
  69. 4
      subjects/valid-ip.en.md
  70. 2
      subjects/vowel-dots.en.md
  71. 2
      subjects/何.en.md

56
js/tests/date-is_test.js

@ -0,0 +1,56 @@
export const tests = []
const t = (f) => tests.push(f)
// is the date a valid date?
const invalid = (callback, ary = 1) => {
for (const s of [
`new Date('')`,
`new Date(NaN)`,
`''`,
`'2013-01-01'`,
`NaN`,
]) {
if (callback(...Array(ary).fill(eval(s)))) {
throw Error(`${callback.name}(${s}) should be false`)
}
}
}
// isValid
t(() => !invalid(isValid))
t(() => isValid(new Date()))
t(() => isValid(Date.now()))
t(() => isValid(new Date('December 17, 1995 03:24:00')))
t(() => isValid(new Date(1488370835081)))
t(() => isValid(new Date('1995-12-17T03:24:00')))
t(() => isValid(new Date('1995-12-17T03:24:00').getTime()))
// isAfter
t(() => !invalid(isAfter, 2))
t(() => !isAfter(new Date('1992-01-01'), new Date('1992-01-02')))
t(() => !isAfter(new Date('1992-01-01'), new Date('1992-01-02')))
t(() => isAfter(new Date(2321, 11, 21), new Date(Date.now())))
t(() => isAfter(123123, 526))
// isBefore
t(() => !invalid(isBefore, 2))
t(() => !isBefore(new Date(2321, 11, 21), new Date(Date.now())))
t(() => !isBefore(123123, 526))
t(() => isBefore(new Date('1992-01-01'), new Date('1992-01-02')))
t(() => isBefore(new Date('1992-01-01'), new Date('1992-01-02')))
// isFuture
t(() => !invalid(isFuture))
t(() => !isFuture(new Date('1992-01-01')))
t(() => !isFuture(new Date(Date.now() - 1)))
t(() => isFuture(new Date(2021, 11, 31)))
t(() => isFuture(new Date(Date.now() + 1)))
// isPast
t(() => !invalid(isPast))
t(() => !isPast(new Date(Date.now() + 1)))
t(() => !isPast(new Date(2021, 11, 31)))
t(() => isPast(new Date(1442, 11, 31)))
t(() => isPast(new Date(Date.now() - 1)))
Object.freeze(tests)

485
js/tests/filter_test.js

@ -0,0 +1,485 @@
Array.prototype.filter = undefined
// /*/ // ⚡
export const tests = []
const t = (f) => tests.push(f)
const check1 = (el) => el % 2 === 0
const check2 = (el, i) => el % 3 === 0 && i % 2 === 0
const check3 = (el) => Array.isArray(el)
const check4 = (el, i, arr) =>
typeof el !== 'number' && i % 2 !== 0 && arr.includes(true)
const check5 = (el, i) =>
(typeof el === 'number' || typeof el === 'boolean') && i > 5
const check6 = (el) => el.region === 'South' || el.region === 'West'
// Filter
t(({ eq, ctx }) =>
eq(filter(ctx.onlyNumbers, check1), [
10,
-10,
20,
86,
2,
32,
450,
950,
66,
150,
]),
)
t(({ eq, ctx }) => eq(filter(ctx.onlyNumbers, check2), [15, 33, 450, 66]))
t(({ eq, ctx }) =>
eq(filter(ctx.mixedTypes, check3), [
['how', 'are', 'the', 2],
['iu', 2],
]),
)
t(({ eq, ctx }) =>
eq(filter(ctx.mixedTypes, check4), [
['how', 'are', 'the', 2],
['iu', 2],
'good',
true,
]),
)
t(({ eq, ctx }) =>
eq(filter(ctx.mixedTypes, check5), [-10, 2, 65, 2, 2678, true]),
)
// Reject
t(({ eq, ctx }) => eq(reject(ctx.onlyNumbers, check1), [-95, 15, 3, 5, 33, 45]))
t(({ eq, ctx }) =>
eq(reject(ctx.onlyNumbers, check2), [
10,
-10,
20,
-95,
86,
2,
3,
5,
32,
45,
950,
150,
]),
)
t(({ eq, ctx }) =>
eq(reject(ctx.mixedTypes, check3), [
1,
2,
4,
8,
'hello',
12,
-10,
'of',
'well',
2,
65,
'good',
2,
2678,
'be',
true,
]),
)
t(({ eq, ctx }) =>
eq(reject(ctx.mixedTypes, check4), [
1,
2,
4,
8,
'hello',
12,
-10,
'of',
'well',
2,
65,
2,
2678,
'be',
]),
)
t(({ eq, ctx }) =>
eq(reject(ctx.mixedTypes, check5), [
1,
2,
4,
8,
'hello',
12,
['how', 'are', 'the', 2],
'of',
['iu', 2],
'well',
'good',
'be',
]),
)
// Partition
t(({ eq, ctx }) =>
eq(partition(ctx.onlyNumbers, check1), [
[10, -10, 20, 86, 2, 32, 450, 950, 66, 150],
[-95, 15, 3, 5, 33, 45],
]),
)
t(({ eq, ctx }) =>
eq(partition(ctx.onlyNumbers, check2), [
[15, 33, 450, 66],
[10, -10, 20, -95, 86, 2, 3, 5, 32, 45, 950, 150],
]),
)
t(({ eq, ctx }) =>
eq(partition(ctx.mixedTypes, check3), [
[
['how', 'are', 'the', 2],
['iu', 2],
],
[
1,
2,
4,
8,
'hello',
12,
-10,
'of',
'well',
2,
65,
'good',
2,
2678,
'be',
true,
],
]),
)
t(({ eq, ctx }) =>
eq(partition(ctx.mixedTypes, check4), [
[['how', 'are', 'the', 2], ['iu', 2], 'good', true],
[1, 2, 4, 8, 'hello', 12, -10, 'of', 'well', 2, 65, 2, 2678, 'be'],
]),
)
t(({ eq, ctx }) =>
eq(partition(ctx.mixedTypes, check5), [
[-10, 2, 65, 2, 2678, true],
[
1,
2,
4,
8,
'hello',
12,
['how', 'are', 'the', 2],
'of',
['iu', 2],
'well',
'good',
'be',
],
]),
)
/// Filter on an object
t(({ eq, ctx }) =>
eq(filter(ctx.statesData, check6), [
{
tag: 'AL',
name: 'Alabama',
capital: 'Montgomery',
region: 'South',
},
{ tag: 'AK', name: 'Alaska', capital: 'Juneau', region: 'West' },
{ tag: 'AZ', name: 'Arizona', capital: 'Phoenix', region: 'West' },
{
tag: 'AR',
name: 'Arkansas',
capital: 'Little Rock',
region: 'South',
},
{
tag: 'CA',
name: 'California',
capital: 'Sacramento',
region: 'West',
},
{ tag: 'CO', name: 'Colorado', capital: 'Denver', region: 'West' },
{ tag: 'DE', name: 'Delaware', capital: 'Dover', region: 'South' },
{
tag: 'DC',
name: 'District Of Columbia',
capital: 'Washington',
region: 'South',
},
{
tag: 'FL',
name: 'Florida',
capital: 'Tallahassee',
region: 'South',
},
{ tag: 'GA', name: 'Georgia', capital: 'Atlanta', region: 'South' },
{ tag: 'HI', name: 'Hawaii', capital: 'Honolulu', region: 'West' },
{ tag: 'ID', name: 'Idaho', capital: 'Boise', region: 'West' },
{
tag: 'KY',
name: 'Kentucky',
capital: 'Frankfort',
region: 'South',
},
{
tag: 'LA',
name: 'Louisiana',
capital: 'Baton Rouge',
region: 'South',
},
{
tag: 'MD',
name: 'Maryland',
capital: 'Annapolis',
region: 'South',
},
{
tag: 'MS',
name: 'Mississippi',
capital: 'Jackson',
region: 'South',
},
{ tag: 'MT', name: 'Montana', capital: 'Helena', region: 'West' },
{ tag: 'NV', name: 'Nevada', capital: 'Carson City', region: 'West' },
{
tag: 'NM',
name: 'New Mexico',
capital: 'Santa Fe',
region: 'West',
},
{
tag: 'NC',
name: 'North Carolina',
capital: 'Raleigh',
region: 'South',
},
{
tag: 'OK',
name: 'Oklahoma',
capital: 'Oklahoma City',
region: 'South',
},
{ tag: 'OR', name: 'Oregon', capital: 'Salem', region: 'West' },
{
tag: 'SC',
name: 'South Carolina',
capital: 'Columbia',
region: 'South',
},
{
tag: 'TN',
name: 'Tennessee',
capital: 'Nashville',
region: 'South',
},
{ tag: 'TX', name: 'Texas', capital: 'Austin', region: 'South' },
{
tag: 'UT',
name: 'Utah',
capital: 'Salt Lake City',
region: 'West',
},
{ tag: 'VA', name: 'Virginia', capital: 'Richmond', region: 'South' },
{ tag: 'WA', name: 'Washington', capital: 'Olympia', region: 'West' },
{
tag: 'WV',
name: 'West Virginia',
capital: 'Charleston',
region: 'South',
},
{ tag: 'WY', name: 'Wyoming', capital: 'Cheyenne', region: 'West' },
]),
)
export const setup = () => {
const onlyNumbers = Object.freeze([
10,
-10,
20,
-95,
15,
86,
2,
3,
5,
32,
33,
45,
450,
950,
66,
150,
])
const mixedTypes = Object.freeze([
1,
2,
4,
8,
'hello',
12,
-10,
['how', 'are', 'the', 2],
'of',
['iu', 2],
'well',
2,
65,
'good',
2,
2678,
'be',
true,
])
const statesData = Object.freeze(
[
{ tag: 'AL', name: 'Alabama', capital: 'Montgomery', region: 'South' },
{ tag: 'AK', name: 'Alaska', capital: 'Juneau', region: 'West' },
{ tag: 'AZ', name: 'Arizona', capital: 'Phoenix', region: 'West' },
{ tag: 'AR', name: 'Arkansas', capital: 'Little Rock', region: 'South' },
{ tag: 'CA', name: 'California', capital: 'Sacramento', region: 'West' },
{ tag: 'CO', name: 'Colorado', capital: 'Denver', region: 'West' },
{
tag: 'CT',
name: 'Connecticut',
capital: 'Hartford',
region: 'Northeast',
},
{ tag: 'DE', name: 'Delaware', capital: 'Dover', region: 'South' },
{
tag: 'DC',
name: 'District Of Columbia',
capital: 'Washington',
region: 'South',
},
{ tag: 'FL', name: 'Florida', capital: 'Tallahassee', region: 'South' },
{ tag: 'GA', name: 'Georgia', capital: 'Atlanta', region: 'South' },
{ tag: 'HI', name: 'Hawaii', capital: 'Honolulu', region: 'West' },
{ tag: 'ID', name: 'Idaho', capital: 'Boise', region: 'West' },
{
tag: 'IL',
name: 'Illinois',
capital: 'Springfield',
region: 'Midwest',
},
{
tag: 'IN',
name: 'Indiana',
capital: 'Indianapolis',
region: 'Midwest',
},
{ tag: 'IA', name: 'Iowa', capital: 'Des Moines', region: 'Midwest' },
{ tag: 'KS', name: 'Kansas', capital: 'Topeka', region: 'Midwest' },
{ tag: 'KY', name: 'Kentucky', capital: 'Frankfort', region: 'South' },
{ tag: 'LA', name: 'Louisiana', capital: 'Baton Rouge', region: 'South' },
{ tag: 'ME', name: 'Maine', capital: 'Augusta', region: 'Northeast' },
{ tag: 'MD', name: 'Maryland', capital: 'Annapolis', region: 'South' },
{
tag: 'MA',
name: 'Massachusetts',
capital: 'Boston',
region: 'Northeast',
},
{ tag: 'MI', name: 'Michigan', capital: 'Lansing', region: 'Midwest' },
{ tag: 'MN', name: 'Minnesota', capital: 'St. Paul', region: 'Midwest' },
{ tag: 'MS', name: 'Mississippi', capital: 'Jackson', region: 'South' },
{
tag: 'MO',
name: 'Missouri',
capital: 'Jefferson City',
region: 'Midwest',
},
{ tag: 'MT', name: 'Montana', capital: 'Helena', region: 'West' },
{ tag: 'NE', name: 'Nebraska', capital: 'Lincoln', region: 'Midwest' },
{ tag: 'NV', name: 'Nevada', capital: 'Carson City', region: 'West' },
{
tag: 'NH',
name: 'New Hampshire',
capital: 'Concord',
region: 'Northeast',
},
{
tag: 'NJ',
name: 'New Jersey',
capital: 'Trenton',
region: 'Northeast',
},
{ tag: 'NM', name: 'New Mexico', capital: 'Santa Fe', region: 'West' },
{ tag: 'NY', name: 'New York', capital: 'Albany', region: 'Northeast' },
{
tag: 'NC',
name: 'North Carolina',
capital: 'Raleigh',
region: 'South',
},
{
tag: 'ND',
name: 'North Dakota',
capital: 'Bismarck',
region: 'Midwest',
},
{ tag: 'OH', name: 'Ohio', capital: 'Colombus', region: 'Midwest' },
{
tag: 'OK',
name: 'Oklahoma',
capital: 'Oklahoma City',
region: 'South',
},
{ tag: 'OR', name: 'Oregon', capital: 'Salem', region: 'West' },
{
tag: 'PA',
name: 'Pennsylvania',
capital: 'Harrisburg',
region: 'Northeast',
},
{
tag: 'RI',
name: 'Rhode Island',
capital: 'Providence',
region: 'Northeast',
},
{
tag: 'SC',
name: 'South Carolina',
capital: 'Columbia',
region: 'South',
},
{ tag: 'SD', name: 'South Dakota', capital: 'Pierre', region: 'Midwest' },
{ tag: 'TN', name: 'Tennessee', capital: 'Nashville', region: 'South' },
{ tag: 'TX', name: 'Texas', capital: 'Austin', region: 'South' },
{ tag: 'UT', name: 'Utah', capital: 'Salt Lake City', region: 'West' },
{
tag: 'VT',
name: 'Vermont',
capital: 'Montpelier',
region: 'Northeast',
},
{ tag: 'VA', name: 'Virginia', capital: 'Richmond', region: 'South' },
{ tag: 'WA', name: 'Washington', capital: 'Olympia', region: 'West' },
{
tag: 'WV',
name: 'West Virginia',
capital: 'Charleston',
region: 'South',
},
{ tag: 'WI', name: 'Wisconsin', capital: 'Madison', region: 'Midwest' },
{ tag: 'WY', name: 'Wyoming', capital: 'Cheyenne', region: 'West' },
].map((e) => Object.freeze(e)),
)
Object.getPrototypeOf([]).proto = ' [avoid for..in] '
return { onlyNumbers, mixedTypes, statesData }
}
Object.freeze(tests)

33
js/tests/for-each_test.js

@ -0,0 +1,33 @@
Array.prototype.forEach = undefined
// /*/ // ⚡
export const tests = []
const t = (f) => tests.push(f)
export const setup = () => {
const arr = [1, 2, 3, 4, 5, Math.random(), 7, 10, -10, 20, -95]
Object.getPrototypeOf([]).proto = ' [avoid for..in] '
return { arr }
}
// callback is call with the item value
t(({ eq, ctx }) => {
const result = []
forEach(ctx.arr, (value) => result.push(value))
return eq(result, ctx.arr)
})
// callback second parameter is the index
t(({ eq, ctx }) => {
const result = []
forEach(ctx.arr, (_, index) => result.push(index))
return eq(result, [...ctx.arr.keys()])
})
// callback third parameter is the array
t(({ eq, ctx }) => {
const result = []
forEach(ctx.arr, (_, __, arr) => result.push(arr))
return eq(result, Array(ctx.arr.length).fill(ctx.arr))
})
Object.freeze(tests)

70
js/tests/get-json_test.js

@ -0,0 +1,70 @@
export const tests = []
const t = (f) => tests.push(f)
const fakeFetch = async ({ data, error, ...opts } = {}) => ({
ok: !opts.status,
type: 'basic',
status: 200,
statusText: 'OK',
json: async () => ({ data, error }),
text: async () => JSON.stringify({ data, error }),
...opts,
})
// check url parsing
t(async ({ eq }) => {
let url
fetch = async (arg) => fakeFetch({ url: (url = arg) })
const pending = getJSON('/test', { query: 'hello world', b: 5 })
return eq(url, '/test?query=hello%20world&b=5')
})
// check that it return the given value
t(async ({ eq }) => {
const data = Math.random()
fetch = (url) => fakeFetch({ url, data })
return eq(await getJSON('/', { q: 1 }), data)
})
// check that it throw an error with the correct message
t(async ({ eq }) => {
const error = `oops: ${Math.random()}`
fetch = (url) => fakeFetch({ url, error })
return eq(
await getJSON('/', { q: 1 }).then(
() => Promise.reject(Error('Should fail')),
(err) => err.message,
),
error,
)
})
// check that it throw if the request is not ok
t(async ({ eq }) => {
fetch = (url) =>
fakeFetch({ url, status: 500, statusText: 'Internal Server Error' })
return eq(
await getJSON('/', { q: 1 }).then(
() => Promise.reject(Error('Should fail')),
(err) => err.message,
),
'Internal Server Error',
)
})
// if fetch fail, the error should not be handled
t(async ({ eq }) => {
const error = `oops: ${Math.random()}`
fetch = (url) => Promise.reject(Error(error))
return eq(
await getJSON('/', { q: 1 }).then(
() => Promise.reject(Error('Should fail')),
(err) => err.message,
),
error,
)
})
export const setup = () => globalThis.fetch

14
js/tests/get-some-time_test.js

@ -0,0 +1,14 @@
export const tests = []
const t = (f) => tests.push(f)
t(({ eq }) => eq(firstDayWeek(1, '1000'), '01-01-1000'))
t(({ eq }) => eq(firstDayWeek(52, '1000'), '22-12-1000'))
t(({ eq }) => eq(firstDayWeek(2, '0001'), '08-01-0001'))
t(({ eq }) => eq(firstDayWeek(43, '1983'), '17-10-1983'))
t(({ eq }) => eq(firstDayWeek(23, '0091'), '04-06-0091'))
Object.freeze(tests)

60
js/tests/gougle-search_test.js

@ -0,0 +1,60 @@
// fake `getJSON` function
let getJSON = async (url) => url
// /*/ // ⚡
export const tests = []
const t = (f) => tests.push(f)
// queryServers with main server be fastest
t(async ({ eq, ctx }) => {
ctx.setTimings({ pouet_backup: 2 })
return eq(await queryServers('pouet', ctx.r), `/pouet?q=${ctx.r}`)
})
// queryServers with backup server be fastest
t(async ({ eq, ctx }) => {
ctx.setTimings({ pouet: 2 })
return eq(await queryServers('pouet', ctx.r), `/pouet_backup?q=${ctx.r}`)
})
// gougleSearch fast enough
t(async ({ eq, ctx }) => {
ctx.setTimings({ web_backup: 3, image: 2, video_backup: 4 })
return eq(await gougleSearch(ctx.r), {
web: `/web?q=${ctx.r}`,
image: `/image_backup?q=${ctx.r}`,
video: `/video?q=${ctx.r}`,
})
})
// gougleSearch fast enough, alternate timings
t(async ({ eq, ctx }) => {
ctx.setTimings({ web: 3, image_backup: 1, video: 4 })
return eq(await gougleSearch(ctx.r), {
web: `/web_backup?q=${ctx.r}`,
image: `/image?q=${ctx.r}`,
video: `/video_backup?q=${ctx.r}`,
})
})
// gougleSearch too slow !
t(async ({ eq, ctx }) => {
ctx.setTimings({ web: 85, web_backup: 99 })
return eq(
await gougleSearch(ctx.r).then(
() => Promise.reject(Error('Should fail')),
(err) => err.message,
),
'timeout',
)
})
Object.freeze(tests)
export const setup = () => ({
r: Math.random().toString(36).slice(2),
setTimings: (timings) =>
(getJSON = (url) =>
new Promise((s) =>
setTimeout(s, timings[url.split(/\/([^?]+)?/)[1]] || 0, url),
)),
})

85
js/tests/interpolation_test.js

@ -0,0 +1,85 @@
export const tests = []
const t = (f) => tests.push(f)
const run = async ({ step, start, end, duration, waitTime = 15 }) => {
let arr = []
const round = (nbr) => Math.round(nbr * 100) / 100
const callback = (el) =>
arr.push(Array.isArray(el) ? el.map(round) : round(el))
interpolation({ step, start, end, callback, duration })
await new Promise((s) => setTimeout(s, waitTime))
return arr
}
// testing duration time, forbid loops
t(async ({ eq }) => {
const { length } = await run({ step: 5, start: 0, end: 4, duration: 28 })
return eq(length, 2)
})
// testing duration time stamp
t(async ({ eq }) => {
const { length } = await run({
step: 5,
start: 0,
end: 4,
duration: 10,
waitTime: 0,
})
return eq(length, 0)
})
// testing the amount of times the callback was called
t(async ({ eq }) => {
const { length } = await run({ step: 5, start: 0, end: 1, duration: 10 })
return eq(length, 5)
})
// testing the interpolation points
t(async ({ eq }) =>
eq(await run({ step: 5, start: 0, end: 1, duration: 10 }), [
[0, 2],
[0.2, 4],
[0.4, 6],
[0.6, 8],
[0.8, 10],
]),
)
// testing with different values
t(async ({ eq }) =>
eq(await run({ step: 3, start: 1, end: 2, duration: 10 }), [
[1, 3.33],
[1.33, 6.67],
[1.67, 10],
]),
)
// testing with `duration` inferior to `step`
t(async ({ eq }) =>
eq(await run({ step: 10, start: 2, end: 6, duration: 4 }), [
[2, 0.4],
[2.4, 0.8],
[2.8, 1.2],
[3.2, 1.6],
[3.6, 2],
[4, 2.4],
[4.4, 2.8],
[4.8, 3.2],
[5.2, 3.6],
[5.6, 4],
]),
)
// testing with `start` superior to `end`
// inverted straight line
t(async ({ eq }) =>
eq(await run({ step: 5, start: 6, end: 2, duration: 6, waitTime: 10 }), [
[6, 1.2],
[5.2, 2.4],
[4.4, 3.6],
[3.6, 4.8],
[2.8, 6],
]),
)
Object.freeze(tests)

120
js/tests/is-winner_test.js

@ -0,0 +1,120 @@
const db = (() => {
//countries that won the FIFA World Cup
const countries = [
{ id: 1, name: 'Brazil', continent: 'South America' },
{ id: 2, name: 'Germany', continent: 'Europe' },
{ id: 3, name: 'Italy', continent: 'Europe' },
{ id: 4, name: 'Argentina', continent: 'South America' },
{ id: 5, name: 'France', continent: 'Europe' },
{ id: 6, name: 'Uruguay', continent: 'South America' },
{ id: 7, name: 'England', continent: 'Europe' },
{ id: 8, name: 'Spain', continent: 'Europe' },
]
//Information about the wins
const results = [
{ id: 1, countryId: 6, year: 1930, score: '4-2' },
{ id: 2, countryId: 3, year: 1934, score: '2-1' },
{ id: 3, countryId: 3, year: 1938, score: '4-2' },
{ id: 4, countryId: 6, year: 1950, score: '2-1' },
{ id: 5, countryId: 2, year: 1954, score: '3-2' },
{ id: 6, countryId: 1, year: 1958, score: '5-2' },
{ id: 7, countryId: 1, year: 1962, score: '3-1' },
{ id: 8, countryId: 7, year: 1966, score: '4-2' },
{ id: 9, countryId: 1, year: 1970, score: '4-1' },
{ id: 10, countryId: 2, year: 1974, score: '2-1' },
{ id: 11, countryId: 4, year: 1978, score: '3-1' },
{ id: 12, countryId: 3, year: 1982, score: '3-1' },
{ id: 13, countryId: 4, year: 1986, score: '3-2' },
{ id: 14, countryId: 2, year: 1990, score: '1-0' },
{ id: 15, countryId: 1, year: 1994, score: '3-2p' },
{ id: 16, countryId: 5, year: 1998, score: '3-0' },
{ id: 17, countryId: 1, year: 2002, score: '2-0' },
{ id: 18, countryId: 3, year: 2006, score: '5-3p' },
{ id: 19, countryId: 8, year: 2010, score: '1-0' },
{ id: 20, countryId: 2, year: 2014, score: '1-0' },
{ id: 21, countryId: 5, year: 2018, score: '4-2' },
]
return {
//returns the information of the country
getWinner: async (countryName) => {
const match = countries.find((country) => country.name === countryName)
if (!match) throw Error('Country Not Found')
return match
},
//returns the information of the wins of that country
getResults: async (countryId) => {
const match = results.filter((result) => result.countryId === countryId)
if (!match.length) throw Error('Results Not Found')
return match
},
addCountry: (country) => countries.push(country),
addResults: (result) => results.push(result),
}
})()
// /*/ // ⚡
export const tests = []
const t = (f) => tests.push(f)
// testing correct continent but wrong number of times
t(async ({ eq }) =>
eq(
await isWinner('England'),
'England is not what we are looking for because of the number of times it was champion',
),
)
// testing non winner country
t(async ({ eq }) =>
eq(await isWinner('Colombia'), 'Colombia never was a winner'),
)
// testing wrong continent country
t(async ({ eq }) =>
eq(
await isWinner('Uruguay'),
'Uruguay is not what we are looking for because of the continent',
),
)
// testing no country
t(async ({ eq }) => eq(await isWinner(''), ' never was a winner'))
// testing correct number of times but wrong continent
t(async ({ eq }) =>
eq(
await isWinner('Brazil'),
'Brazil is not what we are looking for because of the continent',
),
)
// testing correct number of times and correct continent
t(async ({ eq }) =>
eq(
await isWinner('Germany'),
'Germany won the FIFA World Cup in 1954, 1974, 1990, 2014 winning by 3-2, 2-1, 1-0, 1-0',
),
)
// testing correct number of times and correct continent, for the fake country
t(async ({ eq, ctx }) =>
eq(
await isWinner(ctx.name),
`${ctx.name} won the FIFA World Cup in 2022, 2026, 2030 winning by 1-0, 3-1, 2-1`,
),
)
Object.freeze(tests)
export const setup = () => {
const seed = Math.random()
const name = seed.toString(36).slice(2)
db.addCountry({ id: 9, name, continent: 'Europe' })
db.addResults({ countryId: 9, year: 2022, score: '1-0' })
db.addResults({ countryId: 9, year: 2026, score: '3-1' })
db.addResults({ countryId: 9, year: 2030, score: '2-1' })
return { name }
}

34
js/tests/keep-trying-or-giveup_test.js

@ -0,0 +1,34 @@
export const tests = []
const t = (f) => tests.push(f)
const fail = (q) =>
q.then(
(v) => Promise.reject('should fail'),
(e) => e.message,
)
t(async ({ eq, ctx }) => eq(await retry(0, ctx.failNTimes(0))(ctx.r), [ctx.r]))
t(async ({ eq, ctx }) => eq(await retry(3, ctx.failNTimes(3))(ctx.r), [ctx.r]))
t(async ({ eq, ctx }) =>
eq(await retry(10, ctx.failNTimes(5))(ctx.r, ctx.r), [ctx.r, ctx.r]),
)
t(async ({ eq, ctx }) =>
eq(await fail(retry(3, ctx.failNTimes(9))(ctx.r)), `x:${ctx.r}`),
)
t(async ({ eq, ctx }) => eq(await timeout(2, ctx.delayed(0))(ctx.r), [ctx.r]))
t(async ({ eq, ctx }) =>
eq(await timeout(2, ctx.delayed(0))(ctx.r, ctx.r), [ctx.r, ctx.r]),
)
t(async ({ eq, ctx }) =>
eq(await fail(timeout(2, ctx.delayed(4))(ctx.r)), 'timeout'),
)
Object.freeze(tests)
export const setup = () => ({
r: Math.random().toString(36).slice(2),
failNTimes: (n) => async (...v) =>
--n < 0 ? v : Promise.reject(Error(`x:${v}`)),
delayed: (delay) => (...v) => new Promise((s) => setTimeout(s, delay, v)),
})

142
js/tests/mapper_test.js

@ -0,0 +1,142 @@
Array.prototype.map = undefined
Array.prototype.flatMap = undefined
Array.prototype.flat = undefined
// /*/ // ⚡
export const tests = []
const t = (f) => tests.push(f)
const add1 = (el) => el + 1
const sub3 = (el) => el - 3
const mult2 = (el) => el * 2
const doAll = (el) => sub3(mult2(add1(el)))
const posValsIndex = (el, i) => (el >= 0 ? `${i}: ${el}` : undefined)
const indexValsArray = (el, i, arr) =>
`${el} is at index: ${i} out of ${arr.length - 1}`
const arrayFormatSentence = (item, index, arr) => {
if (index === arr.length - 2) return `and ${arr[arr.length - 2]} `
if (index === arr.length - 1) {
return `are ${String(arr.length - 1)} ${item}.`
}
return `${item}, `
}
// map
t(({ eq, ctx }) =>
eq(map(ctx.numbers, add1), [11, -9, 21, -94, 87, 103, 36, 90, 111]),
)
t(({ eq, ctx }) =>
eq(map(ctx.numbers, mult2), [20, -20, 40, -190, 172, 204, 70, 178, 220]),
)
t(({ eq, ctx }) =>
eq(map(ctx.numbers, sub3), [7, -13, 17, -98, 83, 99, 32, 86, 107]),
)
t(({ eq, ctx }) =>
eq(map(ctx.numbers, doAll), [19, -21, 39, -191, 171, 203, 69, 177, 219]),
)
t(({ eq, ctx }) =>
eq(map(ctx.numbers, posValsIndex), [
'0: 10',
undefined,
'2: 20',
undefined,
'4: 86',
'5: 102',
'6: 35',
'7: 89',
'8: 110',
]),
)
t(({ eq, ctx }) =>
eq(map(ctx.numbers, indexValsArray), [
'10 is at index: 0 out of 8',
'-10 is at index: 1 out of 8',
'20 is at index: 2 out of 8',
'-95 is at index: 3 out of 8',
'86 is at index: 4 out of 8',
'102 is at index: 5 out of 8',
'35 is at index: 6 out of 8',
'89 is at index: 7 out of 8',
'110 is at index: 8 out of 8',
]),
)
t(({ eq, ctx }) =>
eq(
map(ctx.sentences[0], arrayFormatSentence).join(''),
'Colombia, Mexico, and El Salvador are 3 Spanish speaking countries.',
),
)
t(({ eq, ctx }) =>
eq(
map(ctx.sentences[1], arrayFormatSentence).join(''),
'Perou, Brazil, Argentina, and Venezuela are 4 countries in South America.',
),
)
t(({ eq, ctx }) =>
eq(
map(ctx.sentences[2], arrayFormatSentence).join(''),
'France, Portugal, and Italy are 3 members of the EU.',
),
)
// flatMap
t(({ eq, ctx }) =>
eq(flatMap(ctx.mixed, add1), ['101', -9, 21, -94, 87, '1021', '35,891', 111]),
)
t(({ eq, ctx }) =>
eq(flatMap(ctx.mixed, posValsIndex), [
'0: 10',
undefined,
'2: 20',
undefined,
'4: 86',
'5: 102',
undefined,
'7: 110',
]),
)
t(({ eq, ctx }) =>
eq(flatMap(ctx.nested, indexValsArray), [
'5 is at index: 0 out of 7',
'4 is at index: 1 out of 7',
'-3 is at index: 2 out of 7',
'20 is at index: 3 out of 7',
'17 is at index: 4 out of 7',
'-33 is at index: 5 out of 7',
'-4 is at index: 6 out of 7',
'18 is at index: 7 out of 7',
]),
)
Object.freeze(tests)
export const setup = () => {
const numbers = [10, -10, 20, -95, 86, 102, 35, 89, 110]
const mixed = [[10], -10, 20, -95, 86, [102], [35, 89], 110]
const nested = [[5], [4], [-3], [20], [17], [-33], [-4], [18]]
const sentences = [
['Colombia', 'Mexico', 'El Salvador', 'Spanish speaking countries'],
['Perou', 'Brazil', 'Argentina', 'Venezuela', 'countries in South America'],
['France', 'Portugal', 'Italy', 'members of the EU'],
]
Object.getPrototypeOf([]).proto = ' [avoid for..in] '
Object.freeze(numbers)
Object.freeze(mixed)
Object.freeze(nested)
Object.freeze(sentences[0])
Object.freeze(sentences[1])
Object.freeze(sentences[2])
return { numbers, mixed, nested, sentences }
}

23
js/tests/match-cron_test.js

@ -0,0 +1,23 @@
export const tests = []
const t = (f) => tests.push(f)
t(() => matchCron('* * * * 1', new Date('2020-06-01 00:00:00')))
t(() => matchCron('* * * 2 *', new Date('2021-02-01 00:00:00')))
t(() => matchCron('* * 9 * *', new Date('2020-06-09 00:00:00')))
t(() => matchCron('* 3 * * *', new Date('2020-05-31 03:00:00')))
t(() => matchCron('1 * * * *', new Date('2020-05-30 19:01:00')))
t(() => matchCron('3 3 * 3 3', new Date('2021-03-03 03:03:00')))
t(() => matchCron('* * * * *', new Date()))
t(({ ctx }) => matchCron('* 7 * * *', new Date(`201${ctx}-01-01 07:00:00`)))
t(() => !matchCron('* * * * 1', new Date('2020-06-02 00:00:00')))
t(() => !matchCron('* * * 2 *', new Date('2021-03-01 00:00:00')))
t(() => !matchCron('* * 8 * *', new Date('2020-06-09 00:00:00')))
t(() => !matchCron('* 2 * * *', new Date('2020-05-31 03:00:00')))
t(() => !matchCron('1 * * * *', new Date('2020-05-30 19:00:00')))
t(() => !matchCron('3 3 * 3 3', new Date('2021-03-02 03:03:00')))
t(({ ctx }) => !matchCron('* 7 * * *', new Date(`201${ctx}-01-01 06:00:00`)))
Object.freeze(tests)
export const setup = () => Math.ceil(Math.random() * 9)

4
js/tests/nested_test.js

@ -33,7 +33,7 @@ t(() => cantEdit(() => (nested.obj.update = 5)))
t(() => nested.obj.update === undefined)
// nested.arr is not frozen and can be changed
t(() => nested.arr.push('hot stuff'))
t(() => nested.arr.length === 4)
t(() => cantEdit(() => nested.arr.push('hot stuff')))
t(() => nested.arr.length === 3)
Object.freeze(tests)

71
js/tests/race_test.js

@ -0,0 +1,71 @@
Promise.race = undefined
// /*/ // ⚡
export const tests = []
const t = (f) => tests.push(f)
//// RACE
// empty array should never resolve, just hang, forever...
t(async ({ eq, wait }) => {
let notCalled = true
race([]).then(() => (notCalled = false))
await wait(5)
return eq(notCalled, true)
})
// it should return the first value to resolve
t(async ({ eq, wait }) =>
eq(await race([Promise.resolve(2), wait(5).then(() => 5)]), 2),
)
// it should not wait for every results to wait
t(async ({ eq, wait }) => {
const start = Date.now()
const result = await race([Promise.resolve(2), wait(50)])
if (Date.now() - start > 5) throw Error("that's too long !")
return eq(result, 2)
})
// it should fail if the first promise reject
t(async ({ eq, wait }) =>
eq(
await race([wait(5), Promise.reject(Error('oops'))]).catch(
(err) => err.message,
),
'oops',
),
)
// it should not fail if the first promise did not reject
t(async ({ eq, wait, ctx }) =>
eq(
await race([
wait(5).then(() => Promise.reject(Error('oops'))),
Promise.resolve(ctx),
]).catch((err) => err.message),
ctx,
),
)
//// SOME
// empty array returns an empty array
t(async ({ eq }) => eq(await some([], 10), []))
// a count of less than 1 also returns an empty array
t(async ({ eq }) => eq(await some([1, 2, 3], 0), []))
// it should return the first value to resolve
t(async ({ eq, wait }) =>
eq(await some([Promise.resolve(2), wait(5).then(() => 5)], 1), [2]),
)
// it should not wait for every results to wait, the order should be preserved.
t(async ({ eq, wait }) => {
const start = Date.now()
const result = await some([wait(1), wait(50), Promise.resolve(5)], 2)
if (Date.now() - start > 5) throw Error("that's too long !")
return eq(result, [undefined, 5])
})
Object.freeze(tests)
export const setup = Math.random

33
js/tests/rebecca-black_test.js

@ -0,0 +1,33 @@
export const tests = []
const t = (f) => tests.push(f)
// isFriday
t(() => isFriday(new Date('2014-08-29')))
t(() => isFriday(new Date('2020-07-17')))
t(() => !isFriday(new Date('1992-08-26')))
t(() => !isFriday(new Date('2000-08-26')))
// isWeekend
t(() => isWeekend(new Date('2014-09-06')))
t(() => isWeekend(new Date('2020-05-30')))
t(() => !isWeekend(new Date('1929-02-13')))
t(() => !isWeekend(new Date('1990-01-30')))
// isLeapYear
t(() => isLeapYear(new Date('1804-02-01')))
t(() => isLeapYear(new Date('2008-02-01')))
t(() => isLeapYear(new Date('2216-02-01')))
t(() => !isLeapYear(new Date('1993-02-01')))
t(() => !isLeapYear(new Date('1999-02-01')))
// isLastDayOfMonth
t(() => isLastDayOfMonth(new Date('2020-02-29')))
t(() => isLastDayOfMonth(new Date('2020-12-31')))
t(() => isLastDayOfMonth(new Date('2019-02-28')))
t(() => isLastDayOfMonth(new Date('1998-02-28')))
t(() => isLastDayOfMonth(new Date('1980-02-29')))
t(() => !isLastDayOfMonth(new Date('2020-12-30')))
t(() => !isLastDayOfMonth(new Date('2020-02-28')))
t(() => !isLastDayOfMonth(new Date('2019-02-29')))
Object.freeze(tests)

293
js/tests/using-filter_test.js

@ -0,0 +1,293 @@
export const tests = []
const t = (f) => tests.push(f)
const check = ({ filterCalls }, eq, a, b) => {
const result = eq(a, b)
const len = filterCalls.length
filterCalls.length = 0
return len ? result : false
}
t(({ eq, ctx }) =>
check(ctx, eq, filterShortStateName(ctx.arr1), [
'Alaska',
'Hawaii',
'Idaho',
'Iowa',
'Kansas',
'Maine',
'Nevada',
'Ohio',
'Oregon',
'Texas',
'Utah',
]),
)
t(({ eq, ctx }) =>
check(ctx, eq, filterStartVowel(ctx.arr1), [
'Alabama',
'Alaska',
'Arizona',
'Arkansas',
'Idaho',
'Illinois',
'Indiana',
'Iowa',
'Ohio',
'Oklahoma',
'Oregon',
'Utah',
]),
)
t(({ eq, ctx }) =>
check(ctx, eq, filter5Vowels(ctx.arr1), [
'California',
'Louisiana',
'North Carolina',
'South Carolina',
'South Dakota',
'West Virginia',
]),
)
t(({ eq, ctx }) =>
check(ctx, eq, filter1DistinctVowel(ctx.arr1), [
'Alabama',
'Alaska',
'Arkansas',
'Kansas',
'Maryland',
'Mississippi',
'New Jersey',
'Tennessee',
]),
)
t(({ eq, ctx }) =>
check(ctx, eq, multiFilter(ctx.arr2), [
{ tag: 'CA', name: 'California', capital: 'Sacramento', region: 'West' },
{ tag: 'HI', name: 'Hawaii', capital: 'Honolulu', region: 'West' },
{
tag: 'MO',
name: 'Missouri',
capital: 'Jefferson City',
region: 'Midwest',
},
{
tag: 'PA',
name: 'Pennsylvania',
capital: 'Harrisburg',
region: 'Northeast',
},
{
tag: 'RI',
name: 'Rhode Island',
capital: 'Providence',
region: 'Northeast',
},
]),
)
Object.freeze(tests)
export const setup = () => {
const filterCalls = []
const _filter = Array.prototype.filter
Array.prototype.filter = function () {
filterCalls.push(this)
return _filter.apply(this, arguments)
}
const arr1 = Object.freeze([
'Alabama',
'Alaska',
'Arizona',
'Arkansas',
'California',
'Colorado',
'Connecticut',
'Delaware',
'Florida',
'Georgia',
'Hawaii',
'Idaho',
'Illinois',
'Indiana',
'Iowa',
'Kansas',
'Kentucky',
'Louisiana',
'Maine',
'Maryland',
'Massachusetts',
'Michigan',
'Minnesota',
'Mississippi',
'Missouri',
'Montana',
'Nebraska',
'Nevada',
'New Hampshire',
'New Jersey',
'New Mexico',
'New York',
'North Carolina',
'North Dakota',
'Ohio',
'Oklahoma',
'Oregon',
'Pennsylvania',
'Rhode Island',
'South Carolina',
'South Dakota',
'Tennessee',
'Texas',
'Utah',
'Vermont',
'Virginia',
'Washington',
'West Virginia',
'Wisconsin',
'Wyoming',
])
const arr2 = Object.freeze(
[
{ tag: 'AL', name: 'Alabama', capital: 'Montgomery', region: 'South' },
{ tag: 'AK', name: 'Alaska', capital: 'Juneau', region: 'West' },
{ tag: 'AZ', name: 'Arizona', capital: 'Phoenix', region: 'West' },
{ tag: 'AR', name: 'Arkansas', capital: 'Little Rock', region: 'South' },
{ tag: 'CA', name: 'California', capital: 'Sacramento', region: 'West' },
{ tag: 'CO', name: 'Colorado', capital: 'Denver', region: 'West' },
{
tag: 'CT',
name: 'Connecticut',
capital: 'Hartford',
region: 'Northeast',
},
{ tag: 'DE', name: 'Delaware', capital: 'Dover', region: 'South' },
{
tag: 'DC',
name: 'District Of Columbia',
capital: 'Washington',
region: 'South',
},
{ tag: 'FL', name: 'Florida', capital: 'Tallahassee', region: 'South' },
{ tag: 'GA', name: 'Georgia', capital: 'Atlanta', region: 'South' },
{ tag: 'HI', name: 'Hawaii', capital: 'Honolulu', region: 'West' },
{ tag: 'ID', name: 'Idaho', capital: 'Boise', region: 'West' },
{
tag: 'IL',
name: 'Illinois',
capital: 'Springfield',
region: 'Midwest',
},
{
tag: 'IN',
name: 'Indiana',
capital: 'Indianapolis',
region: 'Midwest',
},
{ tag: 'IA', name: 'Iowa', capital: 'Des Moines', region: 'Midwest' },
{ tag: 'KS', name: 'Kansas', capital: 'Topeka', region: 'Midwest' },
{ tag: 'KY', name: 'Kentucky', capital: 'Frankfort', region: 'South' },
{ tag: 'LA', name: 'Louisiana', capital: 'Baton Rouge', region: 'South' },
{ tag: 'ME', name: 'Maine', capital: 'Augusta', region: 'Northeast' },
{ tag: 'MD', name: 'Maryland', capital: 'Annapolis', region: 'South' },
{
tag: 'MA',
name: 'Massachusetts',
capital: 'Boston',
region: 'Northeast',
},
{ tag: 'MI', name: 'Michigan', capital: 'Lansing', region: 'Midwest' },
{ tag: 'MN', name: 'Minnesota', capital: 'St. Paul', region: 'Midwest' },
{ tag: 'MS', name: 'Mississippi', capital: 'Jackson', region: 'South' },
{
tag: 'MO',
name: 'Missouri',
capital: 'Jefferson City',
region: 'Midwest',
},
{ tag: 'MT', name: 'Montana', capital: 'Helena', region: 'West' },
{ tag: 'NE', name: 'Nebraska', capital: 'Lincoln', region: 'Midwest' },
{ tag: 'NV', name: 'Nevada', capital: 'Carson City', region: 'West' },
{
tag: 'NH',
name: 'New Hampshire',
capital: 'Concord',
region: 'Northeast',
},
{
tag: 'NJ',
name: 'New Jersey',
capital: 'Trenton',
region: 'Northeast',
},
{ tag: 'NM', name: 'New Mexico', capital: 'Santa Fe', region: 'West' },
{ tag: 'NY', name: 'New York', capital: 'Albany', region: 'Northeast' },
{
tag: 'NC',
name: 'North Carolina',
capital: 'Raleigh',
region: 'South',
},
{
tag: 'ND',
name: 'North Dakota',
capital: 'Bismarck',
region: 'Midwest',
},
{ tag: 'OH', name: 'Ohio', capital: 'Colombus', region: 'Midwest' },
{
tag: 'OK',
name: 'Oklahoma',
capital: 'Oklahoma City',
region: 'South',
},
{ tag: 'OR', name: 'Oregon', capital: 'Salem', region: 'West' },
{
tag: 'PA',
name: 'Pennsylvania',
capital: 'Harrisburg',
region: 'Northeast',
},
{
tag: 'RI',
name: 'Rhode Island',
capital: 'Providence',
region: 'Northeast',
},
{
tag: 'SC',
name: 'South Carolina',
capital: 'Columbia',
region: 'South',
},
{ tag: 'SD', name: 'South Dakota', capital: 'Pierre', region: 'Midwest' },
{ tag: 'TN', name: 'Tennessee', capital: 'Nashville', region: 'South' },
{ tag: 'TX', name: 'Texas', capital: 'Austin', region: 'South' },
{ tag: 'UT', name: 'Utah', capital: 'Salt Lake City', region: 'West' },
{
tag: 'VT',
name: 'Vermont',
capital: 'Montpelier',
region: 'Northeast',
},
{ tag: 'VA', name: 'Virginia', capital: 'Richmond', region: 'South' },
{ tag: 'WA', name: 'Washington', capital: 'Olympia', region: 'West' },
{
tag: 'WV',
name: 'West Virginia',
capital: 'Charleston',
region: 'South',
},
{ tag: 'WI', name: 'Wisconsin', capital: 'Madison', region: 'Midwest' },
{ tag: 'WY', name: 'Wyoming', capital: 'Cheyenne', region: 'West' },
].map((e) => Object.freeze(e)),
)
return { filterCalls, arr1, arr2 }
}

197
js/tests/using-map_test.js

@ -0,0 +1,197 @@
export const tests = []
const t = (f) => tests.push(f)
// citiesOnly
t(({ eq, ctx }) =>
eq(citiesOnly(ctx.states), [
'Los Angeles',
'San Francisco',
'Miami',
'New York City',
'Juneau',
'Boston',
'Jackson',
'Utqiagvik',
'Albuquerque',
]),
)
t(({ eq, ctx }) => eq(ctx.mapCalls[0], ctx.states))
// upperCasingStates
t(({ eq, ctx }) =>
eq(upperCasingStates(ctx.cities), [
'Alabama',
'New Jersey',
'Alaska',
'New York',
'California',
'New Hampshire',
'Ohio',
'Texas',
'West Virginia',
]),
)
t(({ eq, ctx }) => eq(ctx.mapCalls.includes(ctx.cities), true))
// farenheitToCelsius
t(({ eq, ctx }) =>
eq(farenheitToCelsius(ctx.temps), [
'30°C',
'37°C',
'5°C',
'12°C',
'-13°C',
'21°C',
'-19°C',
]),
)
t(({ eq, ctx }) => eq(ctx.mapCalls.includes(ctx.temps), true))
// trimTemp
t(({ eq, ctx }) =>
eq(trimTemp(ctx.states), [
{
city: 'Los Angeles',
state: 'california',
region: 'West',
temperature: '101°F',
},
{
city: 'San Francisco',
state: 'california',
region: 'West',
temperature: '84°F',
},
{ city: 'Miami', state: 'Florida', region: 'South', temperature: '112°F' },
{
city: 'New York City',
state: 'new york',
region: 'North East',
temperature: '0°F',
},
{ city: 'Juneau', state: 'Alaska', region: 'West', temperature: '21°F' },
{
city: 'Boston',
state: 'massachussetts',
region: 'North East',
temperature: '45°F',
},
{
city: 'Jackson',
state: 'mississippi',
region: 'South',
temperature: '70°F',
},
{ city: 'Utqiagvik', state: 'Alaska', region: 'West', temperature: '-1°F' },
{
city: 'Albuquerque',
state: 'new mexico',
region: 'West',
temperature: '95°F',
},
]),
)
t(({ eq, ctx }) => eq(ctx.mapCalls.includes(ctx.states), true))
// tempForecasts
t(({ eq, ctx }) =>
eq(tempForecasts(ctx.states), [
'38°Celsius in Los Angeles, California',
'28°Celsius in San Francisco, California',
'44°Celsius in Miami, Florida',
'-18°Celsius in New York City, New York',
'-7°Celsius in Juneau, Alaska',
'7°Celsius in Boston, Massachussetts',
'21°Celsius in Jackson, Mississippi',
'-19°Celsius in Utqiagvik, Alaska',
'35°Celsius in Albuquerque, New Mexico',
]),
)
export const setup = () => {
const mapCalls = []
const _map = Array.prototype.map
Array.prototype.map = function () {
mapCalls.push(this)
return _map.apply(this, arguments)
}
const states = [
{
city: 'Los Angeles',
temperature: '101 °F',
state: 'california',
region: 'West',
},
{
city: 'San Francisco',
temperature: '84 °F',
state: 'california',
region: 'West',
},
{
city: 'Miami',
temperature: ' 112 °F',
state: 'Florida',
region: 'South',
},
{
city: 'New York City',
temperature: ' 0 °F',
state: 'new york',
region: 'North East',
},
{ city: 'Juneau', temperature: ' 21° F', state: 'Alaska', region: 'West' },
{
city: 'Boston',
temperature: '45 °F',
state: 'massachussetts',
region: 'North East',
},
{
city: 'Jackson',
temperature: ' 70°F ',
state: 'mississippi',
region: 'South',
},
{
city: 'Utqiagvik',
temperature: ' -1 °F',
state: 'Alaska',
region: 'West',
},
{
city: 'Albuquerque',
temperature: ' 95 °F',
state: 'new mexico',
region: 'West',
},
]
const cities = [
'alabama',
'new jersey',
'alaska',
'new york',
'california',
'new hampshire',
'ohio',
'texas',
'west virginia',
]
Object.getPrototypeOf([]).proto = ' [avoid for..in] '
const temps = ['86°F', '100°F', '41°F', '55°F', '10°F', '70°F', '-2°F']
Object.freeze(states)
Object.freeze(cities)
Object.freeze(temps)
return { mapCalls, states, cities, temps }
}
Object.freeze(tests)

4
subjects/abs.en.md

@ -1,6 +1,6 @@
## Abs(olute)
## Abs
### Instruction
### Instructions
Create a `isPositive` function that takes a number as
parameter and return true if the given number is

2
subjects/capitalizer.en.md

@ -1,4 +1,4 @@
## Capitalize
## Capitalizer
### Instructions

4
subjects/chunky.en.md

@ -1,6 +1,6 @@
## Chunk
## Chunky
### Instruction
### Instructions
Create the `chunk` function that returns an array of elements
split into groups the length of the given size.

4
subjects/curry-entries.en.md

@ -1,6 +1,6 @@
## curry entries
## Curry Entries
### Instruction
### Instructions
This exercise consists in creating curry functions to apply in the objects
entries.

2
subjects/cut-corners.en.md

@ -1,4 +1,4 @@
## Cut corners
## Cut Corners
### Instructions

19
subjects/date-is.en.md

@ -0,0 +1,19 @@
## Date Is
### Instructions
Create the following functions:
- `isValid`, this function must return false if its an Invalid Date
- `isAfter`, this function will receive two dates and return true if the first date is bigger then the second date
- `isBefore`, this function will receive two dates and return true if the first date is lesser then the second date
- `isFuture`, will return true if the date given as parameter is higher then the present date
- `isPast`, will return true if the date given as parameter less then the present date
### Notions
- https://date-fns.org/v2.14.0/docs/isValid
- https://date-fns.org/v2.14.0/docs/isAfter
- https://date-fns.org/v2.14.0/docs/isBefore
- https://date-fns.org/v2.14.0/docs/isFuture
- https://date-fns.org/v2.14.0/docs/isPast

2
subjects/day-of-the-year.en.md

@ -1,4 +1,4 @@
## Day of the Year
## Day Of The Year
### Instructions

5
subjects/debounce.en.md

@ -1,11 +1,12 @@
## debouncing
## Debounce
## Instruction
### Instructions
Create two functions that will work like `_.debounce` from lodash
- `debounce`, this function doesn't need to take care of the options
- `opDebounce`, this function will take care of the `leading` options
### Notions
- https://lodash.com/docs/4.17.15#debounce

2
subjects/deep-copy.en.md

@ -1,4 +1,4 @@
## deep-copy
## Deep Copy
### Instructions

25
subjects/filter.en.md

@ -0,0 +1,25 @@
## Filter
### Instructions
- Create a `filter` function that takes an array as first argument, a function as second,
and that works like the method [].filter
- Create a `reject` function that takes an array as first argument, a function as second,
and that works like the reject function from lodash.
- Create a `partition` function that takes an array as first argument, a function as second,
and that works like the partition function from lodash.
### Notions
- https://devdocs.io/javascript/global_objects/array/filter
- https://lodash.com/docs/4.17.15#reject
- https://lodash.com/docs/4.17.15#partition
### Code provided
```js
Array.prototype.filter = undefined
```

4
subjects/find-expression.en.md

@ -1,4 +1,6 @@
### Instruction
## Find Expression
### Instructions
Create a function called `findExpression` that takes a number as parameter and returns a string

4
subjects/flagger.en.md

@ -1,6 +1,6 @@
## flags
## Flagger
### Instruction
### Instructions
Create a function called `flags` that receives an object and outputs
the specific aliases and descriptions from the properties of that object.

17
subjects/for-each.en.md

@ -0,0 +1,17 @@
## For Each
### Instructions
Create a `forEach` function that takes an array as first argument, a function as second,
and that works like the method .forEach
### Notions
- https://devdocs.io/javascript/global_objects/array/foreach
### Code provided
```js
Array.prototype.forEach = undefined
```

2
subjects/fusion.en.md

@ -1,4 +1,4 @@
## fusion
## Fusion
### Instructions

28
subjects/get-json.en.md

@ -0,0 +1,28 @@
## Get Json
### Instructions
In this exercise, we will focus on building complex async flows with promises.
Create a `getJSON` function that takes 2 parameters:
- `path`, that will be the url called by your function
- `params` *optional*, that will be the search parameters appended to your url
`getJSON` must construct a valid url with the `path` and stringified `params`
and call `fetch` with it.
If the response is not ok, your function must throw an error using
the response status message.
The response body must then be read and parsed from json.
The parsed object contains one of those 2 properties:
- `"data"` the actual data to return
- `"error"` the error message to throw
### Notions
- https://nan-academy.github.io/js-training/examples/promise.js
- https://devdocs.io/dom/fetch_api/using_fetch
- https://devdocs.io/dom/urlsearchparams
- https://devdocs.io/javascript/global_objects/json

7
subjects/get-some-time.en.md

@ -0,0 +1,7 @@
## Get Some Time
### Instructions
Create a function `firstDayWeek` that receives a week of the year
(from 1 to 53) and a year (as a string), and returns the first day
of that week, in the format: 'dd-mm-yyyy'.

42
subjects/gougle-search.en.md

@ -0,0 +1,42 @@
## Gougle Search
### Instructions
Create the `queryServers` function, that takes 2 arguments:
- `serverName` a string of the name of the server
- `q` a string of the query given by the user
You have to construct 2 urls, using `q` as a search parameter,
prepending a `'/'` and for the 2nd appending `'_backup'`.
Then return the first value of those 2 calls
```js
queryServers('pouet', 'hello+world')
// return the fastest of those 2 calls:
// -> getJSON('/pouet?q=hello+world')
// -> getJSON('/pouet_backup?q=hello+world')
```
Create a `gougleSearch` function that takes a single query argument.
It must call `queryServers` in concurrently on 3 servers:
`'web'`, `'image'` and `'video'`.
A timeout of 80milliseconds must be set for the whole operation.
You must return the value from each servers in an object
using a the server name as key.
### Notions
- https://devdocs.io/javascript/global_objects/promise/race
- https://devdocs.io/javascript/global_objects/promise/all
### Code provided
```js
// fake `getJSON` function
let getJSON = async (url) => url
```

4
subjects/greedy-url.en.md

@ -1,6 +1,6 @@
## greedy-url
## Greedy Url
### Instruction
### Instructions
Write 3 functions :

2
subjects/has-city.en.md

@ -1,6 +1,6 @@
## Has City
### Instruction
### Instructions
Create a function `hasCity` that given a country and an array of cities
of that country and it returns whether a city is part of that country or not.

45
subjects/interpolation.en.md

@ -0,0 +1,45 @@
## Interpolation
### Instructions
Create a function called `interpolation` that takes an object with 5 properties
`step`, `start`, `end`, `callback` and `duration`.
This function must calculate the interpolation points, (x, y),
from the `start` position to `end` position depending on the number of `steps`.
All the points must be calculated in the duration time.
For each interpolation point you must execute and pass as parameters to the callback the interpolation point ([x, y])
### Example
```
steps = 5
start = 0
end = 1
duration = 10
t
|
10 |___________________. <- execute callback([1.0, 10])
| |
| |
8 |_______________. |
| | |
| | |
6 |___________. | |
| | | |
| | | |
4 |_______. | | |
| | | | |
| | | | |
2 |___. | | | |
| | | | | |
|___|___|___|___|___|__d
0 0.2 0.4 0.6 0.8 1
```
### Notions
- https://javascript.info/settimeout-setinterval

2
subjects/ion-out.en.md

@ -1,6 +1,6 @@
## Ion Out
### Instruction
### Instructions
Make a function `ionOut` that receives a string and returns an array with every
word containing 'ion' following a t, without the 'ion'.

83
subjects/is-winner.en.md

@ -0,0 +1,83 @@
## Is Winner
### Instructions
Create a function `isWinner` that, by making use of `winners` "API", should
return a resolved Promise with the string:
- `<country> + ' never was a winner'`, if the country passed
in `isWinner` has never won a the FIFA World Cup
- `<country> + ' is not what we are looking for because of the continent'`,
if the country passed in `isWinner` is not from the european
continent
- `<country> + ' is not what we are looking for because of the number of
times it was champion'`, if the country passed in `isWinner` was champion
less than 3 times
- `<country> + ' won the FIFA World Cup in ' + <year(s)> + 'winning by '
+ <results>`, otherwise.
If the country was champion in more than one year, the years should be
displayed like : '1000, 1004, 1008'. The same goes for the results
### Code provided
```js
const db = (() => {
//countries that won the FIFA World Cup
const countries = [
{ id: 1, name: 'Brazil', continent: 'South America' },
{ id: 2, name: 'Germany', continent: 'Europe' },
{ id: 3, name: 'Italy', continent: 'Europe' },
{ id: 4, name: 'Argentina', continent: 'South America' },
{ id: 5, name: 'France', continent: 'Europe' },
{ id: 6, name: 'Uruguay', continent: 'South America' },
{ id: 7, name: 'England', continent: 'Europe' },
{ id: 8, name: 'Spain', continent: 'Europe' },
]
//Information about the wins
const results = [
{ id: 1, countryId: 6, year: 1930, score: '4-2' },
{ id: 2, countryId: 3, year: 1934, score: '2-1' },
{ id: 3, countryId: 3, year: 1938, score: '4-2' },
{ id: 4, countryId: 6, year: 1950, score: '2-1' },
{ id: 5, countryId: 2, year: 1954, score: '3-2' },
{ id: 6, countryId: 1, year: 1958, score: '5-2' },
{ id: 7, countryId: 1, year: 1962, score: '3-1' },
{ id: 8, countryId: 7, year: 1966, score: '4-2' },
{ id: 9, countryId: 1, year: 1970, score: '4-1' },
{ id: 10, countryId: 2, year: 1974, score: '2-1' },
{ id: 11, countryId: 4, year: 1978, score: '3-1' },
{ id: 12, countryId: 3, year: 1982, score: '3-1' },
{ id: 13, countryId: 4, year: 1986, score: '3-2' },
{ id: 14, countryId: 2, year: 1990, score: '1-0' },
{ id: 15, countryId: 1, year: 1994, score: '3-2p' },
{ id: 16, countryId: 5, year: 1998, score: '3-0' },
{ id: 17, countryId: 1, year: 2002, score: '2-0' },
{ id: 18, countryId: 3, year: 2006, score: '5-3p' },
{ id: 19, countryId: 8, year: 2010, score: '1-0' },
{ id: 20, countryId: 2, year: 2014, score: '1-0' },
{ id: 21, countryId: 5, year: 2018, score: '4-2' },
]
return {
//returns the information of the country
getWinner: async (countryName) => {
const match = countries.find((country) => country.name === countryName)
if (!match) throw Error('Country Not Found')
return match
},
//returns the information of the wins of that country
getResults: async (countryId) => {
const match = results.filter((result) => result.countryId === countryId)
if (!match.length) throw Error('Results Not Found')
return match
},
addCountry: (country) => countries.push(country),
addResults: (result) => results.push(result),
}
})()
```

4
subjects/its-a-match.en.md

@ -1,6 +1,6 @@
## It's a match
## Its A Match
### Instruction
### Instructions
Create 4 regular expression in variables:

30
subjects/keep-trying-or-giveup.en.md

@ -0,0 +1,30 @@
## Keep Trying Or Giveup
### Instructions
Create a `retry` function, that takes 2 arguments
- a `count`, that tells how many retries must be done
- an async `callback`, that will be call every try
and it return a new function, passing arguments given to the
callback on every tries.
> for count of 3, the function will be called at most 4 times:
> the initial call + 3 retries.
Create a `timeout` function, that takes 2 arguments
- a `delay`, that tells how long to wait
- an async `callback`, that will be call
and it return a new function, passing arguments given to the callback
and either the async callback resolve before the delay is reached,
in that case we return the value from the callback,
or reject an error using the message `"timeout"`
### Notions
- https://nan-academy.github.io/js-training/examples/promise.js
- https://devdocs.io/dom/windoworworkerglobalscope/settimeout
- https://devdocs.io/javascript/global_objects/promise/race

2
subjects/letter-space-number.en.md

@ -1,6 +1,6 @@
## Letter Space Number
### Instruction
### Instructions
Make a function called `letterSpaceNumber` that receives a string and returns an
array with every instance of a letter, followed by a space, followed by a number

2
subjects/manipulate-entries.en.md

@ -1,4 +1,4 @@
## manipulate-entries
## Manipulate Entries
### Instructions

2
subjects/manipulate-keys.en.md

@ -1,4 +1,4 @@
## manipulate-keys
## Manipulate Keys
### Instructions

2
subjects/manipulate-values.en.md

@ -1,4 +1,4 @@
## manipulate-values
## Manipulate Values
### Instructions

23
subjects/mapper.en.md

@ -0,0 +1,23 @@
## Mapper
### Instructions
- Create a `map` function that takes an array as first argument, a function as second,
and that works like the method .map
- Create a `flatMap` function that takes an array as first argument, a function as second,
and that works like the method .flatMap
### Notions
- https://devdocs.io/javascript/global_objects/array/map
- https://devdocs.io/javascript/global_objects/array/flatmap
### Code provided
```js
Array.prototype.map = undefined
Array.prototype.flatMap = undefined
Array.prototype.flat = undefined
```

32
subjects/match-cron.en.md

@ -0,0 +1,32 @@
## Match Cron
### Instructions
Create a function called `matchCron` it takes a valid cron schedule string
and a valid date. \
It returns true if the date match the pattern
> You only have to implement numbers and `*`. \
> other complex patterns are not required.
Only valid pattern will be tested.
### Example
```js
matchCron('9 * * * *', new Date('2020-05-30 18:09:00')) // -> true
matchCron('9 * * * *', new Date('2020-05-30 19:09:00')) // -> true
matchCron('9 * * * *', new Date('2020-05-30 19:21:00')) // -> false
// | | | | |
// | | | | +- Day of the Week (range: 1-7, 1 standing for Monday)
// | | | +--- Month of the Year (range: 1-12)
// | | +----- Day of the Month (range: 1-31)
// | +------- Hour (range: 0-23)
// +--------- Minute (range: 0-59)
```
### Notions
- https://crontab.guru/
- https://devdocs.io/javascript/global_objects/date

4
subjects/molecules-cells.en.md

@ -1,6 +1,6 @@
## molecules-cells
## Molecules Cells
### Instruction
### Instructions
Write two functions:
- `RNA` that given a DNA strand it must return is complement RNA

2
subjects/more-or-less.en.md

@ -1,4 +1,4 @@
## More or less
## More Or Less
### Instructions

4
subjects/mutability.en.md

@ -1,6 +1,6 @@
## Mutability
### Instruction
### Instructions
Create a copy of the person object called clone1.
Create an other copy of the person object called clone2.
@ -11,7 +11,7 @@ Increase by one the property age of `person`
and set his contry to `'FR'`.
## Notions
### Notions
- https://nan-academy.github.io/js-training/examples/set.js
- https://nan-academy.github.io/js-training/examples/get.js

2
subjects/nasa.en.md

@ -1,4 +1,4 @@
## NASA
## Nasa
### Instructions

2
subjects/neuron.en.md

@ -1,4 +1,4 @@
## neuron
## Neuron
### Instructions

2
subjects/pick-omit.en.md

@ -1,4 +1,4 @@
## Pick-Omit
## Pick Omit
### Instructions

2
subjects/primitives.en.md

@ -1,4 +1,4 @@
## Primitive
## Primitives
### Instructions

4
subjects/pronoun.en.md

@ -1,6 +1,6 @@
## pronoun
## Pronoun
### Instruction
### Instructions
Create a function called `pronoun` that has a string as parameter. This function returns an object
that will have all the pronouns, present in the string, as keys. Each key will have a sub object with the

2
subjects/pyramid.en.md

@ -1,4 +1,4 @@
## pyramid
## Pyramid
### Instructions

21
subjects/race.en.md

@ -0,0 +1,21 @@
## Race
### Instructions
Create a function `race` that works like `Promise.race`
Create a function `some` that takes an array of promises or values
and a number and return the first resolved values up to the number given.
> Empty array or a count of 0 return a promise resolving to `undefined`
### Notions
- https://nan-academy.github.io/js-training/examples/promise.js
- https://devdocs.io/javascript/global_objects/promise/race
### Code provided
```js
Promise.race = undefined
```

16
subjects/rebecca-black.en.md

@ -0,0 +1,16 @@
## Rebecca Black
### Instructions
Create the following functions:
- `isFriday` returns true if the date is a friday
- `isWeekend` returns true if the date is a day of the weekend
- `isLeapYear` returns true if the year is a leap year
- `isLastDayOfMonth` returns true if the date is the last day of the month
### Notions
- https://date-fns.org/v2.14.0/docs/isWeekend
- https://date-fns.org/v2.14.0/docs/isAfter
- https://date-fns.org/v2.14.0/docs/isLastDayOfMonth

2
subjects/replica.en.md

@ -1,4 +1,4 @@
## replica
## Replica
### Instructions

2
subjects/reverser.en.md

@ -1,4 +1,4 @@
## Reverse
## Reverser
### Instructions

4
subjects/same-amount.en.md

@ -1,6 +1,6 @@
## same-amount
## Same Amount
### Instruction
### Instructions
Create a `sameAmount` function that takes three parameter,
a data string and 2 regexes.

2
subjects/series.en.md

@ -1,4 +1,4 @@
## series
## Series
### Instructions

2
subjects/sweet-curry.en.md

@ -1,4 +1,4 @@
## Curry Easy
## Sweet Curry
### Instructions

2
subjects/throttle.en.md

@ -1,4 +1,4 @@
## throttling
## Throttle
### Instructions

2
subjects/triangle.en.md

@ -1,4 +1,4 @@
## triangle
## Triangle
### Instructions

6
subjects/unbreakable.en.md

@ -1,12 +1,12 @@
## Title
## Unbreakable
### Instruction
### Instructions
Implement 2 functions:
- `split` that works like the string method `.split` but take the string as
it's first argument.
- `join` that works like the string method `.split` but take the array as
- `join` that works like the string method `.join` but take the array as
it's first argument.

46
subjects/using-filter.en.md

@ -0,0 +1,46 @@
## Using Filter
### Instructions
- Create a function `filterShortStateName` that takes an array of
strings and that returns the ones with less than 7 characters.
> Example: `'Iowa'` only contains 4 characters
- Create a function `filterStartVowel` that takes an array of strings
and that returns only the ones that start with a vowel (a,e,i,o,u).
> Example: `'Alabama'` starts with a vowel
- Create a function `filter5Vowels` that takes an array of strings
and that returns only the ones which contain at least 5
vowels (a,e,i,o,u).
> Example: `'California'` contains at least 5 vowels
- Create a function `filter1DistinctVowel` that takes an array of
strings and that returns only the ones which vowels are of only
one distinct one (a,e,i,o,u).
> Example: `'Alabama'` only contains 1 distinct vowels `'a'`.
- Create a function `multiFilter` that takes an array of
objects and that returns only the ones which:
- the key `capital` contains at least 8 characters.
- the key `name` does not start with a vowel
- the key `tag` has at least one vowel.
- the key `region` is not `'South'`
Example of an array of objects matching the criterias:
[
{ tag: 'CA', name: 'California', capital: 'Sacramento', region: 'West' },
{ tag: 'PA', name: 'Pennsylvania', capital: 'Harrisburg', region: 'Northeast' }
]
### Notions
- https://devdocs.io/javascript/global_objects/array/filter

102
subjects/using-map.en.md

@ -0,0 +1,102 @@
## Using Map
### Instructions
-Create a function named 'citiesOnly' which takes an array of objects
and which return an array of strings from the key `city`.
Example:
```js
[
{
city: 'Los Angeles',
temperature: ' 101 °F ',
},
{
city: 'San Francisco',
temperature: ' 84 ° F ',
},
]
```
returns
```js
['Los Angeles', 'San Francisco']
```
-Create a function named 'upperCasingStates' which takes an array of strings
and which Upper Case each words of a string.
The function returns then an array of strings.
Example:
```js
['alabama', 'new jersey']
```
returns
```js
['Alabama', 'New Jersey']
```
-Create a function named 'fahrenheitToCelsius' which takes an array
of fahrenheit temperatures which converts them to Celsius.
Round down the result.
The function then returns the result as an array of strings like below:
example:
```js
['68°F', '59°F', '25°F']
```
returns
```js
['20°C', '15°C', '-4°C']
```
-Create a function named 'trimTemp' which takes an array of objects
and which removes the spaces from the string in the key `temperature`.
The function then returns an array of objects with the modification.
Example:
```js
[
{ city: 'Los Angeles', temperature: ' 101 °F '},
{ city: 'San Francisco', temperature: ' 84 ° F '},
]
```
returns
```js
[
{ city: 'Los Angeles', temperature: '101°F' },
{ city: 'San Francisco', temperature: '84°F' },
]
```
-Create a 'tempForecasts' function which will take an array of objects, and which will
return an array of strings formatted as below:
```js
[
{
city: 'Pasadena',
temperature: ' 101 °F',
state: 'california',
region: 'West',
}
]
```
returns
```js
['38°Celsius in Pasadena, California']
```
### Notions
- https://devdocs.io/javascript/global_objects/array/map

2
subjects/using-reduce.en.md

@ -1,6 +1,6 @@
## Using Reduce
### Instruction
### Instructions
Create three functions :
- `adder` that receives an array and adds its elements.

4
subjects/valid-ip.en.md

@ -1,6 +1,6 @@
## valid-ip
## Valid Ip
### Instruction
### Instructions
Write a function called `findIP` that search for a valid IP, with or without a port, in a string passed as parameter

2
subjects/vowel-dots.en.md

@ -1,6 +1,6 @@
## Vowel Dots
### Instruction
### Instructions
Create a function called vowelDots that receives a string and adds a `.` after
every vowel ('y' is not considered a vowel here) using a regex called `vowels`.

2
subjects/何.en.md

@ -1,4 +1,4 @@
## 何 !?
## 何
### Instructions

Loading…
Cancel
Save