From 515894b8ccc3c58ea47573104aeff6b9af11a1b3 Mon Sep 17 00:00:00 2001 From: Jonathan Lipps Date: Thu, 11 Oct 2018 15:05:47 -0700 Subject: [PATCH] add unit tests for custom element finding plugin --- lib/basedriver/commands/find.js | 2 +- test/basedriver/commands/find-specs.js | 79 ++++++++++++++++++- .../fixtures/custom-element-finder-bad.js | 5 ++ .../fixtures/custom-element-finder.js | 29 +++++++ 4 files changed, 113 insertions(+), 2 deletions(-) create mode 100644 test/basedriver/fixtures/custom-element-finder-bad.js create mode 100644 test/basedriver/fixtures/custom-element-finder.js diff --git a/lib/basedriver/commands/find.js b/lib/basedriver/commands/find.js index cc83d812d..8c9b8d378 100644 --- a/lib/basedriver/commands/find.js +++ b/lib/basedriver/commands/find.js @@ -371,5 +371,5 @@ helpers.getScreenshotForImageFind = async function (screenWidth, screenHeight) { Object.assign(extensions, commands, helpers); -export { commands, helpers, IMAGE_STRATEGY }; +export { commands, helpers, IMAGE_STRATEGY, CUSTOM_STRATEGY }; export default extensions; diff --git a/test/basedriver/commands/find-specs.js b/test/basedriver/commands/find-specs.js index 512dcf587..048c3cb5e 100644 --- a/test/basedriver/commands/find-specs.js +++ b/test/basedriver/commands/find-specs.js @@ -1,8 +1,9 @@ import chai from 'chai'; +import path from 'path'; import chaiAsPromised from 'chai-as-promised'; import sinon from 'sinon'; import { BaseDriver, ImageElement } from '../../..'; -import { IMAGE_STRATEGY } from '../../../lib/basedriver/commands/find'; +import { IMAGE_STRATEGY, CUSTOM_STRATEGY } from '../../../lib/basedriver/commands/find'; import { imageUtil } from 'appium-support'; @@ -14,6 +15,11 @@ class TestDriver extends BaseDriver { async getScreenshot () {} } +const CUSTOM_FIND_MODULE = path.resolve(__dirname, "..", "..", "..", "..", + "test", "basedriver", "fixtures", "custom-element-finder"); +const BAD_CUSTOM_FIND_MODULE = path.resolve(__dirname, "..", "..", "..", "..", + "test", "basedriver", "fixtures", "custom-element-finder-bad"); + const TINY_PNG = "iVBORw0KGgoAAAANSUhEUgAAAAQAAAAECAIAAAAmkwkpAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyhpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQwIDc5LjE2MDQ1MSwgMjAxNy8wNS8wNi0wMTowODoyMSAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTggKE1hY2ludG9zaCkiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6N0NDMDM4MDM4N0U2MTFFOEEzMzhGMTRFNUUwNzIwNUIiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6N0NDMDM4MDQ4N0U2MTFFOEEzMzhGMTRFNUUwNzIwNUIiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo3Q0MwMzgwMTg3RTYxMUU4QTMzOEYxNEU1RTA3MjA1QiIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo3Q0MwMzgwMjg3RTYxMUU4QTMzOEYxNEU1RTA3MjA1QiIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PpdvJjQAAAAlSURBVHjaJInBEQAACIKw/Xe2Ul5wYBtwmJqkk4+zfvUQVoABAEg0EfrZwc0hAAAAAElFTkSuQmCC"; const TINY_PNG_DIMS = [4, 4]; @@ -191,3 +197,74 @@ describe('finding elements by image', function () { }); }); }); + +describe('custom element finding plugins', function () { + // happys + it('should find a single element using a custom finder', async function () { + const d = new BaseDriver(); + d.opts.customFindModules = {f: CUSTOM_FIND_MODULE}; + await d.findElement(CUSTOM_STRATEGY, "f:foo").should.eventually.eql("bar"); + }); + it('should not require selector prefix if only one find plugin is registered', async function () { + const d = new BaseDriver(); + d.opts.customFindModules = {f: CUSTOM_FIND_MODULE}; + await d.findElement(CUSTOM_STRATEGY, "foo").should.eventually.eql("bar"); + }); + it('should find multiple elements using a custom finder', async function () { + const d = new BaseDriver(); + d.opts.customFindModules = {f: CUSTOM_FIND_MODULE}; + await d.findElements(CUSTOM_STRATEGY, "f:foos").should.eventually.eql(["baz1", "baz2"]); + }); + it('should give a hint to the plugin about whether multiple are requested', async function () { + const d = new BaseDriver(); + d.opts.customFindModules = {f: CUSTOM_FIND_MODULE}; + await d.findElement(CUSTOM_STRATEGY, "f:foos").should.eventually.eql("bar1"); + }); + it('should be able to use multiple find modules', async function () { + const d = new BaseDriver(); + d.opts.customFindModules = {f: CUSTOM_FIND_MODULE, g: CUSTOM_FIND_MODULE}; + await d.findElement(CUSTOM_STRATEGY, "f:foo").should.eventually.eql("bar"); + await d.findElement(CUSTOM_STRATEGY, "g:foo").should.eventually.eql("bar"); + }); + + // errors + it('should throw an error if customFindModules is not set', async function () { + const d = new BaseDriver(); + await d.findElement(CUSTOM_STRATEGY, "f:foo").should.eventually.be.rejectedWith(/customFindModules/); + }); + it('should throw an error if customFindModules is the wrong shape', async function () { + const d = new BaseDriver(); + d.opts.customFindModules = CUSTOM_FIND_MODULE; + await d.findElement(CUSTOM_STRATEGY, "f:foo").should.eventually.be.rejectedWith(/customFindModules/); + }); + it('should throw an error if customFindModules is size > 1 and no selector prefix is used', async function () { + const d = new BaseDriver(); + d.opts.customFindModules = {f: CUSTOM_FIND_MODULE, g: CUSTOM_FIND_MODULE}; + await d.findElement(CUSTOM_STRATEGY, "foo").should.eventually.be.rejectedWith(/multiple element finding/i); + }); + it('should throw an error in attempt to use unregistered plugin', async function () { + const d = new BaseDriver(); + d.opts.customFindModules = {f: CUSTOM_FIND_MODULE, g: CUSTOM_FIND_MODULE}; + await d.findElement(CUSTOM_STRATEGY, "z:foo").should.eventually.be.rejectedWith(/was not registered/); + }); + it('should throw an error if plugin cannot be loaded', async function () { + const d = new BaseDriver(); + d.opts.customFindModules = {f: "./foo.js"}; + await d.findElement(CUSTOM_STRATEGY, "f:foo").should.eventually.be.rejectedWith(/could not load/i); + }); + it('should throw an error if plugin is not the right shape', async function () { + const d = new BaseDriver(); + d.opts.customFindModules = {f: BAD_CUSTOM_FIND_MODULE}; + await d.findElement(CUSTOM_STRATEGY, "f:foo").should.eventually.be.rejectedWith(/constructed correctly/i); + }); + it('should pass on an error thrown by the finder itself', async function () { + const d = new BaseDriver(); + d.opts.customFindModules = {f: CUSTOM_FIND_MODULE}; + await d.findElement(CUSTOM_STRATEGY, "f:error").should.eventually.be.rejectedWith(/plugin error/i); + }); + it('should throw no such element error if element not found', async function () { + const d = new BaseDriver(); + d.opts.customFindModules = {f: CUSTOM_FIND_MODULE}; + await d.findElement(CUSTOM_STRATEGY, "f:nope").should.eventually.be.rejectedWith(/could not be located/); + }); +}); diff --git a/test/basedriver/fixtures/custom-element-finder-bad.js b/test/basedriver/fixtures/custom-element-finder-bad.js new file mode 100644 index 000000000..2d69ff12e --- /dev/null +++ b/test/basedriver/fixtures/custom-element-finder-bad.js @@ -0,0 +1,5 @@ +module.exports = { + notFind: function () { // eslint-disable-line object-shorthand + return []; + } +}; diff --git a/test/basedriver/fixtures/custom-element-finder.js b/test/basedriver/fixtures/custom-element-finder.js new file mode 100644 index 000000000..0e86b7a61 --- /dev/null +++ b/test/basedriver/fixtures/custom-element-finder.js @@ -0,0 +1,29 @@ +module.exports = { + find: function (driver, logger, selector, multiple) { // eslint-disable-line object-shorthand + if (!driver || !driver.opts) { + throw new Error("Expected driver object"); + } + + if (!logger || !logger.info) { + throw new Error("Expected logger object"); + } + + if (selector === "foo") { + return ["bar"]; + } + + if (selector === "foos") { + if (multiple) { + return ["baz1", "baz2"]; + } + + return ["bar1", "bar2"]; + } + + if (selector === "error") { + throw new Error("This is a plugin error"); + } + + return []; + } +};