selenium ide 模拟原始代码转换

在试用selenium-ide 插件录制页面时,我们可以得到这样的界面。

image.png

上图的例子就是执行百度,搜索 nihao

可以发现生成的命令还是比较通俗易懂的。

那么我们如何获取到当前的脚本的的原始代码呢。

经过研究调试,发现可以通过_state.project.toJS() 的形式获取到。

例如在这个项目当中,我获取到的数据就是这样

image.png

在这里可以看到每个命令里面的细节,当然这个我也不是很关注。

下面我先尝试将这数据转换成py的可执行代码试试。

通过前一章节讲到的内容

我们可以在exportCodeToFile 函数中找到转换的方式。直接调用即可。

export async function exportCodeToFile(
  selectedLanguages,
  { test, suite },
  { enableOriginTracing, beforeEachOptions, enableDescriptionAsComment }
) {
  const project = UiState.project.toJS()
  const { url, tests } = project
  for (const language of selectedLanguages) {
    let emittedCode
    let options = {
      url,
      tests,
      project,
      enableOriginTracing,
      beforeEachOptions: {
        browserName: userAgent.browserName,
        ...beforeEachOptions,
      },
      enableDescriptionAsComment,
    }
    options.test = test ? test : undefined
    options.suite = suite
      ? projectProcessor.normalizeTestsInSuite({ suite, tests })
      : undefined
    if (vendorLanguages.hasOwnProperty(language)) {
      const result = await PluginManager.emitMessage({
        action: 'export',
        entity: 'vendor',
        language,
        options,
      })
      emittedCode = result[0].response
    } else if (test) {
      emittedCode = await exporter.emit.test(language, options)

下面我们新建一个简单的项目进行测试

var project = `{"id":"f82b2216-7207-4952-8339-019abfebfde3","version":"2.0","name":"test","url":"https://baidu.com","tests":[{"id":"706b803d-b284-4a34-8102-7975b67306eb","name":"baidu","commands":[{"id":"a95c059d-6185-4d0e-9088-19f1a9b24dcd","comment":"","command":"open","target":"https://www.baidu.com/","targets":[],"value":""},{"id":"c2afbb00-c6f2-4a3d-af92-61f975eb383e","comment":"","command":"setWindowSize","target":"1050x567","targets":[],"value":""},{"id":"286f42e7-da80-444c-a308-7c5eaaab0eba","comment":"","command":"click","target":"id=kw","targets":[["id=kw","id"],["name=wd","name"],["css=#kw","css:finder"],["xpath=//input[@id='kw']","xpath:attributes"],["xpath=//span[@id='s_kw_wrap']/input","xpath:idRelative"],["xpath=//input","xpath:position"]],"value":""},{"id":"e3e75ce9-1220-4fb6-98cc-61cc806dbfc8","comment":"","command":"type","target":"id=kw","targets":[["id=kw","id"],["name=wd","name"],["css=#kw","css:finder"],["xpath=//input[@id='kw']","xpath:attributes"],["xpath=//span[@id='s_kw_wrap']/input","xpath:idRelative"],["xpath=//input","xpath:position"]],"value":"nihao"},{"id":"42be1ed9-d4c3-4696-b242-131bbc5e3741","comment":"","command":"click","target":"id=su","targets":[["id=su","id"],["css=#su","css:finder"],["xpath=//input[@id='su']","xpath:attributes"],["xpath=//span[@id='s_btn_wr']/input","xpath:idRelative"],["xpath=//span[2]/input","xpath:position"]],"value":""},{"id":"d9e54ccb-b849-4eba-8ebc-9f45768f758e","comment":"","command":"close","target":"","targets":[],"value":""}]}],"suites":[{"id":"656f702c-9973-4ec2-a3c8-def3ba081212","name":"Default Suite","persistSession":false,"parallel":false,"timeout":300,"tests":[]}],"urls":["https://element.eleme.io/"],"plugins":[]}`
project = JSON.parse(project)
const { url, tests } = project
for (const language of selectedLanguages) {
  let emittedCode
  let options = {
    url,
    tests,
    project,
    enableOriginTracing, // 是否导入注释
    beforeEachOptions: {
      browserName: userAgent.browserName, // 浏览器名称
      ...beforeEachOptions,
    },
    enableDescriptionAsComment, // 使用描述作为注释
  }
  options.test = test ? test : undefined
  options.suite = suite
    ? projectProcessor.normalizeTestsInSuite({ suite, tests })
    : undefined
  if (vendorLanguages.hasOwnProperty(language)) {
    const result = await PluginManager.emitMessage({
      action: 'export',
      entity: 'vendor',
      language,
      options,
    })
    emittedCode = result[0].response
  } else if (test) {
    emittedCode = await exporter.emit.test(language, options)

可以看到代码里面还有一些我们当前没有获取到的数据options.test以及 options.suite

这里我也简单看了下源码,可以在导出时通过 _modalState.exportPayload 来获取到内容

比如在当前代码片段这里的内容为


image.png

因此我们可以断定,正常导出代码逻辑时,这里的逻辑判断将会走test的分支来运行

通过前一节的内容也可以指定,上面一段转换PluginManager.emitMessage 是没必要的
因此精简下我们的代码逻辑,给能确定后的代码块赋值

// project  原始数据太长就不贴了
project = JSON.parse(project)
const { url, tests } = project
let emittedCode
let options = {
  url,
  tests,
  project,
  enableOriginTracing: true, // 是否导入注释
  beforeEachOptions: {
    browserName: userAgent.browserName, // 浏览器名称
    ...beforeEachOptions,
  },
  enableDescriptionAsComment:true, // 使用描述作为注释
}
options.test = test ? test : undefined
options.suite = undefined

emittedCode = await exporter.emit.test(language, options)

好了,现在仅仅缺少 userAgent.browserNamebeforeEachOptions 当中的数据了

从源码可得知,引用自@seleniumhq/side-utils

import { userAgent, project as projectProcessor } from '@seleniumhq/side-utils'
image.png

这里就可以很清晰的看到,获取方式其实就是通过window.navigator.userAgent 来判断当前浏览器环境。

并且browserName 也可以清楚的看到是在Chrome当中Firefox 二选一

现在还剩下最后一个beforeEachOptions 通过它使用解构赋值的方式,我们知道它一定是object

这里的传递比较复杂, 加上我对react了解不是特别深入。因此切换下查找方案。
通过在测试代码中可以找到它是个配置项,并且通常只用于配置selenium-grid 的地址
因此很明显我们可以忽略它。

image.png

好了,现在我们的代码是这样

import exporter from '@seleniumhq/code-export'

project = JSON.parse(project)
const { url, tests } = project
let emittedCode
let options = {
  url,
  tests,
  project,
  enableOriginTracing: true, // 是否导入注释
  beforeEachOptions: {
    browserName: 'Chrome', // 浏览器名称
  },
  enableDescriptionAsComment:true, // 使用描述作为注释
}
options.test = test ? test : undefined
options.suite = undefined

emittedCode = await exporter.emit.test(language, options)
console.log(emittedCode)

因为我是用node环境调试,所以代码引入需要做一些转换。
await 也需要使用异步方案来包含。

const exporter = require('@seleniumhq/code-export').default;

(async ()=>{
  project = JSON.parse(project)
  const { url, tests } = project
  let emittedCode
  let options = {
    url,
    tests,
    project,
    enableOriginTracing: true, // 是否导入注释
    beforeEachOptions: {
      browserName: 'Chrome', // 浏览器名称
    },
    enableDescriptionAsComment:true, // 使用描述作为注释
  }
  options.test = tests[0]
  emittedCode = await exporter.emit.test('python-pytest', options)
})()

现在万事俱备,之差转换代码了
让我们运行一下

image.png

ok,可以看到我们成功完成了代码转换。

下一篇讲下,转换时注意事项,以及原始字符串的拼接。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,837评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,551评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,417评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,448评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,524评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,554评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,569评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,316评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,766评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,077评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,240评论 1 343
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,912评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,560评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,176评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,425评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,114评论 2 366
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,114评论 2 352

推荐阅读更多精彩内容