I've recently added end-to-end tests using Protractor to my AngularJS application. I've run the tests locally and they all pass, however when I commit to GitHub and Travis for CI most of the tests fail.
I've noticed that the failing tests are those that require routing to other states (I'm using Angular UI Router).
scenarios.js
describe('Test', function () {
beforeEach(function () {
browser.get('/');
})
it('should open the user page', function () {
//browser.get("/");
browser.sleep(3000);
var button = element(by.id('createSession'));
button.click().then(function () {
browser.sleep(3000);
expect(browser.getLocationAbsUrl()).toEqual("/user");
});
});
it('should create a session and add a user', function () {
//browser.get("/");
browser.sleep(3000);
var button = element(by.id('createSession'));
button.click();
browser.sleep(3000);
var input = element(by.id('username'));
input.sendKeys('Simona');
var joinButton = element(by.id('joinSession'));
joinButton.click();
browser.sleep(3000);
expect(element(by.id('addStart')).isPresent()).toBe(true);
});
it('should join an existing session', function () {
//browser.get("/");
browser.sleep(3000);
var inputSession = element(by.id('sessionId'));
inputSession.sendKeys('testing123');
var joinSessionBtn = element(by.id('enterSession'));
joinSessionBtn.click();
browser.sleep(3000);
var input = element(by.id('username'));
input.sendKeys('Simona1');
var joinButton = element(by.id('joinSession'));
joinButton.click();
browser.sleep(3000);
expect(element(by.id('addStart')).isPresent()).toBe(true);
});
it('should add user to active users', function () {
//browser.get("/");
browser.sleep(3000);
var inputSession = element(by.id('sessionId'));
inputSession.sendKeys('testing123');
var joinSessionBtn = element(by.id('enterSession'));
joinSessionBtn.click();
browser.sleep(3000);
var input = element(by.id('username'));
input.sendKeys('Simona');
var joinButton = element(by.id('joinSession'));
joinButton.click();
browser.sleep(3000);
var user = element(by.id('Simona'));
expect(user.isPresent()).toBe(true);
});
it('should not join a non-existing session', function () {
//browser.get("http://localhost:8000/");
browser.sleep(3000);
var inputSession = element(by.id('sessionId'));
inputSession.sendKeys('simonovaSesija');
var joinSessionBtn = element(by.id('enterSession'));
joinSessionBtn.click();
browser.sleep(3000);
var warning = element(by.id('warningSession')).isDisplayed();
expect(warning).toBe(true);
});
it('should add an anonymous user on empty username input', function () {
//browser.get("http://localhost:8000/");
browser.sleep(3000);
var inputSession = element(by.id('sessionId'));
inputSession.sendKeys('testing123');
var joinSessionBtn = element(by.id('enterSession'));
joinSessionBtn.click();
browser.sleep(3000);
var input = element(by.id('username'));
input.sendKeys('');
var joinButton = element(by.id('joinSession'));
joinButton.click();
browser.sleep(4000);
var user = element(by.id('Anonymous'));
expect(user.isPresent()).toBe(true);
});
});
protractor.conf.js
exports.config = {
allScriptsTimeout: 11000,
specs: [
"scenarios.js"
],
capabilities: {
"browserName": "chrome"
},
baseUrl: "http://localhost:8000/",
framework: "jasmine",
jasmineNodeOpts: {
defaultTimeoutInterval: 30000
}
};
package.json
{
"name": "angular-seed",
"private": false,
"version": "0.0.0",
"description": "A starter project for AngularJS",
"repository": "https://github.com/angular/angular-seed",
"license": "MIT",
"devDependencies": {
"bower": "^1.7.7",
"http-server": "^0.9.0",
"jasmine-core": "^2.4.1",
"karma": "^0.13.22",
"karma-chrome-launcher": "^0.2.3",
"karma-firefox-launcher": "^0.1.7",
"karma-jasmine": "^0.3.8",
"karma-junit-reporter": "^0.4.1",
"protractor": "^3.2.2"
},
"scripts": {
"postinstall": "bower install",
"prestart": "npm install",
"start": "http-server -a localhost -p 8000 -c-1 ./app",
"pretest": "npm install",
"test": "karma start karma.conf.js",
"test-single-run": "karma start karma.conf.js --single-run",
"preupdate-webdriver": "npm install",
"update-webdriver": "webdriver-manager update",
"preprotractor": "npm run update-webdriver",
"protractor": "protractor e2e-tests/protractor.conf.js",
"update-index-async": "node -e \"var fs=require('fs'),indexFile='app/index-async.html',loaderFile='app/bower_components/angular-loader/angular-loader.min.js',loaderText=fs.readFileSync(loaderFile,'utf-8').split(/sourceMappingURL=angular-loader.min.js.map/).join('sourceMappingURL=bower_components/angular-loader/angular-loader.min.js.map'),indexText=fs.readFileSync(indexFile,'utf-8').split(/\\/\\/##NG_LOADER_START##[\\s\\S]*\\/\\/##NG_LOADER_END##/).join('//##NG_LOADER_START##\\n'+loaderText+' //##NG_LOADER_END##');fs.writeFileSync(indexFile,indexText);\""
},
"dependencies": {
"bower": "^1.7.9",
"express": "^4.14.0"
}
}
.travis.yml
language: node_js
node_js:
- '4.4'
addons:
firefox: "latest"
# blocklist
branches:
except:
- master
# safelist
branches:
only:
- dev
before_script:
- export CHROME_BIN=chromium-browser
- export DISPLAY=:99.0
- sh -e /etc/init.d/xvfb start
- npm start > /dev/null &
- npm run update-webdriver
- sleep 1 # give server time to start
script:
- node_modules/.bin/karma start karma.conf.js --no-auto-watch --single-run --reporters=dots
- node_modules/.bin/protractor e2e-tests/protractor.conf.js
As you can see, I'm using angular-seed's Angular template.
Any suggestions on why this is happening?
It would be most helpful to know what kind of errors you're getting, but regardless, you've got a couple obvious culprits...
CI is running headless (ie. via XVFB), your local is not. The two will have different timing issues.
You have a lot of sleeps, which can cause your tests to behave differently on different environments (eg. CI vs. local). This is one of the reasons sleeps are bad. This would also lead me to believe your app is not Angular? If that is true, then it's better to handle any waits yourself. If that is not true, then why all the sleeps?
Hope that helps a bit.
Related
UPDATE: index.js file content added.
I have this electron app that is executing some bash scrips(*.sh) files to perform some task.
Everything is working absolutely fine in the development environment but when building the production build for deb installer for Ubuntu platform, everything is working, like opening on the app, other NodeJS stuff, but bash scripts are not executing.
Problem Statement: How to execute shell scripts in the production build of an electron app for Linux(Ubuntu OS). Getting this error
app/terminal_scripts/timer.sh Not Found
Below are the detailed explanation for the app.
**Project Directory Setup**:
ProjectName
|
app > css | images | js | renders
terminal_scripts
node_modules
package.json
package-lock.json
Where inside the app directory, I have all CSS, images, js, HTML, and terminal scripts.
package.json:
{
"name": "timer",
"productName": "Timely",
"version": "1.0.25",
"description": "This desktop app shows you system clock",
"main": "app/js/main/index.js",
"scripts": {
"start": "electron .",
"test": "echo \"Error: no test specified\" && exit 1",
"watch": "nodemon --exec 'electron .'",
"dist": "electron-builder"
},
"homepage": ".",
"keywords": [
"Electron",
"Desktop App"
],
"author": "NotABot Ltd <contact#notabot.com>",
"contributors": [
{
"name": "Not A Bot",
"email": "nab#notabot.com"
}
],
"license": "ISC",
"dependencies": {
"desandro-matches-selector": "^2.0.2",
"electron-context-menu": "^1.0.0",
"electron-is": "^3.0.0",
"fix-path": "^3.0.0",
"isotope-layout": "^3.0.6",
"jquery": "^3.5.0",
"jquery-bridget": "^2.0.1"
},
"build": {
"appId": "com.test.timely",
"productName": "Timely",
"linux": {
"target": "deb",
"category": "System"
}
},
"devDependencies": {
"electron": "^8.1.1",
"electron-builder": "^22.6.0"
}
}
HTML:
<html>
<head>
<title>Timely</title>
</head>
<body>
<button onclick="displayTime()">Display Time</button>
<textarea rows="20" cols="90" id="command-output" disabled="true"></textarea>
<script>
const {app} = require('electron');
function displayTime(){
console.log("button clicked");
let cmd = `bash app/terminal_scripts/timer.sh`;
let completeMessage = 'This is the message';
backgroundProcess(cmd, completeMessage);
}
function getCommandOutput() { return document.getElementById("command-output"); };
function getStatus() { return document.getElementById("status"); };
function appendOutput(msg) { getCommandOutput().value += (msg+'\n'); };
function setStatus(msg) { getStatus().innerHTML = msg; };
function backgroundProcess(cmd, completeMessage){
const process = require('child_process');
var child = process.execFile(cmd, [] , {shell: true} );
appendOutput("Processing......");
child.on('error', function(err) {
appendOutput('stderr: '+err );
});
child.stdout.on('data', function (data) {
appendOutput(data);
});
child.stderr.on('data', function (data) {
appendOutput(data );
});
return new Promise((resolve, reject) => {
child.on('close', function (code) {
console.log(`code is: ${code}`);
if (code == 0){
setStatus(completeMessage);
resolve(1);
}
else{
setStatus('Exited with error code ' + code);
resolve(-1);
}
});
});
}
</script>
</body>
</html>
Bash Script:
#!/bin/bash
timer="$(date)"
echo "$timer"
Permission is set 777 for this shell file
Platform Information:
OS: Ubuntu 18.04.4 LTS
NodeJS: 13.6.0
NPM: 6.14.5
Electron: 8.1.1
Electron Builder: 22.6.0
index.js
const {app, BrowserWindow, Menu, Tray, ipcMain, MenuItem} = require('electron');
const path = require('path');
const contextMenu = require('electron-context-menu');
let splashWindow;
function createMainWindow(){
mainWindow = new BrowserWindow({
minHeight: 700,
minWidth: 800,
webPreferences: {
nodeIntegration: true,
webviewTag: true
},
show: false
});
//For dev only
// mainWindow.webContents.openDevTools();
mainWindow.loadFile('app/renderer/index.html');
mainWindow.maximize();
}
app.on('ready', () =>{
createMainWindow();
});
Another way is to move flies to a new directory outside app directory and call it as extraResources.
Inside that directory you can add all your bash files and for production you can use below method.
let urlPath = path.join(process.resourcesPath, '/extraResources/')
and then use let cmd = `${urlPath}timer.sh`;
I have created a new directory alongside the app directory called the termainal_scripts.
Inside this, I have my bash file timer.sh.
I figured out how to execute shell scripts, in production by using process.resourcesPath inside path.join().
So, let the fixed path be as:
let fixedURL = path.join(process.resourcesPath, '/terminal_scripts/');
Then the command to execute will be:
let cmd = `${fixedURL}timer.sh`
I am using the Detox Test tool, and I am having difficulties.
I only installed Detox, I only ran the basic code for the ios test, and I get the following error:
Please help me.
Just iOS
Error Log
$ detox test --configuration ios.sim.debug --debug-synchronization --take-screenshots all --record-videos nonex --record-logs all
node_modules/.bin/jest e2e --config=e2e/config.json --maxWorkers=1 --testNamePattern='^((?!:android:).)*$'
FAIL e2e/firstTest.spec.js
● Test suite failed to run
ReferenceError: before is not defined
3 | const adapter = require('detox/runners/mocha/adapter');
4 |
> 5 | before(async () => {
| ^
6 | await detox.init(config);
7 | });
8 |
at Object.<anonymous> (init.js:5:1)
package.json
"script":{
"e2e:ios": "detox test --configuration ios.sim.debug --debug-synchronization --take-screenshots all --record-videos nonex --record-logs all",
"e2e:android": "detox test --configuration android.emu.debug --loglevel verbose --take-screenshots all --record-videos none --record-logs all"
},
dependencies": {
"detox": "^8.0.0",
"jest": "^23.1.0",
"mocha": "^5.2.0",
},
"detox": {
"configurations": {
"ios.sim.debug": {
"binaryPath": "ios/build/Build/Products/Debug-iphonesimulator/{app_name[enter image description here][1]}.app",
"build": "xcodebuild -workspace ios/{workspace_Name}.xcworkspace -scheme {scheme_name} Dev -configuration Debug -sdk iphonesimulator -derivedDataPath ios/build",
"type": "ios.simulator",
"name": "iPhone 7"
},
"android.emu.debug": {
"binaryPath": "android/app/build/outputs/apk/dev/debug/{apk_name}.apk",
"build": "react-native run-android --variant=devDebug --appId com.noahclient.dev",
"type": "android.emulator",
"name": "Nexus_5X_API_26"
}
},
"test-runner": "jest"
}
}
I looks like you are trying to run a mocha test on the jest runner. As your init.js is setup for mocha but the test runner that you are using is jest. This is confirmed by the error message node_modules/.bin/jest e2e... that you are getting.
You should pick either one, jest or mocha and use it. Rather than trying to use both.
#Jest
If you are using jest your init.js should look like this:
const detox = require('detox');
const config = require('../package.json').detox;
const adapter = require('detox/runners/jest/adapter');
jest.setTimeout(120000);
jasmine.getEnv().addReporter(adapter);
beforeAll(async () => {
await detox.init(config);
});
beforeEach(async () => {
await adapter.beforeEach();
});
afterAll(async () => {
await adapter.afterAll();
await detox.cleanup();
});
and you should add "test-runner": "jest" to the detox object in your package.json.
You should also have a config.json file in the same location as the init.js containing:
{
"setupFilesAfterEnv" : ["./init.js"]
}
#Mocha
If you are using mocha then your init.js should look like this:
const detox = require('detox');
const config = require('../package.json').detox;
const adapter = require('detox/runners/mocha/adapter');
before(async () => {
await detox.init(config);
});
beforeEach(async function () {
await adapter.beforeEach(this);
});
afterEach(async function () {
await adapter.afterEach(this);
});
after(async () => {
await detox.cleanup();
});
and you should remove the "test-runner": "jest" from the detox object in your package.json as it is not required.
Instead of a config.json file you should have a mocha.opts file beside your init.js and it should have something similar to:
--recursive
--timeout 120000
--bail
#Next steps
Choose the test runner that you are wanting to run; either jest or
mocha.
Make sure you have the correct init.js file for the test runner.
If using jest have a config.json file and add the test-runner to the detox object in the package.json.
If using mocha have a mocha.opts file. No need to specify a test-runner in the detox object in the package.json.
You can see the setup instructions here: https://github.com/wix/detox/blob/master/docs/Introduction.GettingStarted.md#step-3-create-your-first-test
If you are still having issues let me know.
"name": "javascript-development-environment",
"version": "1.0.0",
"description": "CS 235 package.json file for programming projects",
"scripts": {
"prestart": "babel-node buildScripts/startMessage.js",
"redditImgGet": "babel-node buildScripts/srcReddit.js",
"install": "npm install",
"start":"npm-run-all --parallel security-check open:src",
"security-check": "nsp check",
"open:src": "babel-node buildScripts/srcServer.js"
},
This is currently my package.json. I am trying to call the script which obtains an image from reddit. The inside of srcReddit.js is shown below:
var snoowrap = require('snoowrap');
console.log("Starting Reddit Image Fetcher");
const otherRequester = new snoowrap({
userAgent: navigator.userAgent,
clientId: 'Cf8kGqDSuT17xw',
clientSecret: 'DDmMslUwMJW1ZM5JTc07zJDpC8k',
username: 'sharan100',
password: 'Magewindu100'
});
function getRandomInt(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
r.getHot().map(post => post.title).then(console.log);
console.log("Ending Reddit Image Fetcher");
For this, I am using the wrapper snoowrap for the reddit API. Now when I do a npm start, I for some reason get this below:
No idea why the console.log messages do not appear. Does anyone know why?
npm start runs the start task and it does not refer to the redditImgGet task at any time, it seems.
I assume you should change your start task to
npm-run-all --parallel security-check open:src redditImgGet
Or just run the task directly
npm run redditImgGet
Otherwise, I don't see where you could expect the srcReddit file to log anything.
package.json:
{
"name": "electronapp",
"version": "1.0.0",
"description": "electron auto-launch",
"main": "index.js",
"scripts": {
"start": "electron .",
"build": "electron-packager . --all"
},
"author": "ivie",
"license": "ISC",
"devDependencies": {
"Q": "^1.0.0",
"asar": "^0.13.0",
"electron": "^1.7.6",
"electron-packager": "^9.1.0",
"electron-prebuilt": "^1.4.13",
"fs-jetpack": "^1.2.0",
"grunt-electron-installer": "^2.1.0",
"rcedit": "^0.9.0"
},
"dependencies": {
"auto-launch": "^5.0.1"
}
}
index.js:
var electron = require('electron');
var app = electron.app;
var BrowserWindow = electron.BrowserWindow;
var path = require('path');
app.on('ready', ()=>{
var mainwindow = new BrowserWindow({
width: 1200,
height: 800,
icon: "favicon.ico",
frame:true,
title:'Menuboard',
fullscreen: false,
autoHideMenuBar: false
})
mainwindow.openDevTools();
mainwindow.loadURL('https://www.google.com');
mainwindow.on('closed', function() {
mainwindow = null;
});
});
app.on('window-all-closed', function() {
if(process.platform != 'darwin')
app.quit();
})
I have generated an electron .exe using this code. It's getting executed when I'm double clicking on it. But, I want to run it on windows startup. I got to know about auto-launch. But, I'm not sure how to use it in my application? Any help would be appreciated.
Load auto-launch module:
const AutoLaunch = require('auto-launch');
Then add this after app.on('ready', ()=>{:
let autoLaunch = new AutoLaunch({
name: 'Your app name goes here',
path: app.getPath('exe'),
});
autoLaunch.isEnabled().then((isEnabled) => {
if (!isEnabled) autoLaunch.enable();
});
FYI this is now provided by Electron out of the box:
https://electronjs.org/docs/api/app#appsetloginitemsettingssettings-macos-windows
Example:
const electron = require("electron")
electron.app.setLoginItemSettings({
openAtLogin: arg.settings.startOnStartup,
path: electron.app.getPath("exe")
});
EDIT
Based on new comments, this may be out of date. Consider trying Timur Nugmanov's answer first.
At current electron release(19.0.0), the code below works fine:
app.setLoginItemSettings({
openAtLogin: true
})
I'm new in ReactJS and Gulp... .
I have a problem with Gulp. my problem is that when I write gulp serve in terminal, in the browser, my page doesn't show anything and the page doesn't load completely and after a long time with loading status, the browser show me:
This webpage is not available
ERR_CONNECTION_TIMED_OUT
message.
I don't know whats my problem?
My package.json is:
{
"name": "projectOverview",
"version": "1.0.0",
"description": "",
"main": "gulpfile.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "gulp serve"
},
"author": "",
"license": "MIT",
"devDependencies": {
"react": "^0.13.2",
"gulp-react": "^3.0.1",
"gulp": "^3.8.11",
"gulp-connect": "^2.2.0",
"gulp-concat": "^2.5.2",
"gulp-open": "^0.3.2",
"gulp-browserify": "^0.5.1",
"reactify": "^1.1.0"
}
}
and I config gulpfile.js like as follow:
var gulp = require('gulp'),
connect = require('gulp-connect'),
open = require("gulp-open"),
browserify = require('gulp-browserify'),
concat = require('gulp-concat'),
port = process.env.port || 3031;
gulp.task('browserify', function(){
gulp.src('./app/src/js/components/main.js')
.pipe(browserify({ transform: 'reactify' }))
.pipe(gulp.dest('./app/dist/js'));
});
//launch browser in a part
gulp.task('open', function(){
var options = {
url: 'http://localhost:' + port,
};
gulp.src('./app/index.html')
.pipe(open('',options));
});
//live reload server
gulp.task('connect', function(){
connect.server({
root: 'app',
port: port,
livereload: true
});
});
//live reload js
gulp.task('js', function(){
gulp.src('./app/dist/**/*.js')
.pipe(connect.reload());
});
//live reload html
gulp.task('html', function(){
gulp.src('./app/*.html')
.pipe(connect.reload());
});
//watch files for live reload
gulp.task('watch', function(){
gulp.watch('app/dist/js/*.js', ['js']);
gulp.watch('app/index.html', ['html']);
gulp.watch('app/src/js/**/*.js', ['browserify']);
});
gulp.task('default', ['browserify']);
gulp.task('serve', ['browserify', 'connect', 'open', 'watch']);
Note that this is a Test project and the main.js file is empty and it just contain pragma:
/** #jsx React.DOM */
and It should be show ddddd message, if it successfully load.
I think my problem is in the paths that I set in index.html or gulpfile.js. but...
My problem was solved!
my mistake was from 2 part: 1.
I must run two command before calling gulp serve: first:
gulp
and after that,
npm i
in terminal.
2.
My Kerio VPN was enable during test. after disconnecting from VPN account, it works perfect! I think the kerio application and gulp port, has conflict... .