How to get text field history in selenium? - selenium

Is it possible to get a field's history (if it exists) for a field in an array or something of that sort in selenium? For example, user id field, I can see all IDs that have been used so far.
The purpose I'd like to use this is quickly create new IDs that haven't been used before. For example testID45 is already taken, so I'll use testID46 to create a new one. It's a lazy way to fill out a form without keeping track of the taken IDs.

I don't fully understand why you want to create IDs using Selenium. If you would post more info on what problem you are trying to solve, I could try to provide a better answer.
If you want to pull the IDs from existing elements you could do something like this. This finds all INPUT elements that have an ID specified and writes out the IDs. You could parse the IDs and then determine which ID to use next. I wouldn't recommend this because it would be faster to just generate a new ID that will be unique but maybe you need this for some reason.
List<WebElement> ids = driver.findElements(By.cssSelector("input[id]"));
for (WebElement id : ids)
{
System.out.println(id.getAttribute("id"));
}
I would recommend generating a new ID of your own format that would be unique on the page. This should be good enough for your purposes.
Random rnd = new Random();
String id = Long.toHexString(rnd.nextLong());
System.out.println("testID-" + id); // e.g. testID-cb8e7bac29ec7c7a
There are many other methods of generating strings in this post that you can reference also.

Related

Few questions about Grails' createCriteria

I read about createCriteria, and kind of interested on how these works, and its usability in providing values for dropdown box.
So say, i have a table in the database, Resource table, where i have defined the table in the domain class called Resource.groovy. Resource table has a total of 10 columns, where 5 of it are
Material Id
Material description
Resource
Resource Id
Product Code
So using the createCriteria, and i can use just like a query to return the items that i want to
def resList = Resource.createCriteria().list {
and {
eq('resource', resourceInstance)
ne('materialId', '-')
}
}
Where in the above, i want to get the data that matches the resource = resourceInstance, and none of the materialId is equal to '-'.
I want to use the returned data from createCriteria above on my form, where i want to use some of the column on my select dropdown. Below is the code i used for my select dropdown.
<g:select id="resourceId" name="resourceId"
from="${resList}"
disabled="${actionName != 'show' ? false : true}" />
How do i make it so that in a dropdown, it only shows the values taken from column Product Code? I believe the list created using createCriteria returns all 10 columns based on the createCriteria's specification. But i only want to use the Product Column values on my dropdown.
How do i customize the data if in one of the select dropdown in my form, i wanted to show the values as "Resource Id - Resource Description"? The values are combination of more than 1 columns for one select dropdown but i don't know how to combine both in a single select dropdown.
I read that hql and GORM query are better ways of fetching data from table than using createCriteria. Is this true?
Thanks
First of all refer to the document for using select in Grails. To answer all questions:
Yes, the list to select from in the dropdown can be customized. In this case it should be something like from="${resList*.productCode}"
Yes, this can be customized as well with something like
from="${resList.collect { \"${it.resourceId} - ${it.resourceDesc}\" } }"
It depends. If there are associations involved in a domain then using Criteria will lead to eager fetches which might not be required. But with HQL one gets the flexibility of tailoring the query as needed. With latest version of Grails those boundries are minimized a lot. Usage of DetachedCriteria, where queries etc are recommended whereever possible. So it is kind of mixing and matching to the scenario under consideration.

randomly generating unique number between 1-999 for primary key in table

I have a problem I'm not sure how to solve elegantly.
Background Information
I have a table of widgets. Each widget is assigned an ID from a range of numbers, let's say between 1-999. The values of 1-999 is saved in my database as "lower_range" and "upper_range" in a table called "config".
When a user requests to create a new widget using my web app, I need to be able to do the following:
generate a random number between 1 and 999 using lua's math.random function or maybe a random number generator in sqlite (So far, in my tests, lua's math.random always returns the same value...but that's a different issue)
do a select statement to see if there already is a widget with this number assigned...
if not, create the new widget.
otherwise repeat process until you get a number that is not currently in use.
Problem
The problem I see with the above logic is two-fold:
the algorithm can potentially take a long time because I have to keep searching until I find a unique value.
How do I prevent simultaneous requests for new widget numbers generating the same value?
Any suggestions would be appreciated.
Thanks
Generate your random numbers ahead of time and store them in a table; make sure the numbers are unique. Then when you need to get the next number, just check how many have already been assigned and get the next number from your table. So, instead of
Generate a number between 1-999
Check if it's already assigned
Generate a new number, and so on.
do this:
Generate array of 999 elements that have values 1-999 in some random order
Your GetNextId function becomes return ids[currentMaxId+1]
To manage simultaneous requests, you need to have some resource that generates a proper sequence. The easiest is probably to use a key in your widget table as the index in the ids array. So, add a record to the widgets table first, get its key and then generate widget ID using ids[key].
Create a table to store the keys and the 'used' property.
CREATE TABLE KEYS
("id" INTEGER, "used" INTEGER)
;
Then use the following to find a new key
select id
from KEYS
where used = 0
order by RANDOM()
limit 1
Don't generate a random number, just pick the number off a list that's in random order.
For example, make a list of numbers 1 - 999. Shuffle that list using Fisher-Yates or equivalent (see also Randomize a List in C# even if you're not using C#).
Now you can just keep track of the most recently used index into your list. (Shuffling the list should occur exactly once, then you store and reuse the result).
Rough pseudo-code:
If config-file does not contain list of indices
create a list with numbers 1 - 999
Use Fisher-Yates to shuffle that list
// list now looks like 0, 97, 251, 3, ...
Write the list to the config file
Set 'last index used' to 0 and write to config file
end if
To use this,
NextPK = myList[last-index-used]
last-index-used = last-index-used + 1
write last-index-used to config file
To get and flag an ID as used at same time (expanding on Declan_K's answer):
replace into random_sequence values ((select id from random_sequence where used=0 order by random()), 1);
select id from random_sequence where rowid = last_insert_rowid();
6
When you run out of "unused" sequence table entries the select will return "blank"
I use replace into as update doesn't have an last_insert_rowid() equiv that I can see.
You Can get sql to create a primary key, that will increase by one evert time you add a ros to the database.

Get a hash of old attribute values from rails active record

I want to generically access the old attributes that have changed in a model - that is, I want to get a hash of the old attributes values. My code is interested in all attributes that have changed, which may be a different set each time it's run.
I know you can get an array of changed attribute names with
model.changed
and I know you can do
model.attribute_was
to get the old value of an attribute if you know the name, but I can't find a way to programatically combine the two or to otherwise get the set of old values
I'm using it to create news stories about objects, eg
User 'Bob' changed x from a to b
You can use the attributes hash to generate this array:
old = model.changed.map{|attr| model.send("#{attr}_was".to_sym) }

Redis - handling changes to data structures

I have been experimenting with Redis, and I really like the scalability that it brings to the table. However, I'm wondering how to handle changes to data structures for a system that's already in production.
For example, let me say that I am collecting information about a user, and I use the user_id as a key, and dumping the other data about the user as comma separated values.
user_id: name, email, etc.
Now, say after about 100,000 records, I realise that I needed to query by email - how would I now take a snapshot of the existing data and create a new index for it?
Using csv is not a great idea if you want to support changes. You need to use a serializer that handles missing/new values if everything is in one key, or you can use a redis hash, which gives you named subkeys. Either way you can add/remove fields with the only requirement being that your code knows what to do if it reads a record without the new value.
To allow lookup by email you need to add an index - basically a key (or list) for each email with the user id as the value. You will need to populate this index by getting all keys once, then making sure you update it when emails change.
You could iterate over all keys and store them with a different id, but that is probably more trouble than it is worth.
From my understanding of Redis, this would require something which Redis is not designed to do. You would have to loop though all your records (using keys *) and then change the order of the data and make a new key. I, personally, would recommend using a list instead of a comma separated string. In a list, you can reorder it from inside redis. A Redis List looks like the following:
"Colum" => [0] c.mcgaley#gmail.com
[1] password
[2] Something
I am building an app in which I encountered the same problem. I solved it by having a list for all the user's info, and then have a key with the user's email with a value of the user's id. So my database would something like this:
"Colum" => [0] c.mcgaley#gmail.com
[1] password
[2] Something
"c.mcgaley#gmail.com" => "Colum"
So I could query the ID or the Email and still get the information I needed.
Sorry that I was not able to directly answer your question. Just hope this helped.

Boosting Multi-Value Fields

I have a set of documents containing scored items that I'd like to index. Our data structure looks like:
Document
ID
Text
List<RelatedScore>
RelatedScore
ID
Score
My first thought was to add each RelatedScore as a multi-value field using the Boost property of the Field to modify the value of the particular score when searching.
foreach (var relatedScore in document.RelatedScores) {
var field = new Field("RelatedScore", relatedScore.ID,
Field.Store.YES, Field.Index.UN_TOKENIZED);
field.SetBoost(relatedScore.Score);
luceneDoc.Add(field);
}
However, it appears that the "Norm" that is calculated applies to the entire multi-field - all the RelatedScore" values for a document will end up having the same score.
Is there a mechanism in Lucene to allow for this functionality? I would rather not create another index just to account for this - it feels like there should be a way using a single index. If there isn't a means to accomplish this, a few ideas that we have to compensate are :
Insert the multi-value field items in order of descending value. Then somehow add a positional-aware analysis to assign higher boost/score to the first items in the field.
Add a high value score multiple times to the field. So, a RelatedScore with Score==1 might be added three times, while a RelatedScore with Score==.3 would only be added once.
Both of these will result in a loss of search fidelity on these fields, yes, but they may be good enough. Any thoughts on this?
This appears to be a use case for Payloads. I'm not sure if this is available in Lucene.NET, as I've only used the Java version.
Another hacky way to do this, if the absolute values of the scores aren't that important, is to discretize them (place them in buckets based on value) and create a field for each bucket. So if you have scores that range from 1 to 100, create say, 10 buckets called RelatedScore0_10, RelatedScore10_20, etc, and for any document that has a RelatedScore in that bucket, add a "true" value in that field. Then for every search that gets executed tack on an OR query like:
(RelatedScore0_10:true^1 RelatedScore10_20:true^2 ...)
The nice thing about this is that you can tweak the boost values for each one of your buckets on the fly. Otherwise you'd need to reindex to change the field norm (boost) values for each field.
If you use Lucene.Net you might not have payloads functionality yet. What you can do is convert 0-100 relevancy score to a bucket from 1-10 (integer division by 10), then add each indexed value that many times (but only store value once). Then if you search for that field, lucene built-in scoring will take into account frequency of indexed field (it will be indexed 1-10 times based on relevance). Therefore results can be sorted by variable relevance.
foreach (var relatedScore in document.RelatedScores) {
// get bucket for relevance...
int bucket=relatedScore.Score / 10;
var field = new Field("RelatedScore", relatedScore.ID,
Field.Store.YES, Field.Index.UN_TOKENIZED);
luceneDoc.Add(field);
// add more instances of field but only store the first one above...
for(int i=0;i<bucket;i++)
{
luceneDoc.Add(new Field("RelatedScore", relatedScore.ID,
Field.Store.NO, Field.Index.UN_TOKENIZED));
}
}