Capybara or Jasmine? - ruby-on-rails

I need to write a test (in Rails) that just shows a function was called. I am not sure to approach this in Jasmine or in Capybara?
My click event is:
<button class="player_vs_cpu_intro" onclick="playerVsCpu()">Player Vs. CPU's Selection</button>
My function is:
function playerVsCpu() {
alert("Hello World");
//other code is in here as well
}
Also, if I had a function within playerVsCpu();, can I test that as well?
Any advice would be appreciated!

You can use jasmine for that. To check if a function has been called you need to use spyOn().
describe("button click", function() {
var btn;
beforeEach(function() {
btn = $('.player_vs_cpu_intro')[0];
});
it("should call playerVsCpu", function() {
spyOn(window, 'playerVsCpu');
$(btn).click();
expect(window.playerVsCpu).toHaveBeenCalled();
});
});
You can also test if a function has been called inside playerVsCpu(). Let's say you call a function anotherFunction() inside playerVsCpu() and you want to assert that.
describe("playerVsCpu", function() {
it("should call anotherFunction", function() {
spyOn(window, 'anotherFunction');
playerVsCpu();
expect(window.anotherFunction).toHaveBeenCalled();
});
});

Related

Youtube API, gapi is not defined?

I'm trying to do a Youtube API and I feel like I got everything working except this gapi and res thing? It says gapi is not defined. How can I make this work?
function tplawesome(e,t){res=e;for(var n=0;n<t.length;n++){res=res.replace(/\{\{(.*?)\}\}/g,function(e,r){return t[n][r]})}return res}
$(function() {
$("form").on("submit", function(e) {
e.preventDefault();
// prepare the request
var request = gapi.client.youtube.search.list({
part: "snippet",
type: "video",
q: encodeURIComponent($("#search").val()).replace(/%20/g, "+"),
maxResults: 3,
order: "viewCount",
publishedAfter: "2015-01-01T00:00:00Z"
});
// execute the request
request.execute(function(response) {
var results = response.result;
$("#results").html("");
$.each(results.items, function(index, item) {
$.get("tpl/item.html", function(data) {
$("#results").append(tplawesome(data, [{"title":item.snippet.title, "videoid":item.id.videoId}]));
});
});
resetVideoHeight();
});
});
$(window).on("resize", resetVideoHeight);
});
function resetVideoHeight() {
$(".video").css("height", $("#results").width() * 9/16);
}
function init() {
gapi.client.setApiKey("AIzaSyD646m4ZfK5yKBZj9p95LohN-PTUnRHBRY");
gapi.client.load("youtube", "v3", function() {
});
}
gapi is an object created by the Google API javascript library that manages all interactions (i.e. does all the heavy lifting of the requests) for you. If the object is not defined, you may not have included the library itself in your page. Somewhere in your HTML, you'll need a script tag that loads the library located at:
https://apis.google.com/js/client.js
Note that, in loading the library with a script tag, you should also pass it a callback ... this is a function that will be automatically called as soon as the library is done loading. So in your case, your init() method is that callback, and so your script tag would look like this:
<script src="https://apis.google.com/js/client.js?onload=init"></script>
The browser will get the library, load it, then run init() when the library is done loading, and all will be ready for your form to execute when triggered.

How do I get yeoman to auto overwrite files?

I have a custom generator and am writing some tests for it. Before the app.run() call I already have a app.options['skip-install'] = true to prevent npm from running. But I need it to auto-overwrite files too.
Part way through the install I get a [?] Overwrite client/file.js? (Ynaxdh) and need it to auto-answer it for me.
I have tried app.options.force = true but that doesn't seem to do anything.
I'm running in app install with this:
function installApp(obj, opts, done) {
helpers.mockPrompt(obj.app, opts);
obj.app.options['skip-install'] = true;
obj.app.run({}, function () {
async.series([
function (cb) {
if (opts._extras.addPage) {
installAppPage(obj, cb);
} else {
cb();
}
}
], done);
});
}
Then I want to run a sub-generator with this:
function installAppPage(obj, done) {
helpers.mockPrompt(obj.page, {
pageName: 'webPage',
pageType: 'web'
});
obj.page.args = ['--force']; // This isn't working
obj.page.options.force; // This isn't working either
obj.page.run([], function () {
helpers.mockPrompt(obj.page, {
pageName: 'mobilePage',
pageType: 'mobile'
});
obj.page.run({}, function () {
done();
});
});
}
The sub-generator for the page modifies a file. I need to to just overwrite it so I can test it. How do I force it? I can't be prompted while running the tests, it needs to be automated.
I think you're looking for conflicter.force
obj.page.conflicter.force = true;

Backbone callback functions, success not triggering code

I'm doing a simple AJAX call to append an album's tracks in an unordered list. It will append the tracks on the second click with this code:
window.app.views.AlbumView = Backbone.View.extend({...
events: {
'click .queue-add' : 'selectAlbum',
'click .show-tracks' : 'showTracks',
'click .hide-tracks' : 'hideTracks',
},
showTracks: function(){
_this = this
this.model.getTracks().forEach(function(track){
_this.$el.find('.tracks').append("<li>"+track.attributes.title+"</li>");
});
},
Clearly the tracks hadn't been fetched in time for the first click so I added a callback function to the showTracks method like so:
showTracks: function(){
_this = this
this.model.getTracks({
success: function(tracks){
console.log(tracks);
tracks.forEach(function(track){
_this.$el.find('.tracks').append("<li>"+track.attributes.title+"</li>");
});
}
});
},
Yet it won't enter the block and the console.log(tracks); puts nothing to the console.
Any tips would be really awesome here, thanks!!
app.models.Album = Backbone.Model.extend({
....
getTracks: function() {
this.tracks.fetch();
return this.tracks
},
....
});
I couldn't find where did you invoke that callback. you may need modify "getTracks" method like this:
getTracks: function(callback) {
this.tracks.fetch();
callback(this.tracks); //you need to invoke the callback before return
return this.tracks;
}
This is called "callback pattern", google it will find more.
and the backbone model's fetch method accept option argument, It is a object with two keys -- success and error -- both are function. If you provide this argument, backbone will call them automatically.
hope this help.

Is there a way to tell if the last ajax call is finished?

I have this site that i am working on that i need to figure out when the last ajax call is finished...I am using this jQuery plugin and all works great but the problem is the client uploads 2 files at a time... and i need to redirect to another page after the last ajax call. If you look the it in firebug while uploading files it run http://dev.posnation.com/test/j/example/upload.php twice and i need to have the page redirect after and only after the second run..is there a way in javascript or jQuery to tell if the ajax calls are complete.
Here is the code that instantiates it
// Initialize the jQuery File Upload widget:
$('#fileupload').fileupload();
and there is a onDone function in the jQuery.fileupload.js
_onDone: function (result, textStatus, jqXHR, options) {
but its running after the first run not after both files are uploaded....any ideas on how i can redirect to another page after both files are uploaded....thanks in advance
the short answer is to decrement a counter in the onDone callback. one possible implementation would be to use a global variable as illustrated below:
var numberFilesToUpload = 2;
// code to upload file
onDone: function() {
// this is the upload plug-ins callback function
numberFilesToUpload--;
if (numberFileToUpload == 0) {
windows.location.href = "/uploading-finished";
}
}
there are more elegant solutions, but they will all involve decrementing a counter.
You could use closure to produce the function which has a local records for files have uploaded.
var fileUploads = function (filesNum, callback) {
var numberFilesToUpload = filesNum;
// code to upload file
return function() {
// this is the upload plug-ins callback function
numberFilesToUpload--;
if (numberFileToUpload == 0) {
callback();
}
};
}(2, function () {
//what you want to do when files are all uploaded.
});
fileUploads will fire the callback function after 2 files are uploaded. The callback and filelimits are specified in this line
var fileUploads = function () {
//...
} (2, function () {});

JQueryUI Tabs Selection and Validation

I am trying to validate tab content(using ajax validation) before switching to the next tab. So when the user clicks on the tab, the current tab content is sent to the server for validation. And when result from the server is received I switch to the next tab. Here is some code:
$('#tabs').tabs({
select: function(event, ui) {
...
validate(currentIndex, nextIndex);
return false;
}
});
function validate(currentIndex, nextIndex){
$.ajax({
...
complete: function(){
$("#tabs").tabs('select', nextIndex);
}
...
}
}
You probably can see the problem already, it's infinite loop, because validation causes tab's select handler that causes validation and so on. How would I solve this without global variables?
Thanks.
Please take a look on this - official Jquery tabs documentation
Your validate function should not do anything except returning true or false.
$('#tabs').tabs(
{
select: function(event, ui)
{
...
return validate(currentIndex, nextIndex);
}
});
function validate(currentIndex, nextIndex)
{
$.ajax(
{
...
success: function(data)
{
// example response: {"error": 0}
if(!data.error) return true;
else return false;
}
...
}
}
When your tabs('select'... function returns false, the tab won't switch, if true the tab will switch - so you don't have to do it in your validate function.
I'm not sure if this would work (haven't tried your code) but couldn't you use the .data(key,value) to add some sort of a "already validated" flag to check for? So you add an if statement which checks for this before entering the validation function again.

Resources