selenium-ide
拥有代码转换功能,可以将录制的脚本转换为各个语言的selenium版本。
对应的界面实现在packages\selenium-ide\src\neo\components\Dialogs\Export\index.jsx
界面使用react编写,支持导出的脚本类型数组,是由browser.storage
并非写死的。
当选择完毕后会通过selectExportLanguage
设置当前选择的语言。
selectExportLanguage(language) {
this.selectedExportLanguage = language
storage.set({
selectedExportLanguage: language,
})
}
数据通过uiStorage
进行共享,因此他可以设置之前选则的导出类型为默认类型。
选择完成后导出时会调用this.props.completeSelection
方法传递数据。
然后根据调用位置,可以看到具体实现函数exportCodeToFile
其中可以看到函数实现是将字符串 写入 emittedCode
中来实现导出文件
emittedCode
在这里有两种转换方式
首先看一下PluginManager
的实现方式
其中核心逻辑为sendMessage
具体实现形式为
browser.runtime.sendMessage(id,JSON.parse(JSON.stringify(payload)))
第二个参数即为原始脚本。可以看到进行了json操作,说明它应该是按照Json Wire Protocol
进行的组装。
这里的id
为插件的id
。
最后我们记录发送人也就是这个插件id
和插件返回来转换完成的代码。
可以看到插件注册逻辑
可以简单的看到注册调用的方式为
根据找的的文档描述,我们可以得住调用注册的形式
这里不太方便查看。
接下来再看第二种方式exporter
import exporter from '@seleniumhq/code-export'
可以看到引用自code-export
下面是code-export
的具体实现
在这里可以看到实际上导出成不同的语言依靠不同的插件来完成,这是很大的工作量。
因此后续的工作转移到具体的插件上,以python
语言为例
项目整体目录结构是这样的。
Command.js
: 对应基础命令解析,这里存储了大量的命令进行转换,例如assert
,click
,mouseDown
等。
hook.js
: 这里对应的则是一下hook事件,贯穿命令执行的生命周期。
index.js
: 入口文件.这里核心逻辑下面再说。
location.js
: 存储的是定位特征,比如根据那些定位元素之类的id
,name
,xpah
。
selection.js
: 和上面类似,不过这里是存储css selector
定位的。
核心内容都在index.js
文件当中,如下图。
在这里还能看到两个比较熟悉的函数
export async function emitTest({})
export async function emitSuite({})
这就是我们上面看到的转换时调用的。
以 emitSuite
为例子 详细代码如下。
export async function emitSuite({
baseUrl,
suite,
tests,
project,
enableOriginTracing,
beforeEachOptions,
enableDescriptionAsComment,
}) {
global.baseUrl = baseUrl
const result = await exporter.emit.testsFromSuite(tests, suite, opts, {
enableOriginTracing,
enableDescriptionAsComment,
generateTestDeclaration,
project,
})
const suiteDeclaration = generateSuiteDeclaration(suite.name)
const _suite = await exporter.emit.suite(result, tests, {
...opts,
suiteDeclaration,
suite,
project,
beforeEachOptions,
})
return {
filename: generateFilename(suite.name),
body: exporter.emit.orderedSuite(_suite),
}
}
看到这里应该就是解析发送过来的json
数据,返回的body
内容则是对应转换完成的脚本。
转换的所有核心逻辑均是通过 exporter
来完成的
从之前的图片可以看到 这里的exporter
来自于 @seleniumhq/side-utils
这个项目
通过这个简介可以看到,它是作为代码转换套件来使用的,所有selenium
的脚本转换都由他来完成中间解释
到这里我们可以了解到。
如果需要让我们的自动化代码,提供多语言转换,我们可以选择直接使用import exporter from '@seleniumhq/code-export'
模块来同时翻译为多种语言脚本。
那么转换前的原始数据是什么样的?
怎么自动生成原生数据然后通过插件转换?
原始数据生成有哪些规则限制?
后续内容随缘更新~