SWE 432, Fall 2018, Homework 1, Due Sept 17, 10 am

Please post questions on Piazza


  • 8/31: Renamed “addMemeConfiguration” to “addMemeTemplate” — it is expected to process meme templates, not configurations.
  • 9/5: Added hint for part 1
  • 9/7: Clarified some of the test specifications
  • 9/12: Added example for addMemeTemplate
  • 9/13: Added link to Jest’s promise error handling docs

Project Overview

This semester, while you learn the key concepts of web application development, you will apply these skills to build a meme generator, which we will refer to as the Memebase. A meme is a cultural phenomenon that combines some popular graphic (for example, a cat or TV/movie character) with large-block text. As an example, here is a meme generated by combining a graphic called “news cat” with some text relevant to this project:

You will build the Memebase in four different components; each assignment will be one component. Each component will conform to a common interface, allowing them to be independently developed and tested. The final result will be a working website that allows users to generate memes, create accounts to share and track their memes.

This Assignment

For the first component of the Memebase (this assignment), you will build a simple JavaScript (nodejs) application that takes as input a JSON file of desired memes and generates as output the finished graphics by overlaying text on those graphics. This tool will run on the command line.

Getting Started

You’ll need to install Node.js on your computer — version 8 or higher. You can follow the instructions on the Node.js installation page for the “LTS” version to get it installed.

You’ll also need to install GraphicsMagick on your computer. Windows users can use the GraphicsMagick installer package. Mac users can install homebrew, then run brew install graphicsmagick in the terminal. Linux users should use whatever package manager they use to install graphicsmagick.

Note – After installing Node and GraphicsMagick, to make sure it works in your command shell, you should close your shell and open a fresh one.

Finally, it is not required that you use an IDE, but it’s a really really really really good idea. JetBrains’ IntelliJ/WebStorm is a great choice — if you already have IntelliJ you can add the NodeJS component to it, or simply download WebStorm. You can get a free license to use any of the JetBrains IDEs by filling out this simple form.

Then, you are ready to get started. Download the handout, extract it, and then open a terminal in the handout directory. Run the command  npm install, which will download all of the JavaScript modules that the assignment will use.

Important note: DO NOT MAKE CHANGES TO PACKAGE.JSON; DO NOT INSTALL NEW PACKAGES. When we grade your project, we will grade it using the original package.json file!

The handout contains a few stubbed out JavaScript files:

MemeGenerator.js – An (empty) class file that you’ll implement the meme generator in by implementing the following methods:

index.js – a very simple driver that demonstrates the usage of the meme generator

MemeGenerator.tests.js – Automated tests for the MemeGenerator

As well as a few data files:

meme-data.json – A JSON file describing the different meme templates that your meme generator will support. A meme template consists of a reference to a graphic, and a description of the various text areas and formats that the graphic supports. For instance, here is the description of the Gru meme template:

Each text block is a stand-in for text that can be placed in by the meme builder. The location is specified in x/y pixel coordinates, and/or using GraphicsMagick’s gravity parameter.

The template file also defines default text positioning (for 1 line centered at the top and 1 line centered at the bottom), making it easy to add many meme templates that use that same standard text formatting, for example:

Since there is no  text element defined here, the meme generator will inherit the element from the  default template.

sample-memes.json – Defines some meme configurations that you can use to test your meme generator. Example:

This configuration defines a meme that will get output to a file named  You-Get-A-Meme.png, using the meme template named  Oprah, and defining text for both the  top and bottom position (which are defined in the template). Note that if you would like a line break to appear in the text, use the \n escape character. If you would like quotes, they also need to be escaped (e.g. ” becomes \”).

The assignment is broken up into three components:

Part 1 (30 points): Reading and Checking JSON files

The first step will be reading in the list of meme templates and configurations and validating them. You should implement the functions constructor, addMemeTemplate and   validateMeme in MemeGenerator.js. You should partially implement  generateMeme, stubbing it to simply call  validateMeme (no need to generate the graphic yet).

When the  constructor is called, it will be passed the name of a JSON file with the same structure as  meme-data.json. You should parse the JSON file in and store the information about each meme template as an instance field of the  MemeGenerator. You should implement  addMemeTemplate to take a single meme template as input and add it to that same internal data-structure (for later use).

Added 9/5: Hints – You should check out the built-in function  JSON.parse for converting JSON into a JS object; you should check out  fs.readFileSync to see how to read the contents of a file into a string (which perhaps then you might parse into a JS object).

Added 9/12: Hint – Here is an example object that might be passed to addMemeTemplate:
g.addMemeTemplate({        "Example": {            "graphic": "resources/example.jpg"        }    }); When  generateMeme is called, you’ll pass the meme configuration on to  validateMeme, which will do some sanity checking on both the meme configuration and the meme template. Specifically, it will check for:

  • If the requested meme template exists (aka, check meme.meme). If not, validateMeme should return the error message
  • If the meme configuration references text fields that don’t exist for that meme template ( meme.text), it should return the error message:
  • If the graphic file defined by the meme template ( meme.graphics) doesn’t exist, it should return the message
generateMeme must return a promise — so at this point, it should return a new Promise, which will be rejected if there is an error, or resolved otherwise.

Part 1 will be graded with 4 automated tests (6 points each), plus 6 points from manual inspection. These automated tests are  not included with the handout, but will run when you submit on Autolab (see part 2).

Part 2 (20 points): Writing Your Own Tests

We have written four automated tests for part 1 to check the error handling. Before moving on to actually generating graphics, you will implement the same tests yourselves. This will  help you to get your feet with with writing tests for JS, and also with using asynchronous Promises.

Implement the following four tests:

Note (9/7): The above test should be specifying text for a meme, specifying a text block that doesn’t exist.

Note (9/7): The above test should be checking the “name” field of a meme configuration

Note (9/7): The above test should be specifying a “top” or “bottom” text for a meme that uses a meme template that has “text” blocks defined, but does not have “top” or “bottom” as valid options.

You can consult the Jest API for pointers on how to structure these tests. The logic of these tests should be self explanatory based on the title of the test, if in doubt, post on Piazza.

Hint: look carefully at the doc example to test promises returning errors – in particular, the use of catch, and that return.

The tests must interact with the MemeGenerator only with the methods  constructoraddMemeTemplate, and  generateMeme — they must not call  validateMeme directly, and must not access any fields of your MemeGenerator or call any other methods of it. Beware that generateMeme returns a promise — you must write your tests to await the completion of the call.

Part 2 will be graded using known correct and incorrect implementations of the  MemeGenerator class — your tests should pass on the correct implementation and fail on the wrong implementations. You will not have access to our correct or incorrect implementations of the MemeGenerator — but each time that you submit on AutoLab you’ll get the results. For each of the four tests, you will receive up to 5 points. You’ll get 4 points if your test passes and fails when it should, plus 1 point from manual inspection. A test that passes always or fails always will receive 0 points.

Part 2 (50 points): Generating Graphics

Finally! Once you have all of the data loaded in, we get to the fun part – generating the graphics. You will do this in the  generateMeme function using the gm package (the steps above handled the installation so you should be good to go). Given a meme configuration and its corresponding template, you will:

  1. Read the template image into NodeJS using the gm() function, and resize it to 600px width
  2. For each text block that is defined by the template (and configured by the meme configuration), you will:
    1. Set the stroke width and stroke color (if it’s not 0)
    2. Set the text font size and font
    3. Set the fill color
    4. Draw the requested text, using the location (x, y, and gravity) defined by the template and text string defined by the configuration
  3. Add the text “SWE 432” without quotes in the bottom left of the image, specifically:
    1. Using font Impact (included in the project, easily referenced as  "./resources/Impact.ttf"), size 14
    2. Using a black stroke of size 1 and a white fill
    3. Draw the text “SWE 432” at the x,y offset of 5,5 from the gravity location “SouthWest”
  4. Write the image out to disk at the specified location ( name in the meme configuration). WARNING: the “write” function in gm is asynchronous — so you will need to use a callback to find out when the image has been written out.
    1. If this succeeds, resolve the promise
    2. If this fails, reject the promise, passing the error

To successfully pass the tests, you will need to perform these steps precisely. In particular, you must make sure to only resolve the promise after writing the image to disk succeeds.

Hint: the following functions from gm are probably useful to look at;

  • font
  • resize
  • stroke
  • fill
  • drawText
  • write

You can run your meme generator for testing purposes on a few inputs by running the  index.js file (e.g.  node index.js), which will attempt to generate a variety of memes.

You can automatically check your generated files for conformance by running npm test. When you run  npm test, the generated images are checked against our reference memes (in the  reference-images directory); any discrepancies are reported graphically. For instance, here is the debugging output from an incorrect implementation of the meme generator that does not add the “SWE 432”:

Most of the image is spot-on: this is the part that is faded out. The red/yellow in the bottom left is indicating that that part of the image is incorrect.

Part 3 will be graded primarily by the automated test suite (which is available to you both locally with npm test and also runs when you submit to AutoLab). There are 4 tests, worth 10 points each; the remaining 10 points will be assigned from manual code review.


Your meme generator will be graded for correctness using a series of automated tests, and also by hand (as described in each section above). When you submit to Autolab, it will assume that you receive full marks from the manual grading component (6 points for part 1, 5 points for part 2 and 10 points for part 3); this may of course go down when we actually grade your final submission. We are primarily looking for basic code quality (naming, indentation, etc), as well as correctness with handling asynchronous operations (which are incredibly tricky to check automatically).

Hand In Instructions

You must turn in your assignment using Autolab (You MUST be on the campus network, or connected to the GMU VPN to connect to Autolab). If you did not receive a confirmation email from Autolab to set a password, enter your @gmu.edu (NOT @masonlive) email, and click “forgot password” to get a new password.

To prepare your code to be submitted, run npm pack in the assignment directory. This will create an archive  thememebase-1.0.0.tgz – this is what you will submit to Autolab. Do not try and generate this archive without using  npm; it’s highly likely to cause Autolab to reject it. When you upload your assignment, Autolab will automatically compile and test it. You should verify that the result that Autolab generates is what you expect. Your code is built and tested in a Linux VM. Assignments that do not compile using our build environment will receive a maximum of 50%. Note that we have provided ample resources for you to verify that our view of your assignment is the same as your own: you will see the result of the compilation and test execution for your assignment when you submit it.

Important note: You must manually delete the generated file thememebase-1.0.0.tgz each time after you submit, before you do npm pack again. Otherwise the old submission gets included in your next submission, making the submitted file too large. It will be rejected by Autolab immediately if the archive is too large.

You can resubmit your assignment an unlimited number of times before the deadline. Note the course late-submission policy: assignments will be accepted up until 24 hours past the deadline at a penalty of 10%; after 24 hours, no late assignments will be accepted, no exceptions.


Please post questions on Piazza