Compare commits
37 Commits
Author | SHA1 | Date |
---|---|---|
Hifilo | 9eb942909e | |
c-auri | 77c5d64b37 | |
Eric Olkowski | c4301bbd9c | |
Eric Olkowski | 04ced679a3 | |
Yossi Rise | adf2bf93bc | |
James Hogan | 0f57a2afcd | |
Eric Olkowski | 44a95b8e89 | |
Asartea | 171ac956cf | |
Eric Olkowski | 2518281b10 | |
Asartea | e94742d58c | |
Asartea | 6bafdb5094 | |
Asartea | c037ad5bf5 | |
Yossi Rise | b52b2ace26 | |
James Hogan | 10cb98c038 | |
Tatiana | db998d7279 | |
Babatunde Alli | 4b13066369 | |
Michael Frank | 7df108c5de | |
icorvus | de40b279df | |
icorvus | c09df52d6a | |
Tatiana | 8150be944b | |
Yasikhorram | 5b5687862a | |
Marvin Gay | 56ebfc0f7d | |
Kevin Mulhern | 4fca2e249c | |
Kevin Mulhern | fda681965e | |
Kevin Mulhern | a1c56276ea | |
Michael Frank | 085fd89ec8 | |
Michael Frank | 06e90f66c8 | |
Michael Frank | 8546794b47 | |
Michael Frank | ac4d2a94e5 | |
Michael Frank | 276b60a3c3 | |
Michael Frank | 435c1d3779 | |
Michael Frank | 9916e343a3 | |
Michael Frank | cced031981 | |
Michael Frank | 2d6c505096 | |
Michael Frank | a5a0284ac1 | |
Michael Frank | ce0b9fade1 | |
Michael Frank | 749a48adee |
|
@ -1,20 +0,0 @@
|
|||
version: 2.1
|
||||
|
||||
orbs:
|
||||
node: circleci/node@5.1.0
|
||||
|
||||
jobs:
|
||||
test-solutions:
|
||||
executor: node/default
|
||||
steps:
|
||||
- checkout
|
||||
- node/install-packages:
|
||||
pkg-manager: npm
|
||||
- run:
|
||||
command: npm run test solution
|
||||
name: Run tests in **/solution/*.spec.js
|
||||
|
||||
workflows:
|
||||
test-solutions:
|
||||
jobs:
|
||||
- test-solutions
|
|
@ -1,54 +0,0 @@
|
|||
---
|
||||
name: Bug Report
|
||||
about: Create a report to help us improve something that is not working correctly
|
||||
title: "Bug - :"
|
||||
labels: "Status: Needs Review, Type: Bug"
|
||||
assignees: ""
|
||||
---
|
||||
|
||||
<!-- Thank you for taking the time to submit a bug report to The Odin Project. In order to get issues closed in a reasonable amount of time, you must include a baseline of information about the bug in question. Please read this template in its entirety before filling it out to ensure that it is filled out correctly. -->
|
||||
|
||||
Complete the following REQUIRED checkboxes:
|
||||
- [ ] I have thoroughly read and understand [The Odin Project Contributing Guide](https://github.com/TheOdinProject/.github/blob/main/CONTRIBUTING.md)
|
||||
- [ ] The title of this issue follows the `Bug - location of bug: brief description of bug` format, e.g. `Bug - Exercises: File type incorrect for all test files`
|
||||
|
||||
The following checkbox is OPTIONAL:
|
||||
<!-- Completing this checkbox does not guarantee you will be assigned this issue, but rather lets us know you are interested in working on it. -->
|
||||
- [ ] I would like to be assigned this issue to work on it
|
||||
|
||||
<hr>
|
||||
|
||||
**1. Description of the Bug:**
|
||||
<!-- A clear and concise description of what the bug is. Include any screenshots that may help show the bug in action. -->
|
||||
|
||||
|
||||
**2. How To Reproduce:**
|
||||
<!--
|
||||
What steps one might need to take in order to reproduce this bug, e.g.:
|
||||
1. Log in
|
||||
2. Visit a lesson page
|
||||
3. Click the complete button
|
||||
4. The complete button does not update
|
||||
-->
|
||||
|
||||
|
||||
**3. Expected Behavior:**
|
||||
<!--
|
||||
A brief description of what you expected to happen, e.g.:
|
||||
1. Log in
|
||||
2. Visit a lesson page
|
||||
3. Click the complete button
|
||||
4. The complete button updates correctly
|
||||
-->
|
||||
|
||||
|
||||
**4. Desktop/Device:**
|
||||
<!-- The more information you are able to provide, the better. -->
|
||||
- Device: <!-- [e.g. iPhone6] -->
|
||||
- OS: <!-- [e.g. iOS] -->
|
||||
- Browser: <!-- [e.g. chrome, safari] -->
|
||||
- Version: <!-- [e.g. 22] -->
|
||||
|
||||
**5. Additional Information:**
|
||||
<!-- Any additional information about the bug. -->
|
||||
|
|
@ -1,38 +0,0 @@
|
|||
---
|
||||
name: Feature Request
|
||||
about: Suggest a new feature or enhancement for this project
|
||||
title: ""
|
||||
labels: "Status: Needs Review"
|
||||
assignees: ""
|
||||
---
|
||||
|
||||
<!-- Thank you for taking the time to submit a new feature request to The Odin Project. In order to get issues closed in a reasonable amount of time, you must include a baseline of information about the feature/enhancement you are proposing. Please read this template in its entirety before filling it out to ensure that it is filled out correctly. -->
|
||||
|
||||
Complete the following REQUIRED checkboxes:
|
||||
- [ ] I have thoroughly read and understand [The Odin Project Contributing Guide](https://github.com/TheOdinProject/.github/blob/main/CONTRIBUTING.md)
|
||||
- [ ] The title of this issue follows the `location for request: brief description of request` format, e.g. `Exercises: Add exercise on XYZ`
|
||||
|
||||
The following checkbox is OPTIONAL:
|
||||
<!-- Completing this checkbox does not guarantee you will be assigned this issue, but rather lets us know you are interested in working on it. -->
|
||||
- [ ] I would like to be assigned this issue to work on it
|
||||
|
||||
<hr>
|
||||
|
||||
**1. Description of the Feature Request:**
|
||||
<!--
|
||||
A clear and concise description of what the feature or enhancement is, including how it would be useful/beneficial or what problem(s) it would solve.
|
||||
-->
|
||||
|
||||
|
||||
**2. Acceptance Criteria:**
|
||||
<!--
|
||||
A list of checkbox items that explain the requirements needed to be met to resolve this request, e.g.:
|
||||
- [ ] A theme toggle is present on the dashboard
|
||||
- [ ] Clicking the theme toggle changes between light and dark
|
||||
- [ ] A user's theme choice persists after leaving the website
|
||||
-->
|
||||
|
||||
|
||||
**3. Additional Information:**
|
||||
<!-- Any additional information about the feature request, such as a link to a Discord discussion, screenshots, etc. -->
|
||||
|
|
@ -1,32 +0,0 @@
|
|||
<!-- Thank you for taking the time to contribute to The Odin Project. In order to get this pull request (PR) merged in a reasonable amount of time, you must complete this entire template. -->
|
||||
|
||||
## Because
|
||||
<!-- Summarize the purpose or reasons for this PR, e.g. what problem it solves or what benefit it provides. -->
|
||||
|
||||
|
||||
## This PR
|
||||
<!-- A bullet point list of one or more items describing the specific changes. -->
|
||||
|
||||
|
||||
## Issue
|
||||
<!--
|
||||
If this PR closes an open issue in this repo, replace the XXXXX below with the issue number, e.g. Closes #2013.
|
||||
|
||||
If this PR closes an open issue in another TOP repo, replace the #XXXXX with the URL of the issue, e.g. Closes https://github.com/TheOdinProject/curriculum/issues/XXXXX
|
||||
|
||||
If this PR does not close, but is related to another issue or PR, you can link it as above without the 'Closes' keyword, e.g. 'Related to #2013'.
|
||||
-->
|
||||
Closes #XXXXX
|
||||
|
||||
## Additional Information
|
||||
<!-- Any other information about this PR, such as a link to a Discord discussion. -->
|
||||
|
||||
|
||||
## Pull Request Requirements
|
||||
<!-- Replace the whitespace between the square brackets with an 'x', e.g. [x]. After you create the PR, they will become checkboxes that you can click on. -->
|
||||
- [ ] I have thoroughly read and understand [The Odin Project Contributing Guide](https://github.com/TheOdinProject/.github/blob/main/CONTRIBUTING.md)
|
||||
- [ ] The title of this PR follows the `location of change: brief description of change` format, e.g. `01_helloWorld: Update test cases`
|
||||
- [ ] The `Because` section summarizes the reason for this PR
|
||||
- [ ] The `This PR` section has a bullet point list describing the changes in this PR
|
||||
- [ ] If this PR addresses an open issue, it is linked in the `Issue` section
|
||||
- [ ] If this PR includes any changes that affect the solution of an exercise, I've also updated the solution in the `/solutions` folder
|
|
@ -1,5 +0,0 @@
|
|||
const helloWorld = function () {
|
||||
return "Hello, World!";
|
||||
};
|
||||
|
||||
module.exports = helloWorld;
|
|
@ -1,7 +0,0 @@
|
|||
const helloWorld = require('./helloWorld-solution');
|
||||
|
||||
describe('Hello World', function () {
|
||||
test('says "Hello, World!"', function () {
|
||||
expect(helloWorld()).toEqual('Hello, World!');
|
||||
});
|
||||
});
|
|
@ -1,6 +0,0 @@
|
|||
const repeatString = function() {
|
||||
|
||||
};
|
||||
|
||||
// Do not edit below this line
|
||||
module.exports = repeatString;
|
|
@ -1,39 +0,0 @@
|
|||
const repeatString = require('./repeatString-solution');
|
||||
|
||||
describe('repeatString', () => {
|
||||
test('repeats the string', () => {
|
||||
expect(repeatString('hey', 3)).toEqual('heyheyhey');
|
||||
});
|
||||
test('repeats the string many times', () => {
|
||||
expect(repeatString('hey', 10)).toEqual('heyheyheyheyheyheyheyheyheyhey');
|
||||
});
|
||||
test('repeats the string 1 times', () => {
|
||||
expect(repeatString('hey', 1)).toEqual('hey');
|
||||
});
|
||||
test('repeats the string 0 times', () => {
|
||||
expect(repeatString('hey', 0)).toEqual('');
|
||||
});
|
||||
test('returns ERROR with negative numbers', () => {
|
||||
expect(repeatString('hey', -1)).toEqual('ERROR');
|
||||
});
|
||||
test('repeats the string a random amount of times', function () {
|
||||
/*The number is generated by using Math.random to get a value from between
|
||||
0 to 1, when this is multiplied by 1000 and rounded down with Math.floor it
|
||||
equals a number between 0 to 999 (this number will change everytime you run
|
||||
the test).*/
|
||||
|
||||
// DO NOT use Math.floor(Math.random() * 1000) in your code,
|
||||
// this test generates a random number, then passes it into your code with a function parameter.
|
||||
// If this doesn't make sense, you should go read about functions here: https://www.theodinproject.com/paths/foundations/courses/foundations/lessons/fundamentals-part-3
|
||||
const number = Math.floor(Math.random() * 1000);
|
||||
/*The .match(/((hey))/g).length is a regex that will count the number of heys
|
||||
in the result, which if your function works correctly will equal the number that
|
||||
was randomaly generated. */
|
||||
expect(repeatString('hey', number).match(/((hey))/g).length).toEqual(
|
||||
number
|
||||
);
|
||||
});
|
||||
test('works with blank strings', () => {
|
||||
expect(repeatString('', 10)).toEqual('');
|
||||
});
|
||||
});
|
|
@ -1,6 +0,0 @@
|
|||
const reverseString = function() {
|
||||
|
||||
};
|
||||
|
||||
// Do not edit below this line
|
||||
module.exports = reverseString;
|
|
@ -1,5 +0,0 @@
|
|||
const reverseString = function (string) {
|
||||
return string.split("").reverse().join("");
|
||||
};
|
||||
|
||||
module.exports = reverseString;
|
|
@ -1,18 +0,0 @@
|
|||
const reverseString = require('./reverseString-solution');
|
||||
|
||||
describe('reverseString', () => {
|
||||
test('reverses single word', () => {
|
||||
expect(reverseString('hello')).toEqual('olleh');
|
||||
});
|
||||
|
||||
test('reverses multiple words', () => {
|
||||
expect(reverseString('hello there')).toEqual('ereht olleh');
|
||||
});
|
||||
|
||||
test('works with numbers and punctuation', () => {
|
||||
expect(reverseString('123! abc!')).toEqual('!cba !321');
|
||||
});
|
||||
test('works with blank strings', () => {
|
||||
expect(reverseString('')).toEqual('');
|
||||
});
|
||||
});
|
|
@ -1,6 +0,0 @@
|
|||
const removeFromArray = function() {
|
||||
|
||||
};
|
||||
|
||||
// Do not edit below this line
|
||||
module.exports = removeFromArray;
|
|
@ -1,25 +0,0 @@
|
|||
const removeFromArray = require('./removeFromArray-solution');
|
||||
|
||||
describe('removeFromArray', () => {
|
||||
test('removes a single value', () => {
|
||||
expect(removeFromArray([1, 2, 3, 4], 3)).toEqual([1, 2, 4]);
|
||||
});
|
||||
test('removes multiple values', () => {
|
||||
expect(removeFromArray([1, 2, 3, 4], 3, 2)).toEqual([1, 4]);
|
||||
});
|
||||
test('ignores non present values', () => {
|
||||
expect(removeFromArray([1, 2, 3, 4], 7, 'tacos')).toEqual([1, 2, 3, 4]);
|
||||
});
|
||||
test('ignores non present values, but still works', () => {
|
||||
expect(removeFromArray([1, 2, 3, 4], 7, 2)).toEqual([1, 3, 4]);
|
||||
});
|
||||
test('can remove all values', () => {
|
||||
expect(removeFromArray([1, 2, 3, 4], 1, 2, 3, 4)).toEqual([]);
|
||||
});
|
||||
test('works with strings', () => {
|
||||
expect(removeFromArray(['hey', 2, 3, 'ho'], 'hey', 3)).toEqual([2, 'ho']);
|
||||
});
|
||||
test('only removes same type', () => {
|
||||
expect(removeFromArray([1, 2, 3], '1', 3)).toEqual([1, 2]);
|
||||
});
|
||||
});
|
|
@ -1,21 +0,0 @@
|
|||
const sumAll = function (min, max) {
|
||||
if (!Number.isInteger(min) || !Number.isInteger(max)) return "ERROR";
|
||||
if (min < 0 || max < 0) return "ERROR";
|
||||
if (min > max) {
|
||||
const temp = min;
|
||||
min = max;
|
||||
max = temp;
|
||||
}
|
||||
|
||||
// An alternative way to swap the values of min and max like above is to use the array destructuring syntax.
|
||||
// Here's an optional article on it: https://www.freecodecamp.org/news/array-destructuring-in-es6-30e398f21d10/
|
||||
// if (min > max) [min, max] = [max, min];
|
||||
|
||||
let sum = 0;
|
||||
for (let i = min; i <= max; i++) {
|
||||
sum += i;
|
||||
}
|
||||
return sum;
|
||||
};
|
||||
|
||||
module.exports = sumAll;
|
|
@ -1,25 +0,0 @@
|
|||
const sumAll = require('./sumAll-solution');
|
||||
|
||||
describe('sumAll', () => {
|
||||
test('sums numbers within the range', () => {
|
||||
expect(sumAll(1, 4)).toEqual(10);
|
||||
});
|
||||
test('works with large numbers', () => {
|
||||
expect(sumAll(1, 4000)).toEqual(8002000);
|
||||
});
|
||||
test('works with larger number first', () => {
|
||||
expect(sumAll(123, 1)).toEqual(7626);
|
||||
});
|
||||
test('returns ERROR with negative numbers', () => {
|
||||
expect(sumAll(-10, 4)).toEqual('ERROR');
|
||||
});
|
||||
test('returns ERROR with non-integer parameters', () => {
|
||||
expect(sumAll(2.5, 4)).toEqual('ERROR');
|
||||
});
|
||||
test('returns ERROR with non-number parameters', () => {
|
||||
expect(sumAll(10, '90')).toEqual('ERROR');
|
||||
});
|
||||
test('returns ERROR with non-number parameters', () => {
|
||||
expect(sumAll(10, [90, 1])).toEqual('ERROR');
|
||||
});
|
||||
});
|
|
@ -1,6 +0,0 @@
|
|||
const sumAll = function() {
|
||||
|
||||
};
|
||||
|
||||
// Do not edit below this line
|
||||
module.exports = sumAll;
|
|
@ -1,6 +0,0 @@
|
|||
const leapYears = function() {
|
||||
|
||||
};
|
||||
|
||||
// Do not edit below this line
|
||||
module.exports = leapYears;
|
|
@ -1,5 +0,0 @@
|
|||
const leapYears = function (year) {
|
||||
return year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0);
|
||||
};
|
||||
|
||||
module.exports = leapYears;
|
|
@ -1,22 +0,0 @@
|
|||
const leapYears = require('./leapYears-solution');
|
||||
|
||||
describe('leapYears', () => {
|
||||
test('works with non century years', () => {
|
||||
expect(leapYears(1996)).toBe(true);
|
||||
});
|
||||
test('works with non century years', () => {
|
||||
expect(leapYears(1997)).toBe(false);
|
||||
});
|
||||
test('works with ridiculously futuristic non century years', () => {
|
||||
expect(leapYears(34992)).toBe(true);
|
||||
});
|
||||
test('works with century years', () => {
|
||||
expect(leapYears(1900)).toBe(false);
|
||||
});
|
||||
test('works with century years', () => {
|
||||
expect(leapYears(1600)).toBe(true);
|
||||
});
|
||||
test('works with century years', () => {
|
||||
expect(leapYears(700)).toBe(false);
|
||||
});
|
||||
});
|
|
@ -1,12 +0,0 @@
|
|||
const convertToCelsius = function (fahrenheit) {
|
||||
return Math.round((fahrenheit - 32) * (5 / 9) * 10) / 10;
|
||||
};
|
||||
|
||||
const convertToFahrenheit = function (celsius) {
|
||||
return Math.round(((celsius * 9) / 5 + 32) * 10) / 10;
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
convertToCelsius,
|
||||
convertToFahrenheit,
|
||||
};
|
|
@ -1,28 +0,0 @@
|
|||
const {
|
||||
convertToCelsius,
|
||||
convertToFahrenheit,
|
||||
} = require('./tempConversion-solution');
|
||||
|
||||
describe('convertToCelsius', () => {
|
||||
test('works', () => {
|
||||
expect(convertToCelsius(32)).toEqual(0);
|
||||
});
|
||||
test('rounds to 1 decimal', () => {
|
||||
expect(convertToCelsius(100)).toEqual(37.8);
|
||||
});
|
||||
test('works with negatives', () => {
|
||||
expect(convertToCelsius(-100)).toEqual(-73.3);
|
||||
});
|
||||
});
|
||||
|
||||
describe('convertToFahrenheit', () => {
|
||||
test('works', () => {
|
||||
expect(convertToFahrenheit(0)).toEqual(32);
|
||||
});
|
||||
test('rounds to 1 decimal', () => {
|
||||
expect(convertToFahrenheit(73.2)).toEqual(163.8);
|
||||
});
|
||||
test('works with negatives', () => {
|
||||
expect(convertToFahrenheit(-10)).toEqual(14);
|
||||
});
|
||||
});
|
|
@ -1,11 +0,0 @@
|
|||
const convertToCelsius = function() {
|
||||
};
|
||||
|
||||
const convertToFahrenheit = function() {
|
||||
};
|
||||
|
||||
// Do not edit below this line
|
||||
module.exports = {
|
||||
convertToCelsius,
|
||||
convertToFahrenheit
|
||||
};
|
|
@ -1,33 +0,0 @@
|
|||
const add = function() {
|
||||
|
||||
};
|
||||
|
||||
const subtract = function() {
|
||||
|
||||
};
|
||||
|
||||
const sum = function() {
|
||||
|
||||
};
|
||||
|
||||
const multiply = function() {
|
||||
|
||||
};
|
||||
|
||||
const power = function() {
|
||||
|
||||
};
|
||||
|
||||
const factorial = function() {
|
||||
|
||||
};
|
||||
|
||||
// Do not edit below this line
|
||||
module.exports = {
|
||||
add,
|
||||
subtract,
|
||||
sum,
|
||||
multiply,
|
||||
power,
|
||||
factorial
|
||||
};
|
|
@ -1,77 +0,0 @@
|
|||
const calculator = require('./calculator');
|
||||
|
||||
describe('add', () => {
|
||||
test('adds 0 and 0', () => {
|
||||
expect(calculator.add(0, 0)).toBe(0);
|
||||
});
|
||||
|
||||
test.skip('adds 2 and 2', () => {
|
||||
expect(calculator.add(2, 2)).toBe(4);
|
||||
});
|
||||
|
||||
test.skip('adds positive numbers', () => {
|
||||
expect(calculator.add(2, 6)).toBe(8);
|
||||
});
|
||||
});
|
||||
|
||||
describe('subtract', () => {
|
||||
test.skip('subtracts numbers', () => {
|
||||
expect(calculator.subtract(10, 4)).toBe(6);
|
||||
});
|
||||
});
|
||||
|
||||
describe('sum', () => {
|
||||
test.skip('computes the sum of an empty array', () => {
|
||||
expect(calculator.sum([])).toBe(0);
|
||||
});
|
||||
|
||||
test.skip('computes the sum of an array of one number', () => {
|
||||
expect(calculator.sum([7])).toBe(7);
|
||||
});
|
||||
|
||||
test.skip('computes the sum of an array of two numbers', () => {
|
||||
expect(calculator.sum([7, 11])).toBe(18);
|
||||
});
|
||||
|
||||
test.skip('computes the sum of an array of many numbers', () => {
|
||||
expect(calculator.sum([1, 3, 5, 7, 9])).toBe(25);
|
||||
});
|
||||
});
|
||||
|
||||
describe('multiply', () => {
|
||||
test.skip('multiplies two numbers', () => {
|
||||
expect(calculator.multiply([2, 4])).toBe(8);
|
||||
});
|
||||
|
||||
test.skip('multiplies several numbers', () => {
|
||||
expect(calculator.multiply([2, 4, 6, 8, 10, 12, 14])).toBe(645120);
|
||||
});
|
||||
});
|
||||
|
||||
describe('power', () => {
|
||||
test.skip('raises one number to the power of another number', () => {
|
||||
expect(calculator.power(4, 3)).toBe(64); // 4 to third power is 64
|
||||
});
|
||||
});
|
||||
|
||||
describe('factorial', () => {
|
||||
test.skip('computes the factorial of 0', () => {
|
||||
expect(calculator.factorial(0)).toBe(1); // 0! = 1
|
||||
});
|
||||
|
||||
test.skip('computes the factorial of 1', () => {
|
||||
expect(calculator.factorial(1)).toBe(1);
|
||||
});
|
||||
|
||||
test.skip('computes the factorial of 2', () => {
|
||||
expect(calculator.factorial(2)).toBe(2);
|
||||
});
|
||||
|
||||
test.skip('computes the factorial of 5', () => {
|
||||
expect(calculator.factorial(5)).toBe(120);
|
||||
});
|
||||
|
||||
test.skip('computes the factorial of 10', () => {
|
||||
expect(calculator.factorial(10)).toBe(3628800);
|
||||
});
|
||||
});
|
|
@ -1,77 +0,0 @@
|
|||
const calculator = require('./calculator-solution');
|
||||
|
||||
describe('add', () => {
|
||||
test('adds 0 and 0', () => {
|
||||
expect(calculator.add(0, 0)).toBe(0);
|
||||
});
|
||||
|
||||
test('adds 2 and 2', () => {
|
||||
expect(calculator.add(2, 2)).toBe(4);
|
||||
});
|
||||
|
||||
test('adds positive numbers', () => {
|
||||
expect(calculator.add(2, 6)).toBe(8);
|
||||
});
|
||||
});
|
||||
|
||||
describe('subtract', () => {
|
||||
test('subtracts numbers', () => {
|
||||
expect(calculator.subtract(10, 4)).toBe(6);
|
||||
});
|
||||
});
|
||||
|
||||
describe('sum', () => {
|
||||
test('computes the sum of an empty array', () => {
|
||||
expect(calculator.sum([])).toBe(0);
|
||||
});
|
||||
|
||||
test('computes the sum of an array of one number', () => {
|
||||
expect(calculator.sum([7])).toBe(7);
|
||||
});
|
||||
|
||||
test('computes the sum of an array of two numbers', () => {
|
||||
expect(calculator.sum([7, 11])).toBe(18);
|
||||
});
|
||||
|
||||
test('computes the sum of an array of many numbers', () => {
|
||||
expect(calculator.sum([1, 3, 5, 7, 9])).toBe(25);
|
||||
});
|
||||
});
|
||||
|
||||
describe('multiply', () => {
|
||||
test('multiplies two numbers', () => {
|
||||
expect(calculator.multiply([2, 4])).toBe(8);
|
||||
});
|
||||
|
||||
test('multiplies several numbers', () => {
|
||||
expect(calculator.multiply([2, 4, 6, 8, 10, 12, 14])).toBe(645120);
|
||||
});
|
||||
});
|
||||
|
||||
describe('power', () => {
|
||||
test('raises one number to the power of another number', () => {
|
||||
expect(calculator.power(4, 3)).toBe(64); // 4 to third power is 64
|
||||
});
|
||||
});
|
||||
|
||||
describe('factorial', () => {
|
||||
test('computes the factorial of 0', () => {
|
||||
expect(calculator.factorial(0)).toBe(1); // 0! = 1
|
||||
});
|
||||
|
||||
test('computes the factorial of 1', () => {
|
||||
expect(calculator.factorial(1)).toBe(1);
|
||||
});
|
||||
|
||||
test('computes the factorial of 2', () => {
|
||||
expect(calculator.factorial(2)).toBe(2);
|
||||
});
|
||||
|
||||
test('computes the factorial of 5', () => {
|
||||
expect(calculator.factorial(5)).toBe(120);
|
||||
});
|
||||
|
||||
test('computes the factorial of 10', () => {
|
||||
expect(calculator.factorial(10)).toBe(3628800);
|
||||
});
|
||||
});
|
|
@ -1,6 +0,0 @@
|
|||
const palindromes = function () {
|
||||
|
||||
};
|
||||
|
||||
// Do not edit below this line
|
||||
module.exports = palindromes;
|
|
@ -1,6 +0,0 @@
|
|||
const palindromes = function (string) {
|
||||
const processedString = string.toLowerCase().replace(/[^a-z0-9]/g, "");
|
||||
return processedString.split("").reverse().join("") == processedString;
|
||||
};
|
||||
|
||||
module.exports = palindromes;
|
|
@ -1,30 +0,0 @@
|
|||
const palindromes = require('./palindromes-solution');
|
||||
|
||||
describe('palindromes', () => {
|
||||
test('works with single words', () => {
|
||||
expect(palindromes('racecar')).toBe(true);
|
||||
});
|
||||
test('works with punctuation ', () => {
|
||||
expect(palindromes('racecar!')).toBe(true);
|
||||
});
|
||||
test('works with upper-case letters ', () => {
|
||||
expect(palindromes('Racecar!')).toBe(true);
|
||||
});
|
||||
test('works with multiple words', () => {
|
||||
expect(palindromes('A car, a man, a maraca.')).toBe(true);
|
||||
});
|
||||
test('works with multiple words', () => {
|
||||
expect(palindromes('Animal loots foliated detail of stool lamina.')).toBe(
|
||||
true
|
||||
);
|
||||
});
|
||||
test("doesn't just always return true", () => {
|
||||
expect(palindromes('ZZZZ car, a man, a maraca.')).toBe(false);
|
||||
});
|
||||
test('works with numbers in a string', () => {
|
||||
expect(palindromes('rac3e3car')).toBe(true);
|
||||
});
|
||||
test('works with unevenly spaced numbers in a string', () => {
|
||||
expect(palindromes('r3ace3car')).toBe(false);
|
||||
});
|
||||
});
|
|
@ -1,12 +0,0 @@
|
|||
# Exercise 10 - Fibonacci
|
||||
|
||||
Create a function that returns a specific member of the Fibonacci sequence:
|
||||
|
||||
> A series of numbers in which each number ( Fibonacci number ) is the sum of the two preceding numbers.
|
||||
> In this exercise, the Fibonacci sequence used is 1, 1, 2, 3, 5, 8, etc.
|
||||
> To learn more about Fibonacci sequences, go to: https://en.wikipedia.org/wiki/Fibonacci_sequence
|
||||
|
||||
```javascript
|
||||
fibonacci(4); // returns the 4th member of the series: 3 (1, 1, 2, 3)
|
||||
fibonacci(6); // returns 8
|
||||
```
|
|
@ -1,6 +0,0 @@
|
|||
const fibonacci = function() {
|
||||
|
||||
};
|
||||
|
||||
// Do not edit below this line
|
||||
module.exports = fibonacci;
|
|
@ -1,34 +0,0 @@
|
|||
const fibonacci = function(countArg) {
|
||||
// checks argument's type and makes sure we use
|
||||
// a number throughout rest of function.
|
||||
let count
|
||||
if (typeof countArg !== 'number') {
|
||||
count = parseInt(countArg)
|
||||
} else {
|
||||
count = countArg
|
||||
}
|
||||
|
||||
if (count < 0) return "OOPS";
|
||||
if (count == 0) return 0;
|
||||
|
||||
let firstPrev = 1;
|
||||
let secondPrev = 0;
|
||||
|
||||
for (let i = 2; i <= count; i++) {
|
||||
let current = firstPrev + secondPrev;
|
||||
secondPrev = firstPrev;
|
||||
firstPrev = current;
|
||||
}
|
||||
|
||||
return firstPrev;
|
||||
|
||||
};
|
||||
|
||||
// Another way to do it is by using an iterative approach with an array containing two values, 0 and 1.
|
||||
// const fib = [0, 1];
|
||||
// for (let i = 2; i <= count; i++) {
|
||||
// fib[i] = fib[i - 1] + fib[i - 2];
|
||||
// }
|
||||
// return fib[count];
|
||||
|
||||
module.exports = fibonacci;
|
|
@ -1,37 +0,0 @@
|
|||
const fibonacci = require('./fibonacci-solution')
|
||||
|
||||
describe('fibonacci', () => {
|
||||
test('4th fibonacci number is 3', () => {
|
||||
expect(fibonacci(4)).toBe(3);
|
||||
});
|
||||
test('6th fibonacci number is 8', () => {
|
||||
expect(fibonacci(6)).toBe(8);
|
||||
});
|
||||
test('10th fibonacci number is 55', () => {
|
||||
expect(fibonacci(10)).toBe(55);
|
||||
});
|
||||
test('15th fibonacci number is 610', () => {
|
||||
expect(fibonacci(15)).toBe(610);
|
||||
});
|
||||
test('25th fibonacci number is 75025', () => {
|
||||
expect(fibonacci(25)).toBe(75025);
|
||||
});
|
||||
test('0th fibonacci number is 0', () => {
|
||||
expect(fibonacci(0)).toBe(0);
|
||||
});
|
||||
test('doesn\'t accept negatives', () => {
|
||||
expect(fibonacci(-25)).toBe("OOPS");
|
||||
});
|
||||
test('DOES accept strings', () => {
|
||||
expect(fibonacci("0")).toBe(0);
|
||||
});
|
||||
test('DOES accept strings', () => {
|
||||
expect(fibonacci("1")).toBe(1);
|
||||
});
|
||||
test('DOES accept strings', () => {
|
||||
expect(fibonacci("2")).toBe(1);
|
||||
});
|
||||
test('DOES accept strings', () => {
|
||||
expect(fibonacci("8")).toBe(21);
|
||||
});
|
||||
});
|
|
@ -1,6 +0,0 @@
|
|||
const getTheTitles = function() {
|
||||
|
||||
};
|
||||
|
||||
// Do not edit below this line
|
||||
module.exports = getTheTitles;
|
|
@ -1,5 +0,0 @@
|
|||
const getTheTitles = function (array) {
|
||||
return array.map((book) => book.title);
|
||||
};
|
||||
|
||||
module.exports = getTheTitles;
|
|
@ -1,18 +0,0 @@
|
|||
const getTheTitles = require('./getTheTitles-solution');
|
||||
|
||||
describe('getTheTitles', () => {
|
||||
const books = [
|
||||
{
|
||||
title: 'Book',
|
||||
author: 'Name',
|
||||
},
|
||||
{
|
||||
title: 'Book2',
|
||||
author: 'Name2',
|
||||
},
|
||||
];
|
||||
|
||||
test('gets titles', () => {
|
||||
expect(getTheTitles(books)).toEqual(['Book', 'Book2']);
|
||||
});
|
||||
});
|
|
@ -1,6 +0,0 @@
|
|||
const findTheOldest = function() {
|
||||
|
||||
};
|
||||
|
||||
// Do not edit below this line
|
||||
module.exports = findTheOldest;
|
|
@ -1,62 +0,0 @@
|
|||
const findTheOldest = require('./findTheOldest-solution');
|
||||
|
||||
describe('findTheOldest', () => {
|
||||
test('finds the oldest person!', () => {
|
||||
const people = [
|
||||
{
|
||||
name: 'Carly',
|
||||
yearOfBirth: 1942,
|
||||
yearOfDeath: 1970,
|
||||
},
|
||||
{
|
||||
name: 'Ray',
|
||||
yearOfBirth: 1962,
|
||||
yearOfDeath: 2011,
|
||||
},
|
||||
{
|
||||
name: 'Jane',
|
||||
yearOfBirth: 1912,
|
||||
yearOfDeath: 1941,
|
||||
},
|
||||
];
|
||||
expect(findTheOldest(people).name).toBe('Ray');
|
||||
});
|
||||
test('finds the oldest person if someone is still living', () => {
|
||||
const people = [
|
||||
{
|
||||
name: 'Carly',
|
||||
yearOfBirth: 2018,
|
||||
},
|
||||
{
|
||||
name: 'Ray',
|
||||
yearOfBirth: 1962,
|
||||
yearOfDeath: 2011,
|
||||
},
|
||||
{
|
||||
name: 'Jane',
|
||||
yearOfBirth: 1912,
|
||||
yearOfDeath: 1941,
|
||||
},
|
||||
];
|
||||
expect(findTheOldest(people).name).toBe('Ray');
|
||||
});
|
||||
test('finds the oldest person if the OLDEST is still living', () => {
|
||||
const people = [
|
||||
{
|
||||
name: 'Carly',
|
||||
yearOfBirth: 1066,
|
||||
},
|
||||
{
|
||||
name: 'Ray',
|
||||
yearOfBirth: 1962,
|
||||
yearOfDeath: 2011,
|
||||
},
|
||||
{
|
||||
name: 'Jane',
|
||||
yearOfBirth: 1912,
|
||||
yearOfDeath: 1941,
|
||||
},
|
||||
];
|
||||
expect(findTheOldest(people).name).toBe('Carly');
|
||||
});
|
||||
});
|
21
LICENSE
21
LICENSE
|
@ -1,21 +0,0 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2023 The Odin Project
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
43
README.md
43
README.md
|
@ -1,38 +1,27 @@
|
|||
# JavaScript Exercises
|
||||
These are a series of JavaScript exercises intended to be used alongside the curriculum at 'The Odin Project'. They start simple and easy but get more complex and involved as you progress through them.
|
||||
|
||||
These JavaScript exercises are intended to complement the JavaScript content on The Odin Project (TOP). They should only be done when instructed during the course of the curriculum.
|
||||
There will eventually be a suggested order of completion, but at this time since we are still in the process of creating more exercises the order is subject to change and has not yet been specified. However, there are a few exercises that make a good "starting point". Feel free to at least start with these:
|
||||
|
||||
**Note:** The `generator-exercise` file is not actually an exercise; it is a script that generates exercises. It was created to help efficiently write these exercises.
|
||||
|
||||
## Contributing
|
||||
|
||||
If you have a suggestion to improve an exercise, an idea for a new exercise, or notice an issue with an exercise, please feel free to open an issue after thoroughly reading our [contributing guide](https://github.com/TheOdinProject/.github/blob/main/CONTRIBUTING.md).
|
||||
1. Hello World
|
||||
2. Repeat String
|
||||
3. Reverse String
|
||||
|
||||
## How To Use These Exercises
|
||||
Before you start you should have a few things installed on your machine:
|
||||
1. **NPM**. To check if you have NPM installed, type `npm --version` in your terminal. If you get back `Command 'npm' not found, but can be installed with:`, do NOT follow the instructions in the terminal to install with `apt-get`. (This causes permission issues.) Instead, install Node with NVM by following the instructions [here](https://github.com/TheOdinProject/curriculum/blob/master/foundations/installations/installing_node.md).
|
||||
2. **A copy of this repository**. Copies of repositories on your machine are called clones. If you need help cloning, you can learn how [here](https://docs.github.com/en/github/creating-cloning-and-archiving-repositories/cloning-a-repository).
|
||||
3. **Jest**. After cloning this repository to your local machine, go into the newly created directory (`cd javascript-exercises`) and run `npm install`. This will install Jest and set up the testing platform based on our preconfigured settings.
|
||||
|
||||
|
||||
1. Fork and clone this repository. To learn how to fork a repository, see the GitHub documentation on how to [fork a repo](https://docs.github.com/en/get-started/quickstart/fork-a-repo).
|
||||
- Copies of repositories on your machine are called clones. If you need help cloning to your local environment you can learn how from the GitHub documentation on [cloning a repository](https://docs.github.com/en/github/creating-cloning-and-archiving-repositories/cloning-a-repository-from-github/cloning-a-repository).
|
||||
2. Before you start working on any exercises, you should first ensure you have the following installed:
|
||||
- **NPM**. You should have installed NPM already in our [Installing Node.js](https://www.theodinproject.com/paths/foundations/courses/foundations/lessons/installing-node-js) lesson. Just in case you need to check, type `npm --version` in your terminal. If you get back `Command 'npm' not found, but can be installed with:`, **do not follow the instructions in the terminal** to install with `apt-get` as this causes permission issues. Instead, go back to the installation lesson and install Node with NVM by following the instructions there.
|
||||
- **Jest**. After cloning this repository to your local machine and installing NPM, go into the newly created directory (`cd javascript-exercises`) and run `npm install`. This will install Jest and set up the testing platform based on our preconfigured settings. (Note: if you get warnings that packages are out of date or contain vulnerabilities, you can safely ignore them for these exercises.)
|
||||
|
||||
3. Each exercise includes the following:
|
||||
|
||||
- A markdown file with a description of the task, an empty (or mostly empty) JavaScript file, and a set of tests.
|
||||
- A `solutions` directory that contains a solution and the same test file with all of the tests unskipped.
|
||||
|
||||
To complete an exercise, you'll need to go to the exercise directory with `cd exerciseName` in the terminal and run `npm test exerciseName.spec.js`. This should run the test file and show you the output. When you first run a test, it will fail. This is by design! You must open the exercise file and write the code needed to get the test to pass.
|
||||
4. Some of the exercises have test conditions defined in their spec file as `test.skip` compared to `test`. This is purposeful. After you pass one `test`, you will change the next `test.skip` to `test` and test your code again. You'll do this until all conditions are satisfied. **All tests must pass at the same time**, and you should not have any `test.skip` instances by the time you finish an exercise.
|
||||
5. Once you successfully finish an exercise, check the `solutions` directory within each exercise to compare it with yours.
|
||||
- You should not be checking the solution for an exercise until you finish it!
|
||||
- Keep in mind that TOP's solution is not the only solution. Generally as long as all of the tests pass, your solution should be fine.
|
||||
6. Do not submit your solutions to this repo, as any PRs that do so will be closed without merging.
|
||||
Each exercise includes 3 files: a markdown file with a description of the task, an empty (or mostly empty) JavaScript file, and a set of tests. To complete an exercise, you'll need to go to the exercise directory with `cd exerciseName` in the terminal and run `npm test exerciseName.spec.js`. This should run the test file and show you the output. When you first run a test, it will fail. This is by design! You must open the exercise file and write the code needed to get the test to pass. Some of the exercises have test conditions defined in their spec file that are defined as 'test.skip' compared to 'test'. This is purposeful. After you pass your first 'test', you will change the next 'test.skip' to an 'test' and test your code again. You'll do this until all conditions are satisfied. **ALL TESTS MUST PASS AT THE SAME TIME.**
|
||||
|
||||
**Note**: Due to the way Jest handles failed tests, it may return an exit code of 1 if any tests fail. NPM will interpret this as an error and you may see some `npm ERR!` messages after Jest runs. You can ignore these, or run your test with `npm test exerciseName.spec.js --silent` to supress the errors.
|
||||
|
||||
The first exercise, `helloWorld`, will walk you through the process in-depth.
|
||||
|
||||
## Debugging
|
||||
## Solutions
|
||||
|
||||
To debug functions, you can run the tests in the Visual Studio Code debugger terminal. You can open this by clicking the "Run and Debug" icon on the left or pressing <kbd>Ctrl</kbd> + <kbd>Shift</kbd> + <kbd>D</kbd>, then clicking JavaScript Debug Terminal. You will be able to set breakpoints as you would in the Chrome DevTools debugger. You can run `npm test exerciseName.spec.js` to then execute your code up until your breakpoint and step through your code as necessary. **NOTE**: To take advantage of the debugger, you **MUST** run the script in the debugger terminal, not the bash or zsh terminal.
|
||||
Solutions for these exercises can be found in this repo on the 'solutions' branch.
|
||||
|
||||
## A quick note!
|
||||
|
||||
The exercise `generator-exercise` is not actually an exercise; it is a script that generates exercises. It was created to help efficiently write these exercises.
|
||||
|
|
|
@ -1,6 +0,0 @@
|
|||
const caesar = function() {
|
||||
|
||||
};
|
||||
|
||||
// Do not edit below this line
|
||||
module.exports = caesar;
|
|
@ -1,26 +0,0 @@
|
|||
const caesar = function (string, shift) {
|
||||
return string
|
||||
.split("")
|
||||
.map((char) => shiftChar(char, shift))
|
||||
.join("");
|
||||
};
|
||||
|
||||
const codeSet = (code) => (code < 97 ? 65 : 97);
|
||||
|
||||
// this function is just a fancy way of doing % so that it works with negative numbers
|
||||
// see this link for details:
|
||||
// https://stackoverflow.com/questions/4467539/javascript-modulo-gives-a-negative-result-for-negative-numbers
|
||||
const mod = (n, m) => ((n % m) + m) % m;
|
||||
|
||||
const shiftChar = (char, shift) => {
|
||||
const code = char.charCodeAt();
|
||||
|
||||
if ((code >= 65 && code <= 90) || (code >= 97 && code <= 122)) {
|
||||
return String.fromCharCode(
|
||||
mod(code + shift - codeSet(code), 26) + codeSet(code)
|
||||
);
|
||||
}
|
||||
return char;
|
||||
};
|
||||
|
||||
module.exports = caesar;
|
|
@ -1,23 +0,0 @@
|
|||
const caesar = require('./caesar-solution');
|
||||
|
||||
test('works with single letters', () => {
|
||||
expect(caesar('A', 1)).toBe('B');
|
||||
});
|
||||
test('works with words', () => {
|
||||
expect(caesar('Aaa', 1)).toBe('Bbb');
|
||||
});
|
||||
test('works with phrases', () => {
|
||||
expect(caesar('Hello, World!', 5)).toBe('Mjqqt, Btwqi!');
|
||||
});
|
||||
test('works with negative shift', () => {
|
||||
expect(caesar('Mjqqt, Btwqi!', -5)).toBe('Hello, World!');
|
||||
});
|
||||
test('wraps', () => {
|
||||
expect(caesar('Z', 1)).toBe('A');
|
||||
});
|
||||
test('works with large shift factors', () => {
|
||||
expect(caesar('Hello, World!', 75)).toBe('Ebiil, Tloia!');
|
||||
});
|
||||
test('works with large negative shift factors', () => {
|
||||
expect(caesar('Hello, World!', -29)).toBe('Ebiil, Tloia!');
|
||||
});
|
|
@ -1,6 +0,0 @@
|
|||
function pigLatin(string) {
|
||||
|
||||
};
|
||||
|
||||
// Do not edit below this line
|
||||
module.exports = pigLatin;
|
|
@ -1,21 +0,0 @@
|
|||
const pigLatin = function (string) {
|
||||
return string
|
||||
.split(" ")
|
||||
.map((word) => {
|
||||
const index = firstVowelIndex(word);
|
||||
const beginning = word.slice(0, index);
|
||||
const ending = word.slice(index);
|
||||
return `${ending}${beginning}ay`;
|
||||
})
|
||||
.join(" ");
|
||||
};
|
||||
|
||||
const firstVowelIndex = function (string) {
|
||||
const vowels = string.match(/[aeiou]/g);
|
||||
if (vowels[0] == "u" && string[string.indexOf(vowels[0]) - 1] == "q") {
|
||||
return string.indexOf(vowels[1]);
|
||||
}
|
||||
return string.indexOf(vowels[0]);
|
||||
};
|
||||
|
||||
module.exports = pigLatin;
|
|
@ -1,56 +0,0 @@
|
|||
const pigLatin = require('./pigLatin-solution');
|
||||
|
||||
// Topics
|
||||
|
||||
// * modules
|
||||
// * strings
|
||||
|
||||
// Pig Latin
|
||||
|
||||
// Pig Latin is a made-up children's language that's intended to be confusing. test obeys a few simple rules (below) but when test's spoken quickly test's really difficult for non-children (and non-native speakers) to understand.
|
||||
|
||||
// Rule 1: If a word begins with a vowel sound, add an "ay" sound to the end of the word.
|
||||
|
||||
// Rule 2: If a word begins with a consonant sound, move test to the end of the word, and then add an "ay" sound to the end of the word.
|
||||
|
||||
// (There are a few more rules for edge cases, and there are regional variants too, but that should be enough to understand the tests.)
|
||||
|
||||
// See https://en.wikipedia.org/wiki/Pig_Latin for more details.
|
||||
|
||||
describe('translate', () => {
|
||||
test('translates a word beginning with a vowel', () => {
|
||||
expect(pigLatin('apple')).toBe('appleay');
|
||||
});
|
||||
|
||||
test('translates a word beginning with a consonant', () => {
|
||||
expect(pigLatin('banana')).toBe('ananabay');
|
||||
});
|
||||
|
||||
test('translates a word beginning with two consonants', () => {
|
||||
expect(pigLatin('cherry')).toBe('errychay');
|
||||
});
|
||||
|
||||
test('translates two words', () => {
|
||||
expect(pigLatin('eat pie')).toBe('eatay iepay');
|
||||
});
|
||||
|
||||
test('translates a word beginning with three consonants', () => {
|
||||
expect(pigLatin('three')).toBe('eethray');
|
||||
});
|
||||
|
||||
test('counts "sch" as a single phoneme', () => {
|
||||
expect(pigLatin('school')).toBe('oolschay');
|
||||
});
|
||||
|
||||
test('counts "qu" as a single phoneme', () => {
|
||||
expect(pigLatin('quiet')).toBe('ietquay');
|
||||
});
|
||||
|
||||
test('counts "qu" as a consonant even when its preceded by a consonant', () => {
|
||||
expect(pigLatin('square')).toBe('aresquay');
|
||||
});
|
||||
|
||||
test('translates many words', () => {
|
||||
expect(pigLatin('the quick brown fox')).toBe('ethay ickquay ownbray oxfay');
|
||||
});
|
||||
});
|
|
@ -1,6 +0,0 @@
|
|||
const snakeCase = function() {
|
||||
|
||||
};
|
||||
|
||||
// Do not edit below this line
|
||||
module.exports = snakeCase;
|
|
@ -1,26 +0,0 @@
|
|||
const snakeCase = require('./snakeCase-solution');
|
||||
|
||||
describe('snakeCase', () => {
|
||||
test('works with simple lowercased phrases', () => {
|
||||
expect(snakeCase('hello world')).toEqual('hello_world');
|
||||
});
|
||||
test('works with Caps and punctuation', () => {
|
||||
expect(snakeCase('Hello, World???')).toEqual('hello_world');
|
||||
});
|
||||
test('works with longer phrases', () => {
|
||||
expect(snakeCase('This is the song that never ends....')).toEqual(
|
||||
'this_is_the_song_that_never_ends'
|
||||
);
|
||||
});
|
||||
test('works with camel case', () => {
|
||||
expect(snakeCase('snakeCase')).toEqual('snake_case');
|
||||
});
|
||||
test('works with kebab case', () => {
|
||||
expect(snakeCase('snake-case')).toEqual('snake_case');
|
||||
});
|
||||
test('works with WTF case', () => {
|
||||
expect(snakeCase('SnAkE..CaSe..Is..AwEsOmE')).toEqual(
|
||||
'snake_case_is_awesome'
|
||||
);
|
||||
});
|
||||
});
|
Binary file not shown.
|
@ -14,7 +14,7 @@ caesar('A', 1) // simply shifts the letter by 1: returns 'B'
|
|||
|
||||
the cipher should retain capitalization:
|
||||
```javascript
|
||||
caesar('Hey', 5) // returns 'Mjd'
|
||||
caesar('Hey', 5) // returns 'Mjd;
|
||||
```
|
||||
|
||||
should _not_ shift punctuation:
|
|
@ -0,0 +1,29 @@
|
|||
const caesar = function(string, shiftValue) {
|
||||
return string
|
||||
.split("")
|
||||
.map(char => shift(char, shiftValue))
|
||||
.join("");
|
||||
};
|
||||
|
||||
const isLetter = code => {
|
||||
return (code >= 65 && code <= 90) || (code >= 97 && code <= 122);
|
||||
}
|
||||
|
||||
// This function implements a version of the modulo operator
|
||||
// that returns the smallest positive remainder even for negative inputs.
|
||||
// See this link for details:
|
||||
// https://stackoverflow.com/questions/4467539/javascript-modulo-gives-a-negative-result-for-negative-numbers
|
||||
const mod = (n, m) => (n % m + m) % m;
|
||||
|
||||
const shift = (char, shiftValue) => {
|
||||
const code = char.charCodeAt();
|
||||
|
||||
if (isLetter(code)) {
|
||||
const base = code < 97 ? 65 : 97;
|
||||
const shiftedCode = mod(code + shiftValue - base, 26) + base;
|
||||
return String.fromCharCode(shiftedCode);
|
||||
}
|
||||
return char;
|
||||
};
|
||||
|
||||
module.exports = caesar;
|
|
@ -1,24 +1,26 @@
|
|||
const add = function (a, b) {
|
||||
const add = function(a, b) {
|
||||
return a + b;
|
||||
};
|
||||
|
||||
const subtract = function (a, b) {
|
||||
const subtract = function(a, b) {
|
||||
return a - b;
|
||||
};
|
||||
|
||||
const sum = function (array) {
|
||||
const sum = function(array) {
|
||||
return array.reduce((total, current) => total + current, 0);
|
||||
};
|
||||
|
||||
const multiply = function (array) {
|
||||
return array.reduce((product, current) => product * current)
|
||||
const multiply = function(array) {
|
||||
return array.length
|
||||
? array.reduce((accumulator, nextItem) => accumulator * nextItem)
|
||||
: 0;
|
||||
};
|
||||
|
||||
const power = function (a, b) {
|
||||
const power = function(a, b) {
|
||||
return Math.pow(a, b);
|
||||
};
|
||||
|
||||
const factorial = function (n) {
|
||||
const factorial = function(n) {
|
||||
if (n === 0) return 1;
|
||||
let product = 1;
|
||||
for (let i = n; i > 0; i--) {
|
||||
|
@ -29,11 +31,11 @@ const factorial = function (n) {
|
|||
|
||||
// This is another implementation of Factorial that uses recursion
|
||||
// THANKS to @ThirtyThreeB!
|
||||
const recursiveFactorial = function (n) {
|
||||
const recursiveFactorial = function(n) {
|
||||
if (n === 0) {
|
||||
return 1;
|
||||
}
|
||||
return n * recursiveFactorial(n - 1);
|
||||
return n * recursiveFactorial (n-1);
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
|
@ -42,5 +44,5 @@ module.exports = {
|
|||
sum,
|
||||
multiply,
|
||||
power,
|
||||
factorial,
|
||||
factorial
|
||||
};
|
|
@ -0,0 +1,77 @@
|
|||
const calculator = require('./calculator');
|
||||
|
||||
describe('add', () => {
|
||||
test('adds 0 and 0', () => {
|
||||
expect(calculator.add(0,0)).toBe(0);
|
||||
});
|
||||
|
||||
test.skip('adds 2 and 2', () => {
|
||||
expect(calculator.add(2,2)).toBe(4);
|
||||
});
|
||||
|
||||
test.skip('adds positive numbers', () => {
|
||||
expect(calculator.add(2,6)).toBe(8);
|
||||
});
|
||||
});
|
||||
|
||||
describe('subtract', () => {
|
||||
test.skip('subtracts numbers', () => {
|
||||
expect(calculator.subtract(10,4)).toBe(6);
|
||||
});
|
||||
});
|
||||
|
||||
describe('sum', () => {
|
||||
test.skip('computes the sum of an empty array', () => {
|
||||
expect(calculator.sum([])).toBe(0);
|
||||
});
|
||||
|
||||
test.skip('computes the sum of an array of one number', () => {
|
||||
expect(calculator.sum([7])).toBe(7);
|
||||
});
|
||||
|
||||
test.skip('computes the sum of an array of two numbers', () => {
|
||||
expect(calculator.sum([7,11])).toBe(18);
|
||||
});
|
||||
|
||||
test.skip('computes the sum of an array of many numbers', () => {
|
||||
expect(calculator.sum([1,3,5,7,9])).toBe(25);
|
||||
});
|
||||
});
|
||||
|
||||
describe('multiply', () => {
|
||||
test.skip('multiplies two numbers', () => {
|
||||
expect(calculator.multiply([2,4])).toBe(8);
|
||||
});
|
||||
|
||||
test.skip('multiplies several numbers', () => {
|
||||
expect(calculator.multiply([2,4,6,8,10,12,14])).toBe(645120);
|
||||
});
|
||||
});
|
||||
|
||||
describe('power', () => {
|
||||
test.skip('raises one number to the power of another number', () => {
|
||||
expect(calculator.power(4,3)).toBe(64); // 4 to third power is 64
|
||||
});
|
||||
});
|
||||
|
||||
describe('factorial', () => {
|
||||
test.skip('computes the factorial of 0', () => {
|
||||
expect(calculator.factorial(0)).toBe(1); // 0! = 1
|
||||
});
|
||||
|
||||
test.skip('computes the factorial of 1', () => {
|
||||
expect(calculator.factorial(1)).toBe(1);
|
||||
});
|
||||
|
||||
test.skip('computes the factorial of 2', () => {
|
||||
expect(calculator.factorial(2)).toBe(2);
|
||||
});
|
||||
|
||||
test.skip('computes the factorial of 5', () => {
|
||||
expect(calculator.factorial(5)).toBe(120);
|
||||
});
|
||||
|
||||
test.skip('computes the factorial of 10', () => {
|
||||
expect(calculator.factorial(10)).toBe(3628800);
|
||||
});
|
||||
});
|
|
@ -0,0 +1,10 @@
|
|||
# Exercise 10 - Fibonacci
|
||||
|
||||
Create a function that returns a specific member of the Fibonacci sequence:
|
||||
|
||||
> A series of numbers in which each number ( Fibonacci number ) is the sum of the two preceding numbers. The simplest is the series 1, 1, 2, 3, 5, 8, etc.
|
||||
|
||||
```javascript
|
||||
fibonacci(4) // returns the 4th member of the series: 3 (1, 1, 2, 3)
|
||||
fibonacci(6) // returns 8
|
||||
```
|
|
@ -0,0 +1,14 @@
|
|||
const fibonacci = function(count) {
|
||||
if (count < 0) return "OOPS";
|
||||
if (count === 0) return 0;
|
||||
let a = 0;
|
||||
let b = 1;
|
||||
for (let i = 1; i < count; i++) {
|
||||
const temp = b;
|
||||
b = a + b;
|
||||
a = temp;
|
||||
}
|
||||
return b;
|
||||
};
|
||||
|
||||
module.exports = fibonacci;
|
|
@ -16,15 +16,9 @@ describe('fibonacci', () => {
|
|||
test.skip('25th fibonacci number is 75025', () => {
|
||||
expect(fibonacci(25)).toBe(75025);
|
||||
});
|
||||
test.skip('0th fibonacci number is 0', () => {
|
||||
expect(fibonacci(0)).toBe(0);
|
||||
});
|
||||
test.skip('doesn\'t accept negatives', () => {
|
||||
expect(fibonacci(-25)).toBe("OOPS");
|
||||
});
|
||||
test.skip('DOES accept strings', () => {
|
||||
expect(fibonacci("0")).toBe(0);
|
||||
});
|
||||
test.skip('DOES accept strings', () => {
|
||||
expect(fibonacci("1")).toBe(1);
|
||||
});
|
|
@ -2,9 +2,7 @@
|
|||
|
||||
Given an array of objects representing people with a birth and death year, return the oldest person.
|
||||
|
||||
Now that you've reached the final exercise, you should be fairly comfortable getting the information you need from test case(s). Take a look at how the array of objects is constructed in this exercise's test cases to help you write your function.
|
||||
|
||||
## Hints
|
||||
- You should return the whole person object, but the tests mostly just check to make sure the name is correct.
|
||||
- This can be done with a couple of chained array methods, or by using `reduce`.
|
||||
- this can be done with a couple of chained array methods, or by using `reduce`.
|
||||
- One of the tests checks for people with no death-date.. use JavaScript's Date function to get their age as of today.
|
|
@ -1,15 +1,12 @@
|
|||
const findTheOldest = function (array) {
|
||||
const findTheOldest = function(array) {
|
||||
return array.reduce((oldest, currentPerson) => {
|
||||
const oldestAge = getAge(oldest.yearOfBirth, oldest.yearOfDeath);
|
||||
const currentAge = getAge(
|
||||
currentPerson.yearOfBirth,
|
||||
currentPerson.yearOfDeath
|
||||
);
|
||||
const currentAge = getAge(currentPerson.yearOfBirth, currentPerson.yearOfDeath);
|
||||
return oldestAge < currentAge ? currentPerson : oldest;
|
||||
});
|
||||
})
|
||||
};
|
||||
|
||||
const getAge = function (birth, death) {
|
||||
const getAge = function(birth, death) {
|
||||
if (!death) {
|
||||
death = new Date().getFullYear();
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
const findTheOldest = require('./findTheOldest')
|
||||
|
||||
describe('findTheOldest', () => {
|
||||
test('finds the person with the greatest age!', () => {
|
||||
test('finds the oldest person!', () => {
|
||||
const people = [
|
||||
{
|
||||
name: "Carly",
|
||||
|
@ -21,7 +21,7 @@ describe('findTheOldest', () => {
|
|||
]
|
||||
expect(findTheOldest(people).name).toBe('Ray');
|
||||
});
|
||||
test.skip('finds the person with the greatest age if someone is still living', () => {
|
||||
test.skip('finds the oldest person if someone is still living', () => {
|
||||
const people = [
|
||||
{
|
||||
name: "Carly",
|
||||
|
@ -40,7 +40,7 @@ describe('findTheOldest', () => {
|
|||
]
|
||||
expect(findTheOldest(people).name).toBe('Ray');
|
||||
});
|
||||
test.skip('finds the person with the greatest age if the OLDEST is still living', () => {
|
||||
test.skip('finds the oldest person if the OLDEST is still living', () => {
|
||||
const people = [
|
||||
{
|
||||
name: "Carly",
|
|
@ -50,15 +50,6 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"agent-base": {
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.3.0.tgz",
|
||||
"integrity": "sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"es6-promisify": "^5.0.0"
|
||||
}
|
||||
},
|
||||
"ajv": {
|
||||
"version": "4.11.8",
|
||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz",
|
||||
|
@ -491,12 +482,6 @@
|
|||
"integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=",
|
||||
"dev": true
|
||||
},
|
||||
"camelcase": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz",
|
||||
"integrity": "sha512-FxAv7HpHrXbh3aPo4o2qxHay2lkLY3x5Mw3KeE4KQE8ysVfziWeRZDwcjauvwBSGEC/nXUPzZy8zeh4HokqOnw==",
|
||||
"dev": true
|
||||
},
|
||||
"capture-stack-trace": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/capture-stack-trace/-/capture-stack-trace-1.0.0.tgz",
|
||||
|
@ -520,12 +505,6 @@
|
|||
"supports-color": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"chardet": {
|
||||
"version": "0.4.2",
|
||||
"resolved": "https://registry.npmjs.org/chardet/-/chardet-0.4.2.tgz",
|
||||
"integrity": "sha512-j/Toj7f1z98Hh2cYo2BVr85EpIRWqUi7rtRSGxh/cqUjqrnJe9l9UE7IUGd2vQ2p+kSHLkSzObQPZPLUC6TQwg==",
|
||||
"dev": true
|
||||
},
|
||||
"ci-info": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ci-info/-/ci-info-1.0.0.tgz",
|
||||
|
@ -567,48 +546,11 @@
|
|||
"colors": "1.0.3"
|
||||
}
|
||||
},
|
||||
"cli-table2": {
|
||||
"version": "0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/cli-table2/-/cli-table2-0.2.0.tgz",
|
||||
"integrity": "sha512-rNig1Ons+B0eTcophmN0nlbsROa7B3+Yfo1J3leU56awc8IuKDW3MLMv9gayl4zUnYaLGg8CrecKso+hSmUvUw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"colors": "^1.1.2",
|
||||
"lodash": "^3.10.1",
|
||||
"string-width": "^1.0.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"colors": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz",
|
||||
"integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"lodash": {
|
||||
"version": "3.10.1",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz",
|
||||
"integrity": "sha512-9mDDwqVIma6OZX79ZlDACZl8sBm0TEnkf99zV3iMA4GzkIT/9hiqP5mY0HoT1iNLCrKc/R1HByV+yJfRWVJryQ==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"cli-width": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.1.0.tgz",
|
||||
"integrity": "sha1-sjTKIJsp72b8UY2bmNWEewDt8Ao="
|
||||
},
|
||||
"cliui": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz",
|
||||
"integrity": "sha512-0yayqDxWQbqk3ojkYqUKqaAQ6AfNKeKWRNA8kR0WXzAsdHpP4BIaOmMAG87JGuO6qcobyW4GjxHd9PmhEd+T9w==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"string-width": "^1.0.1",
|
||||
"strip-ansi": "^3.0.1",
|
||||
"wrap-ansi": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"clone": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/clone/-/clone-2.1.1.tgz",
|
||||
|
@ -757,12 +699,6 @@
|
|||
"cssom": "0.3.x"
|
||||
}
|
||||
},
|
||||
"cvss": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/cvss/-/cvss-1.0.5.tgz",
|
||||
"integrity": "sha512-lfApnkcBoP+3viCUFOrqRmeqsyoIuiXouYg3Gt+1f3wsYzm1xDXnvyyMiPGoODFYWnoAl9LHPWWJH5zM6HaUoA==",
|
||||
"dev": true
|
||||
},
|
||||
"dargs": {
|
||||
"version": "5.1.0",
|
||||
"resolved": "https://registry.npmjs.org/dargs/-/dargs-5.1.0.tgz",
|
||||
|
@ -958,21 +894,6 @@
|
|||
"is-arrayish": "^0.2.1"
|
||||
}
|
||||
},
|
||||
"es6-promise": {
|
||||
"version": "4.2.8",
|
||||
"resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz",
|
||||
"integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==",
|
||||
"dev": true
|
||||
},
|
||||
"es6-promisify": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz",
|
||||
"integrity": "sha512-C+d6UdsYDk0lMebHNR4S2NybQMMngAOnOwYBQjTOiv0MkoJMP0Myw2mgpDLBcpfCmRLxyFqYhS/CfOENq4SJhQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"es6-promise": "^4.0.3"
|
||||
}
|
||||
},
|
||||
"escape-string-regexp": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
|
||||
|
@ -1300,21 +1221,6 @@
|
|||
"merge": "^1.1.3"
|
||||
}
|
||||
},
|
||||
"execa": {
|
||||
"version": "0.7.0",
|
||||
"resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz",
|
||||
"integrity": "sha512-RztN09XglpYI7aBBrJCPW95jEH7YF1UEPOoX9yDhUTPdp7mK+CQvnLTuD10BNXZ3byLTu2uehZ8EcKT/4CGiFw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"cross-spawn": "^5.0.1",
|
||||
"get-stream": "^3.0.0",
|
||||
"is-stream": "^1.1.0",
|
||||
"npm-run-path": "^2.0.0",
|
||||
"p-finally": "^1.0.0",
|
||||
"signal-exit": "^3.0.0",
|
||||
"strip-eof": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"exit-hook": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/exit-hook/-/exit-hook-1.1.1.tgz",
|
||||
|
@ -1796,33 +1702,6 @@
|
|||
"sshpk": "^1.7.0"
|
||||
}
|
||||
},
|
||||
"https-proxy-agent": {
|
||||
"version": "2.2.4",
|
||||
"resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz",
|
||||
"integrity": "sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"agent-base": "^4.3.0",
|
||||
"debug": "^3.1.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"debug": {
|
||||
"version": "3.2.7",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
|
||||
"integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ms": "^2.1.1"
|
||||
}
|
||||
},
|
||||
"ms": {
|
||||
"version": "2.1.3",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
||||
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"iconv-lite": {
|
||||
"version": "0.4.18",
|
||||
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.18.tgz",
|
||||
|
@ -3217,15 +3096,6 @@
|
|||
"tmpl": "1.0.x"
|
||||
}
|
||||
},
|
||||
"mem": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz",
|
||||
"integrity": "sha512-nOBDrc/wgpkd3X/JOhMqYR+/eLqlfLP4oQfoBA6QExIxEl+GU01oyEkwWyueyO8110pUKijtiHGhEmYoOn88oQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"mimic-fn": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"mem-fs": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/mem-fs/-/mem-fs-1.1.3.tgz",
|
||||
|
@ -3413,12 +3283,6 @@
|
|||
"which": "^1.2.12"
|
||||
}
|
||||
},
|
||||
"nodesecurity-npm-utils": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/nodesecurity-npm-utils/-/nodesecurity-npm-utils-6.0.0.tgz",
|
||||
"integrity": "sha512-NLRle1woNaT2orR6fue2jNqkhxDTktgJj3sZxvR/8kp21pvOY7Gwlx5wvo0H8ZVPqdgd2nE2ADB9wDu5Cl8zNg==",
|
||||
"dev": true
|
||||
},
|
||||
"normalize-package-data": {
|
||||
"version": "2.4.0",
|
||||
"resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz",
|
||||
|
@ -3439,234 +3303,340 @@
|
|||
"remove-trailing-separator": "^1.0.1"
|
||||
}
|
||||
},
|
||||
"npm-run-path": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz",
|
||||
"integrity": "sha512-lJxZYlT4DW/bRUtFh1MQIWqmLwQfAxnqWG4HhEdjMlkrJYnJn0Jrr2u3mgxqaWsdiBc76TYkTG/mhrnYTuzfHw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"path-key": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"nsp": {
|
||||
"version": "3.2.1",
|
||||
"resolved": "https://registry.npmjs.org/nsp/-/nsp-3.2.1.tgz",
|
||||
"integrity": "sha512-dLmGi7IGixJEHKetErIH460MYiYIzAoxuVsloZFu9e1p9U8K0yULx7YQ1+VzrjZbB+wqq67ES1SfOvKVb/qMDQ==",
|
||||
"version": "2.7.0",
|
||||
"resolved": "https://registry.npmjs.org/nsp/-/nsp-2.7.0.tgz",
|
||||
"integrity": "sha512-OeYnX8eKRWKk/mlVeRKvwoocWN4gQlj2tVxNXHttLdasidlP34wwjOV9J9w3C/LbwyYXMb+8zDylZF/7zgyEpA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"chalk": "^2.1.0",
|
||||
"cli-table2": "^0.2.0",
|
||||
"cvss": "^1.0.2",
|
||||
"https-proxy-agent": "^2.1.0",
|
||||
"inquirer": "^3.3.0",
|
||||
"nodesecurity-npm-utils": "^6.0.0",
|
||||
"semver": "^5.4.1",
|
||||
"wreck": "^12.5.1",
|
||||
"yargs": "^9.0.1"
|
||||
"chalk": "^1.1.1",
|
||||
"cli-table": "^0.3.1",
|
||||
"cvss": "^1.0.0",
|
||||
"https-proxy-agent": "^1.0.0",
|
||||
"joi": "^6.9.1",
|
||||
"nodesecurity-npm-utils": "^5.0.0",
|
||||
"path-is-absolute": "^1.0.0",
|
||||
"rc": "^1.1.2",
|
||||
"semver": "^5.0.3",
|
||||
"subcommand": "^2.0.3",
|
||||
"wreck": "^6.3.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"ansi-escapes": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz",
|
||||
"integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==",
|
||||
"dev": true
|
||||
},
|
||||
"ansi-regex": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz",
|
||||
"integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==",
|
||||
"dev": true
|
||||
},
|
||||
"ansi-styles": {
|
||||
"version": "3.2.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
|
||||
"integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"color-convert": "^1.9.0"
|
||||
}
|
||||
},
|
||||
"chalk": {
|
||||
"version": "2.4.2",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
|
||||
"integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
|
||||
"integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ansi-styles": "^3.2.1",
|
||||
"escape-string-regexp": "^1.0.5",
|
||||
"supports-color": "^5.3.0"
|
||||
"ansi-styles": "^2.2.1",
|
||||
"escape-string-regexp": "^1.0.2",
|
||||
"has-ansi": "^2.0.0",
|
||||
"strip-ansi": "^3.0.0",
|
||||
"supports-color": "^2.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"ansi-styles": {
|
||||
"version": "2.2.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
|
||||
"integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
|
||||
"dev": true
|
||||
},
|
||||
"escape-string-regexp": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
|
||||
"integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
|
||||
"dev": true
|
||||
},
|
||||
"has-ansi": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz",
|
||||
"integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ansi-regex": "^2.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"ansi-regex": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.0.0.tgz",
|
||||
"integrity": "sha1-xQYbbg74qBd15Q9dZhUb9r83EQc=",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"strip-ansi": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
|
||||
"integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ansi-regex": "^2.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"ansi-regex": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.0.0.tgz",
|
||||
"integrity": "sha1-xQYbbg74qBd15Q9dZhUb9r83EQc=",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"supports-color": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
|
||||
"integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"cli-cursor": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz",
|
||||
"integrity": "sha512-8lgKz8LmCRYZZQDpRyT2m5rKJ08TnU4tR9FFFW2rxpxR1FzWi4PQ/NfyODchAatHaUgnSPVcx/R5w6NuTBzFiw==",
|
||||
"cli-table": {
|
||||
"version": "0.3.1",
|
||||
"resolved": "https://registry.npmjs.org/cli-table/-/cli-table-0.3.1.tgz",
|
||||
"integrity": "sha1-9TsFJmqLGguTSz0IIebi3FkUriM=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"restore-cursor": "^2.0.0"
|
||||
"colors": "1.0.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"colors": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz",
|
||||
"integrity": "sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs=",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"external-editor": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.2.0.tgz",
|
||||
"integrity": "sha512-bSn6gvGxKt+b7+6TKEv1ZycHleA7aHhRHyAqJyp5pbUFuYYNIzpZnQDk7AsYckyWdEnTeAnay0aCy2aV6iTk9A==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"chardet": "^0.4.0",
|
||||
"iconv-lite": "^0.4.17",
|
||||
"tmp": "^0.0.33"
|
||||
}
|
||||
},
|
||||
"figures": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz",
|
||||
"integrity": "sha512-Oa2M9atig69ZkfwiApY8F2Yy+tzMbazyvqv21R0NsSC8floSOC09BbT1ITWAdoMGQvJ/aZnR1KMwdx9tvHnTNA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"escape-string-regexp": "^1.0.5"
|
||||
}
|
||||
},
|
||||
"has-flag": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
|
||||
"integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
|
||||
"cvss": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/cvss/-/cvss-1.0.1.tgz",
|
||||
"integrity": "sha1-XAffU2FqxW1m6PR0vtJePBRhk9s=",
|
||||
"dev": true
|
||||
},
|
||||
"inquirer": {
|
||||
"version": "3.3.0",
|
||||
"resolved": "https://registry.npmjs.org/inquirer/-/inquirer-3.3.0.tgz",
|
||||
"integrity": "sha512-h+xtnyk4EwKvFWHrUYsWErEVR+igKtLdchu+o0Z1RL7VU/jVMFbYir2bp6bAj8efFNxWqHX0dIss6fJQ+/+qeQ==",
|
||||
"https-proxy-agent": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-1.0.0.tgz",
|
||||
"integrity": "sha1-NffabEjOTdv6JkiRrFk+5f+GceY=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ansi-escapes": "^3.0.0",
|
||||
"chalk": "^2.0.0",
|
||||
"cli-cursor": "^2.1.0",
|
||||
"cli-width": "^2.0.0",
|
||||
"external-editor": "^2.0.4",
|
||||
"figures": "^2.0.0",
|
||||
"lodash": "^4.3.0",
|
||||
"mute-stream": "0.0.7",
|
||||
"run-async": "^2.2.0",
|
||||
"rx-lite": "^4.0.8",
|
||||
"rx-lite-aggregates": "^4.0.8",
|
||||
"string-width": "^2.1.0",
|
||||
"strip-ansi": "^4.0.0",
|
||||
"through": "^2.3.6"
|
||||
"agent-base": "2",
|
||||
"debug": "2",
|
||||
"extend": "3"
|
||||
},
|
||||
"dependencies": {
|
||||
"agent-base": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-2.0.1.tgz",
|
||||
"integrity": "sha1-vY+ehqjrIh//oHvRS+/VXfFCgV4=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"extend": "~3.0.0",
|
||||
"semver": "~5.0.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"semver": {
|
||||
"version": "5.0.3",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-5.0.3.tgz",
|
||||
"integrity": "sha1-d0Zt5YnNXTyV8TiqeLxWmjy10no=",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"debug": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz",
|
||||
"integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ms": "0.7.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"ms": {
|
||||
"version": "0.7.1",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz",
|
||||
"integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"extend": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/extend/-/extend-3.0.0.tgz",
|
||||
"integrity": "sha1-WkdDU7nzNT3dgXbf03uRyDpG8dQ=",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"is-fullwidth-code-point": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
|
||||
"integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==",
|
||||
"joi": {
|
||||
"version": "6.10.1",
|
||||
"resolved": "https://registry.npmjs.org/joi/-/joi-6.10.1.tgz",
|
||||
"integrity": "sha1-TVDDGAeRIgAP5fFq8f+OGRe3fgY=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"hoek": "2.x.x",
|
||||
"isemail": "1.x.x",
|
||||
"moment": "2.x.x",
|
||||
"topo": "1.x.x"
|
||||
},
|
||||
"dependencies": {
|
||||
"hoek": {
|
||||
"version": "2.16.3",
|
||||
"resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz",
|
||||
"integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=",
|
||||
"dev": true
|
||||
},
|
||||
"isemail": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/isemail/-/isemail-1.2.0.tgz",
|
||||
"integrity": "sha1-vgPfjMPineTSxd9lASY/H6RZXpo=",
|
||||
"dev": true
|
||||
},
|
||||
"moment": {
|
||||
"version": "2.12.0",
|
||||
"resolved": "https://registry.npmjs.org/moment/-/moment-2.12.0.tgz",
|
||||
"integrity": "sha1-3CVg0Zg41sBzGxpq+gRnUmTTYNY=",
|
||||
"dev": true
|
||||
},
|
||||
"topo": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/topo/-/topo-1.1.0.tgz",
|
||||
"integrity": "sha1-6ddRYV0buH3IZdsYL6HKCl71NtU=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"hoek": "2.x.x"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"nodesecurity-npm-utils": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/nodesecurity-npm-utils/-/nodesecurity-npm-utils-5.0.0.tgz",
|
||||
"integrity": "sha1-Baow3jDKjIRcQEjpT9eOXgi1Xtk=",
|
||||
"dev": true
|
||||
},
|
||||
"mute-stream": {
|
||||
"version": "0.0.7",
|
||||
"resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz",
|
||||
"integrity": "sha512-r65nCZhrbXXb6dXOACihYApHw2Q6pV0M3V0PSxd74N0+D8nzAdEAITq2oAjA1jVnKI+tGvEBUpqiMh0+rW6zDQ==",
|
||||
"path-is-absolute": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.0.tgz",
|
||||
"integrity": "sha1-Jj2tpmqz8vsQv3+dJN2PPlcO+RI=",
|
||||
"dev": true
|
||||
},
|
||||
"onetime": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz",
|
||||
"integrity": "sha512-oyyPpiMaKARvvcgip+JV+7zci5L8D1W9RZIz2l1o08AM3pfspitVWnPt3mzHcBPp12oYMTy0pqrFs/C+m3EwsQ==",
|
||||
"rc": {
|
||||
"version": "1.1.6",
|
||||
"resolved": "https://registry.npmjs.org/rc/-/rc-1.1.6.tgz",
|
||||
"integrity": "sha1-Q2UbdrauU7XIAvEVH6P8OwWZack=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"mimic-fn": "^1.0.0"
|
||||
"deep-extend": "~0.4.0",
|
||||
"ini": "~1.3.0",
|
||||
"minimist": "^1.2.0",
|
||||
"strip-json-comments": "~1.0.4"
|
||||
},
|
||||
"dependencies": {
|
||||
"deep-extend": {
|
||||
"version": "0.4.1",
|
||||
"resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.4.1.tgz",
|
||||
"integrity": "sha1-7+QRPQgIX05vlod1mBD4B0aeIlM=",
|
||||
"dev": true
|
||||
},
|
||||
"ini": {
|
||||
"version": "1.3.4",
|
||||
"resolved": "https://registry.npmjs.org/ini/-/ini-1.3.4.tgz",
|
||||
"integrity": "sha1-BTfLedr1m1mhpRff9wbIbsA5Fi4=",
|
||||
"dev": true
|
||||
},
|
||||
"minimist": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
|
||||
"integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
|
||||
"dev": true
|
||||
},
|
||||
"strip-json-comments": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-1.0.4.tgz",
|
||||
"integrity": "sha1-HhX7ysl9Pumb8tc7TGVrCCu6+5E=",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"os-locale": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz",
|
||||
"integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"execa": "^0.7.0",
|
||||
"lcid": "^1.0.0",
|
||||
"mem": "^1.1.0"
|
||||
}
|
||||
},
|
||||
"restore-cursor": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz",
|
||||
"integrity": "sha512-6IzJLuGi4+R14vwagDHX+JrXmPVtPpn4mffDJ1UdR7/Edm87fl6yi8mMBIVvFtJaNTUvjughmW4hwLhRG7gC1Q==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"onetime": "^2.0.0",
|
||||
"signal-exit": "^3.0.2"
|
||||
}
|
||||
},
|
||||
"string-width": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
|
||||
"integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"is-fullwidth-code-point": "^2.0.0",
|
||||
"strip-ansi": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"strip-ansi": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
|
||||
"integrity": "sha512-4XaJ2zQdCzROZDivEVIDPkcQn8LMFSa8kj8Gxb/Lnwzv9A8VctNZ+lfivC/sV3ivW8ElJTERXZoPBRrZKkNKow==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ansi-regex": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"supports-color": {
|
||||
"version": "5.5.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
|
||||
"integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"has-flag": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"tmp": {
|
||||
"version": "0.0.33",
|
||||
"resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz",
|
||||
"integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"os-tmpdir": "~1.0.2"
|
||||
}
|
||||
},
|
||||
"which-module": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.1.tgz",
|
||||
"integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==",
|
||||
"semver": {
|
||||
"version": "5.1.0",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-5.1.0.tgz",
|
||||
"integrity": "sha1-hfLPhVBGXE3wAM99hvawVBBqueU=",
|
||||
"dev": true
|
||||
},
|
||||
"yargs": {
|
||||
"version": "9.0.1",
|
||||
"resolved": "https://registry.npmjs.org/yargs/-/yargs-9.0.1.tgz",
|
||||
"integrity": "sha512-XS0NJoM9Iz0azh1cdgfLF5VFK6BSWfrrqA0V2tIx3fV6aGrWCseVDwOkIBg746ev0hes59od5ZvQAfdET4H0pw==",
|
||||
"subcommand": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/subcommand/-/subcommand-2.0.3.tgz",
|
||||
"integrity": "sha1-mz/Rp1PjxEHwBBDLRBMdhlX1LDI=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"camelcase": "^4.1.0",
|
||||
"cliui": "^3.2.0",
|
||||
"decamelize": "^1.1.1",
|
||||
"get-caller-file": "^1.0.1",
|
||||
"os-locale": "^2.0.0",
|
||||
"read-pkg-up": "^2.0.0",
|
||||
"require-directory": "^2.1.1",
|
||||
"require-main-filename": "^1.0.1",
|
||||
"set-blocking": "^2.0.0",
|
||||
"string-width": "^2.0.0",
|
||||
"which-module": "^2.0.0",
|
||||
"y18n": "^3.2.1",
|
||||
"yargs-parser": "^7.0.0"
|
||||
"cliclopts": "^1.1.0",
|
||||
"debug": "^2.1.3",
|
||||
"minimist": "^1.2.0",
|
||||
"xtend": "^4.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"cliclopts": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/cliclopts/-/cliclopts-1.1.1.tgz",
|
||||
"integrity": "sha1-aUMcfLWvcjd0sNORG0w3USQxkQ8=",
|
||||
"dev": true
|
||||
},
|
||||
"debug": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz",
|
||||
"integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ms": "0.7.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"ms": {
|
||||
"version": "0.7.1",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz",
|
||||
"integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"minimist": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
|
||||
"integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
|
||||
"dev": true
|
||||
},
|
||||
"xtend": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz",
|
||||
"integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"yargs-parser": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-7.0.0.tgz",
|
||||
"integrity": "sha512-WhzC+xgstid9MbVUktco/bf+KJG+Uu6vMX0LN1sLJvwmbCQVxb4D8LzogobonKycNasCZLdOzTAk1SK7+K7swg==",
|
||||
"wreck": {
|
||||
"version": "6.3.0",
|
||||
"resolved": "https://registry.npmjs.org/wreck/-/wreck-6.3.0.tgz",
|
||||
"integrity": "sha1-oTaXafB7u2LWo3gzanhx/Hc8dAs=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"camelcase": "^4.1.0"
|
||||
"boom": "2.x.x",
|
||||
"hoek": "2.x.x"
|
||||
},
|
||||
"dependencies": {
|
||||
"boom": {
|
||||
"version": "2.10.1",
|
||||
"resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz",
|
||||
"integrity": "sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"hoek": "2.x.x"
|
||||
}
|
||||
},
|
||||
"hoek": {
|
||||
"version": "2.16.3",
|
||||
"resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz",
|
||||
"integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3754,12 +3724,6 @@
|
|||
"resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
|
||||
"integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ="
|
||||
},
|
||||
"p-finally": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz",
|
||||
"integrity": "sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==",
|
||||
"dev": true
|
||||
},
|
||||
"p-limit": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.1.0.tgz",
|
||||
|
@ -3826,12 +3790,6 @@
|
|||
"integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=",
|
||||
"dev": true
|
||||
},
|
||||
"path-key": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz",
|
||||
"integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==",
|
||||
"dev": true
|
||||
},
|
||||
"path-parse": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.5.tgz",
|
||||
|
@ -4289,9 +4247,9 @@
|
|||
"dev": true
|
||||
},
|
||||
"semver": {
|
||||
"version": "5.7.2",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz",
|
||||
"integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g=="
|
||||
"version": "5.4.1",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz",
|
||||
"integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg=="
|
||||
},
|
||||
"set-blocking": {
|
||||
"version": "2.0.0",
|
||||
|
@ -4521,12 +4479,6 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"strip-eof": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz",
|
||||
"integrity": "sha512-7FCwGGmx8mD5xQd3RPUvnSpUXHM3BWuzjtpD4TXsfcZ9EL4azvVVUscFYwD9nx8Kh+uCBC00XBtAykoMHwTh8Q==",
|
||||
"dev": true
|
||||
},
|
||||
"strip-json-comments": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
|
||||
|
@ -5047,33 +4999,6 @@
|
|||
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
||||
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
|
||||
},
|
||||
"wreck": {
|
||||
"version": "12.5.1",
|
||||
"resolved": "https://registry.npmjs.org/wreck/-/wreck-12.5.1.tgz",
|
||||
"integrity": "sha512-l5DUGrc+yDyIflpty1x9XuMj1ehVjC/dTbF3/BasOO77xk0EdEa4M/DuOY8W88MQDAD0fEDqyjc8bkIMHd2E9A==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"boom": "5.x.x",
|
||||
"hoek": "4.x.x"
|
||||
},
|
||||
"dependencies": {
|
||||
"boom": {
|
||||
"version": "5.2.0",
|
||||
"resolved": "https://registry.npmjs.org/boom/-/boom-5.2.0.tgz",
|
||||
"integrity": "sha512-Z5BTk6ZRe4tXXQlkqftmsAUANpXmuwlsF5Oov8ThoMbQRzdGTA1ngYRW160GexgOgjsFOKJz0LYhoNi+2AMBUw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"hoek": "4.x.x"
|
||||
}
|
||||
},
|
||||
"hoek": {
|
||||
"version": "4.2.1",
|
||||
"resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.1.tgz",
|
||||
"integrity": "sha512-QLg82fGkfnJ/4iy1xZ81/9SIJiq1NGFUMGs6ParyjBZr6jW2Ufj/snDqTHixNlHdPNwN2RLVD0Pi3igeK9+JfA==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"write": {
|
||||
"version": "0.2.1",
|
||||
"resolved": "https://registry.npmjs.org/write/-/write-0.2.1.tgz",
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
"devDependencies": {
|
||||
"yeoman-test": "^1.6.0",
|
||||
"yeoman-assert": "^3.0.0",
|
||||
"nsp": "^3.2.1",
|
||||
"nsp": "^2.6.3",
|
||||
"eslint": "^4.1.0",
|
||||
"eslint-config-xo-space": "^0.16.0",
|
||||
"jest": "^19.0.2",
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
const getTheTitles = function(array) {
|
||||
return array.map(book => book.title);
|
||||
};
|
||||
|
||||
module.exports = getTheTitles;
|
|
@ -13,7 +13,7 @@ Let's look at the spec file first:
|
|||
const helloWorld = require('./helloWorld');
|
||||
|
||||
describe('Hello World', function() {
|
||||
test('says "Hello, World!"', function() {
|
||||
test('says hello world', function() {
|
||||
expect(helloWorld()).toEqual('Hello, World!');
|
||||
});
|
||||
});
|
||||
|
@ -38,7 +38,7 @@ Go ahead and see if you can make the test pass by editing the return value of th
|
|||
|
||||
Just to make sure, in case you're confused at this point, the test is telling you that running the function `helloWorld` should return the phrase `Hello, World!`. Punctuation and capitalization definitely matter here, so double check that if the test still isn't passing.
|
||||
|
||||
This is what the final function should look like:
|
||||
this is what the final function should look like:
|
||||
```javascript
|
||||
const helloWorld = function() {
|
||||
return 'Hello, World!'
|
|
@ -1,5 +1,5 @@
|
|||
const helloWorld = function() {
|
||||
return ''
|
||||
return 'Hello, World!';
|
||||
};
|
||||
|
||||
module.exports = helloWorld;
|
|
@ -0,0 +1,5 @@
|
|||
const leapYears = function(year) {
|
||||
return year % 4 === 0 && ( year % 100 !== 0 || year % 400 === 0);
|
||||
};
|
||||
|
||||
module.exports = leapYears;
|
File diff suppressed because it is too large
Load Diff
12
package.json
12
package.json
|
@ -14,11 +14,11 @@
|
|||
},
|
||||
"homepage": "https://github.com/TheOdinProject/javascript-exercises#readme",
|
||||
"devDependencies": {
|
||||
"eslint": "^8.47.0",
|
||||
"eslint-config-airbnb-base": "^15.0.0",
|
||||
"eslint-plugin-import": "^2.28.1",
|
||||
"jest": "^29.6.4",
|
||||
"jest-cli": "^29.6.4"
|
||||
"eslint": "^7.26.0",
|
||||
"eslint-config-airbnb-base": "^14.2.1",
|
||||
"eslint-plugin-import": "^2.22.1",
|
||||
"jest": "^26.6.3",
|
||||
"jest-cli": "^26.6.3"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "jest"
|
||||
|
@ -26,7 +26,7 @@
|
|||
"eslintConfig": {
|
||||
"root": true
|
||||
},
|
||||
"jest": {
|
||||
"jest": {
|
||||
"testPathIgnorePatterns": [
|
||||
"generator-exercise/"
|
||||
]
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
// Non regex
|
||||
const palindromes = function (string) {
|
||||
let alphabet = 'abcdefghijklmnopqrstuvwxyz'; //Create a variable that holds all the letters of the alphabet
|
||||
const cleanedString = string // Convert to lowercase, split, & filter only letters, rejoin as new const
|
||||
.toLowerCase()
|
||||
.split('')
|
||||
.filter((letter) => alphabet.includes(letter))
|
||||
.join('');
|
||||
const reversedString = cleanedString.split('').reverse().join(''); //Create a new const that holds reversed string
|
||||
return cleanedString === reversedString; //Compare cleanedString & reversedString which returns true/false
|
||||
};
|
||||
|
||||
// Do not edit below this line
|
||||
module.exports = palindromes;
|
|
@ -17,12 +17,6 @@ describe('palindromes', () => {
|
|||
expect(palindromes('Animal loots foliated detail of stool lamina.')).toBe(true);
|
||||
});
|
||||
test.skip('doesn\'t just always return true', () => {
|
||||
expect(palindromes('ZZZZ car, a man, a maracaz.')).toBe(false);
|
||||
});
|
||||
test.skip('works with numbers in a string', () => {
|
||||
expect(palindromes('rac3e3car')).toBe(true);
|
||||
});
|
||||
test.skip('works with unevenly spaced numbers in a string', () => {
|
||||
expect(palindromes('r3ace3car')).toBe(false);
|
||||
expect(palindromes('ZZZZ car, a man, a maraca.')).toBe(false);
|
||||
});
|
||||
});
|
|
@ -0,0 +1,21 @@
|
|||
const pigLatin = function(string) {
|
||||
return string
|
||||
.split(" ")
|
||||
.map(word => {
|
||||
const index = firstVowelIndex(word);
|
||||
const beginning = word.slice(0, index);
|
||||
const ending = word.slice(index);
|
||||
return `${ending}${beginning}ay`;
|
||||
})
|
||||
.join(" ");
|
||||
};
|
||||
|
||||
const firstVowelIndex = function(string) {
|
||||
const vowels = string.match(/[aeiou]/g);
|
||||
if (vowels[0] == "u" && string[string.indexOf(vowels[0]) - 1] == "q") {
|
||||
return string.indexOf(vowels[1]);
|
||||
}
|
||||
return string.indexOf(vowels[0]);
|
||||
};
|
||||
|
||||
module.exports = pigLatin;
|
|
@ -6,10 +6,6 @@ Write a function that simply repeats the string a given number of times:
|
|||
repeatString('hey', 3) // returns 'heyheyhey'
|
||||
```
|
||||
|
||||
This function will take two arguments, `string` and `num`.
|
||||
|
||||
*Note:* The exercises after this one will not have arguments provided as this one does - you will need to provide them yourself from now on. So read each exercise's README carefully to see what kinds of arguments will be expected.
|
||||
|
||||
You will notice in this exercise that there are multiple tests (see in file `repeatString.spec.js`). Only the first test is currently enabled. So after making sure that this first one passes, enable the others one by one by deleting the `.skip` from the `test.skip()` function.
|
||||
|
||||
|
||||
|
@ -21,9 +17,11 @@ You will notice in this exercise that there are multiple tests (see in file `rep
|
|||
|
||||
- Create a variable to hold the string you're going to return, create a loop that repeats the given number of times and add the given string to the result on each loop.
|
||||
|
||||
- If running `npm test repeatString.spec.js` returns results similar to the below, make sure you have enabled the rest of the tests, as described in the instructions above.
|
||||
- If running `npm test repeatString.spec.js` returns results similar to the below:
|
||||
|
||||
```
|
||||
Test Suites: 1 passed, 1 total
|
||||
Tests: 6 skipped, 1 passed, 7 total
|
||||
```
|
||||
|
||||
- Make sure you have enabled the rest of the tests (see above).
|
|
@ -1,6 +1,6 @@
|
|||
const repeatString = function (word, times) {
|
||||
if (times < 0) return "ERROR";
|
||||
let string = "";
|
||||
const repeatString = function(word, times) {
|
||||
if (times < 0) return 'ERROR';
|
||||
let string = '';
|
||||
for (let i = 0; i < times; i++) {
|
||||
string += word;
|
||||
}
|
|
@ -28,7 +28,7 @@ describe('repeatString', () => {
|
|||
const number = Math.floor(Math.random() * 1000)
|
||||
/*The .match(/((hey))/g).length is a regex that will count the number of heys
|
||||
in the result, which if your function works correctly will equal the number that
|
||||
was randomly generated. */
|
||||
was randomaly generated. */
|
||||
expect(repeatString('hey', number).match(/((hey))/g).length).toEqual(number);
|
||||
});
|
||||
test.skip('works with blank strings', () => {
|
|
@ -6,8 +6,7 @@ Pretty simple, write a function called `reverseString` that returns its input, r
|
|||
reverseString('hello there') // returns 'ereht olleh'
|
||||
```
|
||||
|
||||
You will notice in this exercise that there are multiple tests (in the file `reverseString.spec.js`). Currently, only the first test is enabled. After ensuring that the first test passes, enable the remaining tests one by one by removing the `.skip` from the `test.skip()` function.
|
||||
|
||||
You will notice in this exercise that there are multiple tests, after making the first one pass, enable the others one by one by deleting the `.skip` in front the `test.skip()` function.
|
||||
|
||||
## Hints
|
||||
Strings in JavaScript cannot be reversed directly so you're going to have to split it into something else first.. do the reversal and then join it back together into a string.
|
|
@ -0,0 +1,5 @@
|
|||
const reverseString = function(string) {
|
||||
return string.split('').reverse().join('');
|
||||
};
|
||||
|
||||
module.exports = reverseString;
|
|
@ -1,4 +1,4 @@
|
|||
const snakeCase = function (string) {
|
||||
const snakeCase = function(string) {
|
||||
// wtf case
|
||||
string = string.replace(/\.\./g, " ");
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
const sumAll = function(min, max) {
|
||||
if (!Number.isInteger(min) || !Number.isInteger(max)) return "ERROR";
|
||||
if (min < 0 || max < 0) return "ERROR";
|
||||
if (min > max) {
|
||||
const temp = min;
|
||||
min = max;
|
||||
max = temp;
|
||||
}
|
||||
let sum = 0;
|
||||
for (let i = min; i < max + 1; i++) {
|
||||
sum += i;
|
||||
}
|
||||
return sum;
|
||||
};
|
||||
|
||||
module.exports = sumAll;
|
|
@ -13,6 +13,9 @@ describe('sumAll', () => {
|
|||
test.skip('returns ERROR with negative numbers', () => {
|
||||
expect(sumAll(-10, 4)).toEqual('ERROR');
|
||||
});
|
||||
test.skip('returns ERROR with non-integer parameters', () => {
|
||||
expect(sumAll(2.5, 4)).toEqual('ERROR');
|
||||
});
|
||||
test.skip('returns ERROR with non-number parameters', () => {
|
||||
expect(sumAll(10, "90")).toEqual('ERROR');
|
||||
});
|
|
@ -0,0 +1,13 @@
|
|||
const convertToCelsius = function(fahrenheit) {
|
||||
return Math.round((fahrenheit - 32) * (5/9) * 10) / 10;
|
||||
};
|
||||
|
||||
const convertToFahrenheit = function(celsius) {
|
||||
return Math.round(((celsius * 9/5) + 32) * 10) / 10;
|
||||
};
|
||||
|
||||
|
||||
module.exports = {
|
||||
convertToCelsius,
|
||||
convertToFahrenheit
|
||||
};
|
Loading…
Reference in New Issue