Cypress - import and export functions - javascript

How can I better organize my cypress code for testing so that I only need to import some functions?
I want to start by creating a file in which to authenticate on the page, and then I want to import it in a test with several functions.
I tried the following export code and it seems to have been incorrect, with errors:
export function login() {
cy.visit('https://*********')
cy.get('input[name="Parameter.UserName"]').type('*****')
cy.get('input[name="Parameter.Password"]').type('*****')
cy.contains('Login').click()
}
export default {login};
And in test :
import {login} from 'elements/pages/login.js'

Your import needs a relative URL
import {login} from '../elements/pages/login.js' // relative from cypress/integration
or if under cypress/suport/elements
import {login} from '../support/elements/pages/login.js'
Absolute imports (where path has no leading ./ or ../) are presumed to be library packages in node_modules.

Cypress provides something called the Custom commands for this purpose, you can read about it here.
Go to cypress/support/commands.js and write all your code here like:
Cypress.Commands.add('login', () => {
cy.visit('https://*********')
cy.get('input[name="Parameter.UserName"]').type('*****')
cy.get('input[name="Parameter.Password"]').type('*****')
cy.contains('Login').click()
})
And then in your any of your test, you can directly add:
cy.login()

all cys must be excuted in testing content, maybe u can try like this:
export default {
// props
visit: (url)=> { return cy.visit(url) }
get: (el)=> { return cy.get(el) }
// methods
login(){
cy.visit('https://*********')
cy.get('input[name="Parameter.UserName"]').type('*****')
cy.get('input[name="Parameter.Password"]').type('*****')
cy.contains('Login').click()
}
}

Related

tsyringe - Injecting a dependency with overloaded constuctor

Hi friends how are you doing?
I'm trying to do something different, I don't know if it's away from the concept itself but it would help me to achieve what I'm trying to do in an elegant way.
I'm using a repository pattern and in the implementation I want to use a overloaded constructor and use an optional argument, basically passing some adicional information when it's needed.
The problem is, it's working great when the constructor is empty, but by the time change de signature to receive one more argument, the TSYSRINGE throws an execption.
I Really think that I'm missing something really simple, but I can't figure what. Could you please help me on this one? Thanks
ERROR:
Error: Cannot inject the dependency at position #0 of "ListProjectsServices" constructor. Reason:
TypeInfo not known for "ProjectsRepository"
Controller
export default class ProjectsController {
public async index(request: Request, response: Response): Promise<void> {
const listProjectsServices = container.resolve(ListProjectsServices);
const projects = await listProjectsServices.execute();
response.json(projects);
}
Service
#injectable()
export default class ListProjectsServices {
constructor(
#inject('ProjectsRepository')
private ProjectsRepository: IProjectsRepository,
) {}
public async execute(): Promise<Projects[]> {
const ProjectsList = await this.ProjectsRepository.findAllProjects();
return ProjectsList;
}
}
Container - to create the injection token
container.registerSingleton<IProjectsRepository>(
'ProjectsRepository',
ProjectsRepository,
);
Repository - Notice the extra_details argument in the constructor
after adding it, the problem occurs
#EntityRepository(Projects)
export default class ProjectsRepository implements IProjectsRepository {
private ormRepository: Repository<Projects>;
constructor(extra_details?: object) {
this.ormRepository = getRepository(Projects);
}
[...]
Today I went through this same problem.
Read this article on circular dependencies.
It tells us to use the delay function imported from tsyringe.
In the article, he tells us to use the delay inside the constructor.
But you, like me, are not directly sending the object in the inject, but a registered key.
Then you must use the delay in your container file, around the repository object try this:
import { container, delay } from 'tsyringe';
container.registerSingleton<IProjectsRepository>(
'ProjectsRepository',
delay(() => ProjectsRepository),
);
Insert the delay in all your injections that depend on an asynchronous repository
It can also be an error in the seo ormconfig.json, in the entities property.
Make sure the path is pointing to your entities:
"entities": [
"./src/modules/**/infra/typeorm/entities/*.ts"
],
We had the same problem here and we didn't want to have to use the delay function in the controller because we would be breaking the dependency injection principle... One way to solve the problem is to import your "Container" file into the main project file, in our case called "server.ts" and installing a lib called "reflect-metadata".
server.ts:
import * as dotenv from 'dotenv';
dotenv.config();
import express from 'express';
import 'express-async-errors';
import 'reflect-metadata'; // here is reflect-metadata import!
import config from './config/application';
import './infra/container'; // here is container import!
import { errorHandler } from './infra/http/middlewares/errorHandler';
import useSwagger from './infra/http/middlewares/swagger';
import { routes } from './infra/http/routes';
import { morganMiddleware } from './infra/logging/morgan';
export const app = express();
app.use(morganMiddleware);
app.use(express.json());
app.use(`${config.prefix}/api`, routes);
app.use(`${config.prefix}`, express.static('public'));
useSwagger(`${config.prefix}/api/docs`, app);
app.all(`${config.prefix}`, (_, res) => res.redirect(`${config.prefix}/api/docs`));
app.use(errorHandler);
container/index.ts:
import { container } from 'tsyringe';
import { RecurrenceNotificationUseCase } from '../../application/useCases/RecurrenceNotificationUseCase';
import { PubSubImplementation } from '../pubsub/PubSubImplementation';
container.registerSingleton('IPubSub', PubSubImplementation);
container.registerSingleton('IRecurrenceNotificationUseCase', RecurrenceNotificationUseCase);

Substitute or mock import of another file

I want to test functions within foo.js using Jest without altering foo.js. I do not want to test native functions like getBaseOs. Simply importing a function from foo.js will evaluate all the import statements of foo.js. Any import that relies on native code will trigger an error and the test will not run.
Is there a way to substitute imports like getBaseOs but only within the test file, foo.test.js? I simply want to ignore getBaseOs within foo.test.js to allow testing. Is there a way to do that even if substitution is not the way?
// foo.js
import React from 'react';
import { View, } from 'react-native';
import { getBaseOs, } from 'react-native-device-info';
export default function foo(props) {
return null;
}
// foo.test.js
import 'react-native';
import foo from './foo';
describe('test import substitution', () => {
it('test getBaseOs', () => {
const getBaseOs = jest.fn();
expect(true).toBe(true);
});
});
I just found the answer on GitHub by user karimo255 who commented on Jun 20, 2019. Simply putting the code in __mocks__/react-native-device-info.js allows the code to be replaced in tests despite an import. I speculate that Jest imports files from __mocks__ before performing a single test and matches the names of the files to the names of imports to match. Renaming the file will break it.
Here is the file that replaces the import statements of react-native-device-info, __mocks__/react-native-device-info.js:
export default {
getBaseOs: () => 'A',
};

How to properly export/import modules for library usage in javascript

I want to write a javascript library with two files:
snabbpixi.js
export function init() {
}
pixiapi.js
export function createElement() {
}
I want to use this library like this:
import { init } from 'snabbpixi';
import { createElement } from 'snabbpixi/pixiapi';
If I don't do anything and set the package.json for library as:
{
"main": "src/snabbpixi.js"
}
second import doesn't work (import { createElement } from 'snabbpixi/pixiap')
If I compile this library and export as umd format using webpack it also doesn't work.
How can I configure my library so I can import like this:
import { createElement } from 'snabbpixi/pixiap'
I normally do this sort of thing in TypeScript rather than straight JavaScript, but hopefully this works in basically the same way...
Try creating a new file (typically named index.js), with contents like this:
export * from './snabbpixi'; // Adjust paths as needed for your particular case.
export * from './snabbpixi/pixiapi';
Then make index.js your main.
The import you would use would then be flattened-out, however, looking more like:
import { init, createElement } from 'snabbpixi';
When you are using import { Something } from 'somewhere' you are calling on a named export from a given file or directory.
If the two files are in different directories then you can add an index.js file to each directory and then use export { default as function } from './file'
To do this you would have to export the default file from pixiapi and snabbpixi.
If you have both files importing into your index.js then you will still want to export them as defaults. But then you would do the following..
import file1 from './file1'
import file2 from './file2'
export default {
file1,
file2,
}
This will allow you to use the named imports as well and keep them in the same directory

Export default was not found

I have a Vue 2 project, and I've written a simple function for translating months in dates, which I would like to import in one of my components, but I'm getting an error:
export 'default' (imported as 'translateDate') was not found in '#/utils/date-translation'
The relative file path from the src folder is correct, and I am exporting the function like this:
export function translateDate(date) {
// my code
}
And then I am importing it in the component like this:
import translateDate from '#/utils/date-translation'
What am I doing wrong?
You have to specify default explicitly:
export default function translateDate(date) {
..
}
Either specify default as mentioned above, or if you're trying to export multiple items from the same file you need to import them with curly brackets.
So you would have:
export function doWork(){}
export const myVariable = true;
And then you'd import them in a separate file as:
import { doWork, myVariable} from "./myES6Module"
In my case I had to remove '{' and '}' arround the imported component :
import { CustomComponent } from './CustomComponent';
with
import CustomComponent from './CustomComponent';
Maybe you have two files with the same name.For example, "test.vue" and "test.js"
You need to set symlink setting in vue.config.js
config.resolve.symlinks(false);
Rather than using
export function translateDate(date) {
// my code
}
use
function translateDate(date){
//code
}
export default translateDate;
it worked for me...

Import components for server-side rendering in ES6

I've got a nice little ES6 React component file (simplified for this explanation). It uses a library that is browser-specific, store This all works beautifully on the browser:
/app/components/HelloWorld.js:
import React, { Component } from 'react';
import store from 'store';
export default class HelloWorld extends Component {
componentDidMount() {
store.set('my-local-data', 'foo-bar-baz');
}
render() {
return (
<div className="hello-world">Hello World</div>
);
}
}
Now I'm trying to get it to render on the server as follows, using babel-register:
/server/routes/hello-world.js:
import React from 'react';
import ReactDOMServer from 'react-dom/server';
import HelloWorld from '../../app/components/HelloWorld'
export default function(req, res) {
res.render('root', {
reactHTML: ReactDOMServer.renderToString(<HelloWorld />),
});
}
I get an error from the node server saying "window is not defined" due to importing 'store'. Ideally I could conditionally import by detecting the environment (node vs browser), but conditional imports aren't supported in ES6.
What's best way to get around this? I don't actually need to execute the browser code (in this case componentDidMount won't be called by ReactDOMServer.renderToString) just get it running from node.
One way would be using babel-rewire-plugin. You can add it to babel-register via the plugins option
require('babel/register')({
plugins: ['babel-rewire-plugin']
});
Then rewire your store dependency to a mocked store:
HelloWorld.__Rewire__('store', {
set: () => {} // no-op
});
You can now render HelloWorld from the server peacefully.
If you want to suppress the load of some npm module, you can just mock it.
Put this on your node.js application setup, before the HelloWorld.js import:
require.cache[require.resolve('store')] = {
exports: {
set() {} // no-op
}
};
This value will be used instead of the real module, which doesn't need on your purposes. Node.js module API is stable, so this behavior will not be broken and you can rely on it.

Categories

Resources