- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有一个 Electron 应用程序,它首先启动一个启动器窗口(在渲染器进程中),它启动多个后台服务。在这些后台服务成功启动后,它会发送 "services-running"
在其ipcRenderer
回到主进程,该进程又通过关闭启动器窗口并启动主应用程序窗口来对该事件作出 react 。该事件当然由 ipcMain.on('services-running',...)
接收。
我分别对所有处理程序进行了单元测试,所以这些都很好,现在我想集成测试通过 ipcMain
的事件.
这就是我的集成测试目前的样子:
import { Application } from 'spectron';
import * as electron from "electron";
import { expect } from 'chai';
import * as chai from 'chai';
import * as chaiAsPromised from 'chai-as-promised';
let app: Application;
global.before(() => {
app = new Application({
path: "" + electron,
args: ["app/main.js"],
env: {
ELECTRON_ENABLE_LOGGING: true,
ELECTRON_ENABLE_STACK_DUMPING: true,
NODE_ENV: "integrationtest"
},
startTimeout: 20000,
chromeDriverLogPath: '../chromedriverlog.txt'
});
chai.use(chaiAsPromised);
chai.should();
});
describe('Application', () => {
before('Start Application', () => {
return app.start();
});
after(() => {
if(app && app.isRunning()){
return app.stop();
}
});
it('should start the launcher', async () => {
await app.client.waitUntilWindowLoaded();
return app.client.getTitle().should.eventually.equal('Launcher');
});
it('should start all services before timing out', async (done) => {
console.log('subscribed');
app.electron.remote.ipcMain.on('services-running', () => {
done();
});
});
});
subscribed
,但在达到超时后,第二次测试最终会失败。在弹出主窗口之前的 shell 上,因此肯定会触发该事件。
nodeIntegration
需要启用以使用 spectron 访问完整的 Electron api,我所有的渲染器进程都以
{nodeIntegration: true}
开始在他们各自的
webPreferences
.但是由于我对主进程感兴趣,我认为这不适用(或者至少我认为它不应该,因为主进程本身就是一个节点进程)。
ipcMain
事件并将其包括在我的断言中。另外我怎么知道启动器窗口何时关闭并且“主”窗口已打开?
spectron.d.ts
electron
Application
的属性(property)是 Electron.AllElectron
类型这又是 MainInterface
并直接拥有ipcMain
属性(property)。因此,据我了解,访问 ipcMain
应该是 app.electron.ipcMain
(未定义),远程来自哪里以及为什么它在 spectron.d.ts
中不可见. SpectronClient
上的方法全部返回 Promise<void>
.所以我必须await
或 then
那些。如果我查看 javascript 示例,它们会链接客户端语句:return app.client
.waitUntilWindowLoaded()
.getTitle().should.equal('Launcher');
Promise<void>
显然,......这在js中如何工作?
最佳答案
所以我分别解决了这些问题。我将所有内容迁移到类并使用字段/构造函数注入(inject)将所有依赖项放入我的类中,因此我可以模拟它们,包括来自 Electron 的东西。
export class LauncherRenderer implements Renderer {
protected mongo: MongoProcess;
protected logger: Logger;
protected ipc: IpcRenderer;
protected STATUS_LABEL: string = 'status-text';
constructor() {
this.ipc = ipcRenderer;
this.mongo = new MongoProcess(this.ipc);
this.logger = new Logger('launcher', this.ipc);
}
this.ipc
订阅事件时。对于单元测试,我有一个
FakeIpc
类(class):
import { EventEmitter } from 'events';
export class FakeIpc {
public emitter: EventEmitter = new EventEmitter();
public send(channel: string, message?: any): void { }
public on(event: string, listener: () => void): void {
this.emitter.on(event, listener);
}
public emit(event: string): void {
this.emitter.emit(event);
}
}
LauncherRenderer
设置单元测试时我注入(inject)
FakeIpc
进入渲染器:
beforeEach(() => {
fakeIpc = new FakeIpc();
spyOn(fakeIpc, 'on').and.callThrough();
spyOn(fakeIpc, 'send').and.callThrough();
mongoMock = createSpyObj('mongoMock', ['start', 'stop', 'forceStop']);
underTest = new LauncherRenderer();
underTest.mongo = mongoMock;
underTest.ipc = fakeIpc;
});
trigger
拍摄 ipc 事件并测试我的类(class)是否对它做出正确 react 的方法。
it('should start the launcher', async () => {
await app.client.waitUntilWindowLoaded();
const title: string = await app.client.getTitle();
expect(title).toEqual('Launcher');
});
it('should open main window after all services started within 120s', async () => {
let handles: any = await app.client.windowHandles();
try {
await Utils.waitForPredicate(async () => {
handles = await app.client.windowHandles();
return Promise.resolve(handles.value.length === 2);
}, 120000);
await app.client.windowByIndex(1);
} catch (err) {
return Promise.reject(err);
}
const title: string = await app.client.getTitle();
expect(title).toEqual('Main Window');
});
waitForPredicate
只是一个帮助方法,它等待 promise 解决或在达到超时后终止测试。
public static waitForPredicate(
predicate: () => Promise<boolean>,
timeout: number = 10000,
interval: number = 1000,
expectation: boolean = true): Promise<void> {
return new Promise<any>(async (res, rej) => {
let currentTime: number = 0;
while (currentTime < timeout) {
// performance.now() would be nicer, but that doesn't work in jasmin tests
const t0: number = Date.now();
const readyState: boolean | void = await predicate().catch(() => rej());
if (readyState === expectation) {
res();
return;
}
await Utils.sleep(interval);
const t1: number = Date.now();
currentTime += t1 - t0;
}
// timeout
rej();
});
}
public static sleep(ms: number): Promise<void> {
if (this.skipSleep) {
return Promise.resolve();
}
return new Promise<void>((res) => setTimeout(res, ms));
}
关于typescript - 对 Spectron 中的 ipcMain 事件作出 react ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56889026/
我正在尝试使用分而治之(又名 fork /合并)方法来解决数字运算问题。这是代码: import scala.actors.Futures.future private def compute( in
在 node.js 应用程序中,我尝试从 API 查找产品列表,然后仅获取第一项的缩略图。 在我的代码中,getOrderDetails 是一个 promise ,然后如果它是第一个产品,它会调用函数
关于有帮助的问题 Force reload watchOS 2 Complications用户@alexeyvmp 提到 in a comment您应该为 CLKComplicationServerA
我想等待一个特定的时间来执行一个函数,但我得到了 Error: Thread[2,tid=3699,WaitingInMainSignalCatcherLoop,Thread*=0xa9f2c500,
我将 react-plotly.js 与 typescript 一起使用,我从中得到以下错误: No overload matches this call. Overload 1 of 2, '(
我正在尝试为机器人发出命令,当消息中提到的每个人都对机器人的响应使用react时,它会提到原始消息作者 这就是我尝试过的 if msg.content.startswith('/ini
这个问题已经有答案了: JavaScript and querySelector (4 个回答) 已关闭 4 年前。 当我在浏览器中按鼠标时,无法更改图像。我真的一直在努力寻找这个问题的答案,但还没有
我正在尝试让一个 Android USB 主机程序连接到一个从属设备,它实际上是一个 USB 串口转换器。从设备当前设置为在没有可用数据时返回 NAK,我正在轮询从设备以查看是否有任何 IN 数据,方
我是一名优秀的程序员,十分优秀!