My spectron app.client doesn't contains all the methods - electron

I'm trying to test my electron app using spectron and mocha, here is my file 'first.js' containing my tests:
const assert = require('assert');
const path = require('path');
const {Application} = require('spectron');
const electronPath = require('electron');
describe('GULP Tests', function () {
this.timeout(30000)
const app = new Application({
path: electronPath,
args: [path.join(__dirname, '..', 'main.js')]
});
//Start the electron app before each test
before(() => {
return app.start();
});
//Stop the electron app after completion of each test
after(() => {
if (app && app.isRunning()) {
return app.stop();
}
});
it('Is window opened', async () => {
const count = await app.client.getWindowCount();
return assert.equal(count, 1);
});
it('Clicks on the project creation button', async () => {
await app.client.waitUntilWindowLoaded();
const title = await app.client.
console.log(title);
return assert.equal(title, 'Welcome to GULP, !');
});
});
My first test is passing, but for the second one i'd like to do a click on an element, but my app.client does not contain a .click methods, and also no getText or getHTML. I've tried to import browser from webdriverio but it was the same problem, I get an error when testing saying me that those methods doesn't exists. I've red the spectron documentation and they're using .click and .getText methods regularly, why I don't get them ? I've imported spectron as it's said in the documentation to.
Thanks.

I have struggled with the same issue for a while. After much trial and error i changed my async methods to normal functions.
it('Clicks on the project creation button', function() {
app.client.waitUntilWindowLoaded();
const title = await app.client.
console.log(title);
return assert.equal(title, 'Welcome to GULP, !');
});
Strange but it worked for me. hopefully it helps.

Related

can we use the toHaveScreenshot() and toMatchSnaphot() out side the test

Can we use the toHaveScreenshot() and toMatchSnaphot() outside the test without using config file only simple install NPM i playwright in package.json
I have already one snapshot I want to compare snapshot using toHaveScreenshot() method but I am confused we can use outside the test context?
const { chromium } =require( "playwright");
const example = async () => {
const browser = await chromium.launch({ headless: false });
const page = await browser.newPage();
await page.goto("https://zversal.com/");
await page.toHaveScreenshot("zeversal.png", {
fullPage: false,
maxDiffPixelRatio: 0.24,
});
};
example();
Console reports error:
toHaveScreenshot() must be called during the test
I don't think this is possible. Afaik, toHaveScreenshot() is part of the #playwright/test package.
If I'm looking at the Page API docs there's no toHaveScreenshot() listed. I'd say it's only available in combination with Playwright Test and it's provided expect method.
await expect(page).toHaveScreenshot();
As similarly noted by stefan judis in his answer, toHaveScreenshot is an assertion matchers method provided by expect which comes from the Playwright Test library and is made to be used inside tests.
While that assertion can’t be used, you can still take screenshots using Playwright, and then compare them manually or with another tool.
I don't know if it's possible to use it outside of testing, but you can create a PlaywrightDevPage helper class to encapsulate common operations on the page.
Simple Usage =>
// models/PlaywrightDevPage.js
class PlaywrightDevPage {
/**
* #param {import('playwright').Page} page
*/
constructor(page) {
this.page = page;
this.getStartedLink = page.locator('a', { hasText: 'Get started' });
this.gettingStartedHeader = page.locator('h1', { hasText: 'Installation' });
this.pomLink = page.locator('li', { hasText: 'Playwright Test' }).locator('a', { hasText: 'Page Object Model' });
this.tocList = page.locator('article div.markdown ul > li > a');
}
async getStarted() {
await this.getStartedLink.first().click();
await expect(this.gettingStartedHeader).toBeVisible();
}
async pageObjectModel() {
await this.getStarted();
await this.pomLink.click();
}
}
module.exports = { PlaywrightDevPage };
More Info => PlaywrightDevPage

launching Theia based electron app (artifact/package) isn't working

Almost new in using playwright. Exploring the things and checking what we can do with this tool.
I am trying to launch our Theia based electon app in Ubuntu 18.04 with below source.
const { _electron: electron } = require('playwright');
//const { _electron } = require('playwright');
//import { test, expect, Page } from '#playwright/test';
(async () => {
// Launch Electron app.
const electronApp = await electron.launch('./my_executable_file_path');
//this executable is an artifact/packgae
})();
test.describe('New Todo', () => {
test('should allow me to add todo items', async ({ page }) => {
//let's not do anything before the app launch.
});
});
In my package.json file, i have this already
"devDependencies": {
"#playwright/test": "^1.20.2",
I can successfully run test cases based on the browser but not able to launch the electron app.
electron.launch: Cannot find module 'electron/index.js'
We don't have this index.js in our jenkins generated artifact.
This is how I launched electron successfully
const electronApp = await _electron.launch({
args: ['theia-electron-main.js'],
cwd: 'cube-electron/apps/studio/electron/scripts'
});

Debugging Worker thread in electron

I'm testing out worker_thread on an electron application. I'm currently using version 11.0.2.
The code is simple and is working and returning the sample data but I cant seem to step into the code.
Main Process:
import { Worker, isMainThread, workerData } from 'worker_threads';
config.ipcMain.on('entries:search', (evt: any, opts: any) => {
if (isMainThread) {
const pathWorker = path.join(__dirname, '../data/entries_worker.js');
const worker = new Worker(pathWorker, {
workerData: opts.value,
});
worker.on('message', (data) => {
debugger;
const d = 1;
});
worker.on('error', (data) => {
debugger;
const d = 1;
});
worker.on('exit', (data) => {
debugger;
const d = 1;
});
}
});
The worker file code:
import { workerData, parentPort } from 'worker_threads';
debugger;
parentPort.postMessage({ status: 'Done' });
I'm using Visual Studio Code and I do put breakpoints and event the debugger statement but it never seems to break into the worker file.
The message event does receive the response from the script { status: 'Done' } and the exit event returns 0.
Any ideas on how I can stop at the breakpoint in the worker file entries_worker.js?
Update
Found the following link about how it's not available right now. I'm not 100% sure if it has changed
ndb allow debugger worker thread. run in develop env like this:
"electron-dev": "ndb electron ."
When you use worker thread, you can found it easy:
You can also add breakpoints debug your code:

Spectron not visible html element

I am new with spectron and I spend a lot of time with simple example test.
I have an electron app which has loader at the beginning, and after some time it presents simple view. I want to check if header is equal "Welcome"
This is my test code:
const {Application} = require('spectron')
const chaiAsPromised = require('chai-as-promised');
describe('Application set up', function () {
this.timeout(20000)
let app;
beforeEach(async () => {
app = await new Application({
path: path-to-my-exe-electron-app
});
chaiAsPromised.transferPromiseness = app.transferPromiseness;
return app.start();
});
afterEach(async () => {
if (app && app.isRunning()) {
await app.stop();
}
});
it('example', async () => {
return app.client.waitUntilWindowLoaded()
.waitForVisible('h2', 15000)
.getText('h2')
.then(text => expect(text).toEqual('Welcome'));
})
})
And in result i got error: Error: element ("h2") still not visible after 15000ms
What do I do wrong? I spend some hours searching other spectron ways to achieve my goal, I tried adopt many solution but with no result.

Is there any way to track an event using firebase in electron + react

I want to ask about how to send an event using firebase & electron.js. A friend of mine has a problem when using firebase analytics and electron that it seems the electron doesn't send any event to the debugger console. When I see the network it seems the function doesn't send anything but the text successfully go in console. can someone help me to figure it? any workaround way will do, since he said he try to implement the solution in this topic
firebase-analytics-log-event-not-working-in-production-build-of-electron
electron-google-analytics
this is the error I got when Try to use A solution in Point 2
For information, my friend used this for the boiler plate electron-react-boilerplate
The solution above still failed. Can someone help me to solve this?
EDIT 1:
As you can see in the image above, the first image is my friend's code when you run it, it will give a very basic example like in the image 2 with a button to send an event.
ah just for information He used this firebase package :
https://www.npmjs.com/package/firebase
You can intercept HTTP protocol and handle your static content though the provided methods, it would allow you to use http:// protocol for the content URLs. What should make Firebase Analytics work as provided in the first question.
References
Protocol interception documentation.
Example
This is an example of how you can serve local app as loaded by HTTP protocol and simulate regular browser work to use http protocol with bundled web application. This will allow you to add Firebase Analytics. It supports poorly HTTP data upload, but you can do it on your own depending on the goals.
index.js
const {app, BrowserWindow, protocol} = require('electron')
const http = require('http')
const {createReadStream, promises: fs} = require('fs')
const path = require('path')
const {PassThrough} = require('stream')
const mime = require('mime')
const MY_HOST = 'somehostname.example'
app.whenReady()
.then(async () => {
await protocol.interceptStreamProtocol('http', (request, callback) => {
const url = new URL(request.url)
const {hostname} = url
const isLocal = hostname === MY_HOST
if (isLocal) {
serveLocalSite({...request, url}, callback)
}
else {
serveRegularSite({...request, url}, callback)
}
})
const win = new BrowserWindow()
win.loadURL(`http://${MY_HOST}/index.html`)
})
.catch((error) => {
console.error(error)
app.exit(1)
})
async function serveLocalSite(request, callback) {
try {
const {pathname} = request.url
const filepath = path.join(__dirname, path.resolve('/', pathname))
const stat = await fs.stat(filepath)
if (stat.isFile() !== true) {
throw new Error('Not a file')
}
callback(
createResponse(
200,
{
'content-type': mime.getType(path.extname(pathname)),
'content-length': stat.size,
},
createReadStream(filepath)
)
)
}
catch (err) {
callback(
errorResponse(err)
)
}
}
function serveRegularSite(request, callback) {
try {
console.log(request)
const req = http.request({
url: request.url,
host: request.url.host,
port: request.url.port,
method: request.method,
headers: request.headers,
})
if (req.uploadData) {
req.write(request.uploadData.bytes)
}
req.on('error', (error) => {
callback(
errorResponse(error)
)
})
req.on('response', (res) => {
console.log(res.statusCode, res.headers)
callback(
createResponse(
res.statusCode,
res.headers,
res,
)
)
})
req.end()
}
catch (err) {
callback(
errorResponse(err)
)
}
}
function toStream(body) {
const stream = new PassThrough()
stream.write(body)
stream.end()
return stream
}
function errorResponse(error) {
return createResponse(
500,
{
'content-type': 'text/plain;charset=utf8',
},
error.stack
)
}
function createResponse(statusCode, headers, body) {
if ('content-length' in headers === false) {
headers['content-length'] = Buffer.byteLength(body)
}
return {
statusCode,
headers,
data: typeof body === 'object' ? body : toStream(body),
}
}
MY_HOST is any non-existent host (like something.example) or host that is controlled by admin (in my case it could be electron-app.rumk.in). This host will serve as replacement for localhost.
index.html
<html>
<body>
Hello
</body>
</html>

Resources