summaryrefslogtreecommitdiffstats
path: root/browser/components/newtab/test/unit/lib/DownloadsManager.test.js
diff options
context:
space:
mode:
Diffstat (limited to 'browser/components/newtab/test/unit/lib/DownloadsManager.test.js')
-rw-r--r--browser/components/newtab/test/unit/lib/DownloadsManager.test.js373
1 files changed, 373 insertions, 0 deletions
diff --git a/browser/components/newtab/test/unit/lib/DownloadsManager.test.js b/browser/components/newtab/test/unit/lib/DownloadsManager.test.js
new file mode 100644
index 0000000000..0dfdff548b
--- /dev/null
+++ b/browser/components/newtab/test/unit/lib/DownloadsManager.test.js
@@ -0,0 +1,373 @@
+import { actionTypes as at } from "common/Actions.sys.mjs";
+import { DownloadsManager } from "lib/DownloadsManager.jsm";
+import { GlobalOverrider } from "test/unit/utils";
+
+describe("Downloads Manager", () => {
+ let downloadsManager;
+ let globals;
+ const DOWNLOAD_URL = "https://site.com/download.mov";
+
+ beforeEach(() => {
+ globals = new GlobalOverrider();
+ global.Cc["@mozilla.org/timer;1"] = {
+ createInstance() {
+ return {
+ initWithCallback: sinon.stub().callsFake(callback => callback()),
+ cancel: sinon.spy(),
+ };
+ },
+ };
+
+ globals.set("DownloadsCommon", {
+ getData: sinon.stub().returns({
+ addView: sinon.stub(),
+ removeView: sinon.stub(),
+ }),
+ copyDownloadLink: sinon.stub(),
+ deleteDownload: sinon.stub().returns(Promise.resolve()),
+ openDownload: sinon.stub(),
+ showDownloadedFile: sinon.stub(),
+ });
+
+ downloadsManager = new DownloadsManager();
+ downloadsManager.init({ dispatch() {} });
+ downloadsManager.onDownloadAdded({
+ source: { url: DOWNLOAD_URL },
+ endTime: Date.now(),
+ target: { path: "/path/to/download.mov", exists: true },
+ succeeded: true,
+ refresh: async () => {},
+ });
+ assert.ok(downloadsManager._downloadItems.has(DOWNLOAD_URL));
+
+ globals.set("NewTabUtils", { blockedLinks: { isBlocked() {} } });
+ });
+ afterEach(() => {
+ downloadsManager._downloadItems.clear();
+ globals.restore();
+ });
+ describe("#init", () => {
+ it("should add a DownloadsCommon view on init", () => {
+ downloadsManager.init({ dispatch() {} });
+ assert.calledTwice(global.DownloadsCommon.getData().addView);
+ });
+ });
+ describe("#onAction", () => {
+ it("should copy the file on COPY_DOWNLOAD_LINK", () => {
+ downloadsManager.onAction({
+ type: at.COPY_DOWNLOAD_LINK,
+ data: { url: DOWNLOAD_URL },
+ });
+ assert.calledOnce(global.DownloadsCommon.copyDownloadLink);
+ });
+ it("should remove the file on REMOVE_DOWNLOAD_FILE", () => {
+ downloadsManager.onAction({
+ type: at.REMOVE_DOWNLOAD_FILE,
+ data: { url: DOWNLOAD_URL },
+ });
+ assert.calledOnce(global.DownloadsCommon.deleteDownload);
+ });
+ it("should show the file on SHOW_DOWNLOAD_FILE", () => {
+ downloadsManager.onAction({
+ type: at.SHOW_DOWNLOAD_FILE,
+ data: { url: DOWNLOAD_URL },
+ });
+ assert.calledOnce(global.DownloadsCommon.showDownloadedFile);
+ });
+ it("should open the file on OPEN_DOWNLOAD_FILE if the type is download", () => {
+ downloadsManager.onAction({
+ type: at.OPEN_DOWNLOAD_FILE,
+ data: { url: DOWNLOAD_URL, type: "download" },
+ _target: { browser: {} },
+ });
+ assert.calledOnce(global.DownloadsCommon.openDownload);
+ });
+ it("should copy the file on UNINIT", () => {
+ // DownloadsManager._downloadData needs to exist first
+ downloadsManager.onAction({ type: at.UNINIT });
+ assert.calledOnce(global.DownloadsCommon.getData().removeView);
+ });
+ it("should not execute a download command if we do not have the correct url", () => {
+ downloadsManager.onAction({
+ type: at.SHOW_DOWNLOAD_FILE,
+ data: { url: "unknown_url" },
+ });
+ assert.notCalled(global.DownloadsCommon.showDownloadedFile);
+ });
+ });
+ describe("#onDownloadAdded", () => {
+ let newDownload;
+ beforeEach(() => {
+ downloadsManager._downloadItems.clear();
+ newDownload = {
+ source: { url: "https://site.com/newDownload.mov" },
+ endTime: Date.now(),
+ target: { path: "/path/to/newDownload.mov", exists: true },
+ succeeded: true,
+ refresh: async () => {},
+ };
+ });
+ afterEach(() => {
+ downloadsManager._downloadItems.clear();
+ });
+ it("should add a download on onDownloadAdded", () => {
+ downloadsManager.onDownloadAdded(newDownload);
+ assert.ok(
+ downloadsManager._downloadItems.has("https://site.com/newDownload.mov")
+ );
+ });
+ it("should not add a download if it already exists", () => {
+ downloadsManager.onDownloadAdded(newDownload);
+ downloadsManager.onDownloadAdded(newDownload);
+ downloadsManager.onDownloadAdded(newDownload);
+ downloadsManager.onDownloadAdded(newDownload);
+ const results = downloadsManager._downloadItems;
+ assert.equal(results.size, 1);
+ });
+ it("should not return any downloads if no threshold is provided", async () => {
+ downloadsManager.onDownloadAdded(newDownload);
+ const results = await downloadsManager.getDownloads(null, {});
+ assert.equal(results.length, 0);
+ });
+ it("should stop at numItems when it found one it's looking for", async () => {
+ const aDownload = {
+ source: { url: "https://site.com/aDownload.pdf" },
+ endTime: Date.now(),
+ target: { path: "/path/to/aDownload.pdf", exists: true },
+ succeeded: true,
+ refresh: async () => {},
+ };
+ downloadsManager.onDownloadAdded(aDownload);
+ downloadsManager.onDownloadAdded(newDownload);
+ const results = await downloadsManager.getDownloads(Infinity, {
+ numItems: 1,
+ onlySucceeded: true,
+ onlyExists: true,
+ });
+ assert.equal(results.length, 1);
+ assert.equal(results[0].url, aDownload.source.url);
+ });
+ it("should get all the downloads younger than the threshold provided", async () => {
+ const oldDownload = {
+ source: { url: "https://site.com/oldDownload.pdf" },
+ endTime: Date.now() - 40 * 60 * 60 * 1000,
+ target: { path: "/path/to/oldDownload.pdf", exists: true },
+ succeeded: true,
+ refresh: async () => {},
+ };
+ // Add an old download (older than 36 hours in this case)
+ downloadsManager.onDownloadAdded(oldDownload);
+ downloadsManager.onDownloadAdded(newDownload);
+ const RECENT_DOWNLOAD_THRESHOLD = 36 * 60 * 60 * 1000;
+ const results = await downloadsManager.getDownloads(
+ RECENT_DOWNLOAD_THRESHOLD,
+ { numItems: 5, onlySucceeded: true, onlyExists: true }
+ );
+ assert.equal(results.length, 1);
+ assert.equal(results[0].url, newDownload.source.url);
+ });
+ it("should dispatch DOWNLOAD_CHANGED when adding a download", () => {
+ downloadsManager._store.dispatch = sinon.spy();
+ downloadsManager._downloadTimer = null; // Nuke the timer
+ downloadsManager.onDownloadAdded(newDownload);
+ assert.calledOnce(downloadsManager._store.dispatch);
+ });
+ it("should refresh the downloads if onlyExists is true", async () => {
+ const aDownload = {
+ source: { url: "https://site.com/aDownload.pdf" },
+ endTime: Date.now() - 40 * 60 * 60 * 1000,
+ target: { path: "/path/to/aDownload.pdf", exists: true },
+ succeeded: true,
+ refresh: () => {},
+ };
+ sinon.stub(aDownload, "refresh").returns(Promise.resolve());
+ downloadsManager.onDownloadAdded(aDownload);
+ await downloadsManager.getDownloads(Infinity, {
+ numItems: 5,
+ onlySucceeded: true,
+ onlyExists: true,
+ });
+ assert.calledOnce(aDownload.refresh);
+ });
+ it("should not refresh the downloads if onlyExists is false (by default)", async () => {
+ const aDownload = {
+ source: { url: "https://site.com/aDownload.pdf" },
+ endTime: Date.now() - 40 * 60 * 60 * 1000,
+ target: { path: "/path/to/aDownload.pdf", exists: true },
+ succeeded: true,
+ refresh: () => {},
+ };
+ sinon.stub(aDownload, "refresh").returns(Promise.resolve());
+ downloadsManager.onDownloadAdded(aDownload);
+ await downloadsManager.getDownloads(Infinity, {
+ numItems: 5,
+ onlySucceeded: true,
+ });
+ assert.notCalled(aDownload.refresh);
+ });
+ it("should only return downloads that exist if specified", async () => {
+ const nonExistantDownload = {
+ source: { url: "https://site.com/nonExistantDownload.pdf" },
+ endTime: Date.now() - 40 * 60 * 60 * 1000,
+ target: { path: "/path/to/nonExistantDownload.pdf", exists: false },
+ succeeded: true,
+ refresh: async () => {},
+ };
+ downloadsManager.onDownloadAdded(newDownload);
+ downloadsManager.onDownloadAdded(nonExistantDownload);
+ const results = await downloadsManager.getDownloads(Infinity, {
+ numItems: 5,
+ onlySucceeded: true,
+ onlyExists: true,
+ });
+ assert.equal(results.length, 1);
+ assert.equal(results[0].url, newDownload.source.url);
+ });
+ it("should return all downloads that either exist or don't exist if not specified", async () => {
+ const nonExistantDownload = {
+ source: { url: "https://site.com/nonExistantDownload.pdf" },
+ endTime: Date.now() - 40 * 60 * 60 * 1000,
+ target: { path: "/path/to/nonExistantDownload.pdf", exists: false },
+ succeeded: true,
+ refresh: async () => {},
+ };
+ downloadsManager.onDownloadAdded(newDownload);
+ downloadsManager.onDownloadAdded(nonExistantDownload);
+ const results = await downloadsManager.getDownloads(Infinity, {
+ numItems: 5,
+ onlySucceeded: true,
+ });
+ assert.equal(results.length, 2);
+ assert.equal(results[0].url, newDownload.source.url);
+ assert.equal(results[1].url, nonExistantDownload.source.url);
+ });
+ it("should return only unblocked downloads", async () => {
+ const nonExistantDownload = {
+ source: { url: "https://site.com/nonExistantDownload.pdf" },
+ endTime: Date.now() - 40 * 60 * 60 * 1000,
+ target: { path: "/path/to/nonExistantDownload.pdf", exists: false },
+ succeeded: true,
+ refresh: async () => {},
+ };
+ downloadsManager.onDownloadAdded(newDownload);
+ downloadsManager.onDownloadAdded(nonExistantDownload);
+ globals.set("NewTabUtils", {
+ blockedLinks: {
+ isBlocked: item => item.url === nonExistantDownload.source.url,
+ },
+ });
+
+ const results = await downloadsManager.getDownloads(Infinity, {
+ numItems: 5,
+ onlySucceeded: true,
+ });
+
+ assert.equal(results.length, 1);
+ assert.propertyVal(results[0], "url", newDownload.source.url);
+ });
+ it("should only return downloads that were successful if specified", async () => {
+ const nonSuccessfulDownload = {
+ source: { url: "https://site.com/nonSuccessfulDownload.pdf" },
+ endTime: Date.now() - 40 * 60 * 60 * 1000,
+ target: { path: "/path/to/nonSuccessfulDownload.pdf", exists: false },
+ succeeded: false,
+ refresh: async () => {},
+ };
+ downloadsManager.onDownloadAdded(newDownload);
+ downloadsManager.onDownloadAdded(nonSuccessfulDownload);
+ const results = await downloadsManager.getDownloads(Infinity, {
+ numItems: 5,
+ onlySucceeded: true,
+ });
+ assert.equal(results.length, 1);
+ assert.equal(results[0].url, newDownload.source.url);
+ });
+ it("should return all downloads that were either successful or not if not specified", async () => {
+ const nonExistantDownload = {
+ source: { url: "https://site.com/nonExistantDownload.pdf" },
+ endTime: Date.now() - 40 * 60 * 60 * 1000,
+ target: { path: "/path/to/nonExistantDownload.pdf", exists: true },
+ succeeded: false,
+ refresh: async () => {},
+ };
+ downloadsManager.onDownloadAdded(newDownload);
+ downloadsManager.onDownloadAdded(nonExistantDownload);
+ const results = await downloadsManager.getDownloads(Infinity, {
+ numItems: 5,
+ });
+ assert.equal(results.length, 2);
+ assert.equal(results[0].url, newDownload.source.url);
+ assert.equal(results[1].url, nonExistantDownload.source.url);
+ });
+ it("should sort the downloads by recency", async () => {
+ const olderDownload1 = {
+ source: { url: "https://site.com/oldDownload1.pdf" },
+ endTime: Date.now() - 2 * 60 * 60 * 1000, // 2 hours ago
+ target: { path: "/path/to/oldDownload1.pdf", exists: true },
+ succeeded: true,
+ refresh: async () => {},
+ };
+ const olderDownload2 = {
+ source: { url: "https://site.com/oldDownload2.pdf" },
+ endTime: Date.now() - 60 * 60 * 1000, // 1 hour ago
+ target: { path: "/path/to/oldDownload2.pdf", exists: true },
+ succeeded: true,
+ refresh: async () => {},
+ };
+ // Add some older downloads and check that they are in order
+ downloadsManager.onDownloadAdded(olderDownload1);
+ downloadsManager.onDownloadAdded(olderDownload2);
+ downloadsManager.onDownloadAdded(newDownload);
+ const results = await downloadsManager.getDownloads(Infinity, {
+ numItems: 5,
+ onlySucceeded: true,
+ onlyExists: true,
+ });
+ assert.equal(results.length, 3);
+ assert.equal(results[0].url, newDownload.source.url);
+ assert.equal(results[1].url, olderDownload2.source.url);
+ assert.equal(results[2].url, olderDownload1.source.url);
+ });
+ it("should format the description properly if there is no file type", async () => {
+ newDownload.target.path = null;
+ downloadsManager.onDownloadAdded(newDownload);
+ const results = await downloadsManager.getDownloads(Infinity, {
+ numItems: 5,
+ onlySucceeded: true,
+ onlyExists: true,
+ });
+ assert.equal(results.length, 1);
+ assert.equal(results[0].description, "1.5 MB"); // see unit-entry.js to see where this comes from
+ });
+ });
+ describe("#onDownloadRemoved", () => {
+ let newDownload;
+ beforeEach(() => {
+ downloadsManager._downloadItems.clear();
+ newDownload = {
+ source: { url: "https://site.com/removeMe.mov" },
+ endTime: Date.now(),
+ target: { path: "/path/to/removeMe.mov", exists: true },
+ succeeded: true,
+ refresh: async () => {},
+ };
+ downloadsManager.onDownloadAdded(newDownload);
+ });
+ it("should remove a download if it exists on onDownloadRemoved", async () => {
+ downloadsManager.onDownloadRemoved({
+ source: { url: "https://site.com/removeMe.mov" },
+ });
+ const results = await downloadsManager.getDownloads(Infinity, {
+ numItems: 5,
+ });
+ assert.deepEqual(results, []);
+ });
+ it("should dispatch DOWNLOAD_CHANGED when removing a download", () => {
+ downloadsManager._store.dispatch = sinon.spy();
+ downloadsManager.onDownloadRemoved({
+ source: { url: "https://site.com/removeMe.mov" },
+ });
+ assert.calledOnce(downloadsManager._store.dispatch);
+ });
+ });
+});