1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/toolkit/components/places/tests/unit/test_history_observer.js Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,166 @@ 1.4 +/* Any copyright is dedicated to the Public Domain. 1.5 + http://creativecommons.org/publicdomain/zero/1.0/ */ 1.6 + 1.7 +/** 1.8 + * Generic nsINavHistoryObserver that doesn't implement anything, but provides 1.9 + * dummy methods to prevent errors about an object not having a certain method. 1.10 + */ 1.11 +function NavHistoryObserver() { 1.12 +} 1.13 +NavHistoryObserver.prototype = { 1.14 + onBeginUpdateBatch: function() { }, 1.15 + onEndUpdateBatch: function() { }, 1.16 + onVisit: function() { }, 1.17 + onTitleChanged: function() { }, 1.18 + onDeleteURI: function() { }, 1.19 + onClearHistory: function() { }, 1.20 + onPageChanged: function() { }, 1.21 + onDeleteVisits: function() { }, 1.22 + QueryInterface: XPCOMUtils.generateQI([Ci.nsINavHistoryObserver]) 1.23 +}; 1.24 + 1.25 +/** 1.26 + * Registers a one-time history observer for and calls the callback 1.27 + * when the specified nsINavHistoryObserver method is called. 1.28 + * Returns a promise that is resolved when the callback returns. 1.29 + */ 1.30 +function onNotify(callback) { 1.31 + let deferred = Promise.defer(); 1.32 + let obs = new NavHistoryObserver(); 1.33 + obs[callback.name] = function () { 1.34 + PlacesUtils.history.removeObserver(this); 1.35 + callback.apply(this, arguments); 1.36 + deferred.resolve(); 1.37 + }; 1.38 + PlacesUtils.history.addObserver(obs, false); 1.39 + return deferred.promise; 1.40 +} 1.41 + 1.42 +/** 1.43 + * Asynchronous task that adds a visit to the history database. 1.44 + */ 1.45 +function task_add_visit(uri, timestamp, transition) { 1.46 + uri = uri || NetUtil.newURI("http://firefox.com/"); 1.47 + timestamp = timestamp || Date.now() * 1000; 1.48 + yield promiseAddVisits({ 1.49 + uri: uri, 1.50 + transition: transition || TRANSITION_TYPED, 1.51 + visitDate: timestamp 1.52 + }); 1.53 + throw new Task.Result([uri, timestamp]); 1.54 +} 1.55 + 1.56 +function run_test() { 1.57 + run_next_test(); 1.58 +} 1.59 + 1.60 +add_task(function test_onVisit() { 1.61 + let promiseNotify = onNotify(function onVisit(aURI, aVisitID, aTime, 1.62 + aSessionID, aReferringID, 1.63 + aTransitionType, aGUID, 1.64 + aHidden) { 1.65 + do_check_true(aURI.equals(testuri)); 1.66 + do_check_true(aVisitID > 0); 1.67 + do_check_eq(aTime, testtime); 1.68 + do_check_eq(aSessionID, 0); 1.69 + do_check_eq(aReferringID, 0); 1.70 + do_check_eq(aTransitionType, TRANSITION_TYPED); 1.71 + do_check_guid_for_uri(aURI, aGUID); 1.72 + do_check_false(aHidden); 1.73 + }); 1.74 + let testuri = NetUtil.newURI("http://firefox.com/"); 1.75 + let testtime = Date.now() * 1000; 1.76 + yield task_add_visit(testuri, testtime); 1.77 + yield promiseNotify; 1.78 +}); 1.79 + 1.80 +add_task(function test_onVisit() { 1.81 + let promiseNotify = onNotify(function onVisit(aURI, aVisitID, aTime, 1.82 + aSessionID, aReferringID, 1.83 + aTransitionType, aGUID, 1.84 + aHidden) { 1.85 + do_check_true(aURI.equals(testuri)); 1.86 + do_check_true(aVisitID > 0); 1.87 + do_check_eq(aTime, testtime); 1.88 + do_check_eq(aSessionID, 0); 1.89 + do_check_eq(aReferringID, 0); 1.90 + do_check_eq(aTransitionType, TRANSITION_FRAMED_LINK); 1.91 + do_check_guid_for_uri(aURI, aGUID); 1.92 + do_check_true(aHidden); 1.93 + }); 1.94 + let testuri = NetUtil.newURI("http://hidden.firefox.com/"); 1.95 + let testtime = Date.now() * 1000; 1.96 + yield task_add_visit(testuri, testtime, TRANSITION_FRAMED_LINK); 1.97 + yield promiseNotify; 1.98 +}); 1.99 + 1.100 +add_task(function test_onDeleteURI() { 1.101 + let promiseNotify = onNotify(function onDeleteURI(aURI, aGUID, aReason) { 1.102 + do_check_true(aURI.equals(testuri)); 1.103 + // Can't use do_check_guid_for_uri() here because the visit is already gone. 1.104 + do_check_eq(aGUID, testguid); 1.105 + do_check_eq(aReason, Ci.nsINavHistoryObserver.REASON_DELETED); 1.106 + }); 1.107 + let [testuri] = yield task_add_visit(); 1.108 + let testguid = do_get_guid_for_uri(testuri); 1.109 + PlacesUtils.bhistory.removePage(testuri); 1.110 + yield promiseNotify; 1.111 +}); 1.112 + 1.113 +add_task(function test_onDeleteVisits() { 1.114 + let promiseNotify = onNotify(function onDeleteVisits(aURI, aVisitTime, aGUID, 1.115 + aReason) { 1.116 + do_check_true(aURI.equals(testuri)); 1.117 + // Can't use do_check_guid_for_uri() here because the visit is already gone. 1.118 + do_check_eq(aGUID, testguid); 1.119 + do_check_eq(aReason, Ci.nsINavHistoryObserver.REASON_DELETED); 1.120 + do_check_eq(aVisitTime, 0); // All visits have been removed. 1.121 + }); 1.122 + let msecs24hrsAgo = Date.now() - (86400 * 1000); 1.123 + let [testuri] = yield task_add_visit(undefined, msecs24hrsAgo * 1000); 1.124 + // Add a bookmark so the page is not removed. 1.125 + PlacesUtils.bookmarks.insertBookmark(PlacesUtils.unfiledBookmarksFolderId, 1.126 + testuri, 1.127 + PlacesUtils.bookmarks.DEFAULT_INDEX, 1.128 + "test"); 1.129 + let testguid = do_get_guid_for_uri(testuri); 1.130 + PlacesUtils.bhistory.removePage(testuri); 1.131 + yield promiseNotify; 1.132 +}); 1.133 + 1.134 +add_task(function test_onTitleChanged() { 1.135 + let promiseNotify = onNotify(function onTitleChanged(aURI, aTitle, aGUID) { 1.136 + do_check_true(aURI.equals(testuri)); 1.137 + do_check_eq(aTitle, title); 1.138 + do_check_guid_for_uri(aURI, aGUID); 1.139 + }); 1.140 + 1.141 + let [testuri] = yield task_add_visit(); 1.142 + let title = "test-title"; 1.143 + yield promiseAddVisits({ 1.144 + uri: testuri, 1.145 + title: title 1.146 + }); 1.147 + yield promiseNotify; 1.148 +}); 1.149 + 1.150 +add_task(function test_onPageChanged() { 1.151 + let promiseNotify = onNotify(function onPageChanged(aURI, aChangedAttribute, 1.152 + aNewValue, aGUID) { 1.153 + do_check_eq(aChangedAttribute, Ci.nsINavHistoryObserver.ATTRIBUTE_FAVICON); 1.154 + do_check_true(aURI.equals(testuri)); 1.155 + do_check_eq(aNewValue, SMALLPNG_DATA_URI.spec); 1.156 + do_check_guid_for_uri(aURI, aGUID); 1.157 + }); 1.158 + 1.159 + let [testuri] = yield task_add_visit(); 1.160 + 1.161 + // The new favicon for the page must have data associated with it in order to 1.162 + // receive the onPageChanged notification. To keep this test self-contained, 1.163 + // we use an URI representing the smallest possible PNG file. 1.164 + PlacesUtils.favicons.setAndFetchFaviconForPage(testuri, SMALLPNG_DATA_URI, 1.165 + false, 1.166 + PlacesUtils.favicons.FAVICON_LOAD_NON_PRIVATE, 1.167 + null); 1.168 + yield promiseNotify; 1.169 +});