feat: support newlines in headers, params, and variables (#5795)

* feat: support newlines in headers, params, and variables

* add: collectin unit test

* fix: assertion and additional header multiline

* fix: assert

* rm: useEffect for header validation

* rm: comments

* fix: already encoded url

* rm: new line changes

* handle new line in url

* fix: lint error

* add: unit test for multi line test

* change: unit test

* mv: functions in util

* fix: drag icon position

* improve: arrow height

* improvements

* rm: getKeyString from assert

* fix: single line editor

* fix: import MultiLineEditor

* import getKeyString and getValueUrl

* add: getTableCell in utils

* rm: multiline key logic

* fix

* mv: getTableCell in locators.ts
This commit is contained in:
Pooja
2025-11-17 13:27:00 +05:30
committed by GitHub
parent 2be602d16c
commit 8c7888533a
20 changed files with 537 additions and 83 deletions

View File

@@ -99,6 +99,11 @@ class SingleLineEditor extends Component {
this.addOverlay(variables);
this._enableMaskedEditor(this.props.isSecret);
this.setState({ maskInput: this.props.isSecret });
// Add newline arrow markers if enabled
if (this.props.showNewlineArrow) {
this._updateNewlineMarkers();
}
}
/** Enable or disable masking the rendered content of the editor */
@@ -123,6 +128,11 @@ class SingleLineEditor extends Component {
if (this.props.onChange && (this.props.value !== this.cachedValue)) {
this.props.onChange(this.cachedValue);
}
// Update newline markers after edit
if (this.props.showNewlineArrow) {
this._updateNewlineMarkers();
}
}
};
@@ -145,6 +155,11 @@ class SingleLineEditor extends Component {
if (this.props.value !== prevProps.value && this.props.value !== this.cachedValue && this.editor) {
this.cachedValue = String(this.props.value);
this.editor.setValue(String(this.props.value ?? ''));
// Update newline markers after value change
if (this.props.showNewlineArrow) {
this._updateNewlineMarkers();
}
}
if (!isEqual(this.props.isSecret, prevProps.isSecret)) {
// If the secret flag has changed, update the editor to reflect the change
@@ -162,6 +177,7 @@ class SingleLineEditor extends Component {
if (this.editor) {
this.editor.off('change', this._onEdit);
this.editor.off('paste', this._onPaste);
this._clearNewlineMarkers();
this.editor.getWrapperElement().remove();
this.editor = null;
}
@@ -180,6 +196,63 @@ class SingleLineEditor extends Component {
this.editor.setOption('mode', 'brunovariables');
};
/**
* Update markers to show arrows for newlines
*/
_updateNewlineMarkers = () => {
if (!this.editor) return;
// Clear existing markers
this._clearNewlineMarkers();
this.newlineMarkers = [];
const content = this.editor.getValue();
// Find all newlines and replace them with arrow widgets
for (let i = 0; i < content.length; i++) {
if (content[i] === '\n') {
const pos = this.editor.posFromIndex(i);
const nextPos = this.editor.posFromIndex(i + 1);
// Create a widget to display the arrow
const arrow = document.createElement('span');
arrow.className = 'newline-arrow';
arrow.textContent = '↲';
arrow.style.cssText = `
color: #888;
font-size: 8px;
margin: 0 2px;
vertical-align: middle;
display: inline-block;
`;
// Mark the newline character and replace it with the arrow widget
const marker = this.editor.markText(pos, nextPos, {
replacedWith: arrow,
handleMouseEvents: true
});
this.newlineMarkers.push(marker);
}
}
};
/**
* Clear all newline markers
*/
_clearNewlineMarkers = () => {
if (this.newlineMarkers) {
this.newlineMarkers.forEach((marker) => {
try {
marker.clear();
} catch (e) {
// Marker might already be cleared
}
});
this.newlineMarkers = [];
}
};
toggleVisibleSecret = () => {
const isVisible = !this.state.maskInput;
this.setState({ maskInput: isVisible });
@@ -204,13 +277,15 @@ class SingleLineEditor extends Component {
render() {
return (
<div className={`flex flex-row justify-between w-full overflow-x-auto ${this.props.className}`}>
<div className={`flex flex-row items-center w-full overflow-x-auto ${this.props.className}`}>
<StyledWrapper
ref={this.editorRef}
className={`single-line-editor grow ${this.props.readOnly ? 'read-only' : ''}`}
{...(this.props['data-testid'] ? { 'data-testid': this.props['data-testid'] } : {})}
/>
{this.secretEye(this.props.isSecret)}
<div className="flex items-center">
{this.secretEye(this.props.isSecret)}
</div>
</div>
);
}