Is it possible to call methods dynamically? - javascript

I have 73 methods to execute in one test case[This is test to verify Auto merge rules in Salesforce]
As of now i am calling in the below manner :
SFHomePage rule_Test = new SFHomePage(driver, test);
PageFactory.initElements(driver, rule_Test);
test.log(LogStatus.INFO, "About to start validation of Rule 1");
rule_Test.verifyRule1(); // Calling the method to verify Rule 1
test.log(LogStatus.INFO, "Verification for Rule 1 is completed");
as mentioned in the above code i have to call all the 73 rules dynamically.
All the rules have separate methods to maintain the accountability.
I just tried the below manner but i know this will not work :
for(int i=1;i<43;i++)
{
test.log(LogStatus.INFO, "About to start validation of Rule "+i);
rule_Test.verifyRule+i(); // Calling the method to verify Rule
test.log(LogStatus.INFO, "Verification for Rule"+i+" is completed");
}
Is there any way to call these methods dynamically ?

You could use reflection API and getMethod(String name, Class<?>... parameterTypes). With this you could dynamically change method name and then invoke it. Heres the example:
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class Test {
private final Logger logger = LoggerFactory.getLogger(getClass());
public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException,
IllegalAccessException {
Test test = new Test();
for(int i = 1; i < 3; i++) {
String methodName = "verifyRule"+i;
Method method = test.getClass()
.getMethod(methodName);
method.invoke(test);
}
}
public Test() {
}
public void verifyRule1() {
logger.info("Verified rule 1");
}
public void verifyRule2() {
logger.info("Verified rule 2");
}
}
Result:
Connected to the target VM, address: '127.0.0.1:52987', transport: 'socket'
14:36:47.243 [main] INFO Test - Verified rule 1
14:36:47.293 [main] INFO Test - Verified rule 2
Disconnected from the target VM, address: '127.0.0.1:52987', transport: 'socket'
Process finished with exit code 0

There is a way to invoke a method when method name is in string variable. You fetch the class then fetch the method then invoke the method. You can create loop and change the number in the end of the method name string everytime.
// get class.
Class<?> myClass = Class.forName("MyClassName");
// create object of class.
Object myClassObject= myClass.newInstance();
// get method from MyClassName class.
Method myMethod = myClassObject.getClass().getMethod("myMethodName");
// call/invoke myMethodName method.
myMethod.invoke(myClassObject);

Related

Node.js how to take a class method argument and use it to call "this.argument"

hey guys i have a question. So i have a class in nodejs and in the constructor i initialiuse a few smart contracts from uniswap. However i am making a function that takes in as a parameter on one the smart contratcs that i initialise in the constructor. however when I i try to call the method and pass in the uniswapFactoryContract as an arg called "echangeName", node takes this.exchangeName asit is, but instead of taking exchangeName as the arg i pass in it takes it as this.echangeName not this.TheNameOfTheArgIPassIn. My code is below could anyone help me or provide another way
module.exports =class Registry {
constructor() {
//default token addresses
this.DAI = "0x6b175474e89094c44da98b954eedeac495271d0f";
this.WETH = "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2";
//default provided exhange addressses
this.UniswapFactoryAddress = "0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f";
this.UniswapRouterAddress = "0xf164fC0Ec4E93095b804a4795bBe1e041497b92a";
}
//when i call this in index.js i specifcy the uniswapFactoryaddress as the exchange name paramrer
async getTokenPairSddress(addressToken0, addressToken1, exchangeName) {
//this line throws the error it thinks i want this.echange name instead of
//this.uniswapFactoryContract
const pairAddress = await this.exchangeName.methods.getPair(addressToken0, addressToken1).call();
return pairAddress;
}
}

Blazor, how to constantly get currentWindow width?

I want to do something like this in a razor page:
#if (currentwidth<x)
{
le code
}
else
{
le other code
}
I have added javascript file and connected it to a utility service which works when I get the static width (which I tested).
js:
export function getCurrentWidth() {
return window.addEventListener("resize", () => {
window.innerWidth;
});
}
UtilityService method:
public async Task<double> GetCurrentWidth()
{
var m = await GetModule();
var result = await m.InvokeAsync<double>("getCurrentWidth");
return result;
}
Razor file:
double width;
protected async override Task OnInitializedAsync()
{
width = await utilityService.GetCurrentWidth();
}
Thus the problem is I can't call it from OnInitailzedAsync since this function only fired once, so I need a function that constantly checks the GetCurrentWIdth() method to check for resize.
Is there another way of doing this in blazor or what method could I use/ Thank you in advance.
First of all I'd like to point out that you may not have to solve your problem with javascript/C# code. If it's something in the html that you want to manipulate, you may just be better of using css. But I'll leave that up to you.
If however you truly need the window width like you mentioned above, then I would recommend registering a listener to the window (as you've already done) and have that listener call a dotnet function. Doing this with static methods is quite easy, but for instance component this can be a bit trickier as you have to pass an object reference of the current object.
The [JsInvokable] indicates that this method can be called from javascript, which allows communication from the javascript event listener to dotnet.
CSharpFromJs.razor.cs
using Microsoft.AspNetCore.Components;
using Microsoft.JSInterop;
using System.Threading.Tasks;
public partial class CSharpFromJS
{
private DotNetObjectReference<CSharpFromJS> _objectReference;
public int WindowWidth { get; set; }
[Inject]
public IJSRuntime JSRuntime { get; set; }
protected override void OnInitialized()
{
_objectReference = DotNetObjectReference.Create(this);
}
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
await InitWindowWidthListener();
}
}
[JSInvokable]
public void UpdateWindowWidth(int windowWidth)
{
WindowWidth = windowWidth;
StateHasChanged();
}
private async Task InitWindowWidthListener()
{
await JSRuntime.InvokeVoidAsync("AddWindowWidthListener", _objectReference);
}
public async ValueTask DisposeAsync()
{
await JSRuntime.InvokeVoidAsync("RemoveWindowWidthListener", _objectReference);
_objectReference?.Dispose();
}
}
CSharpFromJs.razor
#implements IAsyncDisposable
<h1>Window width: #WindowWidth</h1>
Javascript
// Manages the registered event listeners so they can be disposed later
let windowEventListeners = {};
function AddWindowWidthListener(objReference) {
let eventListener = () => UpdateWindowWidth(objReference);
window.addEventListener("resize", eventListener);
windowEventListeners[objReference] = eventListener;
}
function RemoveWindowWidthListener(objReference) {
window.removeEventListener("resize", windowEventListeners[objReference]);
}
function UpdateWindowWidth(objReference) {
objReference.invokeMethodAsync("UpdateWindowWidth", window.innerWidth);
}
The only thing you should be careful with is when a component is disposd. You should remove the registered handlers in the DisposeAsync function to ensure that they're not still registered to prevent memory leaks.
This link might provide some better instructions on how to use this, but they don't explain the part about disposing handlers.
Note: This only works in .net5 and later, as IAsyncDisposable was not yet implemented for component before that. If for some reason you're working with an earlier version, you could call it using IDisposable. But this could potentially cause deadlocks, so I would not recommend it.
For me works the NuGet package BlazorPro.BlazorSize
Implement the method:
async void WindowResized(object _, BrowserWindowSize window){}
and all necessary Dependencies (see description).

How to inherit from WebElement in WebdriverIO

I looking for a way to inherit from WebElement object that webdriverio returns, without monkey-patching and with TS types support (autocompletion is a must). Is there a way to do something like this?
class Checkbox extends WebdriverIOWebElement {
constructor() {
super($('div'))
}
// overriding base method
isDisplayed(): boolean {
// blabla some new logic here
}
check() {
if(!this.isChecked()) {
this.click()
}
}
uncheck() {
if(this.isChecked()) {
this.click()
}
}
}
Lets take an example , When we have a New Tag (my-app) in HTML and we have to build a case to Login using webdriverIO ,
Assume this is the HTML :
What we would do is using the component object pattern , component object pattern attempts to reduce that repetition and move the component's api into an object of its own. We know that in order to interact with an element's shadow DOM, we first need the host element. Using a base class for your component objects makes this pretty straightforward.
Here's a bare-bones component base class that takes the host element in its constructor and unrolls that element's queries up to the browser object, so it can be reused in many page objects (or other component objects), without having to know anything about the page itself.
class Component {
constructor(host) {
const selectors = [];
// Crawl back to the browser object, and cache all selectors
while (host.elementId && host.parent) {
selectors.push(host.selector);
host = host.parent;
}
selectors.reverse();
this.selectors_ = selectors;
}
get host() {
// Beginning with the browser object, reselect each element
return this.selectors_.reduce((element, selector) => element.$(selector), browser);
}
}
module.exports = Component;
then what we would do is , We will write a subclass for our app-login component:
const Component = require('./component');
class Login extends Component {
get usernameInput() {
return this.host.shadow$('input #username');
}
get passwordInput() {
return this.host.shadow$('input[type=password]');
}
get submitButton() {
return this.login.shadow$('button[type=submit]');
}
login(username, password) {
this.usernameInput.setValue(username);
this.passwordInput.setValue(password);
this.submitButton.click();
}
}
module.exports = Login;
Finally, we can use the component object inside our login page object:
const Login = require('./components/login');
class LoginPage {
open() {
browser.url('/login');
}
get app() {
return browser.$('my-app');
}
get loginComponent() {
// return a new instance of our login component object
return new Login(this.app.$('app-login'));
}
}
Now this component object can now be used in tests for any page or section of your app that uses an app-login web component, without having to know about how that component is structured. If you later decide to change the internal structure of the web component, you only need to update the component object.
Now we apply the same approach with the Check Box Component by using Shadow Dom Support :
public class CheckBox extends Component {
public CheckBox(element) {
this.element = element;
}
get checkBoxSelector() {
return this.host.shadow$(element);
}
get void toggle() {
checkBoxSelector().click();
}
get void check() {
if (!isChecked()) {
toggle();
}
}
get void uncheck() {
if (isChecked()) {
toggle();
}
}
get boolean isChecked() {
return checkBoxSelector().isSelected();
}
}
Then We can write a Check Box Controller component that can get the instance of check box using id and verify what every is necessary.
const CheckBox= require('./components/CheckBox');
class CheckBoxController{
open() {
browser.url('/login');
}
get checkboxComponent() {
// Using this we can verify whether the Specific Check Box has been Selected or Not
let element = browser.$('[id="lpagecheckbox"]');
return new CheckBox(element);
}
}
Note :
Please bear this is not the actual code , This is just a part of the template which can help us to move towards the solution of the Problem .
Source Contends :
https://webdriver.io/docs/api/element/isSelected.html
https://webdriver.io/blog/2019/02/22/shadow-dom-support.html
https://webdriver.io/blog/2019/04/03/react-selectors.html
https://webdriver.io/docs/pageobjects.html
Moreover if we are using Selenium Webdriver , This can help us to Achieve it
Here we have an interface which actually combines all the webdriver interfaces , then we create a Specific implementation by inheriting the Element Class , finally Lets assume of any component you need we should be inheriting and using it with its own implementation , In this case lets assume the Check box that should be inherited from then Element Implementation Class and finally a Cranky way of using it by instantiating the object. CheckBox cb = new CheckBox(element);cb.uncheck();
Step 1:
Create an Interface that combines all of the WebDriver interfaces:
public interface Element extends WebElement, WrapsElement, Locatable {}
Step 2:
Element Implementation Inheriting the element class:
public class ElementImpl implements Element {
private final WebElement element;
public ElementImpl(final WebElement element) {
this.element = element;
}
#Override
public void click() {
element.click();
}
#Override
public void sendKeys(CharSequence... keysToSend) {
element.sendKeys(keysToSend);
}
// And so on, delegates all the way down...
}
Step 3:
Consider any component you use , Lets assume Check Box in this case
public class CheckBox extends ElementImpl {
public CheckBox(WebElement element) {
super(element);
}
public void toggle() {
getWrappedElement().click();
}
public void check() {
if (!isChecked()) {
toggle();
}
}
public void uncheck() {
if (isChecked()) {
toggle();
}
}
public boolean isChecked() {
return getWrappedElement().isSelected();
}
}
Way of Using It :
CheckBox cb = new CheckBox(element);
cb.uncheck();
If you want More Clear way of Implementing Something Like this : refer the third Link
public class Part2ExampleTest {
private final WebDriver driver;
#FindBy(id = "checkbox")
CheckBox checkBox;
protected Part2ExampleTest(WebDriver driver) {
this.driver = driver;
}
protected static Part2ExampleTest initialize(WebDriver driver) {
return ElementFactory.initElements(driver, Part2ExampleTest.class);
}
#Test
public void simple() {
WebDriver driver = new FirefoxDriver();
Part2ExampleTest page = initialize(driver);
PageLoader.get(driver, "forms.html");
Assert.assertFalse(page.checkBox.isChecked());
page.checkBox.check();
Assert.assertTrue(page.checkBox.isChecked());
driver.close();
}
}
Sources :
Extend Selenium WebDriver WebElement?
http://elisarver.com/2012/12/09/wrapping-webelement-1/
http://elisarver.com/2012/12/10/wrapping-webelement-2
IWebElement is an interface that you can just implement inside your driver class.

Uncaught typeError: not a function for a private method in TypeScript

I am trying to access a private method in my MyAccount class but it is giving an error of uncaught typeError: this.displayTabOnClick not a function. I can clearly confirm that it is a private method available in MyAccount class, the other similar method displayTabOnPageLoad works perfectly.
Below is the code snippet:
MyAccount.ts file
class MyAccount
{
private displayTabOnClick(thisObj: JQuery, e:Event, callback?:()=>any): void {
$(document).scrollTop(0);
e.preventDefault()
let hash = thisObj.prop('hash');
// Update the location hash
window.location.hash = hash;
// Add Selected class to the current click elem
// Remove selected class from other .menu-link elem
thisObj.addClass('selected');
$('.menu-link').not(thisObj).removeClass('selected');
// Set Tab Header
this.setHeader(hash);
// Hide all sections
// And display only the hashed section
$('section').css('display','none');
$(hash).css('display','block');
}
/**
* Switch My Account Tab
* According to the passed ID
*
* #return void
*/
public switchTab (e?: Event): void {
if (e && e.type === "click") {
this.displayTabOnClick($('.menu-link'),e);
}
else {
this.displayTabOnPageLoad($('.menu-link'));
}
}
}
App.ts file
// My Account Page
let page = new MyAccount;
if (URL.checkPath('/user/myaccount')) {
page.switchTab();
}
$('.menu-link').click(page.switchTab);
You have this scoping issue when calling $('.menu-link').click(page.switchTab); (this is scoped to the caller, and not to the page)
One of the options to fix it:
$('.menu-link').click(e => page.switchTab(e));
Another one:
$('.menu-link').click(page.switchTab.bind(page));
I'd go with the first one as it keeps type safety.

How to call a C++ method from javascript

I have a C++ method (which role is killing some processes). She needs 2 parameters : a hostname and a port.
On the other hand, I am developing a web-application (using Nodejs and AngularJS), running on Google Chrome.
When I click on a button through the browser, I would like to be able to call the C++ function, through my app.js file.
I haven't found how to "bind" javascript with C++.
EDIT : I think this link could be very useful
How can I use a C++ library from node.js?
You can use Google's V8. V8 is Google's open source JavaScript engine.
V8 can run standalone, or can be embedded into any C++ application.
http://code.google.com/p/v8/
Following example from github demonstrates, binding a C++ class with Google V8.
v8_wrap_class.cpp - Author is nicholas
/*
* v8_wrap_class.cpp
*
* Created on: 14/01/2013
* Author: nicholas
* License: public domain
*/
#include <v8.h>
#include <cstdio>
#include <string>
#include <stdexcept>
#include <memory>
using namespace v8;
/*
var Simple = function(v)
{
this.value = v;
}
Simple.prototype.func = function()
{
alert(this.value);
}
var obj = new Simple(4);
obj.func();
*/
struct Simple
{
double value;
Simple(double v)
: value(v)
{
fprintf(stderr, "Simple::ctor\n");
}
void func()
{
fprintf(stderr, "Simple::func(%f)\n", value);
}
~Simple()
{
fprintf(stderr, "Simple::dtor\n");
}
};
namespace js
{
/*
* Retrieve the c++ object pointer from the js object
*/
template <typename T>
T* unwrap(const Arguments& args)
{
auto self = args.Holder();
auto wrap = Local<External>::Cast(self->GetInternalField(0));
return static_cast<T*>(wrap->Value());
}
/*
* Construct a new c++ object and wrap it in a js object
*/
template <typename T, typename... Args>
Persistent<Object> make_object(Handle<Object> object, Args&&... args)
{
auto x = new T(std::forward<Args>(args)...);
auto obj = Persistent<Object>::New(object);
obj->SetInternalField(0, External::New(x));
obj.MakeWeak(x, [](Persistent<Value> obj, void* data)
{
auto x = static_cast<T*>(data);
delete x;
obj.Dispose();
obj.Clear();
});
return obj;
}
}
void bind_Simple(Local<Object> global)
{
// Name the class in js
auto name = String::NewSymbol("Simple");
auto tpl = FunctionTemplate::New([&](const Arguments& args) -> Handle<Value>
{
if (!args.IsConstructCall())
return ThrowException(String::New("Cannot call constructor as function"));
HandleScope scope;
// Read and pass constructor arguments
js::make_object<Simple>(args.This(), args[0]->NumberValue());
return args.This();
});
tpl->SetClassName(name);
tpl->InstanceTemplate()->SetInternalFieldCount(1);
auto prototype = tpl->PrototypeTemplate();
// Add object properties to the prototype
// Methods, Properties, etc.
prototype->Set(String::New("func"), FunctionTemplate::New([](const Arguments& args) -> Handle<Value>
{
auto s = js::unwrap<Simple>(args);
s->func();
return {};
})->GetFunction());
auto constructor = Persistent<Function>::New(tpl->GetFunction());
global->Set(name, constructor);
}
int main()
{
std::string js_source = R"(
for(var i = 0; i < 1000; ++i)
{
var s = new Simple(4);
s.value = 5;
s.func();
}
)";
/*
* This code is mostly uninteresting.
* Just run the vm with the script provided.
*/
{
HandleScope handle_scope;
Handle<ObjectTemplate> global_template = ObjectTemplate::New();
Persistent<Context> context = Context::New(0, global_template);
Context::Scope context_scope(context);
auto global = context->Global();
// Wrap the class and bind to the global scope.
bind_Simple(global);
{
HandleScope handle_scope;
TryCatch trycatch;
Local<String> source = String::New(js_source.c_str(), js_source.size());
Local<Script> script = Script::Compile(source);
if (script.IsEmpty())
{
Handle<Value> exception = trycatch.Exception();
String::AsciiValue exception_str(exception);
throw std::runtime_error(*exception_str);
}
Local<Value> result = script->Run();
if (result.IsEmpty())
{
Local<Value> exception = trycatch.Exception();
String::AsciiValue exception_str(exception);
throw std::runtime_error(*exception_str);
}
}
context.Dispose();
context.Clear();
}
// Run the GC until there is nothing to reclaim.
while (!V8::IdleNotification())
;
return 0;
}
This answer gives four appraoches to using C++ in javascript. The methods shown try to keep the original C++ in a standard and simple C++ implementation.
Two methods using WASM and two using SWIG and JRPC are used to give examples and ideas on executing C++ in javascript. In detail, this answer gives one example for executing in the browser and one for executing in nodejs using WASM. The end of this answer also lists two other ways to execute C++ in javascript, one of which calls nodejs from the browser which is slightly more complex but possible using jrpc-oo.
If you want to execute in the browser or nodejs, then you can compile your C++ to WASM and load that module in the browser or nodejs, executing the C++ there. This WASM repo exemplifies how to do that. I will expand the key code in the WASM repo here.
Create some C++ code and declare your WASM binding, for example (from the files include/Test.H and src/Test.C) :
class Test {
public:
void sayHello(){
printf("Hi, my name is test\n");
}
};
#include <emscripten/bind.h>
EMSCRIPTEN_BINDINGS(Test_ex) {
emscripten::class_<Test>("Test")
.function("sayHello", &Test::sayHello)
;
}
Compile that down and you can now run that in nodejs (from the file nodejs/WASMTestNode.js) :
libWASM = require('./libwasmNode.js');
libWASM().then((mod)=>{
libWASM = mod;
let test = new libWASM.Test;
test.sayHello();
});
In the browser you can use the WASM code as well. To do that firs import the WASM library (from the file webcomponent/libWASM.js) :
import modProm from './libwasm.js';
The create your webcomponent and compile your WASM then execute the C++ method Test::sayHello (from the file webcomponent/libWASM.js) :
import { LitElement } from 'lit';
export class LibWASM extends LitElement {
constructor() {
super();
modProm().then((mod)=>{
this.libWASM = mod; // for rendered wasm that delay
this.WASMReady();
})
}
WASMReady(){
console.log('LibWASM.libWASM module compiled and ready to go.')
let test = new this.libWASM.Test;
test.sayHello();
}
}
This code example is implemented in the reference repo.
Alternatively a third way to do this is to only use C++, SWIG and nodejs from this reference repo.
If you want to execute nodejs from the browser or use a a different method of integrating C++ into nodejs, you can also look at this SWIG and jrpc-oo reference for doing the same thing, but not only in nodejs, also from the browser calling nodejs.
There are also other ways to execute C++ form javascript, however the methods demonstrated in this answer are reasonably straightforward and either rely on WASM binding or SWIG abstraction which leaves your original code as standard C++.

Categories

Resources