You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1467 lines
49 KiB
1467 lines
49 KiB
var IEorEdge = /Edge\//.test(navigator.userAgent) || /MSIE/.test(navigator.userAgent)
|
|
var Chrome = /Chrome\//.test(navigator.userAgent) && !IEorEdge
|
|
var Safari = /Safari\//.test(navigator.userAgent) && !IEorEdge && !Chrome
|
|
|
|
var support = {
|
|
url: (function(url) {
|
|
try {
|
|
return new URL(url).toString() === url
|
|
} catch (e) {
|
|
return false
|
|
}
|
|
})('http://example.com/'),
|
|
blob:
|
|
'FileReader' in self &&
|
|
'Blob' in self &&
|
|
(function() {
|
|
try {
|
|
new Blob()
|
|
return true
|
|
} catch (e) {
|
|
return false
|
|
}
|
|
})(),
|
|
formData: 'FormData' in self,
|
|
arrayBuffer: 'ArrayBuffer' in self,
|
|
aborting: 'signal' in new Request(''),
|
|
permanentRedirect: !/Trident/.test(navigator.userAgent)
|
|
}
|
|
|
|
function readBlobAsText(blob) {
|
|
if ('FileReader' in self) {
|
|
return new Promise(function(resolve, reject) {
|
|
var reader = new FileReader()
|
|
reader.onload = function() {
|
|
resolve(reader.result)
|
|
}
|
|
reader.onerror = function() {
|
|
reject(reader.error)
|
|
}
|
|
reader.readAsText(blob)
|
|
})
|
|
} else if ('FileReaderSync' in self) {
|
|
return new FileReaderSync().readAsText(blob)
|
|
} else {
|
|
throw new ReferenceError('FileReader is not defined')
|
|
}
|
|
}
|
|
|
|
function readBlobAsBytes(blob) {
|
|
if ('FileReader' in self) {
|
|
return new Promise(function(resolve, reject) {
|
|
var reader = new FileReader()
|
|
reader.onload = function() {
|
|
var view = new Uint8Array(reader.result)
|
|
resolve(Array.prototype.slice.call(view))
|
|
}
|
|
reader.onerror = function() {
|
|
reject(reader.error)
|
|
}
|
|
reader.readAsArrayBuffer(blob)
|
|
})
|
|
} else if ('FileReaderSync' in self) {
|
|
return new FileReaderSync().readAsArrayBuffer(blob)
|
|
} else {
|
|
throw new ReferenceError('FileReader is not defined')
|
|
}
|
|
}
|
|
|
|
function arrayBufferFromText(text) {
|
|
var buf = new ArrayBuffer(text.length)
|
|
var view = new Uint8Array(buf)
|
|
|
|
for (var i = 0; i < text.length; i++) {
|
|
view[i] = text.charCodeAt(i)
|
|
}
|
|
return buf
|
|
}
|
|
|
|
function readArrayBufferAsText(buf) {
|
|
var view = new Uint8Array(buf)
|
|
var chars = new Array(view.length)
|
|
|
|
for (var i = 0; i < view.length; i++) {
|
|
chars[i] = String.fromCharCode(view[i])
|
|
}
|
|
return chars.join('')
|
|
}
|
|
|
|
var preservedGlobals = {}
|
|
var keepGlobals = ['fetch', 'Headers', 'Request', 'Response']
|
|
var exercise = ['polyfill']
|
|
|
|
// If native fetch implementation exists, replace it with the polyfilled
|
|
// version at first. The native implementation will be restored before the
|
|
// additional `native` pass of the test suite.
|
|
if (!self.fetch.polyfill) {
|
|
keepGlobals.forEach(function(name) {
|
|
preservedGlobals[name] = self[name]
|
|
self[name] = WHATWGFetch[name]
|
|
})
|
|
exercise.push('native')
|
|
}
|
|
|
|
var slice = Array.prototype.slice
|
|
|
|
function featureDependent(testOrSuite, condition) {
|
|
// eslint-disable-next-line no-invalid-this
|
|
;(condition ? testOrSuite : testOrSuite.skip).apply(this, slice.call(arguments, 2))
|
|
}
|
|
|
|
exercise.forEach(function(exerciseMode) {
|
|
suite(exerciseMode, function() {
|
|
if (exerciseMode === 'native') {
|
|
suiteSetup(function() {
|
|
keepGlobals.forEach(function(name) {
|
|
self[name] = preservedGlobals[name]
|
|
})
|
|
})
|
|
}
|
|
|
|
var nativeChrome = Chrome && exerciseMode === 'native'
|
|
var nativeSafari = Safari && exerciseMode === 'native'
|
|
var nativeEdge = /Edge\//.test(navigator.userAgent) && exerciseMode === 'native'
|
|
var firefox = navigator.userAgent.match(/Firefox\/(\d+)/)
|
|
var brokenFF = firefox && firefox[1] <= 56 && exerciseMode === 'native'
|
|
var polyfillFirefox = firefox && exerciseMode === 'polyfill'
|
|
var omitSafari =
|
|
Safari && exerciseMode === 'native' && navigator.userAgent.match(/Version\/(\d+\.\d+)/)[1] <= '11.1'
|
|
|
|
// https://fetch.spec.whatwg.org/#concept-bodyinit-extract
|
|
function testBodyExtract(factory) {
|
|
suite('body extract', function() {
|
|
var expected = 'Hello World!'
|
|
var inputs = [['type USVString', expected]]
|
|
if (support.blob) {
|
|
inputs.push(['type Blob', new Blob([expected])])
|
|
}
|
|
if (support.arrayBuffer) {
|
|
inputs = inputs.concat([
|
|
['type ArrayBuffer', arrayBufferFromText(expected)],
|
|
['type TypedArray', new Uint8Array(arrayBufferFromText(expected))],
|
|
['type DataView', new DataView(arrayBufferFromText(expected))]
|
|
])
|
|
}
|
|
|
|
inputs.forEach(function(input) {
|
|
var typeLabel = input[0],
|
|
body = input[1]
|
|
|
|
suite(typeLabel, function() {
|
|
featureDependent(test, support.blob, 'consume as blob', function() {
|
|
var r = factory(body)
|
|
return r
|
|
.blob()
|
|
.then(readBlobAsText)
|
|
.then(function(text) {
|
|
assert.equal(text, expected)
|
|
})
|
|
})
|
|
|
|
test('consume as text', function() {
|
|
var r = factory(body)
|
|
return r.text().then(function(text) {
|
|
assert.equal(text, expected)
|
|
})
|
|
})
|
|
|
|
featureDependent(test, support.arrayBuffer, 'consume as array buffer', function() {
|
|
var r = factory(body)
|
|
return r
|
|
.arrayBuffer()
|
|
.then(readArrayBufferAsText)
|
|
.then(function(text) {
|
|
assert.equal(text, expected)
|
|
})
|
|
})
|
|
})
|
|
})
|
|
})
|
|
}
|
|
|
|
// https://fetch.spec.whatwg.org/#headers-class
|
|
suite('Headers', function() {
|
|
test('constructor copies headers', function() {
|
|
var original = new Headers()
|
|
original.append('Accept', 'application/json')
|
|
original.append('Accept', 'text/plain')
|
|
original.append('Content-Type', 'text/html')
|
|
|
|
var headers = new Headers(original)
|
|
assert.equal(headers.get('Accept'), 'application/json, text/plain')
|
|
assert.equal(headers.get('Content-type'), 'text/html')
|
|
})
|
|
test('constructor works with arrays', function() {
|
|
var array = [['Content-Type', 'text/xml'], ['Breaking-Bad', '<3']]
|
|
var headers = new Headers(array)
|
|
|
|
assert.equal(headers.get('Content-Type'), 'text/xml')
|
|
assert.equal(headers.get('Breaking-Bad'), '<3')
|
|
})
|
|
test('headers are case insensitive', function() {
|
|
var headers = new Headers({Accept: 'application/json'})
|
|
assert.equal(headers.get('ACCEPT'), 'application/json')
|
|
assert.equal(headers.get('Accept'), 'application/json')
|
|
assert.equal(headers.get('accept'), 'application/json')
|
|
})
|
|
test('appends to existing', function() {
|
|
var headers = new Headers({Accept: 'application/json'})
|
|
assert.isFalse(headers.has('Content-Type'))
|
|
headers.append('Content-Type', 'application/json')
|
|
assert.isTrue(headers.has('Content-Type'))
|
|
assert.equal(headers.get('Content-Type'), 'application/json')
|
|
})
|
|
test('appends values to existing header name', function() {
|
|
var headers = new Headers({Accept: 'application/json'})
|
|
headers.append('Accept', 'text/plain')
|
|
assert.equal(headers.get('Accept'), 'application/json, text/plain')
|
|
})
|
|
test('sets header name and value', function() {
|
|
var headers = new Headers()
|
|
headers.set('Content-Type', 'application/json')
|
|
assert.equal(headers.get('Content-Type'), 'application/json')
|
|
})
|
|
test('returns null on no header found', function() {
|
|
var headers = new Headers()
|
|
assert.isNull(headers.get('Content-Type'))
|
|
})
|
|
test('has headers that are set', function() {
|
|
var headers = new Headers()
|
|
headers.set('Content-Type', 'application/json')
|
|
assert.isTrue(headers.has('Content-Type'))
|
|
})
|
|
test('deletes headers', function() {
|
|
var headers = new Headers()
|
|
headers.set('Content-Type', 'application/json')
|
|
assert.isTrue(headers.has('Content-Type'))
|
|
headers.delete('Content-Type')
|
|
assert.isFalse(headers.has('Content-Type'))
|
|
assert.isNull(headers.get('Content-Type'))
|
|
})
|
|
test('converts field name to string on set and get', function() {
|
|
var headers = new Headers()
|
|
headers.set(1, 'application/json')
|
|
assert.isTrue(headers.has('1'))
|
|
assert.equal(headers.get(1), 'application/json')
|
|
})
|
|
test('converts field value to string on set and get', function() {
|
|
var headers = new Headers()
|
|
headers.set('Content-Type', 1)
|
|
headers.set('X-CSRF-Token', undefined)
|
|
assert.equal(headers.get('Content-Type'), '1')
|
|
assert.equal(headers.get('X-CSRF-Token'), 'undefined')
|
|
})
|
|
test('throws TypeError on invalid character in field name', function() {
|
|
assert.throws(function() {
|
|
new Headers({'[Accept]': 'application/json'})
|
|
}, TypeError)
|
|
assert.throws(function() {
|
|
new Headers({'Accept:': 'application/json'})
|
|
}, TypeError)
|
|
assert.throws(function() {
|
|
var headers = new Headers()
|
|
headers.set({field: 'value'}, 'application/json')
|
|
}, TypeError)
|
|
assert.throws(function() {
|
|
new Headers({'': 'application/json'})
|
|
}, TypeError)
|
|
})
|
|
featureDependent(test, !brokenFF, 'is iterable with forEach', function() {
|
|
var headers = new Headers()
|
|
headers.append('Accept', 'application/json')
|
|
headers.append('Accept', 'text/plain')
|
|
headers.append('Content-Type', 'text/html')
|
|
|
|
var results = []
|
|
headers.forEach(function(value, key, object) {
|
|
results.push({value: value, key: key, object: object})
|
|
})
|
|
|
|
assert.equal(results.length, 2)
|
|
assert.deepEqual({key: 'accept', value: 'application/json, text/plain', object: headers}, results[0])
|
|
assert.deepEqual({key: 'content-type', value: 'text/html', object: headers}, results[1])
|
|
})
|
|
test('forEach accepts second thisArg argument', function() {
|
|
var headers = new Headers({Accept: 'application/json'})
|
|
var thisArg = 42
|
|
headers.forEach(function() {
|
|
assert.equal(this, thisArg)
|
|
}, thisArg)
|
|
})
|
|
featureDependent(test, !brokenFF, 'is iterable with keys', function() {
|
|
var headers = new Headers()
|
|
headers.append('Accept', 'application/json')
|
|
headers.append('Accept', 'text/plain')
|
|
headers.append('Content-Type', 'text/html')
|
|
|
|
var iterator = headers.keys()
|
|
assert.deepEqual({done: false, value: 'accept'}, iterator.next())
|
|
assert.deepEqual({done: false, value: 'content-type'}, iterator.next())
|
|
assert.deepEqual({done: true, value: undefined}, iterator.next())
|
|
})
|
|
featureDependent(test, !brokenFF, 'is iterable with values', function() {
|
|
var headers = new Headers()
|
|
headers.append('Accept', 'application/json')
|
|
headers.append('Accept', 'text/plain')
|
|
headers.append('Content-Type', 'text/html')
|
|
|
|
var iterator = headers.values()
|
|
assert.deepEqual({done: false, value: 'application/json, text/plain'}, iterator.next())
|
|
assert.deepEqual({done: false, value: 'text/html'}, iterator.next())
|
|
assert.deepEqual({done: true, value: undefined}, iterator.next())
|
|
})
|
|
featureDependent(test, !brokenFF, 'is iterable with entries', function() {
|
|
var headers = new Headers()
|
|
headers.append('Accept', 'application/json')
|
|
headers.append('Accept', 'text/plain')
|
|
headers.append('Content-Type', 'text/html')
|
|
|
|
var iterator = headers.entries()
|
|
assert.deepEqual({done: false, value: ['accept', 'application/json, text/plain']}, iterator.next())
|
|
assert.deepEqual({done: false, value: ['content-type', 'text/html']}, iterator.next())
|
|
assert.deepEqual({done: true, value: undefined}, iterator.next())
|
|
})
|
|
})
|
|
|
|
// https://fetch.spec.whatwg.org/#request-class
|
|
suite('Request', function() {
|
|
test('construct with string url', function() {
|
|
var request = new Request('https://fetch.spec.whatwg.org/')
|
|
assert.equal(request.url, 'https://fetch.spec.whatwg.org/')
|
|
})
|
|
|
|
featureDependent(test, support.url, 'construct with URL instance', function() {
|
|
var url = new URL('https://fetch.spec.whatwg.org/')
|
|
url.pathname = 'cors'
|
|
var request = new Request(url)
|
|
assert.equal(request.url, 'https://fetch.spec.whatwg.org/cors')
|
|
})
|
|
|
|
test('construct with non-Request object', function() {
|
|
var url = {
|
|
toString: function() {
|
|
return 'https://fetch.spec.whatwg.org/'
|
|
}
|
|
}
|
|
var request = new Request(url)
|
|
assert.equal(request.url, 'https://fetch.spec.whatwg.org/')
|
|
})
|
|
|
|
test('construct with Request', function() {
|
|
var request1 = new Request('https://fetch.spec.whatwg.org/', {
|
|
method: 'post',
|
|
body: 'I work out',
|
|
headers: {
|
|
accept: 'application/json',
|
|
'Content-Type': 'text/plain'
|
|
}
|
|
})
|
|
var request2 = new Request(request1)
|
|
|
|
return request2.text().then(function(body2) {
|
|
assert.equal(body2, 'I work out')
|
|
assert.equal(request2.method, 'POST')
|
|
assert.equal(request2.url, 'https://fetch.spec.whatwg.org/')
|
|
assert.equal(request2.headers.get('accept'), 'application/json')
|
|
assert.equal(request2.headers.get('content-type'), 'text/plain')
|
|
|
|
return request1.text().then(
|
|
function() {
|
|
assert(false, 'original request body should have been consumed')
|
|
},
|
|
function(error) {
|
|
assert(error instanceof TypeError, 'expected TypeError for already read body')
|
|
}
|
|
)
|
|
})
|
|
})
|
|
|
|
test('construct with Request and override headers', function() {
|
|
var request1 = new Request('https://fetch.spec.whatwg.org/', {
|
|
method: 'post',
|
|
body: 'I work out',
|
|
headers: {
|
|
accept: 'application/json',
|
|
'X-Request-ID': '123'
|
|
}
|
|
})
|
|
var request2 = new Request(request1, {
|
|
headers: {'x-test': '42'}
|
|
})
|
|
|
|
assert.equal(request2.headers.get('accept'), undefined)
|
|
assert.equal(request2.headers.get('x-request-id'), undefined)
|
|
assert.equal(request2.headers.get('x-test'), '42')
|
|
})
|
|
|
|
test('construct with Request and override body', function() {
|
|
var request1 = new Request('https://fetch.spec.whatwg.org/', {
|
|
method: 'post',
|
|
body: 'I work out',
|
|
headers: {
|
|
'Content-Type': 'text/plain'
|
|
}
|
|
})
|
|
var request2 = new Request(request1, {
|
|
body: '{"wiggles": 5}',
|
|
headers: {'Content-Type': 'application/json'}
|
|
})
|
|
|
|
return request2.json().then(function(data) {
|
|
assert.equal(data.wiggles, 5)
|
|
assert.equal(request2.headers.get('content-type'), 'application/json')
|
|
})
|
|
})
|
|
|
|
featureDependent(test, !nativeChrome, 'construct with used Request body', function() {
|
|
var request1 = new Request('https://fetch.spec.whatwg.org/', {
|
|
method: 'post',
|
|
body: 'I work out'
|
|
})
|
|
|
|
return request1.text().then(function() {
|
|
assert.throws(function() {
|
|
new Request(request1)
|
|
}, TypeError)
|
|
})
|
|
})
|
|
|
|
test('GET should not have implicit Content-Type', function() {
|
|
var req = new Request('https://fetch.spec.whatwg.org/')
|
|
assert.equal(req.headers.get('content-type'), undefined)
|
|
})
|
|
|
|
test('POST with blank body should not have implicit Content-Type', function() {
|
|
var req = new Request('https://fetch.spec.whatwg.org/', {
|
|
method: 'post'
|
|
})
|
|
assert.equal(req.headers.get('content-type'), undefined)
|
|
})
|
|
|
|
test('construct with string body sets Content-Type header', function() {
|
|
var req = new Request('https://fetch.spec.whatwg.org/', {
|
|
method: 'post',
|
|
body: 'I work out'
|
|
})
|
|
|
|
assert.equal(req.headers.get('content-type'), 'text/plain;charset=UTF-8')
|
|
})
|
|
|
|
featureDependent(test, support.blob, 'construct with Blob body and type sets Content-Type header', function() {
|
|
var req = new Request('https://fetch.spec.whatwg.org/', {
|
|
method: 'post',
|
|
body: new Blob(['test'], {type: 'image/png'})
|
|
})
|
|
|
|
assert.equal(req.headers.get('content-type'), 'image/png')
|
|
})
|
|
|
|
test('construct with body and explicit header uses header', function() {
|
|
var req = new Request('https://fetch.spec.whatwg.org/', {
|
|
method: 'post',
|
|
headers: {'Content-Type': 'image/png'},
|
|
body: 'I work out'
|
|
})
|
|
|
|
assert.equal(req.headers.get('content-type'), 'image/png')
|
|
})
|
|
|
|
featureDependent(test, support.blob, 'construct with Blob body and explicit Content-Type header', function() {
|
|
var req = new Request('https://fetch.spec.whatwg.org/', {
|
|
method: 'post',
|
|
headers: {'Content-Type': 'image/png'},
|
|
body: new Blob(['test'], {type: 'text/plain'})
|
|
})
|
|
|
|
assert.equal(req.headers.get('content-type'), 'image/png')
|
|
})
|
|
|
|
featureDependent(test, !IEorEdge, 'construct with URLSearchParams body sets Content-Type header', function() {
|
|
var req = new Request('https://fetch.spec.whatwg.org/', {
|
|
method: 'post',
|
|
body: new URLSearchParams('a=1&b=2')
|
|
})
|
|
|
|
assert.equal(req.headers.get('content-type'), 'application/x-www-form-urlencoded;charset=UTF-8')
|
|
})
|
|
|
|
featureDependent(
|
|
test,
|
|
!IEorEdge,
|
|
'construct with URLSearchParams body and explicit Content-Type header',
|
|
function() {
|
|
var req = new Request('https://fetch.spec.whatwg.org/', {
|
|
method: 'post',
|
|
headers: {'Content-Type': 'image/png'},
|
|
body: new URLSearchParams('a=1&b=2')
|
|
})
|
|
|
|
assert.equal(req.headers.get('content-type'), 'image/png')
|
|
}
|
|
)
|
|
|
|
test('construct with unsupported body type', function() {
|
|
var req = new Request('https://fetch.spec.whatwg.org/', {
|
|
method: 'post',
|
|
body: {}
|
|
})
|
|
|
|
assert.equal(req.headers.get('content-type'), 'text/plain;charset=UTF-8')
|
|
return req.text().then(function(bodyText) {
|
|
assert.equal(bodyText, '[object Object]')
|
|
})
|
|
})
|
|
|
|
test('construct with null body', function() {
|
|
var req = new Request('https://fetch.spec.whatwg.org/', {
|
|
method: 'post'
|
|
})
|
|
|
|
assert.isNull(req.headers.get('content-type'))
|
|
return req.text().then(function(bodyText) {
|
|
assert.equal(bodyText, '')
|
|
})
|
|
})
|
|
|
|
test('clone GET request', function() {
|
|
var req = new Request('https://fetch.spec.whatwg.org/', {
|
|
headers: {'content-type': 'text/plain'}
|
|
})
|
|
var clone = req.clone()
|
|
|
|
assert.equal(clone.url, req.url)
|
|
assert.equal(clone.method, 'GET')
|
|
assert.equal(clone.headers.get('content-type'), 'text/plain')
|
|
assert.notEqual(clone.headers, req.headers)
|
|
assert.isFalse(req.bodyUsed)
|
|
})
|
|
|
|
test('clone POST request', function() {
|
|
var req = new Request('https://fetch.spec.whatwg.org/', {
|
|
method: 'post',
|
|
headers: {'content-type': 'text/plain'},
|
|
body: 'I work out'
|
|
})
|
|
var clone = req.clone()
|
|
|
|
assert.equal(clone.method, 'POST')
|
|
assert.equal(clone.headers.get('content-type'), 'text/plain')
|
|
assert.notEqual(clone.headers, req.headers)
|
|
assert.equal(req.bodyUsed, false)
|
|
|
|
return Promise.all([clone.text(), req.clone().text()]).then(function(bodies) {
|
|
assert.deepEqual(bodies, ['I work out', 'I work out'])
|
|
})
|
|
})
|
|
|
|
featureDependent(test, !nativeChrome, 'clone with used Request body', function() {
|
|
var req = new Request('https://fetch.spec.whatwg.org/', {
|
|
method: 'post',
|
|
body: 'I work out'
|
|
})
|
|
|
|
return req.text().then(function() {
|
|
assert.throws(function() {
|
|
req.clone()
|
|
}, TypeError)
|
|
})
|
|
})
|
|
|
|
testBodyExtract(function(body) {
|
|
return new Request('', {method: 'POST', body: body})
|
|
})
|
|
|
|
featureDependent(test, !omitSafari, 'credentials defaults to same-origin', function() {
|
|
var request = new Request('')
|
|
assert.equal(request.credentials, 'same-origin')
|
|
})
|
|
|
|
test('credentials is overridable', function() {
|
|
var request = new Request('', {credentials: 'omit'})
|
|
assert.equal(request.credentials, 'omit')
|
|
})
|
|
})
|
|
|
|
// https://fetch.spec.whatwg.org/#response-class
|
|
suite('Response', function() {
|
|
test('default status is 200 OK', function() {
|
|
var res = new Response()
|
|
assert.equal(res.status, 200)
|
|
assert.equal(res.statusText, 'OK')
|
|
assert.isTrue(res.ok)
|
|
})
|
|
|
|
test('default status is 200 OK when an explicit undefined status code is passed', function() {
|
|
var res = new Response('', {status: undefined})
|
|
assert.equal(res.status, 200)
|
|
assert.equal(res.statusText, 'OK')
|
|
assert.isTrue(res.ok)
|
|
})
|
|
|
|
testBodyExtract(function(body) {
|
|
return new Response(body)
|
|
})
|
|
|
|
test('creates Headers object from raw headers', function() {
|
|
var r = new Response('{"foo":"bar"}', {headers: {'content-type': 'application/json'}})
|
|
assert.equal(r.headers instanceof Headers, true)
|
|
return r.json().then(function(json) {
|
|
assert.equal(json.foo, 'bar')
|
|
return json
|
|
})
|
|
})
|
|
|
|
test('always creates a new Headers instance', function() {
|
|
var headers = new Headers({'x-hello': 'world'})
|
|
var res = new Response('', {headers: headers})
|
|
|
|
assert.equal(res.headers.get('x-hello'), 'world')
|
|
assert.notEqual(res.headers, headers)
|
|
})
|
|
|
|
test('clone text response', function() {
|
|
var res = new Response('{"foo":"bar"}', {
|
|
headers: {'content-type': 'application/json'}
|
|
})
|
|
var clone = res.clone()
|
|
|
|
assert.notEqual(clone.headers, res.headers, 'headers were cloned')
|
|
assert.equal(clone.headers.get('content-type'), 'application/json')
|
|
|
|
return Promise.all([clone.json(), res.json()]).then(function(jsons) {
|
|
assert.deepEqual(jsons[0], jsons[1], 'json of cloned object is the same as original')
|
|
})
|
|
})
|
|
|
|
featureDependent(test, support.blob, 'clone blob response', function() {
|
|
var req = new Request(new Blob(['test']))
|
|
req.clone()
|
|
assert.equal(req.bodyUsed, false)
|
|
})
|
|
|
|
test('error creates error Response', function() {
|
|
var r = Response.error()
|
|
assert(r instanceof Response)
|
|
assert.equal(r.status, 0)
|
|
assert.equal(r.statusText, '')
|
|
assert.equal(r.type, 'error')
|
|
})
|
|
|
|
test('redirect creates redirect Response', function() {
|
|
var r = Response.redirect('https://fetch.spec.whatwg.org/', 301)
|
|
assert(r instanceof Response)
|
|
assert.equal(r.status, 301)
|
|
assert.equal(r.headers.get('Location'), 'https://fetch.spec.whatwg.org/')
|
|
})
|
|
|
|
test('construct with string body sets Content-Type header', function() {
|
|
var r = new Response('I work out')
|
|
assert.equal(r.headers.get('content-type'), 'text/plain;charset=UTF-8')
|
|
})
|
|
|
|
featureDependent(test, support.blob, 'construct with Blob body and type sets Content-Type header', function() {
|
|
var r = new Response(new Blob(['test'], {type: 'text/plain'}))
|
|
assert.equal(r.headers.get('content-type'), 'text/plain')
|
|
})
|
|
|
|
test('construct with body and explicit header uses header', function() {
|
|
var r = new Response('I work out', {
|
|
headers: {
|
|
'Content-Type': 'text/plain'
|
|
}
|
|
})
|
|
|
|
assert.equal(r.headers.get('content-type'), 'text/plain')
|
|
})
|
|
|
|
test('init object as first argument', function() {
|
|
var r = new Response({
|
|
status: 201,
|
|
headers: {
|
|
'Content-Type': 'text/html'
|
|
}
|
|
})
|
|
|
|
assert.equal(r.status, 200)
|
|
assert.equal(r.headers.get('content-type'), 'text/plain;charset=UTF-8')
|
|
return r.text().then(function(bodyText) {
|
|
assert.equal(bodyText, '[object Object]')
|
|
})
|
|
})
|
|
|
|
test('null as first argument', function() {
|
|
var r = new Response(null)
|
|
|
|
assert.isNull(r.headers.get('content-type'))
|
|
return r.text().then(function(bodyText) {
|
|
assert.equal(bodyText, '')
|
|
})
|
|
})
|
|
})
|
|
|
|
// https://fetch.spec.whatwg.org/#body-mixin
|
|
suite('Body mixin', function() {
|
|
featureDependent(suite, support.blob, 'arrayBuffer', function() {
|
|
test('resolves arrayBuffer promise', function() {
|
|
return fetch('/hello')
|
|
.then(function(response) {
|
|
return response.arrayBuffer()
|
|
})
|
|
.then(function(buf) {
|
|
assert(buf instanceof ArrayBuffer, 'buf is an ArrayBuffer instance')
|
|
assert.equal(buf.byteLength, 2)
|
|
})
|
|
})
|
|
|
|
test('arrayBuffer handles binary data', function() {
|
|
return fetch('/binary')
|
|
.then(function(response) {
|
|
return response.arrayBuffer()
|
|
})
|
|
.then(function(buf) {
|
|
assert(buf instanceof ArrayBuffer, 'buf is an ArrayBuffer instance')
|
|
assert.equal(buf.byteLength, 256, 'buf.byteLength is correct')
|
|
var view = new Uint8Array(buf)
|
|
for (var i = 0; i < 256; i++) {
|
|
assert.equal(view[i], i)
|
|
}
|
|
})
|
|
})
|
|
|
|
test('arrayBuffer handles utf-8 data', function() {
|
|
return fetch('/hello/utf8')
|
|
.then(function(response) {
|
|
return response.arrayBuffer()
|
|
})
|
|
.then(function(buf) {
|
|
assert(buf instanceof ArrayBuffer, 'buf is an ArrayBuffer instance')
|
|
assert.equal(buf.byteLength, 5, 'buf.byteLength is correct')
|
|
var octets = Array.prototype.slice.call(new Uint8Array(buf))
|
|
assert.deepEqual(octets, [104, 101, 108, 108, 111])
|
|
})
|
|
})
|
|
|
|
test('arrayBuffer handles utf-16le data', function() {
|
|
return fetch('/hello/utf16le')
|
|
.then(function(response) {
|
|
return response.arrayBuffer()
|
|
})
|
|
.then(function(buf) {
|
|
assert(buf instanceof ArrayBuffer, 'buf is an ArrayBuffer instance')
|
|
assert.equal(buf.byteLength, 10, 'buf.byteLength is correct')
|
|
var octets = Array.prototype.slice.call(new Uint8Array(buf))
|
|
assert.deepEqual(octets, [104, 0, 101, 0, 108, 0, 108, 0, 111, 0])
|
|
})
|
|
})
|
|
|
|
test('rejects arrayBuffer promise after body is consumed', function() {
|
|
return fetch('/hello')
|
|
.then(function(response) {
|
|
assert.equal(response.bodyUsed, false)
|
|
response.blob()
|
|
assert.equal(response.bodyUsed, true)
|
|
return response.arrayBuffer()
|
|
})
|
|
.catch(function(error) {
|
|
assert(error instanceof TypeError, 'Promise rejected after body consumed')
|
|
})
|
|
})
|
|
})
|
|
|
|
featureDependent(suite, support.blob, 'blob', function() {
|
|
test('resolves blob promise', function() {
|
|
return fetch('/hello')
|
|
.then(function(response) {
|
|
return response.blob()
|
|
})
|
|
.then(function(blob) {
|
|
assert(blob instanceof Blob, 'blob is a Blob instance')
|
|
assert.equal(blob.size, 2)
|
|
})
|
|
})
|
|
|
|
test('blob handles binary data', function() {
|
|
return fetch('/binary')
|
|
.then(function(response) {
|
|
return response.blob()
|
|
})
|
|
.then(function(blob) {
|
|
assert(blob instanceof Blob, 'blob is a Blob instance')
|
|
assert.equal(blob.size, 256, 'blob.size is correct')
|
|
})
|
|
})
|
|
|
|
test('blob handles utf-8 data', function() {
|
|
return fetch('/hello/utf8')
|
|
.then(function(response) {
|
|
return response.blob()
|
|
})
|
|
.then(readBlobAsBytes)
|
|
.then(function(octets) {
|
|
assert.equal(octets.length, 5, 'blob.size is correct')
|
|
assert.deepEqual(octets, [104, 101, 108, 108, 111])
|
|
})
|
|
})
|
|
|
|
test('blob handles utf-16le data', function() {
|
|
return fetch('/hello/utf16le')
|
|
.then(function(response) {
|
|
return response.blob()
|
|
})
|
|
.then(readBlobAsBytes)
|
|
.then(function(octets) {
|
|
assert.equal(octets.length, 10, 'blob.size is correct')
|
|
assert.deepEqual(octets, [104, 0, 101, 0, 108, 0, 108, 0, 111, 0])
|
|
})
|
|
})
|
|
|
|
test('rejects blob promise after body is consumed', function() {
|
|
return fetch('/hello')
|
|
.then(function(response) {
|
|
assert(response.blob, 'Body does not implement blob')
|
|
assert.equal(response.bodyUsed, false)
|
|
response.text()
|
|
assert.equal(response.bodyUsed, true)
|
|
return response.blob()
|
|
})
|
|
.catch(function(error) {
|
|
assert(error instanceof TypeError, 'Promise rejected after body consumed')
|
|
})
|
|
})
|
|
})
|
|
|
|
featureDependent(suite, support.formData, 'formData', function() {
|
|
test('post sets content-type header', function() {
|
|
return fetch('/request', {
|
|
method: 'post',
|
|
body: new FormData()
|
|
})
|
|
.then(function(response) {
|
|
return response.json()
|
|
})
|
|
.then(function(json) {
|
|
assert.equal(json.method, 'POST')
|
|
assert(/^multipart\/form-data;/.test(json.headers['content-type']))
|
|
})
|
|
})
|
|
|
|
featureDependent(test, !nativeChrome && !nativeEdge, 'formData rejects after body was consumed', function() {
|
|
return fetch('/json')
|
|
.then(function(response) {
|
|
assert(response.formData, 'Body does not implement formData')
|
|
response.formData()
|
|
return response.formData()
|
|
})
|
|
.catch(function(error) {
|
|
if (error instanceof chai.AssertionError) {
|
|
throw error
|
|
} else {
|
|
assert(error instanceof TypeError, 'Promise rejected after body consumed')
|
|
}
|
|
})
|
|
})
|
|
|
|
featureDependent(
|
|
test,
|
|
!nativeChrome && !nativeSafari && !nativeEdge,
|
|
'parses form encoded response',
|
|
function() {
|
|
return fetch('/form')
|
|
.then(function(response) {
|
|
return response.formData()
|
|
})
|
|
.then(function(form) {
|
|
assert(form instanceof FormData, 'Parsed a FormData object')
|
|
})
|
|
}
|
|
)
|
|
})
|
|
|
|
suite('json', function() {
|
|
test('parses json response', function() {
|
|
return fetch('/json')
|
|
.then(function(response) {
|
|
return response.json()
|
|
})
|
|
.then(function(json) {
|
|
assert.equal(json.name, 'Hubot')
|
|
assert.equal(json.login, 'hubot')
|
|
})
|
|
})
|
|
|
|
test('rejects json promise after body is consumed', function() {
|
|
return fetch('/json')
|
|
.then(function(response) {
|
|
assert(response.json, 'Body does not implement json')
|
|
assert.equal(response.bodyUsed, false)
|
|
response.text()
|
|
assert.equal(response.bodyUsed, true)
|
|
return response.json()
|
|
})
|
|
.catch(function(error) {
|
|
assert(error instanceof TypeError, 'Promise rejected after body consumed')
|
|
})
|
|
})
|
|
|
|
featureDependent(test, !polyfillFirefox, 'handles json parse error', function() {
|
|
return fetch('/json-error')
|
|
.then(function(response) {
|
|
return response.json()
|
|
})
|
|
.catch(function(error) {
|
|
if (!IEorEdge) assert(error instanceof Error, 'JSON exception is an Error instance')
|
|
assert(error.message, 'JSON exception has an error message')
|
|
})
|
|
})
|
|
})
|
|
|
|
suite('text', function() {
|
|
test('handles 204 No Content response', function() {
|
|
return fetch('/empty')
|
|
.then(function(response) {
|
|
assert.equal(response.status, 204)
|
|
return response.text()
|
|
})
|
|
.then(function(body) {
|
|
assert.equal(body, '')
|
|
})
|
|
})
|
|
|
|
test('resolves text promise', function() {
|
|
return fetch('/hello')
|
|
.then(function(response) {
|
|
return response.text()
|
|
})
|
|
.then(function(text) {
|
|
assert.equal(text, 'hi')
|
|
})
|
|
})
|
|
|
|
test('rejects text promise after body is consumed', function() {
|
|
return fetch('/hello')
|
|
.then(function(response) {
|
|
assert(response.text, 'Body does not implement text')
|
|
assert.equal(response.bodyUsed, false)
|
|
response.text()
|
|
assert.equal(response.bodyUsed, true)
|
|
return response.text()
|
|
})
|
|
.catch(function(error) {
|
|
assert(error instanceof TypeError, 'Promise rejected after body consumed')
|
|
})
|
|
})
|
|
})
|
|
})
|
|
|
|
suite('fetch method', function() {
|
|
suite('promise resolution', function() {
|
|
test('resolves promise on 500 error', function() {
|
|
return fetch('/boom')
|
|
.then(function(response) {
|
|
assert.equal(response.status, 500)
|
|
assert.equal(response.ok, false)
|
|
return response.text()
|
|
})
|
|
.then(function(body) {
|
|
assert.equal(body, 'boom')
|
|
})
|
|
})
|
|
|
|
test.skip('rejects promise for network error', function() {
|
|
return fetch('/error')
|
|
.then(function(response) {
|
|
assert(false, 'HTTP status ' + response.status + ' was treated as success')
|
|
})
|
|
.catch(function(error) {
|
|
assert(error instanceof TypeError, 'Rejected with Error')
|
|
})
|
|
})
|
|
|
|
test('rejects when Request constructor throws', function() {
|
|
return fetch('/request', {method: 'GET', body: 'invalid'})
|
|
.then(function() {
|
|
assert(false, 'Invalid Request init was accepted')
|
|
})
|
|
.catch(function(error) {
|
|
assert(error instanceof TypeError, 'Rejected with Error')
|
|
})
|
|
})
|
|
})
|
|
|
|
suite('request', function() {
|
|
test('sends headers', function() {
|
|
return fetch('/request', {
|
|
headers: {
|
|
Accept: 'application/json',
|
|
'X-Test': '42'
|
|
}
|
|
})
|
|
.then(function(response) {
|
|
return response.json()
|
|
})
|
|
.then(function(json) {
|
|
assert.equal(json.headers['accept'], 'application/json')
|
|
assert.equal(json.headers['x-test'], '42')
|
|
})
|
|
})
|
|
|
|
test('with Request as argument', function() {
|
|
var request = new Request('/request', {
|
|
headers: {
|
|
Accept: 'application/json',
|
|
'X-Test': '42'
|
|
}
|
|
})
|
|
|
|
return fetch(request)
|
|
.then(function(response) {
|
|
return response.json()
|
|
})
|
|
.then(function(json) {
|
|
assert.equal(json.headers['accept'], 'application/json')
|
|
assert.equal(json.headers['x-test'], '42')
|
|
})
|
|
})
|
|
|
|
test('reusing same Request multiple times', function() {
|
|
var request = new Request('/request', {
|
|
headers: {
|
|
Accept: 'application/json',
|
|
'X-Test': '42'
|
|
}
|
|
})
|
|
|
|
var responses = []
|
|
|
|
return fetch(request)
|
|
.then(function(response) {
|
|
responses.push(response)
|
|
return fetch(request)
|
|
})
|
|
.then(function(response) {
|
|
responses.push(response)
|
|
return fetch(request)
|
|
})
|
|
.then(function(response) {
|
|
responses.push(response)
|
|
return Promise.all(
|
|
responses.map(function(r) {
|
|
return r.json()
|
|
})
|
|
)
|
|
})
|
|
.then(function(jsons) {
|
|
jsons.forEach(function(json) {
|
|
assert.equal(json.headers['accept'], 'application/json')
|
|
assert.equal(json.headers['x-test'], '42')
|
|
})
|
|
})
|
|
})
|
|
|
|
featureDependent(suite, support.arrayBuffer, 'ArrayBuffer', function() {
|
|
test('ArrayBuffer body', function() {
|
|
return fetch('/request', {
|
|
method: 'post',
|
|
body: arrayBufferFromText('name=Hubot')
|
|
})
|
|
.then(function(response) {
|
|
return response.json()
|
|
})
|
|
.then(function(request) {
|
|
assert.equal(request.method, 'POST')
|
|
assert.equal(request.data, 'name=Hubot')
|
|
})
|
|
})
|
|
|
|
test('DataView body', function() {
|
|
return fetch('/request', {
|
|
method: 'post',
|
|
body: new DataView(arrayBufferFromText('name=Hubot'))
|
|
})
|
|
.then(function(response) {
|
|
return response.json()
|
|
})
|
|
.then(function(request) {
|
|
assert.equal(request.method, 'POST')
|
|
assert.equal(request.data, 'name=Hubot')
|
|
})
|
|
})
|
|
|
|
test('TypedArray body', function() {
|
|
return fetch('/request', {
|
|
method: 'post',
|
|
body: new Uint8Array(arrayBufferFromText('name=Hubot'))
|
|
})
|
|
.then(function(response) {
|
|
return response.json()
|
|
})
|
|
.then(function(request) {
|
|
assert.equal(request.method, 'POST')
|
|
assert.equal(request.data, 'name=Hubot')
|
|
})
|
|
})
|
|
})
|
|
|
|
featureDependent(test, !IEorEdge, 'sends URLSearchParams body', function() {
|
|
return fetch('/request', {
|
|
method: 'post',
|
|
body: new URLSearchParams('a=1&b=2')
|
|
})
|
|
.then(function(response) {
|
|
return response.json()
|
|
})
|
|
.then(function(request) {
|
|
assert.equal(request.method, 'POST')
|
|
assert.equal(request.data, 'a=1&b=2')
|
|
})
|
|
})
|
|
})
|
|
|
|
featureDependent(suite, exerciseMode !== 'native' || support.aborting, 'aborting', function() {
|
|
test('initially aborted signal', function() {
|
|
var controller = new AbortController()
|
|
controller.abort()
|
|
|
|
return fetch('/request', {
|
|
signal: controller.signal
|
|
}).then(
|
|
function() {
|
|
assert.ok(false)
|
|
},
|
|
function(error) {
|
|
if (!IEorEdge) assert.instanceOf(error, WHATWGFetch.DOMException)
|
|
assert.equal(error.name, 'AbortError')
|
|
}
|
|
)
|
|
})
|
|
|
|
test('initially aborted signal within Request', function() {
|
|
var controller = new AbortController()
|
|
controller.abort()
|
|
|
|
var request = new Request('/request', {signal: controller.signal})
|
|
|
|
return fetch(request).then(
|
|
function() {
|
|
assert.ok(false)
|
|
},
|
|
function(error) {
|
|
assert.equal(error.name, 'AbortError')
|
|
}
|
|
)
|
|
})
|
|
|
|
test('mid-request', function() {
|
|
var controller = new AbortController()
|
|
|
|
setTimeout(function() {
|
|
controller.abort()
|
|
}, 30)
|
|
|
|
return fetch('/slow?_=' + new Date().getTime(), {
|
|
signal: controller.signal
|
|
}).then(
|
|
function() {
|
|
assert.ok(false)
|
|
},
|
|
function(error) {
|
|
assert.equal(error.name, 'AbortError')
|
|
}
|
|
)
|
|
})
|
|
|
|
test('mid-request within Request', function() {
|
|
var controller = new AbortController()
|
|
var request = new Request('/slow?_=' + new Date().getTime(), {signal: controller.signal})
|
|
|
|
setTimeout(function() {
|
|
controller.abort()
|
|
}, 30)
|
|
|
|
return fetch(request).then(
|
|
function() {
|
|
assert.ok(false)
|
|
},
|
|
function(error) {
|
|
assert.equal(error.name, 'AbortError')
|
|
}
|
|
)
|
|
})
|
|
|
|
test('abort multiple with same signal', function() {
|
|
var controller = new AbortController()
|
|
|
|
setTimeout(function() {
|
|
controller.abort()
|
|
}, 30)
|
|
|
|
return Promise.all([
|
|
fetch('/slow?_=' + new Date().getTime(), {
|
|
signal: controller.signal
|
|
}).then(
|
|
function() {
|
|
assert.ok(false)
|
|
},
|
|
function(error) {
|
|
assert.equal(error.name, 'AbortError')
|
|
}
|
|
),
|
|
fetch('/slow?_=' + new Date().getTime(), {
|
|
signal: controller.signal
|
|
}).then(
|
|
function() {
|
|
assert.ok(false)
|
|
},
|
|
function(error) {
|
|
assert.equal(error.name, 'AbortError')
|
|
}
|
|
)
|
|
])
|
|
})
|
|
})
|
|
|
|
suite('response', function() {
|
|
test('populates body', function() {
|
|
return fetch('/hello')
|
|
.then(function(response) {
|
|
assert.equal(response.status, 200)
|
|
assert.equal(response.ok, true)
|
|
return response.text()
|
|
})
|
|
.then(function(body) {
|
|
assert.equal(body, 'hi')
|
|
})
|
|
})
|
|
|
|
test('parses headers', function() {
|
|
return fetch('/headers?' + new Date().getTime()).then(function(response) {
|
|
assert.equal(response.headers.get('Date'), 'Mon, 13 Oct 2014 21:02:27 GMT')
|
|
assert.equal(response.headers.get('Content-Type'), 'text/html; charset=utf-8')
|
|
})
|
|
})
|
|
})
|
|
|
|
// https://fetch.spec.whatwg.org/#methods
|
|
suite('HTTP methods', function() {
|
|
test('supports HTTP GET', function() {
|
|
return fetch('/request', {
|
|
method: 'get'
|
|
})
|
|
.then(function(response) {
|
|
return response.json()
|
|
})
|
|
.then(function(request) {
|
|
assert.equal(request.method, 'GET')
|
|
assert.equal(request.data, '')
|
|
})
|
|
})
|
|
|
|
test('GET with body throws TypeError', function() {
|
|
assert.throw(function() {
|
|
new Request('', {
|
|
method: 'get',
|
|
body: 'invalid'
|
|
})
|
|
}, TypeError)
|
|
})
|
|
|
|
test('HEAD with body throws TypeError', function() {
|
|
assert.throw(function() {
|
|
new Request('', {
|
|
method: 'head',
|
|
body: 'invalid'
|
|
})
|
|
}, TypeError)
|
|
})
|
|
|
|
test('supports HTTP POST', function() {
|
|
return fetch('/request', {
|
|
method: 'post',
|
|
body: 'name=Hubot'
|
|
})
|
|
.then(function(response) {
|
|
return response.json()
|
|
})
|
|
.then(function(request) {
|
|
assert.equal(request.method, 'POST')
|
|
assert.equal(request.data, 'name=Hubot')
|
|
})
|
|
})
|
|
|
|
test('supports HTTP PUT', function() {
|
|
return fetch('/request', {
|
|
method: 'put',
|
|
body: 'name=Hubot'
|
|
})
|
|
.then(function(response) {
|
|
return response.json()
|
|
})
|
|
.then(function(request) {
|
|
assert.equal(request.method, 'PUT')
|
|
assert.equal(request.data, 'name=Hubot')
|
|
})
|
|
})
|
|
|
|
test('supports HTTP PATCH', function() {
|
|
return fetch('/request', {
|
|
method: 'PATCH',
|
|
body: 'name=Hubot'
|
|
})
|
|
.then(function(response) {
|
|
return response.json()
|
|
})
|
|
.then(function(request) {
|
|
assert.equal(request.method, 'PATCH')
|
|
assert.equal(request.data, 'name=Hubot')
|
|
})
|
|
})
|
|
|
|
test('supports HTTP DELETE', function() {
|
|
return fetch('/request', {
|
|
method: 'delete'
|
|
})
|
|
.then(function(response) {
|
|
return response.json()
|
|
})
|
|
.then(function(request) {
|
|
assert.equal(request.method, 'DELETE')
|
|
assert.equal(request.data, '')
|
|
})
|
|
})
|
|
})
|
|
|
|
// https://fetch.spec.whatwg.org/#atomic-http-redirect-handling
|
|
suite('Atomic HTTP redirect handling', function() {
|
|
test('handles 301 redirect response', function() {
|
|
return fetch('/redirect/301')
|
|
.then(function(response) {
|
|
assert.equal(response.status, 200)
|
|
assert.equal(response.ok, true)
|
|
assert.match(response.url, /\/hello/)
|
|
return response.text()
|
|
})
|
|
.then(function(body) {
|
|
assert.equal(body, 'hi')
|
|
})
|
|
})
|
|
|
|
test('handles 302 redirect response', function() {
|
|
return fetch('/redirect/302')
|
|
.then(function(response) {
|
|
assert.equal(response.status, 200)
|
|
assert.equal(response.ok, true)
|
|
assert.match(response.url, /\/hello/)
|
|
return response.text()
|
|
})
|
|
.then(function(body) {
|
|
assert.equal(body, 'hi')
|
|
})
|
|
})
|
|
|
|
test('handles 303 redirect response', function() {
|
|
return fetch('/redirect/303')
|
|
.then(function(response) {
|
|
assert.equal(response.status, 200)
|
|
assert.equal(response.ok, true)
|
|
assert.match(response.url, /\/hello/)
|
|
return response.text()
|
|
})
|
|
.then(function(body) {
|
|
assert.equal(body, 'hi')
|
|
})
|
|
})
|
|
|
|
test('handles 307 redirect response', function() {
|
|
return fetch('/redirect/307')
|
|
.then(function(response) {
|
|
assert.equal(response.status, 200)
|
|
assert.equal(response.ok, true)
|
|
assert.match(response.url, /\/hello/)
|
|
return response.text()
|
|
})
|
|
.then(function(body) {
|
|
assert.equal(body, 'hi')
|
|
})
|
|
})
|
|
|
|
featureDependent(test, support.permanentRedirect, 'handles 308 redirect response', function() {
|
|
return fetch('/redirect/308')
|
|
.then(function(response) {
|
|
assert.equal(response.status, 200)
|
|
assert.equal(response.ok, true)
|
|
assert.match(response.url, /\/hello/)
|
|
return response.text()
|
|
})
|
|
.then(function(body) {
|
|
assert.equal(body, 'hi')
|
|
})
|
|
})
|
|
})
|
|
|
|
// https://fetch.spec.whatwg.org/#concept-request-credentials-mode
|
|
suite('credentials mode', function() {
|
|
setup(function() {
|
|
return fetch('/cookie?name=foo&value=reset', {credentials: 'same-origin'})
|
|
})
|
|
|
|
featureDependent(suite, exerciseMode === 'native', 'omit', function() {
|
|
test('does not accept cookies with omit credentials', function() {
|
|
return fetch('/cookie?name=foo&value=bar', {credentials: 'omit'})
|
|
.then(function() {
|
|
return fetch('/cookie?name=foo', {credentials: 'same-origin'})
|
|
})
|
|
.then(function(response) {
|
|
return response.text()
|
|
})
|
|
.then(function(data) {
|
|
assert.equal(data, 'reset')
|
|
})
|
|
})
|
|
|
|
test('does not send cookies with omit credentials', function() {
|
|
return fetch('/cookie?name=foo&value=bar')
|
|
.then(function() {
|
|
return fetch('/cookie?name=foo', {credentials: 'omit'})
|
|
})
|
|
.then(function(response) {
|
|
return response.text()
|
|
})
|
|
.then(function(data) {
|
|
assert.equal(data, '')
|
|
})
|
|
})
|
|
})
|
|
|
|
suite('same-origin', function() {
|
|
test('send cookies with same-origin credentials', function() {
|
|
return fetch('/cookie?name=foo&value=bar', {credentials: 'same-origin'})
|
|
.then(function() {
|
|
return fetch('/cookie?name=foo', {credentials: 'same-origin'})
|
|
})
|
|
.then(function(response) {
|
|
return response.text()
|
|
})
|
|
.then(function(data) {
|
|
assert.equal(data, 'bar')
|
|
})
|
|
})
|
|
})
|
|
|
|
suite('include', function() {
|
|
test('send cookies with include credentials', function() {
|
|
return fetch('/cookie?name=foo&value=bar', {credentials: 'include'})
|
|
.then(function() {
|
|
return fetch('/cookie?name=foo', {credentials: 'include'})
|
|
})
|
|
.then(function(response) {
|
|
return response.text()
|
|
})
|
|
.then(function(data) {
|
|
assert.equal(data, 'bar')
|
|
})
|
|
})
|
|
})
|
|
})
|
|
})
|
|
})
|
|
})
|
|
|