Page not defined issue when running Playwright Test - automation

I am new to playwright. When calling methods in different class using object instance, throwing error as "Page not defined".
Code as below:
Page.test.ts
import { expect } from "#playwright/test";
import { Page } from "playwright-core";
export class petStoreLoginPage {
private page: Page;
constructor (page : Page) {
this.page = page
}
//Locators
eleSignIn = async () => await this.page.$("text=Sign In")
eleUserNm = async () => await this.page.$("input[name='username']")
elePwd = async () => await this.page.$("input[name='password']")
eleLogin = async () => await this.page.$("input[value='Login']")
eleWelcomeScreen = async () => await this.page.waitForSelector("div[id='WelcomeContent']")
eleSignOut = async () => await this.page.$("text=Sign Out")
}
actions.test.ts
import { expect, Page } from '#playwright/test'
import {petStoreLoginPage} from '../Pages/pt.page'
declare const page : Page
let userInOut : petStoreLoginPage = new petStoreLoginPage(page)
export class userInOutAction {
public async clickSignIn() {
const ele = await userInOut.eleSignIn()
if (ele != null)
await ele.click()
else throw new Error("No element found")
}
public async clickSignOut() {
const ele = await userInOut.eleSignOut()
if (ele != null)
await ele.click()
else throw new Error("No element found")
}
public async enterUserNm(userNm : string) {
const ele = await userInOut.eleUserNm()
if (ele != null)
await ele.fill(userNm)
else throw new Error("No element found")
}
public async enterPwd(pwd : string) {
const ele = await userInOut.elePwd()
if (ele != null)
await ele.fill(pwd)
else throw new Error("No element found")
}
public async clickLogin() {
const ele = await userInOut.eleLogin()
if (ele != null)
await ele.click()
else throw new Error("No element found")
}
public async verifyHomePage() {
const ele = await userInOut.eleWelcomeScreen()
if (ele != null)
expect(await ele.innerText()).toBe("Welcome cgtdemo!")
else throw new Error("Welcome page not landed!!!")
}
public async verifyLoginLogoutPage() {
const ele = await userInOut.eleSignIn()
if (ele != null)
expect(await ele.innerText()).toBe("Sign In")
else throw new Error("Welcome page not landed!!!")
}
}
test1.test.ts
import { test } from '#playwright/test';
import Environment from '../Environment/environment';
import {userInOutAction} from '../Actions/pt.actions'
test("TC01 - Login and Logout Petstore Application", async ({page}) => {
let login : userInOutAction = new userInOutAction()
await test.step("Step 1 - Go to PetStore Application and Click SignIn", async () => {
await page.goto(Environment.test);
await login.clickSignIn();
await login.verifyLoginLogoutPage();
})
await test.step("Step 2 - Enter username and password", async () => {
await login.enterUserNm("cgtdemo");
await login.enterPwd("cgtdemo");
})
await test.step("Step 3 - userInOutAction to PetStore Application", async () => {
await login.clickLogin()
await login.verifyHomePage()
})
await test.step("Step 4 - Signout the PetStore Application", async () => {
await login.clickSignOut()
await login.verifyLoginLogoutPage()
})
})
test.afterAll(async({page}) =>
{
await page.close()
})
When giving npx playwright test , getting ReferenceError: page is not defined. Able to know it is because of the page is calling properly but I dont see any issue in code and not throwing any error.

Related

null is not an object (evaluating 'LoginManager.logInWithPermissions')

When I try to login to Facebook in expo android app, getting the following error
null is not an object (evaluating 'LoginManager.logInWithPermissions')
const SignInwithFB = async () => {
try {
await LoginManager.logInWithPermissions(["public_profile", "email"]);
const data = await AccessToken.getCurrentAccessToken();
if (!data) {
return;
}
const facebookCredential = FacebookAuthProvider.credential(data.accessToken);
const auth = getAuth(firebase);
const response = await signInwithCredential(auth, facebookCredential);
console.log(response);
} catch (e) {
console.log(e);
}
}
installed by following this instructions: https://www.npmjs.com/package/react-native-fbsdk-next
Check Expo installation section in npm install page, make sure you have implemented the instruction
const SignInwithFB = async () => {
try {
const loginManagerResult = await LoginManager.logInWithPermissions(["public_profile", "email"]);
if(loginManagerResult) {
const data = await AccessToken.getCurrentAccessToken();
if (!data) {
return;
}
const facebookCredential = FacebookAuthProvider.credential(data.accessToken);
const auth = getAuth(firebase);
const response = await signInwithCredential(auth, facebookCredential);
console.log(response);
}
} catch (e) {
console.log(e);
}
}

Where is module './get-username'?

I am attempting to write a script using the puppeteer library for node and I'm running it on the microtask platform rapidworkers.com
I have run into a challenge when writing part of the script that solves the captcha on the rapidworkers login page, when I try to run my script with node index.js I get the error: Cannot find module './get-username'
here is my code: (copied from https://jsoverson.medium.com/bypassing-captchas-with-headless-chrome-93f294518337)
const puppeteer = require('puppeteer');
const request = require('request-promise-native');
const poll = require('promise-poller').default;
const siteDetails = {
sitekey: '6LeEP20UAAAAAPYQsP7kIhE7XUT_LsDYjzO46uG3',
pageurl: 'https://rapidworkers.com/Login'
}
const getUsername = require('./get-username');
const getPassword = require('./get-password');
const apiKey = require('./api-key');
const chromeOptions = {
executablePath:'/Applications/Google Chrome.app/Contents/MacOS/Google
Chrome',
headless:false,
slowMo:10,
defaultViewport: null
};
(async function main() {
const browser = await puppeteer.launch(chromeOptions);
const page = await browser.newPage();
await page.goto('https://rapidworkers.com/Login');
const requestId = await initiateCaptchaRequest(apiKey);
await page.type('#username', getUsername());
const password = getPassword();
await page.type('#password', password);
const response = await pollForRequestResults(apiKey, requestId);
await page.evaluate(`document.getElementById("g-recaptcha-
response").innerHTML="${response}";`);
page.click('#register-form button[type=submit]');
})()
async function initiateCaptchaRequest(apiKey) {
const formData = {
method: 'userrecaptcha',
googlekey: siteDetails.sitekey,
key: apiKey,
pageurl: siteDetails.pageurl,
json: 1
};
const response = await request.post('http://2captcha.com/in.php', {form:
formData});
return JSON.parse(response).request;
}
async function pollForRequestResults(key, id, retries = 30, interval = 1500,
delay = 15000) {
await timeout(delay);
return poll({
taskFn: requestCaptchaResults(key, id),
interval,
retries
});
}
function requestCaptchaResults(apiKey, requestId) {
const url = `http://2captcha.com/res.php?
key=${apiKey}&action=get&id=${requestId}&json=1`;
return async function() {
return new Promise(async function(resolve, reject){
const rawResponse = await request.get(url);
const resp = JSON.parse(rawResponse);
if (resp.status === 0) return reject(resp.request);
resolve(resp.request);
});
}
}
const timeout = millis => new Promise(resolve => setTimeout(resolve,
millis))

Await return undefined

I am working with express server and trying to read data from file and return it to different function.
My code structure looks like this:
async function getUser(req) {
fs.readFile(cfg.fileDefaults, (err, defaults) => {
do something
return user;
}
}
module.exports = {getUser}
In controller I call that function
static getTable(req, res, next) {
async function search() {
user = await getUser(req); //return undefined
getUser(req).then((a) => {
console.log(a); //second try, return undefined
})
}
search();
}
How should I call it correctly?
const fs = require('fs')
function getUser(req) {
return new Promise((resolve, reject) => {
fs.readFile(cfg.fileDefaults, (err, defaults) => {
//do something
const user = { hellow: 'world' }
resolve(user)
})
})
}
module.exports = { getUser }
In controller
static getTable(req, res, next) {
async function search() {
user = await getUser(req); // return { hellow: 'world' }
res.end(JSON.stringify(user, null, ' '))
}
search().catch((err) => {
console.log('err',err)
res.status(500)
res.end('error')
})
}

Testing a cloudflare worker with HTMLRewriter fails as its undefined

I have a test to test my cloudflare worker that looks like this:
const workerScript = fs.readFileSync(
path.resolve(__dirname, '../pkg-prd/worker.js'),
'utf8'
);
describe('worker unit test', function () {
// this.timeout(60000);
let worker;
beforeEach(() => {
worker = new Cloudworker(workerScript, {
bindings: {
HTMLRewriter
},
});
});
it('tests requests and responses', async () => {
const request = new Cloudworker.Request('https://www.example.com/pathname')
const response = await worker.dispatch(request);
console.log(response);
// const body = await response.json();
expect(response.status).to.eql(200);
// expect(body).to.eql({message: 'Hello mocha!'});
});
});
In my worker I do something like this:
const response = await fetch(BASE_URL, request);
const modifiedResponse = new Response(response.body, response);
// Remove the webflow badge
class ElementHandler {
element(element) {
element.append('<style type="text/css">body .w-webflow-badge {display: none!important}</style>', {html: true})
}
}
console.log(3);
return new HTMLRewriter()
.on('head', new ElementHandler()).transform(modifiedResponse);
Now when i run my test I get this error message:
● worker unit test › tests requests and responses
TypeError: Cannot read property 'transform' of undefined
at evalmachine.<anonymous>:1:1364
at FetchEvent.respondWith (node_modules/#dollarshaveclub/cloudworker/lib/cloudworker.js:39:17)
What seems to be wrong?
HTMLRewriter i created looks like this:
function HTMLRewriter() {
const elementHandler = {};
const on = (selector, handler) => {
if (handler && handler.element) {
if (!elementHandler[selector]) {
elementHandler[selector] = [];
}
elementHandler[selector].push(handler.element.bind(handler));
}
};
const transform = async response => {
const tempResponse = response.clone();
const doc = HTMLParser.parse(await tempResponse.text());
Object.keys(elementHandler).forEach(selector => {
const el = doc.querySelector(selector);
if (el) {
elementHandler[selector].map(callback => {
callback(new _Element(el));
});
}
});
return new Response(doc.toString(), response);
};
return {
on,
transform
};
}
Since HTMLRewriter() is called with new, the function needs to be a constructor. In JavaScript, a constructor function should set properties on this and should not return a value. But, your function is written to return a value.
So, try changing this:
return {
on,
transform
};
To this:
this.on = on;
this.transform = transform;

How do I mock a specific function from a module for a specific test (Jest)

I have an api.js file that contains my api call. It looks like this:
// api.js
// reusable fetch call
export const makeFetch = async (url, options) => {
try {
const response = await fetch(url, options);
if (!response.ok) {
throw new Error(`${response.status}`);
}
return await response.json();
} catch (error) {
throw new Error(`Network request failed. (error: ${error.message})`);
}
};
// actual fetch call
export const getCards = async () => {
const url = 'http://localhost:3001/api/v1/cards';
return await makeFetch(url);
};
Then I have an api.test.js file that looks like:
//api.test.js
import { makeFetch, getCards } from './api';
describe('makeFetch', () => {
// three successful tests
});
// this is where I have issues
describe('getCards', () => {
it('calls makeFetch', async () => {
await getCards();
expect(makeFetch).toHaveBeenCalledTimes(1);
});
});
this is the error I get:
FAIL src\api\api.test.js
● getCards › calls makeFetch
ReferenceError: makeFetch is not defined
at Object.it.only (src/api/api.test.js:51:15)
at new Promise (<anonymous>)
at Promise.resolve.then.el (node_modules/p-map/index.js:46:16)
at <anonymous>
at process._tickCallback (internal/process/next_tick.js:182:7)
Does anyone know how to make this pass with making my previous tests fail? Thank you for your time.
You need to create a mock of makeFetch. You can do that using spyOn and mockReturnValue.
You will need to move makeFetch into its own file (lib.js) so that you can mock and replace it in your test:
// ---- lib.js ----
// reusable fetch call
export const makeFetch = async (url, options) => {
try {
const response = await fetch(url, options);
if (!response.ok) {
throw new Error(`${response.status}`);
}
return await response.json();
} catch (error) {
throw new Error(`Network request failed. (error: ${error.message})`);
}
};
// ---- api.js ----
import { makeFetch } from './lib';
// actual fetch call
export const getCards = async () => {
const url = 'http://localhost:3001/api/v1/cards';
return await makeFetch(url);
};
// ---- api.test.js ----
import * as lib from './lib';
import { getCards } from './api';
describe('makeFetch', () => {
// three successful tests
});
describe('getCards', () => {
it('calls makeFetch', async () => {
const simulatedResponse = { data: 'simulated response' };
// mock makeFetch
const mock = jest.spyOn(lib, 'makeFetch');
mock.mockReturnValue(Promise.resolve(simulatedResponse));
const result = await getCards();
expect(result).toEqual(simulatedResponse);
expect(mock).toHaveBeenCalledTimes(1);
expect(mock).toHaveBeenCalledWith('http://localhost:3001/api/v1/cards');
// restore makeFetch
mock.mockRestore();
});
});