Currently I'm doing this:
expect( tasks.at(0).get('title') ).to.be('Root')
expect( tasks.at(0).get('next') ).to.be(true)
But it seems like there should be a better way. I'd rather do something like this:
expect(tasks.at(0).attributes).to.eql({title:'Root', next:true})
But that doesn't work because tasks.at(1).attributes has many other attributes, so it doesn't strictly match. Any ideas? I'm fine with using something other than expectjs.
I don't know if it's the best way, but I took the advice from #skizeey and made my own test extension. In other words, now I call (in coffeescript):
expect(tasks).to.have.modelAttributes
1: title:'Root'
2: title:'Child'
The code I used is pretty specific to the testing library I am using (switched to Chai), but the general idea is that I iterate over the hash, extract the index, and then look at each key:value. Here's a generic example of my code:
# Check each index
for index of properties
# Iterate over each key:value in each index
for key of properties[index]
Related
I'm trying to create a custom template engine in javascript but I'm having trouble getting started as I cannot extract tokens using regex.
Here are the requirements:
Variables are defined like this: $(variable)
Functions: $(name arg1 "this is arg2 but it contains whitespaces.")
Function arguments can contain other variables $(name $(variable) arg2)
Both variables and functions will be rendered async. For example: Get the value for $(variable) from db then replace it.
This is not for rendering an html page but to simply replace a string entered by a user on the backend.
Edit
More information:
Suppose a user enters the following string:
$(id $(lowercase John))
On the backend application must do:
Convert "John" to lowercase.
Get the id for "john" from db.
This is only a simple example to demonstrate how this should work.
Are there any libraries that can help me achieve this? If not, any idea how to implement this?
EDIT 2:
I tried using Mustache and I changed the delimiters to $(), however the function (section) tags do no satisfy the requirements. In Mustache, for functions I must do this: $(#name) $(variable) "this is arg2 but it contains whitespaces."$(/name) also it does not support async rendering.
If not, any idea how to implement this?
You should use an Abstract Syntax Tree, and write a compatible parser. While regex (as Pedro Lima stated) is good for simple templating, if you ever want to extend the parser, you'll need something a bit more robust.
As an example of an Abstract Syntax Tree parser, $(test1 $(test2) test3) lorem ipsum $(test4) would be turned into the following:
(Thanks to Mile Shang's Syntree for the tree generator.)
As for specifically how to write a parser, I think you can figure it out. Just iterate over the string and check for the template delimiter. Reading the source code for a templating library like Handlebars might help.
Here. This regex will identify the templates that can be replaced. Note that it only selects the innermost templates in nested templates.
/\$\((?<FirstTerm>\S+?)(?<OtherTerms>(?:\s+(?:\w+|".*?"))+)?\)/g
So just use a regex replace function with your templating logic recursively until there are no more matches. The inner templates will be replaced and you'll be left with the string with templates replaced.
Other answers on this post are correct, however, I want to share exactly how I managed to implement this:
Create a recursive match function. I used Steven Leviathan's article to implement this.
Create a render function and inside the function call the recursive match function to find and replace variable/function names with appropriate values.
Keep calling the render function recursively until all arguments inside a function have been replaced.
I've been following the V8 embedder's guide example "Accessing Dynamic Variables", and have managed to adjust the given code so that it compiles correctly with the latest version. However, the example shows only how to define accessors for a Class. If I'd like to use javascript to modify an existing Point instance, how do I pass that through?
For example, I imagine this scenario:
C++:
Point* p=...
p->x=10;
....
//This is where I'm completely stuck
....
Handle<Script> handleScript=Local<Script>::New(isolate, ...);
handleScript->Run();
//now p->x should be 5
javascript:
p.x=5;
EDIT: it seems the easiest way would be something like: (continuing from the example)
context->Global()->Set(String::NewFromUtf8(isolate, "p"), obj);
if there's a better way, I'd be happy to hear it.
The easiest way would be: (continuing from the example)
context->Global()->Set(String::NewFromUtf8(isolate, "p"), obj);
I am learning Zombie.js with node.js using sys.debug() statements to track my progress. What is returned by calls like this t = browser.body.querySelector(".navigation"); ? It is hard to tell what is going on without browser developer tools or something like php's var_dump. The API doesn't really explain it.
How do I unpack this?
t = browser.body.querySelector(".navigation");
sys.debug(t); //returns "DEBUG: [ UL.navigation]" I don't know what this means.
.querySelector() is defined as part of a DOM API, specifically the Selectors API, which Zombie.js is using an implementation of.
So, as it does in other browsers, it should return:
[...] the first element that is a descendent of the element on which it is invoked that matches the specified group of selectors.
In this case, based on the UL.navigation in the log, t is an HTMLUListElement. Or:
<ul class="navigation"></ul>
And, in cases where no matching Element can be found, it'll return null.
Apparently ie8 has three properties that get appended to the resulting array from a call to String.prototype.match():
input, index and lastIndex
(MSDN Documentation)
The result is that array comparison fails when using Jasmine's .toEqual() matcher.
I'm still working my way up the learning curve on unit testing, so I'm just curious of what the right way is to do deal with this failure.
The following works but seems a bit lame:
numArray = str.match(/\d+(\.\d+)?/g);
if (numArray && numArray.input) {
delete numArray.index;
delete numArray.input;
delete numArray.lastIndex;
}
Underscore's 'difference' method can help -
expect(_.difference(['item1', 'item2'], ['item1', 'item2'])).toEqual([]);
http://underscorejs.org/#difference
I think #monkeyboy's answer is not correct.
Since underscore.difference() returns the elements of the first array that are not present in the second array: _.difference([1],[1,2]); is also [] so the test will pass when it shouldn't. I couldn't find a way to solve this using underscore.
So i'm using:
expect(JSON.stringify(result)).toBe(JSON.stringify(expected));
which works as expected.
Anyway, i'd like to know how others are doing this.
I'm doing some research for a project that I have going on the uses the document.createTreeWalker and I'm looking at a script that uses quite a few xpath's, but I'm curious as to where these come from. Some are obvious and I have been able to find answers to online, such as [#AttributeName] and [#TagName], but what is [#StoreName], [#AttributeValue1], [#AttributeValue2]...these I have not been able to look up online.
Particularly, I'm looking at these lines and not understanding:
thisURL = window.document.location.href.toString();
if(thisURL.search("[#StoreName]") != -1) { //do something }
Perhaps I'm misunderstanding your question, but there's nothing functionally or syntactically different between [#AttributeName] and [#StoreName]. They're both predicates that are looking for elements with particular attributes. The first one is looking for AttributeName attributes, while the second is looking for StoreName attributes.
That said, the code you're showing isn't actually doing any XPath work. It's just looking at whether the URL contains the character sequence [#StoreName] using JavaScript's string search function, and doing something if it does.