获取requirejs与茉莉花一起工作

我首先想说的是,我对RequireJS是新的,对Jasmine是更新的。

我在使用SpecRunner时遇到了一些问题,需要使用JS。 我一直在跟随Uzi Kilon和Ben Nadel的教程(以及其他一些),他们帮助了一些,但我仍然有一些问题。

看来,如果在testing中出现错误(我可以特别想到一个types错误),则将显示spec runner html。 这告诉我,我在JavaScript中有一些问题。 但是,我修复这些错误后,不再显示HTML。 我无法让testing运行者显示。 有人可以find我的代码会导致这个问题的错误吗?

这是我的目录结构

Root |-> lib |-> jasmine |-> lib (contains all of the jasmine lib) |-> spec |-> src |-> jquery (jquery js file) |-> require (require js file) index.html (spec runner) specRunner.js 

这里是SpecRunner(索引)HTML

 <!doctype html> <html lang="en"> <head> <title>Javascript Tests</title> <link rel="stylesheet" href="lib/jasmine/lib/jasmine.css"> <script src="lib/jasmine/lib/jasmine.js"></script> <script src="lib/jasmine/lib/jasmine-html.js"></script> <script src="lib/jquery/jquery.js"></script> <script data-main="specRunner" src="lib/require/require.js"></script> <script> require({ paths: { spec: "lib/jasmine/spec" } }, [ // Pull in all your modules containing unit tests here. "spec/notepadSpec" ], function () { jasmine.getEnv().addReporter(new jasmine.HtmlReporter()); jasmine.getEnv().execute(); }); </script> </head> <body> </body> </html> 

这里是specRunner.js(config)

 require.config({ urlArgs: 'cb=' + Math.random(), paths: { jquery: 'lib/jquery', jasmine: 'lib/jasmine/lib/jasmine', 'jasmine-html': 'lib/jasmine/lib/jasmine-html', spec: 'lib/jasmine/spec/' }, shim: { jasmine: { exports: 'jasmine' }, 'jasmine-html': { deps: ['jasmine'], exports: 'jasmine' } } }); 

这是一个规范:

 require(["../lib/jasmine/src/notepad"], function (notepad) { describe("returns titles", function() { expect(notepad.noteTitles()).toEqual(""); }); }); 

记事本来源:

 define(['lib/jasmine/src/note'], function (note) { var notes = [ new note('pick up the kids', 'dont forget to pick up the kids'), new note('get milk', 'we need two gallons of milk') ]; return { noteTitles: function () { var val; for (var i = 0, ii = notes.length; i < ii; i++) { //alert(notes[i].title); val += notes[i].title + ' '; } return val; } }; }); 

注释来源(JIC):

 define(function (){ var note = function(title, content) { this.title = title; this.content = content; }; return note; }); 

我已经确定,就应用而言,path是正确的。 一旦我得到这个工作,我可以玩configuration的path,所以它不是很难。

我设法得到这个工作与一些试验和错误。 主要的问题是,当你编写规范时,它不是你想要创build的需求,你想要使用define:

原版的:

 require(["/lib/jasmine/src/notepad"], function (notepad) { describe("returns titles", function() { expect(notepad.noteTitles()).toEqual("pick up the kids get milk"); }); }); 

加工:

 define(["lib/jasmine/src/notepad"], function (notepad) { describe("returns titles", function () { it("something", function() { expect(notepad.noteTitles()).toEqual("pick up the kids get milk "); }); }); }); 

在做了一些研究之后,很明显的是,当使用RequireJS时,任何你想使用require()的东西都必须被包装在一个定义中(现在看来我觉得很明显)。 您可以看到,在specRunner.js文件中,在执行testing时使用了一个require(因此需要“定义”规格。

另一个问题是,在创build规范时,describe()和it()是必要的(不仅仅是像我在发布的例子中描述的那样)。

原版的:

 describe("returns titles", function() { expect(notepad.noteTitles()).toEqual("pick up the kids get milk"); }); 

加工:

 describe("returns titles", function () { it("something", function() { expect(notepad.noteTitles()).toEqual("pick up the kids get milk "); }); }); 

我也改变了testing运行的地方,但这是一个重构,并没有改变testing的结果。

再次,这里是文件和更改:

note.js:保持不变

notepad.js:保持不变

index.html的:

 <!doctype html> <html lang="en"> <head> <title>Javascript Tests</title> <link rel="stylesheet" href="lib/jasmine/lib/jasmine.css"> <script data-main="specRunner" src="lib/require/require.js"></script> </head> <body> </body> </html> 

specRunner.js:

 require.config({ urlArgs: 'cb=' + Math.random(), paths: { jquery: 'lib/jquery', 'jasmine': 'lib/jasmine/lib/jasmine', 'jasmine-html': 'lib/jasmine/lib/jasmine-html', spec: 'lib/jasmine/spec/' }, shim: { jasmine: { exports: 'jasmine' }, 'jasmine-html': { deps: ['jasmine'], exports: 'jasmine' } } }); require(['jquery', 'jasmine-html'], function ($, jasmine) { var jasmineEnv = jasmine.getEnv(); jasmineEnv.updateInterval = 1000; var htmlReporter = new jasmine.HtmlReporter(); jasmineEnv.addReporter(htmlReporter); jasmineEnv.specFilter = function (spec) { return htmlReporter.specFilter(spec); }; var specs = []; specs.push('lib/jasmine/spec/notepadSpec'); $(function () { require(specs, function (spec) { jasmineEnv.execute(); }); }); }); 

notepadSpec.js:

 define(["lib/jasmine/src/notepad"], function (notepad) { describe("returns titles", function () { it("something", function() { expect(notepad.noteTitles()).toEqual("pick up the kids get milk"); }); }); }); 

只要添加这个作为你使用Jasmine 2.0独立的人的替代答案。 我相信这也可以为茉莉花1.3工作,但asynchronous语法是不同的和种丑。

这里是我修改的SpecRunner.html文件:

 <!DOCTYPE HTML> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Jasmine Spec Runner v2.0.0</title> <link rel="shortcut icon" type="image/png" href="lib/jasmine-2.0.0/jasmine_favicon.png"> <link rel="stylesheet" type="text/css" href="lib/jasmine-2.0.0/jasmine.css"> <!-- Notice that I just load Jasmine normally --> <script type="text/javascript" src="lib/jasmine-2.0.0/jasmine.js"></script> <script type="text/javascript" src="lib/jasmine-2.0.0/jasmine-html.js"></script> <script type="text/javascript" src="lib/jasmine-2.0.0/boot.js"></script> <!-- Here we load require.js but we do not use data-main. Instead we will load the the specs separately. In short we need to load the spec files synchronously for this to work. --> <script type="text/javascript" src="js/vendor/require.min.js"></script> <!-- I put my require js config inline for simplicity --> <script type="text/javascript"> require.config({ baseUrl: 'js', shim: { 'underscore': { exports: '_' }, 'react': { exports: 'React' } }, paths: { jquery: 'vendor/jquery.min', underscore: 'vendor/underscore.min', react: 'vendor/react.min' } }); </script> <!-- I put my spec files here --> <script type="text/javascript" src="spec/a-spec.js"></script> <script type="text/javascript" src="spec/some-other-spec.js"></script> </head> <body> </body> </html> 

现在这是一个示例spec文件:

 describe("Circular List Operation", function() { // The CircularList object needs to be loaded by RequireJs // before we can use it. var CircularList; // require.js loads scripts asynchronously, so we can use // Jasmine 2.0's async support. Basically it entails calling // the done function once require js finishes loading our asset. // // Here I put the require in the beforeEach function to make sure the // Circular list object is loaded each time. beforeEach(function(done) { require(['lib/util'], function(util) { CircularList = util.CircularList; done(); }); }); it("should know if list is empty", function() { var list = new CircularList(); expect(list.isEmpty()).toBe(true); }); // We can also use the async feature on the it function // to require assets for a specific test. it("should know if list is not empty", function(done) { require(['lib/entity'], function(entity) { var list = new CircularList([new entity.Cat()]); expect(list.isEmpty()).toBe(false); done(); }); }); }); 

以下是Jasmine 2.0文档中的asynchronous支持部分的链接: http : //jasmine.github.io/2.0/introduction.html#section-Asynchronous_Support

Jasmine 2.0 standalone的另一个选项是创build一个boot.js文件,并在所有的AMD模块加载完毕后设置它来运行你的testing。

在我们的例子中编写testing的理想最终用户案例是不必一次性列出所有的spec文件或依赖关系,只需要将你的* spec文件声明为具有依赖关系的AMD模块。

示例理想spec: spec / javascript / sampleController_spec.js

 require(['app/controllers/SampleController'], function(SampleController) { describe('SampleController', function() { it('should construct an instance of a SampleController', function() { expect(new SampleController() instanceof SampleController).toBeTruthy(); }); }); }); 

理想情况下,加载依赖项并运行规范的背景行为对于任何想要编写testing的项目来说都是完全不透明的,除了用AMD依赖关系创build一个* spec.js文件外,他们不需要做任何事情。

为了得到这一切,我们创build了一个引导文件,并configuration了Jasmine来使用它( http://jasmine.github.io/2.0/boot.html ),并添加了一些魔术环绕要求暂时延迟运行testing,直到我们有我们的deps加载:

我们的boot.js “执行”部分:

 /** * ## Execution * * Replace the browser window's `onload`, ensure it's called, and then run all of the loaded specs. This includes initializing the `HtmlReporter` instance and then executing the loaded Jasmine environment. All of this will happen after all of the specs are loaded. */ var currentWindowOnload = window.onload; // Stack of AMD spec definitions var specDefinitions = []; // Store a ref to the current require function window.oldRequire = require; // Shim in our Jasmine spec require helper, which will queue up all of the definitions to be loaded in later. require = function(deps, specCallback){ //push any module defined using require([deps], callback) onto the specDefinitions stack. specDefinitions.push({ 'deps' : deps, 'specCallback' : specCallback }); }; // window.onload = function() { // Restore original require functionality window.require = oldRequire; // Keep a ref to Jasmine context for when we execute later var context = this, requireCalls = 0, // counter of (successful) require callbacks specCount = specDefinitions.length; // # of AMD specs we're expecting to load // func to execute the AMD callbacks for our test specs once requireJS has finished loading our deps function execSpecDefinitions() { //exec the callback of our AMD defined test spec, passing in the returned modules. this.specCallback.apply(context, arguments); requireCalls++; // inc our counter for successful AMD callbacks. if(requireCalls === specCount){ //do the normal Jamsine HTML reporter initialization htmlReporter.initialize.call(context); //execute our Jasmine Env, now that all of our dependencies are loaded and our specs are defined. env.execute.call(context); } } var specDefinition; // iterate through all of our AMD specs and call require with our spec execution callback for (var i = specDefinitions.length - 1; i >= 0; i--) { require(specDefinitions[i].deps, execSpecDefinitions.bind(specDefinitions[i])); } //keep original onload in case we set one in the HTML if (currentWindowOnload) { currentWindowOnload(); } }; 

我们基本上把我们的AMD语法规范保存在一个堆栈中,popup它们,需要模块,使用我们的断言执行callback,然后一旦加载完成,就运行Jasmine。

这个设置允许我们等待,直到我们各个testing所需的所有AMD模块都被加载,并且不会通过创build全局variables来破坏AMD模式。 有一个小问题,我们暂时覆盖require,只使用require(我们的`src_dir:jasmine.yml中是空的)加载我们的应用程序代码,但是总体目标是减less编写spec的开销。

您可以使用与之前的filter结合使用来testingasynchronouscallback:

  beforeEach(function(done) { return require(['dist/sem-campaign'], function(campaign) { module = campaign; return done(); }); }); 

这是我如何在HTML中使用AMD / requirejs运行茉莉花规范的所有我的来源和规格。

这是我的index.html文件加载茉莉花,然后我的'unit testing启动器':

 <html><head><title>unit test</title><head> <link rel="shortcut icon" type="image/png" href="/jasmine/lib/jasmine-2.1.3/jasmine_favicon.png"> <link rel="stylesheet" href="/jasmine/lib/jasmine-2.1.3/jasmine.css"> <script src="/jasmine/lib/jasmine-2.1.3/jasmine.js"></script> <script src="/jasmine/lib/jasmine-2.1.3/jasmine-html.js"></script> <script src="/jasmine/lib/jasmine-2.1.3/boot.js"></script> </head><body> <script data-main="javascript/UnitTestStarter.js" src="javascript/require.js"></script> </body></html> 

然后我的UnitTestStarter.js是这样的:

 require.config({ "paths": { .... }); require(['MySpec.js'], function() { jasmine.getEnv().execute(); })