Im currently testing using PHPUnit and i need to create and delete the same things. So i create something called test, i want to be able to find it and delete it. I have multiple Delete buttons on the page, and it works by doing something like this -
$this->click("xpath=(//img[#title='Delete'])[11]");
but by choosing [11] for example, it is only using the delete button from row 11. And if Test isnt Row 11 for example, i will delete something i do not wish to delete.
I wish to try and delete a specific row by finding a row with a certain id attached to it.
The row may have the words "Test" followed by more information within columns. Then a delete button at the end titled 'Delete'. I wish to find the row with the id or words 'Test' and then find and use the 'Delete' title on that row.
Any help?
EDIT -Example image of a row. I would like to grab the first text, and then use the very last button on the right titled 'Delete'
http://i.stack.imgur.com/S4BNE.png
SECOND EDIT - This is the whole table, it contains all of the rows and within the rows it contains the td's (Obviously, as you'd know).
This is where ill find the text im trying to find. This tr would count as the 4th of 6.
This shows the td containing delete, a td containing 'Test Profile' and the whole table itself.
http://i.imgur.com/4r1tsJe.png
TL;DR Essentially, im trying to do, Where td contains 'Test', use 'Delete' from the same row.
Not very clear but I'll try to guess from your comments.
Forget about rows, but let's find all the td with "Test" (or some text you want in it)
descendant::td[contains(.,'Test')]/
and from here select the following-sibling td that contains a delete image
following-sibling::td//img[#title='Delete']
now you have the set of images nodes to click on, for each row.
Of course, if your function
$this->click("xpath=.....");
accepts only one node at the time, one possibility is to put the parenthesis and select always the first node (assuming that your test will delete it)
(descendant::td[contains(.,'Test')]/following-sibling::td//img[#title='Delete'])[1]
Even if the node is deleted when you click on it, in the next test this expression will always match, until there is any node left on the page
This is similar (not perfectly the same) to having a for loop ?
buttons = "xpath=....."
for each b in buttons do {
$this->click(b);
}
hope it helps
If you want to find the first row that contains Test in the first <td> element, or that has an id attribute of "Test" on the <tr> element; and you want to click the Delete img element from that row, you could try
$this->click("xpath=(//tr[#id='Test' or contains(td[1], 'Test')]//img[#title='Delete'])[1]");
But this is somewhat guesswork, since I can't see the HTML you're working with.
Since it looks like 'Test' could be in all-caps or in mixed-case, you may have to build in some case-insensitivity:
$this->click("xpath=(//tr[#id='Test' or
contains(translate(td[1], 'abcdefghijklmnopqrstuvwxyz', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'),
'TEST')]//img[#title='Delete'])[1]");
Yes it's kludgy, but AFAIK PHP only supports XPath 1.0.
Related
I have a table with checkboxes in each row. The user can select some rows and delete them, also I have this "select all" checkbox.
I want to test selecting and deleting two rows for example, also click select all and delete them.
So I need to check the second and third checkboxes for the first test and first one for the second test...
I couldn't find a way to select the nth element, the only way I could find is selecting by xpath, so I tried this without luck:
$I->checkOption("(//input[#type='checkbox'])[2]");
The error is smt. like //html(//input[#type='checkbox'])[2] is invalid.
Apparently codeception is modifying the selector, so I tried to use WebDriverBy class but I couldn't find a way to pass it as a parameter...
Any ideas?
PS: This is not the actual case but a simple example to describe the problem...
I found a way to do it from this answer.
This is it:
$I->checkOption("/descendant::input[#type='checkbox'][2]");
This works at my end , you can use this one also
$I->checkOption('[name="published"]');
And for the Question:
we can find nth element in following ways:
$I->click("table#races-table tbody tr:first-child td:last-child button")- Table(if you know first child and last child)
$I->click('#side-menu li:nth-child(2)');- (Side menu you have and need to select item from the sub menu)
$I->selectOption('.radio-tab:nth-child(1)', '1'); -- (Selecting radio button if you have multiple in a form)
In MySQL I have a table with a name, id, position, and content values.
The content is loaded onto a page in php by querying by id. The position is used in php to create a dynamic menu with the menu items ascending by position value.
So for example, say There were 3 rows with each row having a position value of 1, 2, or 3.
I am trying to build a form to allow the user to change the position of the menu, items, or add a new one. So if the row in position 3 wants to be changed to position value 1, then 2 needs to become 3 and 1 needs to become 2. Or if a new item is added, the position its taking and all below it need to be shifted up a value.
What would be the best way of approaching this?
Any suggestions would be appreciated.
If you add new item- frst update all items with position value equal or more:
UPDATE MenuItems SET position = position + 1 WHERE position >= newItemPosition;
If you are updating - update only item with position higher than higherItemPosition (they will only switch places).
UPDATE MenuItems SET position = position - 1 WHERE position = higherItemPosition;
If newItemPosition is updated to lower value I would do sth like that:
UPDATE MenuItems SET position = position + 1 WHERE position = lowerItemPosition;
Two ideas come to mind:
have the menu as an AJAX loaded div and then react to the change and reload the div, which means you could rerun the SQL
load the answers into a javascript array and present them that way as you then have drag change abilities.
Before we swarm the database with queries, create indexes (e.g. primary key) that covers the position field, update several rows with their index entries per change, and so on, let's consider the following:
How long would a menu get, in the worst case?
Do you really need to obtain individual rows from the menu, or whenever you need to display a menu you need to SELECT all of its rows?
Most often, these cases can be solved with a much simpler, pragmatic approach that will also be far easier for you as a programmer. If the menu isn't going to be too long and you probably need all of it every time you need to read it, why not keep it as a list (of items of whatever type) in your program, and serialize it with whatever method (e.g. JSON or Python Pickle) before storing it in the database as a single row with a text field? If the menu is in a list, reordering its elements will be pretty simple, a read operation for the menu would demand a single row SELECT for the database, and a write operation would require a single UPDATE, without caring for keeping a Position field updated.
I am stuck with finding a means of being able to edit a specific row in my table. I have so far managed to come up with add,delete and search for a specific item that is stored in my database, i base the delete on a id field. Currently i am using PHP and HTML, could someone please show me a simple example that retrieves data from a database which stores in a table and when a user selects edit. The row that has been selected for edit becomes editable and thereafter updated without duplicating the data.
CLARIFICATION OF My QUESTION
For Editing to work the UI must look like, when the edit button corresponding to particular row is clicked then all the columns with the data should get replaced with text boxes, i.e. row-wise edit form...
Thanks
This is a very vague question, involves a lot of things. Not, just php, mysql or html but mainly javascript. However I will give a simple example, since you must already be able to bring the data onto a table.
Suppose your <tr> structure is similar to this
<tr>
<td class="nameField"><span class="text">My name</span></td>
<td class="controls"><a class="edit">Edit</a></td>
</tr>
Now using jQuery for this
$('a.edit').click(function() {
$(this).closest("tr").find("td").not(".controls").each(function(k,v) {
// ^ find all td but not the one with the controls
var span = $(this).children('span');
//get the elem holding the value
$(this).append('<input type="text" value="'+span.text()+'" />');
// Add a text box with the input inside the td
span.hide();
});
});
Demo
SQL Syntax you are looking for is UPDATE
For example you have an articles table tied to a user with user_id, then you have a list of articles whereby users can select to edit (with edit link or something similar)
Then you'd do something like
mysql_query('UPDATE articles set content = $new_content where id = $article_id');
Don't forget to sanitize $new_content and $article_id, or better yet, use mysqli altogether.
I have a table on my page which is supposed to contain a certain element. I can identify the table by its name (it has a unique name), and I can also identify the element easily. I would like to assert that the element is present on row r, column c of the table. What is the cleanest way of doing it using Selenium commands?
Remarks:
I don't want to use more than the table name in order to locate it (I don't want all the div\div\table\div\tbody\td\tr[r]\td[c] in the code).
I'm using Selenium within PHPUnit. Hence, I can use PHP logic for the task, though I don't want any complex logic for such a simple task.
Clarification:
If the element in the cell is just plain text, then I can retrieve that text like this:
$this->getText("xpath=//table[#name='tableName']//tr[".$r."]//td[".$c."]"); (PHP)
But what if the cell has an element which is not just plain text? What if the element is a link (link=anchor) or a button (//button[#type='button']) or an image or something more complex?
I need to assert that an element specified by a locator of that element resides in a given cell.
Sounds like you want isElementPresent(...locator of element...). For example:
$cell = "//table[#name='tableName']//tr[".$r."]/td[".$c."]";
$foundLink = $this->isElementPresent("xpath=".$cell."/a[.='".linktext."']");
$foundButton = $this->isElementPresent("xpath=".$cell."/button[#type='button']");
$foundImage = $this->isElementPresent("xpath=".$cell."/img[ends-with(#src='pretty-pony.gif')]");
isElementPresent() returns true if so, false if not.
You could try Selenium's getXpathCount
$this->("xpath=//table[#name='tableName']//tr[".$r."]//td[".$c."]//TAG");
This will return the number of matches the xpath gets. in your case, zero would mean a fail.
I am trying to build a simple forum where the questions wil be refreshed automatically . Although it is done ,I have two problems.
1 . Since I retrieve the last update from database,last entry is dulicated.
2 . The div where I put the AJAX response always refrshes .
How can I remove the duplicate entries and make it smooth forum ,just like in facebook comment page ?
If I understand your first problem, you're saying you are doing something like:
Take the user's input (i.e. the new entry)
Write this input to your database
Select all entries, including the one you just added
Because you are also separately adding the new reply to the div client-side or something the last entry always shows up twice (but doesn't get written to the database twice).
If this is the case you could solve the problem by either omitting the last entry from your MySQL query (e.g. SELECT * FROM entries WHERE id != (SELECT MAX(id) FROM entries)) or by simply refraining from processing the entry on the client's side.
Concerning your second problem:
Instead of fetching all entries and replacing all content inside the div with the new list of entries, try only appending the new entry with .innerHTML += ... or jQuery's .append() for example. This way you won't experience any 'flickering' or jumping content with the rest of the replies.