Create XhrMock test double#9338
Create XhrMock test double#9338taymonbeal wants to merge 3 commits intoampproject:masterfrom google:mock-xhr
Conversation
| /** @const {!Window} */ | ||
| this.win = win; | ||
| /** @type {function(this:Xhr, string, !FetchInitDef): !Promise<!FetchResponse>} */ | ||
| this.fetchImpl = win.fetch ? this.nativeFetch_ : fetchPolyfill; |
There was a problem hiding this comment.
xhr-mock.js mutates it. Should it be private given that?
| * | ||
| * See https://developer.mozilla.org/en-US/docs/Web/API/GlobalFetch/fetch | ||
| * | ||
| * @record |
There was a problem hiding this comment.
Why is this not in externs? Or at least defined as @interface?
There was a problem hiding this comment.
What I was trying to do here was create a structural interface that would be satisfied by all three kinds of response object: browser-native Response, FetchPolyfillResponse as defined in this file, and MockFetchResponse as defined in xhr-mock.js. I'm not sure it entirely worked, since I still had to put type assertions in a couple places. How would you advise doing this?
There was a problem hiding this comment.
I would just leave this as it was, and do proper unit testing of the mock implementation.
| * Create a copy of the response and return it. | ||
| * @return {!FetchResponse} | ||
| */ | ||
| clone() { |
There was a problem hiding this comment.
All of these should have /** @override */
| * interface is implemented by native `Headers` and by the polyfill and mock | ||
| * response headers types. | ||
| * | ||
| * @record |
| * @param {string} name | ||
| * @return {string} | ||
| */ | ||
| get(name) { |
|
@taymonbeal The double itself looks good. I'd still like to see how and where it helps in testing. |
|
I designed this while simultaneously using it to write new tests for PR #9040. Those tests haven't been pushed yet because they necessarily rely on this PR, but here's an excerpt: const expectRequest = (serviceName, cachebusterKid = null) =>
({method, url, headers}) => {
expect(method).to.equal('GET');
let expectedUrl = endpoints[serviceName];
if (cachebusterKid) {
expectedUrl += '?kid=' + cachebusterKid;
}
expect(url).to.equal(expectedUrl);
expect(headers['Origin']).to.equal(origin);
};
const makeResponse = (serviceName, kids) => ({
status: 200,
headers: {'Content-Type': 'application/jwk-set+json'},
body:
JSON.stringify({'keys': kids.map(kid => publicJwks[serviceName][kid])}),
});
const entry = (serviceName, kids, cachebusterKid = null) => ({
request: expectRequest(serviceName, cachebusterKid),
response: Promise.resolve(makeResponse(serviceName, kids)),
});
it('should verify a signature', () => {
xhrMock.use(origin, [entry('service-1', ['key-1'])]);
verifier.loadKeyset('service-1');
return expect(verifier.verify(
'service-1', 'key-1', signatures['service-1']['key-1'][0],
creatives[0]))
.to.eventually.be.null;
});
it('should verify multiple signatures with only one network request', () => {
xhrMock.use(origin, [entry('service-1', ['key-1'])]);
verifier.loadKeyset('service-1');
return verifier
.verify(
'service-1', 'key-1', signatures['service-1']['key-1'][0],
creatives[0])
.then(failure => {
expect(failure).to.be.null;
verifier.loadKeyset('service-1');
return expect(verifier.verify(
'service-1', 'key-1',
signatures['service-1']['key-1'][1], creatives[1]))
.to.eventually.be.null;
});
});
it('should verify a signature from a newly added key', () => {
xhrMock.use(origin, [
entry('service-1', ['key-1']),
entry('service-1', ['key-2'], 'key-2'),
]);
verifier.loadKeyset('service-1');
return expect(verifier.verify(
'service-1', 'key-2', signatures['service-1']['key-2'][0],
creatives[0]))
.to.eventually.be.null;
}) |
| * | ||
| * See https://developer.mozilla.org/en-US/docs/Web/API/GlobalFetch/fetch | ||
| * | ||
| * @record |
There was a problem hiding this comment.
I would just leave this as it was, and do proper unit testing of the mock implementation.
| */ | ||
| constructor(baseUrl, entries) { | ||
| /** @private {!Location} */ | ||
| this.baseUrl_ = typeof baseUrl == 'string' ? |
There was a problem hiding this comment.
This should always be a string.
|
@taymonbeal I see. I'd like to pass it on to @jridgewell and @aghassemi - they are more knowledgeable in tests and mocks. |
|
Looking into this, why don't we go with an npm module? |
|
I recall having looked at that at one point. Will it work with our |
|
Looks like we need to set it up with our fetch polyfill: fetchMock.setImplementations(fetchPolyfill);Then, as long as there's a |
|
This is now a blocking issue for #9040, because that's going to get broken up into multiple PRs (it got too unwieldy to ship all at once and some parts are needed sooner for Origin Trials) and I need to refactor the existing tests to make them not depend on whether the old vs. new implementation is used. I tried integrating |
|
Close or still wip? |
|
Raph took over this in #10776, though he's gone now. |
|
Obsoleted by #11001. |
Fixes #8020.