- Do NOT try to pass tests right away! We'll do them one by one as we go.
- Remember that a FUNCTION is going to be code WE use to get input and output for our own INTERNAL use, while
process.argv
andconsole.log
are for getting input from and output to the USER via the TERMINAL.
- We'll start by printing a greeting and farewell from the database, but with an imaginary user.
- Check out the
db.js
file. That's where all our data is! - Create a
main.js
file. We'll code exclusively in here for a while! - Now
require
db.js
intomain.js
.- Don't forget that
require
takes in one parameter: a string that's the path to another file. - Use
./
for the start of the path and.js
for the end.- Neither of those are standard practice for advanced devs, but they serve as a good reminder that this is just a path to a file!
- Save the result of
require
in a variable calledlanguages
.- even though we're grabbing whatever
db.js
exports, it's our variable and we can call it whatever we want!
- even though we're grabbing whatever
- Don't forget that
- Try printing out a greeting and a farewell from a language.
- First try
console.log
ging out the values inlanguages.english
. Note that it's an object with.greeting
and.farewell
properties. - Now change that
console.log
to print out the values inlanguages.english.greeting
andlanguages.english.farewell
. - Run your code in the terminal by typing
node main.js
. You should see "hello" and "goodbye" print out!
- First try
- We pulled in our object and printed out a greeting and farewell from it, but WE decided which language to print. Now let's take in input using
process.argv
, run it through some simple if/else logic, and print out a response.- Take
process.argv[2]
and save it into a variable. Let's call ituserLanguage
. - Check the value of that language against two or three hard-coded language name strings (maybe "english" and "spanish" and "arabic"?) using an
if/else
chain or aswitch
statement (this is a good use case for that, since we're checking one thing's value against several possible values it could have). - If it matches one of those strings, print out that specific language's
.greeting
and.farewell
properties. Don't hard-code it to the point where you're writing "hello" into the code, but you CAN choose which language to print in each case; for example, if "english" is a match, you can print outlanguages.english.greeting
andlanguages.english.farewell
. This is a fine solution if we only have a few possibilities! - Print out a default response if it doesn't match one of the languages you're searching for (
default
forswitch
or anelse
for anif/else
chain). Maybe something like, "Sorry, that language is not in our database yet." - Try running
node main.js english
and your other languages from your logic chain; if you set up your logic correctly, it should print out the correct greeting and farewell. Now trynode main.js xhosa
. That IS in our database, but if you didn't put it in your logic chain, it will claim we don't have it. - There is, of course, a better way!
- Take
- First let's move this all into a function in its own file.
- Why?
- It's better to separate the user interface (what is our user's input and how do we get them output?) from the logic (what's the appropriate output for their input?)
- And most obviously, code outside functions is difficult to test... have to manually check every language to see if it works this way. Console.log statements are for visual checking by PEOPLE, but code can test return values from functions very quickly and with less error.
- In
main.js
, get rid of therequire
fordb.js
and replace it with arequire
ofgetAloha.js
. The front end won't care where the data is, it'll be the back end's job to get it. - Now call getAloha, pass in that
userLanguage
we took in from our terminal-using friend, and save its response aslanguage
. If all goes according to plan, we'll get back an object likelanguages.english
orlanguages.arabic
. We'll assume that's going to work and print out ourlanguage.greeting
andlanguage.farewell
for the user. - Let's move over to
getAloha.js
and make this happen! First, we'll require ourdb.js
file into alanguages
variable here. - Then take your logic chain from
main.js
and move it into a function calledgetAloha
there. Instead of coming in directly fromprocess.argv
now, our language name will come in as a parameter; maybe call itlanguageName
, and change our logic chain to use that name instead ofuserLanguage
. (Good to make sure we're not confusing the two!) - We're no longer printing here; that's the front end's job to do whatever is appropriate with the answer. We're just here to give back the correct answer. So instead of our
console.log
s of each language's properites, just return the entire language object. So if you get passed "english", you'll want to returnlanguages.english
, but let the front end deal with the object's.greeting
and.farewell
properties. - Now we can run our tests in the terminal, the terminal can run that code, and then
jest
can report whether, given a language, we can give back the matching language object from ourdb.js
. - if you change the languages you're checking for to English, Spanish, and Japanese (keeping in mind that everything should be lowercase!), you SHOULD be passing the first test at this point.
- If you're not, make sure you're:
- grabbing the languages from
db.js
- taking in the language the user wants as a parameter
- using lower case when checking what language it is
- If that all seems like you've got it, but you're not passing the test, try checking what values you're working with, with
console.log
, which should be visible through Quokka if you call your own function or through your results in the terminal when WE call it, or with running the debugger (don't forget to call your own function and set breakpoints!)
- grabbing the languages from
- So the problem with this approach is that to pass the tests, you'd need if/else cases for English, Spanish, Japanese, Russian, and Zulu, and that would be just to pass the tests... those tests are only checking for 5 of the 26 languages we actually have in our database!
- Instead, we want to be able to generalize.
- What we want to do to generalize is to say, "Whatever language you pass me, I can just look it up on the object." This way, if we add "Klingon" to our database, we don't have to add any more code to
getAloha
... if passed "klingon", it will simply find thelanguages.klingon
object and return it. SO: how do we do it?- Since we're getting a string for a language from the terminal-wielding user (as
process.argv[2]
), and ourlanguages
object indb.js
has a property for each language (english
,hawaiian
,luganda
, etc.), we can say, "I want whatever object is at languages dot... that language." So if we're passed "english", we want to give them backlanguages.english
, and so on. - So if we're taking in our parameter here as
userLanguage
(and you can call it what you want), we want to saylanguages.userLanguage
. But that doesn't work, because userLanguage is a variable name, butlanguages.userLanguage
is saying I want a property LITERALLY called "userLanguage", NOT the property at whatever string the variableuserLanguage
HOLDS. - So dot notation won't do it for us. But this is precisely what bracket notation is for! We want to use bracket notation to return the object at the key passed to us. if you're missing how todo this, your friendly search engine should be able to help you.
- If you've got that, then all you need is to return that object to pass the first test.
- Since we're getting a string for a language from the terminal-wielding user (as
- Let's test it manually. Our first automatic test, remember, only checks 5 languages!
- In your
main.js
file, make sure you're a) getting the value from the users'process.argv[2]
, b) passing that in to yourrequire
'd ingetAloha
function, and c) printing out BOTH the.greeting
and.farewell
properties on the object it returns (preferably in some nice sentence). - Now try that out in your terminal! Run
node main.js english
andnode main.js hawaiian
and so on. Try a few that aren't on the first test you're passing but ARE in our db. You should be able to get all of them! - You could even at this point try adding a language object (for a real or imagined language!) as a property of our
db.js
object, in the same format as the others. Then try looking it up usingnode main.js [your language here]
. It should work automagically!
- In your
- Congratulations, you have completed the Minimum Viable Product version of our app!
- But what about the next three tests?!
- Test 2: case insensitivity. Make sure before you look up the value in your key, that you've lower-cased the string you were passed.
- Test 3: If we call getAloha without a parameter, return
null
. This is in case our terminal-using user forgets to give us a real value. Then our front end can deal with that information. Hint: if there is nothing passed in, what will be the value of our parameter? - Test 4: If we call it with
elvish
(and you haven't put that in yourself!), we should returnnull
as well. Hint: there's a way to check if our key isin
our object!
- You may find that passing some of these tests makes some others not work. Make sure you're checking if it's undefined BEFORE you're trying to lowerCase it... otherwise you may run
.toLowerCase
on a value that's not a string! AND make sure you're lowercasing the language when you check if it's in yourdb
... there's a way to get the order of this right. The debugger can help! - But changing the code to return
null
has affected the front end. Now our function is giving us backnull
if our language isn't in the database or we just wrotenode main.js
without a language at all, and on the front end, we're looking for a.greeting
property on something (null
) that doesn't have one. Let's check fornull
and ONLY check for properties if we don't have it, and print something appropriate out if they didn't give us the right response. - We might also consider checking before we call
getAloha
to see if ourprocess.argv
even holds a language, and respond appropriately if it doesn't (without calling our function!). Without that check, we don't know if our function is returningnull
because the language isn't in the db or there was no language at all! - Final stretch goal if you haven't done this already: make sure all your messages to your user are clear. which one is a greeting and which one is a farewell? Are you telling them how to use the app if they're having trouble? Are you repeating back to them the language they typed? We'll be improving the size of our UI toolbox soon, but let's do what we can with the basic terminal interface for now!