We have learned Object-oriented programming and how class
and inheritance work in JavaScript. Now lets work with our Viking friends, applying all of the concepts we have just learned.
- Fork this repo
- Clone this repo
Upon completion, run the following commands:
$ git add .
$ git commit -m "done"
$ git push origin master
Create Pull Request so your TAs can check up your work.
Yes! The best way to ensure your code is doing what is expected is to constantly test. Go ahead and open the file SpecRunner.html
!
Run the tests
We have got a test suite for our constructor functions and their methods but there are no tests currently being executed. We have to uncomment each it()
inside of tests/viking.spec.js
and implement the code in src/viking.js
to make each test pass.
If you open tests/viking.spec.js
and take a look at lines 11-21, You should see some it()
calls (tests) that are commented out. Let's start by uncommenting lines 11-13:
describe('constructor function', () => {
it('should receive 2 arguments (health & strength)', () => {
expect(Soldier.length).toEqual(2);
});
// it('should receive the health property as its 1st argument', () => {
// expect(soldier.health).toEqual(health);
// });
// it('should receive the strength property as its 2nd argument', () => {
// expect(soldier.strength).toEqual(strength);
// });
});
Now that particular test (should receive 2 arguments (health & strength)) is failing!
We must write the correct code in the src/viking.js
file to make the test pass. In this file you will find the following starter code:
// Soldier
class Soldier {}
// Viking
class Viking {}
// Saxon
class Saxon {}
// War
class War {}
In this case, the test says that Soldier class should receive 2 arguments (health & strength), so we have to write the correct code that passes this test. Let's make the Soldier
class receive two arguments:
// Soldier
class Soldier {
constructor(health, strength) {}
}
// Viking
class Viking {}
// Saxon
class Saxon {}
// War
class War {}
Execute all the tests
Now that we are passing the first test, the next step is to uncomment the next test. To do that, we have to remove the comments from lines 15-17 in the tests/viking.spec.js
file, and refresh the page to see what we have to implement next.
Once we have verified that the test is failing, we can implement the code to make it pass.
Modify the Soldier
class and add 2 methods to it: attack()
, and receiveDamage()
.
- should receive 2 arguments (health & strength)
- should receive the
health
property as its 1st argument - should receive the
strength
property as its 2nd argument
- should be a function
- should receive 0 arguments
- should return the
strength
property of theSoldier
- should be a function
- should receive 1 argument (the damage)
- should remove the received damage from the
health
property - shouldn't return anything
A Viking
is a Soldier
with an additional property, their name
. They also have a different receiveDamage()
method and new method, battleCry()
.
Modify the Viking
class, have it inherit from Soldier
, re-implement the receiveDamage()
method for Viking
, and add a new battleCry()
method.
Viking
should extendSoldier
- should receive 3 arguments (name, health & strength)
- should receive the
name
property as its 1st argument - should receive the
health
property as its 2nd argument - should receive the
strength
property as its 3rd argument
(This method should be inherited from Soldier
, no need to re-implement it.)
- should be a function
- should receive 0 arguments
- should return the
strength
property of theViking
(This method needs to be re-implemented for Viking
because the Viking
version needs to have different return values.)
- should be a function
- should receive 1 argument (the damage)
- should remove the received damage from the
health
property - if the
Viking
is still alive, it should return "NAME has received DAMAGE points of damage" - if the
Viking
dies, it should return "NAME has died in act of combat"
Learn more about battle cries.
- should be a function
- should receive 0 arguments
- should return "Odin Owns You All!"
A Saxon
is a weaker kind of Soldier
. Unlike a Viking
, a Saxon
has no name. Their receiveDamage()
method will also be different than the original Soldier
version.
Modify the Saxon
, constructor function, have it inherit from Soldier
and re-implement the receiveDamage()
method for Saxon
.
Saxon
should extendSoldier
- you don't have to include constructor method since this class will inherit perfectly from the parents class, both, the health and the strength (it
extends
Soldier class 😉 )
(This method should be inherited from Soldier
, no need to re-implement it.)
- should be a function
- should receive 0 arguments
- should return the
strength
property of theSaxon
(This method needs to be re-implemented for Saxon
because the Saxon
version needs to have different return values.)
- should be a function
- should receive 1 argument (the damage)
- should remove the received damage from the
health
property - if the Saxon is still alive, it should return "A Saxon has received DAMAGE points of damage"
- if the Saxon dies, it should return "A Saxon has died in combat"
Now we get to the good stuff: WAR! Our War
class will allow us to have a Viking
army and a Saxon
army that battle each other.
Modify the War
class and add 5 methods to its class
:
addViking()
addSaxon()
vikingAttack()
saxonAttack()
showStatus()
When we first create a War
, the armies should be empty. We will add soldiers to the armies later.
- should receive 0 arguments
- should assign an empty array to the
vikingArmy
property - should assign an empty array to the
saxonArmy
property
Adds 1 Viking
to the vikingArmy
. If you want a 10 Viking
army, you need to call this 10 times.
- should be a function
- should receive 1 argument (a
Viking
object) - should add the received
Viking
to the army - shouldn't return anything
The Saxon
version of addViking()
.
- should be a function
- should receive 1 argument (a
Saxon
object) - should add the received
Saxon
to the army - shouldn't return anything
A Saxon
(chosen at random) has their receiveDamage()
method called with the damage equal to the strength
of a Viking
(also chosen at random). This should only perform a single attack and the Saxon
doesn't get to attack back.
- should be a function
- should receive 0 arguments
- should make a
Saxon
receiveDamage()
equal to thestrength
of aViking
- should remove dead saxons from the army
- should return result of calling
receiveDamage()
of aSaxon
with thestrength
of aViking
The Saxon
version of vikingAttack()
. A Viking
receives the damage equal to the strength
of a Saxon
.
- should be a function
- should receive 0 arguments
- should make a
Viking
receiveDamage()
equal to thestrength
of aSaxon
- should remove dead vikings from the army
- should return result of calling
receiveDamage()
of aViking
with thestrength
of aSaxon
Since there is a lot of repetitive code in the previous two iterations, vikingAttack() and saxonAttack() try to create one generic method and call it in the case of vikingAttack and in the case of saxonAttack instead of using almost the same code for both methods. (This iteration doesn't have test, so ask your TAs and your instructor to give you feedback on the quality of your code after the refactor.)
Returns the current status of the War
based on the size of the armies.
- should be a function
- should receive 0 arguments
- if the
Saxon
array is empty, should return "Vikings have won the war of the century!" - if the
Viking
array is empty, should return "Saxons have fought for their lives and survived another day..." - if there are at least 1
Viking
and 1Saxon
, should return "Vikings and Saxons are still in the thick of battle."
Happy Coding! 💙