2 /*global describe, it, beforeEach, afterEach*/
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');
12 var input = 'var foo=lorem?"bar":"baz";';
13 var output = 'var foo = lorem ? "bar" : "baz";';
16 describe('plugin API', function() {
18 describe('> register plugin', function() {
21 beforeEach(function() {
22 plugin = makePlugin();
23 esformatter.register(plugin);
24 esformatter.format(input);
27 afterEach(function() {
28 esformatter.unregister(plugin);
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(' ');
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');
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');
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]);
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]);
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');
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');
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');
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');
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');
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');
98 describe('> load from node_modules', function() {
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.
107 // "transform" was deprecated on v0.4 but we still have a test for it
108 // to make sure we are backwards compatible.
111 mockery.registerMock('esformatter-foo', plugin1);
112 mockery.registerMock('bar', plugin2);
116 afterEach(function() {
117 mockery.deregisterAll();
121 it('format: should load plugins from node_modules and register it', function() {
122 esformatter.format(input, {
123 plugins: ['esformatter-foo', 'bar']
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);
134 it('transform: should load plugins from node_modules and register it', function() {
135 esformatter.transform(rocambole.parse(input), {
136 plugins: ['esformatter-foo', 'bar']
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);
149 describe('> execute in the right order', function() {
152 beforeEach(function() {
153 plugin = makePlugin();
154 esformatter.register(plugin);
155 esformatter.format('\/\/ foo');
158 afterEach(function() {
159 esformatter.unregister(plugin);
162 it('should call methods in the right order', function() {
163 expect(plugin.callOrder).to.eql([
177 describe('> setOptions', function() {
178 var plugin = testPlugin;
183 beforeEach(function() {
184 esformatter.register(plugin);
185 esformatter.format(input, opts);
188 afterEach(function() {
189 esformatter.unregister(plugin);
192 it('should set default options and allow user and plugin to override them', function() {
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);
205 expect(o.indent.value).to.eql(' ');
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() {
218 fn.args.push.apply(fn.args, arguments);
219 if (this.callOrder) this.callOrder.push(name);
232 function makePlugin() {
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')