feat(recorder): assert visibility tool (#28142)
This commit is contained in:
parent
03031a6d2c
commit
0a052cb4d6
|
|
@ -170,10 +170,16 @@ x-pw-tool-item.pick-locator > x-div {
|
|||
mask-image: url("data:image/svg+xml;utf8,<svg width='16' height='16' viewBox='0 0 16 16' xmlns='http://www.w3.org/2000/svg' fill='currentColor'><path fill-rule='evenodd' clip-rule='evenodd' d='M1 3l1-1h12l1 1v6h-1V3H2v8h5v1H2l-1-1V3zm14.707 9.707L9 6v9.414l2.707-2.707h4zM10 13V8.414l3.293 3.293h-2L10 13z'/></svg>");
|
||||
}
|
||||
|
||||
x-pw-tool-item.assert > x-div {
|
||||
/* codicon: check-all */
|
||||
-webkit-mask-image: url("data:image/svg+xml;utf8,<svg width='16' height='16' viewBox='0 0 16 16' xmlns='http://www.w3.org/2000/svg' fill='currentColor'><path fill-rule='evenodd' clip-rule='evenodd' d='M15.62 3.596L7.815 12.81l-.728-.033L4 8.382l.754-.53 2.744 3.907L14.917 3l.703.596z'/><path fill-rule='evenodd' clip-rule='evenodd' d='M7.234 8.774l4.386-5.178L10.917 3l-4.23 4.994.547.78zm-1.55.403l.548.78-.547-.78zm-1.617 1.91l.547.78-.799.943-.728-.033L0 8.382l.754-.53 2.744 3.907.57-.672z'/></svg>");
|
||||
mask-image: url("data:image/svg+xml;utf8,<svg width='16' height='16' viewBox='0 0 16 16' xmlns='http://www.w3.org/2000/svg' fill='currentColor'><path fill-rule='evenodd' clip-rule='evenodd' d='M15.62 3.596L7.815 12.81l-.728-.033L4 8.382l.754-.53 2.744 3.907L14.917 3l.703.596z'/><path fill-rule='evenodd' clip-rule='evenodd' d='M7.234 8.774l4.386-5.178L10.917 3l-4.23 4.994.547.78zm-1.55.403l.548.78-.547-.78zm-1.617 1.91l.547.78-.799.943-.728-.033L0 8.382l.754-.53 2.744 3.907.57-.672z'/></svg>");
|
||||
x-pw-tool-item.text > x-div {
|
||||
/* codicon: whole-word */
|
||||
-webkit-mask-image: url("data:image/svg+xml;utf8,<svg width='16' height='16' viewBox='0 0 16 16' xmlns='http://www.w3.org/2000/svg' fill='currentColor'><path fill-rule='evenodd' clip-rule='evenodd' d='M0 11H1V13H15V11H16V14H15H1H0V11Z'/><path d='M6.84048 11H5.95963V10.1406H5.93814C5.555 10.7995 4.99104 11.1289 4.24625 11.1289C3.69839 11.1289 3.26871 10.9839 2.95718 10.6938C2.64924 10.4038 2.49527 10.0189 2.49527 9.53906C2.49527 8.51139 3.10041 7.91341 4.3107 7.74512L5.95963 7.51416C5.95963 6.57959 5.58186 6.1123 4.82632 6.1123C4.16389 6.1123 3.56591 6.33789 3.03238 6.78906V5.88672C3.57307 5.54297 4.19612 5.37109 4.90152 5.37109C6.19416 5.37109 6.84048 6.05501 6.84048 7.42285V11ZM5.95963 8.21777L4.63297 8.40039C4.22476 8.45768 3.91682 8.55973 3.70914 8.70654C3.50145 8.84977 3.39761 9.10579 3.39761 9.47461C3.39761 9.74316 3.4925 9.96338 3.68228 10.1353C3.87564 10.3035 4.13166 10.3877 4.45035 10.3877C4.8872 10.3877 5.24706 10.2355 5.52994 9.93115C5.8164 9.62321 5.95963 9.2347 5.95963 8.76562V8.21777Z'/><path d='M9.3475 10.2051H9.32601V11H8.44515V2.85742H9.32601V6.4668H9.3475C9.78076 5.73633 10.4146 5.37109 11.2489 5.37109C11.9543 5.37109 12.5057 5.61816 12.9032 6.1123C13.3042 6.60286 13.5047 7.26172 13.5047 8.08887C13.5047 9.00911 13.2809 9.74674 12.8333 10.3018C12.3857 10.8532 11.7734 11.1289 10.9964 11.1289C10.2695 11.1289 9.71989 10.821 9.3475 10.2051ZM9.32601 7.98682V8.75488C9.32601 9.20964 9.47282 9.59635 9.76644 9.91504C10.0636 10.2301 10.4396 10.3877 10.8944 10.3877C11.4279 10.3877 11.8451 10.1836 12.1458 9.77539C12.4502 9.36719 12.6024 8.79964 12.6024 8.07275C12.6024 7.46045 12.4609 6.98063 12.1781 6.6333C11.8952 6.28597 11.512 6.1123 11.0286 6.1123C10.5166 6.1123 10.1048 6.29134 9.7933 6.64941C9.48177 7.00391 9.32601 7.44971 9.32601 7.98682Z'/></svg>");
|
||||
mask-image: url("data:image/svg+xml;utf8,<svg width='16' height='16' viewBox='0 0 16 16' xmlns='http://www.w3.org/2000/svg' fill='currentColor'><path fill-rule='evenodd' clip-rule='evenodd' d='M0 11H1V13H15V11H16V14H15H1H0V11Z'/><path d='M6.84048 11H5.95963V10.1406H5.93814C5.555 10.7995 4.99104 11.1289 4.24625 11.1289C3.69839 11.1289 3.26871 10.9839 2.95718 10.6938C2.64924 10.4038 2.49527 10.0189 2.49527 9.53906C2.49527 8.51139 3.10041 7.91341 4.3107 7.74512L5.95963 7.51416C5.95963 6.57959 5.58186 6.1123 4.82632 6.1123C4.16389 6.1123 3.56591 6.33789 3.03238 6.78906V5.88672C3.57307 5.54297 4.19612 5.37109 4.90152 5.37109C6.19416 5.37109 6.84048 6.05501 6.84048 7.42285V11ZM5.95963 8.21777L4.63297 8.40039C4.22476 8.45768 3.91682 8.55973 3.70914 8.70654C3.50145 8.84977 3.39761 9.10579 3.39761 9.47461C3.39761 9.74316 3.4925 9.96338 3.68228 10.1353C3.87564 10.3035 4.13166 10.3877 4.45035 10.3877C4.8872 10.3877 5.24706 10.2355 5.52994 9.93115C5.8164 9.62321 5.95963 9.2347 5.95963 8.76562V8.21777Z'/><path d='M9.3475 10.2051H9.32601V11H8.44515V2.85742H9.32601V6.4668H9.3475C9.78076 5.73633 10.4146 5.37109 11.2489 5.37109C11.9543 5.37109 12.5057 5.61816 12.9032 6.1123C13.3042 6.60286 13.5047 7.26172 13.5047 8.08887C13.5047 9.00911 13.2809 9.74674 12.8333 10.3018C12.3857 10.8532 11.7734 11.1289 10.9964 11.1289C10.2695 11.1289 9.71989 10.821 9.3475 10.2051ZM9.32601 7.98682V8.75488C9.32601 9.20964 9.47282 9.59635 9.76644 9.91504C10.0636 10.2301 10.4396 10.3877 10.8944 10.3877C11.4279 10.3877 11.8451 10.1836 12.1458 9.77539C12.4502 9.36719 12.6024 8.79964 12.6024 8.07275C12.6024 7.46045 12.4609 6.98063 12.1781 6.6333C11.8952 6.28597 11.512 6.1123 11.0286 6.1123C10.5166 6.1123 10.1048 6.29134 9.7933 6.64941C9.48177 7.00391 9.32601 7.44971 9.32601 7.98682Z'/></svg>");
|
||||
}
|
||||
|
||||
x-pw-tool-item.visibility > x-div {
|
||||
/* codicon: eye */
|
||||
-webkit-mask-image: url("data:image/svg+xml;utf8,<svg width='16' height='16' viewBox='0 0 16 16' xmlns='http://www.w3.org/2000/svg' fill='currentColor'><path d='M7.99993 6.00316C9.47266 6.00316 10.6666 7.19708 10.6666 8.66981C10.6666 10.1426 9.47266 11.3365 7.99993 11.3365C6.52715 11.3365 5.33324 10.1426 5.33324 8.66981C5.33324 7.19708 6.52715 6.00316 7.99993 6.00316ZM7.99993 7.00315C7.07946 7.00315 6.33324 7.74935 6.33324 8.66981C6.33324 9.59028 7.07946 10.3365 7.99993 10.3365C8.9204 10.3365 9.6666 9.59028 9.6666 8.66981C9.6666 7.74935 8.9204 7.00315 7.99993 7.00315ZM7.99993 3.66675C11.0756 3.66675 13.7307 5.76675 14.4673 8.70968C14.5344 8.97755 14.3716 9.24908 14.1037 9.31615C13.8358 9.38315 13.5643 9.22041 13.4973 8.95248C12.8713 6.45205 10.6141 4.66675 7.99993 4.66675C5.38454 4.66675 3.12664 6.45359 2.50182 8.95555C2.43491 9.22341 2.16348 9.38635 1.89557 9.31948C1.62766 9.25255 1.46471 8.98115 1.53162 8.71321C2.26701 5.76856 4.9229 3.66675 7.99993 3.66675Z'/></svg>");
|
||||
mask-image: url("data:image/svg+xml;utf8,<svg width='16' height='16' viewBox='0 0 16 16' xmlns='http://www.w3.org/2000/svg' fill='currentColor'><path d='M7.99993 6.00316C9.47266 6.00316 10.6666 7.19708 10.6666 8.66981C10.6666 10.1426 9.47266 11.3365 7.99993 11.3365C6.52715 11.3365 5.33324 10.1426 5.33324 8.66981C5.33324 7.19708 6.52715 6.00316 7.99993 6.00316ZM7.99993 7.00315C7.07946 7.00315 6.33324 7.74935 6.33324 8.66981C6.33324 9.59028 7.07946 10.3365 7.99993 10.3365C8.9204 10.3365 9.6666 9.59028 9.6666 8.66981C9.6666 7.74935 8.9204 7.00315 7.99993 7.00315ZM7.99993 3.66675C11.0756 3.66675 13.7307 5.76675 14.4673 8.70968C14.5344 8.97755 14.3716 9.24908 14.1037 9.31615C13.8358 9.38315 13.5643 9.22041 13.4973 8.95248C12.8713 6.45205 10.6141 4.66675 7.99993 4.66675C5.38454 4.66675 3.12664 6.45359 2.50182 8.95555C2.43491 9.22341 2.16348 9.38635 1.89557 9.31948C1.62766 9.25255 1.46471 8.98115 1.53162 8.71321C2.26701 5.76856 4.9229 3.66675 7.99993 3.66675Z'/></svg>");
|
||||
}
|
||||
|
||||
x-pw-tool-item.accept > x-div {
|
||||
|
|
|
|||
|
|
@ -83,7 +83,7 @@ class InspectTool implements RecorderTool {
|
|||
private _hoveredModel: HighlightModel | null = null;
|
||||
private _hoveredElement: HTMLElement | null = null;
|
||||
|
||||
constructor(private _recorder: Recorder) {
|
||||
constructor(private _recorder: Recorder, private _assertVisibility: boolean) {
|
||||
}
|
||||
|
||||
cursor() {
|
||||
|
|
@ -97,7 +97,17 @@ class InspectTool implements RecorderTool {
|
|||
|
||||
onClick(event: MouseEvent) {
|
||||
consumeEvent(event);
|
||||
this._recorder.delegate.setSelector?.(this._hoveredModel ? this._hoveredModel.selector : '');
|
||||
if (this._assertVisibility) {
|
||||
if (this._hoveredModel?.selector) {
|
||||
this._recorder.delegate.recordAction?.({
|
||||
name: 'assertVisible',
|
||||
selector: this._hoveredModel.selector,
|
||||
signals: [],
|
||||
});
|
||||
}
|
||||
} else {
|
||||
this._recorder.delegate.setSelector?.(this._hoveredModel ? this._hoveredModel.selector : '');
|
||||
}
|
||||
}
|
||||
|
||||
onPointerDown(event: PointerEvent) {
|
||||
|
|
@ -144,6 +154,8 @@ class InspectTool implements RecorderTool {
|
|||
|
||||
onKeyDown(event: KeyboardEvent) {
|
||||
consumeEvent(event);
|
||||
if (this._assertVisibility && event.key === 'Escape')
|
||||
this._recorder.delegate.setMode?.('recording');
|
||||
}
|
||||
|
||||
onKeyUp(event: KeyboardEvent) {
|
||||
|
|
@ -726,7 +738,8 @@ class Overlay {
|
|||
private _overlayElement: HTMLElement;
|
||||
private _recordToggle: HTMLElement;
|
||||
private _pickLocatorToggle: HTMLElement;
|
||||
private _assertToggle: HTMLElement;
|
||||
private _assertVisibilityToggle: HTMLElement;
|
||||
private _assertTextToggle: HTMLElement;
|
||||
private _offsetX = 0;
|
||||
private _dragState: { offsetX: number, dragStart: { x: number, y: number } } | undefined;
|
||||
private _measure: { width: number, height: number } = { width: 0, height: 0 };
|
||||
|
|
@ -766,20 +779,31 @@ class Overlay {
|
|||
'recording': 'recording-inspecting',
|
||||
'recording-inspecting': 'recording',
|
||||
'assertingText': 'recording-inspecting',
|
||||
'assertingVisibility': 'recording-inspecting',
|
||||
};
|
||||
this._recorder.delegate.setMode?.(newMode[this._recorder.state.mode]);
|
||||
});
|
||||
toolsListElement.appendChild(this._pickLocatorToggle);
|
||||
|
||||
this._assertToggle = this._recorder.injectedScript.document.createElement('x-pw-tool-item');
|
||||
this._assertToggle.title = 'Assert text and values';
|
||||
this._assertToggle.classList.add('assert');
|
||||
this._assertToggle.appendChild(this._recorder.injectedScript.document.createElement('x-div'));
|
||||
this._assertToggle.addEventListener('click', () => {
|
||||
if (!this._assertToggle.classList.contains('disabled'))
|
||||
this._assertVisibilityToggle = this._recorder.injectedScript.document.createElement('x-pw-tool-item');
|
||||
this._assertVisibilityToggle.title = 'Assert visibility';
|
||||
this._assertVisibilityToggle.classList.add('visibility');
|
||||
this._assertVisibilityToggle.appendChild(this._recorder.injectedScript.document.createElement('x-div'));
|
||||
this._assertVisibilityToggle.addEventListener('click', () => {
|
||||
if (!this._assertVisibilityToggle.classList.contains('disabled'))
|
||||
this._recorder.delegate.setMode?.(this._recorder.state.mode === 'assertingVisibility' ? 'recording' : 'assertingVisibility');
|
||||
});
|
||||
toolsListElement.appendChild(this._assertVisibilityToggle);
|
||||
|
||||
this._assertTextToggle = this._recorder.injectedScript.document.createElement('x-pw-tool-item');
|
||||
this._assertTextToggle.title = 'Assert text and values';
|
||||
this._assertTextToggle.classList.add('text');
|
||||
this._assertTextToggle.appendChild(this._recorder.injectedScript.document.createElement('x-div'));
|
||||
this._assertTextToggle.addEventListener('click', () => {
|
||||
if (!this._assertTextToggle.classList.contains('disabled'))
|
||||
this._recorder.delegate.setMode?.(this._recorder.state.mode === 'assertingText' ? 'recording' : 'assertingText');
|
||||
});
|
||||
toolsListElement.appendChild(this._assertToggle);
|
||||
toolsListElement.appendChild(this._assertTextToggle);
|
||||
|
||||
this._updateVisualPosition();
|
||||
}
|
||||
|
|
@ -794,10 +818,12 @@ class Overlay {
|
|||
}
|
||||
|
||||
setUIState(state: UIState) {
|
||||
this._recordToggle.classList.toggle('active', state.mode === 'recording' || state.mode === 'assertingText' || state.mode === 'recording-inspecting');
|
||||
this._recordToggle.classList.toggle('active', state.mode === 'recording' || state.mode === 'assertingText' || state.mode === 'assertingVisibility' || state.mode === 'recording-inspecting');
|
||||
this._pickLocatorToggle.classList.toggle('active', state.mode === 'inspecting' || state.mode === 'recording-inspecting');
|
||||
this._assertToggle.classList.toggle('active', state.mode === 'assertingText');
|
||||
this._assertToggle.classList.toggle('disabled', state.mode === 'none' || state.mode === 'standby' || state.mode === 'inspecting');
|
||||
this._assertVisibilityToggle.classList.toggle('active', state.mode === 'assertingVisibility');
|
||||
this._assertVisibilityToggle.classList.toggle('disabled', state.mode === 'none' || state.mode === 'standby' || state.mode === 'inspecting');
|
||||
this._assertTextToggle.classList.toggle('active', state.mode === 'assertingText');
|
||||
this._assertTextToggle.classList.toggle('disabled', state.mode === 'none' || state.mode === 'standby' || state.mode === 'inspecting');
|
||||
if (this._offsetX !== state.overlay.offsetX) {
|
||||
this._offsetX = state.overlay.offsetX;
|
||||
this._updateVisualPosition();
|
||||
|
|
@ -867,10 +893,11 @@ export class Recorder {
|
|||
this._tools = {
|
||||
'none': new NoneTool(),
|
||||
'standby': new NoneTool(),
|
||||
'inspecting': new InspectTool(this),
|
||||
'inspecting': new InspectTool(this, false),
|
||||
'recording': new RecordActionTool(this),
|
||||
'recording-inspecting': new InspectTool(this),
|
||||
'recording-inspecting': new InspectTool(this, false),
|
||||
'assertingText': new TextAssertionTool(this),
|
||||
'assertingVisibility': new InspectTool(this, true),
|
||||
};
|
||||
this._currentTool = this._tools.none;
|
||||
if (injectedScript.window.top === injectedScript.window) {
|
||||
|
|
|
|||
|
|
@ -246,8 +246,8 @@ export class Recorder implements InstrumentationListener {
|
|||
this._highlightedSelector = '';
|
||||
this._mode = mode;
|
||||
this._recorderApp?.setMode(this._mode);
|
||||
this._contextRecorder.setEnabled(this._mode === 'recording' || this._mode === 'assertingText');
|
||||
this._debugger.setMuted(this._mode === 'recording' || this._mode === 'assertingText');
|
||||
this._contextRecorder.setEnabled(this._mode === 'recording' || this._mode === 'assertingText' || this._mode === 'assertingVisibility');
|
||||
this._debugger.setMuted(this._mode === 'recording' || this._mode === 'assertingText' || this._mode === 'assertingVisibility');
|
||||
if (this._mode !== 'none' && this._mode !== 'standby' && this._context.pages().length === 1)
|
||||
this._context.pages()[0].bringToFront().catch(() => {});
|
||||
this._refreshOverlay();
|
||||
|
|
@ -281,7 +281,7 @@ export class Recorder implements InstrumentationListener {
|
|||
}
|
||||
|
||||
async onBeforeCall(sdkObject: SdkObject, metadata: CallMetadata) {
|
||||
if (this._omitCallTracking || this._mode === 'recording' || this._mode === 'assertingText')
|
||||
if (this._omitCallTracking || this._mode === 'recording' || this._mode === 'assertingText' || this._mode === 'assertingVisibility')
|
||||
return;
|
||||
this._currentCallsMetadata.set(metadata, sdkObject);
|
||||
this._updateUserSources();
|
||||
|
|
@ -295,7 +295,7 @@ export class Recorder implements InstrumentationListener {
|
|||
}
|
||||
|
||||
async onAfterCall(sdkObject: SdkObject, metadata: CallMetadata) {
|
||||
if (this._omitCallTracking || this._mode === 'recording' || this._mode === 'assertingText')
|
||||
if (this._omitCallTracking || this._mode === 'recording' || this._mode === 'assertingText' || this._mode === 'assertingVisibility')
|
||||
return;
|
||||
if (!metadata.error)
|
||||
this._currentCallsMetadata.delete(metadata);
|
||||
|
|
@ -345,7 +345,7 @@ export class Recorder implements InstrumentationListener {
|
|||
}
|
||||
|
||||
updateCallLog(metadatas: CallMetadata[]) {
|
||||
if (this._mode === 'recording' || this._mode === 'assertingText')
|
||||
if (this._mode === 'recording' || this._mode === 'assertingText' || this._mode === 'assertingVisibility')
|
||||
return;
|
||||
const logs: CallLog[] = [];
|
||||
for (const metadata of metadatas) {
|
||||
|
|
|
|||
|
|
@ -158,6 +158,8 @@ export class CSharpLanguageGenerator implements LanguageGenerator {
|
|||
return `await Expect(${subject}.${this._asLocator(action.selector)}).${action.substring ? 'ToContainTextAsync' : 'ToHaveTextAsync'}(${quote(action.text)});`;
|
||||
case 'assertChecked':
|
||||
return `await Expect(${subject}.${this._asLocator(action.selector)})${action.checked ? '' : '.Not'}.ToBeCheckedAsync();`;
|
||||
case 'assertVisible':
|
||||
return `await Expect(${subject}.${this._asLocator(action.selector)}).ToBeVisibleAsync();`;
|
||||
case 'assertValue': {
|
||||
const assertion = action.value ? `ToHaveValueAsync(${quote(action.value)})` : `ToBeEmpty()`;
|
||||
return `await Expect(${subject}.${this._asLocator(action.selector)}).${assertion};`;
|
||||
|
|
|
|||
|
|
@ -126,6 +126,8 @@ export class JavaLanguageGenerator implements LanguageGenerator {
|
|||
return `assertThat(${subject}.${this._asLocator(action.selector, inFrameLocator)}).${action.substring ? 'containsText' : 'hasText'}(${quote(action.text)});`;
|
||||
case 'assertChecked':
|
||||
return `assertThat(${subject}.${this._asLocator(action.selector, inFrameLocator)})${action.checked ? '' : '.not()'}.isChecked();`;
|
||||
case 'assertVisible':
|
||||
return `assertThat(${subject}.${this._asLocator(action.selector, inFrameLocator)}).isVisible();`;
|
||||
case 'assertValue': {
|
||||
const assertion = action.value ? `hasValue(${quote(action.value)})` : `isEmpty()`;
|
||||
return `assertThat(${subject}.${this._asLocator(action.selector, inFrameLocator)}).${assertion};`;
|
||||
|
|
|
|||
|
|
@ -129,6 +129,8 @@ export class JavaScriptLanguageGenerator implements LanguageGenerator {
|
|||
return `${this._isTest ? '' : '// '}await expect(${subject}.${this._asLocator(action.selector)}).${action.substring ? 'toContainText' : 'toHaveText'}(${quote(action.text)});`;
|
||||
case 'assertChecked':
|
||||
return `${this._isTest ? '' : '// '}await expect(${subject}.${this._asLocator(action.selector)})${action.checked ? '' : '.not'}.toBeChecked();`;
|
||||
case 'assertVisible':
|
||||
return `${this._isTest ? '' : '// '}await expect(${subject}.${this._asLocator(action.selector)}).toBeVisible();`;
|
||||
case 'assertValue': {
|
||||
const assertion = action.value ? `toHaveValue(${quote(action.value)})` : `toBeEmpty()`;
|
||||
return `${this._isTest ? '' : '// '}await expect(${subject}.${this._asLocator(action.selector)}).${assertion};`;
|
||||
|
|
|
|||
|
|
@ -138,6 +138,8 @@ export class PythonLanguageGenerator implements LanguageGenerator {
|
|||
return `expect(${subject}.${this._asLocator(action.selector)}).${action.substring ? 'to_contain_text' : 'to_have_text'}(${quote(action.text)})`;
|
||||
case 'assertChecked':
|
||||
return `expect(${subject}.${this._asLocator(action.selector)}).${action.checked ? 'to_be_checked()' : 'not_to_be_checked()'}`;
|
||||
case 'assertVisible':
|
||||
return `expect(${subject}.${this._asLocator(action.selector)}).to_be_visible()`;
|
||||
case 'assertValue': {
|
||||
const assertion = action.value ? `to_have_value(${quote(action.value)})` : `to_be_empty()`;
|
||||
return `expect(${subject}.${this._asLocator(action.selector)}).${assertion};`;
|
||||
|
|
|
|||
|
|
@ -29,7 +29,8 @@ export type ActionName =
|
|||
'setInputFiles' |
|
||||
'assertText' |
|
||||
'assertValue' |
|
||||
'assertChecked';
|
||||
'assertChecked' |
|
||||
'assertVisible';
|
||||
|
||||
export type ActionBase = {
|
||||
name: ActionName,
|
||||
|
|
@ -113,8 +114,13 @@ export type AssertCheckedAction = ActionBase & {
|
|||
checked: boolean,
|
||||
};
|
||||
|
||||
export type Action = ClickAction | CheckAction | ClosesPageAction | OpenPageAction | UncheckAction | FillAction | NavigateAction | PressAction | SelectAction | SetInputFilesAction | AssertTextAction | AssertValueAction | AssertCheckedAction;
|
||||
export type AssertAction = AssertCheckedAction | AssertValueAction | AssertTextAction;
|
||||
export type AssertVisibleAction = ActionBase & {
|
||||
name: 'assertVisible',
|
||||
selector: string,
|
||||
};
|
||||
|
||||
export type Action = ClickAction | CheckAction | ClosesPageAction | OpenPageAction | UncheckAction | FillAction | NavigateAction | PressAction | SelectAction | SetInputFilesAction | AssertTextAction | AssertValueAction | AssertCheckedAction | AssertVisibleAction;
|
||||
export type AssertAction = AssertCheckedAction | AssertValueAction | AssertTextAction | AssertVisibleAction;
|
||||
|
||||
// Signals.
|
||||
|
||||
|
|
|
|||
|
|
@ -29,6 +29,10 @@
|
|||
}
|
||||
|
||||
.recorder .codicon {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.recorder .codicon.circle-large-filled {
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -115,8 +115,8 @@ export const Recorder: React.FC<RecorderProps> = ({
|
|||
|
||||
return <div className='recorder'>
|
||||
<Toolbar>
|
||||
<ToolbarButton icon='circle-large-filled' title='Record' toggled={mode === 'recording' || mode === 'recording-inspecting' || mode === 'assertingText'} onClick={() => {
|
||||
window.dispatch({ event: 'setMode', params: { mode: mode === 'none' || mode === 'standby' || mode === 'inspecting' ? 'recording' : 'none' } });
|
||||
<ToolbarButton icon='circle-large-filled' title='Record' toggled={mode === 'recording' || mode === 'recording-inspecting' || mode === 'assertingText' || mode === 'assertingVisibility'} onClick={() => {
|
||||
window.dispatch({ event: 'setMode', params: { mode: mode === 'none' || mode === 'standby' || mode === 'inspecting' ? 'recording' : 'standby' } });
|
||||
}}>Record</ToolbarButton>
|
||||
<ToolbarSeparator />
|
||||
<ToolbarButton icon='inspect' title='Pick locator' toggled={mode === 'inspecting' || mode === 'recording-inspecting'} onClick={() => {
|
||||
|
|
@ -127,12 +127,16 @@ export const Recorder: React.FC<RecorderProps> = ({
|
|||
'recording': 'recording-inspecting',
|
||||
'recording-inspecting': 'recording',
|
||||
'assertingText': 'recording-inspecting',
|
||||
'assertingVisibility': 'recording-inspecting',
|
||||
}[mode];
|
||||
window.dispatch({ event: 'setMode', params: { mode: newMode } }).catch(() => { });
|
||||
}}>Pick locator</ToolbarButton>
|
||||
<ToolbarButton icon='check-all' title='Assert text and values' toggled={mode === 'assertingText'} disabled={mode === 'none' || mode === 'standby' || mode === 'inspecting'} onClick={() => {
|
||||
}}></ToolbarButton>
|
||||
<ToolbarButton icon='eye' title='Assert visibility' toggled={mode === 'assertingVisibility'} disabled={mode === 'none' || mode === 'standby' || mode === 'inspecting'} onClick={() => {
|
||||
window.dispatch({ event: 'setMode', params: { mode: mode === 'assertingVisibility' ? 'recording' : 'assertingVisibility' } });
|
||||
}}></ToolbarButton>
|
||||
<ToolbarButton icon='whole-word' title='Assert text and values' toggled={mode === 'assertingText'} disabled={mode === 'none' || mode === 'standby' || mode === 'inspecting'} onClick={() => {
|
||||
window.dispatch({ event: 'setMode', params: { mode: mode === 'assertingText' ? 'recording' : 'assertingText' } });
|
||||
}}>Assert</ToolbarButton>
|
||||
}}></ToolbarButton>
|
||||
<ToolbarSeparator />
|
||||
<ToolbarButton icon='files' title='Copy' disabled={!source || !source.text} onClick={() => {
|
||||
copy(source.text);
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ import type { Language } from '../../playwright-core/src/utils/isomorphic/locato
|
|||
|
||||
export type Point = { x: number, y: number };
|
||||
|
||||
export type Mode = 'inspecting' | 'recording' | 'none' | 'assertingText' | 'recording-inspecting' | 'standby';
|
||||
export type Mode = 'inspecting' | 'recording' | 'none' | 'assertingText' | 'recording-inspecting' | 'standby' | 'assertingVisibility';
|
||||
|
||||
export type EventData = {
|
||||
event: 'clear' | 'resume' | 'step' | 'pause' | 'setMode' | 'selectorUpdated' | 'fileChanged';
|
||||
|
|
|
|||
Loading…
Reference in a new issue