aboutsummaryrefslogtreecommitdiff
path: root/deps/npm/node_modules/npm-profile/node_modules/make-fetch-happen/node_modules/http-cache-semantics/test
diff options
context:
space:
mode:
Diffstat (limited to 'deps/npm/node_modules/npm-profile/node_modules/make-fetch-happen/node_modules/http-cache-semantics/test')
-rw-r--r--deps/npm/node_modules/npm-profile/node_modules/make-fetch-happen/node_modules/http-cache-semantics/test/misctest.js33
-rw-r--r--deps/npm/node_modules/npm-profile/node_modules/make-fetch-happen/node_modules/http-cache-semantics/test/okhttptest.js301
-rw-r--r--deps/npm/node_modules/npm-profile/node_modules/make-fetch-happen/node_modules/http-cache-semantics/test/requesttest.js61
-rw-r--r--deps/npm/node_modules/npm-profile/node_modules/make-fetch-happen/node_modules/http-cache-semantics/test/responsetest.js385
-rw-r--r--deps/npm/node_modules/npm-profile/node_modules/make-fetch-happen/node_modules/http-cache-semantics/test/revalidatetest.js181
-rw-r--r--deps/npm/node_modules/npm-profile/node_modules/make-fetch-happen/node_modules/http-cache-semantics/test/satisfytest.js64
-rw-r--r--deps/npm/node_modules/npm-profile/node_modules/make-fetch-happen/node_modules/http-cache-semantics/test/updatetest.js98
-rw-r--r--deps/npm/node_modules/npm-profile/node_modules/make-fetch-happen/node_modules/http-cache-semantics/test/varytest.js75
8 files changed, 1198 insertions, 0 deletions
diff --git a/deps/npm/node_modules/npm-profile/node_modules/make-fetch-happen/node_modules/http-cache-semantics/test/misctest.js b/deps/npm/node_modules/npm-profile/node_modules/make-fetch-happen/node_modules/http-cache-semantics/test/misctest.js
new file mode 100644
index 0000000000..643567d962
--- /dev/null
+++ b/deps/npm/node_modules/npm-profile/node_modules/make-fetch-happen/node_modules/http-cache-semantics/test/misctest.js
@@ -0,0 +1,33 @@
+'use strict';
+
+const assert = require('assert');
+const CachePolicy = require('..');
+
+
+describe('Other', function() {
+ it('Thaw wrong object', function() {
+ assert.throws(() => {
+ CachePolicy.fromObject({});
+ });
+ });
+
+ it('Missing headers', function() {
+ assert.throws(() => {
+ new CachePolicy({});
+ });
+ assert.throws(() => {
+ new CachePolicy({headers:{}}, {});
+ });
+
+ const cache = new CachePolicy({headers:{}}, {headers:{}});
+ assert.throws(() => {
+ cache.satisfiesWithoutRevalidation({});
+ });
+ assert.throws(() => {
+ cache.revalidatedPolicy({});
+ });
+ assert.throws(() => {
+ cache.revalidatedPolicy({headers:{}}, {});
+ });
+ });
+});
diff --git a/deps/npm/node_modules/npm-profile/node_modules/make-fetch-happen/node_modules/http-cache-semantics/test/okhttptest.js b/deps/npm/node_modules/npm-profile/node_modules/make-fetch-happen/node_modules/http-cache-semantics/test/okhttptest.js
new file mode 100644
index 0000000000..315f114ae8
--- /dev/null
+++ b/deps/npm/node_modules/npm-profile/node_modules/make-fetch-happen/node_modules/http-cache-semantics/test/okhttptest.js
@@ -0,0 +1,301 @@
+'use strict';
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+const assert = require('assert');
+const CachePolicy = require('..');
+
+describe('okhttp tests', function(){
+ it('responseCachingByResponseCode', function(){
+ // Test each documented HTTP/1.1 code, plus the first unused value in each range.
+ // http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
+
+ assertCached(false, 100);
+ assertCached(false, 101);
+ assertCached(false, 102);
+ assertCached(true, 200);
+ assertCached(false, 201);
+ assertCached(false, 202);
+ assertCached(true, 203);
+ assertCached(true, 204);
+ assertCached(false, 205);
+ assertCached(false, 206); //Electing to not cache partial responses
+ assertCached(false, 207);
+ assertCached(true, 300);
+ assertCached(true, 301);
+ assertCached(true, 302);
+ // assertCached(false, 303);
+ assertCached(false, 304);
+ assertCached(false, 305);
+ assertCached(false, 306);
+ assertCached(true, 307);
+ assertCached(true, 308);
+ assertCached(false, 400);
+ assertCached(false, 401);
+ assertCached(false, 402);
+ assertCached(false, 403);
+ assertCached(true, 404);
+ assertCached(true, 405);
+ assertCached(false, 406);
+ assertCached(false, 408);
+ assertCached(false, 409);
+ // the HTTP spec permits caching 410s, but the RI doesn't.
+ assertCached(true, 410);
+ assertCached(false, 411);
+ assertCached(false, 412);
+ assertCached(false, 413);
+ assertCached(true, 414);
+ assertCached(false, 415);
+ assertCached(false, 416);
+ assertCached(false, 417);
+ assertCached(false, 418);
+ assertCached(false, 429);
+
+ assertCached(false, 500);
+ assertCached(true, 501);
+ assertCached(false, 502);
+ assertCached(false, 503);
+ assertCached(false, 504);
+ assertCached(false, 505);
+ assertCached(false, 506);
+ });
+
+ function assertCached(shouldPut, responseCode) {
+ let expectedResponseCode = responseCode;
+
+ const mockResponse = {headers:{
+ "last-modified": formatDate(-1, 3600),
+ "expires": formatDate(1, 3600),
+ "www-authenticate": "challenge",
+ },
+ status: responseCode,
+ body: "ABCDE",
+ };
+ if (responseCode == 407) {
+ mockResponse.headers["proxy-authenticate"] = "Basic realm=\"protected area\"";
+ } else if (responseCode == 401) {
+ mockResponse.headers["www-authenticate"] = "Basic realm=\"protected area\"";
+ } else if (responseCode == 204 || responseCode == 205) {
+ mockResponse.body = ""; // We forbid bodies for 204 and 205.
+ }
+
+ const request = {url: "/", headers:{}};
+
+ const cache = new CachePolicy(request, mockResponse, {shared:false});
+
+ assert.equal(shouldPut, cache.storable());
+ }
+
+
+ it('defaultExpirationDateFullyCachedForLessThan24Hours', function() {
+ // last modified: 105 seconds ago
+ // served: 5 seconds ago
+ // default lifetime: (105 - 5) / 10 = 10 seconds
+ // expires: 10 seconds from served date = 5 seconds from now
+ const cache = new CachePolicy({headers:{}}, {headers:{
+ "last-modified": formatDate(-105, 1),
+ "date": formatDate(-5, 1),
+ },
+ body: "A"}, {shared:false});
+
+ assert(cache.timeToLive() > 4000);
+ });
+
+ it('defaultExpirationDateFullyCachedForMoreThan24Hours', function() {
+ // last modified: 105 days ago
+ // served: 5 days ago
+ // default lifetime: (105 - 5) / 10 = 10 days
+ // expires: 10 days from served date = 5 days from now
+ const cache = new CachePolicy({headers:{}}, {headers:{
+ "last-modified": formatDate(-105, 3600*24),
+ "date": formatDate(-5, 3600*24),
+ },
+ body: "A"}, {shared:false});
+
+ assert(cache.maxAge() >= 10*3600*24);
+ assert(cache.timeToLive()+1000 >= 5*3600*24);
+ });
+
+ it('maxAgeInThePastWithDateHeaderButNoLastModifiedHeader', function() {
+ // Chrome interprets max-age relative to the local clock. Both our cache
+ // and Firefox both use the earlier of the local and server's clock.
+ const cache = new CachePolicy({headers:{}}, {headers:{
+ "date": formatDate(-120, 1),
+ "cache-control": "max-age=60",
+ }}, {shared:false});
+
+ assert(cache.stale());
+ });
+
+ it('maxAgePreferredOverLowerSharedMaxAge', function() {
+ const cache = new CachePolicy({headers:{}}, {headers:{
+ "date": formatDate(-2, 60),
+ "cache-control": "s-maxage=60, max-age=180",
+ }}, {shared:false});
+
+ assert.equal(cache.maxAge(), 180);
+ });
+
+ it('maxAgePreferredOverHigherMaxAge', function() {
+ const cache = new CachePolicy({headers:{}}, {headers:{
+ "date": formatDate(-3, 60),
+ "cache-control": "s-maxage=60, max-age=180",
+ }}, {shared:false});
+
+ assert(cache.stale());
+ });
+
+ it('requestMethodOptionsIsNotCached', function() {
+ testRequestMethodNotCached("OPTIONS");
+ });
+
+ it('requestMethodPutIsNotCached', function() {
+ testRequestMethodNotCached("PUT");
+ });
+
+ it('requestMethodDeleteIsNotCached', function() {
+ testRequestMethodNotCached("DELETE");
+ });
+
+ it('requestMethodTraceIsNotCached', function() {
+ testRequestMethodNotCached("TRACE");
+ });
+
+ function testRequestMethodNotCached(method) {
+ // 1. seed the cache (potentially)
+ // 2. expect a cache hit or miss
+ const cache = new CachePolicy({method, headers:{}}, {headers:{
+ "expires": formatDate(1, 3600),
+ }}, {shared:false});
+
+ assert(cache.stale());
+ }
+
+ it('etagAndExpirationDateInTheFuture', function() {
+ const cache = new CachePolicy({headers:{}}, {headers:{
+ "etag": "v1",
+ "last-modified": formatDate(-2, 3600),
+ "expires": formatDate(1, 3600),
+ }}, {shared:false});
+
+ assert(cache.timeToLive() > 0);
+ });
+
+ it('clientSideNoStore', function() {
+ const cache = new CachePolicy({headers:{
+ "cache-control": "no-store",
+ }}, {headers:{
+ "cache-control": "max-age=60",
+ }}, {shared:false});
+
+ assert(!cache.storable());
+ });
+
+ it('requestMaxAge', function() {
+ const cache = new CachePolicy({headers:{}}, {headers:{
+ "last-modified": formatDate(-2, 3600),
+ "date": formatDate(-1, 60),
+ "expires": formatDate(1, 3600),
+ }}, {shared:false});
+
+ assert(!cache.stale());
+ assert(cache.age() >= 60);
+
+ assert(cache.satisfiesWithoutRevalidation({headers:{
+ "cache-control": "max-age=90",
+ }}));
+
+ assert(!cache.satisfiesWithoutRevalidation({headers:{
+ "cache-control": "max-age=30",
+ }}));
+ });
+
+ it('requestMinFresh', function() {
+ const cache = new CachePolicy({headers:{}}, {headers:{
+ "cache-control": "max-age=60",
+ }}, {shared:false});
+
+ assert(!cache.stale());
+
+ assert(!cache.satisfiesWithoutRevalidation({headers:{
+ "cache-control": "min-fresh=120",
+ }}));
+
+ assert(cache.satisfiesWithoutRevalidation({headers:{
+ "cache-control": "min-fresh=10",
+ }}));
+ });
+
+ it('requestMaxStale', function() {
+ const cache = new CachePolicy({headers:{}}, {headers:{
+ "cache-control": "max-age=120",
+ "date": formatDate(-4, 60),
+ }}, {shared:false});
+
+ assert(cache.stale());
+
+ assert(cache.satisfiesWithoutRevalidation({headers:{
+ "cache-control": "max-stale=180",
+ }}));
+
+ assert(cache.satisfiesWithoutRevalidation({headers:{
+ "cache-control": "max-stale",
+ }}));
+
+ assert(!cache.satisfiesWithoutRevalidation({headers:{
+ "cache-control": "max-stale=10",
+ }}));
+ });
+
+ it('requestMaxStaleNotHonoredWithMustRevalidate', function() {
+ const cache = new CachePolicy({headers:{}}, {headers:{
+ "cache-control": "max-age=120, must-revalidate",
+ "date": formatDate(-4, 60),
+ }}, {shared:false});
+
+ assert(cache.stale());
+
+ assert(!cache.satisfiesWithoutRevalidation({headers:{
+ "cache-control": "max-stale=180",
+ }}));
+
+ assert(!cache.satisfiesWithoutRevalidation({headers:{
+ "cache-control": "max-stale",
+ }}));
+ });
+
+ it('getHeadersDeletesCached100LevelWarnings', function() {
+ const cache = new CachePolicy({headers:{}}, {headers:{
+ "warning": "199 test danger, 200 ok ok",
+ }});
+
+ assert.equal("200 ok ok", cache.responseHeaders().warning);
+ });
+
+ it('doNotCachePartialResponse', function() {
+ const cache = new CachePolicy({headers:{}}, {
+ status: 206,
+ headers:{
+ "content-range": "bytes 100-100/200",
+ "cache-control": "max-age=60",
+ }});
+ assert(!cache.storable());
+ });
+
+ function formatDate(delta, unit) {
+ return new Date(Date.now() + delta*unit*1000).toUTCString();
+ }
+});
diff --git a/deps/npm/node_modules/npm-profile/node_modules/make-fetch-happen/node_modules/http-cache-semantics/test/requesttest.js b/deps/npm/node_modules/npm-profile/node_modules/make-fetch-happen/node_modules/http-cache-semantics/test/requesttest.js
new file mode 100644
index 0000000000..f668556ff8
--- /dev/null
+++ b/deps/npm/node_modules/npm-profile/node_modules/make-fetch-happen/node_modules/http-cache-semantics/test/requesttest.js
@@ -0,0 +1,61 @@
+'use strict';
+
+const assert = require('assert');
+const CachePolicy = require('..');
+
+const publicCacheableResponse = {headers:{'cache-control': 'public, max-age=222'}};
+const cacheableResponse = {headers:{'cache-control': 'max-age=111'}};
+
+describe('Request properties', function() {
+ it('No store kills cache', function() {
+ const cache = new CachePolicy({method:'GET',headers:{'cache-control':'no-store'}}, publicCacheableResponse);
+ assert(cache.stale());
+ assert(!cache.storable());
+ });
+
+ it('POST not cacheable by default', function() {
+ const cache = new CachePolicy({method:'POST',headers:{}}, {headers:{'cache-control': 'public'}});
+ assert(cache.stale());
+ assert(!cache.storable());
+ });
+
+ it('POST cacheable explicitly', function() {
+ const cache = new CachePolicy({method:'POST',headers:{}}, publicCacheableResponse);
+ assert(!cache.stale());
+ assert(cache.storable());
+ });
+
+ it('Public cacheable auth is OK', function() {
+ const cache = new CachePolicy({method:'GET',headers:{'authorization': 'test'}}, publicCacheableResponse);
+ assert(!cache.stale());
+ assert(cache.storable());
+ });
+
+ it('Proxy cacheable auth is OK', function() {
+ const cache = new CachePolicy({method:'GET',headers:{'authorization': 'test'}}, {headers:{'cache-control':'max-age=0,s-maxage=12'}});
+ assert(!cache.stale());
+ assert(cache.storable());
+
+ const cache2 = CachePolicy.fromObject(JSON.parse(JSON.stringify(cache.toObject())));
+ assert(cache2 instanceof CachePolicy);
+ assert(!cache2.stale());
+ assert(cache2.storable());
+ });
+
+ it('Private auth is OK', function() {
+ const cache = new CachePolicy({method:'GET',headers:{'authorization': 'test'}}, cacheableResponse, {shared:false});
+ assert(!cache.stale());
+ assert(cache.storable());
+ });
+
+ it('Revalidated auth is OK', function() {
+ const cache = new CachePolicy({headers:{'authorization': 'test'}}, {headers:{'cache-control':'max-age=88,must-revalidate'}});
+ assert(cache.storable());
+ });
+
+ it('Auth prevents caching by default', function() {
+ const cache = new CachePolicy({method:'GET',headers:{'authorization': 'test'}}, cacheableResponse);
+ assert(cache.stale());
+ assert(!cache.storable());
+ });
+});
diff --git a/deps/npm/node_modules/npm-profile/node_modules/make-fetch-happen/node_modules/http-cache-semantics/test/responsetest.js b/deps/npm/node_modules/npm-profile/node_modules/make-fetch-happen/node_modules/http-cache-semantics/test/responsetest.js
new file mode 100644
index 0000000000..763910b82c
--- /dev/null
+++ b/deps/npm/node_modules/npm-profile/node_modules/make-fetch-happen/node_modules/http-cache-semantics/test/responsetest.js
@@ -0,0 +1,385 @@
+'use strict';
+
+const assert = require('assert');
+const CachePolicy = require('..');
+
+const req = {method:'GET', headers:{}};
+
+describe('Response headers', function() {
+ it('simple miss', function() {
+ const cache = new CachePolicy(req, {headers:{}});
+ assert(cache.stale());
+ });
+
+ it('simple hit', function() {
+ const cache = new CachePolicy(req, {headers:{'cache-control': 'public, max-age=999999'}});
+ assert(!cache.stale());
+ assert.equal(cache.maxAge(), 999999);
+ });
+
+ it('weird syntax', function() {
+ const cache = new CachePolicy(req, {headers:{'cache-control': ',,,,max-age = 456 ,'}});
+ assert(!cache.stale());
+ assert.equal(cache.maxAge(), 456);
+
+ const cache2 = CachePolicy.fromObject(JSON.parse(JSON.stringify(cache.toObject())));
+ assert(cache2 instanceof CachePolicy);
+ assert(!cache2.stale());
+ assert.equal(cache2.maxAge(), 456);
+ });
+
+ it('quoted syntax', function() {
+ const cache = new CachePolicy(req, {headers:{'cache-control': ' max-age = "678" '}});
+ assert(!cache.stale());
+ assert.equal(cache.maxAge(), 678);
+ });
+
+ it('IIS', function() {
+ const cache = new CachePolicy(req, {headers:{'cache-control': 'private, public, max-age=259200'}}, {shared:false});
+ assert(!cache.stale());
+ assert.equal(cache.maxAge(), 259200);
+ });
+
+ it('pre-check tolerated', function() {
+ const cc = 'pre-check=0, post-check=0, no-store, no-cache, max-age=100';
+ const cache = new CachePolicy(req, {headers:{'cache-control': cc}});
+ assert(cache.stale());
+ assert(!cache.storable());
+ assert.equal(cache.maxAge(), 0);
+ assert.equal(cache.responseHeaders()['cache-control'], cc);
+ });
+
+ it('pre-check poison', function() {
+ const origCC = 'pre-check=0, post-check=0, no-cache, no-store, max-age=100, custom, foo=bar';
+ const res = {headers:{'cache-control': origCC, pragma: 'no-cache'}};
+ const cache = new CachePolicy(req, res, {ignoreCargoCult:true});
+ assert(!cache.stale());
+ assert(cache.storable());
+ assert.equal(cache.maxAge(), 100);
+
+ const cc = cache.responseHeaders()['cache-control'];
+ assert(!/pre-check/.test(cc), cc);
+ assert(!/post-check/.test(cc), cc);
+ assert(!/no-store/.test(cc), cc);
+
+ assert(/max-age=100/.test(cc));
+ assert(/custom(,|$)/.test(cc));
+ assert(/foo=bar/.test(cc));
+
+ assert.equal(res.headers['cache-control'], origCC);
+ assert(res.headers['pragma']);
+ assert(!cache.responseHeaders()['pragma']);
+ });
+
+ it('pre-check poison undefined header', function() {
+ const origCC = 'pre-check=0, post-check=0, no-cache, no-store';
+ const res = {headers:{'cache-control': origCC, expires: 'yesterday!'}};
+ const cache = new CachePolicy(req, res, {ignoreCargoCult:true});
+ assert(cache.stale());
+ assert(cache.storable());
+ assert.equal(cache.maxAge(), 0);
+
+ const cc = cache.responseHeaders()['cache-control'];
+ assert(!cc);
+
+ assert(res.headers['expires']);
+ assert(!cache.responseHeaders()['expires']);
+ });
+
+ it('cache with expires', function() {
+ const cache = new CachePolicy(req, {headers:{
+ 'date': new Date().toGMTString(),
+ 'expires': new Date(Date.now() + 2000).toGMTString(),
+ }});
+ assert(!cache.stale());
+ assert.equal(2, cache.maxAge());
+ });
+
+ it('cache expires no date', function() {
+ const cache = new CachePolicy(req, {headers:{
+ 'cache-control': 'public',
+ 'expires': new Date(Date.now()+3600*1000).toGMTString(),
+ }});
+ assert(!cache.stale());
+ assert(cache.maxAge() > 3595);
+ assert(cache.maxAge() < 3605);
+ });
+
+ it('Ages', function() {
+ let now = 1000;
+ class TimeTravellingPolicy extends CachePolicy {
+ now() {
+ return now;
+ }
+ }
+ const cache = new TimeTravellingPolicy(req, {headers:{
+ 'cache-control':'max-age=100',
+ 'age': '50',
+ }});
+ assert(cache.storable());
+
+ assert.equal(50*1000, cache.timeToLive());
+ assert(!cache.stale());
+ now += 48*1000;
+ assert.equal(2*1000, cache.timeToLive());
+ assert(!cache.stale());
+ now += 5*1000;
+ assert(cache.stale());
+ assert.equal(0, cache.timeToLive());
+ });
+
+ it('Age can make stale', function() {
+ const cache = new CachePolicy(req, {headers:{
+ 'cache-control':'max-age=100',
+ 'age': '101',
+ }});
+ assert(cache.stale());
+ assert(cache.storable());
+ });
+
+ it('Age not always stale', function() {
+ const cache = new CachePolicy(req, {headers:{
+ 'cache-control':'max-age=20',
+ 'age': '15',
+ }});
+ assert(!cache.stale());
+ assert(cache.storable());
+ });
+
+ it('Bogus age ignored', function() {
+ const cache = new CachePolicy(req, {headers:{
+ 'cache-control':'max-age=20',
+ 'age': 'golden',
+ }});
+ assert(!cache.stale());
+ assert(cache.storable());
+ });
+
+ it('cache old files', function() {
+ const cache = new CachePolicy(req, {headers:{
+ 'date': new Date().toGMTString(),
+ 'last-modified': 'Mon, 07 Mar 2016 11:52:56 GMT',
+ }});
+ assert(!cache.stale());
+ assert(cache.maxAge() > 100);
+ });
+
+ it('immutable simple hit', function() {
+ const cache = new CachePolicy(req, {headers:{'cache-control': 'immutable, max-age=999999'}});
+ assert(!cache.stale());
+ assert.equal(cache.maxAge(), 999999);
+ });
+
+ it('immutable can expire', function() {
+ const cache = new CachePolicy(req, {headers:{'cache-control': 'immutable, max-age=0'}});
+ assert(cache.stale());
+ assert.equal(cache.maxAge(), 0);
+ });
+
+ it('cache immutable files', function() {
+ const cache = new CachePolicy(req, {headers:{
+ 'date': new Date().toGMTString(),
+ 'cache-control':'immutable',
+ 'last-modified': new Date().toGMTString(),
+ }});
+ assert(!cache.stale());
+ assert(cache.maxAge() > 100);
+ });
+
+ it('immutable can be off', function() {
+ const cache = new CachePolicy(req, {headers:{
+ 'date': new Date().toGMTString(),
+ 'cache-control':'immutable',
+ 'last-modified': new Date().toGMTString(),
+ }}, {immutableMinTimeToLive: 0});
+ assert(cache.stale());
+ assert.equal(cache.maxAge(), 0);
+ });
+
+ it('pragma: no-cache', function() {
+ const cache = new CachePolicy(req, {headers:{
+ 'pragma': 'no-cache',
+ 'last-modified': 'Mon, 07 Mar 2016 11:52:56 GMT',
+ }});
+ assert(cache.stale());
+ });
+
+ it('no-store', function() {
+ const cache = new CachePolicy(req, {headers:{
+ 'cache-control': 'no-store, public, max-age=1',
+ }});
+ assert(cache.stale());
+ assert.equal(0, cache.maxAge());
+ });
+
+ it('observe private cache', function() {
+ const privateHeader = {
+ 'cache-control': 'private, max-age=1234',
+ };
+ const proxyCache = new CachePolicy(req, {headers:privateHeader});
+ assert(proxyCache.stale());
+ assert.equal(0, proxyCache.maxAge());
+
+ const uaCache = new CachePolicy(req, {headers:privateHeader}, {shared:false});
+ assert(!uaCache.stale());
+ assert.equal(1234, uaCache.maxAge());
+ });
+
+ it('don\'t share cookies', function() {
+ const cookieHeader = {
+ 'set-cookie': 'foo=bar',
+ 'cache-control': 'max-age=99',
+ };
+ const proxyCache = new CachePolicy(req, {headers:cookieHeader}, {shared:true});
+ assert(proxyCache.stale());
+ assert.equal(0, proxyCache.maxAge());
+
+ const uaCache = new CachePolicy(req, {headers:cookieHeader}, {shared:false});
+ assert(!uaCache.stale());
+ assert.equal(99, uaCache.maxAge());
+ });
+
+ it('do share cookies if immutable', function() {
+ const cookieHeader = {
+ 'set-cookie': 'foo=bar',
+ 'cache-control': 'immutable, max-age=99',
+ };
+ const proxyCache = new CachePolicy(req, {headers:cookieHeader}, {shared:true});
+ assert(!proxyCache.stale());
+ assert.equal(99, proxyCache.maxAge());
+ });
+
+ it('cache explicitly public cookie', function() {
+ const cookieHeader = {
+ 'set-cookie': 'foo=bar',
+ 'cache-control': 'max-age=5, public',
+ };
+ const proxyCache = new CachePolicy(req, {headers:cookieHeader}, {shared:true});
+ assert(!proxyCache.stale());
+ assert.equal(5, proxyCache.maxAge());
+ });
+
+ it('miss max-age=0', function() {
+ const cache = new CachePolicy(req, {headers:{
+ 'cache-control': 'public, max-age=0',
+ }});
+ assert(cache.stale());
+ assert.equal(0, cache.maxAge());
+ });
+
+ it('uncacheable 503', function() {
+ const cache = new CachePolicy(req, {
+ status: 503,
+ headers:{
+ 'cache-control': 'public, max-age=1000',
+ }});
+ assert(cache.stale());
+ assert.equal(0, cache.maxAge());
+ });
+
+ it('cacheable 301', function() {
+ const cache = new CachePolicy(req, {
+ status: 301,
+ headers:{
+ 'last-modified': 'Mon, 07 Mar 2016 11:52:56 GMT',
+ }});
+ assert(!cache.stale());
+ });
+
+ it('uncacheable 303', function() {
+ const cache = new CachePolicy(req, {
+ status: 303,
+ headers:{
+ 'last-modified': 'Mon, 07 Mar 2016 11:52:56 GMT',
+ }});
+ assert(cache.stale());
+ assert.equal(0, cache.maxAge());
+ });
+
+ it('cacheable 303', function() {
+ const cache = new CachePolicy(req, {
+ status: 303,
+ headers:{
+ 'cache-control': 'max-age=1000',
+ }});
+ assert(!cache.stale());
+ });
+
+ it('uncacheable 412', function() {
+ const cache = new CachePolicy(req, {
+ status: 412,
+ headers:{
+ 'cache-control': 'public, max-age=1000',
+ }});
+ assert(cache.stale());
+ assert.equal(0, cache.maxAge());
+ });
+
+ it('expired expires cached with max-age', function() {
+ const cache = new CachePolicy(req, {headers:{
+ 'cache-control': 'public, max-age=9999',
+ 'expires': 'Sat, 07 May 2016 15:35:18 GMT',
+ }});
+ assert(!cache.stale());
+ assert.equal(9999, cache.maxAge());
+ });
+
+ it('expired expires cached with s-maxage', function() {
+ const sMaxAgeHeaders = {
+ 'cache-control': 'public, s-maxage=9999',
+ 'expires': 'Sat, 07 May 2016 15:35:18 GMT',
+ };
+ const proxyCache = new CachePolicy(req, {headers:sMaxAgeHeaders});
+ assert(!proxyCache.stale());
+ assert.equal(9999, proxyCache.maxAge());
+
+ const uaCache = new CachePolicy(req, {headers:sMaxAgeHeaders}, {shared:false});
+ assert(uaCache.stale());
+ assert.equal(0, uaCache.maxAge());
+ });
+
+ it('max-age wins over future expires', function() {
+ const cache = new CachePolicy(req, {headers:{
+ 'cache-control': 'public, max-age=333',
+ 'expires': new Date(Date.now()+3600*1000).toGMTString(),
+ }});
+ assert(!cache.stale());
+ assert.equal(333, cache.maxAge());
+ });
+
+ it('remove hop headers', function() {
+ let now = 10000;
+ class TimeTravellingPolicy extends CachePolicy {
+ now() {
+ return now;
+ }
+ }
+
+ const res = {headers:{
+ 'te': 'deflate',
+ 'date': 'now',
+ 'custom': 'header',
+ 'oompa': 'lumpa',
+ 'connection': 'close, oompa, header',
+ 'age': '10',
+ 'cache-control': 'public, max-age=333',
+ }};
+ const cache = new TimeTravellingPolicy(req, res);
+
+ now += 1005;
+ const h = cache.responseHeaders();
+ assert(!h.connection);
+ assert(!h.te);
+ assert(!h.oompa);
+ assert.equal(h['cache-control'], 'public, max-age=333');
+ assert.equal(h.date, 'now', "date must stay the same for expires, age, etc");
+ assert.equal(h.custom, 'header');
+ assert.equal(h.age, '11');
+ assert.equal(res.headers.age, '10');
+
+ const cache2 = TimeTravellingPolicy.fromObject(JSON.parse(JSON.stringify(cache.toObject())));
+ assert(cache2 instanceof TimeTravellingPolicy);
+ const h2 = cache2.responseHeaders();
+ assert.deepEqual(h, h2);
+ });
+});
diff --git a/deps/npm/node_modules/npm-profile/node_modules/make-fetch-happen/node_modules/http-cache-semantics/test/revalidatetest.js b/deps/npm/node_modules/npm-profile/node_modules/make-fetch-happen/node_modules/http-cache-semantics/test/revalidatetest.js
new file mode 100644
index 0000000000..9dc737718d
--- /dev/null
+++ b/deps/npm/node_modules/npm-profile/node_modules/make-fetch-happen/node_modules/http-cache-semantics/test/revalidatetest.js
@@ -0,0 +1,181 @@
+'use strict';
+
+const assert = require('assert');
+const CachePolicy = require('..');
+
+const simpleRequest = {
+ method:'GET',
+ headers:{
+ host:'www.w3c.org',
+ connection: 'close',
+ 'x-custom': 'yes',
+ },
+ url:'/Protocols/rfc2616/rfc2616-sec14.html',
+};
+function simpleRequestBut(overrides) {
+ return Object.assign({}, simpleRequest, overrides);
+}
+
+const cacheableResponse = {headers:{'cache-control':'max-age=111'}};
+const etaggedResponse = {headers:Object.assign({'etag':'"123456789"'},cacheableResponse.headers)};
+const lastModifiedResponse = {headers:Object.assign({'last-modified':'Tue, 15 Nov 1994 12:45:26 GMT'},cacheableResponse.headers)};
+const multiValidatorResponse = {headers:Object.assign({},etaggedResponse.headers,lastModifiedResponse.headers)};
+const alwaysVariableResponse = {headers:Object.assign({'vary':'*'},cacheableResponse.headers)};
+
+function assertHeadersPassed(headers) {
+ assert.strictEqual(headers.connection, undefined);
+ assert.strictEqual(headers['x-custom'], 'yes');
+}
+function assertNoValidators(headers) {
+ assert.strictEqual(headers['if-none-match'], undefined);
+ assert.strictEqual(headers['if-modified-since'], undefined);
+}
+
+describe('Can be revalidated?', function() {
+ it('ok if method changes to HEAD', function(){
+ const cache = new CachePolicy(simpleRequest,etaggedResponse);
+ const headers = cache.revalidationHeaders(simpleRequestBut({method:'HEAD'}));
+ assertHeadersPassed(headers);
+ assert.equal(headers['if-none-match'], '"123456789"');
+ });
+
+ it('not if method mismatch (other than HEAD)', function(){
+ const cache = new CachePolicy(simpleRequest,etaggedResponse);
+ const incomingRequest = simpleRequestBut({method:'POST'});
+ const headers = cache.revalidationHeaders(incomingRequest);
+ assertHeadersPassed(headers);
+ assertNoValidators(headers);
+ });
+
+ it('not if url mismatch', function(){
+ const cache = new CachePolicy(simpleRequest,etaggedResponse);
+ const incomingRequest = simpleRequestBut({url:'/yomomma'});
+ const headers = cache.revalidationHeaders(incomingRequest);
+ assertHeadersPassed(headers);
+ assertNoValidators(headers);
+ });
+
+ it('not if host mismatch', function(){
+ const cache = new CachePolicy(simpleRequest,etaggedResponse);
+ const incomingRequest = simpleRequestBut({headers:{host:'www.w4c.org'}});
+ const headers = cache.revalidationHeaders(incomingRequest);
+ assertNoValidators(headers);
+ assert.strictEqual(headers['x-custom'], undefined);
+ });
+
+ it('not if vary fields prevent', function(){
+ const cache = new CachePolicy(simpleRequest,alwaysVariableResponse);
+ const headers = cache.revalidationHeaders(simpleRequest);
+ assertHeadersPassed(headers);
+ assertNoValidators(headers);
+ });
+
+ it('when entity tag validator is present', function() {
+ const cache = new CachePolicy(simpleRequest, etaggedResponse);
+ const headers = cache.revalidationHeaders(simpleRequest);
+ assertHeadersPassed(headers);
+ assert.equal(headers['if-none-match'], '"123456789"');
+ });
+
+ it('skips weak validtors on post', function() {
+ const postReq = simpleRequestBut({method:'POST', headers:{'if-none-match': 'W/"weak", "strong", W/"weak2"'}});
+ const cache = new CachePolicy(postReq, multiValidatorResponse);
+ const headers = cache.revalidationHeaders(postReq);
+ assert.equal(headers['if-none-match'], '"strong", "123456789"');
+ assert.strictEqual(undefined, headers['if-modified-since']);
+ });
+
+ it('skips weak validtors on post 2', function() {
+ const postReq = simpleRequestBut({method:'POST', headers:{'if-none-match': 'W/"weak"'}});
+ const cache = new CachePolicy(postReq, lastModifiedResponse);
+ const headers = cache.revalidationHeaders(postReq);
+ assert.strictEqual(undefined, headers['if-none-match']);
+ assert.strictEqual(undefined, headers['if-modified-since']);
+ });
+
+ it('merges validtors', function() {
+ const postReq = simpleRequestBut({headers:{'if-none-match': 'W/"weak", "strong", W/"weak2"'}});
+ const cache = new CachePolicy(postReq, multiValidatorResponse);
+ const headers = cache.revalidationHeaders(postReq);
+ assert.equal(headers['if-none-match'], 'W/"weak", "strong", W/"weak2", "123456789"');
+ assert.equal('Tue, 15 Nov 1994 12:45:26 GMT', headers['if-modified-since']);
+ });
+
+ it('when last-modified validator is present', function() {
+ const cache = new CachePolicy(simpleRequest, lastModifiedResponse);
+ const headers = cache.revalidationHeaders(simpleRequest);
+ assertHeadersPassed(headers);
+ assert.equal(headers['if-modified-since'], 'Tue, 15 Nov 1994 12:45:26 GMT');
+ assert(!/113/.test(headers.warning));
+ });
+
+ it('not without validators', function() {
+ const cache = new CachePolicy(simpleRequest, cacheableResponse);
+ const headers = cache.revalidationHeaders(simpleRequest);
+ assertHeadersPassed(headers);
+ assertNoValidators(headers);
+ assert(!/113/.test(headers.warning));
+ })
+
+ it('113 added', function() {
+ const veryOldResponse = {
+ headers: {
+ age: 3600*72,
+ 'last-modified': 'Tue, 15 Nov 1994 12:45:26 GMT',
+ },
+ };
+
+ const cache = new CachePolicy(simpleRequest, veryOldResponse);
+ const headers = cache.responseHeaders(simpleRequest);
+ assert(/113/.test(headers.warning));
+ })
+
+});
+
+describe('Validation request', function(){
+ it('removes warnings', function() {
+ const cache = new CachePolicy({headers:{}}, {headers:{
+ "warning": "199 test danger",
+ }});
+
+ assert.strictEqual(undefined, cache.responseHeaders().warning);
+ });
+
+ it('must contain any etag', function(){
+ const cache = new CachePolicy(simpleRequest,multiValidatorResponse);
+ const expected = multiValidatorResponse.headers.etag;
+ const actual = cache.revalidationHeaders(simpleRequest)['if-none-match'];
+ assert.equal(actual,expected);
+ });
+
+ it('merges etags', function(){
+ const cache = new CachePolicy(simpleRequest, etaggedResponse);
+ const expected = `"foo", "bar", ${etaggedResponse.headers.etag}`;
+ const headers = cache.revalidationHeaders(simpleRequestBut({headers:{
+ host:'www.w3c.org',
+ 'if-none-match': '"foo", "bar"',
+ }}));
+ assert.equal(headers['if-none-match'],expected);
+ });
+
+ it('should send the Last-Modified value', function(){
+ const cache = new CachePolicy(simpleRequest,multiValidatorResponse);
+ const expected = multiValidatorResponse.headers['last-modified'];
+ const actual = cache.revalidationHeaders(simpleRequest)['if-modified-since'];
+ assert.equal(actual,expected);
+ });
+
+ it('should not send the Last-Modified value for POST', function(){
+ const postReq = {method:'POST', headers:{'if-modified-since':'yesterday'}};
+ const cache = new CachePolicy(postReq, lastModifiedResponse);
+ const actual = cache.revalidationHeaders(postReq)['if-modified-since'];
+ assert.equal(actual, undefined);
+ });
+
+ it('should not send the Last-Modified value for range requests', function(){
+ const rangeReq = {method:'GET', headers:{'accept-ranges':'1-3', 'if-modified-since':'yesterday'}};
+ const cache = new CachePolicy(rangeReq, lastModifiedResponse);
+ const actual = cache.revalidationHeaders(rangeReq)['if-modified-since'];
+ assert.equal(actual, undefined);
+ });
+});
diff --git a/deps/npm/node_modules/npm-profile/node_modules/make-fetch-happen/node_modules/http-cache-semantics/test/satisfytest.js b/deps/npm/node_modules/npm-profile/node_modules/make-fetch-happen/node_modules/http-cache-semantics/test/satisfytest.js
new file mode 100644
index 0000000000..3131ee73d0
--- /dev/null
+++ b/deps/npm/node_modules/npm-profile/node_modules/make-fetch-happen/node_modules/http-cache-semantics/test/satisfytest.js
@@ -0,0 +1,64 @@
+'use strict';
+
+const assert = require('assert');
+const CachePolicy = require('..');
+
+describe('Satisfies', function() {
+ it('when URLs match', function() {
+ const policy = new CachePolicy({url:'/',headers:{}}, {status:200,headers:{'cache-control':'max-age=2'}});
+ assert(policy.satisfiesWithoutRevalidation({url:'/',headers:{}}));
+ });
+
+ it('when expires is present', function() {
+ const policy = new CachePolicy({headers:{}}, {status:302,headers:{'expires':new Date(Date.now()+2000).toGMTString()}});
+ assert(policy.satisfiesWithoutRevalidation({headers:{}}));
+ });
+
+ it('not when URLs mismatch', function() {
+ const policy = new CachePolicy({url:'/foo',headers:{}}, {status:200,headers:{'cache-control':'max-age=2'}});
+ assert(!policy.satisfiesWithoutRevalidation({url:'/foo?bar',headers:{}}));
+ });
+
+ it('when methods match', function() {
+ const policy = new CachePolicy({method:'GET',headers:{}}, {status:200,headers:{'cache-control':'max-age=2'}});
+ assert(policy.satisfiesWithoutRevalidation({method:'GET',headers:{}}));
+ });
+
+ it('not when hosts mismatch', function() {
+ const policy = new CachePolicy({headers:{'host':'foo'}}, {status:200,headers:{'cache-control':'max-age=2'}});
+ assert(policy.satisfiesWithoutRevalidation({headers:{'host':'foo'}}));
+ assert(!policy.satisfiesWithoutRevalidation({headers:{'host':'foofoo'}}));
+ });
+
+ it('when methods match HEAD', function() {
+ const policy = new CachePolicy({method:'HEAD',headers:{}}, {status:200,headers:{'cache-control':'max-age=2'}});
+ assert(policy.satisfiesWithoutRevalidation({method:'HEAD',headers:{}}));
+ });
+
+ it('not when methods mismatch', function() {
+ const policy = new CachePolicy({method:'POST',headers:{}}, {status:200,headers:{'cache-control':'max-age=2'}});
+ assert(!policy.satisfiesWithoutRevalidation({method:'GET',headers:{}}));
+ });
+
+ it('not when methods mismatch HEAD', function() {
+ const policy = new CachePolicy({method:'HEAD',headers:{}}, {status:200,headers:{'cache-control':'max-age=2'}});
+ assert(!policy.satisfiesWithoutRevalidation({method:'GET',headers:{}}));
+ });
+
+ it('not when proxy revalidating', function() {
+ const policy = new CachePolicy({headers:{}}, {status:200,headers:{'cache-control':'max-age=2, proxy-revalidate '}});
+ assert(!policy.satisfiesWithoutRevalidation({headers:{}}));
+ });
+
+ it('when not a proxy revalidating', function() {
+ const policy = new CachePolicy({headers:{}}, {status:200,headers:{'cache-control':'max-age=2, proxy-revalidate '}}, {shared:false});
+ assert(policy.satisfiesWithoutRevalidation({headers:{}}));
+ });
+
+ it('not when no-cache requesting', function() {
+ const policy = new CachePolicy({headers:{}}, {headers:{'cache-control':'max-age=2'}});
+ assert(policy.satisfiesWithoutRevalidation({headers:{'cache-control':'fine'}}));
+ assert(!policy.satisfiesWithoutRevalidation({headers:{'cache-control':'no-cache'}}));
+ assert(!policy.satisfiesWithoutRevalidation({headers:{'pragma':'no-cache'}}));
+ });
+});
diff --git a/deps/npm/node_modules/npm-profile/node_modules/make-fetch-happen/node_modules/http-cache-semantics/test/updatetest.js b/deps/npm/node_modules/npm-profile/node_modules/make-fetch-happen/node_modules/http-cache-semantics/test/updatetest.js
new file mode 100644
index 0000000000..6d498c86e3
--- /dev/null
+++ b/deps/npm/node_modules/npm-profile/node_modules/make-fetch-happen/node_modules/http-cache-semantics/test/updatetest.js
@@ -0,0 +1,98 @@
+'use strict';
+
+const assert = require('assert');
+const CachePolicy = require('..');
+
+const simpleRequest = {
+ method:'GET',
+ headers:{
+ host:'www.w3c.org',
+ connection: 'close',
+ },
+ url:'/Protocols/rfc2616/rfc2616-sec14.html',
+};
+function withHeaders(request, headers) {
+ return Object.assign({}, request, {
+ headers: Object.assign({}, request.headers, headers),
+ });
+}
+
+const cacheableResponse = {headers:{'cache-control':'max-age=111'}};
+const etaggedResponse = {headers:Object.assign({'etag':'"123456789"'},cacheableResponse.headers)};
+const weakTaggedResponse = {headers:Object.assign({'etag':'W/"123456789"'},cacheableResponse.headers)};
+const lastModifiedResponse = {headers:Object.assign({'last-modified':'Tue, 15 Nov 1994 12:45:26 GMT'},cacheableResponse.headers)};
+const multiValidatorResponse = {headers:Object.assign({},etaggedResponse.headers,lastModifiedResponse.headers)};
+
+function notModifiedResponseHeaders(firstRequest, firstResponse, secondRequest, secondResponse) {
+ const cache = new CachePolicy(firstRequest, firstResponse);
+ const headers = cache.revalidationHeaders(secondRequest);
+ const {policy:newCache, modified} = cache.revalidatedPolicy({headers}, secondResponse);
+ if (modified) {
+ return false;
+ }
+ return newCache.responseHeaders();
+}
+
+function assertUpdates(firstRequest, firstResponse, secondRequest, secondResponse) {
+ const headers = notModifiedResponseHeaders(firstRequest, withHeaders(firstResponse, {'foo': 'original', 'x-other':'original'}),
+ secondRequest, withHeaders(secondResponse, {'foo': 'updated', 'x-ignore-new':'ignoreme'}));
+ assert(headers);
+ assert.equal(headers['foo'], 'updated');
+ assert.equal(headers['x-other'], 'original');
+ assert.strictEqual(headers['x-ignore-new'], undefined);
+ assert.strictEqual(headers['etag'], secondResponse.headers.etag);
+}
+
+describe('Update revalidated', function() {
+ it('Matching etags are updated', function(){
+ assertUpdates(simpleRequest, etaggedResponse, simpleRequest, etaggedResponse);
+ });
+
+ it('Matching weak etags are updated', function(){
+ assertUpdates(simpleRequest, weakTaggedResponse, simpleRequest, weakTaggedResponse);
+ });
+
+ it('Matching lastmod are updated', function(){
+ assertUpdates(simpleRequest, lastModifiedResponse, simpleRequest, lastModifiedResponse);
+ });
+
+ it('Both matching are updated', function(){
+ assertUpdates(simpleRequest, multiValidatorResponse, simpleRequest, multiValidatorResponse);
+ });
+
+ it('Checks status', function(){
+ const response304 = Object.assign({}, multiValidatorResponse, {status:304});
+ const response200 = Object.assign({}, multiValidatorResponse, {status:200});
+ assertUpdates(simpleRequest, multiValidatorResponse, simpleRequest, response304);
+ assert(!notModifiedResponseHeaders(simpleRequest, multiValidatorResponse, simpleRequest, response200));
+ });
+
+ it('Last-mod ignored if etag is wrong', function(){
+ assert(!notModifiedResponseHeaders(simpleRequest, multiValidatorResponse, simpleRequest, withHeaders(multiValidatorResponse, {'etag':'bad'})));
+ assert(!notModifiedResponseHeaders(simpleRequest, multiValidatorResponse, simpleRequest, withHeaders(multiValidatorResponse, {'etag':'W/bad'})));
+ });
+
+ it('Ignored if validator is missing', function(){
+ assert(!notModifiedResponseHeaders(simpleRequest, etaggedResponse, simpleRequest, cacheableResponse));
+ assert(!notModifiedResponseHeaders(simpleRequest, weakTaggedResponse, simpleRequest, cacheableResponse));
+ assert(!notModifiedResponseHeaders(simpleRequest, lastModifiedResponse, simpleRequest, cacheableResponse));
+ });
+
+ it('Skips update of content-length', function(){
+ const etaggedResponseWithLenght1 = withHeaders(etaggedResponse, {'content-length':1});
+ const etaggedResponseWithLenght2 = withHeaders(etaggedResponse, {'content-length':2});
+ const headers = notModifiedResponseHeaders(simpleRequest, etaggedResponseWithLenght1, simpleRequest, etaggedResponseWithLenght2);
+ assert.equal(1, headers['content-length']);
+ });
+
+ it('Ignored if validator is different', function(){
+ assert(!notModifiedResponseHeaders(simpleRequest, lastModifiedResponse, simpleRequest, etaggedResponse));
+ assert(!notModifiedResponseHeaders(simpleRequest, lastModifiedResponse, simpleRequest, weakTaggedResponse));
+ assert(!notModifiedResponseHeaders(simpleRequest, etaggedResponse, simpleRequest, lastModifiedResponse));
+ });
+
+ it('Ignored if validator doesn\'t match', function(){
+ assert(!notModifiedResponseHeaders(simpleRequest, etaggedResponse, simpleRequest, withHeaders(etaggedResponse, {etag:'"other"'})), "bad etag");
+ assert(!notModifiedResponseHeaders(simpleRequest, lastModifiedResponse, simpleRequest, withHeaders(lastModifiedResponse, {'last-modified':'dunno'})), "bad lastmod");
+ });
+});
diff --git a/deps/npm/node_modules/npm-profile/node_modules/make-fetch-happen/node_modules/http-cache-semantics/test/varytest.js b/deps/npm/node_modules/npm-profile/node_modules/make-fetch-happen/node_modules/http-cache-semantics/test/varytest.js
new file mode 100644
index 0000000000..9d5cfb2325
--- /dev/null
+++ b/deps/npm/node_modules/npm-profile/node_modules/make-fetch-happen/node_modules/http-cache-semantics/test/varytest.js
@@ -0,0 +1,75 @@
+'use strict';
+
+const assert = require('assert');
+const CachePolicy = require('..');
+
+describe('Vary', function() {
+ it('Basic', function() {
+ const policy = new CachePolicy({headers:{'weather': 'nice'}}, {headers:{'cache-control':'max-age=5','vary':'weather'}});
+
+ assert(policy.satisfiesWithoutRevalidation({headers:{'weather': 'nice'}}));
+ assert(!policy.satisfiesWithoutRevalidation({headers:{'weather': 'bad'}}));
+ });
+
+ it("* doesn't match", function() {
+ const policy = new CachePolicy({headers:{'weather': 'ok'}}, {headers:{'cache-control':'max-age=5','vary':'*'}});
+
+ assert(!policy.satisfiesWithoutRevalidation({headers:{'weather': 'ok'}}));
+ });
+
+ it("* is stale", function() {
+ const policy1 = new CachePolicy({headers:{'weather': 'ok'}}, {headers:{'cache-control':'public,max-age=99', 'vary':'*'}});
+ const policy2 = new CachePolicy({headers:{'weather': 'ok'}}, {headers:{'cache-control':'public,max-age=99', 'vary':'weather'}});
+
+ assert(policy1.stale());
+ assert(!policy2.stale());
+ });
+
+ it('Values are case-sensitive', function() {
+ const policy = new CachePolicy({headers:{'weather': 'BAD'}}, {headers:{'cache-control':'max-age=5','vary':'Weather'}});
+
+ assert(policy.satisfiesWithoutRevalidation({headers:{'weather': 'BAD'}}));
+ assert(!policy.satisfiesWithoutRevalidation({headers:{'weather': 'bad'}}));
+ });
+
+ it('Irrelevant headers ignored', function() {
+ const policy = new CachePolicy({headers:{'weather': 'nice'}}, {headers:{'cache-control':'max-age=5','vary':'moon-phase'}});
+
+ assert(policy.satisfiesWithoutRevalidation({headers:{'weather': 'bad'}}));
+ assert(policy.satisfiesWithoutRevalidation({headers:{'sun': 'shining'}}));
+ assert(!policy.satisfiesWithoutRevalidation({headers:{'moon-phase': 'full'}}));
+ });
+
+ it('Absence is meaningful', function() {
+ const policy = new CachePolicy({headers:{'weather': 'nice'}}, {headers:{'cache-control':'max-age=5','vary':'moon-phase, weather'}});
+
+ assert(policy.satisfiesWithoutRevalidation({headers:{'weather': 'nice'}}));
+ assert(!policy.satisfiesWithoutRevalidation({headers:{'weather': 'nice', 'moon-phase': ''}}));
+ assert(!policy.satisfiesWithoutRevalidation({headers:{}}));
+ });
+
+ it('All values must match', function() {
+ const policy = new CachePolicy({headers:{'sun': 'shining', 'weather': 'nice'}}, {headers:{'cache-control':'max-age=5','vary':'weather, sun'}});
+
+ assert(policy.satisfiesWithoutRevalidation({headers:{'sun': 'shining', 'weather': 'nice'}}));
+ assert(!policy.satisfiesWithoutRevalidation({headers:{'sun': 'shining', 'weather': 'bad'}}));
+ });
+
+ it('Whitespace is OK', function() {
+ const policy = new CachePolicy({headers:{'sun': 'shining', 'weather': 'nice'}}, {headers:{'cache-control':'max-age=5','vary':' weather , sun '}});
+
+ assert(policy.satisfiesWithoutRevalidation({headers:{'sun': 'shining', 'weather': 'nice'}}));
+ assert(!policy.satisfiesWithoutRevalidation({headers:{'weather': 'nice'}}));
+ assert(!policy.satisfiesWithoutRevalidation({headers:{'sun': 'shining'}}));
+ });
+
+ it('Order is irrelevant', function() {
+ const policy1 = new CachePolicy({headers:{'sun': 'shining', 'weather': 'nice'}}, {headers:{'cache-control':'max-age=5','vary':'weather, sun'}});
+ const policy2 = new CachePolicy({headers:{'sun': 'shining', 'weather': 'nice'}}, {headers:{'cache-control':'max-age=5','vary':'sun, weather'}});
+
+ assert(policy1.satisfiesWithoutRevalidation({headers:{'weather': 'nice', 'sun': 'shining'}}));
+ assert(policy1.satisfiesWithoutRevalidation({headers:{'sun': 'shining', 'weather': 'nice'}}));
+ assert(policy2.satisfiesWithoutRevalidation({headers:{'weather': 'nice', 'sun': 'shining'}}));
+ assert(policy2.satisfiesWithoutRevalidation({headers:{'sun': 'shining', 'weather': 'nice'}}));
+ });
+});