Last modified: 2012-04-19 21:10:45 UTC

Wikimedia Bugzilla is closed!

Wikimedia migrated from Bugzilla to Phabricator. Bug reports are handled in Wikimedia Phabricator.
This static website is read-only and for historical purposes. It is not possible to log in and except for displaying bug reports and their history, links might be broken. See T32339, the corresponding Phabricator task for complete and up-to-date bug report information.
Bug 30339 - Implement SpecialPage for running javascript tests
Implement SpecialPage for running javascript tests
Status: RESOLVED FIXED
Product: MediaWiki
Classification: Unclassified
Unit tests (Other open bugs)
unspecified
All All
: Normal enhancement (vote)
: 1.19.0 release
Assigned To: Krinkle
:
Depends on:
Blocks: 30656
  Show dependency treegraph
 
Reported: 2011-08-12 07:59 UTC by Krinkle
Modified: 2012-04-19 21:10 UTC (History)
8 users (show)

See Also:
Web browser: ---
Mobile Platform: ---
Assignee Huggle Beta Tester: ---


Attachments
First shot at implementing Special:UnitTesting infrastructure (17.49 KB, patch)
2011-08-15 08:15 UTC, Krinkle
Details
Better patch (17.33 KB, patch)
2011-08-26 20:10 UTC, Krinkle
Details

Description Krinkle 2011-08-12 07:59:51 UTC
As proposed on mw.org [1] we want to move away from the static unit testing for JavaScript and instead run it in the context of an actual MediaWiki environment that will open many doors, such as:
* interacting with the real dom, not a static mini version in an .html file
* ability for Extensions to register unit tests
* running tests in different skins (usekin=.. ) 
* Query the API



--
Krinkle

[1] http://www.mediawiki.org/wiki/Thread:Manual_talk:JavaScript_unit_testing/QUnit_/_TestSwarm_environment,_Version_2
Comment 1 Krinkle 2011-08-12 08:05:11 UTC
Roughly summarized the approach I plan to take:
* Create a Special:UnitTesting page (disable user scripts, like preferences/login etc.)
* By default shows a list, $par is the framework of choice
* Special:UnitTesting/qunit
** Outputs the QUnit html frame
** Loads the jquery.qunit module and our testrunner
** Loads the test suites from $wgUnitTestingQUnitSuites
* $wgUnitTestingQUnitSuites is an array of module names (eg. array( 'jquery.byteLength.test' )).
* The test suites are registered as resource modules in $wgResourceModules or Resources.php: 'jquery.byteLength.test' => array( 'scripts' => ...., 'dependencies' => 'jquery.byteLength' )
Comment 2 Krinkle 2011-08-15 08:15:37 UTC
Created attachment 8919 [details]
First shot at implementing Special:UnitTesting infrastructure
Comment 3 Krinkle 2011-08-15 08:25:39 UTC
Implementation details:
* New Special:UnitTesting page (user scripts disabled, isListed returns false depending on $wgEnableSpecialUnitTesting)
* Shows a list of frameworks, by default only qunit
* [[Special:UnitTesting/qunit]] outputs the QUnit base html and loads testrunner (which loads jquery.qunit and the other stuff we need) + all test suites by passing $wgUnitTestingQUnitSuites to OutputPage's addModules().

TBD:
* As can be seen in the patch in the comment above wgUnitTestingQUnitSuites in DefaultSettings, adding stuff for extensions looks a little funky. The reason is simple, we don't want all test suites to be registered unless wgEnableSpecialUnitTesting is true (to avoid polluting the start up module with a lot of crap and making it twice or three times as big). I also considered adding a global variable just for these modules and calling register() myself in the SpecialUnitTesting page, but that doesn't work either because load.php doesn't know on what page we are, so they wouldn't be registered. Plus, that would mess up or not work at all with caching since startup has (and should have) only 1 cache. StartUp should never depend on user or page. So I attempted to create a hook inside ResourceLoader->__construct() that is only ran if wgEnableSpecialUnitTesting is true. And if it is register the modules and add the array_keys of the modules to $wgUnitTestingQUnitSuites.

The problem is that didn't work because ResourceLoader->__construct() runs AFTER SpecialUnitTesting->execute(), so when SpecialUnitTesting->execute() did addModules( wgUnitTestingQUnitSuites ), nothing was added. That's why I work around this by letting extensions add their array keys to wgUnitTestingQUnitSuites in the global scope right away, and the registry separately through the hook. If anybody has a better solution, I would love to change it since I'm not liking this very much.

Problems:
* When I applied this patch and set wgEnableSpecialUnitTesting to true, and visited [[Special:UnitTesting/qunit]], I got :
> Uncaught RangeError: Maximum call stack size exceeded
in my console and none of the test suites was loaded. As a result many other modules are broken too. (such as Exception thrown by user.options: Cannot read property 'options' of undefined).

I suspect $.inArray in resolve() inside mw.loader's scope is doing something wrong.
Comment 4 Krinkle 2011-08-15 08:26:36 UTC
cc'ing Roan. Can you figure out what's going on with $.inArray being recursed ?
Comment 5 Roan Kattouw 2011-08-16 12:23:40 UTC
(In reply to comment #4)
> cc'ing Roan. Can you figure out what's going on with $.inArray being recursed ?
I don't have time for that right now, I'm sorry. It would help if you could obtain a backtrace (it seems Chrome/WebKit doesn't give you one, but Firebug should AFAIK), then use the debugger to try to find out why it's doing infinite recursion.
Comment 6 Krinkle 2011-08-24 17:55:21 UTC
Forget the patch, I've got a better plan.
Comment 7 Krinkle 2011-08-26 20:10:43 UTC
Created attachment 8976 [details]
Better patch

Changes since last patch:

* Renamed infrastructure from "UnitTesting" to "JavaScriptTesting"
* Moved the core test suites into a single module, instead of many separate ones
* Using a hook to let extensions register modules (instead of keeping a global variable, and changing it on-run time, better not to move things into a global variable and pull them out again in another part of the code). General test module structure is a lot simpler and straight forward now. 
* Created loop to add 'qunit.testrunner' as a dependency to all qunit test modules. This is needed because no test should run until qunit and friends are loaded.
Comment 8 Krinkle 2011-08-26 21:11:32 UTC
Oh crap, testrunner should only be added to dependencies of $testModules['qunit'] not to all of $testModules.
Comment 9 Sumana Harihareswara 2011-09-30 16:00:46 UTC
Added the "patch" and "need-review" keywords; Mark hopes to get someone to review the patch soon.
Comment 10 Antoine "hashar" Musso (WMF) 2011-10-20 12:54:32 UTC
I have created a branch named JSTesting from trunk@r100338 with r100339.
Your patch is in that branch since r100340.
Comment 11 Antoine "hashar" Musso (WMF) 2011-10-20 13:58:13 UTC
I added some minor patches (see branch commits).

Is there any reason you are loading the QUnit module directly from the resource loader constructor? It would be better placed in includes/specials/SpecialJavaScriptTest.php constructor. Since those resources are only needed for the dedicated special pages, that sounds like a waste of cpu/memory for all the other requests.

Apart for this point above, seems it could be merged to core.
Comment 12 Krinkle 2011-10-20 23:13:36 UTC
This patch is fairly outdated. The above concerns are also taken care of by me in a newer version.

I've committed it to the branch in r100392.
Comment 13 Krinkle 2012-01-03 21:55:39 UTC
Landed in trunk r107919.
Comment 14 Krinkle 2012-01-03 22:21:36 UTC
Documentation will be available soon here:

https://www.mediawiki.org/wiki/Manual:JavaScript_unit_testing

Note You need to log in before you can comment on or make changes to this bug.


Navigation
Links