wagn 1.14.7 → 1.14.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) hide show
  1. checksums.yaml +4 -4
  2. data/JASMINE_RAILS_TEST.md +16 -0
  3. data/VERSION +1 -1
  4. data/db/bootstrap/card_actions.yml +501 -480
  5. data/db/bootstrap/card_acts.yml +1 -1
  6. data/db/bootstrap/card_changes.yml +1815 -1752
  7. data/db/bootstrap/cards.yml +1500 -1443
  8. data/db/migrate/20141121172918_rename_card_migration_table.rb +8 -1
  9. data/lib/card/chunk.rb +0 -1
  10. data/lib/card/content.rb +1 -1
  11. data/lib/card/format.rb +6 -4
  12. data/lib/card/generators/card_migration/card_migration_generator.rb +1 -2
  13. data/lib/card/loader.rb +4 -0
  14. data/lib/card/set.rb +21 -7
  15. data/lib/card/set_pattern.rb +38 -5
  16. data/lib/wagn.rb +3 -3
  17. data/lib/wagn/core_migration.rb +1 -15
  18. data/lib/wagn/generators/wagn/templates/Rakefile +0 -1
  19. data/lib/wagn/log.rb +297 -94
  20. data/lib/wagn/migration.rb +53 -24
  21. data/lib/wagn/tasks/wagn.rake +17 -19
  22. data/mod/01_core/set/all/collection.rb +1 -1
  23. data/mod/01_core/set/all/content.rb +5 -2
  24. data/mod/01_core/set/all/fetch.rb +35 -35
  25. data/mod/01_core/set/all/trash.rb +3 -3
  26. data/mod/01_core/set/all/type.rb +7 -4
  27. data/mod/01_core/spec/set/all/tracked_attributes_spec.rb +1 -1
  28. data/mod/01_core/spec/set/all/trash_spec.rb +19 -0
  29. data/mod/02_basic_types/spec/set/type/pointer_spec.rb +13 -3
  30. data/mod/03_machines/set/type/coffee_script.rb +5 -3
  31. data/mod/03_machines/set/type/css.rb +4 -2
  32. data/mod/03_machines/set/type/java_script.rb +5 -4
  33. data/mod/04_settings/set/right/style.rb +3 -2
  34. data/mod/05_email/format/email_text_format.rb +4 -0
  35. data/mod/05_email/set/all/email_text.rb +1 -2
  36. data/mod/05_email/set/right/bcc.rb +8 -4
  37. data/mod/05_email/set/type/email_template.rb +20 -20
  38. data/mod/05_standard/set/all/attach.rb +0 -1
  39. data/mod/05_standard/set/type/basic.rb +3 -1
  40. data/mod/05_standard/set/type/html.rb +7 -5
  41. data/mod/05_standard/spec/set/type/email_template_spec.rb +166 -99
  42. data/public/assets/ace/ext-searchbox.js +409 -0
  43. data/spec/lib/card/set_pattern_spec.rb +18 -1
  44. data/spec/lib/wagn/log_spec.rb +217 -56
  45. data/test/fixtures/card_actions.yml +945 -924
  46. data/test/fixtures/card_acts.yml +101 -101
  47. data/test/fixtures/card_changes.yml +3764 -3701
  48. data/test/fixtures/cards.yml +2012 -1955
  49. metadata +4 -2
@@ -0,0 +1,409 @@
1
+ define("ace/ext/searchbox",["require","exports","module","ace/lib/dom","ace/lib/lang","ace/lib/event","ace/keyboard/hash_handler","ace/lib/keys"], function(require, exports, module) {
2
+ "use strict";
3
+
4
+ var dom = require("../lib/dom");
5
+ var lang = require("../lib/lang");
6
+ var event = require("../lib/event");
7
+ var searchboxCss = "\
8
+ .ace_search {\
9
+ background-color: #ddd;\
10
+ border: 1px solid #cbcbcb;\
11
+ border-top: 0 none;\
12
+ max-width: 325px;\
13
+ overflow: hidden;\
14
+ margin: 0;\
15
+ padding: 4px;\
16
+ padding-right: 6px;\
17
+ padding-bottom: 0;\
18
+ position: absolute;\
19
+ top: 0px;\
20
+ z-index: 99;\
21
+ white-space: normal;\
22
+ }\
23
+ .ace_search.left {\
24
+ border-left: 0 none;\
25
+ border-radius: 0px 0px 5px 0px;\
26
+ left: 0;\
27
+ }\
28
+ .ace_search.right {\
29
+ border-radius: 0px 0px 0px 5px;\
30
+ border-right: 0 none;\
31
+ right: 0;\
32
+ }\
33
+ .ace_search_form, .ace_replace_form {\
34
+ border-radius: 3px;\
35
+ border: 1px solid #cbcbcb;\
36
+ float: left;\
37
+ margin-bottom: 4px;\
38
+ overflow: hidden;\
39
+ }\
40
+ .ace_search_form.ace_nomatch {\
41
+ outline: 1px solid red;\
42
+ }\
43
+ .ace_search_field {\
44
+ background-color: white;\
45
+ border-right: 1px solid #cbcbcb;\
46
+ border: 0 none;\
47
+ -webkit-box-sizing: border-box;\
48
+ -moz-box-sizing: border-box;\
49
+ box-sizing: border-box;\
50
+ float: left;\
51
+ height: 22px;\
52
+ outline: 0;\
53
+ padding: 0 7px;\
54
+ width: 214px;\
55
+ margin: 0;\
56
+ }\
57
+ .ace_searchbtn,\
58
+ .ace_replacebtn {\
59
+ background: #fff;\
60
+ border: 0 none;\
61
+ border-left: 1px solid #dcdcdc;\
62
+ cursor: pointer;\
63
+ float: left;\
64
+ height: 22px;\
65
+ margin: 0;\
66
+ padding: 0;\
67
+ position: relative;\
68
+ }\
69
+ .ace_searchbtn:last-child,\
70
+ .ace_replacebtn:last-child {\
71
+ border-top-right-radius: 3px;\
72
+ border-bottom-right-radius: 3px;\
73
+ }\
74
+ .ace_searchbtn:disabled {\
75
+ background: none;\
76
+ cursor: default;\
77
+ }\
78
+ .ace_searchbtn {\
79
+ background-position: 50% 50%;\
80
+ background-repeat: no-repeat;\
81
+ width: 27px;\
82
+ }\
83
+ .ace_searchbtn.prev {\
84
+ background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAFCAYAAAB4ka1VAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAADFJREFUeNpiSU1NZUAC/6E0I0yACYskCpsJiySKIiY0SUZk40FyTEgCjGgKwTRAgAEAQJUIPCE+qfkAAAAASUVORK5CYII=); \
85
+ }\
86
+ .ace_searchbtn.next {\
87
+ background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAFCAYAAAB4ka1VAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAADRJREFUeNpiTE1NZQCC/0DMyIAKwGJMUAYDEo3M/s+EpvM/mkKwCQxYjIeLMaELoLMBAgwAU7UJObTKsvAAAAAASUVORK5CYII=); \
88
+ }\
89
+ .ace_searchbtn_close {\
90
+ background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAcCAYAAABRVo5BAAAAZ0lEQVR42u2SUQrAMAhDvazn8OjZBilCkYVVxiis8H4CT0VrAJb4WHT3C5xU2a2IQZXJjiQIRMdkEoJ5Q2yMqpfDIo+XY4k6h+YXOyKqTIj5REaxloNAd0xiKmAtsTHqW8sR2W5f7gCu5nWFUpVjZwAAAABJRU5ErkJggg==) no-repeat 50% 0;\
91
+ border-radius: 50%;\
92
+ border: 0 none;\
93
+ color: #656565;\
94
+ cursor: pointer;\
95
+ float: right;\
96
+ font: 16px/16px Arial;\
97
+ height: 14px;\
98
+ margin: 5px 1px 9px 5px;\
99
+ padding: 0;\
100
+ text-align: center;\
101
+ width: 14px;\
102
+ }\
103
+ .ace_searchbtn_close:hover {\
104
+ background-color: #656565;\
105
+ background-position: 50% 100%;\
106
+ color: white;\
107
+ }\
108
+ .ace_replacebtn.prev {\
109
+ width: 54px\
110
+ }\
111
+ .ace_replacebtn.next {\
112
+ width: 27px\
113
+ }\
114
+ .ace_button {\
115
+ margin-left: 2px;\
116
+ cursor: pointer;\
117
+ -webkit-user-select: none;\
118
+ -moz-user-select: none;\
119
+ -o-user-select: none;\
120
+ -ms-user-select: none;\
121
+ user-select: none;\
122
+ overflow: hidden;\
123
+ opacity: 0.7;\
124
+ border: 1px solid rgba(100,100,100,0.23);\
125
+ padding: 1px;\
126
+ -moz-box-sizing: border-box;\
127
+ box-sizing: border-box;\
128
+ color: black;\
129
+ }\
130
+ .ace_button:hover {\
131
+ background-color: #eee;\
132
+ opacity:1;\
133
+ }\
134
+ .ace_button:active {\
135
+ background-color: #ddd;\
136
+ }\
137
+ .ace_button.checked {\
138
+ border-color: #3399ff;\
139
+ opacity:1;\
140
+ }\
141
+ .ace_search_options{\
142
+ margin-bottom: 3px;\
143
+ text-align: right;\
144
+ -webkit-user-select: none;\
145
+ -moz-user-select: none;\
146
+ -o-user-select: none;\
147
+ -ms-user-select: none;\
148
+ user-select: none;\
149
+ }";
150
+ var HashHandler = require("../keyboard/hash_handler").HashHandler;
151
+ var keyUtil = require("../lib/keys");
152
+
153
+ dom.importCssString(searchboxCss, "ace_searchbox");
154
+
155
+ var html = '<div class="ace_search right">\
156
+ <button type="button" action="hide" class="ace_searchbtn_close"></button>\
157
+ <div class="ace_search_form">\
158
+ <input class="ace_search_field" placeholder="Search for" spellcheck="false"></input>\
159
+ <button type="button" action="findNext" class="ace_searchbtn next"></button>\
160
+ <button type="button" action="findPrev" class="ace_searchbtn prev"></button>\
161
+ <button type="button" action="findAll" class="ace_searchbtn" title="Alt-Enter">All</button>\
162
+ </div>\
163
+ <div class="ace_replace_form">\
164
+ <input class="ace_search_field" placeholder="Replace with" spellcheck="false"></input>\
165
+ <button type="button" action="replaceAndFindNext" class="ace_replacebtn">Replace</button>\
166
+ <button type="button" action="replaceAll" class="ace_replacebtn">All</button>\
167
+ </div>\
168
+ <div class="ace_search_options">\
169
+ <span action="toggleRegexpMode" class="ace_button" title="RegExp Search">.*</span>\
170
+ <span action="toggleCaseSensitive" class="ace_button" title="CaseSensitive Search">Aa</span>\
171
+ <span action="toggleWholeWords" class="ace_button" title="Whole Word Search">\\b</span>\
172
+ </div>\
173
+ </div>'.replace(/>\s+/g, ">");
174
+
175
+ var SearchBox = function(editor, range, showReplaceForm) {
176
+ var div = dom.createElement("div");
177
+ div.innerHTML = html;
178
+ this.element = div.firstChild;
179
+
180
+ this.$init();
181
+ this.setEditor(editor);
182
+ };
183
+
184
+ (function() {
185
+ this.setEditor = function(editor) {
186
+ editor.searchBox = this;
187
+ editor.container.appendChild(this.element);
188
+ this.editor = editor;
189
+ };
190
+
191
+ this.$initElements = function(sb) {
192
+ this.searchBox = sb.querySelector(".ace_search_form");
193
+ this.replaceBox = sb.querySelector(".ace_replace_form");
194
+ this.searchOptions = sb.querySelector(".ace_search_options");
195
+ this.regExpOption = sb.querySelector("[action=toggleRegexpMode]");
196
+ this.caseSensitiveOption = sb.querySelector("[action=toggleCaseSensitive]");
197
+ this.wholeWordOption = sb.querySelector("[action=toggleWholeWords]");
198
+ this.searchInput = this.searchBox.querySelector(".ace_search_field");
199
+ this.replaceInput = this.replaceBox.querySelector(".ace_search_field");
200
+ };
201
+
202
+ this.$init = function() {
203
+ var sb = this.element;
204
+
205
+ this.$initElements(sb);
206
+
207
+ var _this = this;
208
+ event.addListener(sb, "mousedown", function(e) {
209
+ setTimeout(function(){
210
+ _this.activeInput.focus();
211
+ }, 0);
212
+ event.stopPropagation(e);
213
+ });
214
+ event.addListener(sb, "click", function(e) {
215
+ var t = e.target || e.srcElement;
216
+ var action = t.getAttribute("action");
217
+ if (action && _this[action])
218
+ _this[action]();
219
+ else if (_this.$searchBarKb.commands[action])
220
+ _this.$searchBarKb.commands[action].exec(_this);
221
+ event.stopPropagation(e);
222
+ });
223
+
224
+ event.addCommandKeyListener(sb, function(e, hashId, keyCode) {
225
+ var keyString = keyUtil.keyCodeToString(keyCode);
226
+ var command = _this.$searchBarKb.findKeyCommand(hashId, keyString);
227
+ if (command && command.exec) {
228
+ command.exec(_this);
229
+ event.stopEvent(e);
230
+ }
231
+ });
232
+
233
+ this.$onChange = lang.delayedCall(function() {
234
+ _this.find(false, false);
235
+ });
236
+
237
+ event.addListener(this.searchInput, "input", function() {
238
+ _this.$onChange.schedule(20);
239
+ });
240
+ event.addListener(this.searchInput, "focus", function() {
241
+ _this.activeInput = _this.searchInput;
242
+ _this.searchInput.value && _this.highlight();
243
+ });
244
+ event.addListener(this.replaceInput, "focus", function() {
245
+ _this.activeInput = _this.replaceInput;
246
+ _this.searchInput.value && _this.highlight();
247
+ });
248
+ };
249
+ this.$closeSearchBarKb = new HashHandler([{
250
+ bindKey: "Esc",
251
+ name: "closeSearchBar",
252
+ exec: function(editor) {
253
+ editor.searchBox.hide();
254
+ }
255
+ }]);
256
+ this.$searchBarKb = new HashHandler();
257
+ this.$searchBarKb.bindKeys({
258
+ "Ctrl-f|Command-f|Ctrl-H|Command-Option-F": function(sb) {
259
+ var isReplace = sb.isReplace = !sb.isReplace;
260
+ sb.replaceBox.style.display = isReplace ? "" : "none";
261
+ sb[isReplace ? "replaceInput" : "searchInput"].focus();
262
+ },
263
+ "Ctrl-G|Command-G": function(sb) {
264
+ sb.findNext();
265
+ },
266
+ "Ctrl-Shift-G|Command-Shift-G": function(sb) {
267
+ sb.findPrev();
268
+ },
269
+ "esc": function(sb) {
270
+ setTimeout(function() { sb.hide();});
271
+ },
272
+ "Return": function(sb) {
273
+ if (sb.activeInput == sb.replaceInput)
274
+ sb.replace();
275
+ sb.findNext();
276
+ },
277
+ "Shift-Return": function(sb) {
278
+ if (sb.activeInput == sb.replaceInput)
279
+ sb.replace();
280
+ sb.findPrev();
281
+ },
282
+ "Alt-Return": function(sb) {
283
+ if (sb.activeInput == sb.replaceInput)
284
+ sb.replaceAll();
285
+ sb.findAll();
286
+ },
287
+ "Tab": function(sb) {
288
+ (sb.activeInput == sb.replaceInput ? sb.searchInput : sb.replaceInput).focus();
289
+ }
290
+ });
291
+
292
+ this.$searchBarKb.addCommands([{
293
+ name: "toggleRegexpMode",
294
+ bindKey: {win: "Alt-R|Alt-/", mac: "Ctrl-Alt-R|Ctrl-Alt-/"},
295
+ exec: function(sb) {
296
+ sb.regExpOption.checked = !sb.regExpOption.checked;
297
+ sb.$syncOptions();
298
+ }
299
+ }, {
300
+ name: "toggleCaseSensitive",
301
+ bindKey: {win: "Alt-C|Alt-I", mac: "Ctrl-Alt-R|Ctrl-Alt-I"},
302
+ exec: function(sb) {
303
+ sb.caseSensitiveOption.checked = !sb.caseSensitiveOption.checked;
304
+ sb.$syncOptions();
305
+ }
306
+ }, {
307
+ name: "toggleWholeWords",
308
+ bindKey: {win: "Alt-B|Alt-W", mac: "Ctrl-Alt-B|Ctrl-Alt-W"},
309
+ exec: function(sb) {
310
+ sb.wholeWordOption.checked = !sb.wholeWordOption.checked;
311
+ sb.$syncOptions();
312
+ }
313
+ }]);
314
+
315
+ this.$syncOptions = function() {
316
+ dom.setCssClass(this.regExpOption, "checked", this.regExpOption.checked);
317
+ dom.setCssClass(this.wholeWordOption, "checked", this.wholeWordOption.checked);
318
+ dom.setCssClass(this.caseSensitiveOption, "checked", this.caseSensitiveOption.checked);
319
+ this.find(false, false);
320
+ };
321
+
322
+ this.highlight = function(re) {
323
+ this.editor.session.highlight(re || this.editor.$search.$options.re);
324
+ this.editor.renderer.updateBackMarkers()
325
+ };
326
+ this.find = function(skipCurrent, backwards) {
327
+ var range = this.editor.find(this.searchInput.value, {
328
+ skipCurrent: skipCurrent,
329
+ backwards: backwards,
330
+ wrap: true,
331
+ regExp: this.regExpOption.checked,
332
+ caseSensitive: this.caseSensitiveOption.checked,
333
+ wholeWord: this.wholeWordOption.checked
334
+ });
335
+ var noMatch = !range && this.searchInput.value;
336
+ dom.setCssClass(this.searchBox, "ace_nomatch", noMatch);
337
+ this.editor._emit("findSearchBox", { match: !noMatch });
338
+ this.highlight();
339
+ };
340
+ this.findNext = function() {
341
+ this.find(true, false);
342
+ };
343
+ this.findPrev = function() {
344
+ this.find(true, true);
345
+ };
346
+ this.findAll = function(){
347
+ var range = this.editor.findAll(this.searchInput.value, {
348
+ regExp: this.regExpOption.checked,
349
+ caseSensitive: this.caseSensitiveOption.checked,
350
+ wholeWord: this.wholeWordOption.checked
351
+ });
352
+ var noMatch = !range && this.searchInput.value;
353
+ dom.setCssClass(this.searchBox, "ace_nomatch", noMatch);
354
+ this.editor._emit("findSearchBox", { match: !noMatch });
355
+ this.highlight();
356
+ this.hide();
357
+ };
358
+ this.replace = function() {
359
+ if (!this.editor.getReadOnly())
360
+ this.editor.replace(this.replaceInput.value);
361
+ };
362
+ this.replaceAndFindNext = function() {
363
+ if (!this.editor.getReadOnly()) {
364
+ this.editor.replace(this.replaceInput.value);
365
+ this.findNext()
366
+ }
367
+ };
368
+ this.replaceAll = function() {
369
+ if (!this.editor.getReadOnly())
370
+ this.editor.replaceAll(this.replaceInput.value);
371
+ };
372
+
373
+ this.hide = function() {
374
+ this.element.style.display = "none";
375
+ this.editor.keyBinding.removeKeyboardHandler(this.$closeSearchBarKb);
376
+ this.editor.focus();
377
+ };
378
+ this.show = function(value, isReplace) {
379
+ this.element.style.display = "";
380
+ this.replaceBox.style.display = isReplace ? "" : "none";
381
+
382
+ this.isReplace = isReplace;
383
+
384
+ if (value)
385
+ this.searchInput.value = value;
386
+ this.searchInput.focus();
387
+ this.searchInput.select();
388
+
389
+ this.editor.keyBinding.addKeyboardHandler(this.$closeSearchBarKb);
390
+ };
391
+
392
+ this.isFocused = function() {
393
+ var el = document.activeElement;
394
+ return el == this.searchInput || el == this.replaceInput;
395
+ }
396
+ }).call(SearchBox.prototype);
397
+
398
+ exports.SearchBox = SearchBox;
399
+
400
+ exports.Search = function(editor, isReplace) {
401
+ var sb = editor.searchBox || new SearchBox(editor);
402
+ sb.show(editor.session.getTextRange(), isReplace);
403
+ };
404
+
405
+ });
406
+ (function() {
407
+ window.require(["ace/ext/searchbox"], function() {});
408
+ })();
409
+
@@ -26,6 +26,23 @@ describe Card::TypeSet do
26
26
  it_generates :name => "Book+*type", :from => Card.new( :type => "Book" )
27
27
  end
28
28
 
29
+ describe Card::TypeSet do
30
+ before :each do
31
+ Card::Auth.as_bot do
32
+ @mylist = Card.create! :name=>'MyList', :type_id=>Card::CardtypeID
33
+ Card.create :name=>'MyList+*type+*default', :type_id=>Card::PointerID
34
+ end
35
+ @mylist_card = Card.create :name=>'ip', :type_id=>@mylist.id
36
+ end
37
+ # similar tests for an inherited type of Pointer
38
+ it 'has inherited set module' do
39
+ expect(@mylist_card.set_format_modules(Card::HtmlFormat)).to include(Card::Set::Type::Pointer::HtmlFormat)
40
+ expect(@mylist_card.set_format_modules(Card::CssFormat)).to include(Card::Set::Type::Pointer::CssFormat)
41
+ expect(@mylist_card.set_format_modules(Card::JsFormat)).to include(Card::Set::Type::Pointer::JsFormat)
42
+ expect(@mylist_card.set_modules).to include(Card::Set::Type::Pointer)
43
+ end
44
+ end
45
+
29
46
  describe Card::AllPlusSet do
30
47
  it_generates :name => "*all plus", :from => Card.new( :name => "Book+author" )
31
48
  end
@@ -36,4 +53,4 @@ end
36
53
 
37
54
  describe Card::TypePlusRightSet do
38
55
  it_generates :name => "Book+author+*type plus right", :from => Card.new( :name=>"Iliad+author" )
39
- end
56
+ end
@@ -1,3 +1,4 @@
1
+
1
2
  describe Wagn::Log::Request do
2
3
  before do
3
4
  controller = double()
@@ -19,83 +20,243 @@ describe Wagn::Log::Request do
19
20
  it 'creates csv file' do
20
21
  expect(File.exist? Wagn::Log::Request.path).to be_truthy
21
22
  end
22
-
23
+
23
24
  describe 'log file' do
24
25
  subject { File.read Wagn::Log::Request.path }
25
-
26
+
26
27
  it { is_expected.to include 'REMOTE_ADDR' }
27
28
  it { is_expected.to include 'REQUEST_METHOD' }
28
29
  it { is_expected.to include 'view' }
29
30
  it { is_expected.to include 'status' }
30
31
  it { is_expected.to include 'cardname' }
31
- end
32
+ end
32
33
  end
33
34
 
34
35
 
35
36
  describe Wagn::Log::Performance do
36
- def test_log
37
- Wagn::Log::Performance.start :method=>'test'
38
- yield
39
- Wagn::Log::Performance.stop
37
+ def log_method opts
38
+ Wagn::Log::Performance.load_config(:methods=>opts)
40
39
  end
41
-
42
- it 'logs searches if enabled' do
43
- Wagn.config.performance_logger = { :methods=>[:search]}
44
- expect(Rails.logger).to receive(:wagn).with(/test/).once
45
- expect(Rails.logger).to receive(:wagn).with(/search\:/).at_least(1)
46
- test_log do
47
- Card.search :name=>'all'
48
- end
40
+
41
+ def expect_logger_to_receive_once message
42
+ allow(Rails.logger).to receive(:wagn).with(/((?!#{message}).)*/ )
43
+ expect(Rails.logger).to receive(:wagn).once.with(message)
44
+ with_logging { yield }
49
45
  end
50
-
51
- it 'logs fetches if enabled' do
52
- Wagn.config.performance_logger = { :methods=>[:fetch] }
53
- expect(Rails.logger).to receive(:wagn).with(/test/).once
54
- expect(Rails.logger).to receive(:wagn).with(/fetch/).at_least(1)
55
- test_log do
56
- Card.fetch 'all'
46
+
47
+
48
+ def expect_logger_to_receive message
49
+ allow(Rails.logger).to receive(:wagn)
50
+ Array.wrap(message).each do |msg|
51
+ expect(Rails.logger).to receive(:wagn).with(msg)
57
52
  end
53
+ with_logging { yield }
58
54
  end
59
-
60
- it 'logs views if enabled' do
61
- Wagn.config.performance_logger = { :methods=>[:view]}
62
- expect(Rails.logger).to receive(:wagn).with(/test/).once
63
- expect(Rails.logger).to receive(:wagn).with(/process: \*all/)
64
- expect(Rails.logger).to receive(:wagn).with(/view\:/)
65
- test_log do
66
- Card[:all].format.render_raw
55
+
56
+ def expect_logger_not_to_receive message
57
+ allow(Rails.logger).to receive(:wagn)
58
+ Array.wrap(message).each do |msg|
59
+ expect(Rails.logger).not_to receive(:wagn).with(msg)
67
60
  end
61
+ with_logging { yield }
62
+ end
63
+
64
+ def with_logging
65
+ Wagn::Log::Performance.start :method=>'test'
66
+ yield
67
+ Wagn::Log::Performance.stop
68
68
  end
69
-
70
- it 'logs events if enabled' do
71
- Wagn.config.performance_logger = { :methods=>[:event]}
72
- expect(Rails.logger).to receive(:wagn).with(/test/).once
73
- expect(Rails.logger).to receive(:wagn).with(/process: c1/).once
74
- expect(Rails.logger).to receive(:wagn).at_least(1).with(/ \|--\([\d.]+ms\) event\:/)
75
- test_log do
76
- Card::Auth.as_bot { Card.fetch('c1').update_attributes!(:content=>'c1') }
69
+
70
+
71
+
72
+ it 'creates tree for nested method calls' do
73
+ log_method [:view]
74
+ expect_logger_to_receive([
75
+ / \|--\([\d.]+ms\) process: c1/,
76
+ / \|--\([\d.]+ms\) view\: core/,
77
+ / \|--\([\d.]+ms\) view\: raw/,
78
+ ]) do
79
+ Card['c1'].format.render_core
77
80
  end
78
81
  end
79
-
80
- it "doesn't log methods if disabled" do
81
- Wagn.config.performance_logger = { :methods=>[]}
82
- expect(Rails.logger).to receive(:wagn).with(/test/).once
83
- test_log do
84
- Card::Auth.as_bot { Card.fetch('c1').update_attributes!(:content=>'c1') }
85
- Card.search :name=>'all'
86
- Card.fetch 'all'
87
- Card[:all].format.render_raw
82
+
83
+
84
+ describe 'logger configuration' do
85
+
86
+ it 'handles array with method name' do # log arbitrary card method
87
+ log_method( [:content] )
88
+ expect_logger_to_receive(/content/) do
89
+ Card[:all].content
90
+ end
91
+ end
92
+
93
+ it 'handles instance method type' do
94
+ class Card
95
+ def test a, b
96
+ Rails.logger.wagn("orignal method is still alive")
97
+ end
98
+ def self.test a, b; end
99
+ end
100
+ log_method( { Card => { :instance => { :test=> { :title=>:name, :message=>2 }}}} )
101
+
102
+ expect_logger_to_receive([/still alive/,/all: magic/]) do
103
+ Card[:all].test "ignore this argument", "magic"
104
+ Card.test "you won't", "get this one"
105
+ end
106
+ end
107
+
108
+ it 'handles classes and singleton method type' do # log arbitrary method
109
+ log_method( { Wagn => { :singleton=>[:gem_root] } } )
110
+ expect_logger_to_receive(/gem_root/) do
111
+ Wagn.gem_root
112
+ end
113
+ end
114
+
115
+ it 'handles method log options' do
116
+ log_method( {Card::Set::Type::Skin => {:item_names => {:message=>:raw_content, :title=>"skin item names"}}} )
117
+ expect_logger_to_receive(/skin item names/) do
118
+ Card['classic skin'].item_names
119
+ Card['*all+*read'].item_names
120
+ end
121
+ end
122
+
123
+ # it 'uses default method log options' do
124
+ # log_method [:fetch]
125
+ # expect_logger_to_receive( /fetch: all/ ) do
126
+ # Card.fetch 'all'
127
+ # end
128
+ # end
129
+
130
+ it 'handles procs and integers for method log options' do # use method arguments and procs to customize log messages
131
+ log_method( :instance => { :name= => { :title => proc { |method_context| "change name '#{method_context.name}' to"}, :message=>1 } } )
132
+ expect_logger_to_receive_once(/change name 'c1' to: Alfred/) do
133
+ Card['c1'].name = 'Alfred'
134
+ end
135
+ end
136
+
137
+
138
+ describe 'special methods' do
139
+ # FIXME: this test fails because of the logging stuff above. Need a way to reset the Card class or use test classes in all tests
140
+ # it "doesn't log special methods if disabled" do
141
+ # log_method []
142
+ # expect(Rails.logger).to receive(:wagn).with(/test/).once
143
+ # with_logging do
144
+ # Card::Auth.as_bot { Card.fetch('c1').update_attributes!(:content=>'c1') }
145
+ # Card.search :name=>'all'
146
+ # Card[:all].format.render_raw
147
+ # end
148
+ # end
149
+
150
+ it 'logs searches if enabled' do
151
+ log_method [:search]
152
+ expect_logger_to_receive( /search:/ ) do
153
+ Card.search :name=>'all'
154
+ end
155
+ end
156
+
157
+ it 'logs views if enabled' do
158
+ log_method [:view]
159
+ expect_logger_to_receive([/process: \*all/, /view:/ ] ) do
160
+ Card[:all].format.render_raw
161
+ end
162
+ end
163
+
164
+ it 'logs events if enabled' do
165
+ log_method [:event]
166
+ expect_logger_to_receive([/process: c1/, / \|--\([\d.]+ms\) event:/] ) do
167
+ Card::Auth.as_bot { Card.fetch('c1').update_attributes!(:content=>'c1') }
168
+ end
169
+ end
170
+
171
+
88
172
  end
173
+
89
174
  end
90
-
91
- it 'creates tree for nested method calls' do
92
- Wagn.config.performance_logger = { :methods=>[:view]}
93
- expect(Rails.logger).to receive(:wagn).with(/test/).once
94
- expect(Rails.logger).to receive(:wagn).with(/ \|--\([\d.]+ms\) process: c1/)
95
- expect(Rails.logger).to receive(:wagn).with(/ \|--\([\d.]+ms\) view\: core/)
96
- expect(Rails.logger).to receive(:wagn).with(/ \|--\([\d.]+ms\) view\: raw/)
97
- test_log do
98
- Card['c1'].format.render_core
175
+
176
+ describe Wagn::Log::Performance::BigBrother do
177
+ before do
178
+ class TestClass
179
+ extend Wagn::Log::Performance::BigBrother
180
+ def inst_m; end
181
+ def self.sing_m; end
182
+ end
183
+ end
184
+
185
+
186
+ describe '#watch_singleton_method' do
187
+ before do
188
+ TestClass.watch_singleton_method :sing_m
189
+ end
190
+
191
+ it 'logs singleton method' do
192
+ expect_logger_to_receive_once(/sing_m/) do
193
+ TestClass.sing_m
194
+ end
195
+ end
196
+
197
+ it 'does not log instance method' do
198
+ expect_logger_not_to_receive(/inst_,/) do
199
+ TestClass.new.inst_m
200
+ end
201
+ end
99
202
  end
203
+
204
+ describe '#watch_instance_method' do
205
+ before do
206
+ TestClass.watch_instance_method :inst_m
207
+ end
208
+
209
+ it 'logs instance method' do
210
+ expect_logger_to_receive_once(/inst_m/) do
211
+ TestClass.new.inst_m
212
+ end
213
+ end
214
+
215
+ it 'does not log singleton method' do
216
+ expect_logger_not_to_receive(/sing_m/) do
217
+ TestClass.sing_m
218
+ end
219
+ end
220
+ end
221
+
222
+
223
+ describe '#watch_all_singleton_methods' do
224
+ before do
225
+ TestClass.watch_all_singleton_methods
226
+ end
227
+ it 'logs singleton method' do
228
+ expect_logger_to_receive(/sing_m/) do
229
+ TestClass.sing_m
230
+ end
231
+ end
232
+ end
233
+
234
+ describe 'watch_all_instance_methods' do
235
+ before do
236
+ TestClass.watch_all_instance_methods
237
+ end
238
+
239
+ it 'logs instance method' do
240
+ expect_logger_to_receive(/inst_m/) do
241
+ TestClass.new.inst_m
242
+ end
243
+ end
244
+ end
245
+
246
+ describe '#watch_all_methods' do
247
+ before do
248
+ TestClass.watch_all_methods
249
+ end
250
+
251
+ it 'logs instance and singleton methods' do
252
+ expect_logger_to_receive([/inst_m/,/sing_m/]) do
253
+ TestClass.new.inst_m
254
+ TestClass.sing_m
255
+ end
256
+ end
257
+ end
258
+
100
259
  end
260
+
261
+
101
262
  end