Teaspoon: "Can't find variable <function>" (Rails) - ruby-on-rails

So this seems like a weird error, i've just started using teaspoon and im trying to get it set up on a rails project.
I have a very simple function im trying it out on:
export function add(value,value2) {
return value+value2;
}
Simple right?
and im including it in my spec file as such:
//= require config/add
describe("add", function() {
var num;
it("add", function() {
num = add(2,3);
expect(num).toEqual(5);
});
});
Why do I get a "Can't find variable "Add" in http://127.0.0.1:8000/assets/test_spec.self.js?body=1 (line 5)"
Am I missing something? I know this project does have ES6 modules which I know need to be compiled and such, but....this doesn't use any ES6 syntax I believe.

This ended up being a problem with the function export. Which was resolved by using:
import {add} from 'subfolder/add';
Im guessing since it was using ES6 standards...

Related

RAILS 6 - how to use EasyAutocomplete

I try the last hours to integrate EasyAutocomplete into RAILS 6. But not so easy.
What I did :
Install Javascript Package with yarn:
# yarn add easy-autocomplete
Add this in the file app/javascript/packs/application.js
import “easy-autocomplete”
Add this in the file app/assets/stylesheets/application.css
*= require easy-autocomplete
*= require easy-autocomplete.themes
Then start the Rails Server and refresh the Web Page.
Then try to use it. Go into the developer console and type :
var options = {
data: ["otto", "hans", "paula"]
};
$("#task_name_search_field").easyAutocomplete(options);
task_name_search_field was previously defined as id :
<input type="search" class="form-control" id="task_name_search_field">
I got this message:
TypeError: $(...).EasyAutocomplete is not a function
Any idea ?
I had the same problem. Turbolinks does not give access to the script, the code needs to be run after it is loaded, something like this:
document.addEventListener("turbolinks:load", function() {
var options = {
data: ["otto", "hans", "paula"]
};
$("#task_name_search_field").easyAutocomplete(options);
});
In order for the autocomplete to work, you need to add a script file to the application.js like this:
require("packs/youfile")
If it helps you, here is an example of my code:
document.addEventListener("turbolinks:load", function() {
$input = $("[data-behavior='autocomplete']")
var options = {
getValue: "full_name",
url: function(phrase) {
return "/search.json?q=" + phrase;
},
categories: [
{
listLocation: "cameras",
header: "<strong>Cameras</strong>",
}
],
list: {
onChooseEvent: function() {
var url = $input.getSelectedItemData().url
$input.val("")
Turbolinks.visit(url)
}
}
}
$input.easyAutocomplete(options)});
I suppose you wouldn't have included jquery in your application.js. You need to do explicitly as it doesn't get included automatically with rails 6 app.
I ran into a similar issue. I'm a n00b at Webpacker, but by default it doesn't seem to compile in the same order in which plugins are included.
To get around the issue I did this workaround which just wraps the plugin code in an anonymous jQuery function, like so:
(function($) {
//Eac plugin code
})(jQuery);
https://github.com/pawelczak/EasyAutocomplete/issues/200#issuecomment-212277620
Maybe there is a way in the configs to force compilation in the correct order. This looks promising https://stackoverflow.com/a/43005332/148390
Add script-loader to package.json then add
import 'script-loader!jquery/dist/jquery.min'
in app/javascripts/application.js
Check in your browser that $().jquery yields a proper result.

Trying to get angular mock to work with teaspoon-jasmine

So i'm working in ruby on rails, and I've using it with AngularJS 1 for the first time, and therefore am setting up the unit testing for angularjs inside rails for the first time. I can test rails with rspec no problem, but i've been struggling to test angularjs, currently I'm working with teaspoon-jasmine and angular-mocks to test a simple angular controller, but I run into several problems. The first file below is my test file, I currently have it using angular.mock.module/inject and the error i'm getting is "Failed to instantiate module angularrApp due to..." it's basically saying I haven't created or loaded angularApp anywhere, I though mock was supposed to create a test module? If I the module to "angular.module("name", [])" like I would normally create an angular app, I run into more problems such as the mainController hasn't been created. I'm just overall having issues getting this to work properly, any suggestions? I'm trying to get just the simple first expect to work before I move on to the actual tests. And I am requiring angular and angular-mocks in the spec_helper.js file, all the files below. Would it help to require the file that creates the angular app in my spec_helper.js? I've tried but can't get it to work since one is in the spec directory, while my angular app is in app/assets. Also if it helps, here is the link to the tutorial I based this code off of http://angular-rails.com/find_and_browse.html
mainController_spec.js (test file)
'use strict';
describe("mainController", function() {
var scope,
ctrl,
location,
resource;
var setupController = function() {
angular.mock.inject( function($rootScope, $resource, $controller) {
scope = $rootScope.$new();
resource = $resource;
ctrl = $controller('mainController', {$scope: scope, $resource: resource });
})
}
beforeEach(function(){
angular.mock.module("angularApp");
setupController();
})
it('should work', function(){
expect(true).toBe(true);
// expect(scope.games).toBe([])
})
});
mainController.js
'use strict';
myApp.controller('mainController', [ 'mainFactory', '$scope', '$resource', (factory, scope, resource) => {
scope.games = [];
factory.populateTable((data) => {
scope.games = data;
})
}]);
angular-app.js
'use strict';
const myApp = angular.module('angularApp', ['ngRoute', 'ngResource']);
// routes in another file
For those that are interested, the issue I was having was that either teaspoon-jasmine, phantomjs or both don't recognize javascript es6 syntax, if there is any es6 in a file that would normally be required, the entire file and it's contents are ignored without any error messages. Once I reverted my angularApp and controller code to ES5, my problem was solved.

loading momentjs with requirejs causes app to hang

I am trying to require momentjs in my web application. I am using ASP.NET MVC on the server-side, and Durandal on the client-side.
requirejs.config({
urlArgs: "bust=" + (new Date()).getTime(),
paths: {
'text': '../Scripts/text',
'durandal': '../Scripts/durandal',
'plugins': '../Scripts/durandal/plugins',
'transitions': '../Scripts/durandal/transitions',
'moment': '../Scripts/moment'
},
noGlobal: true
});
and then here is my define function
define(['moment'], function(moment) {
moment().format();
});
I am working directly off of the Moment.js Docs
I can see that the moment.js script is loaded but once it gets through the define function the application is just sitting there. If I take the define out everything works fine.
Can someone please help me figure out what I am doing incorrectly here?
I am adding a fiddle of my entire main.js file maybe that will help.
I think that I might have been misunderstanding a concept with require.js. I changed my main.js file to NOT have a the define that returns moment and instead just added a new modules that lookes like this..
define(['moment'], function() {
return {
dates: {
getSimpleDate: getSimpleDate,
getDateTime: getDateTime
}
};
function getSimpleDate (date) {
return moment(date).format('DD-MMM-YYYY');;
};
function getDateTime(date) {
return moment(date).format('DD-MMM-YYYY H:mm:ss a');
}
});
That seems to be working out just fine.

Jasmine, RequireJS and Rails

I'm starting to make the move over to requireJS for a project I'm building. I'm currently using jasminerice, rails 3.2 and the require-rails gem.
I've tried to implement http://ryantownsend.co.uk/post/31662285280/jasminerice-and-requirejs-rails-fix with little success, the specs don't run at all.
I am starting to think it maybe I might be better to use requirejs on it's own or maybe the jasmine gem?
I'm not sold on either jasminerice or require-rails gems, so does anyone have any advice on the best tools, and any tips on how to get it up and running/good tutorials?
Ok as I didn't get any response I managed to find a slightly hacky way of making it work.
If you create a file in your view folder jasminerice/spec/index.html.erb (or haml) and copy the html from the jasminerice gem. Replace the spec.js call with:
%script{"data-main"=>"/assets/#{#specenv}", src:"/assets/require.js"}
Then write your spec file like require template like so:
require.config {
paths:{
'jquery':'/assets/jquery'
'underscore': '/assets/underscore-min'
'sinon':'sinon-1.6.0'
'jasmine-sinon':'jasmine-sinon'
'my_js':'my_js'
'my_spec':'my_spec'
}
}
require ['sinon', 'jasmine-sinon', 'jquery', 'underscore', 'my_js', 'my_spec'], () ->
jasmine.getEnv().execute()
This will prevent jasminerice triggering the tests
jasmine.rice.autoExecute = false
Set up your tests with a beforeFilter similar to this(taken from http://kilon.org/blog/2012/08/testing-backbone-requirejs-applications-with-jasmine/)
describe "MySpec", ->
beforeEach ->
flag = false
#thing = ""
that = #
require ['myjs'], (Myjs) ->
flag = true
that.thing = new Myjs()
waitsFor ->
flag
it 'It should exsist', ->
expect(#thing).toBeDefined()
Hope that helps anyone with a similar issue and if anyone has a better solution please post! :)
I have the same setup, here's what I did (starting from the blog post mentioned in the original question):
1. Create a helper to load all spec files
In a file lib/jasminerice/spec_helper.rb, put the following code:
require "requirejs-rails"
module Jasminerice
module SpecHelper
include RequirejsHelper
def spec_files
Rails.application.assets.each_logical_path.select { |lp| lp =~ %r{^spec/.*\.js$} }
end
end
end
This will create a helper method spec_files which you can call in the Jasminerice runner view to automatically get all your specs, so you don't need to update the list of specs every time you add a new one.
2. Override default Jasminerice index view
Create a view named app/views/jasminerice/spec/index.html.erb with the following:
<!doctype html>
<head>
<title>Jasmine Spec Runner</title>
<%= stylesheet_link_tag "jasmine", "spec" %>
<%= requirejs_include_tag 'application' %>
<%= javascript_include_tag "jasminerice", "spec", :debug => true %>
<script>
jasmine.rice.autoExecute = false;
require([<%= spec_files.map { |f| "'#{f.sub(/\.js$/,'')}'" }.join(',').html_safe %>],
function() { jasmine.getEnv().execute() },
function(err) {
var failedId = err.requireModules && err.requireModules[0];
requirejs.undef(failedId);
define(failedId, function() { return function() { console.debug(failedId + ': ' + err); null }; });
require([ failedId ], function() {} );
});
</script>
<%= csrf_meta_tags %>
</head>
<body>
</body>
</html>
This will require all the specs before running Jasmine (with jasmine.getEnv().execute()). I have an ugly hack in there to take the array of spec paths and generate an array of module names in quotes to pass to require.
I've also included an error callback in case there's a problem loading a module -- if you don't do this, your specs will hang when a module load fails. That's especially a problem when you're running them on the command line through guard-jasmine, which is what I do.
Unfortunately I haven't found a very good way to handle such errors -- here I write some info to console.debug and then required the failed module, returning an anonymous function in its place. This allows the specs to run but produces unpredictable results (which is better than no results). I've been struggling to find a better way to deal with this situation, suggestions would be much appreciated.
3. Write some specs
My Jasmine specs take the form:
define (require) ->
MyModule = require 'my-module'
# any other dependencies needed to test
describe 'MyModule', ->
it 'exists', ->
expect(MyModule).toBeDefined()
etc. Note that all my testing dependencies (jasmine, sinon, jasmine-sinon, etc.) I load outside of require, in spec.js.coffee:
#=require sinon
#=require jasmine-sinon
#=require_tree ./helpers/
I put any other helper functions I need in the helpers directory.
4. Bonus
One other tip: if you have problems because your browser won't reload modules even when they change, I use a trick of adding a dummy argument with a timestamp so that the browser will always see a new file and correctly load it.
I created this function in ApplicationController which I load in a before filter:
before_filter :set_requirejs_config
def set_requirejs_config
opts = { :urlArgs => "bust=#{Time.now.to_i}" }) if Rails.env == "development"
Requirejs::Rails::Engine.config.requirejs.run_config.merge!(opts)
end
This adds a query param bust=... to the end of each module name if we're in development mode, so that we always reload modules and get the most up-to-date version. Somewhere there's a post on SO explaining how to do this in RequireJS, but to get it to work with requirejs-rails you have to put it into ApplicationController (and not config/requirejs.yml) so that it is loaded every time you load the page.
Hope that might provide some hints to anyone else using this configuration!

Override jQuery UI DatePicker _generate HTML Function

In jQuery UI 1.7, I had successfully overridden the datepicker._generateHTML function running a script in the form:
jQuery.datepicker._generateHTML = function(inst) {
...revised code...
};
When I attempted to upgrade to version 1.8 using the same approach, I encountered a problem. Version 1.8 added a datepicker closure scope variable dpuuid, which is referenced in the new version of the '...revised code...'. datepicker._generateHTML now fails with a dpuuid is not defined' error.
I'm still new enough to Javascript to not understand all the subtle aspects of the language. So my first question is: 'Can a function which references a closure scope variable be overridden and still access the original closure scope?'
I found the answer in Thomas' answer for jQuery DatePicker how to disable auto day selection while browsing calendar?
Adding the following to the top of my '...revised code...':
if (!inst.dpuuid) {
for (attr in window) {
if(/^DP_jQuery_/.test(attr)) {
inst.dpuuid = attr.replace(/^DP_jQuery_([0-9]+)/, '$1');
}
}
}
var dpuuid = inst.dpuuid;
eliminated the dpuuid is not defined' error. I had seen in FireBug that the closure scope was visible from the window object, but had no idea how to extract values from it.
Thanks Thomas!!

Resources