nikgoodley-ibboost / js-test-driver

Automatically exported from code.google.com/p/js-test-driver
0 stars 0 forks source link

HTML Injection from separate file #61

Open GoogleCodeExporter opened 9 years ago

GoogleCodeExporter commented 9 years ago
I would like to be able to load specific DOM to be loaded to my test
executes. The two ways of doing that right now are rather cumbersome and
don't make for a good seperation between my HTML fixture and my JavaScript
test code.

It would be really cool if I could just tell js-test-driver to load a html
file together with my js tests by way of configuration file.

Original issue reported on code.google.com by Mark.Lehmacher@gmail.com on 2 Nov 2009 at 1:39

GoogleCodeExporter commented 9 years ago

Original comment by toc...@gmail.com on 2 Nov 2009 at 6:45

GoogleCodeExporter commented 9 years ago
Mark,

How would the configuration file look? Specifically, how would the html be 
associated 
with the test?

Original comment by corbinrs...@gmail.com on 2 Nov 2009 at 7:02

GoogleCodeExporter commented 9 years ago
[deleted comment]
GoogleCodeExporter commented 9 years ago
Hello Corbin,

first let me apologize for the late reply.

I would imagine something like this:

html:
  - */my_test.js: src_test/my_test.html
  - src-test/*.js: src_test/fixture.html

The first match determines the injected html. Tests which don't match any
rule do not get anything injected.

Original comment by Mark.Lehmacher@gmail.com on 3 Dec 2009 at 8:11

GoogleCodeExporter commented 9 years ago
How could you indentify a specific HTML file inside a test case when you have a 
lot of 
html files?

Loading HTML fixtures *INSIDE* a test case would be better I think, like JSPec 
and 
JSUnit does. 

Original comment by herberth...@gmail.com on 25 Jan 2010 at 2:20

GoogleCodeExporter commented 9 years ago
I have a slightly different idea. JsTestDriver already provides two HTML 
fixtures in
which to run tests. A) Blank HTML 4.01 document and B) Blank HTML 4.01 Strict
document. I think the configuration file should make it possible to add custom
environments to run tests in. So, the configuration file could include a 
section like:

fixtures:
  - fixtures/*.html
  - ../other/dir/file.html

All files matched by fixtures rules would then be listed on 
http://localhost:4224/.
So rather than "Capture this browser | Capture this browser in strict mode", 
JSTD
could offer to capture the browser in a given environment, e.g. like:

Capture this browser:
  * In blank HTML 4.01 Transitional Document (Same as today's "Capture this browser")
  * In blank HTML 4.01 Strict Document (Same as today's "Capture this browser in
strict mode")
  * In [title of provided fixture 1]
  * In [title of provided fixture 2]
  * In [title of provided fixture 3]

The title of the user provided fixtures could be extracted from the page's 
<title>.

I'm not sure this solves exactly the problem of the original poster, but would 
be an
interesting feature, as it would allow jstd to be used for more integration 
style
tests as well.

Original comment by chrisj...@gmail.com on 18 Mar 2010 at 3:37

GoogleCodeExporter commented 9 years ago
I agree with core developers, that there is no need for that to be implemented
inside JsTestDriver. Everybody has slightly different needs and this
would make configuration complicated.

It is easy to solve in JavaScript:

* request HTML page with XMLHttpRequest
* extract body
* inject into the body of the document under test

    req = new XMLHttpRequest();
    req.open('GET', url, false); /* synchronous */
    req.send(null);
    /* body element with children */
    body_content = req.responseText.match(/<body[\s\S]*<\/body>/); 
    body = document.documentElement.getElementsByTagName('body')[0];
    /* body tag itself is ignored, only its children will be inserted */
    body.innerHTML = body_content; 
}

I've documented the full solution at
http://www.mobile-web-consulting.de/post/4720306582/jstestdriver-html-injection-
from-separate-file

Original comment by geekQ...@googlemail.com on 18 Apr 2011 at 3:55

GoogleCodeExporter commented 9 years ago
Issue 324 has been merged into this issue.

Original comment by corbinrs...@gmail.com on 4 Jan 2012 at 7:59

GoogleCodeExporter commented 9 years ago
So, in other words, because there's an incredibly awkward and hacky way of 
doing something already, the developers shouldn't make the tool easier to use?  
I really don't follow that logic.  As for "everyone has slightly different 
needs", I strongly disagree: there is (at least) one case that has very common 
requirements across the JS community: templates.

If you're not familiar with the templating paradigm, it's incredibly popular 
right now: there are numerous templating libraries being actively developed 
(eg. Moustache), major libraries (eg. jQuery) are adding their own templating 
functionality, and major frameworks (eg. Backbone.js) already assume templating 
as part of their design.  While details vary from library to library, the basic 
idea is that instead of doing:

var option = "<option value='" + value + "'>" + label + "</option>";

(which of course breaks the MVC barrier and pollutes your JS with HTML) you 
instead do:

*HTML*
<script language="template" id="optionTemplate">
<option value="{{value}}">{{label}}</option>
</script>

*JS*
var option = templatingLibraryFunction("optionTemplate", {value:value, 
label:label});

With this approach you stop having to switch between ', ", \', etc. when 
writing HTML.  You stop having to look at HTML in a JS editor that can't syntax 
color it properly.  You stop having your view (HTML) mixed in to your 
controller (JS).  I could go on about the virtues of templating, but hopefully 
you get the basic idea: this is a common approach/technique used by a 
significant number of developers ... and those developers want to test their JS 
too (moreso than JS developers in general in fact: if you understand the 
importance of the MVC separation of concerns, you're clearly up to date on best 
practices and more likely to also understand the importance of testing).

So what does any of that have to do with this ticket?  Simple: the HTML of the 
templates is a critical part of the code, and there is currently no way of 
bringing them in to the test environment.

Current options:
1) You can use the serve directive to serve the HTML file, then use something 
like what GeekQ included.  Biggest downside: everyone has to roll their own 
solution.  Also, everyone now has to use AsyncTestCases for EVERY test they 
ever write (because everyone now needs a "wait for the HTML to come back" step, 
even if nothing else in their test has anything to do with AJAX).

Also there are other minor inconveniences in this approach.  For instance, if 
your templates aren't in a sub-directory of your jsTestDriver.conf file, you 
wind up having to use a relative path to specify them in the conf, which then 
results in needing an absolute path to access them (an absolute path which, on 
Unix at least, contains your home directory's name ... not something you want 
to include in code you share with other developers who have different home 
directories).

2) You can use the "HTML in comments" approach.  That's an awesome way to go 
for short bits of HTML that are specific to a given test ... but it's a 
terrible way to bring in hundreds of templates.  You would essentially have to 
copy/paste every template in to the JS comments, and then maintain two versions 
of your templates.  That's not just un-DRY, that's plain fugly.

3) You can compile your templates in to your JS.  This is actually not an 
uncommon practice among templaters ... but not everyone wants to have to 
"compile" their HTML (which is essentially what you have to do to get the HTML 
in to the JS, without just writing the HTML in JS in the first place).

All of these are sub-optimal.  A VERY simple alternative would enable template 
testing with none of those downsides:

4) Give users a way (either globally in jsTestDriver.conf or on a test-by-test 
basis; EITHER would be a vast improvement) to specify certain HTML files which 
should be included on the page.  Now I know there are concerns with global 
additions like this, but what is a JS include?  It's a global addition of some 
HTML ("<script src='...").  This new feature would be no different in anyway, 
except that instead of appending script tags it would append the contents of 
HTML files.  As such, it could even use the existing load directive (just add 
support for HTML files).

Hopefully that explains both the problem and a potential solution, but I'm 
happy to elaborate if any of that is unclear.  But please, at least consider 
the benefits this feature (which, again, should be really easy to implement: 
just replace "<script src='someFile'>" with "*contents of someFile*, and do 
everything else identically to what JS-Test-Driver already does).

Original comment by machineg...@gmail.com on 4 Jan 2012 at 9:35

GoogleCodeExporter commented 9 years ago
Further evidence that this would be a beneficial feature:
http://www.mobile-web-consulting.de/post/4720306582/jstestdriver-html-injection-
from-separate-file

BTW, Java isn't my *best* language, but if the project maintainer decides this 
issue is worth fixing I'd be more than happy to (with a little guidance/help) 
write an implementation for this ...

Original comment by jer...@syapse.com on 10 Feb 2012 at 1:56

GoogleCodeExporter commented 9 years ago
I agree with Herbert that HTML files should be associated with individual 
tests. How about a syntax patterned after the very similar /*:DOC foo = 
<div><p>foo</p></div> */ feature? Say, /*:DOCFILE foo = 
../../modules/Foo/index.html */?

Original comment by bluej...@gmail.com on 25 May 2012 at 7:20

GoogleCodeExporter commented 9 years ago
@bluej

I disagree that HTML files should only be associated with individual tests.  
Have you ever written a test suit for a component/widget, where every test 
relies on that component's HTML being there (eg. an autocomplete widget that 
expects a text input with certain classes to always be present)?  It'd be silly 
to have to repeat that setup for every test.

However, that's exactly why I think your suggestion is a great one.  Part of 
the genius of of the HTMLDoc is that it isn't (just) test-specific.  You can 
have test-specific HTMLDoc by putting it in a test, OR you can have 
test-suite-specific HTMLDoc by putting it in to a setUp method.  If you want, 
you can even have HTMLDoc shared by all tests, by putting it in to a 
"setupCommonHtmlDoc" method, and then making sure to call it in every setUp 
method.

If HTML injection used the same mechanism, it could similarly be scoped at 
different levels (test, suite, and universal), which would let everyone use it 
however they wanted to.  That'd be great.

Original comment by jer...@syapse.com on 25 May 2012 at 7:50

GoogleCodeExporter commented 9 years ago
I've prepared a patch set which I think is close to a solution. There are still 
some issues with relative paths which I'm not sure how to resolve.

http://codereview.appspot.com/6453068

Corbin, does this look decent to you?

Original comment by bluej...@gmail.com on 31 Jul 2012 at 7:25

GoogleCodeExporter commented 9 years ago
Thanks GeekQ for the work around.  I'm wondering if there might be a similar 
work abound for calling submit on a form? I found this asked in issue 319, 
https://code.google.com/p/js-test-driver/issues/detail?id=319 but the response 
was to use Webdriver instead of js-test-driver.  I'm not trying to test web 
forms, but the API that I want to call in my tests requires authentication.  

Original comment by malcolm...@gmail.com on 4 Jun 2014 at 1:47