summaryrefslogtreecommitdiffstats
path: root/toolkit/components/thumbnails/test/browser_thumbnails_update.js
blob: 971a2994e84987c21433f77115147e26100deca4 (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
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
/* Any copyright is dedicated to the Public Domain.
   http://creativecommons.org/publicdomain/zero/1.0/ */

/**
 * These tests check the auto-update facility of the thumbnail service.
 */

function* runTests() {
  // A "trampoline" - a generator that iterates over sub-iterators
  let tests = [
    simpleCaptureTest,
    capIfStaleErrorResponseUpdateTest,
    capIfStaleGoodResponseUpdateTest,
    regularCapErrorResponseUpdateTest,
    regularCapGoodResponseUpdateTest
  ];
  for (let test of tests) {
    info("Running subtest " + test.name);
    for (let iterator of test())
      yield iterator;
  }
}

function ensureThumbnailStale(url) {
  // We go behind the back of the thumbnail service and change the
  // mtime of the file to be in the past.
  let fname = PageThumbsStorage.getFilePathForURL(url);
  let file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
  file.initWithPath(fname);
  ok(file.exists(), fname + " should exist");
  // Set it as very stale...
  file.lastModifiedTime = Date.now() - 1000000000;
}

function getThumbnailModifiedTime(url) {
  let fname = PageThumbsStorage.getFilePathForURL(url);
  let file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
  file.initWithPath(fname);
  return file.lastModifiedTime;
}

// The tests!
/* Check functionality of a normal captureAndStoreIfStale request */
function* simpleCaptureTest() {
  let numNotifications = 0;
  const URL = "http://mochi.test:8888/browser/toolkit/components/thumbnails/test/thumbnails_update.sjs?simple";

  function observe(subject, topic, data) {
    is(topic, "page-thumbnail:create", "got expected topic");
    is(data, URL, "data is our test URL");
    if (++numNotifications == 2) {
      // This is the final notification and signals test success...
      Services.obs.removeObserver(observe, "page-thumbnail:create");
      gBrowser.removeTab(gBrowser.selectedTab);
      next();
    }
  }

  Services.obs.addObserver(observe, "page-thumbnail:create", false);
  // Create a tab - we don't care what the content is.
  yield addTab(URL);
  let browser = gBrowser.selectedBrowser;

  // Capture the screenshot.
  PageThumbs.captureAndStore(browser, function () {
    // We've got a capture so should have seen the observer.
    is(numNotifications, 1, "got notification of item being created.");
    // The capture is now "fresh" - so requesting the URL should not cause
    // a new capture.
    PageThumbs.captureAndStoreIfStale(browser, function() {
      is(numNotifications, 1, "still only 1 notification of item being created.");

      ensureThumbnailStale(URL);
      // Ask for it to be updated.
      PageThumbs.captureAndStoreIfStale(browser);
      // But it's async, so wait - our observer above will call next() when
      // the notification comes.
    });
  });
  yield undefined // wait for callbacks to call 'next'...
}

/* Check functionality of captureAndStoreIfStale when there is an error response
   from the server.
 */
function* capIfStaleErrorResponseUpdateTest() {
  const URL = "http://mochi.test:8888/browser/toolkit/components/thumbnails/test/thumbnails_update.sjs?fail";
  yield addTab(URL);

  yield captureAndCheckColor(0, 255, 0, "we have a green thumbnail");
  // update the thumbnail to be stale, then re-request it.  The server will
  // return a 400 response and a red thumbnail.
  // The service should not save the thumbnail - so we (a) check the thumbnail
  // remains green and (b) check the mtime of the file is < now.
  ensureThumbnailStale(URL);
  yield navigateTo(URL);
  // now() returns a higher-precision value than the modified time of a file.
  // As we set the thumbnail very stale, allowing 1 second of "slop" here
  // works around this while still keeping the test valid.
  let now = Date.now() - 1000 ;
  PageThumbs.captureAndStoreIfStale(gBrowser.selectedBrowser, () => {
    ok(getThumbnailModifiedTime(URL) < now, "modified time should be < now");
    retrieveImageDataForURL(URL, function ([r, g, b]) {
      is("" + [r, g, b], "" + [0, 255, 0], "thumbnail is still green");
      gBrowser.removeTab(gBrowser.selectedTab);
      next();
    });
  });
  yield undefined; // wait for callback to call 'next'...
}

/* Check functionality of captureAndStoreIfStale when there is a non-error
   response from the server.  This test is somewhat redundant - although it is
   using a http:// URL instead of a data: url like most others.
 */
function* capIfStaleGoodResponseUpdateTest() {
  const URL = "http://mochi.test:8888/browser/toolkit/components/thumbnails/test/thumbnails_update.sjs?ok";
  yield addTab(URL);
  let browser = gBrowser.selectedBrowser;

  yield captureAndCheckColor(0, 255, 0, "we have a green thumbnail");
  // update the thumbnail to be stale, then re-request it.  The server will
  // return a 200 response and a red thumbnail - so that new thumbnail should
  // end up captured.
  ensureThumbnailStale(URL);
  yield navigateTo(URL);
  // now() returns a higher-precision value than the modified time of a file.
  // As we set the thumbnail very stale, allowing 1 second of "slop" here
  // works around this while still keeping the test valid.
  let now = Date.now() - 1000 ;
  PageThumbs.captureAndStoreIfStale(browser, () => {
    ok(getThumbnailModifiedTime(URL) >= now, "modified time should be >= now");
    // the captureAndStoreIfStale request saw a 200 response with the red body,
    // so we expect to see the red version here.
    retrieveImageDataForURL(URL, function ([r, g, b]) {
      is("" + [r, g, b], "" + [255, 0, 0], "thumbnail is now red");
      next();
    });
  });
  yield undefined; // wait for callback to call 'next'...
}

/* Check functionality of captureAndStore when there is an error response
   from the server.
 */
function* regularCapErrorResponseUpdateTest() {
  const URL = "http://mochi.test:8888/browser/toolkit/components/thumbnails/test/thumbnails_update.sjs?fail";
  yield addTab(URL);
  yield captureAndCheckColor(0, 255, 0, "we have a green thumbnail");
  gBrowser.removeTab(gBrowser.selectedTab);
  // do it again - the server will return a 400, so the foreground service
  // should not update it.
  yield addTab(URL);
  yield captureAndCheckColor(0, 255, 0, "we still have a green thumbnail");
}

/* Check functionality of captureAndStore when there is an OK response
   from the server.
 */
function* regularCapGoodResponseUpdateTest() {
  const URL = "http://mochi.test:8888/browser/toolkit/components/thumbnails/test/thumbnails_update.sjs?ok";
  yield addTab(URL);
  yield captureAndCheckColor(0, 255, 0, "we have a green thumbnail");
  gBrowser.removeTab(gBrowser.selectedTab);
  // do it again - the server will return a 200, so the foreground service
  // should  update it.
  yield addTab(URL);
  yield captureAndCheckColor(255, 0, 0, "we now  have a red thumbnail");
}