how to validate multiple selections on a select element in playwright nodejs - automated-tests

I'm having a hard time getting playwright to validate multiple selections in a multiple select element.
For example, say I have the following multiple select:
<select id="colors" name="selected-colors" multiple>
<option value="R">Red</option>
<option value="Y">Yellow</option>
<option value="B">Blue</option>
</select>
In my playwright script, I issue the following command:
await page.selectOption('#colors', ['R', 'B']);
So, at this time, the Red and Blue options are selected. In my app, the requirement is that after the user makes their selection, runs their report and lands on a new page, they should be able to back to this page and those options are still selected. So, I need to test that.
I've tried
await expect(page.locators('#colors')).toHaveValue(['R', 'B']);
But that isn't working for me. When I do that, it tells me the actual value is R. I've tried looking for an answer, but have not had any luck with it.

Even it not highly recommended by playwright team, I am not sure that you have much choice rather then use "$eval".
const allSelectedValues = await page.$eval('yourMultiSelectorLocator', e => Array.from(e.selectedOptions).map(option => option.value));
expect(selectedValues).toEqual(['R', 'B']);

Related

Meteor realtime game - match two players according to their score?

I want to build a realtime quiz game which randomly matches two players (according to their winning rate if they are logged in). I've read through the book Discover Meteor and have a basic understanding of the framework, but I just have no idea of how to implement the matching part. Anyone know how to do that?
if you want to match users who have scores close to each other, you can do something like this : mongodb - Find document with closest integer value
The Meteor code for those Mongo queries is very similar, but there are some subtle differences that are kind of tricky. In Meteor, it would look something like this :
SP // "selected player" = the User you want to match someone up with
var score = SP.score; // selected player's score
var queryLow = {score: {$lte:score},_id:{$ne:SP._id}};
var queryHigh = {score:{$gte:score},_id:{$ne:SP._id}};
// "L" is the player with the closest lower score
var L=Players.findOne(queryLow,{sort:{score:-1},limit:1});
// "H" is the player with the closest higher score
var H=Players.findOne(queryHigh,{sort:{score:1},limit:1});
so, now you have references to the players with scores right above and right below the 'selected player'. In terms of making it random, perhaps start with a simple algorithm like "match me with the next available player who's score is closest" , then if it's too predictable and boring you can throw some randomness into the algorithm.
you can view the above Meteor code working live here http://meteorpad.com/pad/4umMP4iY8AkB9ct2d/ClosestScore
and you can Fork it and mess about with the queries to see how it works.
good luck! Meteor is great, I really like it.
If you add the package peppelg:random-opponent-matcher to your application, you can match together opponents like this:
On the server, you need to have an instance of RandomOpponentMatcher like this:
new RandomOpponentMatcher('my-matcher', {name: 'fifo'}, function(user1, user2){
// Create the match/game they should play.
})
The function you pass to RandomOpponentMatcher will get called when two users been matched to play against each other. In it, you'll probably want to create the match the users should play against each other (this package does only match opponents together, it does not contain any functionality for playing games/matches).
On the client, you need to create an instance of RandomOpponentMatcher as well, but you only pass the name to it (the same name as you used on the server):
myMatcher = new RandomOpponentMatcher('my-matcher')
Then when the users is logged in and which to be matched with a random opponent, all you need to do is to call the add method. For example:
<template name="myTemplate">
<button class="clickMatchesWithOpponent">Match me with someone!</button>
</template>
Template.myTemplate.events({
'click .clickMatchesWithOpponent': function(event, template){
myMatcher.add()
}
})
When two different logged in users has clicked on the button, the function you passed to RandomOpponentMatcher on the server will get called.
One implementation might be as follows:
A user somehow triggers a 'looking for game' event that sets an attribute on user.profile.lookingForGame to true. The event then makes a call to a server side Meteor method which queries for all other online users looking for games.
From there you it really depends on how you want to handle users once they 'match'.
To determine all online users, try using the User Status package:
https://github.com/mizzao/meteor-user-status
Once added, any online user will have an attribute in the profile object of 'online'. You can use this to query for all online users.

angularjs + mongolab $http.put doesn't update model

I'm just getting started with angular and coding in general so bear with me...
I'm currently trying to write a basic phonebook-like CRUD app. So far, I have no trouble adding and viewing contacts, but I'm stuck on how to update my model on MongoLab via $http.put and MongoLab's API
Any help or pointers in the right direction would be greatly appreciated!
Here's my UpdateCtrl function and related form attached (placed a generic URL here for demonstration purpose):
controller.js
function UpdateCtrl($scope, $http, $routeParams, $location){
$scope.contactId = $routeParams.contactId;
var url = 'https://api.mongolab.com/api/databases/<d>/collections/<c>/<id>;
$http.get(url).
success(function(mongoDataById) {
$scope.contact = mongoDataById;
});
$scope.updateContact = function() {
$http.put(url, $scope.contact);
};
}
update.html (partial view)
<form ng-submit="updateContact()">
<label for="fullname">Name</label>
<input type="text" id="fullname" ng-model="contact.fullname" ><br/>
<label for="email">Email</label>
<input type="text" id="email" ng-model="contact.email"><br/>
<label for="phone">Phone</label>
<input type="text" id="phone" ng-model="contact.phone"><br/>
<button type="submit">Update</button>
</form>
edit
#Stewie and #Arun P Johny, there do not seem to be any errors in the console when I execute updateContact(). I suspect it is sending a PUT request with the same data resulting from the initial GET request, even though changes have been made in the form in the current $scope. (And yes, I have a specific contactId in my Url - tested in browser, and it pulls the data for specific contact I've selected)
#pkozlowski.opensource - yeah I actually added that library when I started on this project, but when I was able to get away with fairly simple $http POST and GET functions, I felt like it wasn't necessary. Might give it a try now if I can't figure out using the basic $http.put.
You might need an API key in order to access Mongo Lab's RESTful API such as:
GET /databases/{database}/collections/{collection}
Example listing all documents in a given collection:
https://api.mongolab.com/api/1/databases/my-db/collections/my-coll?apiKey=myAPIKey
Optional parameters
[q=][&c=true][&f=][&fo=true][&s=][&sk=][&l=]
More info at:
http://docs.mongolab.com/restapi/#authentication
It would be nice if you could tell us if Get commant works correctly

What is the most efficient way of filling in details on a web form?

Take a standard web page with lots of text fields, drop downs etc.
What is the most efficient way in webdriver to fill out the values and then verify if the values have been entered correctly.
You only have to test that the values are entered correctly if you have some javascript validation or other magic happening at your input fields. You don't want to test that webdriver/selenium works correctly.
There are various ways, depending if you want to use webdriver or selenium. Here is a potpourri of the stuff I'm using.
Assert.assertEquals("input field must be empty", "", selenium.getValue("name=model.query"));
driver.findElement(By.name("model.query")).sendKeys("Testinput");
//here you have to wait for javascript to finish. E.g wait for a css Class or id to appear
Assert.assertEquals("Testinput", selenium.getValue("name=model.query"));
With webdriver only:
WebElement inputElement = driver.findElement(By.id("input_field_1"));
inputElement.clear();
inputElement.sendKeys("12");
//here you have to wait for javascript to finish. E.g wait for a css Class or id to appear
Assert.assertEquals("12", inputElement.getAttribute("value"));
Hopefully, the results of filling out your form are visible to the user in some manner. So you could think along these BDD-esque lines:
When I create a new movie
Then I should see my movie page
That is, your "new movie" steps would do the field entry & submit. And your "Then" would assert that the movie shows up with your entered data.
element = driver.find_element(:id, "movie_title")
element.send_keys 'The Good, the Bad, the Ugly'
# etc.
driver.find_element(:id, "submit").click
I'm just dabbling in this now, but this is what I came up with so far. It certainly seems more verbose than something like Capybara:
fill_in 'movie_title', :with => 'The Good, the Bad, the Ugly'
Hope this helps.

Time Picker for Qty Hour Segments in Asp.net MVC

I need to create an control in asp.net mvc that allows the user to select a time that is anywhere between 7am and 7pm with quarter hour segments. i.e. The user could select:
7:00am
7:15am
7:30am
7:45am
8:00am
8:15am
....
....
7:00pm
Currently ive got a dropdown that comprises of a select list with entries for every single time slot. Just wondering if anyone knows a cleaner and or better UI experience for the user.
Thanks in advance
I suggest you looking into a JQuery addon: Timepicker.
It is easy to set up, simple in use, and it looks great.
For easy access put this code into your Layout view in the section:
<script type="text/javascript">
$(function() {
$('.timepicker').live('mousedown', function () {
$(this).timepicker({
stepMinute: 15,
hourMin: 7,
hourMax: 19
});
});
});
</script>
In your view have something like this:
#Html.TextBoxFor(m => m.Time, new { #class = #"timepicker" })
Another JQuery option is Timepickr. I don't like it as much as the first one, but it still is a good option.
The Telerik DateTime Picker can handle this. It defaults to an interval every half-hour, but you can configure it to display any interval you want, such as your 15 minutes. It integrates with their date picker, in case you want a combined datetime picker.
It is a drop-down list, like yours, but they tend to have a lot of whiz-bang chrome on their stuff, so you might be able to configure it in other display formats.
I believe the Telerik MVC controls are free to download and use, but you have to pay if you want support.

Read from values from hidden field values in Jquery?

Last two nights I am struggle with below code. The problem is I need to remember expanded (or) collapsed toggles sections and on page reload I have show them as is expanded (or) collapsed.
$(function() {
$('tr.subCategory')
.css("cursor", "pointer")
.attr("title", "Click to expand/collapse")
.click(function() {
$(this).siblings('.RegText').toggle();
});
$('tr[#class^=RegText]').hide().children('td');
})
I found small solution in another forum like this. Storing ".subCategory" id values in hidden field in commas-seperated values.
In Asp.net page:
<input id="myVisibleRows" type="hidden" value="<% response.write(myVisibleRowsSavedValue) %" />
In .js:
var idsStr = $(#myVisibleRows).val();
Now My question is: How to store multiple values (.subCategory id) in hidden field when I click on toggle?. also How to parse them back and iterate them get ids and show toggles?. I am very very new to jQuery. Please some one help me out from this.
Passing this kind of values in a form isn't probably the best thing to do it. I'd suggest using cookies to store expanded sections id's or something similar. It's much easier to implement and you are not passing unimportant form data between requests. If you want to store multple values you can serialize them (easiest thing: use join function in JS) before you store them and deserialize (split) after reading it from a cookie.

Resources