How to give a time delay in Visual Studio macros - visual-studio

Recently I updated my Visual Studio and start using the extention Macro Explorer.
I tried to use one of the sample macros "removes and sorts all", but I realized if I have a open documents, it doesn't run. So I closed all my open documents and try again this time it open all documents and close them but it doesn't work either.
The problem is the command executed before the document completely load. If there was a event or timer that can help wait until document load completely the problem will solve.
Here is my code. I marked where I want to add wait function:
function formatFile(file) {
dte.ExecuteCommand("View.SolutionExplorer");
if (file.Name.indexOf(".cs", file.Name.length - ".cs".length) !== -1) {
file.Open();
file.Document.Activate();
//here i want to wait for 1 second
dte.ExecuteCommand("Edit.RemoveAndSort");
file.Document.Save();
file.Document.Close();
}
}
I appreciate any sort of help.
Macro Explorer on GitHub: https://github.com/Microsoft/VS-Macros

According to the code snippet you shared in your original post and I also clone the project from GitHub, your code should be JavaScript code.
In JavaScript code, there has setTimeout() or setInterval() functions. For example, if you use setTimeout(), you need to move the code that you need to run after the pause into the setTimeout() callback.
Please modify your code as below.
function formatFile(file) {
dte.ExecuteCommand("View.SolutionExplorer");
if (file.Name.indexOf(".cs", file.Name.length - ".cs".length) !== -1) {
file.Open();
file.Document.Activate();
setTimeout(function () {
//move the code that you want to run after 1 second
dte.ExecuteCommand("Edit.RemoveAndSort");
file.Document.Save();
file.Document.Close();
}, 1000);
}
And there are lots of thread about sleep() in Javascript code. Please refer to:
What is the JavaScript version of sleep()?
JavaScript sleep/wait before continuing

Related

Cypress: How to capture text from a selector on one page to use as text on another page

New cypress user here, I am aware that cypress does not handle variables like how testcafe and others do due to the asyn nature of it. Using the example given and what I could find I have this as an example:
cy.get('selector').invoke('text').as('text_needed')
cy.get('#text_needed')
const txtneeded = this.text_needed
cy.log(txtneeded)
This looks at a given selector, takes what it finds and uses it as text and set it as a variable usable at any time in the test and outputs it to the log. The plan is to use that text in a search filter in another page to find the item it references.
The problem is that it fails with Cannot read properties of undefined (reading 'text_needed')
Is this because the content of the selector is not assigned to text properly, the outer html is <a data-v-78d50a00="" data-v-3d3629a7="" href="#">PO90944</a> The PO90944 is what I want to capture.
Your help would be appreciated!
You cannot save an alias and access it via this.* in the same execution context (callback) because it's a synchronous operation and your alias is not yet resolved at this time.
This is a correct way to go:
cy.get('selector').invoke('text').as('text_needed')
cy.get('#text_needed').then(txtneeded => {
cy.log(txtneeded)
})
First, make sure to define it as traditional function, not as an arrow function as this context doesn't work as you'd expect there, more info here.
Next, typically in a single test you should use .then() callback to perform additional actions on elements, and use aliases when you need to share context between hooks or different tests, so please consider the following:
// using aliases together with this within the single test won't work
cy.get(<selector>).invoke('text').as('text_needed')
cy.get('#text_needed').should('contain', 'PO90944') // works fine
cy.log(this.text_needed) // undefined
// this will work as expected
cy.get(<selector>).invoke('text').then(($el) => {
cy.wrap($el).should('contain', 'PO90944'); // works fine
cy.log($el) // works fine
});
Setting alias in beforeEach hook for example, would let you access this.text_needed in your tests without problems.
Everything nicely explained here.
Edit based on comments:
it('Some test', function() {
cy.visit('www.example.com');
cy.get('h1').invoke('text').as('someVar');
});
it('Some other test', function() {
cy.visit('www.example.com');
cy.log('I expect "Example Domain" here: ' + this.someVar);
});
And here's the output from cypress runner:

Cypress command vs JS function

The Cypress documentation suggests that commands are the right way to reuse fragments of code, e.g.
Cypress.Commands.add("logout", () => {
cy.get("[data-cy=profile-picture]").click();
cy.contains("Logout").click();
});
cy.logout();
For simple cases like this, why would I use a command over a plain JS function (and all the nice IDE assistance that comes with it). What are the drawbacks of rewriting the above snippet as
export function logout(){
cy.get("[data-cy=profile-picture]").click();
cy.contains("Logout").click();
}
// and now somewhere in a test
logout();
Based on my experience with Cypress (one year project and several hundred test cases), I can say that a plan JS function is great for grouping cy commands.
From my point of view, a custom cy command may be really useful only if it is incorporated into the chain processing (utilizes the subject parameter or returns a Chainable to be used further in the chain). Otherwise, a plain JS function is preferable due to it simplicity and full IDE support (unless you're using an additional plugin).
If you for any reason need to do something inside the cypress loop, you can always wrap you code by cy.then() in a plain JS function:
function myFunction() {
cy.then(() => {
console.log(("I'm inside the Cypress event loop"))
})
}
Commands are for behavior that is needed across all tests. For example, cy.setup or cy.login. Otherwise, use functions.
See official docs: https://docs.cypress.io/api/cypress-api/custom-commands#1-Don-t-make-everything-a-custom-command

Tips on solving 'DevTools was disconnected from the page' and Electron Helper dies

I've a problem with Electron where the app goes blank. i.e. It becomes a white screen. If I open the dev tools it displays the following message.
In ActivityMonitor I can see the number of Electron Helper processes drops from 3 to 2 when this happens. Plus it seems I'm not the only person to come across it. e.g.
Facing "Devtools was disconnected from the page. Once page is reloaded, Devtools will automatically reconnect."
Electron dying without any information, what now?
But I've yet to find an answer that helps. In scenarios where Electron crashes are there any good approaches to identifying the problem?
For context I'm loading an sdk into Electron. Originally I was using browserify to package it which worked fine. But I want to move to the SDKs npm release. This version seems to have introduced the problem (though the code should be the same).
A good bit of time has passed since I originally posted this question. I'll answer it myself in case my mistake can assist anyone.
I never got a "solution" to the original problem. At a much later date I switched across to the npm release of the sdk and it worked.
But before that time I'd hit this issue again. Luckily, by then, I'd added a logger that also wrote console to file. With it I noticed that a JavaScript syntax error caused the crash. e.g. Missing closing bracket, etc.
I suspect that's what caused my original problem. But the Chrome dev tools do the worst thing by blanking the console rather than preserve it when the tools crash.
Code I used to setup a logger
/*global window */
const winston = require('winston');
const prettyMs = require('pretty-ms');
/**
* Proxy the standard 'console' object and redirect it toward a logger.
*/
class Logger {
constructor() {
// Retain a reference to the original console
this.originalConsole = window.console;
this.timers = new Map([]);
// Configure a logger
this.logger = winston.createLogger({
level: 'info',
format: winston.format.combine(
winston.format.timestamp(),
winston.format.printf(({ level, message, timestamp }) => {
return `${timestamp} ${level}: ${message}`;
})
),
transports: [
new winston.transports.File(
{
filename: `${require('electron').remote.app.getPath('userData')}/logs/downloader.log`, // Note: require('electron').remote is undefined when I include it in the normal imports
handleExceptions: true, // Log unhandled exceptions
maxsize: 1048576, // 10 MB
maxFiles: 10
}
)
]
});
const _this = this;
// Switch out the console with a proxied version
window.console = new Proxy(this.originalConsole, {
// Override the console functions
get(target, property) {
// Leverage the identical logger functions
if (['debug', 'info', 'warn', 'error'].includes(property)) return (...parameters) => {
_this.logger[property](parameters);
// Simple approach to logging to console. Initially considered
// using a custom logger. But this is much easier to implement.
// Downside is that the format differs but I can live with that
_this.originalConsole[property](...parameters);
}
// The log function differs in logger so map it to info
if ('log' === property) return (...parameters) => {
_this.logger.info(parameters);
_this.originalConsole.info(...parameters);
}
// Re-implement the time and timeEnd functions
if ('time' === property) return (label) => _this.timers.set(label, window.performance.now());
if ('timeEnd' === property) return (label) => {
const now = window.performance.now();
if (!_this.timers.has(label)) {
_this.logger.warn(`console.timeEnd('${label}') called without preceding console.time('${label}')! Or console.timeEnd('${label}') has been called more than once.`)
}
const timeTaken = prettyMs(now - _this.timers.get(label));
_this.timers.delete(label);
const message = `${label} ${timeTaken}`;
_this.logger.info(message);
_this.originalConsole.info(message);
}
// Any non-overriden functions are passed to console
return target[property];
}
});
}
}
/**
* Calling this function switches the window.console for a proxied version.
* The proxy allows us to redirect the call to a logger.
*/
function switchConsoleToLogger() { new Logger(); } // eslint-disable-line no-unused-vars
Then in index.html I load this script first
<script src="js/logger.js"></script>
<script>switchConsoleToLogger()</script>
I had installed Google Chrome version 79.0.3945.130 (64 bit). My app was going to crash every time when I was in debug mode. I try all the solutions I found on the web but no one was useful. I downgrade to all the previous version:
78.x Crashed
77.x Crashed
75.x Not Crashed
I had to re-install the version 75.0.3770.80 (64 bit). Problem has been solved. It can be a new versions of Chrome problem. I sent feedback to Chrome assistence.
My problem was that I was not loading a page such as index.html. Once I loaded problem went away.
parentWindow = new BrowserWindow({
title: 'parent'
});
parentWindow.loadURL(`file://${__dirname}/index.html`);
parentWindow.webContents.openDevTools();
The trick to debugging a crash like this, is to enable logging, which is apparently disabled by default. This is done by setting the environment variable ELECTRON_ENABLE_LOGGING=1, as mentioned in this GitHub issue.
With that enabled, you should see something along the lines of this in the console:
You can download Google Chrome Canary. I was facing this problem on Google Chrome where DevTools was crashing every time on the same spot. On Chrome Canary the debugger doesn't crash.
I also faced the exact same problem
I was trying to require sqlite3 module from renderer side
which was causing a problem but once i removed the request it was working just fine
const {app , BrowserWindow , ipcMain, ipcRenderer } = require('electron')
const { event } = require('jquery')
const sqlite3 = require('sqlite3').verbose(); // <<== problem
I think the best way to solve this (if your code is really really small) just try to remove functions and run it over and over again eventually you can narrow it down to the core problem
It is a really tedious , dumb and not a smart way of doing it , but hey it worked
I encountered this issue, and couldn't figure out why the the DevTool was constantly disconnecting. So on a whim I launched Firefox Developer edition and identified the cause as an undefined variable with a string length property.
if ( args.length > 1 ) {
$( this ).find( "option" ).each(function () {
$( $( this ).attr( "s-group" ) ).hide();
});
$( args ).show();
}
TL;DR Firefox Developer edition can identify these kinds of problems when Chrome's DevTool fails.
After reading the comments above it is clear to me that there is a problem at least in Chrome that consists of not showing any indication of what the fault comes from. In Firefox, the program works but with a long delay.
But, as Shane Gannon said, the origin of the problem is certainly not in a browser but it is in the code: in my case, I had opened a while loop without adding the corresponding incremental, which made the loop infinite. As in the example below:
var a = 0;
while (a < 10) {
...
a ++ // this is the part I was missing;
}
Once this was corrected, the problem disappeared.
I found that upgrading to
react 17.0.2
react-dom 17.0.2
react-scripts 4.0.3
but also as react-scripts start is being used to run electron maybe its just react scripts that needs updating.
Well I nearly went crazy but with electron the main problem I realized I commented out the code to fetch (index.html)
// and load the index.html of the app.
mainWindow.loadFile('index.html');
check this side and make sure you have included it. without this the page will go black or wont load. so check your index.js to see if there's something to load your index.html file :) feel free to mail : profnird#gmail.com if you need additional help
Downgrade from Electron 11 to Electron 8.2 worked for me in Angular 11 - Electron - Typeorm -sqlite3 app.
It is not a solution as such, but it is an assumption of why the problem.
In the angular 'ngOnInit' lifecycle I put too many 'for' and 'while' loops, one inside the other, after cleaning the code and making it more compact, the problem disappeared, I think maybe because it didn't finish the processes within a time limit I hope someone finds this comment helpful. :)
I have stumbled upon the similar problem, My approach is comment out some line that I just added to see if it works. And if that is the case, those problem is at those lines of code.
for(var i = 0;i<objLen; i+3 ){
input_data.push(jsonObj[i].reading2);
input_label.push(jsonObj[i].dateTime);
}
The console works fine after i change the code to like this.
for(var i = 0;i<objLen; i=i+space ){
input_data.push(jsonObj[i].reading2);
input_label.push(jsonObj[i].dateTime);
}
Open your google dev console (Ctrl + shift + i). Then press (fn + F1) or just F1, then scroll down and click on the Restore defaults and reload.

Solution for Dexie.js debugging code taking over on deferred promises

I'm using Dexie.js for handling indexed storage. However, it would take over exception handling on any process launched by the deferred promise. This made it very difficult to catch the bugs where they happened.
This is what works. I would love to get input from other developers if this is a good idea.
function isolate(deferred) {
return {
exec: function() {
var args = arguments;
var timeout = setTimeout(function() {
deferred.apply(this, args);
clearTimeout(timeout);
},1);
}
};
}
function save(name, drawing, data, onComplete) {
return db.drawings.put(
{ name: name, drawing, data: data
).then(isolate(onComplete).exec);
}
This way the promise function completes, Dexie.js is very happy about it, and then a new one starts in the timeout, which Dexie (or any other promise style handler) doesn't care about anymore.
If you need to debug your code and break when an error occurs, you can do that also in Promise-based code without having to do your suggested workaround.
In the F12 debugger in Chrome, check "Pause on caught exceptions". Also make sure to blackbox 3rd part libs so you don't end up breaking on feature testings in babel, jquery, dexie. This is simply done by right-clicking somewhere on the script code (when debugger breaks into it) and choose "blackbox". (Make sure NOT to blackbox your own code though!)
Now the debugger will break when an error occur in your code no matter if it's launched from a promise callback.

Adding custom code to mootools addEvent

Even though I've been using mootools for a while now, I haven't really gotten into playing with the natives yet. Currently I'm trying to extend events by adding a custom addEvent method beside the original. I did that using the following code(copied from mootools core)
Native.implement([Element, Window, Document], {
addMyEvent:function(){/* code here */}
}
Now the problem is that I can't seem to figure out, how to properly overwrite the existing fireEvent method in a way that I can still call the orignal method after executing my own logic.
I could probably get the desired results with some ugly hacks but I'd prefer learning the elegant way :)
Update: Tried a couple of ugly hacks. None of them worked. Either I don't understand closures or I'm tweaking the wrong place. I tried saving Element.fireEvent to a temporary variable(with and without using closures), which I would then call from the overwritten fireEvent function(overwritten using Native.implement - the same as above). The result is an endless loop with fireEvent calling itself over and over again.
Update 2:
I followed the execution using firebug and it lead me to Native.genericize, which seems to act as a kind of proxy for the methods of native classes. So instead of referencing the actual fireEvent method, I referenced the proxy and that caused the infinite loop. Google didn't find any useful documentation about this and I'm a little wary about poking around under the hood when I don't completely understand how it works, so any help is much appreciated.
Update 3 - Original problem solved:
As I replied to Dimitar's comment below, I managed to solve the original problem by myself. I was trying to make a method for adding events that destroy themselves after a certain amount of executions. Although the original problem is solved, my question about extending natives remain.
Here's the finished code:
Native.implement([Element, Window, Document], {
addVolatileEvent:function(type,fn,counter,internal){
if(!counter)
counter=1;
var volatileFn=function(){
fn.run(arguments);
counter-=1;
if(counter<1)
{
this.removeEvent(type,volatileFn);
}
}
this.addEvent(type,volatileFn,internal);
}
});
is the name right? That's the best I could come up with my limited vocabulary.
document.id("clicker").addEvents({
"boobies": function() {
console.info("nipple police");
this.store("boobies", (this.retrieve("boobies")) ? this.retrieve("boobies") + 1 : 1);
if (this.retrieve("boobies") == 5)
this.removeEvents("boobies");
},
"click": function() {
// original function can callback boobies "even"
this.fireEvent("boobies");
// do usual stuff.
}
});
adding a simple event handler that counts the number of iterations it has gone through and then self-destroys.
think of events as simple callbacks under a particular key, some of which are bound to particular events that get fired up.
using element storage is always advisable if possible - it allows you to share data on the same element between different scopes w/o complex punctures or global variables.
Natives should not be modded like so, just do:
Element.implement({
newMethod: function() {
// this being the element
return this;
}
});
document.id("clicker").newMethod();
unless, of course, you need to define something that applies to window or document as well.

Resources