mirror of
https://github.com/koel/koel
synced 2024-11-10 06:34:14 +00:00
Refactor for E2E
This commit is contained in:
parent
46266409d5
commit
46a52a55a6
10 changed files with 261 additions and 144 deletions
|
@ -10,9 +10,8 @@ class PlaylistScreenTest extends TestCase
|
||||||
{
|
{
|
||||||
$this->loginAndGoTo('songs')
|
$this->loginAndGoTo('songs')
|
||||||
->selectRange()
|
->selectRange()
|
||||||
->createPlaylist('Bar');
|
->createPlaylist('Bar')
|
||||||
|
->seeText('Bar', '#playlists > ul');
|
||||||
$this->seeText('Bar', '#playlists > ul');
|
|
||||||
|
|
||||||
$this->click('#sidebar .playlist:nth-last-child(1)');
|
$this->click('#sidebar .playlist:nth-last-child(1)');
|
||||||
$this->see('#playlistWrapper');
|
$this->see('#playlistWrapper');
|
||||||
|
|
|
@ -9,17 +9,17 @@ class ProfileScreenTest extends TestCase
|
||||||
{
|
{
|
||||||
public function testProfileScreen()
|
public function testProfileScreen()
|
||||||
{
|
{
|
||||||
$this->loginAndWait();
|
$this->loginAndWait()
|
||||||
$this->click('a.view-profile');
|
->click('a.view-profile');
|
||||||
$this->see('#profileWrapper');
|
$this->see('#profileWrapper')
|
||||||
// Now we change some user profile details
|
// Now we change some user profile details
|
||||||
$this->typeIn('#profileWrapper input[name="name"]', 'Mr Bar');
|
->typeIn('#profileWrapper input[name="name"]', 'Mr Bar')
|
||||||
$this->typeIn('#profileWrapper input[name="email"]', 'bar@koel.net');
|
->typeIn('#profileWrapper input[name="email"]', 'bar@koel.net')
|
||||||
$this->enter();
|
->enter()
|
||||||
$this->see('.sweet-alert');
|
->see('.sweet-alert')
|
||||||
// Dismiss the alert first
|
// Dismiss the alert first
|
||||||
$this->press(WebDriverKeys::ESCAPE);
|
->press(WebDriverKeys::ESCAPE)
|
||||||
$this->notSee('.sweet-alert');
|
->notSee('.sweet-alert');
|
||||||
|
|
||||||
$avatar = $this->el('a.view-profile img');
|
$avatar = $this->el('a.view-profile img');
|
||||||
// Expect the Gravatar to be updated
|
// Expect the Gravatar to be updated
|
||||||
|
@ -27,17 +27,17 @@ class ProfileScreenTest extends TestCase
|
||||||
|
|
||||||
// Check "Confirm Closing" and validate its functionality
|
// Check "Confirm Closing" and validate its functionality
|
||||||
$this->click('#profileWrapper input[name="confirmClosing"]');
|
$this->click('#profileWrapper input[name="confirmClosing"]');
|
||||||
$this->refresh();
|
$this->refresh()
|
||||||
$this->waitUntil(WebDriverExpectedCondition::alertIsPresent());
|
->waitUntil(WebDriverExpectedCondition::alertIsPresent());
|
||||||
$this->driver->switchTo()->alert()->dismiss();
|
$this->driver->switchTo()->alert()->dismiss();
|
||||||
|
|
||||||
// Reverse all changes for other tests to not be affected
|
// Reverse all changes for other tests to not be affected
|
||||||
$this->typeIn('#profileWrapper input[name="name"]', 'Koel Admin');
|
$this->typeIn('#profileWrapper input[name="name"]', 'Koel Admin')
|
||||||
$this->typeIn('#profileWrapper input[name="email"]', 'koel@example.com');
|
->typeIn('#profileWrapper input[name="email"]', 'koel@example.com')
|
||||||
$this->enter();
|
->enter()
|
||||||
$this->see('.sweet-alert');
|
->see('.sweet-alert')
|
||||||
$this->press(WebDriverKeys::ESCAPE);
|
->press(WebDriverKeys::ESCAPE)
|
||||||
$this->notSee('.sweet-alert');
|
->notSee('.sweet-alert')
|
||||||
$this->click('#profileWrapper input[name="confirmClosing"]');
|
->click('#profileWrapper input[name="confirmClosing"]');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,9 +11,7 @@ class QueueScreenTest extends TestCase
|
||||||
|
|
||||||
// As the queue is currently empty, the "Shuffling all song" link should be there
|
// As the queue is currently empty, the "Shuffling all song" link should be there
|
||||||
$this->click('#queueWrapper a.start');
|
$this->click('#queueWrapper a.start');
|
||||||
$this->waitUntil(function () {
|
$this->see('#queueWrapper .song-item');
|
||||||
return count($this->els('#queueWrapper .song-item'));
|
|
||||||
});
|
|
||||||
|
|
||||||
// Clear the queue
|
// Clear the queue
|
||||||
$this->click('#queueWrapper .buttons button.btn-clear-queue');
|
$this->click('#queueWrapper .buttons button.btn-clear-queue');
|
||||||
|
|
|
@ -10,34 +10,32 @@ class SideBarTest extends TestCase
|
||||||
|
|
||||||
// All basic navigation
|
// All basic navigation
|
||||||
foreach (['home', 'queue', 'songs', 'albums', 'artists', 'youtube', 'settings', 'users'] as $screen) {
|
foreach (['home', 'queue', 'songs', 'albums', 'artists', 'youtube', 'settings', 'users'] as $screen) {
|
||||||
$this->goto($screen);
|
$this->goto($screen)
|
||||||
$this->waitUntil(function () use ($screen) {
|
->waitUntil(function () use ($screen) {
|
||||||
return $this->driver->getCurrentURL() === $this->url.'/#!/'.$screen;
|
return $this->driver->getCurrentURL() === $this->url.'/#!/'.$screen;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add a playlist
|
// Add a playlist
|
||||||
$this->click('#playlists > h1 > i.create');
|
$this->click('#playlists > h1 > i.create');
|
||||||
$this->see('#playlists > form.create');
|
$this->see('#playlists > form.create')
|
||||||
$this->typeIn('#playlists > form > input[type="text"]', 'Bar');
|
->typeIn('#playlists > form > input[type="text"]', 'Bar')
|
||||||
$this->enter();
|
->enter()
|
||||||
$this->waitUntil(function () {
|
->waitUntil(function () {
|
||||||
$list = $this->els('#playlists .playlist');
|
$list = $this->els('#playlists .playlist');
|
||||||
|
return end($list)->getText() === 'Bar';
|
||||||
return end($list)->getText() === 'Bar';
|
});
|
||||||
});
|
|
||||||
|
|
||||||
// Double click to edit/rename a playlist
|
// Double click to edit/rename a playlist
|
||||||
$this->doubleClick('#playlists .playlist:nth-child(2)');
|
$this->doubleClick('#playlists .playlist:nth-child(2)')
|
||||||
$this->see('#playlists .playlist:nth-child(2) input[type="text"]');
|
->see('#playlists .playlist:nth-child(2) input[type="text"]')
|
||||||
$this->typeIn('#playlists .playlist:nth-child(2) input[type="text"]', 'Qux');
|
->typeIn('#playlists .playlist:nth-child(2) input[type="text"]', 'Qux')
|
||||||
$this->enter();
|
->enter()
|
||||||
$this->seeText('Qux', '#playlists .playlist:nth-child(2)');
|
->seeText('Qux', '#playlists .playlist:nth-child(2)');
|
||||||
|
|
||||||
// Edit with an empty name shouldn't do anything.
|
// Edit with an empty name shouldn't do anything.
|
||||||
$this->doubleClick('#playlists .playlist:nth-child(2)');
|
$this->doubleClick('#playlists .playlist:nth-child(2)');
|
||||||
$this->click('#playlists .playlist:nth-child(2) input[type="text"]')->clear();
|
$this->click('#playlists .playlist:nth-child(2) input[type="text"]')->clear();
|
||||||
$this->enter();
|
$this->enter()->seeText('Qux', '#playlists .playlist:nth-child(2)');
|
||||||
$this->seeText('Qux', '#playlists .playlist:nth-child(2)');
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,13 +55,11 @@ trait SongListActions
|
||||||
*/
|
*/
|
||||||
public function cmdSelectSongs()
|
public function cmdSelectSongs()
|
||||||
{
|
{
|
||||||
$actions = (new WebDriverActions($this->driver))
|
$actions = (new WebDriverActions($this->driver))->keyDown(null, WebDriverKeys::COMMAND);
|
||||||
->keyDown(null, WebDriverKeys::COMMAND);
|
|
||||||
foreach (func_get_args() as $i) {
|
foreach (func_get_args() as $i) {
|
||||||
$actions->click($this->el("{$this->wrapperId} tr.song-item:nth-child($i)"));
|
$actions->click($this->el("{$this->wrapperId} tr.song-item:nth-child($i)"));
|
||||||
}
|
}
|
||||||
$actions->keyUp(null, WebDriverKeys::COMMAND)
|
$actions->keyUp(null, WebDriverKeys::COMMAND)->perform();
|
||||||
->perform();
|
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
@ -77,8 +75,8 @@ trait SongListActions
|
||||||
{
|
{
|
||||||
// Try adding a song into a new playlist
|
// Try adding a song into a new playlist
|
||||||
$this->click("{$this->wrapperId} .buttons button.btn-add-to");
|
$this->click("{$this->wrapperId} .buttons button.btn-add-to");
|
||||||
$this->typeIn("{$this->wrapperId} .buttons input[type='text']", $playlistName);
|
$this->typeIn("{$this->wrapperId} .buttons input[type='text']", $playlistName)
|
||||||
$this->enter();
|
->enter();
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,6 @@ namespace E2E;
|
||||||
|
|
||||||
use Facebook\WebDriver\WebDriverBy;
|
use Facebook\WebDriver\WebDriverBy;
|
||||||
use Facebook\WebDriver\WebDriverElement;
|
use Facebook\WebDriver\WebDriverElement;
|
||||||
use Facebook\WebDriver\WebDriverExpectedCondition;
|
|
||||||
use Facebook\WebDriver\WebDriverKeys;
|
use Facebook\WebDriver\WebDriverKeys;
|
||||||
|
|
||||||
class SongListTest extends TestCase
|
class SongListTest extends TestCase
|
||||||
|
@ -38,8 +37,7 @@ class SongListTest extends TestCase
|
||||||
);
|
);
|
||||||
|
|
||||||
// Delete key should remove selected songs
|
// Delete key should remove selected songs
|
||||||
$this->press(WebDriverKeys::DELETE);
|
$this->press(WebDriverKeys::DELETE)->waitUntil(function () {
|
||||||
$this->waitUntil(function () {
|
|
||||||
return count($this->els('#queueWrapper tr.song-item.selected')) === 0
|
return count($this->els('#queueWrapper tr.song-item.selected')) === 0
|
||||||
&& count($this->els('#queueWrapper tr.song-item')) === 7;
|
&& count($this->els('#queueWrapper tr.song-item')) === 7;
|
||||||
});
|
});
|
||||||
|
@ -51,18 +49,13 @@ class SongListTest extends TestCase
|
||||||
|
|
||||||
public function testActionButtons()
|
public function testActionButtons()
|
||||||
{
|
{
|
||||||
$this->loginAndWait()->repopulateList();
|
$this->loginAndWait()
|
||||||
|
->repopulateList()
|
||||||
// Since no songs are selected, the "Shuffle All" button must be shown
|
// Since no songs are selected, the "Shuffle All" button must be shown
|
||||||
$this->waitUntil(WebDriverExpectedCondition::visibilityOfElementLocated(
|
->see('#queueWrapper button.btn-shuffle-all')
|
||||||
WebDriverBy::cssSelector('#queueWrapper button.btn-shuffle-all')
|
// Now we selected all songs for the "Shuffle Selected" button to be shown
|
||||||
));
|
->selectAllSongs()
|
||||||
|
->see('#queueWrapper button.btn-shuffle-selected');
|
||||||
// Now we selected all songs for the "Shuffle Selected" button to be shown
|
|
||||||
$this->selectAllSongs();
|
|
||||||
$this->waitUntil(WebDriverExpectedCondition::visibilityOfElementLocated(
|
|
||||||
WebDriverBy::cssSelector('#queueWrapper button.btn-shuffle-selected')
|
|
||||||
));
|
|
||||||
|
|
||||||
// Add to favorites
|
// Add to favorites
|
||||||
$this->selectSong();
|
$this->selectSong();
|
||||||
|
@ -71,13 +64,11 @@ class SongListTest extends TestCase
|
||||||
$this->goto('favorites');
|
$this->goto('favorites');
|
||||||
static::assertCount(1, $this->els('#favoritesWrapper tr.song-item'));
|
static::assertCount(1, $this->els('#favoritesWrapper tr.song-item'));
|
||||||
|
|
||||||
$this->goto('queue');
|
$this->goto('queue')
|
||||||
$this->selectSong();
|
->selectSong();
|
||||||
// Try adding a song into a new playlist
|
// Try adding a song into a new playlist
|
||||||
$this->createPlaylist('Foo');
|
$this->createPlaylist('Foo')
|
||||||
$this->waitUntil(WebDriverExpectedCondition::textToBePresentInElement(
|
->seeText('Foo', '#playlists > ul');
|
||||||
WebDriverBy::cssSelector('#playlists > ul'), 'Foo'
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testSorting()
|
public function testSorting()
|
||||||
|
@ -97,8 +88,8 @@ class SongListTest extends TestCase
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now go to All Songs screen and sort there
|
// Now go to All Songs screen and sort there
|
||||||
$this->goto('songs');
|
$this->goto('songs')
|
||||||
$this->click('#songsWrapper div.song-list-wrap th:nth-child(2)');
|
->click('#songsWrapper div.song-list-wrap th:nth-child(2)');
|
||||||
$last = null;
|
$last = null;
|
||||||
$results = [];
|
$results = [];
|
||||||
/** @var WebDriverElement $td */
|
/** @var WebDriverElement $td */
|
||||||
|
@ -124,43 +115,34 @@ class SongListTest extends TestCase
|
||||||
|
|
||||||
public function testContextMenu()
|
public function testContextMenu()
|
||||||
{
|
{
|
||||||
$this->loginAndGoTo('songs');
|
$this->loginAndGoTo('songs')
|
||||||
$this->rightClickOnSong();
|
->rightClickOnSong()
|
||||||
|
->see('#songsWrapper .song-menu');
|
||||||
$by = WebDriverBy::cssSelector('#songsWrapper .song-menu');
|
|
||||||
$this->waitUntil(WebDriverExpectedCondition::visibilityOfElementLocated($by));
|
|
||||||
|
|
||||||
// 7 sub menu items
|
// 7 sub menu items
|
||||||
static::assertCount(7, $this->els('#songsWrapper .song-menu > li'));
|
static::assertCount(7, $this->els('#songsWrapper .song-menu > li'));
|
||||||
|
|
||||||
// Clicking the "Go to Album" menu item
|
// Clicking the "Go to Album" menu item
|
||||||
$this->click('#songsWrapper .song-menu > li:nth-child(2)');
|
$this->click('#songsWrapper .song-menu > li:nth-child(2)');
|
||||||
$this->waitUntil(WebDriverExpectedCondition::visibilityOfElementLocated(
|
$this->see('#albumWrapper');
|
||||||
WebDriverBy::cssSelector('#albumWrapper')
|
|
||||||
));
|
|
||||||
|
|
||||||
// Clicking the "Go to Artist" menu item
|
// Clicking the "Go to Artist" menu item
|
||||||
$this->back();
|
$this->back()
|
||||||
$this->rightClickOnSong();
|
->rightClickOnSong()
|
||||||
$this->click('#songsWrapper .song-menu > li:nth-child(3)');
|
->click('#songsWrapper .song-menu > li:nth-child(3)');
|
||||||
$this->waitUntil(WebDriverExpectedCondition::visibilityOfElementLocated(
|
$this->see('#artistWrapper');
|
||||||
WebDriverBy::cssSelector('#artistWrapper')
|
|
||||||
));
|
|
||||||
|
|
||||||
// Clicking "Edit"
|
// Clicking "Edit"
|
||||||
$this->back();
|
$this->back()
|
||||||
$this->rightClickOnSong();
|
->rightClickOnSong()
|
||||||
$this->click('#songsWrapper .song-menu > li:nth-child(5)');
|
->click('#songsWrapper .song-menu > li:nth-child(5)');
|
||||||
$this->waitUntil(WebDriverExpectedCondition::visibilityOfElementLocated(
|
$this->see('#editSongsOverlay form');
|
||||||
WebDriverBy::cssSelector('#editSongsOverlay form')
|
|
||||||
));
|
|
||||||
// Updating song
|
// Updating song
|
||||||
$this->typeIn('#editSongsOverlay form input[name="title"]', 'Foo');
|
$this->typeIn('#editSongsOverlay form input[name="title"]', 'Foo')
|
||||||
$this->typeIn('#editSongsOverlay form input[name="track"]', 99);
|
->typeIn('#editSongsOverlay form input[name="track"]', 99)
|
||||||
$this->enter();
|
->enter()
|
||||||
$this->waitUntil(WebDriverExpectedCondition::invisibilityOfElementLocated(
|
->notSee('#editSongsOverlay form');
|
||||||
WebDriverBy::cssSelector('#editSongsOverlay form')
|
|
||||||
));
|
|
||||||
static::assertEquals('99', $this->el('#songsWrapper tr.song-item:nth-child(1) .track-number')->getText());
|
static::assertEquals('99', $this->el('#songsWrapper tr.song-item:nth-child(1) .track-number')->getText());
|
||||||
static::assertEquals('Foo', $this->el('#songsWrapper tr.song-item:nth-child(1) .title')->getText());
|
static::assertEquals('Foo', $this->el('#songsWrapper tr.song-item:nth-child(1) .title')->getText());
|
||||||
}
|
}
|
||||||
|
@ -171,5 +153,7 @@ class SongListTest extends TestCase
|
||||||
$this->goto('albums');
|
$this->goto('albums');
|
||||||
$this->click('#albumsWrapper > div > article:nth-child(1) .meta a.shuffle-album');
|
$this->click('#albumsWrapper > div > article:nth-child(1) .meta a.shuffle-album');
|
||||||
$this->goto('queue');
|
$this->goto('queue');
|
||||||
|
|
||||||
|
return $this;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,6 +58,9 @@ abstract class TestCase extends \PHPUnit_Framework_TestCase
|
||||||
return $this->app;
|
return $this->app;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reset the test data for E2E tests.
|
||||||
|
*/
|
||||||
protected function resetData()
|
protected function resetData()
|
||||||
{
|
{
|
||||||
// Make sure we have a fresh database.
|
// Make sure we have a fresh database.
|
||||||
|
@ -90,16 +93,23 @@ abstract class TestCase extends \PHPUnit_Framework_TestCase
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Log in and wait for the app to finish loading.
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*
|
||||||
|
* @throws \Exception
|
||||||
|
*/
|
||||||
protected function loginAndWait()
|
protected function loginAndWait()
|
||||||
{
|
{
|
||||||
$this->login();
|
$this->login()
|
||||||
$this->seeText('Koel Admin', '#userBadge > a.view-profile');
|
->seeText('Koel Admin', '#userBadge > a.view-profile');
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A helper to allow going to a specific screen.
|
* Go to a specific screen.
|
||||||
*
|
*
|
||||||
* @param $screen
|
* @param $screen
|
||||||
*
|
*
|
||||||
|
@ -122,11 +132,23 @@ abstract class TestCase extends \PHPUnit_Framework_TestCase
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Log in and go to a specific screen.
|
||||||
|
*
|
||||||
|
* @param $screen string
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*
|
||||||
|
* @throws \Exception
|
||||||
|
*/
|
||||||
protected function loginAndGoTo($screen)
|
protected function loginAndGoTo($screen)
|
||||||
{
|
{
|
||||||
return $this->loginAndWait()->goto($screen);
|
return $this->loginAndWait()->goto($screen);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wait for the user to press ENTER key before continuing.
|
||||||
|
*/
|
||||||
protected function waitForUserInput()
|
protected function waitForUserInput()
|
||||||
{
|
{
|
||||||
if (trim(fgets(fopen('php://stdin', 'rb'))) !== chr(13)) {
|
if (trim(fgets(fopen('php://stdin', 'rb'))) !== chr(13)) {
|
||||||
|
|
|
@ -8,26 +8,25 @@ class UsersScreenTest extends TestCase
|
||||||
{
|
{
|
||||||
public function testUsersScreen()
|
public function testUsersScreen()
|
||||||
{
|
{
|
||||||
$this->loginAndGoTo('users');
|
$this->loginAndGoTo('users')->see('.user-item.me');
|
||||||
$this->see('.user-item.me');
|
|
||||||
// Hover to the first user item
|
// Hover to the first user item
|
||||||
(new WebDriverMouseMoveAction($this->driver->getMouse(), $this->el('#usersWrapper .user-item.me')))
|
(new WebDriverMouseMoveAction($this->driver->getMouse(), $this->el('#usersWrapper .user-item.me')))
|
||||||
->perform();
|
->perform();
|
||||||
// and validate that the button reads "Update Profile" instead of "Edit"
|
// and validate that the button reads "Update Profile" instead of "Edit"
|
||||||
static::assertContains('Update Profile', $this->el('#usersWrapper .user-item.me .btn-edit')->getText());
|
static::assertContains('Update Profile',
|
||||||
|
$this->el('#usersWrapper .user-item.me .btn-edit')->getText());
|
||||||
// Also, clicking it should show the "Profile & Preferences" panel
|
// Also, clicking it should show the "Profile & Preferences" panel
|
||||||
$this->click('#usersWrapper .user-item.me .btn-edit');
|
$this->click('#usersWrapper .user-item.me .btn-edit');
|
||||||
$this->see('#profileWrapper');
|
$this->see('#profileWrapper')
|
||||||
$this->back();
|
->back()
|
||||||
|
// Add new user
|
||||||
// Add new user
|
->click('#usersWrapper .btn-add');
|
||||||
$this->click('#usersWrapper .btn-add');
|
$this->see('form.user-create')
|
||||||
$this->see('form.user-create');
|
->typeIn('form.user-create input[name="name"]', 'Foo')
|
||||||
$this->typeIn('form.user-create input[name="name"]', 'Foo');
|
->typeIn('form.user-create input[name="email"]', 'foo@koel.net')
|
||||||
$this->typeIn('form.user-create input[name="email"]', 'foo@koel.net');
|
->typeIn('form.user-create input[name="password"]', 'SecureMuch')
|
||||||
$this->typeIn('form.user-create input[name="password"]', 'SecureMuch');
|
->enter()
|
||||||
$this->enter();
|
->seeText('foo@koel.net', '#usersWrapper');
|
||||||
$this->seeText('foo@koel.net', '#usersWrapper');
|
|
||||||
|
|
||||||
// Hover the next user item (not me)
|
// Hover the next user item (not me)
|
||||||
(new WebDriverMouseMoveAction($this->driver->getMouse(), $this->el('#usersWrapper .user-item:not(.me)')))
|
(new WebDriverMouseMoveAction($this->driver->getMouse(), $this->el('#usersWrapper .user-item:not(.me)')))
|
||||||
|
@ -35,9 +34,9 @@ class UsersScreenTest extends TestCase
|
||||||
static::assertContains('Edit', $this->el('#usersWrapper .user-item:not(.me) .btn-edit')->getText());
|
static::assertContains('Edit', $this->el('#usersWrapper .user-item:not(.me) .btn-edit')->getText());
|
||||||
// Edit user
|
// Edit user
|
||||||
$this->click('#usersWrapper .user-item:not(.me) .btn-edit');
|
$this->click('#usersWrapper .user-item:not(.me) .btn-edit');
|
||||||
$this->see('form.user-edit');
|
$this->see('form.user-edit')
|
||||||
$this->typeIn('form.user-edit input[name="email"]', 'bar@koel.net');
|
->typeIn('form.user-edit input[name="email"]', 'bar@koel.net')
|
||||||
$this->enter();
|
->enter()
|
||||||
$this->seeText('bar@koel.net', '#usersWrapper');
|
->seeText('bar@koel.net', '#usersWrapper');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,16 +30,40 @@ trait WebDriverShortcuts
|
||||||
return $selector;
|
return $selector;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a list of elements by a selector.
|
||||||
|
*
|
||||||
|
* @param $selector
|
||||||
|
*
|
||||||
|
* @return \Facebook\WebDriver\Remote\RemoteWebElement[]
|
||||||
|
*/
|
||||||
protected function els($selector)
|
protected function els($selector)
|
||||||
{
|
{
|
||||||
return $this->driver->findElements(WebDriverBy::cssSelector($selector));
|
return $this->driver->findElements(WebDriverBy::cssSelector($selector));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Type a string.
|
||||||
|
*
|
||||||
|
* @param $string
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
protected function type($string)
|
protected function type($string)
|
||||||
{
|
{
|
||||||
return $this->driver->getKeyboard()->sendKeys($string);
|
$this->driver->getKeyboard()->sendKeys($string);
|
||||||
|
|
||||||
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Type into an element.
|
||||||
|
*
|
||||||
|
* @param $element
|
||||||
|
* @param $string
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
protected function typeIn($element, $string)
|
protected function typeIn($element, $string)
|
||||||
{
|
{
|
||||||
$this->click($element)->clear();
|
$this->click($element)->clear();
|
||||||
|
@ -47,41 +71,80 @@ trait WebDriverShortcuts
|
||||||
return $this->type($string);
|
return $this->type($string);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Press a key.
|
||||||
|
*
|
||||||
|
* @param string $key
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
protected function press($key = WebDriverKeys::ENTER)
|
protected function press($key = WebDriverKeys::ENTER)
|
||||||
{
|
{
|
||||||
return $this->driver->getKeyboard()->pressKey($key);
|
$this->driver->getKeyboard()->pressKey($key);
|
||||||
|
|
||||||
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Press enter.
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
protected function enter()
|
protected function enter()
|
||||||
{
|
{
|
||||||
return $this->press();
|
return $this->press();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Click an element.
|
||||||
|
*
|
||||||
|
* @param $element
|
||||||
|
*
|
||||||
|
* @return WebDriverElement
|
||||||
|
*/
|
||||||
protected function click($element)
|
protected function click($element)
|
||||||
{
|
{
|
||||||
return $this->el($element)->click();
|
return $this->el($element)->click();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Right-click an element.
|
||||||
|
*
|
||||||
|
* @param $element
|
||||||
|
*
|
||||||
|
* @return \Facebook\WebDriver\Remote\RemoteMouse
|
||||||
|
*/
|
||||||
protected function rightClick($element)
|
protected function rightClick($element)
|
||||||
{
|
{
|
||||||
return $this->driver->getMouse()->contextClick($this->el($element)->getCoordinates());
|
return $this->driver->getMouse()->contextClick($this->el($element)->getCoordinates());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Double-click and element.
|
||||||
|
*
|
||||||
|
* @param $element
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
protected function doubleClick($element)
|
protected function doubleClick($element)
|
||||||
{
|
{
|
||||||
$action = new WebDriverDoubleClickAction($this->driver->getMouse(), $this->el($element));
|
(new WebDriverDoubleClickAction($this->driver->getMouse(), $this->el($element)))->perform();
|
||||||
|
|
||||||
$action->perform();
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sleep (implicit wait) for some seconds.
|
* Sleep (implicit wait) for some seconds.
|
||||||
*
|
*
|
||||||
* @param $seconds
|
* @param $seconds
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
*/
|
*/
|
||||||
protected function sleep($seconds)
|
protected function sleep($seconds)
|
||||||
{
|
{
|
||||||
$this->driver->manage()->timeouts()->implicitlyWait($seconds);
|
$this->driver->manage()->timeouts()->implicitlyWait($seconds);
|
||||||
|
|
||||||
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -92,46 +155,102 @@ trait WebDriverShortcuts
|
||||||
*
|
*
|
||||||
* @throws \Exception
|
* @throws \Exception
|
||||||
*
|
*
|
||||||
* @return mixed
|
* @return $this
|
||||||
*/
|
*/
|
||||||
protected function waitUntil($func, $timeout = 10)
|
protected function waitUntil($func, $timeout = 10)
|
||||||
{
|
{
|
||||||
return $this->driver->wait($timeout)->until($func);
|
$this->driver->wait($timeout)->until($func);
|
||||||
|
|
||||||
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wait and validate an element to be visible.
|
||||||
|
*
|
||||||
|
* @param $selector
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*
|
||||||
|
* @throws \Exception
|
||||||
|
*/
|
||||||
public function see($selector)
|
public function see($selector)
|
||||||
{
|
{
|
||||||
return $this->waitUntil(WebDriverExpectedCondition::visibilityOfElementLocated(
|
$this->waitUntil(WebDriverExpectedCondition::visibilityOfElementLocated(
|
||||||
WebDriverBy::cssSelector($selector)
|
WebDriverBy::cssSelector($selector)
|
||||||
));
|
));
|
||||||
|
|
||||||
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wait and validate an element to be invisible.
|
||||||
|
*
|
||||||
|
* @param $selector string The element's CSS selector.
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*
|
||||||
|
* @throws \Exception
|
||||||
|
*/
|
||||||
public function notSee($selector)
|
public function notSee($selector)
|
||||||
{
|
{
|
||||||
return $this->waitUntil(WebDriverExpectedCondition::invisibilityOfElementLocated(
|
$this->waitUntil(WebDriverExpectedCondition::invisibilityOfElementLocated(
|
||||||
WebDriverBy::cssSelector($selector)
|
WebDriverBy::cssSelector($selector)
|
||||||
));
|
));
|
||||||
|
|
||||||
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wait and validate a text to be visible in an element.
|
||||||
|
*
|
||||||
|
* @param $text
|
||||||
|
* @param $selector string The element's CSS selector.
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
* @throws \Exception
|
||||||
|
*/
|
||||||
public function seeText($text, $selector)
|
public function seeText($text, $selector)
|
||||||
{
|
{
|
||||||
$this->waitUntil(WebDriverExpectedCondition::textToBePresentInElement(
|
$this->waitUntil(WebDriverExpectedCondition::textToBePresentInElement(
|
||||||
WebDriverBy::cssSelector($selector), $text
|
WebDriverBy::cssSelector($selector), $text
|
||||||
));
|
));
|
||||||
|
|
||||||
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Navigate back.
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
protected function back()
|
protected function back()
|
||||||
{
|
{
|
||||||
return $this->driver->navigate()->back();
|
$this->driver->navigate()->back();
|
||||||
|
|
||||||
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Navigate forward.
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
protected function forward()
|
protected function forward()
|
||||||
{
|
{
|
||||||
return $this->driver->navigate()->forward();
|
$this->driver->navigate()->forward();
|
||||||
|
|
||||||
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Refresh the page.
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
protected function refresh()
|
protected function refresh()
|
||||||
{
|
{
|
||||||
return $this->driver->navigate()->refresh();
|
$this->driver->navigate()->refresh();
|
||||||
|
|
||||||
|
return $this;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,17 +11,17 @@ class ZSettingsScreenTest extends TestCase
|
||||||
{
|
{
|
||||||
public function testSettingsScreen()
|
public function testSettingsScreen()
|
||||||
{
|
{
|
||||||
$this->loginAndGoTo('settings');
|
$this->loginAndGoTo('settings')
|
||||||
$this->typeIn('#inputSettingsPath', dirname(__DIR__.'/../songs'));
|
->typeIn('#inputSettingsPath', dirname(__DIR__.'/../songs'))
|
||||||
$this->enter();
|
->enter()
|
||||||
// Wait for the page to reload
|
// Wait for the page to reload
|
||||||
$this->waitUntil(function () {
|
->waitUntil(function () {
|
||||||
return $this->driver->executeScript('return document.readyState') === 'complete';
|
return $this->driver->executeScript('return document.readyState') === 'complete';
|
||||||
});
|
})
|
||||||
// And for the loading screen to disappear
|
// And for the loading screen to disappear
|
||||||
$this->notSee('#overlay');
|
->notSee('#overlay')
|
||||||
$this->goto('albums');
|
->goto('albums')
|
||||||
// and make sure the scanning is good.
|
// and make sure the scanning is good.
|
||||||
$this->seeText('Koel Testing Vol', '#albumsWrapper');
|
->seeText('Koel Testing Vol', '#albumsWrapper');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue