d90d06cb8e8d8a15943f6facb6534309f8cdf7b4
[platform/framework/web/crosswalk-tizen.git] /
1 //jshint node:true
2 /*global describe, it, beforeEach, afterEach*/
3 'use strict';
4
5 var expect = require('chai').expect;
6 var mockery = require('mockery');
7 var esformatter = require('../lib/esformatter');
8 var esformatterOptions = require('../lib/options');
9 var rocambole = require('rocambole');
10 var testPlugin = require('esformatter-test-plugin');
11
12 var input = 'var foo=lorem?"bar":"baz";';
13 var output = 'var foo = lorem ? "bar" : "baz";';
14
15
16 describe('plugin API', function() {
17
18   describe('> register plugin', function() {
19     var plugin;
20
21     beforeEach(function() {
22       plugin = makePlugin();
23       esformatter.register(plugin);
24       esformatter.format(input);
25     });
26
27     afterEach(function() {
28       esformatter.unregister(plugin);
29     });
30
31     it('should call setOptions and not override user set options', function() {
32       expect(plugin.setOptions.count).to.eql(1);
33       expect(plugin.setOptions.args[0].indent.value).to.eql('  ');
34     });
35
36     it('should call tokenBefore for each token', function() {
37       expect(plugin.tokenBefore.count).to.eql(10);
38       expect(plugin.tokenBefore.args.length).to.eql(10);
39       expect(plugin.tokenBefore.args[0].value).to.eql('var');
40       expect(plugin.tokenBefore.args[4].value).to.eql('lorem');
41     });
42
43     it('should call tokenAfter for each token', function() {
44       expect(plugin.tokenAfter.count).to.eql(16);
45       expect(plugin.tokenAfter.args.length).to.eql(16);
46       expect(plugin.tokenAfter.args[0].value).to.eql('var');
47       expect(plugin.tokenAfter.args[6].value).to.eql('lorem');
48     });
49
50     it('should call stringBefore at the begining of process', function() {
51       expect(plugin.stringBefore.count).to.eql(1);
52       expect(plugin.stringBefore.args).to.eql([input]);
53     });
54
55     it('should call stringAfter at end of process', function() {
56       expect(plugin.stringAfter.count).to.eql(1);
57       expect(plugin.stringAfter.args).to.eql([output]);
58     });
59
60     it('should call nodeBefore for each node', function() {
61       expect(plugin.nodeBefore.count).to.eql(8);
62       expect(plugin.nodeBefore.args[3].toString()).to.eql('foo');
63     });
64
65     it('should call nodeAfter for each node', function() {
66       expect(plugin.nodeAfter.count).to.eql(8);
67       expect(plugin.nodeAfter.args[3].toString()).to.eql('foo');
68     });
69
70     it('should call transformBefore once', function() {
71       expect(plugin.transformBefore.count).to.eql(1);
72       expect(plugin.transformBefore.args[0].type).to.eql('Program');
73     });
74
75     it('should call transformAfter once', function() {
76       expect(plugin.transformAfter.count).to.eql(1);
77       expect(plugin.transformAfter.args[0].type).to.eql('Program');
78     });
79
80     describe('> multiple calls', function() {
81       it('should call plugin once per transform call', function() {
82         esformatter.format(input);
83         expect(plugin.transformAfter.count).to.eql(2);
84         expect(plugin.transformAfter.args[1].type).to.eql('Program');
85
86       });
87
88       it('should not execute plugin if unregistered', function() {
89         esformatter.unregisterAll();
90         esformatter.format(input);
91         expect(plugin.transformAfter.count).to.eql(1);
92         expect(plugin.transformAfter.args[0].type).to.eql('Program');
93       });
94     });
95
96   });
97
98   describe('> load from node_modules', function() {
99     var plugin1;
100     var plugin2;
101
102     beforeEach(function() {
103       plugin1 = makePlugin();
104       // this should be enough to ensure plugin methods are optional and that
105       // multiple plugins are executed in a row.
106       plugin2 = {
107         // "transform" was deprecated on v0.4 but we still have a test for it
108         // to make sure we are backwards compatible.
109         transform: stub()
110       };
111       mockery.registerMock('esformatter-foo', plugin1);
112       mockery.registerMock('bar', plugin2);
113       mockery.enable();
114     });
115
116     afterEach(function() {
117       mockery.deregisterAll();
118       mockery.disable();
119     });
120
121     it('format: should load plugins from node_modules and register it', function() {
122       esformatter.format(input, {
123         plugins: ['esformatter-foo', 'bar']
124       });
125
126       expect(plugin1.stringBefore.count).to.eql(1);
127       expect(plugin1.transformBefore.count).to.eql(1);
128       expect(plugin1.transformAfter.count).to.eql(1);
129       expect(plugin1.nodeAfter.count).to.eql(8);
130       expect(plugin2.transform.count).to.eql(1);
131       expect(plugin1.stringAfter.count).to.eql(1);
132     });
133
134     it('transform: should load plugins from node_modules and register it', function() {
135       esformatter.transform(rocambole.parse(input), {
136         plugins: ['esformatter-foo', 'bar']
137       });
138
139       expect(plugin1.stringBefore.count).to.eql(0);
140       expect(plugin1.transformBefore.count).to.eql(1);
141       expect(plugin1.transformAfter.count).to.eql(1);
142       expect(plugin1.nodeAfter.count).to.eql(8);
143       expect(plugin2.transform.count).to.eql(1);
144       expect(plugin1.stringAfter.count).to.eql(0);
145     });
146
147   });
148
149   describe('> execute in the right order', function() {
150     var plugin;
151
152     beforeEach(function() {
153       plugin = makePlugin();
154       esformatter.register(plugin);
155       esformatter.format('\/\/ foo');
156     });
157
158     afterEach(function() {
159       esformatter.unregister(plugin);
160     });
161
162     it('should call methods in the right order', function() {
163       expect(plugin.callOrder).to.eql([
164         'setOptions',
165         'stringBefore',
166         'transformBefore',
167         'tokenBefore',
168         'nodeBefore',
169         'nodeAfter',
170         'tokenAfter',
171         'transformAfter',
172         'stringAfter'
173       ]);
174     });
175   });
176
177   describe('> setOptions', function() {
178     var plugin = testPlugin;
179     var opts = {
180       foo: 'ipsum'
181     };
182
183     beforeEach(function() {
184       esformatter.register(plugin);
185       esformatter.format(input, opts);
186     });
187
188     afterEach(function() {
189       esformatter.unregister(plugin);
190     });
191
192     it('should set default options and allow user and plugin to override them', function() {
193       var o = plugin.opts;
194       // it clones the user proveid options object to avoid undesired side effects
195       expect(o).not.to.eql(opts);
196       // it should pass options object by reference
197       expect(o).to.eql(esformatterOptions.get());
198       // user should be able to override options
199       expect(o.foo).to.eql('ipsum');
200       // plugin should be able to create a new value
201       expect(o.bar).to.eql(123);
202       // plugin should be able to override a value
203       expect(o.indent.ArrayExpression).to.eql(3);
204       // default value
205       expect(o.indent.value).to.eql('  ');
206     });
207
208   });
209
210 });
211
212
213 // extremely basic stub method, I know I could have used something more
214 // complex like sinon, but this is good enough for now
215 function stub(name, isIdentity) {
216   var fn = function() {
217     fn.count += 1;
218     fn.args.push.apply(fn.args, arguments);
219     if (this.callOrder) this.callOrder.push(name);
220     if (isIdentity) {
221       return arguments[0];
222     }
223   };
224
225   fn.count = 0;
226   fn.args = [];
227
228   return fn;
229 }
230
231
232 function makePlugin() {
233   return {
234     callOrder: [],
235     setOptions: stub('setOptions'),
236     stringBefore: stub('stringBefore', true),
237     stringAfter: stub('stringAfter', true),
238     tokenBefore: stub('tokenBefore'),
239     tokenAfter: stub('tokenAfter'),
240     nodeBefore: stub('nodeBefore'),
241     nodeAfter: stub('nodeAfter'),
242     transformAfter: stub('transformAfter'),
243     transformBefore: stub('transformBefore')
244   };
245 }