WebDriverTest.php 38 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109
  1. <?php
  2. use Codeception\Step;
  3. use Codeception\Util\Stub;
  4. use Facebook\WebDriver\Remote\DesiredCapabilities;
  5. use Facebook\WebDriver\Remote\RemoteWebDriver;
  6. use Facebook\WebDriver\WebDriverBy;
  7. use Facebook\WebDriver\WebDriverKeys;
  8. require_once codecept_data_dir() . 'app/data.php';
  9. require_once __DIR__ . '/../unit/Codeception/Module/TestsForBrowsers.php';
  10. class WebDriverTest extends TestsForBrowsers
  11. {
  12. /**
  13. * @var \Codeception\Module\WebDriver
  14. */
  15. protected $module;
  16. /**
  17. * @var RemoteWebDriver
  18. */
  19. protected $webDriver;
  20. const MODULE_CLASS = 'Codeception\Module\WebDriver';
  21. const WEBDRIVER_CLASS = 'Facebook\WebDriver\Remote\RemoteWebDriver';
  22. public function _before()
  23. {
  24. $this->module = $this->getModule('WebDriver');
  25. $this->webDriver = &$this->getModule('WebDriver')->webDriver;
  26. }
  27. public function _after()
  28. {
  29. data::clean();
  30. }
  31. public function testClickEventOnCheckbox()
  32. {
  33. $this->module->amOnPage('/form/checkbox');
  34. $this->module->uncheckOption('#checkin');
  35. $this->module->dontSee('ticked', '#notice');
  36. $this->module->checkOption('#checkin');
  37. $this->module->see('ticked', '#notice');
  38. }
  39. public function testAcceptPopup()
  40. {
  41. $this->notForPhantomJS();
  42. $this->module->amOnPage('/form/popup');
  43. $this->module->click('Confirm');
  44. $this->module->acceptPopup();
  45. $this->module->see('Yes', '#result');
  46. }
  47. public function testCancelPopup()
  48. {
  49. $this->notForPhantomJS();
  50. $this->module->amOnPage('/form/popup');
  51. $this->module->click('Confirm');
  52. $this->module->cancelPopup();
  53. $this->module->see('No', '#result');
  54. }
  55. public function testSelectByCss()
  56. {
  57. $this->module->amOnPage('/form/select');
  58. $this->module->selectOption('form select[name=age]', '21-60');
  59. $this->module->click('Submit');
  60. $form = data::get('form');
  61. $this->assertEquals('adult', $form['age']);
  62. }
  63. public function testSelectInvalidOptionForSecondSelectFails()
  64. {
  65. $this->shouldFail();
  66. $this->module->amOnPage('/form/select_second');
  67. $this->module->selectOption('#select2', 'Value2');
  68. }
  69. public function testSeeInPopup()
  70. {
  71. $this->notForPhantomJS();
  72. $this->module->amOnPage('/form/popup');
  73. $this->module->click('Alert');
  74. $this->module->seeInPopup('Really?');
  75. $this->module->cancelPopup();
  76. }
  77. public function testFailedSeeInPopup()
  78. {
  79. $this->notForPhantomJS();
  80. $this->setExpectedException(
  81. '\PHPUnit\Framework\AssertionFailedError',
  82. 'Failed asserting that \'Really?\' contains "Different text"'
  83. );
  84. $this->module->amOnPage('/form/popup');
  85. $this->module->click('Alert');
  86. $this->module->seeInPopup('Different text');
  87. $this->module->cancelPopup();
  88. }
  89. public function testDontSeeInPopup()
  90. {
  91. $this->notForPhantomJS();
  92. $this->module->amOnPage('/form/popup');
  93. $this->module->click('Alert');
  94. $this->module->dontSeeInPopup('Different text');
  95. $this->module->cancelPopup();
  96. }
  97. public function testFailedDontSeeInPopup()
  98. {
  99. $this->notForPhantomJS();
  100. $this->setExpectedException(
  101. '\PHPUnit\Framework\AssertionFailedError',
  102. 'Failed asserting that \'Really?\' does not contain "Really?"'
  103. );
  104. $this->module->amOnPage('/form/popup');
  105. $this->module->click('Alert');
  106. $this->module->dontSeeInPopup('Really?');
  107. $this->module->cancelPopup();
  108. }
  109. public function testScreenshot()
  110. {
  111. $this->module->amOnPage('/');
  112. @unlink(\Codeception\Configuration::outputDir().'testshot.png');
  113. $testName="debugTest";
  114. $this->module->makeScreenshot($testName);
  115. $this->assertFileExists(\Codeception\Configuration::outputDir().'debug/'.$testName.'.png');
  116. @unlink(\Codeception\Configuration::outputDir().'debug/'.$testName.'.png');
  117. $this->module->_saveScreenshot(\Codeception\Configuration::outputDir().'testshot.png');
  118. $this->assertFileExists(\Codeception\Configuration::outputDir().'testshot.png');
  119. @unlink(\Codeception\Configuration::outputDir().'testshot.png');
  120. }
  121. public function testSubmitForm()
  122. {
  123. $this->module->amOnPage('/form/complex');
  124. $this->module->submitForm('form', [
  125. 'name' => 'Davert',
  126. 'age' => 'child',
  127. 'terms' => 'agree',
  128. 'description' => 'My Bio'
  129. ]);
  130. $form = data::get('form');
  131. $this->assertEquals('Davert', $form['name']);
  132. $this->assertEquals('kill_all', $form['action']);
  133. $this->assertEquals('My Bio', $form['description']);
  134. $this->assertEquals('agree', $form['terms']);
  135. $this->assertEquals('child', $form['age']);
  136. }
  137. public function testSubmitFormWithNumbers()
  138. {
  139. $this->module->amOnPage('/form/complex');
  140. $this->module->submitForm('form', [
  141. 'name' => 'Davert',
  142. 'age' => 'child',
  143. 'terms' => 'agree',
  144. 'description' => 10
  145. ]);
  146. $form = data::get('form');
  147. $this->assertEquals('Davert', $form['name']);
  148. $this->assertEquals('kill_all', $form['action']);
  149. $this->assertEquals('10', $form['description']);
  150. $this->assertEquals('agree', $form['terms']);
  151. $this->assertEquals('child', $form['age']);
  152. }
  153. /**
  154. * @dataProvider strictSelectorProvider
  155. */
  156. public function testSubmitFormWithButtonAsStrictSelector(array $selector)
  157. {
  158. $this->module->amOnPage('/form/strict_selectors');
  159. $this->module->submitForm('form', [
  160. 'name' => 'Davert',
  161. 'age' => 'child',
  162. 'terms' => 'agree',
  163. 'description' => 'My Bio'
  164. ], $selector);
  165. $form = data::get('form');
  166. $this->assertEquals('Davert', $form['name']);
  167. $this->assertEquals('kill_all', $form['action']);
  168. $this->assertEquals('My Bio', $form['description']);
  169. $this->assertEquals('agree', $form['terms']);
  170. $this->assertEquals('child', $form['age']);
  171. }
  172. public function strictSelectorProvider()
  173. {
  174. return [
  175. 'by id' => [['id' => 'submit_button']],
  176. 'by name' => [['name' => 'submit_button_name']],
  177. 'by css' => [['css' => 'form #submit_button']],
  178. 'by xpath' => [['xpath' => '//*[@id="submit_button"]']],
  179. 'by link' => [['link' => 'Submit']],
  180. 'by class' => [['class' => 'button']],
  181. ];
  182. }
  183. /**
  184. * @dataProvider webDriverByProvider
  185. */
  186. public function testSubmitFormWithButtonAsWebDriverBy(WebDriverBy $selector)
  187. {
  188. $this->module->amOnPage('/form/strict_selectors');
  189. $this->module->submitForm('form', [
  190. 'name' => 'Davert',
  191. 'age' => 'child',
  192. 'terms' => 'agree',
  193. 'description' => 'My Bio'
  194. ], $selector);
  195. $form = data::get('form');
  196. $this->assertEquals('Davert', $form['name']);
  197. $this->assertEquals('kill_all', $form['action']);
  198. $this->assertEquals('My Bio', $form['description']);
  199. $this->assertEquals('agree', $form['terms']);
  200. $this->assertEquals('child', $form['age']);
  201. }
  202. public function webDriverByProvider()
  203. {
  204. return [
  205. 'by id' => [WebDriverBy::id('submit_button')],
  206. 'by name' => [WebDriverBy::name('submit_button_name')],
  207. 'by css selector' => [WebDriverBy::cssSelector('form #submit_button')],
  208. 'by xpath' => [WebDriverBy::xpath('//*[@id="submit_button"]')],
  209. 'by link text' => [WebDriverBy::linkText('Submit')],
  210. 'by class name' => [WebDriverBy::className('button')],
  211. ];
  212. }
  213. public function testRadioButtonByValue()
  214. {
  215. $this->module->amOnPage('/form/radio');
  216. $this->module->selectOption('form', 'disagree');
  217. $this->module->click('Submit');
  218. $form = data::get('form');
  219. $this->assertEquals('disagree', $form['terms']);
  220. }
  221. public function testRadioButtonByLabelOnContext()
  222. {
  223. $this->module->amOnPage('/form/radio');
  224. $this->module->selectOption('form input', 'Get Off');
  225. $this->module->seeOptionIsSelected('form input', 'disagree');
  226. $this->module->dontSeeOptionIsSelected('form input', 'agree');
  227. $this->module->click('Submit');
  228. $form = data::get('form');
  229. $this->assertEquals('disagree', $form['terms']);
  230. }
  231. public function testRadioButtonByLabel()
  232. {
  233. $this->module->amOnPage('/form/radio');
  234. $this->module->checkOption('Get Off');
  235. $this->module->click('Submit');
  236. $form = data::get('form');
  237. $this->assertEquals('disagree', $form['terms']);
  238. }
  239. public function testRawSelenium()
  240. {
  241. $this->module->amOnPage('/');
  242. $this->module->executeInSelenium(function ($webdriver) {
  243. $webdriver->findElement(WebDriverBy::id('link'))->click();
  244. });
  245. $this->module->seeCurrentUrlEquals('/info');
  246. }
  247. public function testKeys()
  248. {
  249. $this->module->amOnPage('/form/field');
  250. $this->module->pressKey('#name', ['ctrl', 'a'], WebDriverKeys::DELETE);
  251. $this->module->pressKey('#name', 'test', ['shift', '111']);
  252. $this->module->pressKey('#name', '1');
  253. $this->module->seeInField('#name', 'test!!!1');
  254. }
  255. public function testWait()
  256. {
  257. $this->module->amOnPage('/');
  258. $time = time();
  259. $this->module->wait(3);
  260. $this->assertGreaterThanOrEqual($time+3, time());
  261. }
  262. public function testSelectInvalidOptionFails()
  263. {
  264. $this->shouldFail();
  265. $this->module->amOnPage('/form/select');
  266. $this->module->selectOption('#age', '13-22');
  267. }
  268. public function testAppendFieldSelect()
  269. {
  270. $this->module->amOnPage('/form/select_multiple');
  271. $this->module->selectOption('form #like', 'eat');
  272. $this->module->appendField('form #like', 'code');
  273. $this->module->click('Submit');
  274. $form = data::get('form');
  275. $this->assertEmpty(array_diff($form['like'], ["eat", "code"]));
  276. }
  277. public function testAppendFieldSelectFails()
  278. {
  279. $this->shouldFail();
  280. $this->module->amOnPage('/form/select_multiple');
  281. $this->module->appendField('form #like', 'code123');
  282. }
  283. public function testAppendFieldTextarea()
  284. {
  285. $this->module->amOnPage('/form/textarea');
  286. $this->module->fillField('form #description', 'eat');
  287. $this->module->appendField('form #description', ' code');
  288. $this->module->click('Submit');
  289. $form = data::get('form');
  290. $this->assertEquals('eat code', $form['description']);
  291. }
  292. public function testAppendFieldTextareaFails()
  293. {
  294. $this->shouldFail();
  295. $this->module->amOnPage('/form/textarea');
  296. $this->module->appendField('form #description123', ' code');
  297. }
  298. public function testAppendFieldText()
  299. {
  300. $this->module->amOnPage('/form/field');
  301. $this->module->appendField('form #name', ' code');
  302. $this->module->click('Submit');
  303. $form = data::get('form');
  304. $this->assertEquals('OLD_VALUE code', $form['name']);
  305. }
  306. public function testAppendFieldTextFails()
  307. {
  308. $this->shouldFail();
  309. $this->module->amOnPage('/form/field');
  310. $this->module->appendField('form #name123', ' code');
  311. }
  312. public function testAppendFieldCheckboxByValue()
  313. {
  314. $this->module->amOnPage('/form/checkbox');
  315. $this->module->appendField('form input[name=terms]', 'agree');
  316. $this->module->click('Submit');
  317. $form = data::get('form');
  318. $this->assertEquals('agree', $form['terms']);
  319. }
  320. public function testAppendFieldCheckboxByValueFails()
  321. {
  322. $this->shouldFail();
  323. $this->module->amOnPage('/form/checkbox');
  324. $this->module->appendField('form input[name=terms]', 'agree123');
  325. }
  326. public function testAppendFieldCheckboxByLabel()
  327. {
  328. $this->module->amOnPage('/form/checkbox');
  329. $this->module->appendField('form input[name=terms]', 'I Agree');
  330. $this->module->click('Submit');
  331. $form = data::get('form');
  332. $this->assertEquals('agree', $form['terms']);
  333. }
  334. public function testAppendFieldCheckboxByLabelFails()
  335. {
  336. $this->shouldFail();
  337. $this->module->amOnPage('/form/checkbox');
  338. $this->module->appendField('form input[name=terms]', 'I Agree123');
  339. }
  340. public function testAppendFieldRadioButtonByValue()
  341. {
  342. $this->module->amOnPage('/form/radio');
  343. $this->module->appendField('form input[name=terms]', 'disagree');
  344. $this->module->click('Submit');
  345. $form = data::get('form');
  346. $this->assertEquals('disagree', $form['terms']);
  347. }
  348. public function testAppendFieldRadioButtonByValueFails()
  349. {
  350. $this->shouldFail();
  351. $this->module->amOnPage('/form/radio');
  352. $this->module->appendField('form input[name=terms]', 'disagree123');
  353. }
  354. public function testAppendFieldRadioButtonByLabel()
  355. {
  356. $this->module->amOnPage('/form/radio');
  357. $this->module->appendField('form input[name=terms]', 'Get Off');
  358. $this->module->click('Submit');
  359. $form = data::get('form');
  360. $this->assertEquals('disagree', $form['terms']);
  361. }
  362. public function testAppendFieldRadioButtonByLabelFails()
  363. {
  364. $this->shouldFail();
  365. $this->module->amOnPage('/form/radio');
  366. $this->module->appendField('form input[name=terms]', 'Get Off123');
  367. }
  368. public function testPauseExecution()
  369. {
  370. $this->module->amOnPage('/');
  371. $this->module->pauseExecution();
  372. }
  373. // Issue https://github.com/Codeception/Codeception/pull/875
  374. public function testFillPasswordOnFormSubmit()
  375. {
  376. $this->module->amOnPage('/form/complex');
  377. $this->module->submitForm('form', [
  378. 'password' => '123456'
  379. ]);
  380. $form = data::get('form');
  381. $this->assertEquals('123456', $form['password']);
  382. }
  383. public function testEmptyFormSubmit()
  384. {
  385. $this->shouldFail();
  386. $this->module->amOnPage('/form/complex');
  387. $this->module->submitForm('form111', []);
  388. }
  389. public function testWebDriverByLocators()
  390. {
  391. $this->module->amOnPage('/login');
  392. $this->module->seeElement(WebDriverBy::id('submit-label'));
  393. $this->module->seeElement(WebDriverBy::name('password'));
  394. $this->module->seeElement(WebDriverBy::className('optional'));
  395. $this->module->seeElement(WebDriverBy::cssSelector('form.global_form_box'));
  396. $this->module->seeElement(WebDriverBy::xpath(\Codeception\Util\Locator::tabIndex(4)));
  397. $this->module->fillField(WebDriverBy::name('password'), '123456');
  398. $this->module->amOnPage('/form/select');
  399. $this->module->selectOption(WebDriverBy::name('age'), 'child');
  400. $this->module->amOnPage('/form/checkbox');
  401. $this->module->checkOption(WebDriverBy::name('terms'));
  402. $this->module->amOnPage('/');
  403. $this->module->seeElement(WebDriverBy::linkText('Test'));
  404. $this->module->click(WebDriverBy::linkText('Test'));
  405. $this->module->seeCurrentUrlEquals('/form/hidden');
  406. }
  407. public function testSeeVisible()
  408. {
  409. $this->module->amOnPage('/info');
  410. $this->module->dontSee('Invisible text');
  411. $this->module->dontSee('Invisible', '.hidden');
  412. $this->module->seeInPageSource('Invisible text');
  413. }
  414. public function testSeeInvisible()
  415. {
  416. $this->shouldFail();
  417. $this->module->amOnPage('/info');
  418. $this->module->see('Invisible text');
  419. }
  420. public function testFailWebDriverByLocator()
  421. {
  422. $this->shouldFail();
  423. $this->module->amOnPage('/form/checkbox');
  424. $this->module->checkOption(WebDriverBy::name('age'));
  425. }
  426. // fails in PhpBrowser :(
  427. public function testSubmitUnchecked()
  428. {
  429. $this->module->amOnPage('/form/unchecked');
  430. $this->module->seeCheckboxIsChecked('#checkbox');
  431. $this->module->uncheckOption('#checkbox');
  432. $this->module->click('#submit');
  433. ;
  434. $this->module->see('0', '#notice');
  435. }
  436. public function testCreateCeptScreenshotFail()
  437. {
  438. $fakeWd = Stub::make('\Facebook\WebDriver\Remote\RemoteWebDriver', [
  439. 'takeScreenshot' => Stub::once(function () {
  440. }),
  441. 'getPageSource' => Stub::once(function () {
  442. }),
  443. 'manage' => Stub::make('\Facebook\WebDriver\WebDriverOptions', [
  444. 'getAvailableLogTypes' => Stub::atLeastOnce(function () {
  445. return [];
  446. }),
  447. ]),
  448. ]);
  449. $module = Stub::make(self::MODULE_CLASS, ['webDriver' => $fakeWd]);
  450. $cept = (new \Codeception\Test\Cept('loginCept', 'loginCept.php'));
  451. $module->_failed($cept, new \PHPUnit\Framework\AssertionFailedError());
  452. }
  453. public function testCreateCestScreenshotOnFail()
  454. {
  455. $fakeWd = Stub::make(self::WEBDRIVER_CLASS, [
  456. 'takeScreenshot' => Stub::once(function ($filename) {
  457. PHPUnit_Framework_Assert::assertEquals(codecept_log_dir('stdClass.login.fail.png'), $filename);
  458. }),
  459. 'getPageSource' => Stub::once(function () {
  460. }),
  461. 'manage' => Stub::make('\Facebook\WebDriver\WebDriverOptions', [
  462. 'getAvailableLogTypes' => Stub::atLeastOnce(function () {
  463. return [];
  464. }),
  465. ]),
  466. ]);
  467. $module = Stub::make(self::MODULE_CLASS, ['webDriver' => $fakeWd]);
  468. $cest = new \Codeception\Test\Cest(new stdClass(), 'login', 'someCest.php');
  469. $module->_failed($cest, new \PHPUnit\Framework\AssertionFailedError());
  470. }
  471. public function testCreateTestScreenshotOnFail()
  472. {
  473. $test = Stub::make('\Codeception\TestCase\Test', ['getName' => 'testLogin']);
  474. $fakeWd = Stub::make(self::WEBDRIVER_CLASS, [
  475. 'takeScreenshot' => Stub::once(function ($filename) use ($test) {
  476. PHPUnit_Framework_Assert::assertEquals(
  477. codecept_log_dir(get_class($test).'.testLogin.fail.png'),
  478. $filename
  479. );
  480. }),
  481. 'getPageSource' => Stub::once(function () {
  482. }),
  483. 'manage' => Stub::make('\Facebook\WebDriver\WebDriverOptions', [
  484. 'getAvailableLogTypes' => Stub::atLeastOnce(function () {
  485. return [];
  486. }),
  487. ]),
  488. ]);
  489. $module = Stub::make(self::MODULE_CLASS, ['webDriver' => $fakeWd]);
  490. $module->_failed($test, new \PHPUnit\Framework\AssertionFailedError());
  491. }
  492. public function testWebDriverWaits()
  493. {
  494. $fakeWd = Stub::make(self::WEBDRIVER_CLASS, ['wait' => Stub::exactly(12, function () {
  495. return new \Codeception\Util\Maybe();
  496. })]);
  497. $module = Stub::make(self::MODULE_CLASS, ['webDriver' => $fakeWd]);
  498. $module->waitForElement(WebDriverBy::partialLinkText('yeah'));
  499. $module->waitForElement(['id' => 'user']);
  500. $module->waitForElement(['css' => '.user']);
  501. $module->waitForElement('//xpath');
  502. $module->waitForElementVisible(WebDriverBy::partialLinkText('yeah'));
  503. $module->waitForElementVisible(['id' => 'user']);
  504. $module->waitForElementVisible(['css' => '.user']);
  505. $module->waitForElementVisible('//xpath');
  506. $module->waitForElementNotVisible(WebDriverBy::partialLinkText('yeah'));
  507. $module->waitForElementNotVisible(['id' => 'user']);
  508. $module->waitForElementNotVisible(['css' => '.user']);
  509. $module->waitForElementNotVisible('//xpath');
  510. }
  511. public function testWaitForElement()
  512. {
  513. $this->module->amOnPage('/form/timeout');
  514. $this->module->waitForElement('#btn');
  515. $this->module->click('Click');
  516. $this->module->see('Hello');
  517. }
  518. public function testImplicitWait()
  519. {
  520. $this->module->_reconfigure(['wait' => 5]);
  521. $this->module->amOnPage('/form/timeout');
  522. $this->module->click('#btn');
  523. $this->module->see('Hello');
  524. }
  525. public function testBug1467()
  526. {
  527. $this->module->amOnPage('/form/bug1467');
  528. $this->module->selectOption('form[name=form2] input[name=first_test_radio]', 'Yes');
  529. $this->module->selectOption('form[name=form2] input[name=second_test_radio]', 'No');
  530. $this->module->seeOptionIsSelected('form[name=form2] input[name=first_test_radio]', 'Yes');
  531. $this->module->seeOptionIsSelected('form[name=form2] input[name=second_test_radio]', 'No');
  532. // shouldn't have touched form1 at all
  533. $this->module->dontSeeOptionIsSelected('form[name=form1] input[name=first_test_radio]', 'No');
  534. $this->module->dontSeeOptionIsSelected('form[name=form1] input[name=first_test_radio]', 'Yes');
  535. $this->module->dontSeeOptionIsSelected('form[name=form1] input[name=second_test_radio]', 'No');
  536. $this->module->dontSeeOptionIsSelected('form[name=form1] input[name=second_test_radio]', 'Yes');
  537. }
  538. /**
  539. * @Issue 1598
  540. */
  541. public function testWaitForTextBug1598()
  542. {
  543. $this->module->amOnPage('/form/bug1598');
  544. $this->module->waitForText('12,345', 10, '#field');
  545. }
  546. public function testSeeElementMalformedWdLocator()
  547. {
  548. $this->setExpectedException('Codeception\Exception\MalformedLocatorException');
  549. $this->module->amOnPage('/');
  550. $this->module->seeElement(WebDriverBy::xpath('H---EY!'));
  551. }
  552. public function testBug1637()
  553. {
  554. $this->module->amOnPage('/form/bug1637');
  555. // confirm that options outside a form are still selectable
  556. $this->module->selectOption('input[name=first_test_radio]', 'Yes');
  557. // confirm that it did what we expected and did not do anything else
  558. $this->module->seeOptionIsSelected('input[name=first_test_radio]', 'Yes');
  559. $this->module->dontSeeOptionIsSelected('input[name=first_test_radio]', 'No');
  560. }
  561. public function testBug2046()
  562. {
  563. $this->module->webDriver = null;
  564. $this->module->_saveScreenshot(\Codeception\Configuration::outputDir().'testshot.png');
  565. }
  566. public function testSessionSnapshots()
  567. {
  568. $this->notForPhantomJS();
  569. $this->module->amOnPage('/');
  570. $this->module->setCookie('PHPSESSID', '123456', ['path' => '/']);
  571. $this->module->saveSessionSnapshot('login');
  572. $this->module->seeCookie('PHPSESSID');
  573. $this->webDriver->manage()->deleteAllCookies();
  574. $this->module->dontSeeCookie('PHPSESSID');
  575. $this->module->loadSessionSnapshot('login');
  576. $this->module->seeCookie('PHPSESSID');
  577. }
  578. public function testSaveSessionSnapshotsExcludeInvalidCookieDomains()
  579. {
  580. $this->notForPhantomJS();
  581. $fakeWdOptions = Stub::make('\Facebook\WebDriver\WebDriverOptions', [
  582. 'getCookies' => Stub::atLeastOnce(function () {
  583. return [
  584. [
  585. 'name' => 'PHPSESSID',
  586. 'value' => '123456',
  587. 'path' => '/',
  588. ],
  589. [
  590. 'name' => '3rdParty',
  591. 'value' => '_value_',
  592. 'path' => '/',
  593. 'domain' => '.3rd-party.net',
  594. ]
  595. ];
  596. }),
  597. ]);
  598. $fakeWd = Stub::make(self::WEBDRIVER_CLASS, [
  599. 'manage' => Stub::atLeastOnce(function () use ($fakeWdOptions) {
  600. return $fakeWdOptions;
  601. }),
  602. ]);
  603. // Mock the WebDriverOptions::getCookies() method on the first call to introduce a 3rd-party cookie
  604. // which has to be ignored when saving a snapshot.
  605. $originalWebDriver = $this->module->webDriver;
  606. $this->module->webDriver = $fakeWd;
  607. $this->module->seeCookie('PHPSESSID');
  608. $this->module->seeCookie('3rdParty');
  609. $this->module->saveSessionSnapshot('login');
  610. // Restore the original WebDriver
  611. $this->module->webDriver = $originalWebDriver;
  612. $this->webDriver->manage()->deleteAllCookies();
  613. $this->module->dontSeeCookie('PHPSESSID');
  614. $this->module->dontSeeCookie('3rdParty');
  615. $this->module->amOnPage('/');
  616. $this->module->loadSessionSnapshot('login');
  617. $this->module->seeCookie('PHPSESSID');
  618. $this->module->dontSeeCookie('3rdParty');
  619. }
  620. public function testSeeInFieldTextarea()
  621. {
  622. $this->module->amOnPage('/form/textarea');
  623. //make sure we see 'sunrise' which is the default text in the textarea
  624. $this->module->seeInField('#description', 'sunrise');
  625. if ($this->notForSelenium()) {
  626. $this->module->seeInField('#whitespaces', ' no_whitespaces ');
  627. }
  628. $this->module->seeInField('#whitespaces', 'no_whitespaces');
  629. //fill in some new text and see if we can see it
  630. $textarea_value = 'test string';
  631. $this->module->fillField('#description', $textarea_value);
  632. $this->module->seeInField('#description', $textarea_value);
  633. }
  634. public function testSeeInFieldSelect()
  635. {
  636. $this->module->amOnPage('/form/select_second');
  637. if ($this->notForSelenium()) {
  638. $this->module->seeInField('#select2', ' no_whitespaces ');
  639. }
  640. $this->module->seeInField('#select2', 'no_whitespaces');
  641. // select new option and check it
  642. $option_value = 'select2_value1';
  643. $this->module->selectOption('#select2', $option_value);
  644. $this->module->seeInField('#select2', $option_value);
  645. }
  646. public function testAppendFieldDiv()
  647. {
  648. $this->notForPhantomJS();
  649. $this->module->amOnPage('/form/div_content_editable');
  650. //make sure we see 'sunrise' which is the default text in the textarea
  651. $this->module->see('sunrise', '#description');
  652. //fill in some new text and see if we can see it
  653. $textarea_value = 'moonrise';
  654. $this->module->appendField('#description', $textarea_value);
  655. $this->module->see('sunrise' . $textarea_value, '#description');
  656. }
  657. public function testOpenPageException()
  658. {
  659. if (!$this->module->_getConfig('restart')) {
  660. $this->markTestSkipped('works only on restarts');
  661. }
  662. parent::testOpenPageException();
  663. }
  664. public function testCookies()
  665. {
  666. $this->notForPhantomJS();
  667. parent::testCookies();
  668. }
  669. public function testSendingCookies()
  670. {
  671. $this->notForPhantomJS();
  672. parent::testSendingCookies();
  673. }
  674. public function testCookiesWithPath()
  675. {
  676. $this->notForPhantomJS();
  677. parent::testCookiesWithPath();
  678. }
  679. protected function notForPhantomJS()
  680. {
  681. if ($this->module->_getConfig('browser') == 'phantomjs') {
  682. $this->markTestSkipped('does not work for phantomjs');
  683. }
  684. }
  685. protected function notForSelenium()
  686. {
  687. if ($this->module->_getConfig('browser') != 'phantom') {
  688. $this->markTestSkipped('does not work for selenium');
  689. }
  690. }
  691. public function testScrollTo()
  692. {
  693. $this->module->amOnPage('/form/example18');
  694. $this->module->scrollTo('#clickme');
  695. $this->module->click('Submit');
  696. $this->module->see('Welcome to test app!');
  697. }
  698. /**
  699. * @Issue 2921
  700. */
  701. public function testSeeInFieldForTextarea()
  702. {
  703. $this->module->amOnPage('/form/bug2921');
  704. $this->module->seeInField('foo', 'bar baz');
  705. }
  706. /**
  707. * @Issue 4726
  708. */
  709. public function testClearField()
  710. {
  711. $this->module->amOnPage('/form/textarea');
  712. $this->module->fillField('#description', 'description');
  713. $this->module->clearField('#description');
  714. $this->module->dontSeeInField('#description', 'description');
  715. }
  716. public function testClickHashLink()
  717. {
  718. $this->module->amOnPage('/form/anchor');
  719. $this->module->click('Hash Link');
  720. $this->module->seeCurrentUrlEquals('/form/anchor#b');
  721. }
  722. /**
  723. * @Issue 3865
  724. */
  725. public function testClickNumericLink()
  726. {
  727. $this->module->amOnPage('/form/bug3865');
  728. $this->module->click('222');
  729. $this->module->see('Welcome to test app');
  730. }
  731. public function testClickHashButton()
  732. {
  733. $this->module->amOnPage('/form/anchor');
  734. $this->module->click('Hash Button');
  735. $this->module->seeCurrentUrlEquals('/form/anchor#c');
  736. }
  737. public function testSubmitHashForm()
  738. {
  739. $this->module->amOnPage('/form/anchor');
  740. $this->module->click('Hash Form');
  741. $this->module->seeCurrentUrlEquals('/form/anchor#a');
  742. }
  743. public function testSubmitHashButtonForm()
  744. {
  745. $this->module->amOnPage('/form/anchor');
  746. $this->module->click('Hash Button Form');
  747. $this->module->seeCurrentUrlEquals('/form/anchor#a');
  748. }
  749. public function testJSErrorLoggingPositive()
  750. {
  751. // arrange
  752. $this->module->_setConfig(['log_js_errors' => true]);
  753. $cept = new \Codeception\Test\Cept('foo', 'bar');
  754. // act
  755. $this->module->amOnPage('/jserroronload');
  756. $this->module->_failed($cept, 'anyFailMessage');
  757. // assert
  758. /* @var $steps Step[] */
  759. $steps = $cept->getScenario()->getSteps();
  760. $this->assertGreaterThan(0, count($steps));
  761. $lastStep = end($steps);
  762. $this->assertContains(
  763. "TypeError",
  764. $lastStep->getHtml()
  765. );
  766. }
  767. public function testJSErrorLoggingNegative()
  768. {
  769. // arrange
  770. $this->module->_setConfig(['log_js_errors' => false]);
  771. $cept = new \Codeception\Test\Cept('foo', 'bar');
  772. // act
  773. $this->module->amOnPage('/jserroronload');
  774. $this->module->_failed($cept, 'anyFailMessage');
  775. // assert
  776. /* @var $steps Step[] */
  777. $steps = $cept->getScenario()->getSteps();
  778. $this->assertCount(0, $steps);
  779. }
  780. public function testMoveMouseOver()
  781. {
  782. $this->module->amOnPage('/form/click');
  783. $this->module->moveMouseOver(null, 123, 88);
  784. $this->module->clickWithLeftButton(null, 0, 0);
  785. $this->module->see('click, offsetX: 123 - offsetY: 88');
  786. $this->module->moveMouseOver(null, 10, 10);
  787. $this->module->clickWithLeftButton(null, 0, 0);
  788. $this->module->see('click, offsetX: 133 - offsetY: 98');
  789. $this->module->moveMouseOver('#element2');
  790. $this->module->clickWithLeftButton(null, 0, 0);
  791. $this->module->see('click, offsetX: 58 - offsetY: 158');
  792. $this->module->moveMouseOver('#element2', 0, 0);
  793. $this->module->clickWithLeftButton(null, 0, 0);
  794. $this->module->see('click, offsetX: 8 - offsetY: 108');
  795. }
  796. public function testLeftClick()
  797. {
  798. $this->module->amOnPage('/form/click');
  799. $this->module->clickWithLeftButton(null, 123, 88);
  800. $this->module->see('click, offsetX: 123 - offsetY: 88');
  801. $this->module->clickWithLeftButton('body');
  802. $this->module->see('click, offsetX: 600 - offsetY: 384');
  803. $this->module->clickWithLeftButton('body', 50, 75);
  804. $this->module->see('click, offsetX: 58 - offsetY: 83');
  805. $this->module->clickWithLeftButton('body div');
  806. $this->module->see('click, offsetX: 58 - offsetY: 58');
  807. $this->module->clickWithLeftButton('#element2', 70, 75);
  808. $this->module->see('click, offsetX: 78 - offsetY: 183');
  809. }
  810. public function testRightClick()
  811. {
  812. // actually not supported in phantomjs see https://github.com/ariya/phantomjs/issues/14005
  813. $this->notForPhantomJS();
  814. $this->module->amOnPage('/form/click');
  815. $this->module->clickWithRightButton(null, 123, 88);
  816. $this->module->see('context, offsetX: 123 - offsetY: 88');
  817. $this->module->clickWithRightButton('body');
  818. $this->module->see('context, offsetX: 600 - offsetY: 384');
  819. $this->module->clickWithRightButton('body', 50, 75);
  820. $this->module->see('context, offsetX: 58 - offsetY: 83');
  821. $this->module->clickWithRightButton('body div');
  822. $this->module->see('context, offsetX: 58 - offsetY: 58');
  823. $this->module->clickWithRightButton('#element2', 70, 75);
  824. $this->module->see('context, offsetX: 78 - offsetY: 183');
  825. }
  826. public function testBrowserTabs()
  827. {
  828. $this->notForPhantomJS();
  829. $this->module->amOnPage('/form/example1');
  830. $this->module->openNewTab();
  831. $this->module->amOnPage('/form/example2');
  832. $this->module->openNewTab();
  833. $this->module->amOnPage('/form/example3');
  834. $this->module->openNewTab();
  835. $this->module->amOnPage('/form/example4');
  836. $this->module->openNewTab();
  837. $this->module->amOnPage('/form/example5');
  838. $this->module->closeTab();
  839. $this->module->seeInCurrentUrl('example4');
  840. $this->module->switchToPreviousTab(2);
  841. $this->module->seeInCurrentUrl('example2');
  842. $this->module->switchToNextTab();
  843. $this->module->seeInCurrentUrl('example3');
  844. $this->module->closeTab();
  845. $this->module->seeInCurrentUrl('example2');
  846. $this->module->switchToNextTab(2);
  847. $this->module->seeInCurrentUrl('example1');
  848. }
  849. public function testPerformOnWithArray()
  850. {
  851. $asserts = PHPUnit_Framework_Assert::getCount();
  852. $this->module->amOnPage('/form/example1');
  853. $this->module->performOn('.rememberMe', [
  854. 'see' => 'Remember me next time',
  855. 'seeElement' => '#LoginForm_rememberMe',
  856. 'dontSee' => 'Login'
  857. ]);
  858. $this->assertEquals(3, PHPUnit_Framework_Assert::getCount() - $asserts);
  859. $this->module->see('Login');
  860. }
  861. public function testPerformOnWithCallback()
  862. {
  863. $asserts = PHPUnit_Framework_Assert::getCount();
  864. $this->module->amOnPage('/form/example1');
  865. $this->module->performOn('.rememberMe', function (\Codeception\Module\WebDriver $I) {
  866. $I->see('Remember me next time');
  867. $I->seeElement('#LoginForm_rememberMe');
  868. $I->dontSee('Login');
  869. });
  870. $this->assertEquals(3, PHPUnit_Framework_Assert::getCount() - $asserts);
  871. $this->module->see('Login');
  872. }
  873. public function testPerformOnWithBuiltArray()
  874. {
  875. $asserts = PHPUnit_Framework_Assert::getCount();
  876. $this->module->amOnPage('/form/example1');
  877. $this->module->performOn('.rememberMe', \Codeception\Util\ActionSequence::build()
  878. ->see('Remember me next time')
  879. ->seeElement('#LoginForm_rememberMe')
  880. ->dontSee('Login')
  881. );
  882. $this->assertEquals(3, PHPUnit_Framework_Assert::getCount() - $asserts);
  883. $this->module->see('Login');
  884. }
  885. public function testPerformOnWithArrayAndSimilarActions()
  886. {
  887. $asserts = PHPUnit_Framework_Assert::getCount();
  888. $this->module->amOnPage('/form/example1');
  889. $this->module->performOn('.rememberMe', \Codeception\Util\ActionSequence::build()
  890. ->see('Remember me')
  891. ->see('next time')
  892. ->dontSee('Login')
  893. );
  894. $this->assertEquals(3, PHPUnit_Framework_Assert::getCount() - $asserts);
  895. $this->module->see('Login');
  896. }
  897. public function testPerformOnFail()
  898. {
  899. $this->shouldFail();
  900. $this->module->amOnPage('/form/example1');
  901. $this->module->performOn('.rememberMe', \Codeception\Util\ActionSequence::build()
  902. ->seeElement('#LoginForm_rememberMe')
  903. ->see('Remember me tomorrow')
  904. );
  905. }
  906. public function testPerformOnFail2()
  907. {
  908. $this->shouldFail();
  909. $this->module->amOnPage('/form/example1');
  910. $this->module->performOn('.rememberMe', ['see' => 'Login']);
  911. }
  912. public function testSwitchToIframe()
  913. {
  914. $this->module->amOnPage('iframe');
  915. $this->module->switchToIFrame('content');
  916. $this->module->see('Lots of valuable data here');
  917. $this->module->switchToIFrame();
  918. $this->module->see('Iframe test');
  919. }
  920. public function testGrabPageSourceWhenNotOnPage()
  921. {
  922. $this->setExpectedException(
  923. '\Codeception\Exception\ModuleException',
  924. 'Current url is blank, no page was opened'
  925. );
  926. $this->module->grabPageSource();
  927. }
  928. public function testGrabPageSourceWhenOnPage()
  929. {
  930. $this->module->amOnPage('/minimal');
  931. $sourceExpected =
  932. <<<HTML
  933. <!DOCTYPE html>
  934. <html>
  935. <head>
  936. <title>
  937. Minimal page
  938. </title>
  939. </head>
  940. <body>
  941. <h1>
  942. Minimal page
  943. </h1>
  944. </body>
  945. </html>
  946. HTML
  947. ;
  948. $sourceActualRaw = $this->module->grabPageSource();
  949. // `Selenium` adds the `xmlns` attribute while `PhantomJS` does not do that.
  950. $sourceActual = str_replace('xmlns="http://www.w3.org/1999/xhtml"', '', $sourceActualRaw);
  951. $this->assertXmlStringEqualsXmlString($sourceExpected, $sourceActual);
  952. }
  953. public function testChangingCapabilities()
  954. {
  955. $this->notForPhantomJS();
  956. $this->assertNotTrue($this->module->webDriver->getCapabilities()->getCapability('acceptInsecureCerts'));
  957. $this->module->_closeSession();
  958. $this->module->_capabilities(function($current) {
  959. $current['acceptInsecureCerts'] = true;
  960. return new DesiredCapabilities($current);
  961. });
  962. $this->assertNotTrue($this->module->webDriver->getCapabilities()->getCapability('acceptInsecureCerts'));
  963. $this->module->_initializeSession();
  964. $this->assertTrue(true, $this->module->webDriver->getCapabilities()->getCapability('acceptInsecureCerts'));
  965. }
  966. }