-
Notifications
You must be signed in to change notification settings - Fork 20.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Ajax tests: Refactor tests and fix bugs. #1060
Conversation
}, | ||
contentType: false, | ||
success: function( data ) { | ||
strictEqual( data, "content-type: \n", "Test content-type is not sent when options.contentType===false" ); | ||
deepEqual( data.headers, [], "Test content-type is not sent when options.contentType===false" ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be an empty object for consistency.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
PHP has no distinction between associative arrays and numerical arrays. It is a very blurry thing. Either way, when an "intended to be" associative array is empty, json_encode
outputs an array, not an object.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I know, but client-side unit tests shouldn't have to be dependant on a flaw in the PHP implementation of json_encode.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed. Fixed on the PHP side by casting the (potentially empty) associative array to a stdClass
object. That way json_encode
will always encode it to a plain object.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
BTW, I'm just going to leave this here:
json_encode(array(), JSON_FORCE_OBJECT);
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I knew about JSON_FORCE_OBJECT
but the solution I went with in the next amendment (casting (object)
) is basically exactly the same (people commonly doing that lead to PHP implementing JSON_FORCE_OBJECT
natively as of PHP 5.3).
I guess I'm still getting used to the fact that PHP 5.3+ is okay nowadays :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's been forever. 5.3 is fine! closures, namespaces, late static binding.... huzzah!
Nice overall but I think you went a step too far when merging the request headers logic in |
@jaubourg I think it makes perfect sense to use valid JSON transportation protocols for this. There are already tests before this that assert that stuff like that is working fine. Once past that we can just use this. We also use hasClass, addClass, remove, load and what not in unit tests. Also, the other reason I did this is to fix the "Content MIME type" warnings I was getting in Chrome. Those are all gone now. As for the content type changing based on which headers are passed, that's not true in the latest version. The logic is like this: echo.php responds with whatever content-type it is told to respond with. If none given, the default behaviour is that plain Note that the parameter is I don't see how it makes a difference whether it is in the same script or not. Instead of the content-type changing between "headers/request" and "echo" it now changes between "echo?content" and "echo?extended". I even thought about merging the other two in as well. For the most part they are already obsolete, I just hadn't given it the time yet. |
Unit tests are units, they should not test more than what they are supposed to test (and, yes, we have some further cleanup to do). They also should be independant on whether a previous test passed or not (keep aside most extreme cases like Deferreds being broken). If you have implicit json responses, then you test a whole bunch of the internals of That's why I started the rewrite: things had gone very wrong because too big a proportion of the logic of our ajax tests was taking place in PHP due to "magical" scripts that would do one thing or another, implicit changes to the response given an unrelated parameter. They created hidden dependencies client-side, they were also hidding actual problems in our unit tests. The fact we had a lot of PHP scripts that served no purpose is one thing and good riddance. But the goal here is to empower our javascript unit tests and give them power over the whole client-server cycle. Implicit logic server-side like changing the content type because headers are supposed to be set is a no-go. I'm guessing the actual reason you're doing so is because it makes it simpler to test for the results using deepEqual: if so create a helper client-side that does the parsing / test but keep the content type alone, please :) |
Some tests are still failing, this is due to Nginx/php-fpm somehow consistently serving an empty response body for some of the requests. They're all passing for me locally now. Asked @gnarf37 to investigate this server side (filed internally as jquery/infrastructure#132) |
Magic quotes: Various tests were failing because (depending on php settings) the XML string passed to echo.php would be quote-escaped. So the round tripped content was no longer valid XML. Fixed by adding a simplified version of the popular "fix magic_quotes" script and including it from the other files. Variable name eval: $requestArray =& ${"_$requestArray"}; Aside from minor security issues (accessing arbitrary _SERVER, or _ENV properties) it is rather hacky. Changed to using $_POST for POST requests, and $_GET for GET requests. Never using $_REQUEST (can contain cookies sometimes, too). For the 1 test that needed to reverse this, added an option. Header echo: The test for options.contentType wasn't working. It didn't fail in QUnit because the assertion was changed to ok() instead of strictEqual in 228ab3d. When changed back the failure was revealed. Turns out PHP doesn't expose Content-Type and Content-Length in the HTTP_ match group (it exposes any arbitrary headers, e.g. HTTP_FOO_BAR, but these those are explicitly blacklisted and only accessible from by their unprefixed key, and even then only on POST requests) See: http://php.net/manual/en/reserved.variables.server.php#110763 Path-info style ("REST-like"): When replacing preg_match( '/index.php\/([^\/\?&]+)/' .. ) with the proper $_SERVER['PATH_INFO'] for .php/<path-info> reading, a bug was uncovered where the ajax test service() was building an invalid query string. See: 228ab3d#commitcomment-2256611 XSS: Although it is just a test suite, they can run on servers and clients and XSS can bite you when least expected. Added a simple but strict/safe sanitiser for the callback name. Avoids injection of javascript. Content type: Instead of defaulting to text/plain, defaulting to the proper content-type response header for the given content. * text/javascript for JSON-P * application/json for JSON Also added charset=UTF-8 Advanced echo: To make echo a little easier and more flexible I split it into a basic mode and an advanced mode. The advanced mode, among other things, replaces the "headers/request" script. Misc: * Named success callback parameter consistently "data" instead of "msg" or "obj" etc. * Added an "assertJqXhr" function, replacing the use of ok() in its place. At the very least it should've asserted that it returned some kind of object, anyhow it should be much better now. * Changed $.each([x, y], fn(toggle, val)) where !!toggle was used as named boolean switch into more explicit: $.each({x: false, y: true}, fn (val, toggle)) * Changed conditional for 304 fail to include the isOpera factor otherwise when it does fail the only error message "this is OK to fail in Opera", which is useless outside Opera. That should only be displayed if it is failing and if it is in Opera. If either is not the case, the actual condition should be asserted
Where does this pull stand? |
The code is fine afaik. We can't merge it yet because it fails on swarm.jquery.com because of issues with NGINX and/or php-fpm (several of the AJAX tests are consistently failing due to an empty response from the server). They work fine locally in Apache. |
The code is not fine. We need to extract header requests back out of echo.php for reasons exposed in an earlier comment. |
@jaubourg Is the concern about what causes the content-type of the response to change ( |
The implicit change of We should probably go back to a separate script (so that it makes the intent clear client-side -- name of the service in url === server-side action -- and reduces implicit server-side logic) that outputs JSON as I'm just trying to keep client-side code in charge here while having tests as orthogonal and independant from one another as possible. |
I'll close this until the issues with testswarm/ngnix/moonphase are resolved. It would be great to land a cleanup like this at some point, or figure out a way to use our own nodejs "server" for ajax testing. |
This must have gone stale at this point, I'll reopen but it will need some airing out. |
Okay, closing this into obscurity unless someone rescues it. |
@dmethvin, you said you're closing this but you didn't. :) |
Why the rush? I'll get to it, I promise. There's been a lot of effort put into this. Archiving it now will probably mean we forget about it and waste efforts a few months from now going through he same arguments. |
It's been 6 months on this... @Krinkle do you have a plan/schedule for it? |
@Krinkle, ping? 9 months have passed... |
Imma close this. Glad to reopen if it gets love. |
cc @jaubourg @gibson042