Files
gerrit/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-auth_test.html
Dmitrii Filippov 777b287894 Get rid of global Auth
* Replace the global Auth variable with named imports.
* Update gr-app-global-var-init.js

Note: this is not recommended approach for a services!
The change only focuses on removing global variables.
The service must be moved to the appContext in the future.

Change-Id: I80ec37db00b1a6682f3471867eb8207416622082
2020-04-21 15:50:48 +02:00

392 lines
12 KiB
HTML

<!DOCTYPE html>
<!--
@license
Copyright (C) 2017 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.
-->
<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
<title>gr-auth</title>
<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
<script src="/components/wct-browser-legacy/browser.js"></script>
<script type="module">
import '../../../test/common-test-setup.js';
import {BaseUrlBehavior} from '../../../behaviors/base-url-behavior/base-url-behavior.js';
import {Auth, authService} from './gr-auth.js';
suite('gr-auth', () => {
let auth;
let sandbox;
setup(() => {
sandbox = sinon.sandbox.create();
auth = authService;
});
teardown(() => {
sandbox.restore();
});
suite('Auth class methods', () => {
let fakeFetch;
setup(() => {
auth = new Auth();
fakeFetch = sandbox.stub(window, 'fetch');
});
test('auth-check returns 403', done => {
fakeFetch.returns(Promise.resolve({status: 403}));
auth.authCheck().then(authed => {
assert.isFalse(authed);
assert.equal(auth.status, Auth.STATUS.NOT_AUTHED);
done();
});
});
test('auth-check returns 204', done => {
fakeFetch.returns(Promise.resolve({status: 204}));
auth.authCheck().then(authed => {
assert.isTrue(authed);
assert.equal(auth.status, Auth.STATUS.AUTHED);
done();
});
});
test('auth-check returns 502', done => {
fakeFetch.returns(Promise.resolve({status: 502}));
auth.authCheck().then(authed => {
assert.isFalse(authed);
assert.equal(auth.status, Auth.STATUS.NOT_AUTHED);
done();
});
});
test('auth-check failed', done => {
fakeFetch.returns(Promise.reject(new Error('random error')));
auth.authCheck().then(authed => {
assert.isFalse(authed);
assert.equal(auth.status, Auth.STATUS.ERROR);
done();
});
});
});
suite('cache and events behaivor', () => {
let fakeFetch;
let clock;
setup(() => {
auth = new Auth();
clock = sinon.useFakeTimers();
fakeFetch = sandbox.stub(window, 'fetch');
});
test('cache auth-check result', done => {
fakeFetch.returns(Promise.resolve({status: 403}));
auth.authCheck().then(authed => {
assert.isFalse(authed);
assert.equal(auth.status, Auth.STATUS.NOT_AUTHED);
fakeFetch.returns(Promise.resolve({status: 204}));
auth.authCheck().then(authed2 => {
assert.isFalse(authed);
assert.equal(auth.status, Auth.STATUS.NOT_AUTHED);
done();
});
});
});
test('clearCache should refetch auth-check result', done => {
fakeFetch.returns(Promise.resolve({status: 403}));
auth.authCheck().then(authed => {
assert.isFalse(authed);
assert.equal(auth.status, Auth.STATUS.NOT_AUTHED);
fakeFetch.returns(Promise.resolve({status: 204}));
auth.clearCache();
auth.authCheck().then(authed2 => {
assert.isTrue(authed2);
assert.equal(auth.status, Auth.STATUS.AUTHED);
done();
});
});
});
test('cache expired on auth-check after certain time', done => {
fakeFetch.returns(Promise.resolve({status: 403}));
auth.authCheck().then(authed => {
assert.isFalse(authed);
assert.equal(auth.status, Auth.STATUS.NOT_AUTHED);
clock.tick(1000 * 10000);
fakeFetch.returns(Promise.resolve({status: 204}));
auth.authCheck().then(authed2 => {
assert.isTrue(authed2);
assert.equal(auth.status, Auth.STATUS.AUTHED);
done();
});
});
});
test('no cache if auth-check failed', done => {
fakeFetch.returns(Promise.reject(new Error('random error')));
auth.authCheck().then(authed => {
assert.isFalse(authed);
assert.equal(auth.status, Auth.STATUS.ERROR);
assert.equal(fakeFetch.callCount, 1);
auth.authCheck().then(() => {
assert.equal(fakeFetch.callCount, 2);
done();
});
});
});
test('fire event when switch from authed to unauthed', done => {
fakeFetch.returns(Promise.resolve({status: 204}));
auth.authCheck().then(authed => {
assert.isTrue(authed);
assert.equal(auth.status, Auth.STATUS.AUTHED);
clock.tick(1000 * 10000);
fakeFetch.returns(Promise.resolve({status: 403}));
const emitStub = sinon.stub();
Gerrit.emit = emitStub;
auth.authCheck().then(authed2 => {
assert.isFalse(authed2);
assert.equal(auth.status, Auth.STATUS.NOT_AUTHED);
assert.isTrue(emitStub.called);
done();
});
});
});
test('fire event when switch from authed to error', done => {
fakeFetch.returns(Promise.resolve({status: 204}));
auth.authCheck().then(authed => {
assert.isTrue(authed);
assert.equal(auth.status, Auth.STATUS.AUTHED);
clock.tick(1000 * 10000);
fakeFetch.returns(Promise.reject(new Error('random error')));
const emitStub = sinon.stub();
Gerrit.emit = emitStub;
auth.authCheck().then(authed2 => {
assert.isFalse(authed2);
assert.isTrue(emitStub.called);
assert.equal(auth.status, Auth.STATUS.ERROR);
done();
});
});
});
test('no event from non-authed to other status', done => {
fakeFetch.returns(Promise.resolve({status: 403}));
auth.authCheck().then(authed => {
assert.isFalse(authed);
assert.equal(auth.status, Auth.STATUS.NOT_AUTHED);
clock.tick(1000 * 10000);
fakeFetch.returns(Promise.resolve({status: 204}));
const emitStub = sinon.stub();
Gerrit.emit = emitStub;
auth.authCheck().then(authed2 => {
assert.isTrue(authed2);
assert.isFalse(emitStub.called);
assert.equal(auth.status, Auth.STATUS.AUTHED);
done();
});
});
});
test('no event from non-authed to other status', done => {
fakeFetch.returns(Promise.resolve({status: 403}));
auth.authCheck().then(authed => {
assert.isFalse(authed);
assert.equal(auth.status, Auth.STATUS.NOT_AUTHED);
clock.tick(1000 * 10000);
fakeFetch.returns(Promise.reject(new Error('random error')));
const emitStub = sinon.stub();
Gerrit.emit = emitStub;
auth.authCheck().then(authed2 => {
assert.isFalse(authed2);
assert.isFalse(emitStub.called);
assert.equal(auth.status, Auth.STATUS.ERROR);
done();
});
});
});
});
suite('default (xsrf token header)', () => {
setup(() => {
sandbox.stub(window, 'fetch').returns(Promise.resolve({ok: true}));
});
test('GET', done => {
auth.fetch('/url', {bar: 'bar'}).then(() => {
const [url, options] = fetch.lastCall.args;
assert.equal(url, '/url');
assert.equal(options.credentials, 'same-origin');
done();
});
});
test('POST', done => {
sandbox.stub(auth, '_getCookie')
.withArgs('XSRF_TOKEN')
.returns('foobar');
auth.fetch('/url', {method: 'POST'}).then(() => {
const [url, options] = fetch.lastCall.args;
assert.equal(url, '/url');
assert.equal(options.credentials, 'same-origin');
assert.equal(options.headers.get('X-Gerrit-Auth'), 'foobar');
done();
});
});
});
suite('cors (access token)', () => {
setup(() => {
sandbox.stub(window, 'fetch').returns(Promise.resolve({ok: true}));
});
let getToken;
const makeToken = opt_accessToken => {
return {
access_token: opt_accessToken || 'zbaz',
expires_at: new Date(Date.now() + 10e8).getTime(),
};
};
setup(() => {
getToken = sandbox.stub();
getToken.returns(Promise.resolve(makeToken()));
auth.setup(getToken);
});
test('base url support', done => {
const baseUrl = 'http://foo';
sandbox.stub(BaseUrlBehavior, 'getBaseUrl').returns(baseUrl);
auth.fetch(baseUrl + '/url', {bar: 'bar'}).then(() => {
const [url] = fetch.lastCall.args;
assert.equal(url, 'http://foo/a/url?access_token=zbaz');
done();
});
});
test('fetch not signed in', done => {
getToken.returns(Promise.resolve());
auth.fetch('/url', {bar: 'bar'}).then(() => {
const [url, options] = fetch.lastCall.args;
assert.equal(url, '/url');
assert.equal(options.bar, 'bar');
assert.equal(Object.keys(options.headers).length, 0);
done();
});
});
test('fetch signed in', done => {
auth.fetch('/url', {bar: 'bar'}).then(() => {
const [url, options] = fetch.lastCall.args;
assert.equal(url, '/a/url?access_token=zbaz');
assert.equal(options.bar, 'bar');
done();
});
});
test('getToken calls are cached', done => {
Promise.all([
auth.fetch('/url-one'), auth.fetch('/url-two')]).then(() => {
assert.equal(getToken.callCount, 1);
done();
});
});
test('getToken refreshes token', done => {
sandbox.stub(auth, '_isTokenValid');
auth._isTokenValid
.onFirstCall().returns(true)
.onSecondCall()
.returns(false)
.onThirdCall()
.returns(true);
auth.fetch('/url-one')
.then(() => {
getToken.returns(Promise.resolve(makeToken('bzzbb')));
return auth.fetch('/url-two');
})
.then(() => {
const [[firstUrl], [secondUrl]] = fetch.args;
assert.equal(firstUrl, '/a/url-one?access_token=zbaz');
assert.equal(secondUrl, '/a/url-two?access_token=bzzbb');
done();
});
});
test('signed in token error falls back to anonymous', done => {
getToken.returns(Promise.resolve('rubbish'));
auth.fetch('/url', {bar: 'bar'}).then(() => {
const [url, options] = fetch.lastCall.args;
assert.equal(url, '/url');
assert.equal(options.bar, 'bar');
done();
});
});
test('_isTokenValid', () => {
assert.isFalse(auth._isTokenValid());
assert.isFalse(auth._isTokenValid({}));
assert.isFalse(auth._isTokenValid({access_token: 'foo'}));
assert.isFalse(auth._isTokenValid({
access_token: 'foo',
expires_at: Date.now()/1000 - 1,
}));
assert.isTrue(auth._isTokenValid({
access_token: 'foo',
expires_at: Date.now()/1000 + 1,
}));
});
test('HTTP PUT with content type', done => {
const originalOptions = {
method: 'PUT',
headers: new Headers({'Content-Type': 'mail/pigeon'}),
};
auth.fetch('/url', originalOptions).then(() => {
assert.isTrue(getToken.called);
const [url, options] = fetch.lastCall.args;
assert.include(url, '$ct=mail%2Fpigeon');
assert.include(url, '$m=PUT');
assert.include(url, 'access_token=zbaz');
assert.equal(options.method, 'POST');
assert.equal(options.headers.get('Content-Type'), 'text/plain');
done();
});
});
test('HTTP PUT without content type', done => {
const originalOptions = {
method: 'PUT',
};
auth.fetch('/url', originalOptions).then(() => {
assert.isTrue(getToken.called);
const [url, options] = fetch.lastCall.args;
assert.include(url, '$ct=text%2Fplain');
assert.include(url, '$m=PUT');
assert.include(url, 'access_token=zbaz');
assert.equal(options.method, 'POST');
assert.equal(options.headers.get('Content-Type'), 'text/plain');
done();
});
});
});
});
</script>