web-console 3.5.1 → 4.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.markdown +91 -8
  3. data/MIT-LICENSE +1 -1
  4. data/README.markdown +41 -38
  5. data/Rakefile +14 -12
  6. data/lib/web-console.rb +3 -1
  7. data/lib/web_console/context.rb +8 -6
  8. data/lib/web_console/errors.rb +2 -0
  9. data/lib/web_console/evaluator.rb +14 -5
  10. data/lib/web_console/exception_mapper.rb +33 -10
  11. data/lib/web_console/extensions.rb +12 -23
  12. data/lib/web_console/injector.rb +32 -0
  13. data/lib/web_console/interceptor.rb +17 -0
  14. data/lib/web_console/middleware.rb +21 -24
  15. data/lib/web_console/permissions.rb +42 -0
  16. data/lib/web_console/railtie.rb +36 -19
  17. data/lib/web_console/request.rb +8 -20
  18. data/lib/web_console/session.rb +13 -9
  19. data/lib/web_console/source_location.rb +17 -0
  20. data/lib/web_console/tasks/extensions.rake +15 -13
  21. data/lib/web_console/tasks/templates.rake +9 -13
  22. data/lib/web_console/template.rb +4 -3
  23. data/lib/web_console/templates/console.js.erb +140 -38
  24. data/lib/web_console/templates/error_page.js.erb +7 -8
  25. data/lib/web_console/templates/index.html.erb +4 -0
  26. data/lib/web_console/templates/layouts/inlined_string.erb +1 -1
  27. data/lib/web_console/templates/layouts/javascript.erb +1 -1
  28. data/lib/web_console/templates/regular_page.js.erb +24 -0
  29. data/lib/web_console/templates/style.css.erb +182 -33
  30. data/lib/web_console/testing/erb_precompiler.rb +5 -3
  31. data/lib/web_console/testing/fake_middleware.rb +14 -9
  32. data/lib/web_console/testing/helper.rb +3 -1
  33. data/lib/web_console/version.rb +3 -1
  34. data/lib/web_console/view.rb +11 -3
  35. data/lib/web_console/whiny_request.rb +7 -5
  36. data/lib/web_console.rb +17 -8
  37. metadata +17 -15
  38. data/lib/web_console/response.rb +0 -23
  39. data/lib/web_console/whitelist.rb +0 -44
@@ -251,12 +251,14 @@ Autocomplete.prototype.removeView = function() {
251
251
  }
252
252
 
253
253
  // HTML strings for dynamic elements.
254
- var consoleInnerHtml = <%= render_inlined_string '_inner_console_markup.html' %>;
255
- var promptBoxHtml = <%= render_inlined_string '_prompt_box_markup.html' %>;
254
+ var consoleInnerHtml = <%= render_inlined_string '_inner_console_markup' %>;
255
+ var promptBoxHtml = <%= render_inlined_string '_prompt_box_markup' %>;
256
256
  // CSS
257
- var consoleStyleCss = <%= render_inlined_string 'style.css' %>;
257
+ var consoleStyleCss = <%= render_inlined_string 'style' %>;
258
258
  // Insert a style element with the unique ID
259
259
  var styleElementId = 'sr02459pvbvrmhco';
260
+ // Nonce to use for CSP
261
+ var styleElementNonce = '<%= @nonce %>';
260
262
 
261
263
  // REPLConsole Constructor
262
264
  function REPLConsole(config) {
@@ -380,8 +382,13 @@ REPLConsole.prototype.install = function(container) {
380
382
  var clientHeightStart = consoleOuter.clientHeight;
381
383
 
382
384
  var doDrag = function(e) {
383
- container.style.height = (startHeight + startY - e.clientY) + 'px';
385
+ var height = startHeight + startY - e.clientY;
384
386
  consoleOuter.scrollTop = scrollTopStart + (clientHeightStart - consoleOuter.clientHeight);
387
+ if (height > document.documentElement.clientHeight) {
388
+ container.style.height = document.documentElement.clientHeight;
389
+ } else {
390
+ container.style.height = height + 'px';
391
+ }
385
392
  shiftConsoleActions();
386
393
  };
387
394
 
@@ -411,6 +418,14 @@ REPLConsole.prototype.install = function(container) {
411
418
  }
412
419
  }
413
420
 
421
+ var observer = new MutationObserver(function(mutationsList) {
422
+ for (let mutation of mutationsList) {
423
+ if (mutation.type === 'childList' && mutation.addedNodes.length > 0) {
424
+ shiftConsoleActions();
425
+ }
426
+ }
427
+ });
428
+
414
429
  // Initialize
415
430
  this.container = container;
416
431
  this.outer = consoleOuter;
@@ -422,7 +437,7 @@ REPLConsole.prototype.install = function(container) {
422
437
 
423
438
  findChild(container, 'resizer').addEventListener('mousedown', resizeContainer);
424
439
  findChild(consoleActions, 'close-button').addEventListener('click', closeContainer);
425
- consoleOuter.addEventListener('DOMNodeInserted', shiftConsoleActions);
440
+ observer.observe(consoleOuter, { childList: true, subtree: true });
426
441
 
427
442
  REPLConsole.currentSession = this;
428
443
  };
@@ -436,6 +451,9 @@ REPLConsole.prototype.insertCss = function() {
436
451
  style.type = 'text/css';
437
452
  style.innerHTML = consoleStyleCss;
438
453
  style.id = styleElementId;
454
+ if (styleElementNonce.length > 0) {
455
+ style.nonce = styleElementNonce;
456
+ }
439
457
  document.getElementsByTagName('head')[0].appendChild(style);
440
458
  };
441
459
 
@@ -494,7 +512,7 @@ REPLConsole.prototype.getSuggestion = function(keyword) {
494
512
  hint.className = 'console-hint';
495
513
  hint.dataset.keyword = found;
496
514
  hint.innerText = found.substr(self.suggestKeyword.length);
497
- // clear hinting information after timeout in a few time
515
+ // clear hinting information after timeout in a few time
498
516
  if (self.suggestTimeout) clearTimeout(self.suggestTimeout);
499
517
  self.suggestTimeout = setTimeout(function() { self.renderInput() }, self.suggestWait);
500
518
  }
@@ -603,6 +621,12 @@ REPLConsole.prototype.writeError = function(output) {
603
621
  return consoleMessage;
604
622
  };
605
623
 
624
+ REPLConsole.prototype.writeNotification = function(output) {
625
+ var consoleMessage = this.writeOutput(output);
626
+ addClass(consoleMessage, "notification-message");
627
+ return consoleMessage;
628
+ };
629
+
606
630
  REPLConsole.prototype.onEnterKey = function() {
607
631
  var input = this._input;
608
632
 
@@ -654,65 +678,94 @@ REPLConsole.prototype.onKeyDown = function(ev) {
654
678
  }
655
679
 
656
680
  switch (ev.keyCode) {
657
- case 69:
658
- // Ctrl-E
681
+ case 65: // Ctrl-A
682
+ if (ev.ctrlKey) {
683
+ this.setInput(this._input, 0);
684
+ ev.preventDefault();
685
+ }
686
+ break;
687
+
688
+ case 69: // Ctrl-E
689
+ if (ev.ctrlKey) {
690
+ this.onTabKey();
691
+ ev.preventDefault();
692
+ }
693
+ break;
694
+
695
+ case 87: // Ctrl-W
696
+ if (ev.ctrlKey) {
697
+ this.deleteWord();
698
+ ev.preventDefault();
699
+ }
700
+ break;
701
+
702
+ case 85: // Ctrl-U
703
+ if (ev.ctrlKey) {
704
+ this.deleteLine();
705
+ ev.preventDefault();
706
+ }
707
+ break;
708
+
709
+ case 69: // Ctrl-E
659
710
  if (ev.ctrlKey) {
660
711
  this.onTabKey();
661
712
  ev.preventDefault();
662
713
  }
663
714
  break;
664
- case 9:
665
- // Tab
715
+
716
+ case 80: // Ctrl-P
717
+ if (! ev.ctrlKey) break;
718
+
719
+ case 78: // Ctrl-N
720
+ if (! ev.ctrlKey) break;
721
+
722
+ case 9: // Tab
666
723
  this.onTabKey();
667
724
  ev.preventDefault();
668
725
  break;
669
- case 13:
670
- // Enter key
726
+
727
+ case 13: // Enter key
671
728
  this.onEnterKey();
672
729
  ev.preventDefault();
673
730
  break;
674
- case 80:
675
- // Ctrl-P
676
- if (! ev.ctrlKey) break;
677
- case 38:
678
- // Up arrow
731
+
732
+ case 38: // Up arrow
679
733
  this.onNavigateHistory(-1);
680
734
  ev.preventDefault();
681
735
  break;
682
- case 78:
683
- // Ctrl-N
684
- if (! ev.ctrlKey) break;
685
- case 40:
686
- // Down arrow
736
+
737
+ case 40: // Down arrow
687
738
  this.onNavigateHistory(1);
688
739
  ev.preventDefault();
689
740
  break;
690
- case 37:
691
- // Left arrow
741
+
742
+ case 37: // Left arrow
692
743
  var caretPos = this._caretPos > 0 ? this._caretPos - 1 : this._caretPos;
693
744
  this.setInput(this._input, caretPos);
694
745
  ev.preventDefault();
695
746
  break;
696
- case 39:
697
- // Right arrow
747
+
748
+ case 39: // Right arrow
698
749
  var length = this._input.length;
699
750
  var caretPos = this._caretPos < length ? this._caretPos + 1 : this._caretPos;
700
751
  this.setInput(this._input, caretPos);
701
752
  ev.preventDefault();
702
753
  break;
703
- case 8:
704
- // Delete
754
+
755
+ case 8: // Delete
705
756
  this.deleteAtCurrent();
706
757
  ev.preventDefault();
707
758
  break;
759
+
708
760
  default:
709
761
  break;
710
762
  }
711
763
 
712
764
  if (ev.ctrlKey || ev.metaKey) {
713
- // Set focus to our clipboard in case they hit the "v" key
714
- this.clipboard.focus();
715
765
  if (ev.keyCode == 86) {
766
+ // Set focus to our clipboard when they hit the "v" key
767
+ this.clipboard.focus();
768
+
716
769
  // Pasting to clipboard doesn't happen immediately,
717
770
  // so we have to wait for a while to get the pasted text.
718
771
  var _this = this;
@@ -720,7 +773,7 @@ REPLConsole.prototype.onKeyDown = function(ev) {
720
773
  _this.addToInput(_this.clipboard.value);
721
774
  _this.clipboard.value = "";
722
775
  _this.clipboard.blur();
723
- }, 10);
776
+ }, 100);
724
777
  }
725
778
  }
726
779
 
@@ -732,7 +785,7 @@ REPLConsole.prototype.onKeyDown = function(ev) {
732
785
  */
733
786
  REPLConsole.prototype.onKeyPress = function(ev) {
734
787
  // Only write to the console if it's a single key press.
735
- if (ev.ctrlKey || ev.metaKey) { return; }
788
+ if (ev.ctrlKey && !ev.altKey || ev.metaKey) { return; }
736
789
  var keyCode = ev.keyCode || ev.which;
737
790
  this.insertAtCurrent(String.fromCharCode(keyCode));
738
791
  ev.stopPropagation();
@@ -756,6 +809,47 @@ REPLConsole.prototype.deleteAtCurrent = function() {
756
809
  }
757
810
  };
758
811
 
812
+ /**
813
+ * Deletes the current line.
814
+ */
815
+ REPLConsole.prototype.deleteLine = function() {
816
+ if (this._caretPos > 0) {
817
+ this.setInput("", 0);
818
+
819
+ if (!this._input) {
820
+ this.autocomplete && this.autocomplete.cancel();
821
+ this.autocomplete = false;
822
+ }
823
+ }
824
+ };
825
+
826
+ /**
827
+ * Deletes the current word.
828
+ */
829
+ REPLConsole.prototype.deleteWord = function() {
830
+ if (this._caretPos > 0) {
831
+ var i = 1, current = this._caretPos;
832
+ while (this._input[current - i++] == " ");
833
+
834
+ var deleteIndex = 0;
835
+ for (; current - i > 0; i++) {
836
+ if (this._input[current - i] == " ") {
837
+ deleteIndex = current - i;
838
+ break;
839
+ }
840
+ }
841
+
842
+ var before = this._input.substring(0, deleteIndex);
843
+ var after = this._input.substring(current, this._input.length);
844
+ this.setInput(before + after, deleteIndex);
845
+
846
+ if (!this._input) {
847
+ this.autocomplete && this.autocomplete.cancel();
848
+ this.autocomplete = false;
849
+ }
850
+ }
851
+ };
852
+
759
853
  /**
760
854
  * Insert a character at the current position.
761
855
  */
@@ -794,11 +888,20 @@ REPLConsole.prototype.scrollToBottom = function() {
794
888
  this.outer.scrollTop = this.outer.scrollHeight;
795
889
  };
796
890
 
797
- // Change the binding of the console
798
- REPLConsole.prototype.switchBindingTo = function(frameId, callback) {
891
+ // Change the binding of the console.
892
+ REPLConsole.prototype.switchBindingTo = function(frameId, exceptionObjectId, callback) {
799
893
  var url = this.getSessionUrl('trace');
800
894
  var params = "frame_id=" + encodeURIComponent(frameId);
801
- postRequest(url, params, callback);
895
+
896
+ if (exceptionObjectId) {
897
+ params = params + "&exception_object_id=" + encodeURIComponent(exceptionObjectId);
898
+ }
899
+
900
+ var _this = this;
901
+ postRequest(url, params, function() {
902
+ var text = "Context has changed to: " + callback();
903
+ _this.writeNotification(text);
904
+ });
802
905
  };
803
906
 
804
907
  /**
@@ -832,9 +935,8 @@ REPLConsole.request = function request(method, url, params, callback) {
832
935
  var xhr = new REPLConsole.XMLHttpRequest();
833
936
 
834
937
  xhr.open(method, url, true);
835
- xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
836
- xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
837
- xhr.setRequestHeader("Accept", "<%= Mime[:web_console_v2] %>");
938
+ xhr.setRequestHeader("content-type", "application/x-www-form-urlencoded");
939
+ xhr.setRequestHeader("x-requested-with", "XMLHttpRequest");
838
940
  xhr.send(params);
839
941
 
840
942
  xhr.onreadystatechange = function() {
@@ -8,15 +8,13 @@ for (var i = 0; i < traceFrames.length; i++) {
8
8
  e.preventDefault();
9
9
  var target = e.target;
10
10
  var frameId = target.dataset.frameId;
11
+ var exceptionObjectId = target.dataset.exceptionObjectId;
11
12
 
12
13
  // Change the binding of the console.
13
- changeBinding(frameId, function() {
14
- if (selectedFrame) {
15
- selectedFrame.className = selectedFrame.className.replace("selected", "");
16
- }
17
-
18
- target.className += " selected";
14
+ changeBinding(frameId, exceptionObjectId, function() {
15
+ // Rails already handles toggling the select class
19
16
  selectedFrame = target;
17
+ return target.innerHTML;
20
18
  });
21
19
 
22
20
  // Change the extracted source code
@@ -24,8 +22,9 @@ for (var i = 0; i < traceFrames.length; i++) {
24
22
  });
25
23
  }
26
24
 
27
- function changeBinding(frameId, callback) {
28
- REPLConsole.currentSession.switchBindingTo(frameId, callback);
25
+ // Change the binding of the current session and prompt the user.
26
+ function changeBinding(frameId, exceptionObjectId, callback) {
27
+ REPLConsole.currentSession.switchBindingTo(frameId, exceptionObjectId, callback);
29
28
  }
30
29
 
31
30
  function changeSourceExtract(frameId) {
@@ -6,3 +6,7 @@
6
6
  <% only_on_error_page do %>
7
7
  <%= render_javascript 'error_page' %>
8
8
  <% end %>
9
+
10
+ <% only_on_regular_page do %>
11
+ <%= render_javascript 'regular_page' %>
12
+ <% end %>
@@ -1 +1 @@
1
- "<%= j yield %>"
1
+ `<%= j yield %>`
@@ -1,4 +1,4 @@
1
- <script type="text/javascript" data-template="<%= @template %>">
1
+ <script type="text/javascript" data-template="<%= @template %>" nonce="<%= @nonce %>">
2
2
  (function() {
3
3
  <%= yield %>
4
4
  }).call(this);
@@ -0,0 +1,24 @@
1
+ // Push the error page body upwards the size of the console.
2
+ document.addEventListener('DOMContentLoaded', function() {
3
+ var consoleElement = document.getElementById('console');
4
+ var resizerElement = consoleElement.getElementsByClassName('resizer')[0];
5
+ var bodyElement = document.body;
6
+
7
+ function setBodyElementBottomMargin(pixels) {
8
+ bodyElement.style.marginBottom = pixels + 'px';
9
+ }
10
+
11
+ var currentConsoleElementHeight = consoleElement.offsetHeight;
12
+ setBodyElementBottomMargin(currentConsoleElementHeight);
13
+
14
+ resizerElement.addEventListener('mousedown', function(event) {
15
+ function recordConsoleElementHeight(event) {
16
+ resizerElement.removeEventListener('mouseup', recordConsoleElementHeight);
17
+
18
+ var currentConsoleElementHeight = consoleElement.offsetHeight;
19
+ setBodyElementBottomMargin(currentConsoleElementHeight);
20
+ }
21
+
22
+ resizerElement.addEventListener('mouseup', recordConsoleElementHeight);
23
+ });
24
+ });
@@ -1,33 +1,182 @@
1
- .console .pos-absolute { position: absolute; }
2
- .console .pos-fixed { position: fixed; }
3
- .console .pos-right { right: 0; }
4
- .console .border-box { box-sizing: border-box; }
5
- .console .layer { width: 100%; height: 100%; }
6
- .console .layer.console-outer { z-index: 1; }
7
- .console .layer.resizer { z-index: 2; }
8
- .console { position: fixed; left: 0; bottom: 0; width: 100%; height: 148px; padding: 0; margin: 0; background: none repeat scroll 0% 0% #333; z-index: 9999; }
9
- .console .console-outer { overflow: auto; padding-top: 4px; }
10
- .console .console-inner { font-family: monospace; font-size: 11px; width: 100%; height: 100%; overflow: none; background: #333; }
11
- .console .console-prompt-box { color: #FFF; }
12
- .console .console-message { color: #1AD027; margin: 0; border: 0; white-space: pre-wrap; background-color: #333; padding: 0; }
13
- .console .console-message.error-message { color: #fc9; }
14
- .console .console-message.auto-complete { word-break: break-all; }
15
- .console .console-message.auto-complete .keyword { margin-right: 11px; }
16
- .console .console-message.auto-complete .keyword.selected { background: #FFF; color: #000; }
17
- .console .console-message.auto-complete .hidden { display: none; }
18
- .console .console-message.auto-complete .trimmed { display: none; }
19
- .console .console-hint { color: #096; }
20
- .console .console-focus .console-cursor { background: #FEFEFE; color: #333; font-weight: bold; }
21
- .console .resizer { background: #333; width: 100%; height: 4px; cursor: ns-resize; }
22
- .console .console-actions { padding-right: 3px; }
23
- .console .console-actions .button { float: left; }
24
- .console .button { cursor: pointer; border-radius: 1px; font-family: monospace; font-size: 13px; width: 14px; height: 14px; line-height: 14px; text-align: center; color: #ccc; }
25
- .console .button:hover { background: #666; color: #fff; }
26
- .console .button.close-button:hover { background: #966; }
27
- .console .clipboard { height: 0px; padding: 0px; margin: 0px; width: 0px; margin-left: -1000px; }
28
- .console .console-prompt-label { display: inline; color: #FFF; background: none repeat scroll 0% 0% #333; border: 0; padding: 0; }
29
- .console .console-prompt-display { display: inline; color: #FFF; background: none repeat scroll 0% 0% #333; border: 0; padding: 0; }
30
- .console.full-screen { height: 100%; }
31
- .console.full-screen .console-outer { padding-top: 3px; }
32
- .console.full-screen .resizer { display: none; }
33
- .console.full-screen .close-button { display: none; }
1
+ .console .pos-absolute {
2
+ position: absolute;
3
+ }
4
+
5
+ .console .pos-fixed {
6
+ position: fixed;
7
+ }
8
+
9
+ .console .pos-right {
10
+ right: 0;
11
+ }
12
+
13
+ .console .border-box {
14
+ box-sizing: border-box;
15
+ }
16
+
17
+ .console .layer {
18
+ width: 100%;
19
+ height: 100%;
20
+ }
21
+
22
+ .console .layer.console-outer {
23
+ z-index: 1;
24
+ }
25
+
26
+ .console .layer.resizer {
27
+ z-index: 2;
28
+ }
29
+
30
+ .console {
31
+ position: fixed;
32
+ left: 0;
33
+ bottom: 0;
34
+ width: 100%;
35
+ height: 148px;
36
+ padding: 0;
37
+ margin: 0;
38
+ background: none repeat scroll 0% 0% #333;
39
+ z-index: 9999;
40
+ }
41
+
42
+ .console .console-outer {
43
+ overflow: auto;
44
+ padding-top: 4px;
45
+ }
46
+
47
+ .console .console-inner {
48
+ font-family: monospace;
49
+ font-size: 11px;
50
+ width: 100%;
51
+ height: 100%;
52
+ overflow: unset;
53
+ background: #333;
54
+ }
55
+
56
+ .console .console-prompt-box {
57
+ color: #fff;
58
+ }
59
+
60
+ .console .console-message {
61
+ color: #1ad027;
62
+ margin: 0;
63
+ border: 0;
64
+ white-space: pre-wrap;
65
+ background-color: #333;
66
+ padding: 0;
67
+ }
68
+
69
+ .console .console-message.error-message {
70
+ color: #fc9;
71
+ }
72
+
73
+ .console .console-message.notification-message {
74
+ color: #99f;
75
+ }
76
+
77
+ .console .console-message.auto-complete {
78
+ word-break: break-all;
79
+ }
80
+
81
+ .console .console-message.auto-complete .keyword {
82
+ margin-right: 11px;
83
+ }
84
+
85
+ .console .console-message.auto-complete .keyword.selected {
86
+ background: #fff;
87
+ color: #000;
88
+ }
89
+
90
+ .console .console-message.auto-complete .hidden {
91
+ display: none;
92
+ }
93
+
94
+ .console .console-message.auto-complete .trimmed {
95
+ display: none;
96
+ }
97
+
98
+ .console .console-hint {
99
+ color: #096;
100
+ }
101
+
102
+ .console .console-focus .console-cursor {
103
+ background: #fefefe;
104
+ color: #333;
105
+ font-weight: bold;
106
+ }
107
+
108
+ .console .resizer {
109
+ background: #333;
110
+ width: 100%;
111
+ height: 4px;
112
+ cursor: ns-resize;
113
+ }
114
+
115
+ .console .console-actions {
116
+ padding-right: 3px;
117
+ }
118
+
119
+ .console .console-actions .button {
120
+ float: left;
121
+ }
122
+
123
+ .console .button {
124
+ cursor: pointer;
125
+ border-radius: 1px;
126
+ font-family: monospace;
127
+ font-size: 13px;
128
+ width: 14px;
129
+ height: 14px;
130
+ line-height: 14px;
131
+ text-align: center;
132
+ color: #ccc;
133
+ }
134
+
135
+ .console .button:hover {
136
+ background: #666;
137
+ color: #fff;
138
+ }
139
+
140
+ .console .button.close-button:hover {
141
+ background: #966;
142
+ }
143
+
144
+ .console .clipboard {
145
+ height: 0px;
146
+ padding: 0px;
147
+ margin: 0px;
148
+ width: 0px;
149
+ margin-left: -1000px;
150
+ }
151
+
152
+ .console .console-prompt-label {
153
+ display: inline;
154
+ color: #fff;
155
+ background: none repeat scroll 0% 0% #333;
156
+ border: 0;
157
+ padding: 0;
158
+ }
159
+
160
+ .console .console-prompt-display {
161
+ display: inline;
162
+ color: #fff;
163
+ background: none repeat scroll 0% 0% #333;
164
+ border: 0;
165
+ padding: 0;
166
+ }
167
+
168
+ .console.full-screen {
169
+ height: 100%;
170
+ }
171
+
172
+ .console.full-screen .console-outer {
173
+ padding-top: 3px;
174
+ }
175
+
176
+ .console.full-screen .resizer {
177
+ display: none;
178
+ }
179
+
180
+ .console.full-screen .close-button {
181
+ display: none;
182
+ }
@@ -1,5 +1,7 @@
1
- require 'web_console/testing/helper'
2
- require 'web_console/testing/fake_middleware'
1
+ # frozen_string_literal: true
2
+
3
+ require "web_console/testing/helper"
4
+ require "web_console/testing/fake_middleware"
3
5
 
4
6
  module WebConsole
5
7
  module Testing
@@ -8,7 +10,7 @@ module WebConsole
8
10
  def initialize(path)
9
11
  @erb = ERB.new(File.read(path))
10
12
  @view = FakeMiddleware.new(
11
- view_path: Helper.gem_root.join('lib/web_console/templates'),
13
+ view_path: Helper.gem_root.join("lib/web_console/templates"),
12
14
  ).view
13
15
  end
14
16
 
@@ -1,14 +1,16 @@
1
- require 'action_view'
2
- require 'web_console'
3
- require 'web_console/testing/helper'
4
- Mime = { web_console_v2: 'fake' }
1
+ # frozen_string_literal: true
2
+
3
+ require "action_view"
4
+ require "action_dispatch" # This is needed to use Mime::Type
5
+ require "web_console"
6
+ require "web_console/testing/helper"
5
7
 
6
8
  module WebConsole
7
9
  module Testing
8
10
  class FakeMiddleware
9
- I18n.load_path.concat(Dir[Helper.gem_root.join('lib/web_console/locales/*.yml')])
11
+ I18n.load_path.concat(Dir[Helper.gem_root.join("lib/web_console/locales/*.yml")])
10
12
 
11
- DEFAULT_HEADERS = { "Content-Type" => "application/javascript" }
13
+ DEFAULT_HEADERS = { Rack::CONTENT_TYPE => "application/javascript" }
12
14
 
13
15
  def initialize(opts)
14
16
  @headers = opts.fetch(:headers, DEFAULT_HEADERS)
@@ -17,18 +19,21 @@ module WebConsole
17
19
  end
18
20
 
19
21
  def call(env)
20
- [ 200, @headers, [ render(req_path(env)) ] ]
22
+ body = render(req_path(env))
23
+ @headers[Rack::CONTENT_LENGTH] = body.bytesize.to_s
24
+
25
+ [ 200, @headers, [ body ] ]
21
26
  end
22
27
 
23
28
  def view
24
- @view = View.new(@view_path)
29
+ @view = View.with_empty_template_cache.with_view_paths(@view_path)
25
30
  end
26
31
 
27
32
  private
28
33
 
29
34
  # extract target path from REQUEST_PATH
30
35
  def req_path(env)
31
- env["REQUEST_PATH"].match(@req_path_regex)[1]
36
+ File.basename(env["REQUEST_PATH"].match(@req_path_regex)[1], ".*")
32
37
  end
33
38
 
34
39
  def render(template)
@@ -1,8 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module WebConsole
2
4
  module Testing
3
5
  module Helper
4
6
  def self.gem_root
5
- Pathname(File.expand_path('../../../../', __FILE__))
7
+ Pathname(File.expand_path("../../../../", __FILE__))
6
8
  end
7
9
  end
8
10
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module WebConsole
2
- VERSION = '3.5.1'
4
+ VERSION = "4.2.1"
3
5
  end