I'm new with Appium and WebdriverIO, I have an app created (a .zip file) and I want to test it with those 2 frameworks.
TL:DR - just go to the fourth code block.
I followed some tutorials and created a project containing
config files
test files
and of course a package.json.
First things first, my package.json:
{
"name": "my-test",
"version": "1.0.0",
"main": "index.js",
"license": "MIT",
"scripts": {
"wdio": "wdio run ./config/wdio.conf.js",
"ios.app": "./node_modules/.bin/wdio ./config/wdio.ios.app.conf.js"
},
"devDependencies": {
"#wdio/appium-service": "^7.16.16",
"#wdio/cli": "^7.16.16",
"#wdio/devtools-service": "^7.16.16",
"#wdio/local-runner": "^7.16.16",
"#wdio/mocha-framework": "^7.16.15",
"#wdio/spec-reporter": "^7.16.14",
"chai": "^4.3.6",
"chromedriver": "^99.0.0",
"wdio-chromedriver-service": "^7.2.8",
"webdriverio": "^7.16.16"
}
}
Then, my config files, divided in shared and ios :
shared.conf.js
exports.config = {
// ====================
// Runner and framework
// Configuration
// ====================
runner: "local",
framework: "mocha",
mochaOpts: {
timeout: 30000,
},
sync: true,
logLevel: "info",
deprecationWarnings: true,
bail: 0,
baseUrl: "localhost",
// path for appium sessions
path: "/wd/hub",
waitforTimeout: 15000,
connectionRetryTimeout: 90000,
connectionRetryCount: 3,
reporters: ["spec"],
autoGrantPermissions: true,
autoAcceptAlerts: true,
nativeWebTap: true,
// ====================
// Appium Configuration
// ====================
services: [
[
"appium",
{
// For options see
// https://github.com/webdriverio/webdriverio/tree/master/packages/wdio-appium-service
args: {
// Auto download ChromeDriver
relaxedSecurity: true,
// chromedriverAutodownload: true,
// For more arguments see
// https://github.com/webdriverio/webdriverio/tree/master/packages/wdio-appium-service
},
command: "appium",
},
],
],
port: 4723,
};
wdio.ios.app.conf.js
const { join } = require("path");
const { config } = require("./shared.conf");
// ============
// Specs
// ============
config.specs = ["./tests/specs/**/*.spec.js"];
// ============
// Capabilities
// ============
// For all capabilities please check
// http://appium.io/docs/en/writing-running-appium/caps/#general-capabilities
config.capabilities = [
{
// The defaults you need to have in your config
platformName: "iOS",
maxInstances: 1,
// For W3C the appium capabilities need to have an extension prefix
// This is `appium:` for all Appium Capabilities which can be found here
// http://appium.io/docs/en/writing-running-appium/caps/
"appium:deviceName": "iPhone 7",
"appium:platformVersion": "15.2",
"appium:orientation": "PORTRAIT",
// `automationName` will be mandatory, see
// https://github.com/appium/appium/releases/tag/v1.13.0
"appium:automationName": "XCUITest",
// The path to the app
"appium:app": join(process.cwd(), "../../../my-test.zip"),
// Read the reset strategies very well, they differ per platform, see
// http://appium.io/docs/en/writing-running-appium/other/reset-strategies/
"appium:noReset": true,
// How long (in seconds) Appium will wait for a new command from the client before assuming the client quit and ending the session
// default: 240
"appium:newCommandTimeout": 240,
},
];
exports.config = config;
So I created a very simple test file: there's a login screen, it finds the login textarea, writes the login, same for password, and push the button "signin":
describe("a test group", function () {
it("a test", async function () {
console.log("*******start*******");
// commands here
const selectUsername = 'type == "XCUIElementTypeTextField"';
const selectPassword = 'type == "XCUIElementTypeSecureTextField"';
const username = await $(`-ios predicate string:${selectUsername}`);
const password = await $(`-ios predicate string:${selectPassword}`);
const btnText = 'label == "SIGNIN"';
const loginBtn = await $(`-ios predicate string:${btnText}`);
await username.click();
await username.addValue("my#email.com");
await password.click();
await password.addValue("mypassword");
await loginBtn.click();
});
});
My issue here is that when the test is running
a) if I open the appium inspector, I can't find any running session, even if it has to exist somewhere:
plus (minor) I think the session never stops. If I re-run the test, the app running in the simulator shows the page of already logged-in, failing the test (because does not find the login/password fields).
Where are the sessions? and what I'm doing wrong?
Solved.
I was not able to edit the path in config file, but if I change the remote path in appium inspector to / , it finds the current session.
Related
I'm currently running a node application with Pm2, but am struggling to get logs.
Currently, if I start the script with just node index.js my logger function (using winston) sends the logs to the screen just fine. The first two lines in the below video ("IS THIS SHOWING UP" and "YA") are from console.log statements inside my javascript files, and the latter lines are from my logger function. It looks like this:
However, in the deployment of my server, I'm using an ecosystem.config.js file with Pm2. When I run my server with pm2 start index.js, the logger also works. HOWEVER, when I start my server using my ecosystem file, the pm2 instance only sends the console.log statements to the output, not the logs output by the winston logger.
This means that I've got something misconfigured in my ecosystem.config.js file. What's going wrong?
package.json (script that kicks off the pm2 instance)
{
"name": "graphqlCourse",
...
"scripts": {
"prod:serve": "NODE_ENV=production pm2 startOrRestart ecosystem.config.js"
},
"dependencies": {
...
ecosystem.config.js
module.exports = {
apps: [
/// I believe that something is misconfigured in here relating to logging.....
{
name: process.env.APP_NAME,
args: ["--color"],
interpreter: process.env.NODE_PATH,
cwd: path.resolve(process.env.PROJECT_PATH, 'current' ),
script: 'dist/index.js',
instances: process.env.INSTANCES || 0,
exec_mode: "cluster",
env: {
...process.env,
},
},
],
deploy: {
production: {
user: "harrison",
host: process.env.HOST,
key: "~/.ssh/id_rsa2",
ref: "origin/master",
repo: process.env.GIT_REPO,
path: process.env.PROJECT_PATH,
"pre-deploy-local": `scp -Cr envs harrison#${process.env.HOST}:${process.env.PROJECT_PATH}/current`,
"post-deploy": `yarn install --ignore-engines && \
pwd && \
yarn prod:build && \
yarn prod:serve`,
},
},
};
-- EDIT --
Here's my logger as well:
import winston, { format } from "winston";
import "winston-daily-rotate-file"; // Attaches new transport to winston.transports
// Define the custom settings for each transport (file, console)
let consoleOptions = {
level: "info",
handleExceptions: true,
stderrLevels: ["error"],
silent: process.env.SILENT === "true",
format: format.combine(
format.colorize(),
format.align(),
format.printf((info) => {
const { level, message } = info;
return `[${level}]: ${message}`;
})
),
};
let consoleTransport = new winston.transports.Console(consoleOptions);
// Log rotation
const transport = new winston.transports.DailyRotateFile({
filename: `API_${process.env.NODE_ENV}.log`,
dirname: `./${
process.env.NODE_ENV === "production" ? "dist" : "server"
}/logs`,
frequency: null, // Rely on date pattern, rotate daily
datePattern: "YYYY-MM-DD",
zippedArchive: true,
maxSize: "10m",
maxFiles: "14d",
format: format.combine(format.timestamp(), format.json()),
});
transport.on("rotate", (oldFileName, newFilename) => {
console.log(`ROTATING LOGS. OLD: ${oldFileName} -- NEW: ${newFilename}`);
});
// Handles input from Morgan.
var writer = new winston.createLogger({
transports: [transport],
});
// Handles logger.XX calls from within app.
export const logger = new winston.createLogger({
transports: [consoleTransport, transport],
exitOnError: false, // do not exit on handled exceptions
});
// Recieves message from morganToWinston
logger.stream = {
write: function (message) {
writer.info(message);
},
};
My electron app works as expected but it keeps on opening new windows when I run spectron test that tests for number of windows opened.
Electron version - v8.0.2 , "spectron": "^10.0.1" . I am not sure how to check exact version of spectron.
I am just running a small demo, below I will give code snippet
Note: I am running the spectron test pointing to .exe file generated by electron-packager.
Does Anyone have an idea what is the issue if possible how to solve it?
main.js
const { app, BrowserWindow } = require('electron')
function createWindow () {
let win = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nodeIntegration: true
}
})
win.loadFile('index.html')
}
app.whenReady().then(createWindow)
index.js
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Hello World!</title>
<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';" />
</head>
<body>
<h1>Hello World!</h1>
</body>
</html>
test.js
const assert = require('assert');
const path = require('path');
const Application = require('spectron').Application;
const electronPath = require('electron');
const app = new Application({
path: 'C:/demoElectronApp/winx64/demoelectronapp-win32-x64/demoelectronapp.exe',
});
describe('client_settings_app', function () {
this.timeout(10000);
beforeEach(() => {
return app.start();
});
it('shows only one initial window', async () => {
const count = await app.client.getWindowCount();
return assert.equal(count, 1);
});
})
package.json
{
"name": "demoelectronapp",
"version": "1.0.0",
"description": "",
"main": "main.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"electronpackage": "electron-packager . --out winx64"
},
"author": "",
"license": "ISC",
"dependencies": {
"path": "^0.12.7"
},
"devDependencies": {
"electron": "^8.2.2",
"electron-packager": "^14.2.1",
"assert": "^2.0.0",
"mocha": "^7.1.1",
"spectron": "^10.0.1"
}
}
Okay, I was having the same issue. And solved by setting remote debugging port.
chromeDriverArgs: ['remote-debugging-port=9222']
Full test code:
const Application = require('spectron').Application
const assert = require('assert')
const electronPath = require('electron') // Require Electron from the binaries included in node_modules.
const path = require('path')
describe('Application launch', function () {
this.timeout(10000)
beforeEach(function () {
this.app = new Application({
// Your electron path can be any binary
// i.e for OSX an example path could be '/Applications/MyApp.app/Contents/MacOS/MyApp'
// But for the sake of the example we fetch it from our node_modules.
path: path.join(__dirname, '..', 'node_modules', '.bin', 'electron' + (process.platform === 'win32' ? '.cmd' : '')),
// Assuming you have the following directory structure
// |__ my project
// |__ ...
// |__ main.js
// |__ package.json
// |__ index.html
// |__ ...
// |__ test
// |__ spec.js <- You are here! ~ Well you should be.
// The following line tells spectron to look and use the main.js file
// and the package.json located 1 level above.
args: [path.join(__dirname, '..')],
env: {
ELECTRON_ENABLE_LOGGING: true,
ELECTRON_ENABLE_STACK_DUMPING: true,
NODE_ENV: 'test'
},
waitTimeout: 10e3,
requireName: 'electronRequire',
chromeDriverLogPath: '../chromedriverlog.txt',
chromeDriverArgs: ['remote-debugging-port=9222']
})
return this.app.start()
})
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)
})
})
})
I was having a similar issue, and changed the version of the packages I was working with.
This page has the version map:
https://github.com/electron-userland/spectron#version-map
It seems like this isn't your problem byt may help others.
I FINALLY found a way to fix this that worked for me. I found it in a comment by #wburgess-invision on this gitHub thread here: https://github.com/electron-userland/spectron/issues/60
Navigate to node_modules -> spectron -> lib -> launcher.js
after the line "const args = appArgs.concat(chromeArgs);" add a new line and copy and paste this: args.splice(args.indexOf('--enable-logging'), 1)
npm run build
To quote the thread: "I noticed that it was happening because of the --enable-logging parameter being passed in. So I made a modified version of launcher.js which purposely didn't include --enable-logging and it worked fine for us. I couldn't find where the spectron launcher was managing to pick up the --enable-logging flag from as I thought a better solution would have been just not providing it to launcher.js in the first place but I couldn't find out so I just went with the solution that worked for now. My assumption was that the --enable-logging flag was being picked up somewhere inside of webdriverio when the client is initialized and thus calls launcher.bat but I couldn't find out where."
Is there a way I can disable the prefetching of the sauce connect binary when I run an npm install on a polymer project?
I am running my tests on a CI that has no connection to the outside world.
I do not wish to use the sauce connect binary so I would like to be able to disable the fetching of the binary.
wct.conf.js:
const seleniumGridAddress = 'http://selenium-hub:4444/wd/hub';
const os = require('os');
let json;
if (os.platform() !== 'darwin') {
json = {
activeBrowsers: [{
browserName: 'chrome',
url: seleniumGridAddress
}
],
expanded: true,
suites: [
'test/**/*_test.html'
],
webserver: {
hostname: os.hostname()
},
}
} else {
json = {
expanded: true,
plugins: {
local: {
browsers: ["chrome"]
},
},
suites: [
'test/**/*_test.html'
]
}
}
module.exports = json;
Found out in the wct source code that you can set SKIP_WCT_SAUCE_POSTINSTALL_DOWNLOADas an environment variable to disable the fetching of the Sauce Connect binary cfr 2.0.0-pre.1 at https://github.com/Polymer/wct-sauce/blob/master/CHANGELOG.md
I'm new to frontend world, I would like to write some test using protractor-image-comparison. I followed installation instructions from https://github.com/wswebcreation/protractor-image-comparison. Also I make configuration according to this page.
When I try to use functions form this lib I get following error: "TypeError: Cannot read property 'checkFullPageScreen' of undefined". I'm getting a warrning in protractor.conf.js in
const protractorImageComparison = require('protractor-image-comparison');
"Could not find a declaration file for module
'protractor-image-comparison'.
'/home/rafa/repos/example/src/example/node_modules/protractor-image-comparison/index.js'
implicitly has an 'any' type. Try npm install
#types/protractor-image-comparison if it exists or add a new
declaration (.d.ts) file containing declare module
'protractor-image-comparison';"
So I did, I made simple *.d.ts file with `declare module protractor-image-comparison' in it, but it didn't solve the problem just the warning disappear. It's propably the config issue, but I can't handle it or maybe I made wrong declaration. This is my config file :
// Protractor configuration file, see link for more information
// https://github.com/angular/protractor/blob/master/lib/config.ts
const reporter = require("cucumber-html-reporter");
const path = require("path");
const jsonReports = path.join(process.cwd(), "/reports/json");
const htmlReports = path.join(process.cwd(), "/reports/html");
const targetJson = jsonReports + "/cucumber_report.json";
const cucumberReporterOptions = {
jsonFile: targetJson,
output: htmlReports + "/cucumber_reporter.html",
reportSuiteAsScenarios: true,
theme: "bootstrap",
};
exports.config = {
allScriptsTimeout: 110000,
restartBrowserBetweenTests: true,
//SELENIUM_PROMISE_MANAGER: false,
specs: [
'./e2e/**/login.feature'
],
capabilities: {
'browserName': 'chrome'
},
directConnect: true,
baseUrl: 'http://localhost:4200/',
framework: 'custom',
frameworkPath: require.resolve('protractor-cucumber-framework'),
cucumberOpts: {
format: "json:" + targetJson,
require: ['./e2e/steps/*.ts', "./e2e/timeout.ts"],
},
useAllAngular2AppRoots: true,
onPrepare: () => {
browser.ignoreSynchronization = true;
const protractorImageComparison = require('protractor-image-comparison');
browser.protractorImageComparison = new protractorImageComparison(
{
baselineFolder: "report/screens/baseline",
screenshotPath: "report/screens/actual"
}
);
},
beforeLaunch: function() {
require('ts-node').register({
project: 'e2e'
});
},
onComplete: () => {
reporter.generate(cucumberReporterOptions);
}
};
Ok, I solved it. The reason why I was getting this TypeError is that I lunched few test scenarios and onPrepare was lunched only in the begining. I move config of protractor-image-comparison to cucumber befor hook and everything works fine now.
I'm getting the following error when trying to build:
Building for production...Error: ENOENT: no such file or directory, stat '/Users/me/Code/project/index.html'
Package: "prerender-spa-plugin": "^3.1.0"
File: vue.config.js:
const PrerenderSPAPlugin = require('prerender-spa-plugin');
const Renderer = PrerenderSPAPlugin.PuppeteerRenderer;
const path = require('path');
module.exports = {
configureWebpack: config => {
if (process.env.NODE_ENV !== 'production') return;
return {
plugins: [
new PrerenderSPAPlugin({
staticDir: path.join(__dirname),
routes: ['/'],
minify: {
collapseBooleanAttributes: true,
collapseWhitespace: true,
decodeEntities: true,
keepClosingSlash: true,
sortAttributes: true,
},
renderer: new Renderer({
renderAfterDocumentEvent: 'render-event',
}),
}),
],
};
},
};
I don't have any routes, only a single index.html page.
Also, when I run yarn build and get that error, I try to kill the process in terminal but it keeps returning Building for production... without anything happening, and I have to quit terminal for it to stop.
Edit: I've also tried adding staticDir: path.join(__dirname, './public') but the build hangs without any errors.
Try adding headless: false to your renderer options. This will open a Chromium browser with your specified array of routes. Open the inspector in the Chromium browser and its very likely that you will see errors in the console.