michael@0: /* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* vim:set ts=2 sw=2 sts=2 et: */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: // Get history service michael@0: var hs = Cc["@mozilla.org/browser/nav-history-service;1"]. michael@0: getService(Ci.nsINavHistoryService); michael@0: var bh = hs.QueryInterface(Ci.nsIBrowserHistory); michael@0: var bs = Cc["@mozilla.org/browser/nav-bookmarks-service;1"]. michael@0: getService(Ci.nsINavBookmarksService); michael@0: var ps = Cc["@mozilla.org/preferences-service;1"]. michael@0: getService(Ci.nsIPrefBranch); michael@0: michael@0: /** michael@0: * Adds a test URI visit to the database. michael@0: * michael@0: * @param aURI michael@0: * The URI to add a visit for. michael@0: * @param aTime michael@0: * Reference "now" time. michael@0: * @param aDayOffset michael@0: * number of days to add, pass a negative value to subtract them. michael@0: */ michael@0: function task_add_normalized_visit(aURI, aTime, aDayOffset) { michael@0: var dateObj = new Date(aTime); michael@0: // Normalize to midnight michael@0: dateObj.setHours(0); michael@0: dateObj.setMinutes(0); michael@0: dateObj.setSeconds(0); michael@0: dateObj.setMilliseconds(0); michael@0: // Days where DST changes should be taken in count. michael@0: var previousDateObj = new Date(dateObj.getTime() + aDayOffset * 86400000); michael@0: var DSTCorrection = (dateObj.getTimezoneOffset() - michael@0: previousDateObj.getTimezoneOffset()) * 60 * 1000; michael@0: // Substract aDayOffset michael@0: var PRTimeWithOffset = (previousDateObj.getTime() - DSTCorrection) * 1000; michael@0: var timeInMs = new Date(PRTimeWithOffset/1000); michael@0: print("Adding visit to " + aURI.spec + " at " + timeInMs); michael@0: yield promiseAddVisits({ michael@0: uri: aURI, michael@0: visitDate: PRTimeWithOffset michael@0: }); michael@0: } michael@0: michael@0: function days_for_x_months_ago(aNowObj, aMonths) { michael@0: var oldTime = new Date(); michael@0: // Set day before month, otherwise we could try to calculate 30 February, or michael@0: // other nonexistent days. michael@0: oldTime.setDate(1); michael@0: oldTime.setMonth(aNowObj.getMonth() - aMonths); michael@0: oldTime.setHours(0); michael@0: oldTime.setMinutes(0); michael@0: oldTime.setSeconds(0); michael@0: // Stay larger for eventual timezone issues, add 2 days. michael@0: return parseInt((aNowObj - oldTime) / (1000*60*60*24)) + 2; michael@0: } michael@0: michael@0: var nowObj = new Date(); michael@0: // This test relies on en-US locale michael@0: // Offset is number of days michael@0: var containers = [ michael@0: { label: "Today" , offset: 0 , visible: true }, michael@0: { label: "Yesterday" , offset: -1 , visible: true }, michael@0: { label: "Last 7 days" , offset: -3 , visible: true }, michael@0: { label: "This month" , offset: -8 , visible: nowObj.getDate() > 8 }, michael@0: { label: "" , offset: -days_for_x_months_ago(nowObj, 0) , visible: true }, michael@0: { label: "" , offset: -days_for_x_months_ago(nowObj, 1) , visible: true }, michael@0: { label: "" , offset: -days_for_x_months_ago(nowObj, 2) , visible: true }, michael@0: { label: "" , offset: -days_for_x_months_ago(nowObj, 3) , visible: true }, michael@0: { label: "" , offset: -days_for_x_months_ago(nowObj, 4) , visible: true }, michael@0: { label: "Older than 6 months" , offset: -days_for_x_months_ago(nowObj, 5) , visible: true }, michael@0: ]; michael@0: michael@0: var visibleContainers = containers.filter( michael@0: function(aContainer) {return aContainer.visible}); michael@0: michael@0: /** michael@0: * Asynchronous task that fills history and checks containers' labels. michael@0: */ michael@0: function task_fill_history() { michael@0: print("\n\n*** TEST Fill History\n"); michael@0: // We can't use "now" because our hardcoded offsets would be invalid for some michael@0: // date. So we hardcode a date. michael@0: for (var i = 0; i < containers.length; i++) { michael@0: var container = containers[i]; michael@0: var testURI = uri("http://mirror"+i+".mozilla.com/b"); michael@0: yield task_add_normalized_visit(testURI, nowObj.getTime(), container.offset); michael@0: var testURI = uri("http://mirror"+i+".mozilla.com/a"); michael@0: yield task_add_normalized_visit(testURI, nowObj.getTime(), container.offset); michael@0: var testURI = uri("http://mirror"+i+".google.com/b"); michael@0: yield task_add_normalized_visit(testURI, nowObj.getTime(), container.offset); michael@0: var testURI = uri("http://mirror"+i+".google.com/a"); michael@0: yield task_add_normalized_visit(testURI, nowObj.getTime(), container.offset); michael@0: // Bug 485703 - Hide date containers not containing additional entries michael@0: // compared to previous ones. michael@0: // Check after every new container is added. michael@0: check_visit(container.offset); michael@0: } michael@0: michael@0: var options = hs.getNewQueryOptions(); michael@0: options.resultType = options.RESULTS_AS_DATE_SITE_QUERY; michael@0: var query = hs.getNewQuery(); michael@0: michael@0: var result = hs.executeQuery(query, options); michael@0: var root = result.root; michael@0: root.containerOpen = true; michael@0: michael@0: var cc = root.childCount; michael@0: print("Found containers:"); michael@0: var previousLabels = []; michael@0: for (var i = 0; i < cc; i++) { michael@0: var container = visibleContainers[i]; michael@0: var node = root.getChild(i); michael@0: print(node.title); michael@0: if (container.label) michael@0: do_check_eq(node.title, container.label); michael@0: // Check labels are not repeated. michael@0: do_check_eq(previousLabels.indexOf(node.title), -1); michael@0: previousLabels.push(node.title); michael@0: } michael@0: do_check_eq(cc, visibleContainers.length); michael@0: root.containerOpen = false; michael@0: } michael@0: michael@0: /** michael@0: * Bug 485703 - Hide date containers not containing additional entries compared michael@0: * to previous ones. michael@0: */ michael@0: function check_visit(aOffset) { michael@0: var options = hs.getNewQueryOptions(); michael@0: options.resultType = options.RESULTS_AS_DATE_SITE_QUERY; michael@0: var query = hs.getNewQuery(); michael@0: var result = hs.executeQuery(query, options); michael@0: var root = result.root; michael@0: root.containerOpen = true; michael@0: var cc = root.childCount; michael@0: michael@0: var unexpected = []; michael@0: switch (aOffset) { michael@0: case 0: michael@0: unexpected = ["Yesterday", "Last 7 days", "This month"]; michael@0: break; michael@0: case -1: michael@0: unexpected = ["Last 7 days", "This month"]; michael@0: break; michael@0: case -3: michael@0: unexpected = ["This month"]; michael@0: break; michael@0: default: michael@0: // Other containers are tested later. michael@0: } michael@0: michael@0: print("Found containers:"); michael@0: for (var i = 0; i < cc; i++) { michael@0: var node = root.getChild(i); michael@0: print(node.title); michael@0: do_check_eq(unexpected.indexOf(node.title), -1); michael@0: } michael@0: michael@0: root.containerOpen = false; michael@0: } michael@0: michael@0: /** michael@0: * Queries history grouped by date and site, checking containers' labels and michael@0: * children. michael@0: */ michael@0: function test_RESULTS_AS_DATE_SITE_QUERY() { michael@0: print("\n\n*** TEST RESULTS_AS_DATE_SITE_QUERY\n"); michael@0: var options = hs.getNewQueryOptions(); michael@0: options.resultType = options.RESULTS_AS_DATE_SITE_QUERY; michael@0: var query = hs.getNewQuery(); michael@0: var result = hs.executeQuery(query, options); michael@0: var root = result.root; michael@0: root.containerOpen = true; michael@0: michael@0: // Check one of the days michael@0: var dayNode = root.getChild(0) michael@0: .QueryInterface(Ci.nsINavHistoryContainerResultNode); michael@0: dayNode.containerOpen = true; michael@0: do_check_eq(dayNode.childCount, 2); michael@0: michael@0: // Items should be sorted by host michael@0: var site1 = dayNode.getChild(0) michael@0: .QueryInterface(Ci.nsINavHistoryContainerResultNode); michael@0: do_check_eq(site1.title, "mirror0.google.com"); michael@0: michael@0: var site2 = dayNode.getChild(1) michael@0: .QueryInterface(Ci.nsINavHistoryContainerResultNode); michael@0: do_check_eq(site2.title, "mirror0.mozilla.com"); michael@0: michael@0: site1.containerOpen = true; michael@0: do_check_eq(site1.childCount, 2); michael@0: michael@0: // Inside of host sites are sorted by title michael@0: var site1visit = site1.getChild(0); michael@0: do_check_eq(site1visit.uri, "http://mirror0.google.com/a"); michael@0: michael@0: // Bug 473157: changing sorting mode should not affect the containers michael@0: result.sortingMode = options.SORT_BY_TITLE_DESCENDING; michael@0: michael@0: // Check one of the days michael@0: var dayNode = root.getChild(0) michael@0: .QueryInterface(Ci.nsINavHistoryContainerResultNode); michael@0: dayNode.containerOpen = true; michael@0: do_check_eq(dayNode.childCount, 2); michael@0: michael@0: // Hosts are still sorted by title michael@0: var site1 = dayNode.getChild(0) michael@0: .QueryInterface(Ci.nsINavHistoryContainerResultNode); michael@0: do_check_eq(site1.title, "mirror0.google.com"); michael@0: michael@0: var site2 = dayNode.getChild(1) michael@0: .QueryInterface(Ci.nsINavHistoryContainerResultNode); michael@0: do_check_eq(site2.title, "mirror0.mozilla.com"); michael@0: michael@0: site1.containerOpen = true; michael@0: do_check_eq(site1.childCount, 2); michael@0: michael@0: // But URLs are now sorted by title descending michael@0: var site1visit = site1.getChild(0); michael@0: do_check_eq(site1visit.uri, "http://mirror0.google.com/b"); michael@0: michael@0: site1.containerOpen = false; michael@0: dayNode.containerOpen = false; michael@0: root.containerOpen = false; michael@0: } michael@0: michael@0: /** michael@0: * Queries history grouped by date, checking containers' labels and children. michael@0: */ michael@0: function test_RESULTS_AS_DATE_QUERY() { michael@0: print("\n\n*** TEST RESULTS_AS_DATE_QUERY\n"); michael@0: var options = hs.getNewQueryOptions(); michael@0: options.resultType = options.RESULTS_AS_DATE_QUERY; michael@0: var query = hs.getNewQuery(); michael@0: var result = hs.executeQuery(query, options); michael@0: var root = result.root; michael@0: root.containerOpen = true; michael@0: michael@0: var cc = root.childCount; michael@0: do_check_eq(cc, visibleContainers.length); michael@0: print("Found containers:"); michael@0: for (var i = 0; i < cc; i++) { michael@0: var container = visibleContainers[i]; michael@0: var node = root.getChild(i); michael@0: print(node.title); michael@0: if (container.label) michael@0: do_check_eq(node.title, container.label); michael@0: } michael@0: michael@0: // Check one of the days michael@0: var dayNode = root.getChild(0) michael@0: .QueryInterface(Ci.nsINavHistoryContainerResultNode); michael@0: dayNode.containerOpen = true; michael@0: do_check_eq(dayNode.childCount, 4); michael@0: michael@0: // Items should be sorted by title michael@0: var visit1 = dayNode.getChild(0); michael@0: do_check_eq(visit1.uri, "http://mirror0.google.com/a"); michael@0: michael@0: var visit2 = dayNode.getChild(3); michael@0: do_check_eq(visit2.uri, "http://mirror0.mozilla.com/b"); michael@0: michael@0: // Bug 473157: changing sorting mode should not affect the containers michael@0: result.sortingMode = options.SORT_BY_TITLE_DESCENDING; michael@0: michael@0: // Check one of the days michael@0: var dayNode = root.getChild(0) michael@0: .QueryInterface(Ci.nsINavHistoryContainerResultNode); michael@0: dayNode.containerOpen = true; michael@0: do_check_eq(dayNode.childCount, 4); michael@0: michael@0: // But URLs are now sorted by title descending michael@0: var visit1 = dayNode.getChild(0); michael@0: do_check_eq(visit1.uri, "http://mirror0.mozilla.com/b"); michael@0: michael@0: var visit2 = dayNode.getChild(3); michael@0: do_check_eq(visit2.uri, "http://mirror0.google.com/a"); michael@0: michael@0: dayNode.containerOpen = false; michael@0: root.containerOpen = false; michael@0: } michael@0: michael@0: /** michael@0: * Queries history grouped by site, checking containers' labels and children. michael@0: */ michael@0: function test_RESULTS_AS_SITE_QUERY() { michael@0: print("\n\n*** TEST RESULTS_AS_SITE_QUERY\n"); michael@0: // add a bookmark with a domain not in the set of visits in the db michael@0: var itemId = bs.insertBookmark(bs.toolbarFolder, uri("http://foobar"), michael@0: bs.DEFAULT_INDEX, ""); michael@0: michael@0: var options = hs.getNewQueryOptions(); michael@0: options.resultType = options.RESULTS_AS_SITE_QUERY; michael@0: options.sortingMode = options.SORT_BY_TITLE_ASCENDING; michael@0: var query = hs.getNewQuery(); michael@0: var result = hs.executeQuery(query, options); michael@0: var root = result.root; michael@0: root.containerOpen = true; michael@0: do_check_eq(root.childCount, containers.length * 2); michael@0: michael@0: /* Expected results: michael@0: "mirror0.google.com", michael@0: "mirror0.mozilla.com", michael@0: "mirror1.google.com", michael@0: "mirror1.mozilla.com", michael@0: "mirror2.google.com", michael@0: "mirror2.mozilla.com", michael@0: "mirror3.google.com", <== We check for this site (index 6) michael@0: "mirror3.mozilla.com", michael@0: "mirror4.google.com", michael@0: "mirror4.mozilla.com", michael@0: "mirror5.google.com", michael@0: "mirror5.mozilla.com", michael@0: ... michael@0: */ michael@0: michael@0: // Items should be sorted by host michael@0: var siteNode = root.getChild(6) michael@0: .QueryInterface(Ci.nsINavHistoryContainerResultNode); michael@0: do_check_eq(siteNode.title, "mirror3.google.com"); michael@0: michael@0: siteNode.containerOpen = true; michael@0: do_check_eq(siteNode.childCount, 2); michael@0: michael@0: // Inside of host sites are sorted by title michael@0: var visitNode = siteNode.getChild(0); michael@0: do_check_eq(visitNode.uri, "http://mirror3.google.com/a"); michael@0: michael@0: // Bug 473157: changing sorting mode should not affect the containers michael@0: result.sortingMode = options.SORT_BY_TITLE_DESCENDING; michael@0: var siteNode = root.getChild(6) michael@0: .QueryInterface(Ci.nsINavHistoryContainerResultNode); michael@0: do_check_eq(siteNode.title, "mirror3.google.com"); michael@0: michael@0: siteNode.containerOpen = true; michael@0: do_check_eq(siteNode.childCount, 2); michael@0: michael@0: // But URLs are now sorted by title descending michael@0: var visit = siteNode.getChild(0); michael@0: do_check_eq(visit.uri, "http://mirror3.google.com/b"); michael@0: michael@0: siteNode.containerOpen = false; michael@0: root.containerOpen = false; michael@0: michael@0: // Cleanup. michael@0: bs.removeItem(itemId); michael@0: } michael@0: michael@0: /** michael@0: * Checks that queries grouped by date do liveupdate correctly. michael@0: */ michael@0: function task_test_date_liveupdate(aResultType) { michael@0: var midnight = nowObj; michael@0: midnight.setHours(0); michael@0: midnight.setMinutes(0); michael@0: midnight.setSeconds(0); michael@0: midnight.setMilliseconds(0); michael@0: michael@0: // TEST 1. Test that the query correctly updates when it is root. michael@0: var options = hs.getNewQueryOptions(); michael@0: options.resultType = aResultType; michael@0: var query = hs.getNewQuery(); michael@0: var result = hs.executeQuery(query, options); michael@0: var root = result.root; michael@0: root.containerOpen = true; michael@0: michael@0: do_check_eq(root.childCount, visibleContainers.length); michael@0: // Remove "Today". michael@0: hs.removePagesByTimeframe(midnight.getTime() * 1000, Date.now() * 1000); michael@0: do_check_eq(root.childCount, visibleContainers.length - 1); michael@0: michael@0: // Open "Last 7 days" container, this way we will have a container accepting michael@0: // the new visit, but we should still add back "Today" container. michael@0: var last7Days = root.getChild(1) michael@0: .QueryInterface(Ci.nsINavHistoryContainerResultNode); michael@0: last7Days.containerOpen = true; michael@0: michael@0: // Add a visit for "Today". This should add back the missing "Today" michael@0: // container. michael@0: yield task_add_normalized_visit(uri("http://www.mozilla.org/"), nowObj.getTime(), 0); michael@0: do_check_eq(root.childCount, visibleContainers.length); michael@0: michael@0: last7Days.containerOpen = false; michael@0: root.containerOpen = false; michael@0: michael@0: // TEST 2. Test that the query correctly updates even if it is not root. michael@0: var itemId = bs.insertBookmark(bs.toolbarFolder, michael@0: uri("place:type=" + aResultType), michael@0: bs.DEFAULT_INDEX, ""); michael@0: michael@0: // Query toolbar and open our query container, then check again liveupdate. michael@0: options = hs.getNewQueryOptions(); michael@0: query = hs.getNewQuery(); michael@0: query.setFolders([bs.toolbarFolder], 1); michael@0: result = hs.executeQuery(query, options); michael@0: root = result.root; michael@0: root.containerOpen = true; michael@0: do_check_eq(root.childCount, 1); michael@0: var dateContainer = root.getChild(0).QueryInterface(Ci.nsINavHistoryContainerResultNode); michael@0: dateContainer.containerOpen = true; michael@0: michael@0: do_check_eq(dateContainer.childCount, visibleContainers.length); michael@0: // Remove "Today". michael@0: hs.removePagesByTimeframe(midnight.getTime() * 1000, Date.now() * 1000); michael@0: do_check_eq(dateContainer.childCount, visibleContainers.length - 1); michael@0: // Add a visit for "Today". michael@0: yield task_add_normalized_visit(uri("http://www.mozilla.org/"), nowObj.getTime(), 0); michael@0: do_check_eq(dateContainer.childCount, visibleContainers.length); michael@0: michael@0: dateContainer.containerOpen = false; michael@0: root.containerOpen = false; michael@0: michael@0: // Cleanup. michael@0: bs.removeItem(itemId); michael@0: } michael@0: michael@0: function run_test() michael@0: { michael@0: run_next_test(); michael@0: } michael@0: michael@0: add_task(function test_history_sidebar() michael@0: { michael@0: // If we're dangerously close to a date change, just bail out. michael@0: if (nowObj.getHours() == 23 && nowObj.getMinutes() >= 50) { michael@0: return; michael@0: } michael@0: michael@0: yield task_fill_history(); michael@0: test_RESULTS_AS_DATE_SITE_QUERY(); michael@0: test_RESULTS_AS_DATE_QUERY(); michael@0: test_RESULTS_AS_SITE_QUERY(); michael@0: michael@0: yield task_test_date_liveupdate(Ci.nsINavHistoryQueryOptions.RESULTS_AS_DATE_SITE_QUERY); michael@0: yield task_test_date_liveupdate(Ci.nsINavHistoryQueryOptions.RESULTS_AS_DATE_QUERY); michael@0: michael@0: // The remaining views are michael@0: // RESULTS_AS_URI + SORT_BY_VISITCOUNT_DESCENDING michael@0: // -> test_399266.js michael@0: // RESULTS_AS_URI + SORT_BY_DATE_DESCENDING michael@0: // -> test_385397.js michael@0: });