chore: extract recorder dialog into a class (#32233)
This commit is contained in:
parent
fc4d8f2bb6
commit
109cab66f1
|
|
@ -552,28 +552,14 @@ class TextAssertionTool implements RecorderTool {
|
|||
private _recorder: Recorder;
|
||||
private _hoverHighlight: HighlightModel | null = null;
|
||||
private _action: actions.AssertAction | null = null;
|
||||
private _dialogElement: HTMLElement | null = null;
|
||||
private _acceptButton: HTMLElement;
|
||||
private _cancelButton: HTMLElement;
|
||||
private _keyboardListener: ((event: KeyboardEvent) => void) | undefined;
|
||||
private _dialog: Dialog;
|
||||
private _textCache = new Map<Element | ShadowRoot, ElementText>();
|
||||
private _kind: 'text' | 'value';
|
||||
|
||||
constructor(recorder: Recorder, kind: 'text' | 'value') {
|
||||
this._recorder = recorder;
|
||||
this._kind = kind;
|
||||
|
||||
this._acceptButton = this._recorder.document.createElement('x-pw-tool-item');
|
||||
this._acceptButton.title = 'Accept';
|
||||
this._acceptButton.classList.add('accept');
|
||||
this._acceptButton.appendChild(this._recorder.document.createElement('x-div'));
|
||||
this._acceptButton.addEventListener('click', () => this._commit());
|
||||
|
||||
this._cancelButton = this._recorder.document.createElement('x-pw-tool-item');
|
||||
this._cancelButton.title = 'Close';
|
||||
this._cancelButton.classList.add('cancel');
|
||||
this._cancelButton.appendChild(this._recorder.document.createElement('x-div'));
|
||||
this._cancelButton.addEventListener('click', () => this._closeDialog());
|
||||
this._dialog = new Dialog(recorder);
|
||||
}
|
||||
|
||||
cursor() {
|
||||
|
|
@ -581,7 +567,7 @@ class TextAssertionTool implements RecorderTool {
|
|||
}
|
||||
|
||||
cleanup() {
|
||||
this._closeDialog();
|
||||
this._dialog.close();
|
||||
this._hoverHighlight = null;
|
||||
}
|
||||
|
||||
|
|
@ -590,7 +576,7 @@ class TextAssertionTool implements RecorderTool {
|
|||
if (this._kind === 'value') {
|
||||
this._commitAssertValue();
|
||||
} else {
|
||||
if (!this._dialogElement)
|
||||
if (!this._dialog.isShowing())
|
||||
this._showDialog();
|
||||
}
|
||||
}
|
||||
|
|
@ -611,7 +597,7 @@ class TextAssertionTool implements RecorderTool {
|
|||
}
|
||||
|
||||
onMouseMove(event: MouseEvent) {
|
||||
if (this._dialogElement)
|
||||
if (this._dialog.isShowing())
|
||||
return;
|
||||
const target = this._recorder.deepEventTarget(event);
|
||||
if (this._hoverHighlight?.elements[0] === target)
|
||||
|
|
@ -691,9 +677,9 @@ class TextAssertionTool implements RecorderTool {
|
|||
}
|
||||
|
||||
private _commit() {
|
||||
if (!this._action || !this._dialogElement)
|
||||
if (!this._action || !this._dialog.isShowing())
|
||||
return;
|
||||
this._closeDialog();
|
||||
this._dialog.close();
|
||||
this._recorder.delegate.recordAction?.(this._action);
|
||||
this._recorder.delegate.setMode?.('recording');
|
||||
}
|
||||
|
|
@ -705,31 +691,6 @@ class TextAssertionTool implements RecorderTool {
|
|||
if (!this._action || this._action.name !== 'assertText')
|
||||
return;
|
||||
|
||||
this._dialogElement = this._recorder.document.createElement('x-pw-dialog');
|
||||
this._keyboardListener = (event: KeyboardEvent) => {
|
||||
if (event.key === 'Escape') {
|
||||
this._closeDialog();
|
||||
return;
|
||||
}
|
||||
if (event.key === 'Enter' && (event.ctrlKey || event.metaKey)) {
|
||||
if (this._dialogElement)
|
||||
this._commit();
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
this._recorder.document.addEventListener('keydown', this._keyboardListener, true);
|
||||
const toolbarElement = this._recorder.document.createElement('x-pw-tools-list');
|
||||
const labelElement = this._recorder.document.createElement('label');
|
||||
labelElement.textContent = 'Assert that element contains text';
|
||||
toolbarElement.appendChild(labelElement);
|
||||
toolbarElement.appendChild(this._recorder.document.createElement('x-spacer'));
|
||||
toolbarElement.appendChild(this._acceptButton);
|
||||
toolbarElement.appendChild(this._cancelButton);
|
||||
|
||||
this._dialogElement.appendChild(toolbarElement);
|
||||
const bodyElement = this._recorder.document.createElement('x-pw-dialog-body');
|
||||
|
||||
const action = this._action;
|
||||
const textElement = this._recorder.document.createElement('textarea');
|
||||
textElement.setAttribute('spellcheck', 'false');
|
||||
|
|
@ -747,24 +708,18 @@ class TextAssertionTool implements RecorderTool {
|
|||
textElement.classList.toggle('does-not-match', !matches);
|
||||
};
|
||||
textElement.addEventListener('input', updateAndValidate);
|
||||
bodyElement.appendChild(textElement);
|
||||
|
||||
this._dialogElement.appendChild(bodyElement);
|
||||
this._recorder.highlight.appendChild(this._dialogElement);
|
||||
const position = this._recorder.highlight.tooltipPosition(this._recorder.highlight.firstBox()!, this._dialogElement);
|
||||
this._dialogElement.style.top = position.anchorTop + 'px';
|
||||
this._dialogElement.style.left = position.anchorLeft + 'px';
|
||||
const label = 'Assert that element contains text';
|
||||
const dialogElement = this._dialog.show({
|
||||
label,
|
||||
body: textElement,
|
||||
onCommit: () => this._commit(),
|
||||
});
|
||||
const position = this._recorder.highlight.tooltipPosition(this._recorder.highlight.firstBox()!, dialogElement);
|
||||
this._dialog.moveTo(position.anchorTop, position.anchorLeft);
|
||||
textElement.focus();
|
||||
}
|
||||
|
||||
private _closeDialog() {
|
||||
if (!this._dialogElement)
|
||||
return;
|
||||
this._dialogElement.remove();
|
||||
this._recorder.document.removeEventListener('keydown', this._keyboardListener!);
|
||||
this._dialogElement = null;
|
||||
}
|
||||
|
||||
private _commitAssertValue() {
|
||||
if (this._kind !== 'value')
|
||||
return;
|
||||
|
|
@ -1219,6 +1174,87 @@ export class Recorder {
|
|||
}
|
||||
}
|
||||
|
||||
class Dialog {
|
||||
private _recorder: Recorder;
|
||||
private _dialogElement: HTMLElement | null = null;
|
||||
private _keyboardListener: ((event: KeyboardEvent) => void) | undefined;
|
||||
|
||||
constructor(recorder: Recorder) {
|
||||
this._recorder = recorder;
|
||||
}
|
||||
|
||||
isShowing(): boolean {
|
||||
return !!this._dialogElement;
|
||||
}
|
||||
|
||||
show(options: {
|
||||
label: string;
|
||||
body: Element;
|
||||
onCommit: () => void;
|
||||
onCancel?: () => void;
|
||||
}) {
|
||||
const acceptButton = this._recorder.document.createElement('x-pw-tool-item');
|
||||
acceptButton.title = 'Accept';
|
||||
acceptButton.classList.add('accept');
|
||||
acceptButton.appendChild(this._recorder.document.createElement('x-div'));
|
||||
acceptButton.addEventListener('click', () => options.onCommit());
|
||||
|
||||
const cancelButton = this._recorder.document.createElement('x-pw-tool-item');
|
||||
cancelButton.title = 'Close';
|
||||
cancelButton.classList.add('cancel');
|
||||
cancelButton.appendChild(this._recorder.document.createElement('x-div'));
|
||||
cancelButton.addEventListener('click', () => {
|
||||
this.close();
|
||||
options.onCancel?.();
|
||||
});
|
||||
|
||||
this._dialogElement = this._recorder.document.createElement('x-pw-dialog');
|
||||
this._keyboardListener = (event: KeyboardEvent) => {
|
||||
if (event.key === 'Escape') {
|
||||
this.close();
|
||||
options.onCancel?.();
|
||||
return;
|
||||
}
|
||||
if (event.key === 'Enter' && (event.ctrlKey || event.metaKey)) {
|
||||
if (this._dialogElement)
|
||||
options.onCommit();
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
this._recorder.document.addEventListener('keydown', this._keyboardListener, true);
|
||||
const toolbarElement = this._recorder.document.createElement('x-pw-tools-list');
|
||||
const labelElement = this._recorder.document.createElement('label');
|
||||
labelElement.textContent = options.label;
|
||||
toolbarElement.appendChild(labelElement);
|
||||
toolbarElement.appendChild(this._recorder.document.createElement('x-spacer'));
|
||||
toolbarElement.appendChild(acceptButton);
|
||||
toolbarElement.appendChild(cancelButton);
|
||||
|
||||
this._dialogElement.appendChild(toolbarElement);
|
||||
const bodyElement = this._recorder.document.createElement('x-pw-dialog-body');
|
||||
bodyElement.appendChild(options.body);
|
||||
this._dialogElement.appendChild(bodyElement);
|
||||
this._recorder.highlight.appendChild(this._dialogElement);
|
||||
return this._dialogElement;
|
||||
}
|
||||
|
||||
moveTo(top: number, left: number) {
|
||||
if (!this._dialogElement)
|
||||
return;
|
||||
this._dialogElement.style.top = top + 'px';
|
||||
this._dialogElement.style.left = left + 'px';
|
||||
}
|
||||
|
||||
close() {
|
||||
if (!this._dialogElement)
|
||||
return;
|
||||
this._dialogElement.remove();
|
||||
this._recorder.document.removeEventListener('keydown', this._keyboardListener!);
|
||||
this._dialogElement = null;
|
||||
}
|
||||
}
|
||||
|
||||
function deepActiveElement(document: Document): Element | null {
|
||||
let activeElement = document.activeElement;
|
||||
while (activeElement && activeElement.shadowRoot && activeElement.shadowRoot.activeElement)
|
||||
|
|
|
|||
Loading…
Reference in a new issue