VS Code API:How to insert text in the bottom of line - vscode-extensions

I started to create an extension of VS Code and am facing a problem.
As you see in the title, I want to insert the certain text in the bottom of line. To realize this, I tried this:
let moveBy = {to: 'wrappedLineEnd', by: 'line'};
vscode.commands.executeCommand('cursorMove', moveBy);
editor.edit(editBuilder =>{
if (editor !== undefined){
editBuilder.insert(editor.selection.active, "test");
}
});
However, it does not work well; it resulted in this:
//Before: this is the text.
//cursor is between 'h' and 'i'(from 'this')
//After: thtestis is the text
//Omg 'test' is inserted here
It seems to me that the cursor did not move and it ended up inserting the string there.
Is there any solution to this?

While you can await the cursorMove command, I think it is better practice to simply compute the range at the end of the line yourself. You do not have to await moving a cursor to where you want to make an edit.
You just have to know where you want to make an edit (in case you didn't know you can make an edit anywhere in the document, there doesn't need to be a cursor there already).
const editor = vscode.window.activeTextEditor;
// let moveBy = {to: 'wrappedLineEnd', by: 'line'};
// await vscode.commands.executeCommand('cursorMove', moveBy);
// get range at end of line
const editRange = editor.document.lineAt(editor.selection.end.line).range.end;
editor.edit(editBuilder =>{
if (editor !== undefined){
// editBuilder.insert(editor.selection.active, "test");
editBuilder.insert(editRange, "test");
}
});

Related

How to get VS Code IntelliSense suggestions and print them to the screen?

I am trying to make a VS code extension.
In this extension I am interested in printing VS Code IntelliSense suggestions as an array to the debug console when the user types or ask for suggestions with ctrl+space.
Is this possible and if so where should I look?
This help me to a solution: Hook IntelliSense
let disposable2 = vscode.workspace.onDidChangeTextDocument((event) => {
const editor = vscode.window.activeTextEditor;
// the Position object gives you the line and character where the cursor is
const position = editor?.selection.active;
// Get document Uri
const docUri = editor?.document.uri;
let completionList = vscode.commands.executeCommand(
'vscode.executeCompletionItemProvider',
docUri,
position
);
completionList.then((value: any) => {
for (let i of value.items) {
console.log(i)
}
});
});

How to click on a specific TD element with puppeteer without id and name

I'm having trouble while trying to find a way to click the submenu option in this nav menu
The submenu option I want to click and the code of it
Is there a way of selecting it by it's content of it or by other alternative?
I tried await page.click(); but since i don't have any id, name or value to identify that option it automatically closes the chromium page
also tried clicking wit the content
const select = require('puppeteer-select'); const element = await select(page).getElement('div:contains(Negociação)'); await element.click(); didn't work either.
It is possible to filter certain elements by its text. Here is an example on how to select a table element and search in all its cells for a given text.
I started by writing 2 helper functions for getting text from an element and another to search text within an array of elements:
// returns text for an array of elements
async function findElementByText(elements, searchText) {
for(let el of elements) {
// get the text of the element and return
// element if text matches
const text = await getText(el)
console.log(`found text: "${text}", searchText: "${searchText}"`)
// alternatively you could use this for being a little more error tolerant
// depends on your use case and comes with some pitfalls.
// return text.toUpperCase().includes(searchText.toUpperCase())
// compare text and return element if matched
if(searchText === text) {
return el
}
}
// NO element found..
console.log('No element found by text', searchText)
return null
}
// returns text from a html element
async function getText(element) {
const textElement = await element.getProperty('textContent')
const text = await textElement.jsonValue()
// make sure to remove white spaces.
return text.trim()
}
With given helper functions you can now select the table and search within its td elements (the cells) .
// This selects the first found table. You may wanna grab the correct table by a classname.
const table = await page.$('table')
// select all cells in the table.
const cells = await table.$$('td')
// search in the cells for a given text. "cell" will be a JSHandle
// which can be clicked!
const searchText = 'text4'
const cell = await findElementByText(cells, searchText)
if(!cell) {
throw 'Cell with text ' + searchText + ' not found!!.'
}
console.log('clicking cell now.')
// click the element
await cell.click()
If you host the html yourselve it would make life easier by setting a classname OR id to the cells you wanna click. (only if allowed and possible ofc) .
In your next question you should provide the html as plaint text instead of an image. Plain text can easily be copied by other users to test and debug.
Feel free to leave a comment.

Unable to interact with elments using $$ sign in WebdriverIO

I'm using WebdrivreIO(v7) but unable to export $$ value from another file. If I'm working with the same file it's working fine, but another file not working. not sure what's wrong here
sample.js
module.exports = {
details: $$('.agent-rows p.name'),
}
script_file.js
When("Getting the list from the listing page"){
const sample=require("./sample.js");
console.log("value 1"+ await sample.details) // Output : nothing empty
console.log("value 2"+ await sample.details[0]) // Output : undefined
}
are you sure you are not doing any thing between constant sample, console.log lines? require will trigger the details property as soon as you call it .
so if you are trying the below thing , it won't work
const elem = sample.details
//do something for the element to be present
(await elem)[0].dosomething
because sample.details will trigger the fetch process before the element is present. await is used to wait for an async process to complete, not to trigger it.
use instead:
module.exports = {
details: ()=>{$$('.agent-rows p.name')},
}
in code:
const elem = sample.details
//do something for the element to be present
(await elem())[0].dosomething //here you are triggering the fetch
It seems you have a typo s. It should be sample.detail not sample.details.
When("Getting the list from the listing page"){
const sample=require("./sample.js");
console.log("value 1"+ await sample.detail) // 'detail' not 'details'
}

How to prevent closing of cell edit mode on validation errors with custom vue components in ag-grid

I have succesfully rendered my own component as the cellEditor and would like and on-leave I would like it to try to validate the value and prevent the closing if it fails.
If I look at this then https://www.ag-grid.com/javascript-grid-cell-editing/#editing-api there's cancelable callback functions for editing. But in this callback function is there a way to access the current instantiated component? I would think that would be the easiest way to handle this.
I'm using vee-validate so the validation function is async, just to keep in mind.
Use Full row editing.
Create a global variable like
var problemRow = -1;
Then Subscribe to this events:
onRowEditingStarted: function (event) {
if (problemRow!=-1 && event.rowIndex!=problemRow) {
gridOptions.api.stopEditing();
gridOptions.api.startEditingCell({
rowIndex: problemRow,
colKey: 'the column you want to focus',
});
}
},
onRowEditingStopped: function (event) {
if (problemRow==-1) {
if (event.data.firstName != "your validation") {
problemRow = event.rowIndex
gridOptions.api.startEditingCell({
rowIndex: problemRow,
colKey: 'the column you want to focus',
});
}
}
if (problemRow == event.rowIndex) {
if (event.data.firstName != "your validation") {
problemRow = event.rowIndex
gridOptions.api.startEditingCell({
rowIndex: problemRow,
colKey: 'the column you want to focus',
});
}
else{
problemRow=-1;
}
}
},
I had a similar issue - albeit in AngularJS and the non-Angular mode for ag-grid - I needed to prevent the navigation when the cell editor didn't pass validation.
The documentation is not very detailed, so in the end I added a custom cell editor with a form wrapped around the input field (to handle the niceties such as red highlighting etc), and then used Angular JS validation. That got me so far, but the crucial part was trying to prevent the user tabbing out or away when the value was invalid so the user could at least fix the issue.
I did this by adding a value parser when adding the cell, and then within that if the value was invalid according to various rules, throw an exception. Not ideal, I know - but it does prevent ag-grid from trying to move away from the cell.
I tried loads of approaches to solving this - using the tabToNextCell events, suppressKeyboardEvent, navigateToNextCell, onCellEditingStopped - to name a few - this was the only thing that got it working correctly.
Here's my value parser, for what it's worth:
var codeParser = function (args) {
var cellEditor = _controller.currentCellEditor.children['codeValue'];
var paycodeId = +args.colDef.field;
var paycodeInfo = _controller.paycodes.filter(function (f) { return f.id === paycodeId; })[0];
// Check against any mask
if (paycodeInfo && paycodeInfo.mask) {
var reg = new RegExp("^" + paycodeInfo.mask + '$');
var match = args.newValue.match(reg);
if (!match) {
$mdToast.show($mdToast.simple().textContent('Invalid value - does not match paycode format.').position('top right').toastClass('errorToast'))
.then(function(r) {
_controller.currentCellEditor.children['codeValue'].focus();
});
throw 'Invalid value - does not match paycode format.';
}
}
return true;
};
The _controller.currentCellEditor value is set during the init of the cell editor component. I do this so I can then refocus the control after the error has been shown in the toast:
CodeValueEditor.prototype.init = function (params) {
var form = document.createElement('form');
form.setAttribute('id', 'mainForm');
form.setAttribute('name', 'mainForm');
var input = document.createElement('input');
input.classList.add('ag-cell-edit-input');
input.classList.add('paycode-editor');
input.setAttribute('name', 'codeValue');
input.setAttribute('id', 'codeValue');
input.tabIndex = "0";
input.value = params.value;
if (params.mask) {
input.setAttribute('data-mask', params.mask);
input.setAttribute('ng-pattern','/^' + params.mask + '$/');
input.setAttribute('ng-class',"{'pattern-error': mainForm.codeValue.$error.pattern}");
input.setAttribute('ng-model', 'ctl.currentValue');
}
form.appendChild(input);
this.container = form;
$compile(this.container)($scope);
_controller.currentValue = null;
// This is crucial - we can then reference the container in
// the parser later on to refocus the control
_controller.currentCellEditor = this.container;
$scope.$digest();
};
And then cleared in the grid options onCellEditingStopped event:
onCellEditingStopped: function (event) {
$scope.$apply(function() {
_controller.currentCellEditor = null;
});
},
I realise it's not specifically for your components (Vue.js) but hopefully it'll help someone else. If anyone has done it a better way, I'm all ears as I don't like throwing the unnecessary exception!

Checking button text matches a certain string in Nightwatch.js

I'm having a heck of a time trying to write a test where I check that text on a button matches a certain string. I tried ".valueContains", ".attributeContains" and got blank or null, and I've tried getText(), but that only seems to return an object.
I feel like it's something obvious I'm missing, so any help would be appreciated!
Based on what you have written so far in your question, I am wondering if there is there a reason you cannot use .containsText?
.waitForElementVisible('.yourclass', this.timeout)
.assert.containsText('.yourclass', 'Text of Button you expect to match')
http://nightwatchjs.org/api#assert-containsText
Without actually looking at the code its little difficult to predict whats going on. However all of the methods in selenium return a promise, so you need to wait for it to resolve.
function async getTextOfButton() {
const element = await driver.findElement(By.className('item-class'));
const text = await element.getText();
}
If you are not using async/await you could do
driver.findElement(By.className('item-class')).then(function(element) {
element.getText().then(function(text) {
console.log(text);
});
});