summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorSam Spilsbury <smspillaz@gmail.com>2013-12-17 14:40:47 -0800
committerPhilip Chimento <philip@endlessm.com>2014-01-17 10:46:11 -0200
commit29b69c9c974b40727b95e1f96b16058a34ab9a54 (patch)
tree47c44ba9e9951c15c123cf27160476b24f6ced92 /test
parent3b818a6587c015a3ac6d4afcbc8abc04bcd7b194 (diff)
Move to JS tests to Jasmine
[endlessm/eos-sdk#444]
Diffstat (limited to 'test')
-rw-r--r--test/Makefile.am.inc7
-rw-r--r--test/smoke-tests/webhelper/webview.js (renamed from test/webhelper/smoke-tests/webview.js)0
-rw-r--r--test/webhelper/testTranslate.js117
-rw-r--r--test/webhelper/testWebActions.js215
-rw-r--r--test/wikipedia/models/testArticleModel.js172
-rw-r--r--test/wikipedia/models/testCategoryModel.js248
-rw-r--r--test/wikipedia/models/testDomainWikiModel.js346
7 files changed, 654 insertions, 451 deletions
diff --git a/test/Makefile.am.inc b/test/Makefile.am.inc
index 826824f..08dd5e8 100644
--- a/test/Makefile.am.inc
+++ b/test/Makefile.am.inc
@@ -14,7 +14,6 @@ include test/demos/Makefile.am.inc
include test/smoke-tests/Makefile.am.inc
javascript_tests = \
- test/tools/eos-run-test/sanitycheck.js \
test/tools/eos-application-manifest/testInit.js \
test/webhelper/testTranslate.js \
test/webhelper/testWebActions.js \
@@ -29,8 +28,7 @@ TESTS = \
test/endless/run-tests \
$(javascript_tests) \
$(NULL)
-TEST_EXTENSIONS = .js
-JS_LOG_COMPILER = tools/eos-run-test
+TEST_EXTENSIONS =
AM_JS_LOG_FLAGS = \
--include-path=$(top_srcdir)/webhelper \
--include-path=$(top_srcdir) \
@@ -38,6 +36,9 @@ AM_JS_LOG_FLAGS = \
LOG_COMPILER = gtester
AM_LOG_FLAGS = -k --verbose
+JASMINE_SUBMODULE_PATH = $(top_srcdir)/test/jasmine
+include test/jasmine/Makefile-jasmine.am.inc
+
# Use locally built versions of Endless-0.gir and libraries; this may need to be
# changed to AM_TESTS_ENVIRONMENT in a future version of Automake
# Set XDG_CONFIG_HOME so as to avoid cluttering the user's actual config
diff --git a/test/webhelper/smoke-tests/webview.js b/test/smoke-tests/webhelper/webview.js
index a3b91e5..a3b91e5 100644
--- a/test/webhelper/smoke-tests/webview.js
+++ b/test/smoke-tests/webhelper/webview.js
diff --git a/test/webhelper/testTranslate.js b/test/webhelper/testTranslate.js
index 009efaf..f4d4f68 100644
--- a/test/webhelper/testTranslate.js
+++ b/test/webhelper/testTranslate.js
@@ -5,14 +5,20 @@ const Lang = imports.lang;
const WebHelper = imports.webhelper;
const WebKit = imports.gi.WebKit;
-const TestClass = new Lang.Class({
- Name: 'testclass',
+const WebHelperApplicationWithTranslatableText = new Lang.Class({
+ Name: 'WebHelperApplicationWithTranslatableText',
Extends: WebHelper.Application,
+
+ get_translation_string: function() {
+ return 'Translate Me';
+ },
vfunc_startup: function() {
this.parent();
this.webview = new WebKit.WebView();
- let string = '<html><body><p name="translatable">Translate Me</p></body></html>';
+ let string = '<html><body><p name="translatable">' +
+ this.get_translation_string() +
+ '</p></body></html>';
this.webview.load_string(string, 'text/html', 'UTF-8', 'file://');
this.win = new Endless.Window({
application: this
@@ -36,62 +42,67 @@ const TestClass = new Lang.Class({
}
});
-let app;
+describe("Translation strategy", function() {
+ let app;
-function setUp() {
- // Generate a unique ID for each app instance that we test
- let fake_pid = GLib.random_int();
- // FIXME In this version of GJS there is no Posix module, so fake the PID
- let id_string = 'com.endlessm.webhelper.test' + GLib.get_real_time() + fake_pid;
- app = new TestClass({
- application_id: id_string
+ beforeEach(function() {
+ // FIXME In this version of GJS there is no Posix module, so fake the PID
+ let id_string = 'com.endlessm.webhelper.test' + GLib.get_real_time() + fake_pid;
+ // Generate a unique ID for each app instance that we test
+ let fake_pid = GLib.random_int();
+ app = new WebHelperApplicationWithTranslatableText({
+ application_id: id_string
+ });
});
-}
-
-function testStringIsTranslated() {
- let translationFunctionWasCalled = false;
- let translationFunctionCalledWithString;
- app.set_translation_function(function(s) {
- translationFunctionWasCalled = true;
- translationFunctionCalledWithString = s;
- return s;
+
+ describe("translation function", function() {
+ let translationFunctionSpy;
+ beforeEach(function() {
+ translationFunctionSpy = jasmine.createSpy('translate').and.returnValue('Translated');
+ });
+ it("gets called with string to translate on run", function() {
+ app.set_translation_function(translationFunctionSpy);
+ app.run([]);
+ expect(translationFunctionSpy).toHaveBeenCalledWith(app.get_translation_string());
+ });
});
- app.run([]);
- assertTrue(translationFunctionWasCalled);
- assertEquals('Translate Me', translationFunctionCalledWithString);
-}
-
-// The following test is commented out because GJS cannot catch exceptions
-// across FFI interfaces (e.g. in GObject callbacks.)
-// function testMissingTranslationFunctionIsHandled() {
-// assertRaises(function() {
-// app.run([]);
-// });
-// }
+ it("throws when an incompatible type is set as the translation function", function() {
+ expect(function() {
+ app.set_translation_function({});
+ }).toThrow();
+ });
-function testSetBadTranslationFunction() {
- assertRaises(function() {
- app.set_translation_function("I am not a function");
+ // Can't test this right now as there is no support for propagating exceptions across
+ // GI interfaces
+ xit("throws when there isn't a translation function set", function() {
+ expect(function() {
+ app.run([]);
+ }).toThrow();
});
-}
-function testGetSetTranslationFunction() {
- let translationFunction = function(string) {
- return string;
- };
- app.set_translation_function(translationFunction);
- let actualTranslationFunction = app.get_translation_function();
- assertEquals(translationFunction, actualTranslationFunction);
-}
+ it("has a null translation function by default", function() {
+ expect(app.get_translation_function()).toBe(null);
+ });
-function testTranslationFunctionIsNullByDefault() {
- assertNull(app.get_translation_function());
-}
+ it("stores the expected translation function", function() {
+ let translation = function(str) {
+ return str;
+ };
+
+ app.set_translation_function(translation);
+ expect(app.get_translation_function()).toBe(translation);
+ });
-function testGetSetNullTranslationFunction() {
- app.set_translation_function(function (s) { return s; });
- assertNotNull(app.get_translation_function());
- app.set_translation_function(null);
- assertNull(app.get_translation_function());
-}
+ it("allows us to store a null translation function", function() {
+ let nonNullTranslation = function(str) {
+ return str;
+ }
+
+ // set a non-null translation function first so that we get
+ // the non-default behaviour for get_translation_function
+ app.set_translation_function(nonNullTranslation);
+ app.set_translation_function(null);
+ expect(app.get_translation_function()).toBe(null);
+ });
+});
diff --git a/test/webhelper/testWebActions.js b/test/webhelper/testWebActions.js
index 8c790b2..b2ddaf0 100644
--- a/test/webhelper/testWebActions.js
+++ b/test/webhelper/testWebActions.js
@@ -6,8 +6,8 @@ const Lang = imports.lang;
const WebHelper = imports.webhelper;
const WebKit = imports.gi.WebKit;
-const TestClass = new Lang.Class({
- Name: 'testclass',
+const WebActionTestApplication = new Lang.Class({
+ Name: 'WebActionTestApplication',
Extends: WebHelper.Application,
vfunc_startup: function() {
@@ -33,128 +33,113 @@ const TestClass = new Lang.Class({
}
});
-let app;
+// TODO: These tests depend on a running X Server and Window Manager. That means
+// that they are not runnable in a continuous-integration server
+describe("Web Actions Bindings", function() {
+ let app;
+ let webActionSpy;
+
+ beforeEach(function() {
+ // Generate a unique ID for each app instance that we test
+ let fake_pid = GLib.random_int();
+ // FIXME In this version of GJS there is no Posix module, so fake the PID
+ let id_string = 'com.endlessm.webhelper.test' + GLib.get_real_time() + fake_pid;
+ app = new WebActionTestApplication({
+ application_id: id_string
+ });
+ webActionSpy = jasmine.createSpy('quitAction').and.callFake(function() {
+ app.quit();
+ });
+ });
+
+ let RunApplicationWithWebAction = function(app, action) {
+ app.webActionToTest = action;
+ app.run([]);
+ }
+ it("has a working quitApplication uri upon defining quitApplication as a string", function() {
+ app.define_web_action('quitApplication', webActionSpy);
+ RunApplicationWithWebAction(app, 'endless://quitApplication');
-function setUp() {
- // Generate a unique ID for each app instance that we test
- let fake_pid = GLib.random_int();
- // FIXME In this version of GJS there is no Posix module, so fake the PID
- let id_string = 'com.endlessm.webhelper.test' + GLib.get_real_time() + fake_pid;
- app = new TestClass({
- application_id: id_string
+ expect(webActionSpy).toHaveBeenCalled();
});
-}
-function testWebActionIsCalled() {
- let actionWasCalled = false;
- app.define_web_action('quitApplication', function() {
- actionWasCalled = true;
- app.quit();
+ it("is called with a parameter", function() {
+ app.define_web_action('getParameterAndQuit', webActionSpy);
+ RunApplicationWithWebAction(app, 'endless://getParameterAndQuit?param=value');
+
+ expect(webActionSpy).toHaveBeenCalledWith(new jasmine.ObjectContaining({ param: 'value' }));
});
- app.webActionToTest = 'endless://quitApplication';
- app.run([]);
- assertTrue(actionWasCalled);
-}
-
-function testWebActionIsCalledWithParameter() {
- let actionParameter;
- app.define_web_action('getParameterAndQuit', function(dict) {
- actionParameter = dict['param'];
- app.quit();
+
+ it("can be called with many parameters", function() {
+ app.define_web_action('getParametersAndQuit', webActionSpy);
+ RunApplicationWithWebAction(app, 'endless://getParametersAndQuit?first=thefirst&second=thesecond&third=thethird');
+
+ expect(webActionSpy).toHaveBeenCalledWith(new jasmine.ObjectContaining({
+ first: 'thefirst',
+ second: 'thesecond',
+ third: 'thethird'
+ }));
});
- app.webActionToTest = 'endless://getParameterAndQuit?param=value';
- app.run([]);
- assertEquals('value', actionParameter);
-}
-
-function testWebActionIsCalledWithManyParameters() {
- let firstParameter, secondParameter, thirdParameter;
- app.define_web_action('getParametersAndQuit', function(dict) {
- firstParameter = dict['first'];
- secondParameter = dict['second'];
- thirdParameter = dict['third'];
- app.quit();
+
+ it("decodes parameter URI names", function() {
+ app.define_web_action('getUriDecodedParameterAndQuit', webActionSpy);
+ RunApplicationWithWebAction(app, 'endless://getUriDecodedParameterAndQuit?p%C3%A4r%C3%A4m%F0%9F%92%A9=value');
+
+ expect(webActionSpy).toHaveBeenCalledWith(new jasmine.ObjectContaining({
+ 'päräm💩' : 'value'
+ }));
});
- app.webActionToTest = 'endless://getParametersAndQuit?first=thefirst&second=thesecond&third=thethird';
- app.run([]);
- assertEquals('thefirst', firstParameter);
- assertEquals('thesecond', secondParameter);
- assertEquals('thethird', thirdParameter);
-}
-
-function testParameterNameIsUriDecoded() {
- let expectedParameter = 'päräm💩';
- let parameterWasFound = false;
- app.define_web_action('getUriDecodedParameterAndQuit', function(dict) {
- parameterWasFound = (expectedParameter in dict);
- app.quit();
+
+ it("decodes parameter URI values", function() {
+ app.define_web_action('getUriDecodedParameterValueAndQuit', webActionSpy);
+ RunApplicationWithWebAction(app, 'endless://getUriDecodedParameterValueAndQuit?param=v%C3%A1lu%C3%A9%F0%9F%92%A9');
+
+ expect(webActionSpy).toHaveBeenCalledWith(new jasmine.ObjectContaining({
+ param : 'válué💩'
+ }));
});
- app.webActionToTest = 'endless://getUriDecodedParameterAndQuit?p%C3%A4r%C3%A4m%F0%9F%92%A9=value';
- app.run([]);
- assertTrue(parameterWasFound);
-}
-
-function testParameterValueIsUriDecoded() {
- let expectedValue = 'válué💩';
- let actualValue;
- app.define_web_action('getUriDecodedValueAndQuit', function(dict) {
- actualValue = dict['param'];
- app.quit();
+
+ // We currently can't catch exceptions across GObject-Introspection callbacks
+ xit('bad action is not called', function() {
+ expect(function() { RunApplicationWithWebAction(app, 'endless://nonexistentWebAction') }).toThrow();
});
- app.webActionToTest = 'endless://getUriDecodedValueAndQuit?param=v%C3%A1lu%C3%A9%F0%9F%92%A9';
- app.run([]);
- assertEquals(expectedValue, actualValue);
-}
-
-// This is commented out because GJS cannot catch exceptions across FFI
-// interfaces (e.g. in GObject callbacks.)
-// function testBadActionIsNotCalled() {
-// app.webActionToTest = 'endless://nonexistentAction?param=value';
-// assertRaises(function() { app.run([]); });
-// }
-
-function testWebActionIsCalledWithBlankParameter() {
- let parameterWasFound = false;
- let parameterValue;
- app.define_web_action('getBlankValueAndQuit', function(dict) {
- parameterWasFound = ('param' in dict);
- if(parameterWasFound)
- parameterValue = dict['param'];
- app.quit();
+
+ describe("with blank parameters", function() {
+ beforeEach(function() {
+ app.define_web_action('getBlankValueAndQuit', webActionSpy);
+ RunApplicationWithWebAction(app, 'endless://getBlankValueAndQuit?param=');
+ });
+
+ it("can be called", function() {
+ expect(webActionSpy).toHaveBeenCalled();
+ });
+
+ it("is called with a paramater that is an empty string", function() {
+ expect(webActionSpy).toHaveBeenCalledWith(new jasmine.ObjectContaining({
+ 'param' : ''
+ }));
+ });
});
- app.webActionToTest = 'endless://getBlankValueAndQuit?param=';
- app.run([]);
- assertTrue(parameterWasFound);
- assertNotUndefined(parameterValue);
- assertEquals('', parameterValue);
-}
-
-function testWebActionIsUriDecoded() {
- let actionWasCalled = false;
- app.define_web_action('äction💩Quit', function(dict) {
- actionWasCalled = true;
- app.quit();
+
+ it("URI decodes the action", function() {
+ app.define_web_action('äction💩Quit', webActionSpy);
+ RunApplicationWithWebAction(app, 'endless://%C3%A4ction%F0%9F%92%A9Quit');
+ expect(webActionSpy).toHaveBeenCalled();
});
- app.webActionToTest = 'endless://%C3%A4ction%F0%9F%92%A9Quit';
- app.run([]);
- assertTrue(actionWasCalled);
-}
-
-function testDefineMultipleActionsOverride() {
- let actionWasCalled = false;
- app.define_web_actions({
- quitApplication: function() {
- actionWasCalled = true;
- app.quit();
- }
+
+ it("allows web actions to be defined as object properties", function() {
+ app.define_web_actions({
+ quitApplication: webActionSpy
+ });
+
+ RunApplicationWithWebAction(app, 'endless://quitApplication');
+
+ expect(webActionSpy).toHaveBeenCalled();
});
- app.webActionToTest = 'endless://quitApplication';
- app.run([]);
- assertTrue(actionWasCalled);
-}
-
-function testDefineBadAction() {
- assertRaises(function() {
- app.define_web_action('badAction', 'not a function');
+
+ it("throws an error when trying to define an action that is not a function", function() {
+ expect(function() {
+ app.define_web_action('action', {});
+ }).toThrow();
});
-}
+});
diff --git a/test/wikipedia/models/testArticleModel.js b/test/wikipedia/models/testArticleModel.js
index 655f187..f916369 100644
--- a/test/wikipedia/models/testArticleModel.js
+++ b/test/wikipedia/models/testArticleModel.js
@@ -1,72 +1,110 @@
const ArticleModel = imports.wikipedia.models.article_model;
-let mockJsonData = {
- title: 'Article Title',
- url: 'file:///',
- source: 'Mock data',
- categories: [
- 'Category One',
- 'Category Two'
- ]
-};
-
-function _assertCategoryListHasIds(categoryList, idList) {
- assertEquals(idList.length, categoryList.length);
- idList.forEach(function (id) {
- assertTrue(categoryList.some(function (actualId) {
- return actualId == id;
- }));
- });
-}
-
-function testNewModelFromJson() {
- let model = ArticleModel.newFromJson(mockJsonData);
- assertTrue(model instanceof ArticleModel.ArticleModel);
- assertEquals('Article Title', model.title);
- assertEquals('file:///', model.uri);
- _assertCategoryListHasIds(model.getCategories(),
- ['Category One', 'Category Two']);
-}
-
-function testNewWithProperties() {
- let model = new ArticleModel.ArticleModel({
+describe("Wikipedia article model", function() {
+ let mockJsonData = {
title: 'Article Title',
- uri: 'file:///'
+ url: 'file:///',
+ source: 'Mock data',
+ categories: [
+ 'Category One',
+ 'Category Two'
+ ]
+ };
+
+ describe("from JSON", function() {
+ let model;
+
+ beforeEach(function() {
+ model = ArticleModel.newFromJson(mockJsonData);
+ });
+
+ it("has an article title", function() {
+ expect(model.title).toEqual(mockJsonData.title);
+ });
+
+ it("has a uri", function() {
+ expect(model.uri).toEqual(mockJsonData.url);
+ });
+
+ it("has a list of categories", function() {
+ expect(model.getCategories()).toEqual(mockJsonData.categories);
+ });
+ });
+
+ describe("from properties", function() {
+ let model;
+ beforeEach(function() {
+ model = new ArticleModel.ArticleModel({
+ title: 'Article Title',
+ uri: 'file://'
+ });
+ });
+
+ it("is an instance of an ArticleModel", function() {
+ expect(model instanceof ArticleModel.ArticleModel).toBeTruthy();
+ });
+
+ it("has a title", function() {
+ expect(model.title).toEqual('Article Title');
+ });
+
+ it("has a URI", function() {
+ expect(model.uri).toEqual('file://');
+ });
+
+ it("has no categories", function() {
+ expect(model.getCategories().length).toEqual(0);
+ });
+ });
+
+ describe("setCategories method", function() {
+ let model;
+
+ beforeEach(function() {
+ model = new ArticleModel.ArticleModel();
+ });
+
+ it("adds categories", function() {
+ let expectedCategories = ['One', 'Two', 'Three'];
+ model.setCategories(expectedCategories);
+ expect(model.getCategories()).toEqual(expectedCategories);
+ });
+
+ it("replaces existing categories", function() {
+ model.setCategories(['One', 'Two']);
+ let expectedCategories = ['One', 'Two', 'Three'];
+ model.setCategories(expectedCategories);
+ expect(model.getCategories()).toEqual(expectedCategories);
+ });
});
- assertEquals('Article Title', model.title);
- assertEquals('file:///', model.uri);
- assertEquals(0, model.getCategories().length);
-}
-
-function testSetAndGetCategories() {
- let model = new ArticleModel.ArticleModel();
- let expectedCategories = ['One', 'Two', 'Three'];
- model.setCategories(expectedCategories);
- _assertCategoryListHasIds(model.getCategories(), expectedCategories);
-}
-
-function testSetCategoriesWipesPreviousCategories() {
- let model = new ArticleModel.ArticleModel();
- let firstCategories = ['One', 'Two', 'Three'];
- model.setCategories(firstCategories);
- let expectedCategories = ['A', 'B', 'C', 'D'];
- model.setCategories(expectedCategories);
- _assertCategoryListHasIds(model.getCategories(), expectedCategories);
-}
-
-function testAddAndGetCategories() {
- let model = new ArticleModel.ArticleModel();
- model.addCategory('One');
- model.addCategory('Two');
- model.addCategory('Three');
- _assertCategoryListHasIds(model.getCategories(), ['One', 'Two', 'Three']);
-}
-
-function testHasCategories() {
- let model = new ArticleModel.ArticleModel();
- let expectedCategories = ['One', 'Two', 'Three'];
- model.setCategories(expectedCategories);
- expectedCategories.forEach(function (id) {
- assertTrue(model.hasCategory(id));
+
+ it("appends new categories on addCategory", function() {
+ let model = new ArticleModel.ArticleModel();
+
+ model.addCategory('One');
+ model.addCategory('Two');
+ model.addCategory('Three');
+ expect(model.getCategories()).toEqual(['One', 'Two', 'Three']);
+ });
+ describe("hasCategory method", function() {
+ let model;
+ let expectedCategories = ['One', 'Two', 'Three'];
+
+ beforeEach(function() {
+ model = new ArticleModel.ArticleModel;
+ model.setCategories(expectedCategories);
+ });
+
+ expectedCategories.forEach(function(category) {
+ (function(categoryName) {
+ it("returns true for category named " + categoryName, function() {
+ expect(model.hasCategory(categoryName)).toBeTruthy();
+ });
+ });
+ });
+
+ it("returns false for an unexpected category", function() {
+ expect(model.hasCategory('unexpected')).toBeFalsy();
+ });
});
-}
+});
diff --git a/test/wikipedia/models/testCategoryModel.js b/test/wikipedia/models/testCategoryModel.js
index 8d15665..4ffc1a0 100644
--- a/test/wikipedia/models/testCategoryModel.js
+++ b/test/wikipedia/models/testCategoryModel.js
@@ -1,76 +1,180 @@
const CategoryModel = imports.wikipedia.models.category_model;
-let mockJsonData = {
- category_name: 'Category Name',
- content_text: 'Lorem Ipsum',
- image_file: 'file:///image.jpg',
- image_thumb_uri: 'file:///thumb.jpg',
- is_main_category: false,
- subcategories: [ 'Category Two' ]
-};
-
-function testNewModelFromJson() {
- let model = CategoryModel.newFromJson(mockJsonData);
- assertTrue(model instanceof CategoryModel.CategoryModel);
- assertEquals('Category Name', model.id);
- assertEquals(0, model.getSubcategories().length);
-}
-
-function testNewWithProperties() {
- let model = new CategoryModel.CategoryModel({
- id: 'id',
- title: 'title',
- description: 'description',
- image_uri: 'image-uri',
- image_thumbnail_uri: 'image-thumbnail-uri',
- is_main_category: true,
- has_articles: true
+describe("Category Model", function() {
+ let mockJsonData = {
+ category_name: 'Category Name',
+ content_text: 'Lorem Ipsum',
+ image_file: 'file:///image.jpg',
+ image_thumb_uri: 'file:///thumb.jpg',
+ is_main_category: false,
+ subcategories: [ 'Category Two' ]
+ };
+ describe("from JSON", function() {
+
+ let model;
+ beforeEach(function() {
+ model = CategoryModel.newFromJson(mockJsonData);
+ });
+
+ it("is a CategoryModel", function() {
+ expect(model instanceof CategoryModel.CategoryModel).toBeTruthy();
+ });
+
+ it("has an id", function() {
+ expect(model.id).toEqual(mockJsonData.category_name);
+ });
+
+ it("has no subcategories", function() {
+ expect(model.getSubcategories().length).toEqual(0);
+ });
});
- assertEquals('id', model.id);
- assertEquals('title', model.title);
- assertEquals('description', model.description);
- assertEquals('image-uri', model.image_uri);
- assertEquals('image-thumbnail-uri', model.image_thumbnail_uri);
- assertEquals(true, model.is_main_category);
- assertEquals(true, model.has_articles);
-
- model.has_articles = false;
- assertEquals(false, model.has_articles);
-}
-
-function testGetSubcategoriesEmpty() {
- let model = new CategoryModel.CategoryModel();
- assertEquals(0, model.getSubcategories().length);
-}
-
-function _assertCategoryListContainsCategoryIds(categoryList, idList) {
- assertEquals(idList.length, categoryList.length);
- idList.forEach(function (id) {
- assertTrue(categoryList.some(function (categoryModel) {
- return categoryModel.id == id;
- }));
+
+ describe("from properties", function() {
+ let model;
+
+ beforeEach(function() {
+ model = new CategoryModel.CategoryModel({
+ id: 'id',
+ title: 'title',
+ description: 'description',
+ image_uri: 'image-uri',
+ image_thumbnail_uri: 'image-thumbnail-uri',
+ is_main_category: true,
+ has_articles: true
+ });
+ });
+
+ it("has an id", function() {
+ expect(model.id).toEqual('id');
+ });
+
+ it("has a title", function() {
+ expect(model.title).toEqual('title');
+ });
+
+ it("has a description", function() {
+ expect(model.description).toEqual('description');
+ });
+
+ it("has an image uri", function() {
+ expect(model.image_uri).toEqual('image-uri');
+ });
+
+ it("has an image thumbnail uri", function() {
+ expect(model.image_thumbnail_uri).toEqual('image-thumbnail-uri');
+ });
+
+ it("is a main category", function() {
+ expect(model.is_main_category).toBeTruthy();
+ });
+
+ it("has articles", function() {
+ expect(model.has_articles).toBeTruthy();
+ });
+
+ // FIXME: This seems to be a fairly useless test. Does it actually
+ // test anything?
+ it("does not have articles once the flag is unset", function() {
+ model.has_articles = false;
+ expect(model.has_articles).toBeFalsy();
+ });
+ });
+
+ it("starts with no subcategories", function() {
+ let model = new CategoryModel.CategoryModel();
+
+ expect(model.getSubcategories().length).toEqual(0);
+ });
+
+ describe("in a tree-like structure", function() {
+ let parent;
+
+ beforeEach(function() {
+ jasmine.addMatchers({
+ toContainCategoriesWithNames: function() {
+ return {
+ compare: function(actual, names) {
+ let result = {
+ pass: (function() {
+ let outer_pass = true;
+ names.forEach(function (id) {
+ let categories = actual.getSubcategories();
+ if (!categories.some(function(category) {
+ return category.id == id;
+ })) {
+ outer_pass = false;
+ }
+ });
+ return outer_pass;
+ })(),
+
+ message: (function() {
+ let msg = "Expected categories with the following names\n";
+ names.forEach(function(name) {
+ msg += " " + name + "\n";
+ });
+ msg += "Object actually has the following categories\n";
+ actual.getSubcategories().forEach(function(category) {
+ msg += " " + category.id + "\n";
+ });
+ return msg;
+ })()
+ }
+
+ return result;
+ }
+ }
+ },
+ toHaveOnlyTheFollowingCategoriesInOrder: function() {
+ return {
+ compare: function(actual, names) {
+ let result = {
+ pass: (function() {
+ let categories = actual.getSubcategories();
+ if (categories.length != names.length)
+ return false;
+
+ for (let i = 0; i < categories.length; i++) {
+ if (categories[i].id != names[i])
+ return false;
+ }
+
+ return true;
+ })(),
+
+ message: (function() {
+ let msg = "Expected exactly the following category names\n";
+ names.forEach(function(name) {
+ msg += " " + name + "\n";
+ });
+
+ msg += "Actually had the following category names\n";
+ actual.getSubcategories().forEach(function(category) {
+ msg += " " + category.id + "\n";
+ });
+
+ return msg;
+ })()
+ }
+
+ return result;
+ }
+ }
+ }
+ });
+
+ parent = new CategoryModel.CategoryModel({ id: 'Category One' });
+ parent.addSubcategory(new CategoryModel.CategoryModel({ id: 'Category Two' }));
+ parent.addSubcategory(new CategoryModel.CategoryModel({ id: 'Category Three' }));
+ });
+
+ it("has subcategories", function() {
+ expect(parent).toContainCategoriesWithNames(['Category Two', 'Category Three']);
+ });
+
+ it("silently does not add duplicates", function() {
+ parent.addSubcategory(new CategoryModel.CategoryModel({ id: 'Category Two' }));
+ expect(parent).toHaveOnlyTheFollowingCategoriesInOrder(['Category Two', 'Category Three']);
+ });
});
-}
-
-function testAddAndGetSubcategories() {
- let model1 = new CategoryModel.CategoryModel({ id: 'Category One' });
- let model2 = new CategoryModel.CategoryModel({ id: 'Category Two' });
- let model3 = new CategoryModel.CategoryModel({ id: 'Category Three' });
- model1.addSubcategory(model2);
- model1.addSubcategory(model3);
-
- let categories = model1.getSubcategories();
- _assertCategoryListContainsCategoryIds(categories,
- ['Category Two', 'Category Three']);
-}
-
-function testAddSubcategoryDoesNothingForDuplicate() {
- let model1 = new CategoryModel.CategoryModel({ id: 'Category One' });
- let model2 = new CategoryModel.CategoryModel({ id: 'Category Two' });
- let model3 = new CategoryModel.CategoryModel({ id: 'Category Two' });
- model1.addSubcategory(model2);
- model1.addSubcategory(model3);
-
- let categories = model1.getSubcategories();
- _assertCategoryListContainsCategoryIds(categories, ['Category Two']);
-}
+});
diff --git a/test/wikipedia/models/testDomainWikiModel.js b/test/wikipedia/models/testDomainWikiModel.js
index e4e4d3f..f30d1bd 100644
--- a/test/wikipedia/models/testDomainWikiModel.js
+++ b/test/wikipedia/models/testDomainWikiModel.js
@@ -1,144 +1,208 @@
const DomainWikiModel = imports.wikipedia.models.domain_wiki_model;
-let model;
-
-let mockJsonData = {
- categories: [
- {
- category_name: 'Main Category',
- content_text: 'Lorem Ipsum',
- image_file: 'file:///image.jpg',
- image_thumb_uri: 'file:///image_thumb.jpg',
- is_main_category: true,
- subcategories: [
- 'Category One',
- 'Category Two'
- ]
- },
- {
- category_name: 'Category One',
- content_text: 'Lorem Ipsum',
- image_file: 'file:///image.jpg',
- image_thumb_uri: 'file:///image_thumb.jpg',
- is_main_category: false,
- subcategories: []
- },
- {
- category_name: 'Category Two',
- content_text: 'Lorem Ipsum',
- image_file: 'file:///image.jpg',
- image_thumb_uri: 'file:///image_thumb.jpg',
- is_main_category: false,
- subcategories: [
- 'Category Three'
- ]
- },
- {
- category_name: 'Category Three',
- content_text: 'Lorem Ipsum',
- image_file: 'file:///image.jpg',
- image_thumb_uri: 'file:///image_thumb.jpg',
- is_main_category: false,
- subcategories: []
- },
- ],
- articles: [
- {
- title: 'Article One',
- url: 'file:///article1.html',
- source: 'Mock data',
- categories: [
- 'Category One'
- ]
- },
- {
- title: 'Article Two',
- url: 'file:///article2.html',
- source: 'Mock data',
- categories: [
- 'Category One',
- 'Category Two'
- ]
- },
- {
- title: 'Article Three',
- url: 'file:///article3.html',
- source: 'Mock data',
- categories: [
- 'Category Two'
- ]
- }
- ]
-};
-
-function setUp() {
- model = new DomainWikiModel.DomainWikiModel();
-}
-
-function _assertArticleListContainsArticleTitles(articleList, titleList) {
- assertEquals(titleList.length, articleList.length);
- titleList.forEach(function (title) {
- assertTrue(articleList.some(function (articleModel) {
- return articleModel.title == title;
- }));
+describe('Domain Wiki Model', function () {
+ const mockJsonData = {
+ categories: [
+ {
+ category_name: 'Main Category',
+ content_text: 'Lorem Ipsum',
+ image_file: 'file:///image.jpg',
+ image_thumb_uri: 'file:///image_thumb.jpg',
+ is_main_category: true,
+ subcategories: [
+ 'Category One',
+ 'Category Two'
+ ]
+ },
+ {
+ category_name: 'Category One',
+ content_text: 'Lorem Ipsum',
+ image_file: 'file:///image.jpg',
+ image_thumb_uri: 'file:///image_thumb.jpg',
+ is_main_category: false,
+ subcategories: []
+ },
+ {
+ category_name: 'Category Two',
+ content_text: 'Lorem Ipsum',
+ image_file: 'file:///image.jpg',
+ image_thumb_uri: 'file:///image_thumb.jpg',
+ is_main_category: false,
+ subcategories: [
+ 'Category Three'
+ ]
+ },
+ {
+ category_name: 'Category Three',
+ content_text: 'Lorem Ipsum',
+ image_file: 'file:///image.jpg',
+ image_thumb_uri: 'file:///image_thumb.jpg',
+ is_main_category: false,
+ subcategories: []
+ }
+ ],
+ articles: [
+ {
+ title: 'Article One',
+ url: 'file:///article1.html',
+ source: 'Mock data',
+ categories: [
+ 'Category One'
+ ]
+ },
+ {
+ title: 'Article Two',
+ url: 'file:///article2.html',
+ source: 'Mock data',
+ categories: [
+ 'Category One',
+ 'Category Two'
+ ]
+ },
+ {
+ title: 'Article Three',
+ url: 'file:///article3.html',
+ source: 'Mock data',
+ categories: [
+ 'Category Two'
+ ]
+ }
+ ]
+ };
+ beforeEach(function () {
+ let model = new DomainWikiModel.DomainWikiModel();
+
+ jasmine.addMatchers({
+ toHaveObjectsContainingProperties: function () {
+ return {
+ compare: function (actual, propertyMap) {
+ let result = {
+ pass: (function () {
+ for (let property in propertyMap) {
+ let allValuesListedHaveAMatchForObject = actual.some(function (object) {
+ if (object[property] == 'undefined') {
+ return false;
+ }
+
+ let propertyValueMatchedForObject =
+ propertyMap[property].some(function (value) {
+ return object[property] == value;
+ });
+
+ return propertyValueMatchedForObject;
+ });
+
+ if (!allValuesListedHaveAMatchForObject)
+ return false;
+ }
+
+ return true;
+ })(),
+
+ message: (function () {
+ let msg = 'Expected objects to have the following values for the following properties \n';
+ for (let property in propertyMap) {
+ msg += ' - Property: ' + property + '\n';
+ for (let value in propertyMap[property]) {
+ msg += ' * Value: ' + propertyMap[property][value].toString() + '\n';
+ }
+ }
+
+ msg += 'Object actually has the following toplevel properties\n';
+
+ for (let i = 0; i < actual.length; i++) {
+ let object = actual[i];
+ msg += ' Object in position ' + i + '\n';
+ for (let property in object) {
+ msg += ' - ' + property + ' : ' + object[property] + '\n';
+ }
+ }
+
+ return msg;
+ })()
+ };
+
+ return result;
+ }
+ };
+ }
+ });
+ });
+
+ describe('when loaded from some mock JSON data', function () {
+ let model;
+ beforeEach(function () {
+ model = new DomainWikiModel.DomainWikiModel();
+ model.loadFromJson(mockJsonData);
+ });
+
+ it('returns all articles when getting articles', function () {
+ let articles = model.getArticles();
+ expect(articles).toHaveObjectsContainingProperties({
+ title: [ 'Article One', 'Article Two', 'Article Three' ]
+ });
+ });
+
+ it('can get articles for a category', function () {
+ let articles = model.getArticlesForCategory('Category One');
+ expect(articles).toHaveObjectsContainingProperties({
+ title: [ 'Article One', 'Article Two' ]
+ });
+ });
+
+ it('has no articles on a category that does not have articles', function () {
+ let articles = model.getArticlesForCategory('Main Category');
+ expect(articles.length).toEqual(0);
+ });
+
+ it('has no articles for a category that does not exist', function () {
+ let articles = model.getArticlesForCategory('Nonexistent');
+ expect(articles.length).toEqual(0);
+ });
+
+ it('can check whether or not a category has articles', function () {
+ expect(model._getCategoryHasArticles('Category Two')).toBeTruthy();
+ });
+
+ it('can check whether or not a category does not have articles', function () {
+ expect(model._getCategoryHasArticles('Category Three')).toBeFalsy();
+ });
+
+ it('verifies that a category that does not exist has no articles', function () {
+ expect(model._getCategoryHasArticles('Nonexistent')).toBeFalsy();
+ });
+
+ describe('category fetch', function () {
+ let category;
+
+ beforeEach(function () {
+ category = model.getCategory('Category One');
+ });
+
+ it('actually returns a category', function () {
+ expect(category.__name__).toEqual('CategoryModel');
+ });
+
+ it('returns the right category', function () {
+ expect(category.title).toEqual('Category One');
+ });
+ });
+
+ it("returns an undefined value if we try to get a category that doesn't exist", function () {
+ expect(model.getCategory('Nonexistent')).toBeUndefined();
+ });
+
+ it("returns 'Main Category' when getting the main category", function () {
+ let category = model.getMainCategory();
+
+ expect(category).toEqual(new jasmine.ObjectContaining({
+ 'title' : 'Main Category'
+ }));
+ });
+ });
+
+ it('returns null when the Main Category is unset', function () {
+ let model = new DomainWikiModel.DomainWikiModel();
+ expect(model.getMainCategory()).toBeNull();
});
-}
-
-function testGetArticlesReturnsAllArticles() {
- model.loadFromJson(mockJsonData);
- let articles = model.getArticles();
- _assertArticleListContainsArticleTitles(articles,
- [ 'Article One', 'Article Two', 'Article Three' ]);
-}
-
-function testGetArticlesForCategoryWithArticles() {
- model.loadFromJson(mockJsonData);
- let articles = model.getArticlesForCategory('Category One');
- _assertArticleListContainsArticleTitles(articles,
- [ 'Article One', 'Article Two' ]);
-}
-
-function testGetArticlesForCategoryWithoutArticles() {
- model.loadFromJson(mockJsonData);
- assertEquals(0, model.getArticlesForCategory('Main Category').length);
-}
-
-function testGetArticlesForCategoryWithNonexistentId() {
- assertEquals(0, model.getArticlesForCategory('Nonexistent').length);
-}
-
-function testCategoryHasArticlesReturnsTrue() {
- model.loadFromJson(mockJsonData);
- assertTrue(model._getCategoryHasArticles('Category Two'));
-}
-
-function testCategoryHasArticlesReturnsFalse() {
- model.loadFromJson(mockJsonData);
- assertFalse(model._getCategoryHasArticles('Category Three'));
-}
-
-function testCategoryHasArticlesWithNonexistentId() {
- assertFalse(model._getCategoryHasArticles('Nonexistent'));
-}
-
-function testGetCategory() {
- model.loadFromJson(mockJsonData);
- let category = model.getCategory('Category One');
- assertEquals('CategoryModel', category.__name__);
- assertEquals('Category One', category.title);
-}
-
-function testGetNonexistentCategory() {
- assertUndefined(model.getCategory('Nonexistent'));
-}
-
-function testGetMainCategory() {
- model.loadFromJson(mockJsonData);
- let category = model.getMainCategory();
- assertTrue(category.__name__ == 'CategoryModel');
- assertEquals('Main Category', category.title);
-}
-
-function testGetUnsetMainCategory() {
- assertNull(model.getMainCategory());
-}
+});