summaryrefslogtreecommitdiffstats
path: root/browser/components/newtab/test/unit/lib/PersistentCache.test.js
blob: dd39d246e6e93d02b3079b78944e6c86a307af18 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
import { GlobalOverrider } from "test/unit/utils";
import { PersistentCache } from "lib/PersistentCache.jsm";

describe("PersistentCache", () => {
  let fakeOS;
  let fakeJsonParse;
  let fakeFetch;
  let cache;
  let filename = "cache.json";
  let reportErrorStub;
  let globals;
  let sandbox;

  beforeEach(() => {
    globals = new GlobalOverrider();
    sandbox = sinon.createSandbox();
    fakeOS = {
      Constants: { Path: { localProfileDir: "/foo/bar" } },
      File: {
        writeAtomic: sinon.stub().returns(Promise.resolve()),
      },
      Path: { join: () => filename },
    };
    fakeJsonParse = sandbox.stub().resolves({});
    fakeFetch = sandbox.stub().resolves({ json: fakeJsonParse });
    reportErrorStub = sandbox.stub();
    globals.set("OS", fakeOS);
    globals.set("Cu", { reportError: reportErrorStub });
    globals.set("fetch", fakeFetch);

    cache = new PersistentCache(filename);
  });
  afterEach(() => {
    globals.restore();
    sandbox.restore();
  });

  describe("#get", () => {
    it("tries to fetch the file", async () => {
      await cache.get("foo");
      assert.calledOnce(fakeFetch);
    });
    it("doesnt try to parse file if it doesn't exist", async () => {
      fakeFetch.throws();
      await cache.get("foo");
      assert.notCalled(fakeJsonParse);
    });
    it("doesnt try to fetch the file if it was already loaded", async () => {
      await cache._load();
      fakeFetch.resetHistory();
      await cache.get("foo");
      assert.notCalled(fakeFetch);
    });
    it("should catch and report errors", async () => {
      fakeJsonParse.throws();
      await cache._load();
      assert.calledOnce(reportErrorStub);
    });
    it("returns data for a given cache key", async () => {
      fakeJsonParse.resolves({ foo: "bar" });
      let value = await cache.get("foo");
      assert.equal(value, "bar");
    });
    it("returns undefined for a cache key that doesn't exist", async () => {
      let value = await cache.get("baz");
      assert.equal(value, undefined);
    });
    it("returns all the data if no cache key is specified", async () => {
      fakeJsonParse.resolves({ foo: "bar" });
      let value = await cache.get();
      assert.deepEqual(value, { foo: "bar" });
    });
  });

  describe("#set", () => {
    it("tries to fetch the file on the first set", async () => {
      await cache.set("foo", { x: 42 });
      assert.calledOnce(fakeFetch);
    });
    it("doesnt try to fetch the file if it was already loaded", async () => {
      cache = new PersistentCache(filename, true);
      await cache._load();
      fakeFetch.resetHistory();
      await cache.set("foo", { x: 42 });
      assert.notCalled(fakeFetch);
    });
    it("tries to fetch the file on the first set", async () => {
      await cache.set("foo", { x: 42 });
      assert.calledOnce(fakeFetch);
    });
    it("sets a string value", async () => {
      const key = "testkey";
      const value = "testvalue";
      await cache.set(key, value);
      const cachedValue = await cache.get(key);
      assert.equal(cachedValue, value);
    });
    it("sets an object value", async () => {
      const key = "testkey";
      const value = { x: 1, y: 2, z: 3 };
      await cache.set(key, value);
      const cachedValue = await cache.get(key);
      assert.deepEqual(cachedValue, value);
    });
    it("writes the data to file", async () => {
      const key = "testkey";
      const value = { x: 1, y: 2, z: 3 };
      fakeOS.File.exists = async () => false;
      await cache.set(key, value);
      assert.calledOnce(fakeOS.File.writeAtomic);
      assert.calledWith(
        fakeOS.File.writeAtomic,
        filename,
        `{"testkey":{"x":1,"y":2,"z":3}}`,
        { tmpPath: `${filename}.tmp` }
      );
    });
    it("throws when failing the file", async () => {
      sandbox.stub(OS.Path, "join").throws("bad file");

      let rejected = false;
      try {
        await cache.set("key", "val");
      } catch (error) {
        rejected = true;
      }

      assert(rejected);
    });
  });
});