What to hand in, and how to hand it in
- Make a directory
~fcshome/cs2613/assigments/A3
(i.e. in your git repo for this class). All files related to this assignment should be saved in that directory. - Make sure you commit and push all your work using coursegit before 16:30 on Friday October 21
Background
This assignment is to write several functions to extract information from some JSON files. Conceptually this is very similar to the second part of L06, except that here you are working in JavaScript rather than Racket. The specifics of working with JSON in JavaScript are covered in L09.
Marking
- This assignment will be worth 5% of your final grade.
- You will be marked on the last version pushed to coursegit
You will be marked on
- coding style
- Follow the Crockford style guide
- functional JavaScript
- Part of the point of the assignment is to see that a certain tasks can be accomplished in a very similar way in JavaScript as in Racket. So don't go crazy with mutation.
- testing
- Remember to have full test coverage. In addition to line based coverage using
nyc jasmine
, what kinds of input your code should handle.
For detailed marking scheme, see javascript-assignment.
Test Data
There are three sample JSON files provided for you, output from mailing lists generated by notmuch-show
In order to read JSON from a file, you can use the following function
let fs = require('fs');
function read_json_file(filename) {
let contents = fs.readFileSync(filename);
return JSON.parse(contents);
}
exports.read_json_file=read_json_file;
Question 1: match
function
Write an match
function. This method takes a JavaScript object
representing a mail message, and a second object defining header
fields that must match match.
Make a module message.js
that passes at least the following tests
(the tests should be saved as spec/message.spec.js
; refer to
L09 for an introduction to jasmine
):
let read_json_file = require("../read_json_file.js").read_json_file;
let message = require("../message.js");
let testMsg = {"headers": {"Subject" : "lunch", "Date" : "now"}};
let otherMsg = {"headers": {"Subject" : "dinner", "Date" : "now"}};
describe("match",
function() {
it("message matches itself",
function () {
expect(message.match(testMsg,testMsg.headers)).toEqual(true);
});
it("message does not match if field changes",
function () {
expect(message.match(testMsg,otherMsg.headers)).toEqual(false);
});
it("match subset of fields",
function () {
expect(message.match(testMsg,{"Subject": "lunch"})).toEqual(true);
});
Question 2: extracting message bodies.
Depending on the MIME structure of the given email, the message body is represented differently in the resulting JSON. Your task in this part is to reverse engineer those (2) representations and provide uniform output of the body. The JSON structure looks complicated, and in general it can be (as MIME messages can be complicated). To explore the JSON structure, you can view the JSON file in Firefox.
In this sample data there are only two cases, tested below. It is possible to extract the body text with a relatively small amount of code.
Write a function and export it as message.body
so that (at least)
the following tests pass:
describe("message body",
function () {
it("unsigned message",
function () {
let message_objects=read_json_file("example1.json").flat(Infinity);
let msg = message_objects.filter((m) => message.match(m,{ "From": "Aron Griffis <agriffis@n01se.net>"}))[0];
expect(msg).not.toEqual(null);
expect(message.body(msg)).toEqual(`Just subscribed, I'd like to catch up on the previous postings,
but the archive link seems to be bogus?
Thanks,
Aron
`);
});
it("signed message",
function () {
let message_objects=read_json_file("example2.json").flat(Infinity);
let msg = message_objects.filter((m) => message.match(m,{"From": "md@Linux.IT (Marco d'Itri)"}))[0];
expect(msg).not.toEqual(null);
expect(message.body(msg)).toEqual(`On Sep 09, Sean Whitton <spwhitton@spwhitton.name> wrote:
> 1. Is the 'should not' for the /etc/default practice too strong? I
No, because it cannot be supported in a sane way by systemd units.
It should even be "must not".
--
ciao,
Marco
`);
});
});
Output messages as strings.
Like Java, JavaScript objects have a toString
method that can be
overridden to give a more useful output. We will talk about classes
and inheritence in the lab, but for now we just write a simple
function and export it as message.string
, so that at least the
following tests pass. Note that you need to match the given output
order of headers, and add a blank line between the body and the
headers (but only if the body is actually present).
let fullHeaderMsg ={"headers": {
"Subject": "[notmuch] archive",
"From": "Aron Griffis <agriffis@n01se.net>",
"To": "notmuch <notmuch@notmuchmail.org>",
"Date": "Tue, 17 Nov 2009 18:21:38 -0500"
}};
describe("toString",
function () {
it("works with no body",
function () {
expect(message.string(testMsg)).toEqual(`Date: now
Subject: lunch
`);
});
it("full set of headers",
function() {
expect(message.string(fullHeaderMsg)).toEqual(`From: Aron Griffis <agriffis@n01se.net>
Date: Tue, 17 Nov 2009 18:21:38 -0500
Subject: [notmuch] archive
To: notmuch <notmuch@notmuchmail.org>
`);
});
});
describe("toString real data",
function () {
it("unsigned message",
function () {
let message_objects=read_json_file("example1.json").flat(Infinity);
let msg = message_objects.filter((m) => message.match(m,{ "From": "Aron Griffis <agriffis@n01se.net>"}))[0];
expect(msg).not.toEqual(null);
expect(message.string(msg)).toEqual(`From: Aron Griffis <agriffis@n01se.net>
Date: Tue, 17 Nov 2009 18:21:38 -0500
Subject: [notmuch] archive
To: notmuch <notmuch@notmuchmail.org>
Just subscribed, I'd like to catch up on the previous postings,
but the archive link seems to be bogus?
Thanks,
Aron
`);
});
it("signed message",
function () {
let message_objects=read_json_file("example2.json").flat(Infinity);
let msg = message_objects.filter((m) => message.match(m,{"From": "md@Linux.IT (Marco d'Itri)"}))[0];
expect(msg).not.toEqual(null);
expect(message.string(msg)).toEqual(`From: md@Linux.IT (Marco d'Itri)
Date: Sun, 10 Sep 2017 09:48:44 +0200
Subject: Bug#601455: Steps towards a patch to document disabling a daemon upon installation
To: debian-policy@lists.debian.org
On Sep 09, Sean Whitton <spwhitton@spwhitton.name> wrote:
> 1. Is the 'should not' for the /etc/default practice too strong? I
No, because it cannot be supported in a sane way by systemd units.
It should even be "must not".
--
ciao,
Marco
`);});
});