blob: 77f055824aab353b062a5fe3c5af875d9dfb9532 [file] [log] [blame]
<!DOCTYPE html>
<!--
Copyright 2017 The Chromium Authors. All rights reserved.
Use of this source code is governed by a BSD-style license that can be
found in the LICENSE file.
-->
<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
<title>cr-buildbucket-client</title>
<script src="./bower_components/webcomponentsjs/webcomponents-lite.js"></script>
<script src="./bower_components/web-component-tester/browser.js"></script>
<link rel="import" href="./bower_components/iron-test-helpers/iron-test-helpers.html">
<link rel="import" href="../static/cr-buildbucket-client.html">
<test-fixture id="instanceOne">
<template>
<cr-buildbucket-client></cr-buildbucket-client>
</template>
</test-fixture>
<test-fixture id="instanceTwo">
<template>
<cr-buildbucket-client></cr-buildbucket-client>
</template>
</test-fixture>
<script>
suite('cr-buildbucket-client basic tests', () => {
let element;
let otherElement;
let sandbox;
let pluginStub;
async function assertRejects(promise, expectedReason = null) {
try {
await promise();
assert.fail('exception', 'no exception');
} catch (actualReason) {
if (expectedReason) {
assert.deepEqual(actualReason, expectedReason);
}
}
}
setup(() => {
element = fixture('instanceOne');
otherElement = fixture('instanceTwo');
sandbox = sinon.sandbox.create();
pluginStub = {
restApi() {
return {getLoggedIn: async () => true};
},
};
element.plugin = pluginStub;
element.baseUrl = 'http://buildbucket.example.com';
element._sharedAuthState.oauth_client_id = null;
element._sharedAuthState.oauth_configured = false;
element._sharedAuthState.oauth_token = null;
element._sharedAuthState.oauth_email = null;
sandbox.stub(gapi, 'load', (_, resolve) => { resolve(); });
gapi.auth = {
init: () => { throw Error('should be stubbed'); },
authorize: () => { throw Error('should be stubbed'); },
};
});
teardown(() => {
sandbox.restore();
});
test('compare ids', () => {
assert.isBelow(element.compareIds('9999', '999'), 0);
assert.isAbove(element.compareIds('999', '9999'), 0);
assert.isBelow(element.compareIds('999', '998'), 0);
assert.isAbove(element.compareIds('998', '999'), 0);
assert.equal(element.compareIds('0', '0'), 0);
assert.equal(element.compareIds('999999999999', '999999999999'), 0);
});
test('valid token', () => {
const now = ~~(Date.now() / 1000);
const expiration = (now + 3600) + '';
assert.isFalse(element._oauthTokenIsValid(null));
assert.isFalse(element._oauthTokenIsValid(undefined));
assert.isFalse(element._oauthTokenIsValid({access_token: 'foo'}));
assert.isFalse(element._oauthTokenIsValid({expires_at: expiration}));
assert.isTrue(element._oauthTokenIsValid({
access_token: 'foo',
expires_at: expiration,
}));
assert.isFalse(element._oauthTokenIsValid({
access_token: 'foo',
expires_at: (now - 5) + '',
}));
});
test('multiple oauth config calls', async () => {
const oauthConfigStub =
sandbox.stub(element, '_getOAuthConfig', async () => ({
auth_url: '',
proxy_url: '',
client_id: 'test_client_id',
email: 'andybons@chromium.org',
}));
sandbox.stub(gapi.auth, 'init', (resolve) => { resolve(); });
await element._configureOAuthLibrary();
await element._configureOAuthLibrary();
assert.equal(oauthConfigStub.callCount, 1);
console.log(element._sharedAuthState);
console.log(otherElement._sharedAuthState);
assert.strictEqual(element._sharedAuthState, otherElement._sharedAuthState);
assert.equal(element._sharedAuthState.oauth_client_id, 'test_client_id');
assert.equal(element._sharedAuthState.oauth_email, 'andybons@chromium.org');
assert.isTrue(element._sharedAuthState.oauth_configured);
});
test('get oauth token', async () => {
const now = ~~(Date.now() / 1000);
const token = {
state: '',
access_token: '1234abcdabcd1234',
token_type: 'Bearer',
expires_in: '3600',
scope: 'test scope',
client_id: 'test_client_id',
response_type: 'token',
issued_at: now + '',
expires_at: (now + 3600) + '',
_aa: '1',
status: {
google_logged_in: false,
signed_in: true,
method: 'AUTO',
},
};
const refreshTokenStub =
sandbox.stub(element, '_refreshToken', async () => token);
const configureStub = sandbox.stub(element, '_configureOAuthLibrary',
async () => {});
await element.getOAuthToken();
await element.getOAuthToken();
assert.equal(configureStub.callCount, 1);
assert.equal(refreshTokenStub.callCount, 1);
assert.equal(element._sharedAuthState.oauth_token, token);
});
test('search builds', async () => {
const builds = [
{id: '1'},
{id: '1'},
];
sandbox.stub(window, 'fetch', async (url, opts) => {
assert.equal(
url,
('http://buildbucket.example.com/' +
'_ah/api/buildbucket/v1/search?bucket=x'));
return {
ok: true,
json: async () => ({builds}),
};
});
assert.deepEqual(await element.searchBuilds({bucket: 'x'}), builds);
});
test('fetch', async () => {
const res = {a: 1};
sandbox.stub(window, 'fetch', async (url, opts) => {
assert.equal(url, 'http://buildbucket.example.com/a/b?c=d');
assert.equal(opts.method, 'GET');
const headers = Array.from(opts.headers.entries()).map(
([k, v]) => `${k}: ${v}`);
headers.sort();
assert.deepEqual(headers, [
'accept: application/json',
'user-agent: Gerrit-Buildbucket plugin',
]);
return {
ok: true,
json: async () => res,
};
});
assert.deepEqual(await element._fetch('GET', 'a/b', 'c=d'), res);
});
test('fetch with auth token includes bearer token header', async () => {
element._sharedAuthState = {
oauth_token: {access_token: 'foo'},
oauth_configured: true,
};
const fetchStub = sandbox.stub(window, 'fetch', async (url, opts) => {
assert.equal(opts.headers.get('authorization'), 'Bearer foo');
return {ok: true, json: async () => ({})};
});
await element._fetch('GET', 'somepath', 'somequery');
assert.equal(fetchStub.callCount, 1);
});
test('fetch POST', async () => {
const req = {body: 1};
const res = {a: 1};
sandbox.stub(window, 'fetch', async (url, opts) => {
assert.equal(opts.method, 'POST');
assert.deepEqual(JSON.parse(opts.body), req);
assert.equal(
opts.headers.get('content-type'),
'application/json');
return {
ok: true,
json: async () => res,
};
});
assert.deepEqual(await element._fetch('POST', 'a/b', null, req), res);
});
test('fetch fails with json response', async () => {
const res = {a: 1};
sandbox.stub(window, 'fetch', async (url, opts) => ({
ok: false,
status: 403,
text: async () => JSON.stringify(res),
}));
await assertRejects(async () => await element._fetch('GET', 'a/b'), res);
});
test('fetch fails with textual response', async () => {
const res = 'no';
sandbox.stub(window, 'fetch', async (url, opts) => ({
ok: false,
status: 403,
text: async () => res,
}));
await assertRejects(async () => await element._fetch('GET', 'a/b'), res);
});
test('_refreshToken resolves when authorize gives token', async () => {
const token = {access_token: 'test_access_token'};
sandbox.stub(window.gapi.auth, 'authorize', (opts, callback) => {
callback(token);
});
const value = await element._refreshToken(100);
assert.deepEqual(value, token);
});
test('_refreshToken rejects when authorize gives error', async () => {
const token = {error: 'could not authorize'};
sandbox.stub(window.gapi.auth, 'authorize', (opts, callback) => {
callback(token);
});
await assertRejects(async () => await element._refreshToken(100));
});
test('_refreshToken rejects when authorize times out', async () => {
// In this test, we make it so that authorize never resolves,
// and the timeout is made smaller so that the test completes faster.
sandbox.stub(window.gapi.auth, 'authorize', () => new Promise(() => {}));
await assertRejects(async () => element._refreshToken(0));
});
});
</script>