Visual studio code not autocompleting my javascript methods - javascript

I am writing automated tests for a webshop using Visual studio Code, webdriverIO and javascript/nodeJS
Everything works fine, but I can't seem to get vs code to autocomplete my methods (I am using a page object model, pageobjects which contain methods are called in tests).
This is my login pageobject with a method to login a user (just an example, actual pageobject contains many more methods) :
class LoginPage{
login(username, password) {
browser.setValue('#ShopLoginForm_Login', username)
browser.setValue('#ShopLoginForm_Password', password)
browser.click('button=Login')
}
}
module.exports = { LoginPage };
This is how I call it in the testfile:
describe('login test', function() {
const LoginPage = require('../../pages/loginPage').LoginPage;
loginPage = new LoginPage
const Menu = require('../../pages/menu').Menu;
menu = new Menu
it('should be able to login with valid credentials', function () {
browser.url(url)
menu.gotoLoginPage()
loginPage.login(username, password)
});
});
Every time I want to call a method in a test, it does not autocomplete the methods name, forcing me to write it out full, leading to many unneccesary typo's. Other types of methods, like webdriverIO browser.click, are autocompleted just fine.
I have tried the same code in webstorm, and there autocomplete does work.
Does anyone know what I can do to get VS code to autocomplete my methods?

pity that no-one was able to answer. I eventually found the answer myself. I will post it here for reference
in my imports:
const LoginPage = require('../../pages/loginPage').LoginPage;
loginPage = new LoginPage
I am forgetting to declare the new instance of the class. The right way should have been;
const LoginPage = require('../../pages/loginPage').LoginPage;
var loginPage = new LoginPage
An alternative way would have been to make my methods static, which removes the need for instantiating the class altogether

I struggled to use auto-suggest in vscode with webdriverio.
This links helped me.
https://webdriver.io/docs/autocompletion.html
https://webdriver.io/docs/pageobjects.html
You answer is right. instanciate the page.
In the official doc, they export class with 'new'
export default new LoginPage()

Related

Store web element's value in a parameter and use it in various js files in testcafe

In our insurance domain, the below scenario we want to achieve using testcafe:-
1st file:- Login into the application
2nd file:- create a claim, store the claim number into the global variable
3rd file:- use that globally declared claim number in all the Testscripts.
we are using the Page object model to achieve our scenario.
Please let us know how can we achieve this in testcafe.
As we suspect, the web element value that we get in 2nd file gets vanished as soon as the test case gets executed. so how can we pass that web element value in our 3rd file?
If possible, please let us know the steps in detail.
we have tried the below keywords to define our selector but it didn't work.
global
globalthis
We want to pass the data(fetched web element value) from one testscript to another testscript. Our question is whether it's possible or not
//page.js
import { Selector, t } from 'testcafe';
class PageModel {
constructor() {
global.ClaimNumber = Selector('#Txt_claimnumber');
//selector for Claim Number
this.DateOfEvent = Selector('#dateofevent');
//selector for Date of Event
this.DateOfClaim = Selector('#dateofclaim')
//selector for Date of Claim
this.TimeOfEvent = Selector('#timeofevent')
//selector for Time of Event
this.TimeOfClaim = Selector('#timeofclaim')
//selector for Time of Claim
this.ClaimStatus = Selector('#claimstatus')
//selector for Claim Status
this.Save = Selector('#Save');
//selector for Save Button
}};
export default new PageModel();
//test.js
import { Selector } from 'testcafe';
import PageModel from './page';
fixtureGetting Started
.pagehttps://devexpress.github.io/testcafe/example;
var claimid;//claimid will be generate after saving a claim
test('My first test', async t => {
await t
.typeText(this.DateOfEvent, '20/09/2022')
.typeText(this.DateOfClaim, '20/09/2022')
.typeText(this.TimeOfEvent, '12:00')
.typeText(this.TimeOfClaim, '12:00')
.typeText(this.ClaimStatus, 'xyz')
.click(this.Save)
claimid=global.ClaimNumber.value
//After saving the claim we want to fetch claimid and want to use that claim id in another testscript
});
//test1.js
import { Selector } from 'testcafe';
import PageModel from './page';
import Test from './test'
fixtureGetting Started
.pagehttps://devexpress.github.io/testcafe/example;
test('My first test', async t => {
var claimid1='23445';
await t.expect(claimid1).eql('claimid');
//want to verify claimid getting from test.js is equal to claimid from test1.js or not
//this is just an example but our requirement is to use claimid (getting from test.js) for different different operation into test1.js testscript.
});
Could you please tell us how to achieve this scenario.
It isn't correct to use information from one test in another one. If you want to prepare something before any test starts, you can use hooks. Also, if you need to reuse auth information, use Roles. It will be great practice.
Please see the following example with a global variable:
//test.js
import { Selector } from 'testcafe';
import PageModel from './page';
fixture`Getting Started`
.page`https://devexpress.github.io/testcafe/example`;
test('My first test', async t => {
await t
.typeText(global.developerNameSelector, 'John Smith')
.click('#submit-button')
// Use the assertion to check if the actual header text is equal to the expected one
.expect(Selector('#article-header').innerText).eql('Thank you, John Smith!');
});
//page.js
import { Selector, t } from 'testcafe';
class PageModel {
constructor() {
global.developerNameSelector = Selector('#developer-name');
}
};
export default new PageModel();
As my colleague mentioned above, it is very bad practice to use data from one test in another one. However, if it is required, you can use the "global" object in a common JavaScript way to accomplish this task:
test('My first test', async () => {
global.someVar = 'developer-name';
});
test('My second test', async t => {
await t.typeText(`#${global.someVar}`, 'some text');
});
Note that if, for some reason, the order in which the tests are executed changes (for example, in concurrency mode), then you will encounter unexpected behavior.
Also, I just checked your code and found out that you are trying to save the result of the "expect" method call (Assertion object) to your variable. Would you please clarify why? What behavior are you are trying to achieve?

Can I use axios in this example?

I'm still new to web development so I'm really sorry if the answer is obvious or the information provided by me is not much, but I hope this is sufficient:
Can I make an axios.post request within this vue.js component?
<script>
module.exports = {
mounted() {
// game code
};
</script>
Let me explain the problem I'm having at this moment: I can't import axios by import axios from "axios";. I neither can use export default { ... }. Both result in the page not loading (giving me an TypeError: "exports" is read-only). However, I need to access a variable within the gamecode since I want to axios.post that said variable (game score plus some more json info) to my MongoDB database.
If I can't make the request from there, am I able to get a variable from that code in mounted() { // game code }; and pass it to another component (and post it from there)? I searched the Internet for many hours but nothing seems to work for me, so again, sorry if it seems like I'm just too lazy to search for answers.
I managed to use axios within the module.exports part of the code.
Normally I would use import axios from 'axios'; and use axios as a method within
export default {
...
methods: {
// here (axios method)
...
But the
module.exports = { mounted() {
// game code
};
part did not work if I used the export default code part. I'm almost sure there is a more elegant way to solve this whole problem, but since I'm new and still don't understand totally how Vue and axios works, I simply tried some possibilities to include axios there and one worked:
module.exports = { mounted() {
const axios = require("axios");
// game code
// and later, for example: axios.post(...)...
};
At first I thought it wouldn't work since my IDE did not recognize the axios methods, but it actually posted data to my DB, so it did work.

Write global functions to use in all components in angular

Note : Its not for global variable but for a global common function to perform a functionality on all components
I am working on an angular app where I have around 400 components in different modules, almost all components have one same kind of functionality as mentioned below
There is a sections on many pages which shows a "How to work section" which can be closed by users and will remain closed unless they open it again, I have done it with cookies which I set on click on close or open icon but this function is written in a component and this needs to be imported in other components
I want to create a functions somewhere which perform this functionality on click on icon and can be called without importing any component in others.
One way to do it ( as I thought ) could be create a JavaScript function in a file and load it in index file and then call this function on click on close and open icon
Not sure if this is the best way to do this. Hope someone will come up with a better solution.
1. create your global function service, i.e. 'funcs.services.ts' under 'services' directory:
import { Injectable } from '#angular/core';
#Injectable({
providedIn: 'root'
})
export class FuncsService {
constructor() { }
myGlobalAddFunction(a){
return a++;
}
mySecondFunc(){
// add more... and so on
}
}
2. Import the function in your component:
// your path may different
import { FuncsService } from './../services/funcs/funcs.service';
//...
constructor(
private funcs: FuncsService
) {}
ngOnInit(): void {
let x = 1;
myResult = this.funcs.myGlobalAddFunction(x);
// Then you are expecting 2 for return value
}
3. Hope that works... :)
You can export a function that is a written in .ts file and then call it in all your components.
export function myFunction(){
// Do something
}
And then import the function myFunction() in other components. That works fine for me and can be useful in certain cases
This isn't the best solution (in my opinion). The best solution would be to either create a service, or an utils class.
But if you want to do this, I suggest you make a JS file, that you declare in your angular-cli.json file under the scripts property, containing your functions.
EDIT Now that you've came back to reason, here is a code sample to make utils classes.
export const IMG_UTILS = {
convertPngToJpg = (picture: any) => {
// Your logic here
}
};
export const VIEW_MANAGER = {
isAdblockActive = () => {
// test if an ad-blocker is active
}
};
You can make any utils class you want in a const, then put it into a file. Then, you can put this file in an utils folder, and request it with
import { VIEW_MANAGER } from 'src/app/utils/view-manager';
Otherwise, you can make a service, which is handled by Angular, with a console command such as
ng g s services/view-manager/view-manager
And it will behave the exact same way : you will import it in your components to use it.
Hope this helps !
The most recommended way is to use a service and inject it whenever needed, but there is a way to have a function available globally.
Although I don't think it's a really good idea, you can add the function in the index.html file, then whenever you want to use it, you have to use #ts-ignore to avoid an error from being thrown.
e.g
index.html
<script>
function globalFunc(){
alert(2)
}
</script>
anywhere else on the app
// #ts-ignore
globalFunc();
List item
Just to chime in with possibly a duplicate answer albeit more fleshed out... I have a utilities class which I use.
For example:
export class Utilities {
// Simple promise wrapper for setTimeout. See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Using_promises#creating_a_promise_around_an_old_callback_api
public static Wait = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));
}
The class is referenced in a component via the import statement:
import { Utilities } from 'path/to/Utilities';
And then you can call your static methods thus:
Utilities.Wait(30000)
.then(() => DoStuff())
.catch(() => console.log('Darn!'));
I would tend to use RxJs but I've written it this way to keep things a little cleaner.

How to call a class methods in JavaScript

I am currently learning ES6. While I was playing with the new features, I got stuck at one point. How to call a class method.
So let's say I have a class in one file like below:
class Auth {
checkUserSignedIn() {
//check user signed in
}
signupUser(account) {
//signup user
}
loginUser(account) {
//login user
}
getCurentUser() {
//Current User
}
}
module.exports = Auth;
and then in some other file, let's say a controller I would like to call these functions.
const Auth = require('./auth');
class Controller {
signupUserUsingEmailAndPass(user) {
Auth.signupUser(account);
}
loginUserUsingEmailAndPass(account) {
Auth.loginUser(account);
}
isUserSignedIn() {
checkUserSignedIn();
}
}
module.exports = Controller;
But this doesn't work at all. I guess there is something I am not understanding correctly. Any suggestion/advice?
Methods defined in a class require an instance of that class, i.e. a new Auth somewhere.
Your controller should be defined has
class Controller {
constructor(auth) {
this.auth = auth;
}
}
This approach over the require('myclass') allows for you to inject different implementations of your Auth class.
Should you not desire an instance of Auth for those methods, declare them as static. More on that here
You need to either instatiate the Auth
const authorization = new Auth();
Possibly inside the file containing the Auth class, and just export the instance.
export const authorization = new Auth();
Or, if You want this methods available outside. You can make the methods static. Just add static keyword before the method name during method creation.
You can read more about static methods here
Javascript classes don't work quite like the module pattern (that it seems) you're used to. When you export `Auth, you're exporting the class definition but you still need to instantiate it.
let auth = new Auth()
auth.signupUserUsingEmailAndPass() // or any other function you define
In javascript, a class is useful when you want to populate it with data or some sort of state. If you don't want or need that then you can use a module.

Returning another Page Object from a Page Object function in webdriverJS / Protractor?

I am used to WebDriver Java approach for implementing Page Object pattern, which is described here
So everything in Java WebDriver Page Object pattern boils down to following:
The public methods represent the services that the page offers
Try not to expose the internals of the page
Generally don't make assertions
Methods return other PageObjects
Need not represent an entire page
Different results for the same action are modelled as different
methods
So I am concerned about point 4.Methods return other PageObjects -
Can it be applied to webdriverJS or Protractor cases?
The reason I am asking this is that I have not yet seen this approach applied to Protractor scripts - usually all specs(tests in jasmine) are intended for testing only ONE page, BUT not testing complete work flow (1.logging in 2.going into the system further to test a whole feature of a system, but not only one page)
E.g.:
MainPage=require('./MainPage.js');
var LoginPage = function() {
this.userNameInput = element(by.id('login'));
this.passwordInput = element(by.id('password'));
this.submitButton = element(by.id('submit'));
this.loginWithValidCredentials= function(userName, password) {
this.userNameInput.sendKeys(userName);
this.passwordInput.sendKeys(password);
this.submitButton.click();
return new MainPage();
};
this.loginWithInvalidCredentials = function(userName, password) {
this.userNameInput.sendKeys(userName);
this.passwordInput.sendKeys(password);
this.submitButton.click();
return this;
};
};
module.exports = LoginPage;
Successful Login in to a page from LoginPage object: loginWithValidCredentials() function should return new MenuPage object
Unsuccessful Login in to a page from LoginPage object: loginWithInvalidCredentials() function should return the same LoginPage object (e.g. this)
So basically I want to use this Page Object pattern in spec files like this:
var LoginPage = require('../pages/LoginPage.js');
describe('Login with username and password', function () {
var loginPage = new LoginPage();
var mainPage;
it('Logging in with VALID credentials', function () {
mainPage = loginPage.loginWithValidCredentials(
"username",
"password");
**//interaction with mainPage goes here**
});

Categories

Resources