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: 'use strict'; michael@0: michael@0: module.metadata = { michael@0: 'engines': { michael@0: 'Firefox': '*' michael@0: } michael@0: }; michael@0: michael@0: const { Cc, Ci } = require('chrome'); michael@0: const { defer, all } = require('sdk/core/promise'); michael@0: const { filter } = require('sdk/event/utils'); michael@0: const { on, off } = require('sdk/event/core'); michael@0: const { events } = require('sdk/places/events'); michael@0: const { setTimeout } = require('sdk/timers'); michael@0: const { before, after } = require('sdk/test/utils'); michael@0: const bmsrv = Cc['@mozilla.org/browser/nav-bookmarks-service;1']. michael@0: getService(Ci.nsINavBookmarksService); michael@0: const { release, platform } = require('node/os'); michael@0: michael@0: const isOSX10_6 = (() => { michael@0: let vString = release(); michael@0: return vString && /darwin/.test(platform()) && /10\.6/.test(vString); michael@0: })(); michael@0: michael@0: const { michael@0: search michael@0: } = require('sdk/places/history'); michael@0: const { michael@0: invalidResolve, invalidReject, createTree, createBookmark, michael@0: compareWithHost, addVisits, resetPlaces, createBookmarkItem, michael@0: removeVisits michael@0: } = require('../places-helper'); michael@0: const { save, MENU, UNSORTED } = require('sdk/places/bookmarks'); michael@0: const { promisedEmitter } = require('sdk/places/utils'); michael@0: michael@0: exports['test bookmark-item-added'] = function (assert, done) { michael@0: function handler ({type, data}) { michael@0: if (type !== 'bookmark-item-added') return; michael@0: if (data.title !== 'bookmark-added-title') return; michael@0: michael@0: assert.equal(type, 'bookmark-item-added', 'correct type in bookmark-added event'); michael@0: assert.equal(data.type, 'bookmark', 'correct data in bookmark-added event'); michael@0: assert.ok(data.id != null, 'correct data in bookmark-added event'); michael@0: assert.ok(data.parentId != null, 'correct data in bookmark-added event'); michael@0: assert.ok(data.index != null, 'correct data in bookmark-added event'); michael@0: assert.equal(data.url, 'http://moz.com/', 'correct data in bookmark-added event'); michael@0: assert.ok(data.dateAdded != null, 'correct data in bookmark-added event'); michael@0: events.off('data', handler); michael@0: done(); michael@0: } michael@0: events.on('data', handler); michael@0: createBookmark({ title: 'bookmark-added-title' }); michael@0: }; michael@0: michael@0: exports['test bookmark-item-changed'] = function (assert, done) { michael@0: let id; michael@0: let complete = makeCompleted(done); michael@0: michael@0: // Due to bug 969616 and bug 971964, disabling tests in 10.6 (happens only michael@0: // in debug builds) to prevent intermittent failures michael@0: if (isOSX10_6) { michael@0: assert.ok(true, 'skipping test in OSX 10.6'); michael@0: return done(); michael@0: } michael@0: michael@0: function handler ({type, data}) { michael@0: if (type !== 'bookmark-item-changed') return; michael@0: if (data.id !== id) return; michael@0: // Abort if the 'bookmark-item-changed' event isn't for the `title` property, michael@0: // as sometimes the event can be for the `url` property. michael@0: // Intermittent failure, bug 969616 michael@0: if (data.property !== 'title') return; michael@0: michael@0: assert.equal(type, 'bookmark-item-changed', michael@0: 'correct type in bookmark-item-changed event'); michael@0: assert.equal(data.type, 'bookmark', michael@0: 'correct data in bookmark-item-changed event'); michael@0: assert.equal(data.property, 'title', michael@0: 'correct property in bookmark-item-changed event'); michael@0: assert.equal(data.value, 'bookmark-changed-title-2', michael@0: 'correct value in bookmark-item-changed event'); michael@0: assert.ok(data.id === id, 'correct id in bookmark-item-changed event'); michael@0: assert.ok(data.parentId != null, 'correct data in bookmark-added event'); michael@0: michael@0: events.off('data', handler); michael@0: complete(); michael@0: } michael@0: events.on('data', handler); michael@0: michael@0: createBookmarkItem({ title: 'bookmark-changed-title' }).then(item => { michael@0: id = item.id; michael@0: item.title = 'bookmark-changed-title-2'; michael@0: return saveP(item); michael@0: }).then(complete); michael@0: }; michael@0: michael@0: exports['test bookmark-item-moved'] = function (assert, done) { michael@0: let id; michael@0: let complete = makeCompleted(done); michael@0: let previousIndex, previousParentId; michael@0: michael@0: // Due to bug 969616 and bug 971964, disabling tests in 10.6 (happens only michael@0: // in debug builds) to prevent intermittent failures michael@0: if (isOSX10_6) { michael@0: assert.ok(true, 'skipping test in OSX 10.6'); michael@0: return done(); michael@0: } michael@0: michael@0: function handler ({type, data}) { michael@0: if (type !== 'bookmark-item-moved') return; michael@0: if (data.id !== id) return; michael@0: assert.equal(type, 'bookmark-item-moved', michael@0: 'correct type in bookmark-item-moved event'); michael@0: assert.equal(data.type, 'bookmark', michael@0: 'correct data in bookmark-item-moved event'); michael@0: assert.ok(data.id === id, 'correct id in bookmark-item-moved event'); michael@0: assert.equal(data.previousParentId, previousParentId, michael@0: 'correct previousParentId'); michael@0: assert.equal(data.currentParentId, bmsrv.getFolderIdForItem(id), michael@0: 'correct currentParentId'); michael@0: assert.equal(data.previousIndex, previousIndex, 'correct previousIndex'); michael@0: assert.equal(data.currentIndex, bmsrv.getItemIndex(id), 'correct currentIndex'); michael@0: michael@0: events.off('data', handler); michael@0: complete(); michael@0: } michael@0: events.on('data', handler); michael@0: michael@0: createBookmarkItem({ michael@0: title: 'bookmark-moved-title', michael@0: group: UNSORTED michael@0: }).then(item => { michael@0: id = item.id; michael@0: previousIndex = bmsrv.getItemIndex(id); michael@0: previousParentId = bmsrv.getFolderIdForItem(id); michael@0: item.group = MENU; michael@0: return saveP(item); michael@0: }).then(complete); michael@0: }; michael@0: michael@0: exports['test bookmark-item-removed'] = function (assert, done) { michael@0: let id; michael@0: let complete = makeCompleted(done); michael@0: function handler ({type, data}) { michael@0: if (type !== 'bookmark-item-removed') return; michael@0: if (data.id !== id) return; michael@0: assert.equal(type, 'bookmark-item-removed', michael@0: 'correct type in bookmark-item-removed event'); michael@0: assert.equal(data.type, 'bookmark', michael@0: 'correct data in bookmark-item-removed event'); michael@0: assert.ok(data.id === id, 'correct id in bookmark-item-removed event'); michael@0: assert.equal(data.parentId, UNSORTED.id, michael@0: 'correct parentId in bookmark-item-removed'); michael@0: assert.equal(data.url, 'http://moz.com/', michael@0: 'correct url in bookmark-item-removed event'); michael@0: assert.equal(data.index, 0, michael@0: 'correct index in bookmark-item-removed event'); michael@0: michael@0: events.off('data', handler); michael@0: complete(); michael@0: } michael@0: events.on('data', handler); michael@0: michael@0: createBookmarkItem({ michael@0: title: 'bookmark-item-remove-title', michael@0: group: UNSORTED michael@0: }).then(item => { michael@0: id = item.id; michael@0: item.remove = true; michael@0: return saveP(item); michael@0: }).then(complete); michael@0: }; michael@0: michael@0: exports['test bookmark-item-visited'] = function (assert, done) { michael@0: let id; michael@0: let complete = makeCompleted(done); michael@0: function handler ({type, data}) { michael@0: if (type !== 'bookmark-item-visited') return; michael@0: if (data.id !== id) return; michael@0: assert.equal(type, 'bookmark-item-visited', michael@0: 'correct type in bookmark-item-visited event'); michael@0: assert.ok(data.id === id, 'correct id in bookmark-item-visited event'); michael@0: assert.equal(data.parentId, UNSORTED.id, michael@0: 'correct parentId in bookmark-item-visited'); michael@0: assert.ok(data.transitionType != null, michael@0: 'has a transition type in bookmark-item-visited event'); michael@0: assert.ok(data.time != null, michael@0: 'has a time in bookmark-item-visited event'); michael@0: assert.ok(data.visitId != null, michael@0: 'has a visitId in bookmark-item-visited event'); michael@0: assert.equal(data.url, 'http://bookmark-item-visited.com/', michael@0: 'correct url in bookmark-item-visited event'); michael@0: michael@0: events.off('data', handler); michael@0: complete(); michael@0: } michael@0: events.on('data', handler); michael@0: michael@0: createBookmarkItem({ michael@0: title: 'bookmark-item-visited', michael@0: url: 'http://bookmark-item-visited.com/' michael@0: }).then(item => { michael@0: id = item.id; michael@0: return addVisits('http://bookmark-item-visited.com/'); michael@0: }).then(complete); michael@0: }; michael@0: michael@0: exports['test history-start-batch, history-end-batch, history-start-clear'] = function (assert, done) { michael@0: let complete = makeCompleted(done, 4); michael@0: let startEvent = filter(events, ({type}) => type === 'history-start-batch'); michael@0: let endEvent = filter(events, ({type}) => type === 'history-end-batch'); michael@0: let clearEvent = filter(events, ({type}) => type === 'history-start-clear'); michael@0: function startHandler ({type, data}) { michael@0: assert.pass('history-start-batch called'); michael@0: assert.equal(type, 'history-start-batch', michael@0: 'history-start-batch has correct type'); michael@0: off(startEvent, 'data', startHandler); michael@0: on(endEvent, 'data', endHandler); michael@0: complete(); michael@0: } michael@0: function endHandler ({type, data}) { michael@0: assert.pass('history-end-batch called'); michael@0: assert.equal(type, 'history-end-batch', michael@0: 'history-end-batch has correct type'); michael@0: off(endEvent, 'data', endHandler); michael@0: complete(); michael@0: } michael@0: function clearHandler ({type, data}) { michael@0: assert.pass('history-start-clear called'); michael@0: assert.equal(type, 'history-start-clear', michael@0: 'history-start-clear has correct type'); michael@0: off(clearEvent, 'data', clearHandler); michael@0: complete(); michael@0: } michael@0: michael@0: on(startEvent, 'data', startHandler); michael@0: on(clearEvent, 'data', clearHandler); michael@0: michael@0: createBookmark().then(() => { michael@0: resetPlaces(complete); michael@0: }) michael@0: }; michael@0: michael@0: exports['test history-visit, history-title-changed'] = function (assert, done) { michael@0: let complete = makeCompleted(() => { michael@0: off(titleEvents, 'data', titleHandler); michael@0: off(visitEvents, 'data', visitHandler); michael@0: done(); michael@0: }, 6); michael@0: let visitEvents = filter(events, ({type}) => type === 'history-visit'); michael@0: let titleEvents = filter(events, ({type}) => type === 'history-title-changed'); michael@0: michael@0: let urls = ['http://moz.com/', 'http://firefox.com/', 'http://mdn.com/']; michael@0: michael@0: function visitHandler ({type, data}) { michael@0: assert.equal(type, 'history-visit', 'correct type in history-visit'); michael@0: assert.ok(~urls.indexOf(data.url), 'history-visit has correct url'); michael@0: assert.ok(data.visitId != null, 'history-visit has a visitId'); michael@0: assert.ok(data.time != null, 'history-visit has a time'); michael@0: assert.ok(data.sessionId != null, 'history-visit has a sessionId'); michael@0: assert.ok(data.referringId != null, 'history-visit has a referringId'); michael@0: assert.ok(data.transitionType != null, 'history-visit has a transitionType'); michael@0: complete(); michael@0: } michael@0: michael@0: function titleHandler ({type, data}) { michael@0: assert.equal(type, 'history-title-changed', michael@0: 'correct type in history-title-changed'); michael@0: assert.ok(~urls.indexOf(data.url), michael@0: 'history-title-changed has correct url'); michael@0: assert.ok(data.title, 'history-title-changed has title'); michael@0: complete(); michael@0: } michael@0: michael@0: on(titleEvents, 'data', titleHandler); michael@0: on(visitEvents, 'data', visitHandler); michael@0: addVisits(urls); michael@0: } michael@0: michael@0: exports['test history-delete-url'] = function (assert, done) { michael@0: let complete = makeCompleted(() => { michael@0: events.off('data', handler); michael@0: done(); michael@0: }, 3); michael@0: let urls = ['http://moz.com/', 'http://firefox.com/', 'http://mdn.com/']; michael@0: function handler({type, data}) { michael@0: if (type !== 'history-delete-url') return; michael@0: assert.equal(type, 'history-delete-url', michael@0: 'history-delete-url has correct type'); michael@0: assert.ok(~urls.indexOf(data.url), 'history-delete-url has correct url'); michael@0: complete(); michael@0: } michael@0: michael@0: events.on('data', handler); michael@0: addVisits(urls).then(() => { michael@0: removeVisits(urls); michael@0: }); michael@0: }; michael@0: michael@0: exports['test history-page-changed'] = function (assert) { michael@0: assert.pass('history-page-changed tested in test-places-favicons'); michael@0: }; michael@0: michael@0: exports['test history-delete-visits'] = function (assert) { michael@0: assert.pass('TODO test history-delete-visits'); michael@0: }; michael@0: michael@0: before(exports, (name, assert, done) => resetPlaces(done)); michael@0: after(exports, (name, assert, done) => resetPlaces(done)); michael@0: michael@0: function saveP () { michael@0: return promisedEmitter(save.apply(null, Array.slice(arguments))); michael@0: } michael@0: michael@0: function makeCompleted (done, countTo) { michael@0: let count = 0; michael@0: countTo = countTo || 2; michael@0: return function () { michael@0: if (++count === countTo) done(); michael@0: }; michael@0: }