validating if sort options work on protractor - protractor

I am new to protractor and I have clicked on my webpage to sort items by prices low to high. How do I check that the first item has price less than the second and so forth?
Any kind of guidance will be appreciated.
Thanks,
Shark

You could try something like this:
$$('cellTargetSelector').getText().then(valueArray => {
valueArray = sort(valueArray);
sortBtn.click();
$$('cellTargetSelector').getText().then(valueArrayAfterSort => {
for(let i=0; i < valueArrayAfterSort.length; i++) {
expect(valueArrayAfterSort[i]).toEqual(valueArray[i]);
}
});
});
Where sort(arr) func returns sorted arr

Related

Unity: How to get the metadata tag of a leaderboard score in Unity?

I've been looking everywhere for this, apparently Google forgot about getting the metadata tags associated with a leaderboard score.
In their Official Github unity plugin Documentation, they clearly stated:
To post a score and include a metadata tag use the Play Game Services instance directly:
And this worked just great, but now after a lot of searching i think that there is no way that you can get this Metadata Tag back from the leaderboard!.
Also from the official documentation:
You can load scores from a leaderboard using this function:
PlayGamesPlatform.Instance.LoadScores(lId,
leaderboardStart,
scoresToDisplay,
leaderboardType,
leaderboardTimeSpan,
(LeaderboardScoreData data) => {
for (int i = 0; i < data.Scores.Length; i++)
{
IScore score = data.Scores[i];
//handle where you want to save the scores
}
});
Can anyone help about how to get the score metadata tag?
I finally figured this out, for anyone who's trying to do what i wanted, here's the solution:
First you have to assign a metadata tag to the score that you want to report like this:
public void ReportScoreToLeaderboard(string leaderboardId, int score)
{
PlayGamesPlatform.Instance.ReportScore(score, leaderboardId, "SantaCharacter", (bool success) => {
// handle success or failure
});
}
Then when you want to get the score with the tag just cast the IScore to PlayGamesScore like so:
PlayGamesPlatform.Instance.LoadScores(lId,
leaderboardStart,
scoresToDisplay,
leaderboardType,
leaderboardTimeSpan,
(LeaderboardScoreData data) => {
for (int i = 0; i < data.Scores.Length; i++)
{
//Just cast the IScore to PlayGamesScore :)
PlayGamesScore score = (PlayGamesScore) data.Scores[i];
float scoreValue = score.value;
string tag = score.metaData;
//store them and do what you want with them
}
}
);
I Hope this will help someone.

Reformatting spreadsheet responses into a new tab on form submit

Here are my spreadsheet responses from a form: https://docs.google.com/spreadsheets/d/1a9H2HqAwl29IY6-aCvCKs12Xb3vDcZHCOoNugx81PTA/edit#gid=1939572907
The form data generates in the "raw data" tab of the above spreadsheet. However, I'd like to automatically rearrange the form responses in a different format on the "teacher list" tab of the spreadsheet on form submissions. We are trying to keep track of how often we visit a teacher's room and so want all of the timestamps to appear next to the teacher's name.
I do not know if I should be using formulas or a script to get the job done.
To show you our end goal, I have two form submissions that I have typed into the cells where'd we like them to appear on the "teacher list" tab.
Any suggestions or resources to help me accomplish this would be very much appreciated!
This should give you a good start. And, I have removed the merging of the cells in G column in teacher list tab.
function myFunction() {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Raw Data');
var data = sheet.getDataRange().getValues();
var formatSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Teacher List');
var formatData = formatSheet.getDataRange().getValues();
var name = data[sheet.getLastRow()-1][2];
var flag = 0, index;
for(var i=1; i<formatData.length; i++)
{
if(name == formatData[i][0])
{
flag = 1;
index = i;
break;
}
}
if(flag == 1)
{
for(var i=1; i<=5; i++)
{
if(formatData[index][i] == "")
{
formatSheet.getRange(index+1, i+1).setValue(data[sheet.getLastRow()-1][0]);
formatSheet.getRange(index+1, 7).setValue(formatData[index][6].concat('; '+data[sheet.getLastRow()-1][3]));
break;
}
}
}
}
But is there more than 5 visits possible? Is first column of teacher list tab is going to remian same throughout? Do you want to add new row if no match is found for 'Teacher or PLC Observed' from Raw Data with first column of Teacher List tab?
If answer to these questions is positive, you need to tweak a code little bit, try it. I'll help if you're stuck.
Edit: Please set the appscript trigger as: From form -> onSubmit.

Protractor: how to click all delete buttons in a page object

I have a table with 3 rows of data and 3 delete buttons. I want to delete all rows of data and so am trying to write a method in my page object to do so... this should be a snap but I can't get it to work. I'm trying it like this:
this.rows = element.all(by.repeater('row in rows'));
this.deleteAllFriends = function() {
this.rows.each(function(row) {
row.$('i.icon-trash').click();
})
};
But this throws an error:
Error: Index out of bound. Trying to access index:2, but locator: by.repeater("row in rows") only has 1 elements
So obviously, the index protractor expects next is no longer there, because it's been deleted. How can I work around this?
This also does not work and throws the same error:
this.deleteButtons = $$('i.icon-trash');
this.deleteAllFriends = function() {
this.deleteButtons.each(function(button) {
button.click();
});
};
This also doesn't work...
this.deleteAllFriends = function() {
while(this.deleteButton.isDisplayed()) {
this.deleteButton.click();
}
};
With today's version >= 1.3.0 of Protractor you are now be able to do this at once
$$('i.icon-trash').click();
feat(protractor): allow advanced features for ElementArrayFinder
I finally figured it out...
this.deleteButtons = $$('i.icon-trash'); // locator
this.deleteAllFriends = function() {
var buttons = this.deleteButtons;
buttons.count().then(function(count) {
while(count > 0) {
buttons.first().click();
count--;
}
})
};

Filter getElementsByTagName list by option values

I'm using getElementsByTagName to return all the select lists on a page - is it possible to then filter these based upon an option value, ie of the first or second item in the list?
The reason is that for reasons I won't go into here there are a block of select lists with number values (1,2,3,4,5 etc) and others which have text values (Blue and Black, Red and Black etc) and I only want the scripting I have to run on the ones with numerical values. I can't add a class to them which would more easily let me do this however I can be certain that the first option value in the list will be "1".
Therefore is there a way to filter the returned list of selects on the page by only those whose first option value is "1"?
I am pretty sure that there is a better solution, but for the moment you can try something like:
var allSelect = document.getElementsByTagName("select");
var result = filterBy(allSelect, 0/*0 == The first option*/, "1"/* 1 == the value of the first option*/);
function filterBy(allSelect, index, theValue) {
var result = [];
for (var i = 0; i < allSelect.length; i++) {
if(allSelect[i].options[index].value == theValue ) {
result.push(allSelect[i]);
}
}
return result;
}
I managed to get this working by wrapping a simple IF statement around the action to be performed (in this case, disabling options) as follows:
inputs = document.getElementsByTagName('select');
for (i = 0; i < inputs.length; i++) {
if (inputs[i].options[1].text == 1) {
// perform action required
}
}
No doubt there is a slicker or more economic way to do this but the main thing is it works for me.

Peculiar Map/Reduce result from CouchDB

I have been using CouchDB for quite sometime without any issues. That is up until now. I recently saw something in my map/reduce results which I had overlooked!
This is before performing a sum on the "avgs" variable. I'm basically trying to find the average of all values pertaining to a particular key. Nothing fancy. The result is as expected.
Note the result for timestamp 1308474660000 (4th row in the table):
Now I sum the "avgs" array. Now here is something that is peculiar about the result. The sum for the key with timestamp 1308474660000 is a null!! Why is CouchDB spitting out nulls for a simple sum? I tried with a custom addition function and its the same problem.
Can someone explain to me why is there this issue with my map/reduce result?
CouchDB version: 1.0.1
UPDATE:
After doing a rereduce I get a reduce overflow error!
Error: reduce_overflow_error
Reduce output must shrink more rapidly: Current output: '["001,1,1,1,1,1,11,1,1,1,1,1,1,11,1,1,1,1,1,1,11,1,1,1,1,1,1,11,1,1,1,1,1,101,1,1,1,1,1,1,11,1,1,1,1'... (first 100 of 396 bytes)
This is my modified reduce function:
function (key, values, rereduce) {
if(!rereduce) {
var avgs = [];
for(var i=values.length-1; i>=0 ; i--) {
avgs.push(Number(values[i][0])/Number(values[i][1]));
}
return avgs;
} else {
return sum(values);
};
}
UPDATE 2:
Well now it has gotten worse. Its selectively rereducing. Also, the ones it has rereduced show wrong results. The length of the value in 4th row for timestamp (1308474660000) should be 2 and not 3.
UPDATE 3:
I finally got it to work. I hadn't understood the specifics of rereduce properly. AFAIK, Couchdb itself decides how to/when to rereduce. In this example, whenever the array was long enough to process, Couchdb would send it to rereduce. So I basically had to sum twice. Once in reduce, and again in rereduce.
function (key, values, rereduce) {
if(!rereduce) {
var avgs = [];
for(var i=values.length-1; i>=0 ; i--) {
avgs.push(Number(values[i][0])/Number(values[i][1]));
}
return sum(avgs);
} else {
return sum(values); //If my understanding of rereduce is correct, it only receives only the avgs that are large enough to not be processed by reduce.
}
}
Your for loop in the reduce function is probably not doing what you think it is. For example, it might be throwing an exception that you did not expect.
You are expecting an array of 2-tuples:
// Expectation
values = [ [value1, total1]
, [value2, total2]
, [value3, total3]
];
During a re-reduce, the function will get old results from itself before.
// Re-reduce values
values = [ avg1
, avg2
, avg3
]
Therefore I would begin by examining how your code works if and when rereduce is true. Perhaps something simple will fix it (although often I have to log() things until I find the problem.)
function(keys, values, rereduce) {
if(rereduce)
return sum(values);
// ... then the same code as before.
}
I will elaborate on my count/sum comment, just in case you are curious.
This code is not tested, but hopefully you will get the idea. The end result is always a simple object {"count":C, "sum":S} and you know the average by computing S / C.
function (key, values, rereduce) {
// Reduce function
var count = 0;
var sum = 0;
var i;
if(!rereduce) {
// `values` stores actual map output
for(i = 0; i < values.length; i++) {
count += Number(values[i][1]);
sum += Number(values[i][0]);
}
return {"count":count, "sum":sum};
}
else {
// `values` stores count/sum objects returned previously.
for(i = 0; i < values.length; i++) {
count += values[i].count;
sum += values[i].sum;
}
return {"count":count, "sum":sum};
}
}
I use the following code to do average. Hope it helps.
function (key, values) {
return sum(values)/values.length;
}