How do I run selenium after serving create react app application? - selenium

I am trying to make some e2e tests with selenium over my Create React App application.
The problem is that before selenium can even run, I must run the react application itself (using for example npm start).
The problem: serving the app will stay in 'watch' mode in any autumation process I am trying to build.
Is it possible to run a create react app, and only after that selenium? (using grunt, npm or whatever?)
The current flow:
Run react development server with grunt (using npm start)
Run selenium
Is there a way to make them work one after the other?
grunfile:
require('dotenv').config();
module.exports = function(grunt) {
const API = process.env.REACT_APP_API_PATH + ':' + process.env.REACT_APP_API_PORT + '/api';
const DEV_PORT = 3001;
grunt.initConfig({
http: {
prepare_e2e_tests: {
options: {
url: API + '/prepare_e2e_tests'
}
}
},
exec: {
start_dev_server: {
cmd: 'REACT_APP_IS_TESTING=true PORT=' + DEV_PORT + ' npm start'
},
e2e: {
cmd: 'DEV_SERVER_PORT=3001 npm run e2e'
}
},
concurrent: {
test: {
tasks: ['http:prepare_e2e_tests','exec:start_dev_server','exec:e2e'],
options: {
logConcurrentOutput: true
}
}
}
});
grunt.registerTask('run_e2e', function() {
console.log('running e2e tests');
grutn.task.run('exec:e2e')
});
grunt.registerTask('prepare_server', function() {
console.log('preparing e2e tests on server:');
grunt.task.run('http:prepare_e2e_tests');
});
grunt.registerTask('setup_dev_server', function() {
console.log('running development server on port ' + DEV_PORT);
grunt.task.run('exec:start_dev_server');
});
grunt.registerTask('test', 'run e2e tests', ['concurrent:test']);
grunt.loadNpmTasks('grunt-http');
grunt.loadNpmTasks('grunt-exec');
grunt.loadNpmTasks('grunt-concurrent');
grunt.registerTask('default', []);
};
Thanks!

Related

Cypress 12 Component Tests Wont Load

I am trying to use Cypress 12 to run compnent tests in a Vue.js 2 app. Below is my cypress.config.ts file:
import { defineConfig } from "cypress";
export default defineConfig({
e2e: {
setupNodeEvents(on, config) {
// implement node event listeners here
},
baseUrl: "http://localhost:9090/.......",
defaultCommandTimeout: 60000,
},
component: {
devServer(cypressConfig: CypressConfiguration) {
// return devServer instance or a promise that resolves to
// a dev server here
return {
port: 9090,
close: () => {},
};
},
},
});
I setup a custom devServer in vue.config.js (otherwise Cypress starts uses its own localhost):
module.exports = {
devServer: {
port: 9090,
proxy: 'http://localhost:8080'
}
}
However, the tests wont load
When I run e2e tests, all is fine: tests appears, calls localhost:9090. However, if I want to run only component tests, it just gets stuck trying to load the tests.
It is not a DevTools problem as I have looked into that. All other configuration settings are standard.

VUE2 + Electron + Flask -> Python not spawning on build

I've just finished my first vue+electron+flask project and I am having quite a hard time trying to package it. Everything is workig "perfectly" when using "npm run electron:serve" but when running "npm run electron:build" I do not get any error, but Flask is not launched at all. I do not really know how to fix the problem, my guess is that when building the dist folder the path to app.py is not correct, but I tried to fix it without luck.
Here is the background.js code:
'use strict'
import { app, protocol, BrowserWindow } from 'electron'
import { createProtocol } from 'vue-cli-plugin-electron-builder/lib'
import installExtension, { VUEJS_DEVTOOLS } from 'electron-devtools-installer'
const isDevelopment = process.env.NODE_ENV !== 'production'
// Scheme must be registered before the app is ready
protocol.registerSchemesAsPrivileged([
{ scheme: 'app', privileges: { secure: true, standard: true } }
])
async function createWindow() {
// spawn flask app (https://medium.com/red-buffer/integrating-python-flask-backend-with-electron-nodejs-frontend-8ac621d13f72)
var python = require('child_process').spawn('py', ['../server/app.py']);
python.stdout.on('data', function (data) {
console.log("data: ", data.toString('utf8'));
});
python.stderr.on('data', (data) => {
console.log(`stderr: ${data}`); // when error
});
// Create the browser window.
const win = new BrowserWindow({
width: 1500,
height: 1200,
webPreferences: {
// Use pluginOptions.nodeIntegration, leave this alone
// See nklayman.github.io/vue-cli-plugin-electron-builder/guide/security.html#node-integration for more info
nodeIntegration: process.env.ELECTRON_NODE_INTEGRATION,
contextIsolation: !process.env.ELECTRON_NODE_INTEGRATION
}
})
if (process.env.WEBPACK_DEV_SERVER_URL) {
// Load the url of the dev server if in development mode
await win.loadURL(process.env.WEBPACK_DEV_SERVER_URL)
if (!process.env.IS_TEST) win.webContents.openDevTools()
} else {
createProtocol('app')
// Load the index.html when not in development
win.loadURL('app://./index.html')
}
}
// Quit when all windows are closed.
app.on('window-all-closed', () => {
// On macOS it is common for applications and their menu bar
// to stay active until the user quits explicitly with Cmd + Q
if (process.platform !== 'darwin') {
app.quit()
}
})
app.on('activate', () => {
// On macOS it's common to re-create a window in the app when the
// dock icon is clicked and there are no other windows open.
if (BrowserWindow.getAllWindows().length === 0) createWindow()
})
// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.on('ready', async () => {
if (isDevelopment && !process.env.IS_TEST) {
// Install Vue Devtools
try {
await installExtension(VUEJS_DEVTOOLS)
} catch (e) {
console.error('Vue Devtools failed to install:', e.toString())
}
}
createWindow()
})
// Exit cleanly on request from parent process in development mode.
if (isDevelopment) {
if (process.platform === 'win32') {
process.on('message', (data) => {
if (data === 'graceful-exit') {
app.quit()
}
})
} else {
process.on('SIGTERM', () => {
app.quit()
})
}
}
The relevant part of the code calling app.py is the following:
async function createWindow() {
// spawn flask app (https://medium.com/red-buffer/integrating-python-flask-backend-with-electron-nodejs-frontend-8ac621d13f72)
var python = require('child_process').spawn('py', ['../server/app.py']);
python.stdout.on('data', function (data) {
console.log("data: ", data.toString('utf8'));
});
python.stderr.on('data', (data) => {
console.log(`stderr: ${data}`); // when error
});
// Create the browser window.
const win = new BrowserWindow({
width: 1500,
height: 1200,
webPreferences: {
// Use pluginOptions.nodeIntegration, leave this alone
// See nklayman.github.io/vue-cli-plugin-electron-builder/guide/security.html#node-integration for more info
nodeIntegration: process.env.ELECTRON_NODE_INTEGRATION,
contextIsolation: !process.env.ELECTRON_NODE_INTEGRATION
}
})
I tried to put 3 dots insted of 2 in the app.py path ['.../server/app.py] just in case when creating the dist folder I need this extra dot to find the app.py file, but this is not working either.
My folder structure is the follwing:
Vue-Electron
client
dist_electron
node_modules
public
src
assets
components
router
views
App.vue
background.js
main.js
other config files
server
data
env
app.py
requirements.txt
other python scripts imported to app.py
sqlite_portofolio.db
As this program will only be used by me in my personal pc, I did not want to bother using pyInstaller (I thought it would be easier to not package the python side, but if I am wrong please let me know). I would like to have a electron .exe file that I can just doble click to open the electron build and then spawn the Flask server.
Also, my feeling is that I am not killing the Flask server correctly when closing the app. I think Flask is still running when closing electron. What should I do to ensure Flask server is properly closed.
There is not a lot of information of those topics that I can follow. Any help will be aprreaciated.
I´m having the same problem. I followed the link to this article (https://medium.com/red-buffer/integrating-python-flask-backend-with-electron-nodejs-frontend-8ac621d13f72), and it has the answer about killing the python flask server. And if you follow everything the article says, it's supposed to run the backend when opening the electron.exe, but this is not happening here on my end.
EDIT: I found the error, you need to change the path on your spawn. I sugest you to run the electron.exe on the cmd so you can see the error on it, so you will see the path that spawn is trying to run.
it´s probably:
var python = require('child_process').spawn('py', ['../resources/app/server/app.py']);
you will need to acess the app.py through [resources/app] as spawn start at the base dir of the electron build.
PS: I used electron-packeger that´s why mine need to add resources/app, and I used pyinstaller on my backend
Hope it will help you.

Expo App environments for Dev, UAT and Production

I have a React Native app built in Expo that connects to a Rest API. There are three environments for the rest api - dev, uat and production as below (example).
dev = https://dev.myapi.com/api
uat = https://uat.myapi.com/api
prod = https://prod.myapi.com/api
Depending on where the app is being used it needs to connect to the correct environment.
Running in the Expo Client = Dev API
Running in TestFlight or Internal Testing for the Play Store = UAT API
Running in the App Store or Play Store = Production API
What is the simplest way to achieve this?
Follow below Steps
Install expo-constants package. To install the package run the below command.
npm i expo-constants
Add environment.js file and paste below code.
import Constants from 'expo-constants';
import { Platform } from 'react-native';
const localhost = Platform.OS === 'ios' ? 'localhost:8080' : '10.0.2.2:8080';
const ENV = {
dev: {
apiUrl: 'https://dev.myapi.com/api',
amplitudeApiKey: null,
},
staging: {
apiUrl: 'https://uat.myapi.com/api',
amplitudeApiKey: '[Enter your key here]',
// Add other keys you want here
},
prod: {
apiUrl: 'https://prod.myapi.com/api',
amplitudeApiKey: '[Enter your key here]',
// Add other keys you want here
},
};
const getEnvVars = (env = Constants.manifest.releaseChannel) => {
// What is __DEV__ ?
// This variable is set to true when react-native is running in Dev mode.
// __DEV__ is true when run locally, but false when published.
if (__DEV__) {
return ENV.dev;
} else if (env === 'staging') {
return ENV.staging;
} else if (env === 'prod') {
return ENV.prod;
}
};
export default getEnvVars;
Accessing Environment Variables
// Import getEnvVars() from environment.js
import getEnvVars from '../environment';
const { apiUrl } = getEnvVars();
/******* SESSIONS::LOG IN *******/
// LOG IN
// credentials should be an object containing phone number:
// {
// "phone" : "9876342222"
// }
export const logIn = (credentials, jsonWebToken) =>
fetch(`${apiUrl}/phone`, {
method: 'POST',
headers: {
Authorization: 'Bearer ' + jsonWebToken,
'Content-Type': 'application/json',
},
body: JSON.stringify(credentials),
});
To create the builds use the below commands.
Dev - expo build:ios --release-channel dev
Staging - expo build:ios --release-channel staging
Production - expo build:ios --release-channel prod
Now that Expo supports config file as app.config.js or app.config.ts, we can use the dotenv. Check this: https://docs.expo.io/guides/environment-variables/#using-a-dotenv-file
Refer link
This can be done using different Release Channel names,
lets say you have created 3 release channels this way:
expo publish --release-channel prod
expo publish --release-channel staging
expo publish --release-channel dev
then you can have a function to set environment vars accordingly:
import * as Updates from 'expo-updates';
function getEnvironment() {
if (Updates.releaseChannel.startsWith('prod')) {
// matches prod*
return { envName: 'PRODUCTION', dbUrl: 'ccc', apiKey: 'ddd' }; // prod env settings
} else if (Updates.releaseChannel.startsWith('staging')) {
// matches staging*
return { envName: 'STAGING', dbUrl: 'eee', apiKey: 'fff' }; // stage env settings
} else {
// assume any other release channel is development
return { envName: 'DEVELOPMENT', dbUrl: 'aaa', apiKey: 'bbb' }; // dev env settings
}
}
Refer to expo documentation for more info!
For those who are using Expo sdk 46(or any newer version), you can do the following way
Rename the app.json to app.config.js
Add API URL under extra property
export default () => ({
expo: {
name: '',
slug: ''
extra: {
API_URL: process.env.API_URL || null,
},
// ...
},
});
We can access this API using expo constants like this(wherever we want).
Don't forget to import constants from Expo.
const myApi = Constants.expoConfig.extra.API_URL
axios.get(myApi).... // using API END POINT
For Local development to access API you can do it in two ways
API_URL="http:// localhost:3000" expo start
Just comment the Contants.expoConfig..... and directly paste local URL
like const myApi = "http:// localhost:3000"
And in eas.json
{
"production": {
"env": {
"API_URL": "https://prod.example.com"
}
},
"staging": {
"env": {
"API_URL": "https://staging.example.com"
}
}
}
Once we run eas build the appropriate API endpoint will be set.
Refer to the same in Expo documentation
https://docs.expo.dev/eas-update/environment-variables/

how to automate electron exe file using protractor framework

Please tell me in detail ..
I have an electron application and I have exe of that .. but want to automate using protractor framework.
Guide me in that .
You should try using Spectron
https://electronjs.org/spectron
Spectron is a testing tool for electron application. You can test it after packing into a exe file or straight away starting the test by mentioning the main.js
npm install --save-dev spectron
Install spectron via npm . Below example uses mocha for assertions.
To get up and running from your command line:
Install mocha locally as a dev dependency.
npm i mocha -D
create a spec file like below
const Application = require('spectron').Application
const assert = require('assert')
const electronPath = require('electron')
const path = require('path')
const chai = require('chai');
const chaiAsPromised = require('chai-as-promised');
global.before(() => {
chai.should();
chai.use(chaiAsPromised);
});
describe('Application launch', function () {
this.timeout(10000)
beforeEach(function () {
const opts = {
path: './your.exe'
};
const app = new Application(opts);
return app.start().then((app) => {
chaiAsPromised.transferPromiseness = app.transferPromiseness;
return app;
})
})
afterEach(function () {
if (this.app && this.app.isRunning()) {
return this.app.stop()
}
})
it('shows an initial window', function () {
return this.app.client.getWindowCount().then(function (count) {
assert.equal(count, 1)
// Please note that getWindowCount() will return 2 if `dev tools` are opened.
// assert.equal(count, 2)
})
})
})
Run the test by:
mocha spec.js

Debugging protractor test in intellij idea

I have project and I use protractor test. But I would like use debugging but I don't know how to create config for him.
It is my protractor.conf.js
'use strict';
var paths = require('./.yo-rc.json')['generator-gulp-angular'].props.paths;
exports.config = {
capabilities: {
'browserName': 'chrome'
},
specs: [paths.e2e + '/**/*.js'],
mochaOpts: {
timeout: 5000
},
framework: 'mocha'
};
And e2e-tests.js gulp file:
'use strict';
var gulp = require('gulp');
var $ = require('gulp-load-plugins')();
var browserSync = require('browser-sync');
module.exports = function(options) {
gulp.task('webdriver-update', $.protractor.webdriver_update);
gulp.task('webdriver-standalone', $.protractor.webdriver_standalone);
function runProtractor (done) {
gulp.src(options.e2e + '/**/**.js')
.pipe($.protractor.protractor({
configFile: 'protractor.conf.js'
}))
.on('error', function (err) {
// Make sure failed tests cause gulp to exit non-zero
throw err;
})
.on('end', function () {
// Close browser sync server
browserSync.exit();
done();
});
}
gulp.task('protractor', ['protractor:src']);
gulp.task('protractor:src', ['serve:e2e', 'webdriver-update'], runProtractor);
gulp.task('protractor:dist', ['serve:e2e-dist', 'webdriver-update'], runProtractor);
};
Help me please fix this issue because write code without quick watch and other good components not very well.