Skip to content

Commit

Permalink
- added quizCount to the return values from parse
Browse files Browse the repository at this point in the history
  • Loading branch information
Jon Sullivan committed Feb 12, 2014
1 parent 00d4fd9 commit 4bf4474
Show file tree
Hide file tree
Showing 5 changed files with 49 additions and 86 deletions.
6 changes: 2 additions & 4 deletions index.js
Expand Up @@ -8,21 +8,19 @@ var parseManifestXml = require('./parseManifestXml.js');

function scoParser(params) {
params = params || {};
var imsManifestJSON;

function validate(cb) {
async.series({
unpackScoZip: _.curry(unpackScoZip)(params),
manifest: _.curry(readManifestXml)(params)
}, function (err, result) {
if(err) cb(err);
imsManifestJSON = result.manifest;
cb(null, imsManifestJSON);
cb(null, result.manifest);
});
}

function parse(cb) {
parseManifestXml(imsManifestJSON, cb);
parseManifestXml(params, cb);
}

function destroy(cb) {
Expand Down
10 changes: 7 additions & 3 deletions package.json
@@ -1,6 +1,6 @@
{
"name": "sco-parser",
"version": "0.0.1",
"version": "0.0.2",
"description": "A simple validator and parser for SCO zip files.",
"main": "index.js",
"directories": {
Expand All @@ -15,7 +15,9 @@
},
"keywords": [
"SCORM",
"SCO"
"SCO",
"SCORM 1.2",
"LMS"
],
"author": "Mindflash <npmjs@mindflash.com>",
"license": "MIT",
Expand All @@ -31,6 +33,8 @@
"async": "~0.2.10",
"lodash": "~2.4.1",
"rimraf": "~2.2.6",
"xml2js": "~0.4.1"
"xml2js": "~0.4.1",
"xpath": "0.0.5",
"xmldom": "~0.1.19"
}
}
63 changes: 26 additions & 37 deletions parseManifestXml.js
@@ -1,45 +1,34 @@
"use strict";

var xpath = require('xpath');
var dom = require('xmldom').DOMParser;
var fs = require('fs');
var _ = require('lodash');
var async = require('async');

module.exports = function(manifestJSON, cb) {
async.series({
scoHtmlHref: getScoHtmlHref
}, function (err, result) {
if(err) cb(err);
cb(null, result);
});
module.exports = function(params, cb) {
var params = params || {};
if (!params.pathToExtractZip) return cb('Requires a path in which to find the SCO manifest XML');

fs.readFile(params.pathToExtractZip + '/imsmanifest.xml', 'ascii', function(err, data) {
if (err) return cb(err);

function getScoHtmlHref(cb) {
var scoResource = getScoResource(manifestJSON);
if(!scoResource) return cb(null);
var href = scoResource.href;
if(!href || href == '') return cb(null);
cb(null, href);
}
var doc = new dom().parseFromString(data.substring(2, data.length));

function getScoResource(json) {
if(!json) return null;
var manifest = json.manifest;
if(!manifest) return null;
var resources = manifest.resources;

This comment has been minimized.

Copy link
@maxnachlinger

maxnachlinger Feb 12, 2014

Contributor

Defining a function inside the fs.readFile cb isn't wrong, but it's not what one would expect.

function findIndexFile() {
var nodes = xpath.select("(//resource[@href])[1]", doc);
var attr = nodes[0].attributes;
var filename = attr[_.findKey(attr, { 'name': 'href' })].value;
return filename;
}

var scoResource = null;
_.each(resources, function(resourcesItem) {
if(!resourcesItem) return;
_.each(resourcesItem, function (resourceItem) {
if(!resourceItem) return;
_.each(resourceItem, function (resourceInfoItem) {
if(!resourceInfoItem) return;
var resource = resourceInfoItem.$;
if(!resource) return;
var type = resource.type ? resource.type.toLowerCase() : null;
var scormType = resource['adlcp:scormtype'] ? resource['adlcp:scormtype'].toLowerCase() : null;
if(type != 'webcontent' || scormType != 'sco') return;
scoResource = resource;
});
});
function findQuizCount() {
var nodes = xpath.select("//*[name()='adlcp:masteryscore']", doc);
return nodes.length;
}

return cb(null, {
scoHtmlHref: findIndexFile(),
quizCount: findQuizCount()
});
return scoResource;
}
});
};
15 changes: 5 additions & 10 deletions tests/indexTests.js
Expand Up @@ -2,34 +2,29 @@
var fs = require('fs');
var test = require('tap').test;
var scoParserIndex = require('../index.js');
var testFolder = 'testFiles/unpackScoZipTests';
var pathToExtractZip = 'testFiles/unpackScoZipTests/extractFolder';

var params = {
pathToScoZip: testFolder + '/articulate_sco_with_quiz.zip',
pathToExtractZip: pathToExtractZip
pathToScoZip: 'testFiles/unpackScoZipTests/articulate_sco_with_quiz.zip',
pathToExtractZip: 'testFiles/unpackScoZipTests/extractFolder'
};

test('Successfully unpacks SCO zip file, validates imsmanifest.xml, and parses it for information', function(t) {
var params = {
pathToScoZip: testFolder + '/articulate_sco_with_quiz.zip',
pathToExtractZip: pathToExtractZip
};
var scoParser = scoParserIndex(params);
t.test('Should extract SCO zip file and validate imsmanifest.xml', function (t) {
scoParser.validate(function (err, result) {
t.notOk(err, 'Should not error');
t.ok(fs.existsSync(pathToExtractZip), 'Should have created path in which to extract zip');
t.ok(fs.existsSync(params.pathToExtractZip), 'Should have created path in which to extract zip');
t.ok(result, 'Should receive XML JSONified');
t.end();
});
});

t.test('Should parse imsmanifest.xml to find base html file', function(t) {
scoParser.parse(function (err, result) {
scoParser.parse(function (err, result) {

This comment has been minimized.

Copy link
@maxnachlinger

maxnachlinger Feb 12, 2014

Contributor

Crazy tabs!

t.notOk(err, 'Should not error');
t.ok(result, 'Should receive information parsed from the manifest XML');
t.equal(result.scoHtmlHref, 'index_lms.html', 'Should receive the SCO\'s start-up HTML file from the manifest');
t.equal(result.quizCount, 1, 'Finds a quiz in the sco');
t.end();
})
});
Expand Down
41 changes: 9 additions & 32 deletions tests/parseManifestXmlTests.js
@@ -1,51 +1,28 @@
var test = require('tap').test;
var parseManifestXml = require('../parseManifestXml.js');
var readManifestXml = require('../readManifestXml.js');

test('Finds SCO HTML file href in Articulate SCO', function(t) {
var manifestJSON;

t.test('Reads SCO XML file', function (t) {
t.test('Finds quiz in SCO', function (t) {
var params = {pathToExtractZip: 'testFiles/parseManifestXmlTests/articulate/scoWithQuiz'};
readManifestXml(params, function (err, result) {
t.notOk(err, 'Should not error');
t.ok(result, 'Should receive XML JSONified');
manifestJSON = result;
t.end();
});
});

t.test('Finds SCO HTML file href in read XML', function (t) {
parseManifestXml(manifestJSON, function (err, result) {
parseManifestXml(params, function (err, result) {
t.notOk(err, 'Should not error');
t.ok(result, 'Should receive information parsed from the manifest XML');
t.equal(result.scoHtmlHref, 'index_lms.html', 'Should receive the SCO\'s start-up HTML file from the manifest');
t.equal(result.scoHtmlHref, 'index_lms.html', 'got a starting point');
t.equal(result.quizCount, 1, 'Recognize that a quiz exists in the sco');
t.end();
});
});
t.end();
});

test('Finds SCO HTML file href in Captivate SCO', function(t) {
var manifestJSON;

t.test('Reads SCO XML file', function (t) {
t.test('Finds no quiz in SCO', function (t) {
var params = {pathToExtractZip: 'testFiles/parseManifestXmlTests/captivate/scoWithNoQuizAndSwfAndHtml5Outputs'};
readManifestXml(params, function (err, result) {
t.notOk(err, 'Should not error');
t.ok(result, 'Should receive XML JSONified');
manifestJSON = result;
t.end();
});
});

t.test('Finds SCO HTML file href in read XML', function (t) {
parseManifestXml(manifestJSON, function (err, result) {
parseManifestXml(params, function (err, result) {
t.notOk(err, 'Should not error');
t.ok(result, 'Should receive information parsed from the manifest XML');
t.equal(result.scoHtmlHref, 'multiscreen.html', 'Should receive the SCO\'s start-up HTML file from the manifest');
t.equal(result.scoHtmlHref, 'multiscreen.html', 'got a starting point');
t.equal(result.quizCount, 0, 'Finds no quizzes in the sco');
t.end();
});
});

t.end();
});

0 comments on commit 4bf4474

Please sign in to comment.