Mocha as a JavaScript Test Framework

The last few projects I discussed were to get you started coding in ES6 JavaScript. I intentionally kept the functionality very limited. In this article, I will show how to set up a test framework using my ES6 CLI Promises repository, promises. There are many different frameworks to choose from. A simple one to set up is Mocha.

Setting up

First, clone promises (the instructions for cloning are included in the article that goes with this repository, My JS Journey: Promises).

Next, install the node dependencies.

npm install

Then, build and run it to ensure everything is set up correctly.

npm run build
npm start

It should say,
hello world

Install Mocha

Install Mocha.

npm install mocha --save-dev

This should have added mocha to the devDependencies in package.json. Now is a good time to change the name.

{
  "name": "MochaExample",
  "version": "1.0.0",
  "description": "Simple Mocha example",
  "main": "index.js",
  "scripts": {
    "build": "babel src -d dist",
    "start": "node dist/index",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "babel-cli": "^6.24.0",
    "babel-core": "^6.24.0",
    "babel-preset-env": "^1.3.2",
    "babel-register": "^6.24.0",
    "mocha": "^3.3.0"
  }
}

Might as well check in the code.

Convert src/hello.js to Implement a class

To facilitate exporting, I find it easiest to use classes. Modify src/hello.js as follows.

class Hello {
  static getWorld() {
    return new Promise((resolve) => {
      setTimeout(() => resolve(' world'), 500);
    });
  }

  static hello() {
    return new Promise((resolve) => {
      this.getWorld().then(result => {
        resolve('hello' + result);
      });
    });
  }
}
export default Hello;

Notice that the functions changed from const to static. Also, now that they are part of the object, to reference them within the object, it is necessary to prefix them with this., e.g. this.getWorld(), as in line 10.
Modify src/index.js to accommodate the new class.

import Hello from './hello';

const sayHello = (message) => {
  console.log(message);
};

const main = () => {
    var args = process.argv;
    if (args[2] && args[2] === '--v' ) {
        console.log('Es6CliSkeleton - version 1.0.0');
    } else {
        Hello.hello().then(res => sayHello(res));
    }
};

main();

The lines that changed are 1 and 12, both of which reference the new Hello class.

Build and run to ensure everything still works.

Adding Tests

First, create a folder test. Add a file to this folder called hello_test.js.
Add the first test.

import assert from 'assert';
import Hello from '../src/hello';

describe('Hello', function() {
  describe('getWorld', function() {
    it('should return space world', function() {
      Hello.getWorld()
      .then(result => {
        assert.equal(' world', result);
      });
    });
  });
});

Next, in package.json, modify the “scripts” section’s “test” to “mocha –compilers js:babel-core/register test/*_test.js”.
Build and run the test.

npm run build
npm run test

You should get output something like this.

> MochaExample@1.0.0 test /Users/your_src/promises
> mocha --compilers js:babel-core/register test/*_test.js
  Hello
    getWorld
      ✓ should return space world
  1 passing (100ms)

With a nice green checkmark.
Check the code in.

A Second Test

We should have a test on the other function, Hello.hello(). It will be very similar the first one. Add this right code after the other test.

  describe('hello', function() {
    it('should return hello world', function() {
      Hello.hello()
      .then(result => {
        assert.equal('hello world', result);
      });
    });
  });

Build and run. The output should look like this.

  Hello
    getWorld
      ✓ should return space world
    hello
      ✓ should return hello world

  2 passing (65ms)

Go ahead and check that in since the next section covers something a little different.

A Broken Promise

Let’s see what happens when the promise is broken. Modify what the promise returns in Hello.getWorld() from

  setTimeout(() => resolve(' world'), 500);

to

  let input = "myErr";
  if (input === "myErr") { reject(new Error(input)); }
  setTimeout(() => resolve(' world'), 500);

Build and run the app.

> MochaExample@1.0.0 start /Users/your_src/Closet/promises
> node dist/index

(node:61097) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 2): 42

It fails, kind of how you might expect. Run the tests.

  Hello
    getWorld
      ✓ should return space world
(node:61087) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 2): Error: myErr
    hello
      ✓ should return hello world
(node:61087) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 4): Error: myErr

  2 passing (111ms)

Interestingly, the tests pass, although they report the unhandled promise rejection. Let’s fix that first. Modify the tests to include a catch, which will also require the use of done in lines 6, 10 and 14, and 19, 23 and 27.

import assert from 'assert';
import Hello from '../src/hello';

describe('Hello', function() {
  describe('getWorld', function() {
    it('should return space world', function(done) {
      Hello.getWorld()
      .then(result => {
        assert.equal(' world', result);
        done();
      })
      .catch(err => {
        console.log(err);
        done(err);
      });
    });
  });
  describe('hello', function() {
    it('should return hello world', function(done) {
      Hello.hello()
      .then(result => {
        assert.equal('hello world', result);
        done();
      })
      .catch(err => {
        console.log(err);
        done(err);
      });
    });
  });
});

Now, the tests fail and let you know why:

  1) Hello getWorld should return space world:
     Error: myErr
      at src/hello.js:5:39
      at Function.getWorld (src/hello.js:3:12)
      at Context.<anonymous> (test/hello_test.js:7:13)

  2) Hello hello should return hello world:
     Error: myErr
      at src/hello.js:5:39
      at Function.getWorld (src/hello.js:3:12)
      at src/hello.js:12:12
      at Function.hello (src/hello.js:11:12)
      at Context.<anonymous> (test/hello_test.js:20:13)

Remove the changes to getWorld(). Check in the code.

In Conclusion

I generally start by writing my tests (Test Driven Development or TDD). I believe it is one of the fundamental practices in good code development. It is important to ensure you have complete test coverage. In this example, you can see I had tests for the “happy path” but had not covered potential failures. It was a bit contrived, but be on the lookout for things that can go wrong. In the future, I will show how to use Node fs, which is their file system interface. It has a lot of good examples where you need to test for things that might go wrong—a missing file, an empty file, invalid permissions—lots of things to test for.

You can find the code for this project in my github repository, mocha-example.

Copyright ©2014-17 Ramona Ridgewell. All rights reserved.

Posted in #Education, AmWriting, Education, GitHub, JavaScript, Programming, Science, Software Development, STEM | Tagged , , , , , , , , , , | Leave a comment

Take Your Daughter to Work Day

What do you think when you hear, “Black Lives Matter?” Do you immediately think, “well, all lives matter?” If so, you’re missing the concept of systemic discrimination. It’s built into our societal norms. It won’t change unless we take steps to make it change. That might mean that someone in the group of discriminators will feel left out or cheated out of an opportunity he thinks he deserves as much as the next person. I’ll tell you this, until Black lives do matter, no lives matter in our country.

The reason I brought up the Black Lives Matter movement is to draw a comparison to another movement from the ’90s, “Take Your Daughter to Work Day.” It was an attempt by women in my industry, computer engineering, to show girls how cool coding could be—and to encourage them to study maths and sciences so that becoming a computer geek was not beyond their reaches.

Over the next couple of years, the movement spread to other disciplines—but it was about daughters. It didn’t take long for parents of boys to complain it was unfair to set aside a special day for girls. Their sons were being left out. They had never witnessed a group of children entering a computer lab—in those days, there would have been just a few machines available—the rush forward, the elbowing to get on the limited resources. Let me! Let me, do it! If they had been there, they would have seen the boys take over all of the machines, with clusters of their peers around them. The girls—at least most of them—would be standing behind the boys, watching, not doing. This was the reason to give girls a special day—to let them engage with the technology on their own terms.

Every year on Take Your Child to Work Day, I am reminded of the way girls continue to be excluded from the sciences, especially Computer Science. Back in the ’80s—the heyday of women in computing—the percentage of young women graduating in the field was around 35%. By 2013, the number had dropped to 18%. We are responsible for this drop. We encourage the practices that preclude girls from a science-rich education. For the men who rule this lucrative, high-paying profession, this leaves little competition from a whole gender—half the population—of people. I wonder if things would be better for women today if we had focused, as a nation, on educating girls in what is now called STEM.

I know, from personal experience, the challenges of being a woman in a man’s field—I  remember only being mentored by one of my male managers, and not very proactively; I was passed over for the coolest and most important projects; I was excluded from being part of “the club”—perhaps not overtly, but just by virtue of the extracurricular activities “the club” pursued, like telling an off-color joke, or going out to drink scotch and smoke cigars, or going on a camping trip to shoot guns and ride dirt bikes. In my day-to-day jobs, I have almost always been the sole woman on my team, in a hierarchy of all-men teams. All of these things, combined, leads to women in computing making only 87% of what their male counterparts are paid. The percentage of women computer engineers, from my direct observation over many years, is around 10%. When high-tech companies state their percentages at closer to twenty, they are including women who work in all capacities, such as program managers, scrum masters, human resources and recruiting—the latter two being predominantly women.

The practice of exclusion of women reaches beyond computer engineering to other high-paying professions. A good example is the Hollywood movie industry. I wrote about this a couple of years ago. It includes the fact that women directed only 6% of the top 250 U.S. grossing films in 2013. The pay gap for women is also well documented. A big deal was made of Anna Boden being selected to direct the new Marvel movie, “Captain Marvel,” although, the co-director is a man, Ryan Fleck. One of the reasons for the hoopla is that Marvel has never had a woman at the helm of one of its movies before. Maybe things are progressing at Marvel—the writers, Nicole Perlman and Meg LeFauvre, are also women, as is the star, Captain Marvel herself, Brie Larson. I hope the company hired these women on the merits of their work and not to save 30% on their wages.

So, on this Take Your Child to Work Day, remember its original intent. Also, when you think about Black Lives Matter, remember, in my field, Black Americans of all genders make up just over 5% of the employees, and Black engineers make up only 1-3%. I can count on one hand the number of Blacks I have worked with, and almost never on my own team. I have nothing against Chinese and Indian immigrants coming to America—some of my best friends are Indians, and we are all, except for Indigenous people, children of immigrants—but, in computing, they are grossly over-represented, especially in the engineering jobs. Maybe we should think about enabling our own children—most importantly women and minorities—to fill these high-paying jobs.

Don’t forget to take your daughter to work today.

Thanks to:
fortune.com
www.aauw.org
time.com/money
www.polygon.com
cra.org

Copyright ©2014-17 Ramona Ridgewell. All rights reserved.

Posted in #Education, Black Lives Matter, Coding, Education, family, Programming, Science, STEM, Uncategorized, Women | Tagged , , , , , , , , , , , , | Leave a comment

An Accessible and Usable GitHub Repository

After adding a few repositories to GitHub, I realized I neglected to discuss README.md. This is a place where you can put notes about your project which will appear on the repository page. For example, here’s the README.md from my newest repository, promises-browser.

See [this article](https://ramonaridgewell.wordpress.com/2017/04/24/my-js-journey-a-promise-in-a-browser/) for a description of how to set up this project.

It shows up at the bottom of the GitHub page, after the list of files. It’s also a good practice to add a description, a link to a webpage, and topics (up near the top).

Screen Shot 2017-04-24 at 12.06.05

I’ve been linking to the articles in my blog for setup instructions, but you could include pertinent notes in the README.md, and they will show up there.

Copyright ©2014-17 Ramona Ridgewell. All rights reserved.

Posted in #Education, AmWriting, Coding, Education, GitHub, JavaScript, Science, Women, Writing | Tagged , , , , , , , , , | Leave a comment

My JS Journey: A Promise in a Browser

In this example, I’m going to explain how to fork a GitHub repository—or copy someone else’s—as well as implement a simple promises app. As an added bonus, I threw in using a Class. The code to fork is my JavaScript browser skeleton.

Forking a Repository

In GitHub:

In the upper right, Click the Fork.

In iTerm:

Once you have your local GitHub repository, you can follow the instructions for cloning I outlined in Promises. For more on forking, see this GitHub article.

To install all the node packages, run:

npm install

Then build:

npm run build

To see it run, open index.html. When you click the Get Message button, the Message should dislpay “Hello.”

Screen Shot 2017-04-03 at 09.37.37

Adding A Class

Because I like classes, I implemented one, so you can see how that works with respect to export.

First, implement the class by changing src/hello.js as follows:

class Hello {
  static hello(){
    return 'Hello';
  }
}

export default Hello;

Modify src/index.js to import the class:

import Hello from './hello.js';

var sayHello = function () {
  return Hello.hello();
}

document.getElementById('msgBtn').addEventListener('click', function () {
    var message = sayHello();
    document.getElementById("message").innerHTML = message;
});

Build the project.

npm run build

Load or refresh index.html:
Screen Shot 2017-04-03 at 09.37.37
Checkin the code.

Adding Promises

This example is basically the same as the CLI one I described in Promises. The major difference, of course, is this one is in the browser. Promises let you ensure the order of asynchronous events, such as file reading. In my example, I retrieve the text ” world” after a timeout, and append it to “Hello” from the origin example. It’s contrived, but it shows how a promise works.

Modify src/hello.js as follows:

class Hello {
  static getWorld() {
    return new Promise((resolve) => {
      setTimeout(() => resolve(' world'), 500);
    });
  }

  static hello(){
    return new Promise((resolve) => {
      this.getWorld().then(result => {
        resolve('Hello' + result);
      });
    });
  }
}

export default Hello;

Modify src/index.js to resolve the promise returned from Hello.hello():

import Hello from './hello.js';

const sayHello = (message) => {
document.getElementById("message").innerHTML = message;
};

document.getElementById('msgBtn').addEventListener('click', () => {
Hello.hello()
.then(res => sayHello(res));
});

Build the code and refresh index.html. It should now display “Hello world” instead of simply “Hello.” You might be able to see the half-second lag on getting the message. That’s the timeout.

Screen Shot 2017-04-21 at 12.59.10

Check the code in.

In Conclusion

Promises in ES6 are not difficult, although they can be cumbersome if there are a lot of nested Promises. The new—and, as of yet, not completely supported—ES7 feature, async/await, is meant to simplify nested Promises. I’ll write about that in a future post. You can find the Browser Promise code in my github repository, promises-browser.

Copyright ©2014-17 Ramona Ridgewell. All rights reserved.

Posted in #Education, AmWriting, Coding, Education, JavaScript, Programming, Science, Women, Writing | Tagged , , , , , , , , | 1 Comment

Seattle React.js April Meetup

I had the pleasure tonight to attend the Seattle React.js April Meetup. It was hosted by Textio, who have created an augmented writing platform for creating highly effective job listings and who provided a light dinner; and Galvanize, who provide a dynamic learning community for technology and who also provide space for the event.

Host Lee Ngo, from Galvanize, started the evening by introducing Stephan Prockow, the Seattle React.js Meetup organizer. After the greetings and salutations were complete, he introduced the first guest speaker, Max Winderbaum of Textio.

Winderbaum talked about how to create lovely rich-text editors using draft-js, a JavaScript rich text editor framework, built for React and backed by an immutable model. Textio began their text editor by trying to utilize the HTML tag < contenteditable> to highlight or do other rich text enhancements. After starting down the path of writing their own solution, they found Facebook was already providing something very close to what they were trying to accomplish. State becomes immutable and atomic. It renders to all browsers the same way. And, best of all, the state is separate from the view, which facilitates testing. draft-js nicely supports plugins like draft-js-plugins. Winderbaum warned us to keep an eye out for new kid, slatejs.org. There’s always something new on the horizon for JavaScript.

The second presentation was about using react-apollo with graphql. Presenter Greg Hardin, of IceBrg.io, offered as an example a lookup from a collection of books. He covered the details of how react-apollo is integrated into the code and also cited some tools that can help with setup, such as Scaphold. Hardin explained some benefits of react-apollo with less boilerplate, the ability to run multiple named queries in the same space, mutations that an be separated from queries, and the fact that it is already integrated with redux.

mobx is another alternative to working in react. High Seas Consulting‘s Bryan Brophy gave a compelling talk on the ease of use of mobx, whose goal is simple, scalable state management. In an entertaining demo that used the Beatles as an example for band members changing state over time, Brophy showed the basic usage of mobx, including injecting stores, actions, and observers to keep the state up-to-date. It is certainly something I will look at seriously before making my next major software updates.

I’m happy I was able to be present for this well-attended event. The speakers were well-versed in their respective technologies and I learned a lot. Thanks so much to the hosts, Galvanize and Textio, and the event organizers at Seattle React.js Meetup. When video of the talks is available, I’ll add a link to it here.

Copyright ©2014-17 Ramona Ridgewell. All rights reserved.

Posted in #Education, Coding, JavaScript, Programming, Science | Tagged , , , , , , | Leave a comment

Norwescon 2017

Over the weekend, I attended Norwescon 40: Over the Hills and Far Away. It was my first time attending. I had a great time in the writing panels and workshops. You can read more about it on my writing blog.

I spent all of April 14 in writer’s panels and workshops at Norwescon 40. It was intense and exhausting, but time well-spent.

via NorWesCon 40: Over the Hills and Far Away — thewolfdreambooks

Posted in #Education, AmWriting, AmWritingFantasy, Books, Education, Fantasy, Horror, Novel, Reading, Writing | Tagged , , , , , , , , | Leave a comment

My JS Journey: Promises

Promises

There are a lot of ES6 features that are not supported in ES5 browsers. Promises are among them. Your ES6 code may or may not work based on which Node.js or WebPack you are using, which browser version it is rendering in, etc. Here is a comprehensive chart that shows which features are supported in which environments. Here’s another more detailed one specific to Node.js.

Although Promises are supported by the most current versions of WebPack, babel-core and Node.js, in the past, babel-polyfill was a separate requirement. If you find that adding the Promise code doesn’t work, first update your WebPack or Node.js, or try installing polyfill. Its purpose is to add to the global scope as well as native prototypes like String to enable use of new built-ins until they are added to the core packages. For more information, read how it works here.

install --save babel-polyfill

For this example, I will show how to add a promise to my ES6 CLI Skeleton.

Get the Skeleton

If you have not already followed the instructions to create the ES6 CLI Skeleton, you should do that now (or follow the instructions for Forking that I will include in another blog soon). If you know how to copy one of your GitHub repositories, clone it, then skip this section.

Clone the Project

In GitHub:

Navigate to your CLI Skeleton.
On the right side, click the green Clone or Download button.
Copy the URL.

In the console:

Navigate to the directory where you want the project directory to exist.
Run the following command:

git clone https://github.com/YourRepo/skeleton-cli-js.git

Output:

Cloning into 'skeleton-cli-js'...
remote: Counting objects: 21, done.
remote: Compressing objects: 100% (11/11), done.
remote: Total 21 (delta 4), reused 21 (delta 4), pack-reused 0
Unpacking objects: 100% (21/21), done.
Checking connectivity... done.

Navigate to skeleton-cli-js (the project directory).
Run this command:

git remote show origin

Output:
remote origin
Fetch URL: https://github.com/RidgewellServices/skeleton-cli-js.git
Push URL: https://github.com/RidgewellServices/skeleton-cli-js.git
HEAD branch: master
Remote branch:
master tracked
Local branch configured for 'git pull':
master rebases onto remote master
Local ref configured for 'git push':
master pushes to master (up to date)

If you plan to submit pull requests to augment a repository, this is fine. Otherwise, to create your own project, but keep all the history from the original project, run the following commands.

This command disassociates the code from the original repository.

git remote remove origin

Create a new repository on GitHub, then run the next command to
associate the code with your new repository.

git remote add origin https://github.com/YourGitHub/your-new-repo.git

Now, when you show the origin, you are pointed to your new repo. In the project directory, run:

git remote show origin

Output:
remote origin
Fetch URL: https://github.com/YourGitHub/your-new-repo.git
Push URL: https://github.com/YourGitHub/your-new-repo.git
HEAD branch: (unknown)

When you checkin, it will go to your repository.
To install the package dependencies, from the command line, run:

npm install

Then, build to ensure everything is working:

npm run build

And, finally, run the code:

npm start

It should say “Hello.”

Add a Promise

Promises let you ensure the order of asynchronous events, such as file reading. In my example, I retrieve text after a timeout. It’s contrived, but it shows how a promise works.

Add Promises

Change the app code by adding some promises. Change src/hello.js as follows:

const getWorld = () => new Promise((resolve) => {
  setTimeout(() => resolve(' world'), 500);
});

const hello = () => new Promise((resolve) => {
  getWorld().then(result => {
    resolve('hello' + result);
  });
});

export default hello;

Change src/index.js to resolve the Promise, as follows:

import hello from './hello';

const sayHello = (message) => {
  console.log(message);
};

function main() {
    var args = process.argv;
    if (args[2] && args[2] === '--v' ) {
        console.log('Es6CliSkeleton - version 1.0.0');
    } else {
        hello().then(res => sayHello(res));
    }
}

main();

In the project directory, run:

npm run build

In the project directory, run:

npm start

Output:
node dist/index
hello world

If you want to do the same thing in the browser, download my ES6 Browser Skeleton instead. Change src/hello.js as above. Then, modify src/index.js to resolve the Promise, as follows:

import hello from './hello.js';

const sayHello = (message) => {
  document.getElementById("message").innerHTML = message;
};

document.getElementById('msgBtn').addEventListener('click', () => {
  hello()
  .then(res => sayHello(res));
});

Verify it works by building and refreshing index.html. It should say, “hello world.”

Check the code in.

In Conclusion

Promises in ES6 are not difficult, although they can be cumbersome if there are a lot of nested Promises. The new—and, as of yet, not completely supported—ES7 feature, async/await, is meant to simplify nested Promises. I’ll write about that in a future post. You can find the CLI Promise code in my github repository, promises.

Copyright ©2014-17 Ramona Ridgewell. All rights reserved.

Posted in #Education, AmWriting, Coding, Education, JavaScript, Programming, Software Development, Writing | Tagged , , , , , , | 2 Comments