先看第一段代码
import { browser, by, element } from 'protractor'; export class ReconcileFlightPage { navigateTo() { browser.get(browser.baseUrl + 'admin/reconcile-flight'); } getTitleText() { return element(by.tagName('h3')).getText() as Promise<string>; } search() { browser.waitForAngular(); element(by.css('[formControlName=startDate]')).element(by.css('span[role=button]')).click(); browser.waitForAngular(); element(by.tagName('kendo-calendar-viewlist')).element(by.css('[title="Sunday, August 14, 2016"]')).click(); element(by.css('[formControlName=endDate]')).element(by.css('span[role=button]')).click(); element(by.tagName('kendo-calendar-viewlist')).element(by.css('[title="Thursday, May 7, 2020"]')).click(); element(by.id('searchBtn')).click(); } getGridRowCount() { return element(by.tagName('tbody')).all(by.tagName('tr')).count() as Promise<number>; } }
代码是一个名为ReconcileFlightPage 类的建立
首先是从protractor中引用browser,by以及element接口(对象)。
然后是类内容的创建。包括4个函数:导航navigateTo() ,获取文本getTitleText() ,搜索search(),以及获得行数getGridRowCount() 。
导航
导航是对brower对象方法的封装。将引导向目标网址,目标网站是给定的网址(browser.baseUrl)与'admin/reconcile-flight'的拼接。
获取文本
是对elementFinder对象方法的封装。首先是by对象通过查找HTML标签‘h3’,返回一个locator对象。由element对象接收后,成为elementFinder对象。然后对elementFinder对象采取获取文本值的交互操作。最后将操作结果返回,返回对象是一个promise对象,变量类型是字符型。
搜索
其中的函数方法执行是异步的?
- 首先是浏览器等待,
- 接着是查找——by对象按照css样式formControlName=startDate查找,返回对象后,再按照css样式span[role=button]查找,找到之后执行点击的交互命令。
- 又是浏览器等待
- 接着也是查找——by对象按照标签名字kendo-calendar-viewlist查找,返回对象后,再按照css样式[title="Sunday, August 14, 2016"]查找,找到之后执行点击的交互命令。
- 还是查找——by对象按照css样式formControlName=endDate查找,返回对象后,再按照css样式span[role=button]查找,找到之后执行点击的交互命令。
- 再找一次——by对象按照标签名字kendo-calendar-viewlist查找,返回对象后,再按照css样式[title="Thursday, May 7, 2020"]查找,找到之后执行点击的交互命令。
以上命令其实是从历史数据中,找到航班运行时间是August 14, 2016~May 7, 2020的数据。最后再是点击搜索按钮。
获取表格行数
显示按照标签名字查找‘tbody’的locator,返回为elementFinder。然后使用all方法,查找‘tr’标签名的所有elementFinder。接着发出计数命令,返回为promise对象。
之前说过,上面的代码就是类创建,下面的代码是测试脚本
import { browser, logging, element, by } from 'protractor'; import { ReconcileFlightPage } from './page/reconcile-flight.po'; describe('admin module', () => { let reconcileFlightPage: ReconcileFlightPage; beforeAll(() => { browser.manage().timeouts().pageLoadTimeout(60000); browser.manage().timeouts().implicitlyWait(50000); browser.ignoreSynchronization = true; reconcileFlightPage = new ReconcileFlightPage(); }); beforeEach(() => { }); it('should display page title', () => { reconcileFlightPage.navigateTo(); expect(reconcileFlightPage.getTitleText()).toEqual('Reconcile Flight'); }); it('should search and get the result', () => { reconcileFlightPage.navigateTo(); reconcileFlightPage.search(); expect(reconcileFlightPage.getGridRowCount()).toEqual(10); }); afterEach(async () => { // Assert that there are no errors emitted from the browser const logs = await browser.manage().logs().get(logging.Type.BROWSER); expect(logs).not.toContain(jasmine.objectContaining({ level: logging.Level.SEVERE, } as logging.Entry)); }); });
首先是调用protractor中的接口,同时还调用之前创建的ReconcileFlightPage类。
接下来是测试代码。
第一步是describe函数,之前介绍过,可以看做是一个user story。创建好后,先声明一个ReconcileFlightPage类。
第二步是setup。通过beforeAll函数,为测试做准备。看到代码8-10行,就是浏览器打开响应之类的内容。第11行就是之前ReconcileFlightPage类的实例化。
第三步还是setup,是在每个it块运行前的准备工作,从15-16行看出,这里没有对每个it块的准备工作。
第四步就是运行。第1个运行的是‘should display page title’,即测试有无展现页面的名称。调用ReconcileFlightPage类,先进入指定页面,然后获取文本函数,再加入断言。之后是aftereach工作。再后面是第2个it运行‘should search and get the result’,即应当搜索并获取结果。调用ReconcileFlightPage类,先进入指定页面,然后进行搜索,再加入断言。之后是aftereach工作。
第五步是teardown。一部分清理缓存的工作,已经在第四步中,以aftereach介绍了。找理讲,应该还有afterall。
以上就是这个demo的全部内容,难度为1星。