UNPKG

web2driver

Version:

Pure-JS, browser-based WebDriver (+ Appium) client

275 lines 21.9 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const index_1 = __importDefault(require("../index")); const chai_1 = __importDefault(require("chai")); const should_1 = __importDefault(require("should")); chai_1.default.use(should_1.default); const MOCHA_TIMEOUT = 60000; const INIT_TIMEOUT = 120000; const SERVER = "127.0.0.1"; const PORT = 4723; const OPTS = { hostname: SERVER, port: PORT, path: '/', connectionRetryCount: 0, }; const CAPS = { platformName: "iOS", browserName: "Safari", 'appium:platformVersion': "16.2", 'appium:deviceName': "iPhone 13", 'appium:automationName': "XCUITest" }; const TEST_URL = "http://localhost:1234/fixture.html"; if (typeof mocha !== 'undefined') { mocha.setup({ timeout: MOCHA_TIMEOUT }); } describe('Web2Driver', function () { let driver; before(function () { return __awaiter(this, void 0, void 0, function* () { this.timeout(INIT_TIMEOUT); driver = yield index_1.default.remote(OPTS, CAPS); yield driver.navigateTo(TEST_URL); }); }); after(function () { return __awaiter(this, void 0, void 0, function* () { yield driver.quit(); }); }); it('should store the session id', function () { driver.sessionId.should.be.a.string; }); it('should have capabilities from the session', function () { driver.capabilities.should.be.a.object; driver.capabilities.platformName.should.eql('iOS'); }); it('should not be able to use jsonwp commands', function () { return __awaiter(this, void 0, void 0, function* () { should_1.default.not.exist(driver.setImplicitWaitTimeout); }); }); it('should be able to use mjsonwp commands', function () { return __awaiter(this, void 0, void 0, function* () { const ctxs = yield driver.getContexts(); ctxs.length.should.be.above(1); }); }); it('should be able to find elements and do stuff to them', function () { return __awaiter(this, void 0, void 0, function* () { const el = yield driver.findElement('id', 'header'); (yield el.getText()).should.eql('This is a header'); }); }); it('should throw errors for not found elements', function () { return __awaiter(this, void 0, void 0, function* () { let err; try { yield driver.findElement('id', 'notathingatall'); } catch (_err) { err = _err; } should_1.default.exist(err); err.message.should.match(/element could not be located/); }); }); it('should be able to find multiple elements', function () { return __awaiter(this, void 0, void 0, function* () { const els = yield driver.findElements('id', 'header'); (yield els[0].getText()).should.eql('This is a header'); }); }); it('should be able to find an element from an element', function () { return __awaiter(this, void 0, void 0, function* () { const el = yield driver.findElement('id', 'outerDiv'); const el2 = yield el.findElement('tag name', 'div'); (yield el2.getText()).should.eql('This is an inner div'); }); }); it('should be able to find multiple elements from an element', function () { return __awaiter(this, void 0, void 0, function* () { const el = yield driver.findElement('id', 'outerDiv'); const ps = yield el.findElements('tag name', 'p'); const validTexts = ['This is an outer div', 'This is an inner div']; for (const p of ps) { validTexts.should.containEql(yield p.getText()); } }); }); it('should serialize elements for use in executeScript', function () { return __awaiter(this, void 0, void 0, function* () { const el = yield driver.findElement('id', 'innerDiv'); const p = yield el.findElement('tag name', 'p'); const res = yield driver.executeScript("return arguments[0].innerHTML;", [p]); res.should.eql('This is an inner div'); }); }); it('should be able to run w3c actions', function () { return __awaiter(this, void 0, void 0, function* () { yield driver.performActions([{ type: 'pointer', id: 'finger1', parameters: { pointerType: 'touch' }, actions: [ { type: 'pointerMove', duration: 0, x: 500, y: 500 }, { type: 'pointerDown', button: 0 }, { type: 'pause', duration: 200 }, { type: 'pointerUp', button: 0 }, ] }]); }); }); it('should be able to send keys', function () { return __awaiter(this, void 0, void 0, function* () { const ctx = yield driver.getContext(); yield driver.switchContext('NATIVE_APP'); try { let el = yield driver.waitForElement(1000, 'accessibility id', 'TabBarItemTitle'); yield el.click(); el = yield driver.waitForElement(1000, 'accessibility id', 'URL'); (yield el.getText()).should.not.eql('foo'); yield el.sendKeys("foo"); (yield el.getText()).should.eql('foo'); el = yield driver.waitForElement(1000, 'accessibility id', 'CancelBarItemButton'); yield el.click(); } finally { yield driver.switchContext(ctx); } }); }); it('should respect implicit wait timeout', function () { return __awaiter(this, void 0, void 0, function* () { let start = Date.now(); try { yield driver.findElement('id', 'doesnotexist'); } catch (ign) { } (Date.now() - start).should.be.below(1000); yield driver.setTimeouts(2000); start = Date.now(); try { yield driver.findElement('id', 'doesnotexist'); } catch (ign) { } (Date.now() - start).should.be.above(1900); }); }); it('should be able to explicitly wait for an element', function () { return __awaiter(this, void 0, void 0, function* () { yield driver.waitForElement(2000, 'id', 'innerDiv'); }); }); it('should throw an error after timeout for explicit wait', function () { return __awaiter(this, void 0, void 0, function* () { let start = Date.now(); try { yield driver.waitForElement(2000, 'id', 'doesnotexist'); } catch (ign) { } (Date.now() - start).should.be.above(2000); }); }); it('should be able to explicitly wait for multiple elements', function () { return __awaiter(this, void 0, void 0, function* () { (yield driver.waitForElements(2000, 'id', 'innerDiv')).should.have.length(1); }); }); it('should throw an error after timeout for explicit wait, even for multiple elements', function () { return __awaiter(this, void 0, void 0, function* () { let start = Date.now(); try { yield driver.waitForElements(2000, 'id', 'doesnotexist'); } catch (ign) { } (Date.now() - start).should.be.above(2000); }); }); it('should be able to attach to an existing session', function () { return __awaiter(this, void 0, void 0, function* () { const driver2 = yield index_1.default.attachToSession(driver.sessionId, { hostname: SERVER, port: PORT, path: '/', }); (yield driver2.getUrl()).should.eql(TEST_URL); }); }); }); describe('Web2Driver - Auth details', function () { it('should be able to send auth details without error', function () { return __awaiter(this, void 0, void 0, function* () { let err; const opts = { connectionRetryCount: 0, hostname: SERVER, key: "foo", path: "/", port: PORT, protocol: "http", user: "user", }; const caps = {}; try { yield index_1.default.remote(opts, caps); } catch (e) { err = e; } // we expect an error because appium servers don't allow the authorization header, but if we // get this far, we knew we sent it ok anyway err.message.should.match(/Failed to (fetch|create session)/); }); }); }); describe('Web2Driver - Direct Connect', function () { let driver = null; beforeEach(function () { this.timeout(INIT_TIMEOUT); }); it('should not use direct connection caps if they are not all present', function () { return __awaiter(this, void 0, void 0, function* () { driver = yield index_1.default.remote(OPTS, Object.assign({}, CAPS, { 'appium:directConnectPort': PORT + 1, })); yield driver.navigateTo("http://localhost:8080/test/fixture.html"); driver.connectedUrl.should.eql(`http://${SERVER}:${PORT}/`); }); }); it('should attempt to use new connection details in response capabilities', function () { return __awaiter(this, void 0, void 0, function* () { driver = yield index_1.default.remote(OPTS, Object.assign({}, CAPS, { 'appium:directConnectProtocol': 'http', 'appium:directConnectHost': SERVER, 'appium:directConnectPort': PORT, 'appium:directConnectPath': '', })); yield driver.navigateTo("http://localhost:8080/test/fixture.html"); driver.connectedUrl.should.eql(`http://${SERVER}:${PORT}`); }); }); afterEach(function () { return __awaiter(this, void 0, void 0, function* () { if (driver) { yield driver.quit(); driver = null; } }); }); }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi90ZXN0L2luZGV4LmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7O0FBQUEscURBQWtDO0FBQ2xDLGdEQUF3QjtBQUN4QixvREFBNEI7QUFFNUIsY0FBSSxDQUFDLEdBQUcsQ0FBQyxnQkFBTSxDQUFDLENBQUM7QUFFakIsTUFBTSxhQUFhLEdBQUcsS0FBSyxDQUFDO0FBQzVCLE1BQU0sWUFBWSxHQUFHLE1BQU0sQ0FBQztBQUU1QixNQUFNLE1BQU0sR0FBRyxXQUFXLENBQUM7QUFDM0IsTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDO0FBQ2xCLE1BQU0sSUFBSSxHQUFHO0lBQ1gsUUFBUSxFQUFFLE1BQU07SUFDaEIsSUFBSSxFQUFFLElBQUk7SUFDVixJQUFJLEVBQUUsR0FBRztJQUNULG9CQUFvQixFQUFFLENBQUM7Q0FDeEIsQ0FBQTtBQUNELE1BQU0sSUFBSSxHQUFHO0lBQ1gsWUFBWSxFQUFFLEtBQUs7SUFDbkIsV0FBVyxFQUFFLFFBQVE7SUFDckIsd0JBQXdCLEVBQUUsTUFBTTtJQUNoQyxtQkFBbUIsRUFBRSxXQUFXO0lBQ2hDLHVCQUF1QixFQUFFLFVBQVU7Q0FDcEMsQ0FBQztBQUVGLE1BQU0sUUFBUSxHQUFHLG9DQUFvQyxDQUFDO0FBRXRELElBQUksT0FBTyxLQUFLLEtBQUssV0FBVyxFQUFFO0lBQ2hDLEtBQUssQ0FBQyxLQUFLLENBQUMsRUFBQyxPQUFPLEVBQUUsYUFBYSxFQUFDLENBQUMsQ0FBQztDQUN2QztBQUVELFFBQVEsQ0FBQyxZQUFZLEVBQUU7SUFFckIsSUFBSSxNQUFNLENBQUM7SUFFWCxNQUFNLENBQUM7O1lBQ0wsSUFBSSxDQUFDLE9BQU8sQ0FBQyxZQUFZLENBQUMsQ0FBQztZQUUzQixNQUFNLEdBQUcsTUFBTSxlQUFVLENBQUMsTUFBTSxDQUFDLElBQUksRUFBRSxJQUFJLENBQUMsQ0FBQztZQUU3QyxNQUFNLE1BQU0sQ0FB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