Using Custom Functions with "I" in Page Object and Custom Helper in CodeceptJS - helper

Hi CodeceptJS Community,
Is there a way to use custom defined functions (under steps_file.js) as I. customFunction() in page object files.
Is there a way to use native codeceptjs functions (like I.click()) in my custom helper files
I couldn't find any help in the documentation and in other sources. Is there any way to achieve this?
And is there any way to use xpath locators in puppeteer helper?
this.helpers['Puppeteer'].page.click(xpath);

I had the same problem to use custom steps in pageObjects.
To avoid it, i passed the actor (I) as parameter to my pageObject function.
page object:
const I = actor();
module.exports = {
doSomething(I){
I.login();
}
};
Test scenario:
Scenario('Test something' (I,pageObject)=>{
pageObject.doSomething(I)
})
In this case, pageObjects will has access to all custom steps from I :)

Thank you for your sharing Matheus. I have used a different solution. Instead of writing "I" object in every page object method (which was also one option for me), I have created a custom helper file and written all methods using puppeteer helper like below;
async method() {
await this.helpers['Puppeteer'].click(xpath);
}
I can call this method both in tests and page objects
I.method();

I was facing the same issue and when I looked into the typescripts definitions I noticed that actor() which is required in every page object etc. has custom steps arguments.
So this worked for me to extend the const I = actor(); witht the custom steps form steps_file.js;
const customSteps = require('./steps_file');
const I = actor(customSteps());
After that, I can use all methods in page objects like in tests scenarios which are accessing the methods from steps_file.js

Related

Why TypeOrm advises to create empty object via `new EntityClass()` THEN only pass fields value?

I'm using NestJS (not Next) NodeJS framework
When I'm creating new objects I used to use new OjbectClass({...fieldsValues});
It's great especially when you use transform pipes from class-transformer;
Besides this approach is used for entity creating:
https://docs.nestjs.com/techniques/database#separating-entity-definition
But as far I see in different guides of TypeOrm usage
here: https://typeorm.io/#/ ,
and here: https://orkhan.gitbook.io/typeorm/docs/entities .
They show first to create an empty object, then only set fields with values:
const object = new EntityObject();
object.field = 'value';
Why? Does it make sense?
Does NodeJS create a redundant hidden class of properties passed via object into Entity Class constructor? If yes - then we can pass coma-separated arguments
I believe it's just cause that's how the docs are. Looking at the code for BaseEntity it does not look like having a constructor to assign the fields would be a problem

VS code, code completion on parsed variables

I am seeking a suggestion for the code completion in VS Code. We are developing a node/express application in VS Code. We have a main javascript document app.js, which calls each page business logic based on routes which calls functions from other documents.
app.js looks like:
const uploadFunction = require("./router/uploadFunction.js);
const commonFunctions = require("./functions/commonFunctions.js);
...
app.post("/fileupload", function(req, res) {uploadFunction.someFunction(req,res,commonFunctions)});
In the uploadFunction document we would like to use auto completion fx.
function someFunction(req, res, commonFunctions){
commonFunctions.anotherFunction <= We want this to show on the code completion list
}
I hope it makes sense, and someone have a good suggestion
Vs code completion works best using classes but it also can determine the content of just functions. Classess automatically expose all public functions and vars to autocompletion. Using classes implies types. Types are always good for autocompletion.
Interface definitions work too. A class is an interface.
For plain ole functions, any function returing one or more functions will be picked up by autocompletion.
Also function input and return parameters are seen automatically by autocompletion. This is also true for all public properties.
Javascript objects should work to discover key names, but types are not knowable as all things in Javascript are of type any and can morph at will.
Pass the result of the other functions back to someFunction, which will then return it to your application.
function someFunction(req, res, commonFunctions){
commonFunctions.anotherFunction <= We want this to show on the code completion list
...
someFunction = result
}

Identify Reference to Destroy & Re-Initialize Swiper in Elementor

Elementor Pro (the WordPress page builder) integrates beautifully with Swiper, tying their GUI to the JS parameters and database content.
However, for my project, I need to make some changes to the Swiper "CoverFlow" skin Init parameters (show more slides, change the 3D effect facing direction...).
My hope is to to use the Destroy method of the Swiper API which looks like:
mySwiper.destroy(deleteInstance, cleanStyles);
Then I can initialize the Swiper again, with my own custom parameters. The challenge is that the way Elementor calls Swiper in frontend.js is a complex anonymous function that doesn't really allow me to know what "mySwiper" would be... On line 567:
this.swipers.main = new Swiper(this.elements.$mainSwiper, this.getSwiperOptions());
I would be so grateful if someone could please help me understand what "this.swipers.main" would translate to after Init so that I can destroy the swiper and initialize it again with my own parameters.
Obviously I cannot edit frontend.js itself as it is a plugin file that needs to be updated.
Extra points for whomever teaches me how to fish and what the methodology is to solve these types of puzzles for other similar situations.
You can give an ID to the Elementor widget ex: slider1 and then with JS you can use:
var sliderInstance = document.querySelector('#slider1 .swiper-container').swiper;
After this you can call sliderInstance.destroy() wherever you want.
And if you want to initialize it again you can call:
var sliderInstance = new Swiper('#slider1 .swiper-container', {
//options
});

Best way to add helper methods to context object in Koa2

I would like to add method such as view and json to the context object passed to my controllers. I do this in a middleware that runs before everything else:
async function(ctx, next){
ctx.view = view.bind(ctx);
ctx.json = json.bind(ctx);
await next()
ctx.renderer.render();
}
these methods set some conventional configuration object (Renderer) that the middleware interprets and then renders out the actual response by setting the correct ctx.body. That allows me to switch template language easily and have an easier time combining API and Template requests.
Except it doesn't work because after await next() the ctx.renderer is the default one, not the one set by controllers. I suspect it's a namespacing issue, but I am not sure where it comes from.
What's the best practice to attach functions to the context that can reference context without it being passed to them?
Ok it's here in the docs I just missed it, the docs are inside a repo and are not hosted, which makes them hard to navigate.
TL;DR: use app.context to access the context prototype. Adding functions there attaches them to the context object and allows you to use this from within to access it.

How to Include Other Models in Loopback?

I've read the document here: https://docs.strongloop.com/display/public/LB/Include+filter
But they are not clear! For example, they give the example:
User.find({include: 'posts'}, function() { ... });
Where should this code fit into? Is it in the common/models/user.js? Then what inside the function? what is the returned?
Of course I'm getting frustrated with their documents.
Please suggest. Thanks.
According to documentation you can use an include filter with find(), findOne() and findById(). I have attached links to respective sections of API reference.
To use these methods you need your PersistedModel object (e.g. User). Like you mentioned, you can get it in common/models/model-name.js (if you store your models there). You can also easily retrieve it from your LoopBackApplication object, which you can get in several ways. Bottom line is ... you can basically use these methods, wherever you need.
function() { ... } argument signalizes a callback. It lets you define a function which is going to be used on a returned instance(s). What is inside that function depends on your needs.

Resources