webdriveragent-specs.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342
  1. import { BOOTSTRAP_PATH } from '../../lib/utils';
  2. import { WebDriverAgent } from '../../lib/webdriveragent';
  3. import * as utils from '../../lib/utils';
  4. import chai from 'chai';
  5. import chaiAsPromised from 'chai-as-promised';
  6. import path from 'path';
  7. import _ from 'lodash';
  8. import sinon from 'sinon';
  9. chai.should();
  10. chai.use(chaiAsPromised);
  11. const fakeConstructorArgs = {
  12. device: 'some sim',
  13. platformVersion: '9',
  14. host: 'me',
  15. port: '5000',
  16. realDevice: false
  17. };
  18. const defaultAgentPath = path.resolve(BOOTSTRAP_PATH, 'WebDriverAgent.xcodeproj');
  19. const customBootstrapPath = '/path/to/wda';
  20. const customAgentPath = '/path/to/some/agent/WebDriverAgent.xcodeproj';
  21. const customDerivedDataPath = '/path/to/some/agent/DerivedData/';
  22. describe('Constructor', function () {
  23. it('should have a default wda agent if not specified', function () {
  24. let agent = new WebDriverAgent({}, fakeConstructorArgs);
  25. agent.bootstrapPath.should.eql(BOOTSTRAP_PATH);
  26. agent.agentPath.should.eql(defaultAgentPath);
  27. });
  28. it('should have custom wda bootstrap and default agent if only bootstrap specified', function () {
  29. let agent = new WebDriverAgent({}, _.defaults({
  30. bootstrapPath: customBootstrapPath,
  31. }, fakeConstructorArgs));
  32. agent.bootstrapPath.should.eql(customBootstrapPath);
  33. agent.agentPath.should.eql(path.resolve(customBootstrapPath, 'WebDriverAgent.xcodeproj'));
  34. });
  35. it('should have custom wda bootstrap and agent if both specified', function () {
  36. let agent = new WebDriverAgent({}, _.defaults({
  37. bootstrapPath: customBootstrapPath,
  38. agentPath: customAgentPath,
  39. }, fakeConstructorArgs));
  40. agent.bootstrapPath.should.eql(customBootstrapPath);
  41. agent.agentPath.should.eql(customAgentPath);
  42. });
  43. it('should have custom derivedDataPath if specified', function () {
  44. let agent = new WebDriverAgent({}, _.defaults({
  45. derivedDataPath: customDerivedDataPath
  46. }, fakeConstructorArgs));
  47. agent.xcodebuild.derivedDataPath.should.eql(customDerivedDataPath);
  48. });
  49. });
  50. describe('launch', function () {
  51. it('should use webDriverAgentUrl override and return current status', async function () {
  52. const override = 'http://mockurl:8100/';
  53. const args = Object.assign({}, fakeConstructorArgs);
  54. args.webDriverAgentUrl = override;
  55. const agent = new WebDriverAgent({}, args);
  56. const wdaStub = sinon.stub(agent, 'getStatus');
  57. wdaStub.callsFake(function () {
  58. return {build: 'data'};
  59. });
  60. await agent.launch('sessionId').should.eventually.eql({build: 'data'});
  61. agent.url.href.should.eql(override);
  62. agent.jwproxy.server.should.eql('mockurl');
  63. agent.jwproxy.port.should.eql('8100');
  64. agent.jwproxy.base.should.eql('');
  65. agent.noSessionProxy.server.should.eql('mockurl');
  66. agent.noSessionProxy.port.should.eql('8100');
  67. agent.noSessionProxy.base.should.eql('');
  68. wdaStub.reset();
  69. });
  70. });
  71. describe('use wda proxy url', function () {
  72. it('should use webDriverAgentUrl wda proxy url', async function () {
  73. const override = 'http://127.0.0.1:8100/aabbccdd';
  74. const args = Object.assign({}, fakeConstructorArgs);
  75. args.webDriverAgentUrl = override;
  76. const agent = new WebDriverAgent({}, args);
  77. const wdaStub = sinon.stub(agent, 'getStatus');
  78. wdaStub.callsFake(function () {
  79. return {build: 'data'};
  80. });
  81. await agent.launch('sessionId').should.eventually.eql({build: 'data'});
  82. agent.url.port.should.eql('8100');
  83. agent.url.hostname.should.eql('127.0.0.1');
  84. agent.url.path.should.eql('/aabbccdd');
  85. agent.jwproxy.server.should.eql('127.0.0.1');
  86. agent.jwproxy.port.should.eql('8100');
  87. agent.jwproxy.base.should.eql('/aabbccdd');
  88. agent.noSessionProxy.server.should.eql('127.0.0.1');
  89. agent.noSessionProxy.port.should.eql('8100');
  90. agent.noSessionProxy.base.should.eql('/aabbccdd');
  91. });
  92. });
  93. describe('get url', function () {
  94. it('should use default WDA listening url', function () {
  95. const args = Object.assign({}, fakeConstructorArgs);
  96. const agent = new WebDriverAgent({}, args);
  97. agent.url.href.should.eql('http://127.0.0.1:8100/');
  98. });
  99. it('should use default WDA listening url with emply base url', function () {
  100. const wdaLocalPort = '9100';
  101. const wdaBaseUrl = '';
  102. const args = Object.assign({}, fakeConstructorArgs);
  103. args.wdaBaseUrl = wdaBaseUrl;
  104. args.wdaLocalPort = wdaLocalPort;
  105. const agent = new WebDriverAgent({}, args);
  106. agent.url.href.should.eql('http://127.0.0.1:9100/');
  107. });
  108. it('should use customised WDA listening url', function () {
  109. const wdaLocalPort = '9100';
  110. const wdaBaseUrl = 'http://mockurl';
  111. const args = Object.assign({}, fakeConstructorArgs);
  112. args.wdaBaseUrl = wdaBaseUrl;
  113. args.wdaLocalPort = wdaLocalPort;
  114. const agent = new WebDriverAgent({}, args);
  115. agent.url.href.should.eql('http://mockurl:9100/');
  116. });
  117. it('should use customised WDA listening url with slash', function () {
  118. const wdaLocalPort = '9100';
  119. const wdaBaseUrl = 'http://mockurl/';
  120. const args = Object.assign({}, fakeConstructorArgs);
  121. args.wdaBaseUrl = wdaBaseUrl;
  122. args.wdaLocalPort = wdaLocalPort;
  123. const agent = new WebDriverAgent({}, args);
  124. agent.url.href.should.eql('http://mockurl:9100/');
  125. });
  126. it('should use the given webDriverAgentUrl and ignore other params', function () {
  127. const args = Object.assign({}, fakeConstructorArgs);
  128. args.wdaBaseUrl = 'http://mockurl/';
  129. args.wdaLocalPort = '9100';
  130. args.webDriverAgentUrl = 'https://127.0.0.1:8100/';
  131. const agent = new WebDriverAgent({}, args);
  132. agent.url.href.should.eql('https://127.0.0.1:8100/');
  133. });
  134. });
  135. describe('setupCaching()', function () {
  136. let wda;
  137. let wdaStub;
  138. let wdaStubUninstall;
  139. const getTimestampStub = sinon.stub(utils, 'getWDAUpgradeTimestamp');
  140. beforeEach(function () {
  141. wda = new WebDriverAgent('1');
  142. wdaStub = sinon.stub(wda, 'getStatus');
  143. wdaStubUninstall = sinon.stub(wda, 'uninstall');
  144. });
  145. afterEach(function () {
  146. for (const stub of [wdaStub, wdaStubUninstall, getTimestampStub]) {
  147. if (stub) {
  148. stub.reset();
  149. }
  150. }
  151. });
  152. it('should not call uninstall since no Running WDA', async function () {
  153. wdaStub.callsFake(function () {
  154. return null;
  155. });
  156. wdaStubUninstall.callsFake(_.noop);
  157. await wda.setupCaching();
  158. wdaStub.calledOnce.should.be.true;
  159. wdaStubUninstall.notCalled.should.be.true;
  160. _.isUndefined(wda.webDriverAgentUrl).should.be.true;
  161. });
  162. it('should not call uninstall since running WDA has only time', async function () {
  163. wdaStub.callsFake(function () {
  164. return {build: { time: 'Jun 24 2018 17:08:21' }};
  165. });
  166. wdaStubUninstall.callsFake(_.noop);
  167. await wda.setupCaching();
  168. wdaStub.calledOnce.should.be.true;
  169. wdaStubUninstall.notCalled.should.be.true;
  170. wda.webDriverAgentUrl.should.equal('http://127.0.0.1:8100/');
  171. });
  172. it('should call uninstall once since bundle id is not default without updatedWDABundleId capability', async function () {
  173. wdaStub.callsFake(function () {
  174. return {build: { time: 'Jun 24 2018 17:08:21', productBundleIdentifier: 'com.example.WebDriverAgent' }};
  175. });
  176. wdaStubUninstall.callsFake(_.noop);
  177. await wda.setupCaching();
  178. wdaStub.calledOnce.should.be.true;
  179. wdaStubUninstall.calledOnce.should.be.true;
  180. _.isUndefined(wda.webDriverAgentUrl).should.be.true;
  181. });
  182. it('should call uninstall once since bundle id is different with updatedWDABundleId capability', async function () {
  183. wdaStub.callsFake(function () {
  184. return {build: { time: 'Jun 24 2018 17:08:21', productBundleIdentifier: 'com.example.different.WebDriverAgent' }};
  185. });
  186. wdaStubUninstall.callsFake(_.noop);
  187. await wda.setupCaching();
  188. wdaStub.calledOnce.should.be.true;
  189. wdaStubUninstall.calledOnce.should.be.true;
  190. _.isUndefined(wda.webDriverAgentUrl).should.be.true;
  191. });
  192. it('should not call uninstall since bundle id is equal to updatedWDABundleId capability', async function () {
  193. wda = new WebDriverAgent('1', { updatedWDABundleId: 'com.example.WebDriverAgent' });
  194. wdaStub = sinon.stub(wda, 'getStatus');
  195. wdaStubUninstall = sinon.stub(wda, 'uninstall');
  196. wdaStub.callsFake(function () {
  197. return {build: { time: 'Jun 24 2018 17:08:21', productBundleIdentifier: 'com.example.WebDriverAgent' }};
  198. });
  199. wdaStubUninstall.callsFake(_.noop);
  200. await wda.setupCaching();
  201. wdaStub.calledOnce.should.be.true;
  202. wdaStubUninstall.notCalled.should.be.true;
  203. wda.webDriverAgentUrl.should.equal('http://127.0.0.1:8100/');
  204. });
  205. it('should call uninstall if current revision differs from the bundled one', async function () {
  206. wdaStub.callsFake(function () {
  207. return {build: { upgradedAt: '1' }};
  208. });
  209. getTimestampStub.callsFake(() => '2');
  210. wdaStubUninstall.callsFake(_.noop);
  211. await wda.setupCaching();
  212. wdaStub.calledOnce.should.be.true;
  213. wdaStubUninstall.calledOnce.should.be.true;
  214. });
  215. it('should not call uninstall if current revision is the same as the bundled one', async function () {
  216. wdaStub.callsFake(function () {
  217. return {build: { upgradedAt: '1' }};
  218. });
  219. getTimestampStub.callsFake(() => '1');
  220. wdaStubUninstall.callsFake(_.noop);
  221. await wda.setupCaching();
  222. wdaStub.calledOnce.should.be.true;
  223. wdaStubUninstall.notCalled.should.be.true;
  224. });
  225. it('should not call uninstall if current revision cannot be retrieved from WDA status', async function () {
  226. wdaStub.callsFake(function () {
  227. return {build: {}};
  228. });
  229. getTimestampStub.callsFake(() => '1');
  230. wdaStubUninstall.callsFake(_.noop);
  231. await wda.setupCaching();
  232. wdaStub.calledOnce.should.be.true;
  233. wdaStubUninstall.notCalled.should.be.true;
  234. });
  235. it('should not call uninstall if current revision cannot be retrieved from the file system', async function () {
  236. wdaStub.callsFake(function () {
  237. return {build: { upgradedAt: '1' }};
  238. });
  239. getTimestampStub.callsFake(() => null);
  240. wdaStubUninstall.callsFake(_.noop);
  241. await wda.setupCaching();
  242. wdaStub.calledOnce.should.be.true;
  243. wdaStubUninstall.notCalled.should.be.true;
  244. });
  245. describe('uninstall', function () {
  246. let device;
  247. let wda;
  248. let deviceGetBundleIdsStub;
  249. let deviceRemoveAppStub;
  250. beforeEach(function () {
  251. device = {
  252. getUserInstalledBundleIdsByBundleName: () => {},
  253. removeApp: () => {}
  254. };
  255. wda = new WebDriverAgent('1', {device});
  256. deviceGetBundleIdsStub = sinon.stub(device, 'getUserInstalledBundleIdsByBundleName');
  257. deviceRemoveAppStub = sinon.stub(device, 'removeApp');
  258. });
  259. afterEach(function () {
  260. for (const stub of [deviceGetBundleIdsStub, deviceRemoveAppStub]) {
  261. if (stub) {
  262. stub.reset();
  263. }
  264. }
  265. });
  266. it('should not call uninstall', async function () {
  267. deviceGetBundleIdsStub.callsFake(() => []);
  268. await wda.uninstall();
  269. deviceGetBundleIdsStub.calledOnce.should.be.true;
  270. deviceRemoveAppStub.notCalled.should.be.true;
  271. });
  272. it('should call uninstall once', async function () {
  273. const uninstalledBundIds = [];
  274. deviceGetBundleIdsStub.callsFake(() => ['com.appium.WDA1']);
  275. deviceRemoveAppStub.callsFake((id) => uninstalledBundIds.push(id));
  276. await wda.uninstall();
  277. deviceGetBundleIdsStub.calledOnce.should.be.true;
  278. deviceRemoveAppStub.calledOnce.should.be.true;
  279. uninstalledBundIds.should.eql(['com.appium.WDA1']);
  280. });
  281. it('should call uninstall twice', async function () {
  282. const uninstalledBundIds = [];
  283. deviceGetBundleIdsStub.callsFake(() => ['com.appium.WDA1', 'com.appium.WDA2']);
  284. deviceRemoveAppStub.callsFake((id) => uninstalledBundIds.push(id));
  285. await wda.uninstall();
  286. deviceGetBundleIdsStub.calledOnce.should.be.true;
  287. deviceRemoveAppStub.calledTwice.should.be.true;
  288. uninstalledBundIds.should.eql(['com.appium.WDA1', 'com.appium.WDA2']);
  289. });
  290. });
  291. });