Merge pull request #13177 from dotnet-maestro-bot/merge/release/3.0-to-master

[automated] Merge branch 'release/3.0' => 'master'
This commit is contained in:
N. Taylor Mullen 2019-08-15 16:14:18 -07:00 committed by GitHub
commit 6699353dc6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 57 additions and 21 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -37,13 +37,8 @@ async function boot(userOptions?: Partial<BlazorOptions>): Promise<void> {
}
const reconnection = existingConnection || await initializeConnection(options, logger);
if (reconnection.state !== signalR.HubConnectionState.Connected) {
logger.log(LogLevel.Information, 'Reconnection attempt failed. Unable to connect to the server.');
return false;
}
if (!(await circuit.reconnect(reconnection))) {
logger.log(LogLevel.Information, 'Reconnection attempt to the circuit failed.');
logger.log(LogLevel.Information, 'Reconnection attempt to the circuit was rejected by the server. This may indicate that the associated state is no longer available on the server.');
return false;
}

View File

@ -1,4 +1,5 @@
import { ReconnectDisplay } from './ReconnectDisplay';
import { Logger, LogLevel } from '../Logging/Logger';
export class DefaultReconnectDisplay implements ReconnectDisplay {
modal: HTMLDivElement;
@ -11,7 +12,7 @@ export class DefaultReconnectDisplay implements ReconnectDisplay {
reloadParagraph: HTMLParagraphElement;
constructor(dialogId: string, private document: Document) {
constructor(dialogId: string, private readonly document: Document, private readonly logger: Logger) {
this.modal = this.document.createElement('div');
this.modal.id = dialogId;
@ -38,8 +39,19 @@ export class DefaultReconnectDisplay implements ReconnectDisplay {
this.button.addEventListener('click', async () => {
this.show();
const successful = await window['Blazor'].reconnect();
if (!successful) {
try {
// reconnect will asynchronously return:
// - true to mean success
// - false to mean we reached the server, but it rejected the connection (e.g., unknown circuit ID)
// - exception to mean we didn't reach the server (this can be sync or async)
const successful = await window['Blazor'].reconnect();
if (!successful) {
this.rejected();
}
} catch (err) {
// We got an exception, server is currently unavailable
this.logger.log(LogLevel.Error, err);
this.failed();
}
});
@ -66,4 +78,10 @@ export class DefaultReconnectDisplay implements ReconnectDisplay {
this.reloadParagraph.style.display = 'none';
this.message.innerHTML = 'Reconnection failed. Try <a href>reloading</a> the page if you\'re unable to reconnect.';
}
rejected(): void {
this.button.style.display = 'none';
this.reloadParagraph.style.display = 'none';
this.message.innerHTML = 'Could not reconnect to the server. <a href>Reload</a> the page to restore functionality.';
}
}

View File

@ -21,7 +21,7 @@ export class DefaultReconnectionHandler implements ReconnectionHandler {
const modal = document.getElementById(options.dialogId);
this._reconnectionDisplay = modal
? new UserSpecifiedDisplay(modal)
: new DefaultReconnectDisplay(options.dialogId, document);
: new DefaultReconnectDisplay(options.dialogId, document, this._logger);
}
if (!this._currentReconnectionProcess) {
@ -67,7 +67,8 @@ class ReconnectionProcess {
const result = await this.reconnectCallback();
if (!result) {
// If the server responded and refused to reconnect, stop auto-retrying.
break;
this.reconnectDisplay.rejected();
return;
}
return;
} catch (err) {

View File

@ -2,4 +2,5 @@ export interface ReconnectDisplay {
show(): void;
hide(): void;
failed(): void;
rejected(): void;
}

View File

@ -6,6 +6,8 @@ export class UserSpecifiedDisplay implements ReconnectDisplay {
static readonly FailedClassName = 'components-reconnect-failed';
static readonly RefusedClassName = 'components-reconnect-refused';
constructor(private dialog: HTMLElement) {
}
@ -23,8 +25,13 @@ export class UserSpecifiedDisplay implements ReconnectDisplay {
this.removeClasses();
this.dialog.classList.add(UserSpecifiedDisplay.FailedClassName);
}
rejected(): void {
this.removeClasses();
this.dialog.classList.add(UserSpecifiedDisplay.RefusedClassName);
}
private removeClasses() {
this.dialog.classList.remove(UserSpecifiedDisplay.ShowClassName, UserSpecifiedDisplay.HideClassName, UserSpecifiedDisplay.FailedClassName);
this.dialog.classList.remove(UserSpecifiedDisplay.ShowClassName, UserSpecifiedDisplay.HideClassName, UserSpecifiedDisplay.FailedClassName, UserSpecifiedDisplay.RefusedClassName);
}
}

View File

@ -1,11 +1,12 @@
import { DefaultReconnectDisplay } from "../src/Platform/Circuits/DefaultReconnectDisplay";
import {JSDOM} from 'jsdom';
import { NullLogger} from '../src/Platform/Logging/Loggers';
describe('DefaultReconnectDisplay', () => {
it ('adds element to the body on show', () => {
const testDocument = new JSDOM().window.document;
const display = new DefaultReconnectDisplay('test-dialog-id', testDocument);
const display = new DefaultReconnectDisplay('test-dialog-id', testDocument, NullLogger.instance);
display.show();
@ -20,7 +21,7 @@ describe('DefaultReconnectDisplay', () => {
it ('does not add element to the body multiple times', () => {
const testDocument = new JSDOM().window.document;
const display = new DefaultReconnectDisplay('test-dialog-id', testDocument);
const display = new DefaultReconnectDisplay('test-dialog-id', testDocument, NullLogger.instance);
display.show();
display.show();
@ -30,7 +31,7 @@ describe('DefaultReconnectDisplay', () => {
it ('hides element', () => {
const testDocument = new JSDOM().window.document;
const display = new DefaultReconnectDisplay('test-dialog-id', testDocument);
const display = new DefaultReconnectDisplay('test-dialog-id', testDocument, NullLogger.instance);
display.hide();
@ -39,7 +40,7 @@ describe('DefaultReconnectDisplay', () => {
it ('updates message on fail', () => {
const testDocument = new JSDOM().window.document;
const display = new DefaultReconnectDisplay('test-dialog-id', testDocument);
const display = new DefaultReconnectDisplay('test-dialog-id', testDocument, NullLogger.instance);
display.show();
display.failed();
@ -49,4 +50,16 @@ describe('DefaultReconnectDisplay', () => {
expect(display.button.style.display).toBe('block');
});
it ('updates message on refused', () => {
const testDocument = new JSDOM().window.document;
const display = new DefaultReconnectDisplay('test-dialog-id', testDocument, NullLogger.instance);
display.show();
display.rejected();
expect(display.modal.style.display).toBe('block');
expect(display.message.innerHTML).toBe('Could not reconnect to the server. <a href=\"\">Reload</a> the page to restore functionality.');
expect(display.button.style.display).toBe('none');
});
});

View File

@ -93,6 +93,7 @@ function createTestDisplay(): ReconnectDisplay {
return {
show: jest.fn(),
hide: jest.fn(),
failed: jest.fn()
failed: jest.fn(),
rejected: jest.fn()
};
}