Raft Snapshot Download Bug (#17769)
* moves service worker message event listener from addon to raft-storage-overview component * adds changelog entry * adds raft-storage-overview test for downloading snapshot via service worker
This commit is contained in:
parent
723145d922
commit
2bb7da0f27
|
@ -0,0 +1,3 @@
|
||||||
|
```release-note:bug
|
||||||
|
ui: Fixes issue with not being able to download raft snapshot via service worker
|
||||||
|
```
|
|
@ -5,6 +5,8 @@ import { inject as service } from '@ember/service';
|
||||||
|
|
||||||
export default Component.extend({
|
export default Component.extend({
|
||||||
flashMessages: service(),
|
flashMessages: service(),
|
||||||
|
auth: service(),
|
||||||
|
|
||||||
useServiceWorker: null,
|
useServiceWorker: null,
|
||||||
|
|
||||||
async init() {
|
async init() {
|
||||||
|
@ -16,12 +18,32 @@ export default Component.extend({
|
||||||
if ('serviceWorker' in navigator) {
|
if ('serviceWorker' in navigator) {
|
||||||
// this checks to see if there's an active service worker - if it failed to register
|
// this checks to see if there's an active service worker - if it failed to register
|
||||||
// for any reason, then this would be null
|
// for any reason, then this would be null
|
||||||
let worker = await navigator.serviceWorker.getRegistration(config.serviceWorkerScope);
|
const worker = await navigator.serviceWorker.getRegistration(config.serviceWorkerScope);
|
||||||
if (worker) {
|
if (worker) {
|
||||||
|
navigator.serviceWorker.addEventListener('message', this.serviceWorkerGetToken.bind(this));
|
||||||
|
|
||||||
this.set('useServiceWorker', true);
|
this.set('useServiceWorker', true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
willDestroy() {
|
||||||
|
if (this.useServiceWorker) {
|
||||||
|
navigator.serviceWorker.removeEventListener('message', this.serviceWorkerGetToken);
|
||||||
|
}
|
||||||
|
this._super(...arguments);
|
||||||
|
},
|
||||||
|
|
||||||
|
serviceWorkerGetToken(event) {
|
||||||
|
const { action } = event.data;
|
||||||
|
const [port] = event.ports;
|
||||||
|
|
||||||
|
if (action === 'getToken') {
|
||||||
|
port.postMessage({ token: this.auth.currentToken });
|
||||||
|
} else {
|
||||||
|
console.error('Unknown event', event); // eslint-disable-line
|
||||||
|
port.postMessage({ error: 'Unknown request' });
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
actions: {
|
actions: {
|
||||||
async removePeer(model) {
|
async removePeer(model) {
|
||||||
|
|
|
@ -1,32 +1,6 @@
|
||||||
import { addSuccessHandler } from 'ember-service-worker/service-worker-registration';
|
import { addSuccessHandler } from 'ember-service-worker/service-worker-registration';
|
||||||
import Namespace from '@ember/application/namespace';
|
|
||||||
|
|
||||||
function getToken() {
|
|
||||||
// fix this later by allowing registration somewhere in the app lifecycle were we can have access to
|
|
||||||
// services, etc.
|
|
||||||
return Namespace.NAMESPACES_BY_ID['vault'].__container__.lookup('service:auth').currentToken;
|
|
||||||
}
|
|
||||||
|
|
||||||
addSuccessHandler(function (registration) {
|
addSuccessHandler(function (registration) {
|
||||||
// attach the handler for the message event so we can send over the auth token
|
|
||||||
navigator.serviceWorker.addEventListener('message', (event) => {
|
|
||||||
let { action } = event.data;
|
|
||||||
let port = event.ports[0];
|
|
||||||
|
|
||||||
if (action === 'getToken') {
|
|
||||||
let token = getToken();
|
|
||||||
if (!token) {
|
|
||||||
console.error('Unable to retrieve Vault tokent'); // eslint-disable-line
|
|
||||||
}
|
|
||||||
port.postMessage({ token: token });
|
|
||||||
} else {
|
|
||||||
console.error('Unknown event', event); // eslint-disable-line
|
|
||||||
port.postMessage({
|
|
||||||
error: 'Unknown request',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// attempt to unregister the service worker on unload because we're not doing any sort of caching
|
// attempt to unregister the service worker on unload because we're not doing any sort of caching
|
||||||
window.addEventListener('unload', function () {
|
window.addEventListener('unload', function () {
|
||||||
registration.unregister();
|
registration.unregister();
|
||||||
|
|
|
@ -2,17 +2,56 @@ import { module, test } from 'qunit';
|
||||||
import { setupRenderingTest } from 'ember-qunit';
|
import { setupRenderingTest } from 'ember-qunit';
|
||||||
import { render } from '@ember/test-helpers';
|
import { render } from '@ember/test-helpers';
|
||||||
import hbs from 'htmlbars-inline-precompile';
|
import hbs from 'htmlbars-inline-precompile';
|
||||||
|
import sinon from 'sinon';
|
||||||
|
|
||||||
module('Integration | Component | raft-storage-overview', function (hooks) {
|
module('Integration | Component | raft-storage-overview', function (hooks) {
|
||||||
setupRenderingTest(hooks);
|
setupRenderingTest(hooks);
|
||||||
|
|
||||||
test('it renders', async function (assert) {
|
hooks.beforeEach(function () {
|
||||||
let model = [
|
this.model = [
|
||||||
{ address: '127.0.0.1:8200', voter: true },
|
{ address: '127.0.0.1:8200', voter: true },
|
||||||
{ address: '127.0.0.1:8200', voter: true, leader: true },
|
{ address: '127.0.0.1:8200', voter: true, leader: true },
|
||||||
];
|
];
|
||||||
this.set('model', model);
|
});
|
||||||
|
|
||||||
|
test('it renders', async function (assert) {
|
||||||
await render(hbs`<RaftStorageOverview @model={{this.model}} />`);
|
await render(hbs`<RaftStorageOverview @model={{this.model}} />`);
|
||||||
assert.dom('[data-raft-row]').exists({ count: 2 });
|
assert.dom('[data-raft-row]').exists({ count: 2 });
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('it should download snapshot via service worker', async function (assert) {
|
||||||
|
assert.expect(3);
|
||||||
|
|
||||||
|
const token = this.owner.lookup('service:auth').currentToken;
|
||||||
|
const generateMockEvent = (action) => ({
|
||||||
|
data: { action },
|
||||||
|
ports: [
|
||||||
|
{
|
||||||
|
postMessage(message) {
|
||||||
|
const getToken = action === 'getToken';
|
||||||
|
const expected = getToken ? { token } : { error: 'Unknown request' };
|
||||||
|
assert.deepEqual(
|
||||||
|
message,
|
||||||
|
expected,
|
||||||
|
`${
|
||||||
|
getToken ? 'Token' : 'Error'
|
||||||
|
} is returned to service worker in message event listener callback`
|
||||||
|
);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
sinon.stub(navigator.serviceWorker, 'getRegistration').resolves(true);
|
||||||
|
sinon.stub(navigator.serviceWorker, 'addEventListener').callsFake((name, cb) => {
|
||||||
|
assert.strictEqual(name, 'message', 'Event listener added for service worker message');
|
||||||
|
cb(generateMockEvent('getToken'));
|
||||||
|
cb(generateMockEvent('unknown'));
|
||||||
|
});
|
||||||
|
|
||||||
|
await render(hbs`<RaftStorageOverview @model={{this.model}} />`);
|
||||||
|
// avoid clicking the download button or the url will change
|
||||||
|
// the service worker invokes the event listener callback when it intercepts the request to /v1/sys/storage/raft/snapshot
|
||||||
|
// for the test we manually fire the callback as soon as it is passed to the addEventListener stub
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue