diff --git a/modules/twitter.js b/modules/twitter.js index 29af082..5316089 100644 --- a/modules/twitter.js +++ b/modules/twitter.js @@ -508,9 +508,12 @@ SnowlTwitter.prototype = { this._saveLogin(this._authInfo); } - this._processRefresh(request.responseText, this._refreshTime); + let items = JSON.parse(request.responseText); + this.messages = this._processItems(items, this._refreshTime); this._resetRefresh(); + + Observers.notify("snowl:subscribe:get:end", this); }, onRefreshError: function(event) { @@ -525,6 +528,54 @@ SnowlTwitter.prototype = { this._resetRefresh(); }, + + //**************************************************************************// + // Processing + + /** + * Process an array of items (from the server) into an array of messages. + * + * @param items {Array} the items to process + * @param received {Date} when the items were received + */ + _processItems: function(items, received) { + let messages = []; + + for each (let item in items) { + let externalID; + try { + externalID = item.id; + let message = this._processItem(item, received); + messages.push(message); + } + catch(ex) { + this._log.error("couldn't process item " + externalID + ": " + ex); + } + } + + return messages; + }, + + _processItem: function(item, received) { + let message = new SnowlMessage(); + + message.sourceID = this.id; + message.externalID = item.id; + message.timestamp = new Date(item.created_at); + message.received = received; + message.author = new SnowlIdentity(null, this.id, item.user.id); + message.author.person = new SnowlPerson(null, item.user.screen_name, null, item.user.url, item.user.profile_image_url); + + message.content = + new SnowlMessagePart({ + partType: PART_TYPE_CONTENT, + content: item.text, + mediaType: "text/plain" + }); + + return message; + }, + _processRefresh: strand(function(responseText, refreshTime) { //this._log.debug("_processRefresh: this.name = " + this.name + "; responseText = " + responseText); @@ -758,6 +809,8 @@ SnowlTwitter.prototype = { } }; +Mixins.mix(SnowlSource).into(SnowlTwitter); Mixins.mix(SnowlSource.prototype).into(SnowlTwitter.prototype); +Mixins.mix(SnowlTarget).into(SnowlTwitter); Mixins.mix(SnowlTarget.prototype).into(SnowlTwitter.prototype); SnowlService.addAccountType(SnowlTwitter); diff --git a/test/unit/test_twitter.js b/test/unit/test_twitter.js new file mode 100644 index 0000000..86ea5ff --- /dev/null +++ b/test/unit/test_twitter.js @@ -0,0 +1,138 @@ +// modules that come with Firefox + +// modules that are generic +Cu.import("resource://snowl/modules/Observers.js"); +Cu.import("resource://snowl/modules/URI.js"); + +// Snowl-specific modules +Cu.import("resource://snowl/modules/collection.js"); +Cu.import("resource://snowl/modules/message.js"); +Cu.import("resource://snowl/modules/twitter.js"); +Cu.import("resource://snowl/modules/service.js"); + +let server, twitter; +let refreshTime = new Date(); + +function run_test() { + server = new nsHttpServer(); + let basePath = do_get_file("test/unit/twitter/"); + server.registerDirectory("/", basePath); + server.start(8080); + + do_test_pending(); + + Observers.add("snowl:subscribe:get:end", do_callback(finish_test)); + twitter = new SnowlTwitter(null, "snowl_test", new URI("http://localhost:8080/")); + // FIXME: provide credentials { username: "snowl_test", password: "whatever" } + twitter.username = "snowl_test"; + twitter.refresh(refreshTime); +} + +function check_account(twitter) { + do_check_eq(twitter.constructor.name, "SnowlTwitter"); + do_check_eq(twitter.name, "snowl_test"); + do_check_eq(twitter.machineURI.spec, "http://localhost:8080/"); + do_check_eq(twitter.humanURI.spec, "http://twitter.com/home"); + do_check_eq(twitter.username, "snowl_test"); + do_check_eq(twitter.lastRefreshed.getTime(), refreshTime.getTime()); + do_check_eq(twitter.importance, null); + + let messages = twitter.messages; + do_check_eq(messages.length, 1); + + let message = messages[0]; + + // Check the primitive attributes of the message object. + do_check_eq(message.id.constructor.name, "Number"); + do_check_eq(message.sourceID, twitter.id); + do_check_eq(message.subject, null); + do_check_eq(message.link, null); + do_check_eq(message.timestamp.getTime(), 1242332345000); + do_check_eq(message.read, false); + do_check_eq(message.received.getTime(), refreshTime.getTime()); + + // Check the attributes of the message author. + do_check_eq(message.author.id.constructor.name, "Number"); + do_check_eq(message.author.sourceID, twitter.id); + do_check_eq(message.author.externalID, 55555); + + // Check the attributes of the person associated with the message author. + do_check_eq(message.author.person.constructor.name, "Object"); + do_check_eq(message.author.person.id.constructor.name, "Number"); + do_check_eq(message.author.person.name, "nofx_test"); + do_check_eq(message.author.person.placeID.constructor.name, "Number"); + do_check_eq(message.author.person.homeURL, "http://www.nofxofficialwebsite.com/"); + do_check_eq(message.author.person.iconURL, "http://www.nofxofficialwebsite.com/images/index/index_02.gif"); + // FIXME: figure out how to check that this is correct. + //do_check_eq(message.author.person.icon, null); + + // Check the message's content. + do_check_true(message.content instanceof SnowlMessagePart); + do_check_eq(message.content.text, "Or maybe, tear it apart, Start with assumption, That a million people are smart, Smarter than one!"); + do_check_eq(message.content.type, "text"); + do_check_eq(message.content.base, null); + do_check_eq(message.content.lang, null); + + // Check the message's summary. + do_check_eq(message.summary, null); +} + +function finish_test() { + let id = twitter.persist(); + do_check_eq(id, twitter.id); + + try { + + // Make sure the account is as expected both before and after retrieval. + check_account(twitter); + do_check_eq(id.constructor.name, "Number"); + do_check_eq(twitter.placeID.constructor.name, "Number"); + let twitter2 = SnowlTwitter.retrieve(id); + check_account(twitter2); + do_check_eq(twitter2.id, twitter.id); + do_check_eq(twitter2.placeID, twitter.placeID); + + do_check_eq(SnowlService.accounts.length, 1); + let account = SnowlService.accounts[0]; + do_check_eq(account.id.constructor.name, "Number"); + do_check_eq(account.constructor.name, "SnowlTwitter"); + do_check_eq(account.name, "snowl_test"); + do_check_eq(account.machineURI.spec, "http://localhost:8080/"); + do_check_eq(account.humanURI.spec, "http://twitter.com/home"); + do_check_eq(account.username, "snowl_test"); + // TODO: separate retrieval from storage of this value. + //do_check_eq(account.lastRefreshed.getTime(), refreshTime.getTime()); + do_check_eq(account.importance, null); + do_check_eq(account.placeID.constructor.name, "Number"); + + let collection = new SnowlCollection(); + let messages = collection.messages; + do_check_eq(messages.length, 1); + let message = messages[0]; + do_check_eq(message.id.constructor.name, "Number"); + do_check_eq(message.sourceID, account.id); + do_check_eq(message.subject, null); + do_check_eq(message.authorName, "nofx_test"); + // TODO: do_check_eq(message.authorID, authorID); + // TODO: test that the message's author is a real identity record + // with a real person record behind it and the values of those records + // are all correct. + do_check_eq(message.link, null); + do_check_eq(message.timestamp.getTime(), 1242332345000); + do_check_eq(message.read, false); + do_check_eq(message.authorIcon, "http://www.nofxofficialwebsite.com/images/index/index_02.gif"); + do_check_eq(message.received.constructor.name, "Date"); + + do_check_true(message.content instanceof Ci.nsIFeedTextConstruct); + do_check_eq(message.content.text, "Or maybe, tear it apart, Start with assumption, That a million people are smart, Smarter than one!"); + do_check_eq(message.content.type, "text"); + do_check_eq(message.content.base, null); + do_check_eq(message.content.lang, null); + + do_check_eq(message.summary, null); + } + finally { + server.stop(); + do_test_finished(); + } +} diff --git a/test/unit/twitter/statuses/friends_timeline.json b/test/unit/twitter/statuses/friends_timeline.json new file mode 100644 index 0000000..17d48cc --- /dev/null +++ b/test/unit/twitter/statuses/friends_timeline.json @@ -0,0 +1,37 @@ +[ + {"in_reply_to_screen_name":null, + "text":"Or maybe, tear it apart, Start with assumption, That a million people are smart, Smarter than one!", + "user":{"profile_sidebar_fill_color":"CCCCCC", + "description":"Punk in Drublic", + "utc_offset":-28800, + "notifications":null, + "profile_sidebar_border_color":"DDDDDD", + "following":null, + "profile_background_tile":false, + "followers_count":1111, + "url":"http:\/\/www.nofxofficialwebsite.com\/", + "name":"NOFX", + "time_zone":"Pacific Time (US & Canada)", + "friends_count":2222, + "profile_background_color":"EEEEEE", + "protected":false, + "statuses_count":3333, + "favourites_count":44, + "created_at":"Tue Nov 28 15:41:30 +0000 2006", + "profile_text_color":"111111", + "profile_image_url":"http:\/\/www.nofxofficialwebsite.com\/images\/index\/index_02.gif", + "profile_background_image_url":"http:\/\/static.twitter.com\/images\/themes\/theme3\/bg.gif", + "profile_link_color":"222222", + "location":"San Francisco, CA", + "id":55555, + "screen_name":"nofx_test" + }, + "truncated":false, + "in_reply_to_status_id":null, + "in_reply_to_user_id":null, + "created_at":"Thu May 14 20:19:05 +0000 2009", + "favorited":false, + "id":1234567890, + "source":"web" + } +]