Yesod route interpolation in Julius via widgetFile - yesod

I think #{SomeRouteR} should work in .julius files, as described in:
https://www.yesodweb.com/book/shakespearean-templates#shakespearean-templates_julius_javascript
Everything was working when I first had this in my Handler:
toWidget [julius|
$("#examplespan").click(function(){
$.ajax({
url: #{ExampleR},
type: "POST",
...
|]
But now that I've changed my Handler to work like this:
$(widgetFile "example")
I added this code in example.julius:
$("#examplespan").click(function(){
$.ajax({
url: #{ExampleR},
type: "POST",
...
I now get the error:
[Error#yesod-core] expected EUrl but got Nothing for: DerefIdent (Ident "ExampleR")
CallStack (from HasCallStack):
error, called at ./Text/Shakespeare.hs:441:27 in shakespeare-2.0.20-3iMfZ8A5DXH3Twhu6IoWNc:Text.Shakespeare #(yesod-core-1.6.9-7g4SwkDmJJ261rdNBKrLzX:Yesod.Core.Class.Yesod ./Yesod/Core/Class/Yesod.hs:662:5)
What am I doing wrong?

There might not be anything wrong here. I will copy in a troubleshooting note I have written previously for my company.
DerefBranch Error from a Template File
I made a change in a template ({*.hamlet,*.cassius,*.lucius,*.julius}) and I get an error like this:
\"rawJS\")) (DerefBranch (DerefIdent (Ident \"tshow\")) (DerefIdent (Ident
\"errors\")))\nCallStack (from HasCallStack):\n error
This is an issue with [I believe] template Haskell and the way that we're compiling. Maybe it's some GHC flags, maybe it's GHCi itself, I'm not sure.
You can resolve this by touching the file that references the template, e.g., if your template file is templates/foo.julius, and you reference it with $(widgetFile "foo") in the Handler.Foo module, then touch (or save from your editor) the src/Handler/Foo.hs file and reload GHCi.

Related

Qunit assert throws not working

I am trying to assert that a few steps in the code (visiting page, providing wrong card-number, password combination and clicking submit)should generate an error from the backend service - I have referred to this already..
and tried the suggestion of using Error Object as the second argument to assert.throws but that doesn't work for me.
i did see this link as well before posting my question,
My problem is - I don't have control over the code that throws the exception/error in this case. (I cannot change it to say Ember.assert etc) I just want to be able to catch an erroneous case.
Secondly, I don't have a component in this case. Its a straight forward API call that's made when click on submit is done, basically an action submitAuthForm is called in controller which calls ember cli mirage scenario that returns the following object problems object.
return new Response(401,{'X-Auth-Token': 'wrong-username-password-combination'},failResponse401);
and the returned object looks like
var failResponse401 = {
problems: [ {
field: null,
index: null,
value: null,
code: '0006',
subCode: '',
details: {},
_type: 'error'
} ]
};
We have a node_module dependency on an in-house exceptions kit that throws an Error object based on this.
Here's my Qunit test
test('ERROR_CASE_visiting /signon, provide cardNumber(2342314) and ' +
'password, submit and expect to see invalid cardnumber/password error',
function (assert) {
assert.expect(2);
assert.throws(
function () {
visit('/signon');
fillIn('#a8n-signon-card-number input', '2342314');
fillIn('#a8n-signon-password input', 'password');
click('#a8n-signon-submit-button button');
},
Error,
"Error Thrown"
);
});
I keep getting this error from Qunit
Error Thrown# 110 ms
Expected:
function Error( a ){
[code]
}
Result:
undefined
Diff:
function Error( a ){
[code]
}defined
Source:
at Object.<anonymous> (http://localhost:7357/assets/tests.js:175:12)
at runTest (http://localhost:7357/assets/test-support.js:3884:30)
at Test.run (http://localhost:7357/assets/test-support.js:3870:6)
at http://localhost:7357/assets/test-support.js:4076:12
at Object.advance (http://localhost:7357/assets/test-support.js:3529:26)
at begin (http://localhost:7357/assets/test-support.js:5341:20)
API rejected the request because of : []# 1634 ms
Expected:
true
Result:
false
Source:
Error: API rejected the request because of : []
at Class.init (http://localhost:7357/assets/vendor.js:172237:14)
at Class.superWrapper [as init] (http://localhost:7357/assets/vendor.js:55946:22)
at new Class (http://localhost:7357/assets/vendor.js:51657:19)
at Function._ClassMixinProps.create (http://localhost:7357/assets/vendor.js:51849:12)
at Function.createException (http://localhost:7357/assets/vendor.js:172664:16)
at Class.<anonymous> (http://localhost:7357/assets/vendor.js:133592:72)
at ComputedPropertyPrototype.get (http://localhost:7357/assets/vendor.js:32450:27)
at Object.get (http://localhost:7357/assets/vendor.js:37456:19)
at Class.get (http://localhost:7357/assets/vendor.js:50194:26)
at http://localhost:7357/assets/vendor.js:133645:30
Is there anything else that i can try to get it to work.
Is there someway i could somehow pass this test, by wrapping the returned response somehow in a way that it doesn't break my test altogether.
I found a workaround following this link
the user pablobm has posted a link to a helper
I used that to workaround this Qunit issue.

Exact field input mongoose for nodejs

I've recently been attempting to pull my hair out getting stuck on what I would call a trivial issue.
The way mongoose in nodejs handles the specific field inputs. I have a specific issue where mongoose is not doing the same as mongodb is doing.
The issue is the following, if I use a "-" symbol in my field name, mongoose seems to run some weird operation on it, instead of accepting it as part of a string.
I've tried running several regex commands, some / escapes, however it should literally just take the input, as I know the specific data I'm looking for.
The code causing the issue is the following:
datapoints.find({type: "charging-type", device: device._id})
.exec(function(err, objects){
if(!objects){
log("Can't find objects");
}
});
Going straight into mongo shell and typing:
db.datapoints.count({type: "charging-type", device: device._id})
taking out the type makes everything work, changing the type to for example: shuntvoltage, current, ... all work perfectly.
The problem thus occurs with the usage of this - symbol.
What would be the way to enter this inputstring with a special character as an exact string?
Any help would be much appreciated.
Edit as per request; I don't get any error, I get objects==undefined (or !objects), schema is below.
var datapointSchema = mongoose.Schema({
type: { type: String, lowercase: true},
value: { type: Number},
timestamp: { type: Number},
device: { type: ObjectId, ref: "devices"}
});
module.exports = mongoose.model('datapoints', datapointSchema)
Manually updated the field in mongodb from charging-status to chargingstatus, as no useful answer was produced.
It's a workaround and should be considered unresolved.
Final code ended up looking as such:
var cursor = calcpoints.find({device: device._id}).where('type').equals('chargingstatus').sort({timestamp: 1}).cursor();

How to import Shakespearean Templates in Yesod?

I was using QuasiQuotations in Yesod, and everything worked fine. BUT my file became very large and not nice to look at. Also, my TextEditor does not highlight this syntax correctly. That is why is split my files like so:
getHomeR :: Handler Html
getHomeR = do
webSockets chatApp
defaultLayout $ do
$(luciusFile "templates/chat.lucius")
$(juliusFile "templates/chat.julius")
$(hamletFile "templates/chat.hamlet")
If this is wrong, please do tell. Doing runghc myFile.hs throws many errors like this:
chat_new.hs:115:9:
Couldn't match expected type ‘t0 -> Css’
with actual type ‘WidgetT App IO a0’
The lambda expression ‘\ _render_ajFK
-> (shakespeare-2.0.7:Text.Css.CssNoWhitespace . (foldr ($) ...))
...’
has one argument,
but its type ‘WidgetT App IO a0’ has none
In a stmt of a 'do' block:
\ _render_ajFK
...
And this.
chat_new.hs:116:9:
Couldn't match type ‘(url0 -> [(Text, Text)] -> Text)
-> Javascript’
with ‘WidgetT App IO a1’
Expected type: WidgetT App IO a1
Actual type: JavascriptUrl url0
Probable cause: ‘asJavascriptUrl’ is applied to too few arguments
...
And also one for the HTML (Hamlet).
Thus, one per template.
It seems that hamletFile and others treat templates as self-contained, while yours are referencing something from each other. You can play with order of *File calls, or use widgetFile* from Yesod.Default.Util module:
$(widgetFileNoReload def "chat")
The Reload variant is useful for development - it would make yesod devel to watch for file changes and reload them.

experiencing issue with route in play 1.2.5

I probably have misconfigured my route file for play-1.2.5 - below is the relevant route file part & the URL being used:
URL:
GET /application/autoComplete?term=mac
Route:
GET /autoComplete/{term} controllers.Application.AutoCompleteTerm
I also have the following route defined but its not getting picked up:
GET /autoComplete/ controllers.Application.AutoCompleteTerm
The route does not get hit - instead, I get a template not found exception:
play.exceptions.TemplateNotFoundException: Template not found
Any suggestions to help troubleshoot this will be quite welcome. thanks
The route:
GET /autoComplete/{term} controllers.Application.AutoCompleteTerm
...is wrong. It should be like this:
GET /autoComplete/{term} Application.autoCompleteTerm
This would correspond to the following URL:
GET http://127.0.0.1:9000/autoComplete/mac
The corresponding method in Application would look like this:
public static void autoCompleteTerm(String term) {
...
}
The URL:
GET http://127.0.0.1:9000/autoComplete?term=mac
...would need the following route:
GET /autoComplete Application.autoCompleteTerm
...and the same method as above:
public static void autoCompleteTerm(String term) {
...
}

Jasmine tests AngularJS Directives with templateUrl

I'm writing directive tests for AngularJS with Jasmine, and using templateUrl with them: https://gist.github.com/tanepiper/62bd10125e8408def5cc
However, when I run the test I get the error included in the gist:
Error: Unexpected request: GET views/currency-select.html
From what I've read in the docs I thought I was doing this correctly, but it doesn't seem so - what am I missing here?
Thanks
If you're using ngMockE2E or ngMock:
all HTTP requests are processed locally using rules you specify and none are passed to the server. Since templates are requested via HTTP, they too are processed locally. Since you did not specify anything to do when your app tries to connect to views/currency-select.html, it tells you it doesn't know how to handle it. You can easily tell ngMockE2E to pass along your template request:
$httpBackend.whenGET('views/currency-select.html').passThrough();
Remember that you can also use regular expressions in your routing paths to pass through all templates if you'd like.
The docs discuss this in more detail: http://docs.angularjs.org/api/ngMockE2E.$httpBackend
Otherwise use this:
You'll need to use the $injector to access the new backend. From the linked docs:
var $httpBackend;
beforeEach(inject(function($injector) {
$httpBackend = $injector.get('$httpBackend');
$httpBackend.whenGET('views/currency-select.html').respond(200, '');
}));
the Karma way is to load the template html dynamically into $templateCache. you could just use html2js karma pre-processor, as explained here
this boils down to adding templates '.html' to your files in the conf.js file
as well
preprocessors = {
'.html': 'html2js'
};
and use
beforeEach(module('..'));
beforeEach(module('...html', '...html'));
into your js testing file
If this is a unit-test, you won't have access to $httpBackend.passthrough(). That's only available in ngMock2E2, for end-to-end testing. I agree with the answers involving ng-html2js (used to be named html2js) but I would like to expand on them to provide a full solution here.
To render your directive, Angular uses $http.get() to fetch your template from templateUrl. Because this is unit-testing and angular-mocks is loaded, angular-mocks intercepts the call to $http.get() and give you the Unexpected request: GET error. You can try to find ways to by pass this, but it's much simpler to just use angular's $templateCache to preload your templates. This way, $http.get() won't even be an issue.
That's what the ng-html2js preprocessor do for you. To put it to work, first install it:
$ npm install karma-ng-html2js-preprocessor --save-dev
Then configure it by adding/updating the following fields in your karma.conf.js
{
files: [
//
// all your other files
//
//your htmp templates, assuming they're all under the templates dir
'templates/**/*.html'
],
preprocessors: {
//
// your other preprocessors
//
//
// tell karma to use the ng-html2js preprocessor
"templates/**/*.html": "ng-html2js"
},
ngHtml2JsPreprocessor: {
//
// Make up a module name to contain your templates.
// We will use this name in the jasmine test code.
// For advanced configs, see https://github.com/karma-runner/karma-ng-html2js-preprocessor
moduleName: 'test-templates',
}
}
Finally, in your test code, use the test-templates module that you've just created. Just add test-templates to the module call that you typically make in beforeEach, like this:
beforeEach(module('myapp', 'test-templates'));
It should be smooth sailing from here on out. For a more in depth look at this and other directive testing scenarios, check out this post
You could perhaps get the $templatecache from the injector and then do something like
$templateCache.put("views/currency-select.html","<div.....>");
where in place of <div.....> you would be putting your template.
After that you setup your directive and it should work just fine!
If this is still not working , use fiddler to see the content of the js file dynamically generated by htmltojs processor and check the path of template file.
It should be something like this
angular.module('app/templates/yourtemplate.html', []).run(function($templateCache) {
$templateCache.put('app/templates/yourtemplate.html',
In my case , it was not same as I had in my actual directive which was causing the issue.
Having the templateURL exactly same in all places got me through.
As requested, converting a comment to an answer.
For the people who want to make use of #Lior's answer in Yeoman apps:
Sometimes the way the templates are referenced in karma config and consequently - the names of modules produced by ng-html2js don't match the values specified as templateUrls in directive definitions.
You will need adjusting generated module names to match templateUrls.
These might be helpful:
https://github.com/karma-runner/karma-ng-html2js-preprocessor#configuration
gist: https://gist.github.com/vucalur/7238489
this is example how to test directive that use partial as a templateUrl
describe('with directive', function(){
var scope,
compile,
element;
beforeEach(module('myApp'));//myApp module
beforeEach(inject(function($rootScope, $compile, $templateCache){
scope = $rootScope.$new();
compile = $compile;
$templateCache.put('view/url.html',
'<ul><li>{{ foo }}</li>' +
'<li>{{ bar }}</li>' +
'<li>{{ baz }}</li>' +
'</ul>');
scope.template = {
url: 'view/url.html'
};
scope.foo = 'foo';
scope.bar = 'bar';
scope.baz = 'baz';
scope.$digest();
element = compile(angular.element(
'<section>' +
'<div ng-include="template.url" with="{foo : foo, bar : bar, baz : baz}"></div>' +
'<div ng-include="template.url" with=""></div>' +
'</section>'
))(scope);
scope.$digest();
}));
it('should copy scope parameters to ngInclude partial', function(){
var isolateScope = element.find('div').eq(0).scope();
expect(isolateScope.foo).toBeDefined();
expect(isolateScope.bar).toBeDefined();
expect(isolateScope.baz).toBeDefined();
})
});
If you are using the jasmine-maven-plugin together with RequireJS you can use the text plugin to load the template content into a variable and then put it in the template cache.
define(['angular', 'text!path/to/template.html', 'angular-route', 'angular-mocks'], function(ng, directiveTemplate) {
"use strict";
describe('Directive TestSuite', function () {
beforeEach(inject(function( $templateCache) {
$templateCache.put("path/to/template.html", directiveTemplate);
}));
});
});