// META: title=Cache.add and Cache.addAll
// META: global=window,worker
// META: script=/common/get-host-info.sub.js
// META: script=./resources/test-helpers.js
// META: timeout=long

const { REMOTE_HOST } = get_host_info();

cache_test(function(cache, test) {
    return promise_rejects_js(
      test,
      TypeError,
      cache.add(),
      'Cache.add should throw a TypeError when no arguments are given.');
  }, 'Cache.add called with no arguments');

cache_test(function(cache) {
    return cache.add('./resources/simple.txt')
      .then(function(result) {
          assert_equals(result, undefined,
                        'Cache.add should resolve with undefined on success.');
          return cache.match('./resources/simple.txt');
        })
        .then(function(response) {
          assert_class_string(response, 'Response',
                              'Cache.add should put a resource in the cache.');
          return response.text();
        })
        .then(function(body) {
          assert_equals(body, 'a simple text file\n',
                        'Cache.add should retrieve the correct body.');
        });
  }, 'Cache.add called with relative URL specified as a string');

cache_test(function(cache, test) {
    return promise_rejects_js(
      test,
      TypeError,
      cache.add('javascript://this-is-not-http-mmkay'),
      'Cache.add should throw a TypeError for non-HTTP/HTTPS URLs.');
  }, 'Cache.add called with non-HTTP/HTTPS URL');

cache_test(function(cache) {
    var request = new Request('./resources/simple.txt');
    return cache.add(request)
      .then(function(result) {
          assert_equals(result, undefined,
                        'Cache.add should resolve with undefined on success.');
        });
  }, 'Cache.add called with Request object');

cache_test(function(cache, test) {
    var request = new Request('./resources/simple.txt',
                              {method: 'POST', body: 'This is a body.'});
    return promise_rejects_js(
      test,
      TypeError,
      cache.add(request),
      'Cache.add should throw a TypeError for non-GET requests.');
  }, 'Cache.add called with POST request');

cache_test(function(cache) {
    var request = new Request('./resources/simple.txt');
    return cache.add(request)
      .then(function(result) {
          assert_equals(result, undefined,
                        'Cache.add should resolve with undefined on success.');
        })
      .then(function() {
          return cache.add(request);
        })
      .then(function(result) {
          assert_equals(result, undefined,
                        'Cache.add should resolve with undefined on success.');
        });
  }, 'Cache.add called twice with the same Request object');

cache_test(function(cache) {
    var request = new Request('./resources/simple.txt');
    return request.text()
      .then(function() {
          assert_false(request.bodyUsed);
        })
      .then(function() {
          return cache.add(request);
        });
  }, 'Cache.add with request with null body (not consumed)');

cache_test(function(cache, test) {
    return promise_rejects_js(
      test,
      TypeError,
      cache.add('./resources/fetch-status.py?status=206'),
      'Cache.add should reject on partial response');
  }, 'Cache.add with 206 response');

cache_test(function(cache, test) {
    var urls = ['./resources/fetch-status.py?status=206',
                './resources/fetch-status.py?status=200'];
    var requests = urls.map(function(url) {
        return new Request(url);
      });
    return promise_rejects_js(
      test,
      TypeError,
      cache.addAll(requests),
      'Cache.addAll should reject with TypeError if any request fails');
  }, 'Cache.addAll with 206 response');

cache_test(function(cache, test) {
    var urls = ['./resources/fetch-status.py?status=206',
                './resources/fetch-status.py?status=200'];
    var requests = urls.map(function(url) {
        var cross_origin_url = new URL(url, location.href);
        cross_origin_url.hostname = REMOTE_HOST;
        return new Request(cross_origin_url.href, { mode: 'no-cors' });
      });
    return promise_rejects_js(
      test,
      TypeError,
      cache.addAll(requests),
      'Cache.addAll should reject with TypeError if any request fails');
  }, 'Cache.addAll with opaque-filtered 206 response');

cache_test(function(cache, test) {
    return promise_rejects_js(
      test,
      TypeError,
      cache.add('this-does-not-exist-please-dont-create-it'),
      'Cache.add should reject if response is !ok');
  }, 'Cache.add with request that results in a status of 404');


cache_test(function(cache, test) {
    return promise_rejects_js(
      test,
      TypeError,
      cache.add('./resources/fetch-status.py?status=500'),
      'Cache.add should reject if response is !ok');
  }, 'Cache.add with request that results in a status of 500');

cache_test(function(cache, test) {
    return promise_rejects_js(
      test,
      TypeError,
      cache.addAll(),
      'Cache.addAll with no arguments should throw TypeError.');
  }, 'Cache.addAll with no arguments');

cache_test(function(cache, test) {
    // Assumes the existence of ../resources/simple.txt and ../resources/blank.html
    var urls = ['./resources/simple.txt', undefined, './resources/blank.html'];
    return promise_rejects_js(
      test,
      TypeError,
      cache.addAll(urls),
      'Cache.addAll should throw TypeError for an undefined argument.');
  }, 'Cache.addAll with a mix of valid and undefined arguments');

cache_test(function(cache) {
    return cache.addAll([])
      .then(function(result) {
          assert_equals(result, undefined,
                        'Cache.addAll should resolve with undefined on ' +
                        'success.');
          return cache.keys();
        })
      .then(function(result) {
          assert_equals(result.length, 0,
                        'There should be no entry in the cache.');
        });
  }, 'Cache.addAll with an empty array');

cache_test(function(cache) {
    // Assumes the existence of ../resources/simple.txt and
    // ../resources/blank.html
    var urls = ['./resources/simple.txt',
                self.location.href,
                './resources/blank.html'];
    return cache.addAll(urls)
      .then(function(result) {
          assert_equals(result, undefined,
                        'Cache.addAll should resolve with undefined on ' +
                        'success.');
          return Promise.all(
            urls.map(function(url) { return cache.match(url); }));
        })
      .then(function(responses) {
          assert_class_string(
            responses[0], 'Response',
            'Cache.addAll should put a resource in the cache.');
          assert_class_string(
            responses[1], 'Response',
            'Cache.addAll should put a resource in the cache.');
          assert_class_string(
            responses[2], 'Response',
            'Cache.addAll should put a resource in the cache.');
          return Promise.all(
            responses.map(function(response) { return response.text(); }));
        })
      .then(function(bodies) {
          assert_equals(
            bodies[0], 'a simple text file\n',
            'Cache.add should retrieve the correct body.');
          assert_equals(
            bodies[2], '<!DOCTYPE html>\n<title>Empty doc</title>\n',
            'Cache.add should retrieve the correct body.');
        });
  }, 'Cache.addAll with string URL arguments');

cache_test(function(cache) {
    // Assumes the existence of ../resources/simple.txt and
    // ../resources/blank.html
    var urls = ['./resources/simple.txt',
                self.location.href,
                './resources/blank.html'];
    var requests = urls.map(function(url) {
        return new Request(url);
      });
    return cache.addAll(requests)
      .then(function(result) {
          assert_equals(result, undefined,
                        'Cache.addAll should resolve with undefined on ' +
                        'success.');
          return Promise.all(
            urls.map(function(url) { return cache.match(url); }));
        })
      .then(function(responses) {
          assert_class_string(
            responses[0], 'Response',
            'Cache.addAll should put a resource in the cache.');
          assert_class_string(
            responses[1], 'Response',
            'Cache.addAll should put a resource in the cache.');
          assert_class_string(
            responses[2], 'Response',
            'Cache.addAll should put a resource in the cache.');
          return Promise.all(
            responses.map(function(response) { return response.text(); }));
        })
      .then(function(bodies) {
          assert_equals(
            bodies[0], 'a simple text file\n',
            'Cache.add should retrieve the correct body.');
          assert_equals(
            bodies[2], '<!DOCTYPE html>\n<title>Empty doc</title>\n',
            'Cache.add should retrieve the correct body.');
        });
  }, 'Cache.addAll with Request arguments');

cache_test(function(cache, test) {
    // Assumes that ../resources/simple.txt and ../resources/blank.html exist.
    // The second resource does not.
    var urls = ['./resources/simple.txt',
                'this-resource-should-not-exist',
                './resources/blank.html'];
    var requests = urls.map(function(url) {
        return new Request(url);
      });
    return promise_rejects_js(
      test,
      TypeError,
      cache.addAll(requests),
      'Cache.addAll should reject with TypeError if any request fails')
      .then(function() {
          return Promise.all(urls.map(function(url) {
              return cache.match(url);
            }));
      })
      .then(function(matches) {
          assert_array_equals(
            matches,
            [undefined, undefined, undefined],
            'If any response fails, no response should be added to cache');
      });
  }, 'Cache.addAll with a mix of succeeding and failing requests');

cache_test(function(cache, test) {
    var request = new Request('../resources/simple.txt');
    return promise_rejects_dom(
      test,
      'InvalidStateError',
      cache.addAll([request, request]),
      'Cache.addAll should throw InvalidStateError if the same request is added ' +
      'twice.');
  }, 'Cache.addAll called with the same Request object specified twice');

cache_test(async function(cache, test) {
    const url = './resources/vary.py?vary=x-shape';
    let requests = [
      new Request(url, { headers: { 'x-shape': 'circle' }}),
      new Request(url, { headers: { 'x-shape': 'square' }}),
    ];
    let result = await cache.addAll(requests);
    assert_equals(result, undefined, 'Cache.addAll() should succeed');
  }, 'Cache.addAll should succeed when entries differ by vary header');

cache_test(async function(cache, test) {
    const url = './resources/vary.py?vary=x-shape';
    let requests = [
      new Request(url, { headers: { 'x-shape': 'circle' }}),
      new Request(url, { headers: { 'x-shape': 'circle' }}),
    ];
    await promise_rejects_dom(
      test,
      'InvalidStateError',
      cache.addAll(requests),
      'Cache.addAll() should reject when entries are duplicate by vary header');
  }, 'Cache.addAll should reject when entries are duplicate by vary header');

// VARY header matching is asymmetric.  Determining if two entries are duplicate
// depends on which entry's response is used in the comparison.  The target
// response's VARY header determines what request headers are examined.  This
// test verifies that Cache.addAll() duplicate checking handles this asymmetric
// behavior correctly.
cache_test(async function(cache, test) {
    const base_url = './resources/vary.py';

    // Define a request URL that sets a VARY header in the
    // query string to be echoed back by the server.
    const url = base_url + '?vary=x-size';

    // Set a cookie to override the VARY header of the response
    // when the request is made with credentials.  This will
    // take precedence over the query string vary param.  This
    // is a bit confusing, but it's necessary to construct a test
    // where the URL is the same, but the VARY headers differ.
    //
    // Note, the test could also pass this information in additional
    // request headers.  If the cookie approach becomes too unwieldy
    // this test could be rewritten to use that technique.
    await fetch(base_url + '?set-vary-value-override-cookie=x-shape');
    test.add_cleanup(_ => fetch(base_url + '?clear-vary-value-override-cookie'));

    let requests = [
      // This request will result in a Response with a "Vary: x-shape"
      // header.  This *will not* result in a duplicate match with the
      // other entry.
      new Request(url, { headers: { 'x-shape': 'circle',
                                    'x-size': 'big' },
                         credentials: 'same-origin' }),

      // This request will result in a Response with a "Vary: x-size"
      // header.  This *will* result in a duplicate match with the other
      // entry.
      new Request(url, { headers: { 'x-shape': 'square',
                                    'x-size': 'big' },
                         credentials: 'omit' }),
    ];
    await promise_rejects_dom(
      test,
      'InvalidStateError',
      cache.addAll(requests),
      'Cache.addAll() should reject when one entry has a vary header ' +
      'matching an earlier entry.');

    // Test the reverse order now.
    await promise_rejects_dom(
      test,
      'InvalidStateError',
      cache.addAll(requests.reverse()),
      'Cache.addAll() should reject when one entry has a vary header ' +
      'matching a later entry.');

  }, 'Cache.addAll should reject when one entry has a vary header ' +
     'matching another entry');

done();
