ruber 0.0.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (166) hide show
  1. data/COPYING +339 -0
  2. data/INSTALL +137 -0
  3. data/LICENSE +8 -0
  4. data/bin/ruber +65 -0
  5. data/data/share/apps/ruber/core_components.yaml +31 -0
  6. data/data/share/apps/ruber/ruberui.rc +109 -0
  7. data/data/share/icons/ruber.png +0 -0
  8. data/data/share/pixmaps/ruby.png +0 -0
  9. data/icons/ruber-16.png +0 -0
  10. data/icons/ruber-32.png +0 -0
  11. data/icons/ruber-48.png +0 -0
  12. data/icons/ruber-8.png +0 -0
  13. data/lib/ruber/application/application.rb +288 -0
  14. data/lib/ruber/application/plugin.yaml +11 -0
  15. data/lib/ruber/component_manager.rb +899 -0
  16. data/lib/ruber/config/config.rb +82 -0
  17. data/lib/ruber/config/plugin.yaml +3 -0
  18. data/lib/ruber/document_project.rb +209 -0
  19. data/lib/ruber/documents/document_list.rb +416 -0
  20. data/lib/ruber/documents/plugin.yaml +4 -0
  21. data/lib/ruber/editor/document.rb +506 -0
  22. data/lib/ruber/editor/editor_view.rb +167 -0
  23. data/lib/ruber/editor/ktexteditor_wrapper.rb +202 -0
  24. data/lib/ruber/exception_widgets.rb +245 -0
  25. data/lib/ruber/external_program_plugin.rb +397 -0
  26. data/lib/ruber/filtered_output_widget.rb +342 -0
  27. data/lib/ruber/gui_states_handler.rb +231 -0
  28. data/lib/ruber/kde_config_option_backend.rb +167 -0
  29. data/lib/ruber/kde_sugar.rb +249 -0
  30. data/lib/ruber/main_window/choose_plugins_dlg.rb +353 -0
  31. data/lib/ruber/main_window/main_window.rb +524 -0
  32. data/lib/ruber/main_window/main_window_actions.rb +537 -0
  33. data/lib/ruber/main_window/main_window_internal.rb +239 -0
  34. data/lib/ruber/main_window/open_file_in_project_dlg.rb +212 -0
  35. data/lib/ruber/main_window/output_color_widget.rb +35 -0
  36. data/lib/ruber/main_window/plugin.yaml +58 -0
  37. data/lib/ruber/main_window/save_modified_files_dlg.rb +89 -0
  38. data/lib/ruber/main_window/status_bar.rb +156 -0
  39. data/lib/ruber/main_window/ui/choose_plugins_widget.rb +90 -0
  40. data/lib/ruber/main_window/ui/choose_plugins_widget.ui +77 -0
  41. data/lib/ruber/main_window/ui/main_window_settings_widget.rb +108 -0
  42. data/lib/ruber/main_window/ui/main_window_settings_widget.ui +89 -0
  43. data/lib/ruber/main_window/ui/new_project_widget.rb +119 -0
  44. data/lib/ruber/main_window/ui/new_project_widget.ui +178 -0
  45. data/lib/ruber/main_window/ui/open_file_in_project_dlg.rb +109 -0
  46. data/lib/ruber/main_window/ui/open_file_in_project_dlg.ui +168 -0
  47. data/lib/ruber/main_window/ui/output_color_widget.rb +241 -0
  48. data/lib/ruber/main_window/ui/output_color_widget.ui +204 -0
  49. data/lib/ruber/main_window/workspace.rb +442 -0
  50. data/lib/ruber/output_widget.rb +1093 -0
  51. data/lib/ruber/plugin.rb +264 -0
  52. data/lib/ruber/plugin_like.rb +589 -0
  53. data/lib/ruber/plugin_specification.rb +106 -0
  54. data/lib/ruber/plugin_specification_reader.rb +451 -0
  55. data/lib/ruber/project.rb +493 -0
  56. data/lib/ruber/project_backend.rb +105 -0
  57. data/lib/ruber/projects/plugin.yaml +11 -0
  58. data/lib/ruber/projects/project_files_list.rb +314 -0
  59. data/lib/ruber/projects/project_files_widget.rb +301 -0
  60. data/lib/ruber/projects/project_list.rb +314 -0
  61. data/lib/ruber/projects/ui/project_files_rule_chooser_widget.rb +74 -0
  62. data/lib/ruber/projects/ui/project_files_rule_chooser_widget.ui +61 -0
  63. data/lib/ruber/projects/ui/project_files_widget.rb +117 -0
  64. data/lib/ruber/projects/ui/project_files_widget.ui +123 -0
  65. data/lib/ruber/qt_sugar.rb +673 -0
  66. data/lib/ruber/settings_container.rb +515 -0
  67. data/lib/ruber/settings_dialog.rb +244 -0
  68. data/lib/ruber/settings_dialog_manager.rb +503 -0
  69. data/lib/ruber/utils.rb +414 -0
  70. data/lib/ruber/yaml_option_backend.rb +159 -0
  71. data/outsider_files +15 -0
  72. data/plugins/autosave/autosave.rb +404 -0
  73. data/plugins/autosave/plugin.yaml +16 -0
  74. data/plugins/autosave/ui/autosave_config_widget.rb +83 -0
  75. data/plugins/autosave/ui/autosave_config_widget.ui +68 -0
  76. data/plugins/command/command.png +0 -0
  77. data/plugins/command/command.rb +74 -0
  78. data/plugins/command/plugin.yaml +11 -0
  79. data/plugins/find_in_files/find_in_files.rb +337 -0
  80. data/plugins/find_in_files/find_in_files_dlg.rb +411 -0
  81. data/plugins/find_in_files/find_in_files_ui.rc +11 -0
  82. data/plugins/find_in_files/find_in_files_widgets.rb +485 -0
  83. data/plugins/find_in_files/plugin.yaml +23 -0
  84. data/plugins/find_in_files/ui/config_widget.rb +58 -0
  85. data/plugins/find_in_files/ui/config_widget.ui +41 -0
  86. data/plugins/find_in_files/ui/find_in_files_widget.rb +260 -0
  87. data/plugins/find_in_files/ui/find_in_files_widget.ui +324 -0
  88. data/plugins/project_browser/plugin.yaml +10 -0
  89. data/plugins/project_browser/project_browser.rb +245 -0
  90. data/plugins/rake/plugin.yaml +39 -0
  91. data/plugins/rake/rake.png +0 -0
  92. data/plugins/rake/rake.rb +567 -0
  93. data/plugins/rake/rake_extension.rb +153 -0
  94. data/plugins/rake/rake_widgets.rb +615 -0
  95. data/plugins/rake/rakeui.rc +27 -0
  96. data/plugins/rake/ui/add_quick_task_widget.rb +71 -0
  97. data/plugins/rake/ui/add_quick_task_widget.ui +59 -0
  98. data/plugins/rake/ui/choose_task_widget.rb +77 -0
  99. data/plugins/rake/ui/choose_task_widget.ui +72 -0
  100. data/plugins/rake/ui/config_widget.rb +127 -0
  101. data/plugins/rake/ui/config_widget.ui +123 -0
  102. data/plugins/rake/ui/project_widget.rb +217 -0
  103. data/plugins/rake/ui/project_widget.ui +246 -0
  104. data/plugins/rspec/plugin.yaml +30 -0
  105. data/plugins/rspec/rspec.png +0 -0
  106. data/plugins/rspec/rspec.rb +945 -0
  107. data/plugins/rspec/rspec.svg +90 -0
  108. data/plugins/rspec/rspecui.rc +20 -0
  109. data/plugins/rspec/ruber_rspec_formatter.rb +312 -0
  110. data/plugins/rspec/ui/rspec_project_widget.rb +170 -0
  111. data/plugins/rspec/ui/rspec_project_widget.ui +193 -0
  112. data/plugins/ruby_development/plugin.yaml +27 -0
  113. data/plugins/ruby_development/ruby_development.png +0 -0
  114. data/plugins/ruby_development/ruby_development.rb +453 -0
  115. data/plugins/ruby_development/ruby_developmentui.rc +19 -0
  116. data/plugins/ruby_development/ui/project_widget.rb +112 -0
  117. data/plugins/ruby_development/ui/project_widget.ui +108 -0
  118. data/plugins/ruby_runner/config_widget.rb +116 -0
  119. data/plugins/ruby_runner/plugin.yaml +26 -0
  120. data/plugins/ruby_runner/project_widget.rb +62 -0
  121. data/plugins/ruby_runner/ruby.png +0 -0
  122. data/plugins/ruby_runner/ruby_interpretersui.rc +26 -0
  123. data/plugins/ruby_runner/ruby_runner.rb +411 -0
  124. data/plugins/ruby_runner/ui/config_widget.rb +92 -0
  125. data/plugins/ruby_runner/ui/config_widget.ui +91 -0
  126. data/plugins/ruby_runner/ui/project_widget.rb +60 -0
  127. data/plugins/ruby_runner/ui/project_widget.ui +48 -0
  128. data/plugins/ruby_runner/ui/ruby_runnner_plugin_option_widget.rb +59 -0
  129. data/plugins/ruby_runner/ui/ruby_runnner_plugin_option_widget.ui +44 -0
  130. data/plugins/state/plugin.yaml +28 -0
  131. data/plugins/state/state.rb +520 -0
  132. data/plugins/state/ui/config_widget.rb +92 -0
  133. data/plugins/state/ui/config_widget.ui +89 -0
  134. data/plugins/syntax_checker/plugin.yaml +18 -0
  135. data/plugins/syntax_checker/syntax_checker.rb +662 -0
  136. data/ruber.desktop +10 -0
  137. data/spec/annotation_model_spec.rb +174 -0
  138. data/spec/common.rb +119 -0
  139. data/spec/component_manager_spec.rb +1259 -0
  140. data/spec/document_list_spec.rb +626 -0
  141. data/spec/document_project_spec.rb +373 -0
  142. data/spec/document_spec.rb +779 -0
  143. data/spec/editor_view_spec.rb +167 -0
  144. data/spec/external_program_plugin_spec.rb +676 -0
  145. data/spec/filtered_output_widget_spec.rb +642 -0
  146. data/spec/gui_states_handler_spec.rb +304 -0
  147. data/spec/kde_config_option_backend_spec.rb +214 -0
  148. data/spec/kde_sugar_spec.rb +101 -0
  149. data/spec/ktexteditor_wrapper_spec.rb +305 -0
  150. data/spec/output_widget_spec.rb +1703 -0
  151. data/spec/plugin_spec.rb +1393 -0
  152. data/spec/plugin_specification_reader_spec.rb +1765 -0
  153. data/spec/plugin_specification_spec.rb +401 -0
  154. data/spec/project_backend_spec.rb +172 -0
  155. data/spec/project_files_list_spec.rb +401 -0
  156. data/spec/project_list_spec.rb +511 -0
  157. data/spec/project_spec.rb +990 -0
  158. data/spec/qt_sugar_spec.rb +328 -0
  159. data/spec/settings_container_spec.rb +617 -0
  160. data/spec/settings_dialog_manager_spec.rb +773 -0
  161. data/spec/settings_dialog_spec.rb +419 -0
  162. data/spec/state_spec.rb +991 -0
  163. data/spec/utils_spec.rb +406 -0
  164. data/spec/workspace_spec.rb +869 -0
  165. data/spec/yaml_option_backend_spec.rb +246 -0
  166. metadata +284 -0
@@ -0,0 +1,419 @@
1
+ require 'spec/common'
2
+
3
+ require 'ruber/settings_dialog'
4
+ require 'ruber/settings_container'
5
+
6
+ describe 'Ruber::SettingsDialog, when created' do
7
+
8
+ include FlexMock::ArgumentTypes
9
+
10
+ before do
11
+ @back = flexmock('backend'){|m| m.should_ignore_missing}
12
+ @cont = Object.new
13
+ @cont.extend Ruber::SettingsContainer
14
+ @cont.send :setup_container, @back
15
+ @widgets = [
16
+ OS.new({:caption => 'C1', :class_obj => Qt::CheckBox}),
17
+ OS.new({:caption => 'C2', :class_obj => Qt::LineEdit}),
18
+ OS.new({:caption => 'C2', :code => 'Qt::PushButton.new("test")'}),
19
+ OS.new({:caption => 'C1', :class_obj => Qt::RadioButton, :code => 'Qt::ComboBox.new'})
20
+ ]
21
+ @mw = Qt::Widget.new
22
+ flexmock(Ruber).should_receive(:[]).with(:main_window).by_default.and_return @mw
23
+ end
24
+
25
+ it 'should set its title to the fourth argument, if given' do
26
+ dlg = Ruber::SettingsDialog.new @cont, {}, [], 'Title'
27
+ dlg.window_title.should == 'Title'
28
+ dlg = Ruber::SettingsDialog.new @cont, {}, []
29
+ dlg.window_title.should == KDE::Application.instance.application_name
30
+ end
31
+
32
+ it 'should store the first argument in the @container instance variable' do
33
+ dlg = Ruber::SettingsDialog.new @cont, {}, []
34
+ dlg.instance_variable_get(:@container).should equal(@cont)
35
+ end
36
+
37
+ it 'should create the widgets specified in the third argument and store it in the @pages instance variable, grouped by captions' do
38
+ @widgets.each{|w| @cont.add_widget w}
39
+ dlg = Ruber::SettingsDialog.new @cont, [], @widgets
40
+ res = dlg.instance_variable_get(:@widgets)
41
+ res['C1'][0].should be_a(Qt::CheckBox)
42
+ res['C1'][1].should be_a(Qt::ComboBox)
43
+ res['C2'][0].should be_a(Qt::LineEdit)
44
+ res['C2'][1].should be_a(Qt::PushButton)
45
+ res['C2'][1].text.should == 'test'
46
+ end
47
+
48
+ it 'should add an @settings_dialog instance variable and set it to self for each widget it creates' do
49
+ @widgets.each{|w| @cont.add_widget w}
50
+ dlg = Ruber::SettingsDialog.new @cont, [], @widgets
51
+ widgets = dlg.instance_variable_get(:@widgets).values.flatten
52
+ widgets.each{|w| w.instance_variable_get(:@settings_dialog).should equal(dlg)}
53
+ end
54
+
55
+ it 'should add a page for each caption and store the corresponding PageWidgetItems in the @page_items instance variable' do
56
+ dlg = Ruber::SettingsDialog.new @cont, [], @widgets
57
+ dlg.instance_variable_get(:@page_items).size.should == 2
58
+ end
59
+
60
+ it 'should create a page for each caption, in alphabetical order, with the widgets stored in a vertical layout, from first to last' do
61
+ @widgets.unshift @widgets.delete_at(1)
62
+ @widgets.each{|w| @cont.add_widget w}
63
+ dlg = Ruber::SettingsDialog.new @cont, [], @widgets
64
+ items = dlg.instance_variable_get :@page_items
65
+
66
+ l = items[0].widget.layout
67
+ l.should be_a(Qt::VBoxLayout)
68
+ l.item_at(0).widget.should be_a(Qt::CheckBox)
69
+ l.item_at(1).widget.should be_a(Qt::ComboBox)
70
+
71
+ l = items[1].widget.layout
72
+ l.item_at(0).widget.should be_a(Qt::LineEdit)
73
+ l.item_at(1).widget.should be_a(Qt::PushButton)
74
+ end
75
+
76
+ it 'should use the first specified icon for each page' do
77
+ %w[xyz.png 123.png 456.png abc.png].each_with_index{|p, i| @widgets[i].pixmap = p}
78
+ @widgets.each{|w| @cont.add_widget w}
79
+ icons = [KDE::Icon.new( 'xyz.png'), KDE::Icon.new('123.png')]
80
+ flexmock(KDE::Icon).should_receive(:new).once.with('xyz.png').and_return(icons[0])
81
+ flexmock(KDE::Icon).should_receive(:new).once.with('123.png').and_return(icons[1])
82
+ flexmock(KDE::Icon).should_receive(:new).with('abc.png').never
83
+ flexmock(KDE::Icon).should_receive(:new).with('456.png').never
84
+ dlg = Ruber::SettingsDialog.new @cont, [], @widgets
85
+ items = dlg.instance_variable_get :@page_items
86
+ end
87
+
88
+ it 'should create an instance of the SettingsDialogManager class, passing it self, the widgets and the options' do
89
+ options = {
90
+ OS.new({:group => 'G1', :name => :o1, :default => 2}) => 3,
91
+ OS.new({:group => :G2, :name => :o2, :default => 'xyz'}) => 'abc'
92
+ }
93
+ @widgets.each{|w| @cont.add_widget w}
94
+ flexmock(Ruber::SettingsDialogManager).should_receive(:new).once.with(Ruber::SettingsDialog, options, on{|a| a.map(&:class) == [Qt::CheckBox, Qt::ComboBox, Qt::LineEdit, Qt::PushButton]})
95
+ dlg = Ruber::SettingsDialog.new @cont, options, @widgets
96
+ end
97
+
98
+ end
99
+
100
+ describe 'Ruber::SettingsDialog#read_settings' do
101
+
102
+ before do
103
+ @mw = Qt::Widget.new
104
+ flexmock(Ruber).should_receive(:[]).with(:main_window).by_default.and_return @mw
105
+ @back = flexmock('backend'){|m| m.should_ignore_missing}
106
+ @cont = Object.new
107
+ @cont.extend Ruber::SettingsContainer
108
+ @cont.send :setup_container, @back
109
+ @widgets = [
110
+ OS.new({:caption => 'C1', :class_obj => Qt::CheckBox}),
111
+ OS.new({:caption => 'C2', :class_obj => Qt::LineEdit}),
112
+ OS.new({:caption => 'C2', :code => 'Qt::PushButton.new("test")'}),
113
+ OS.new({:caption => 'C1', :class_obj => Qt::RadioButton, :code => 'Qt::ComboBox.new'})
114
+ ]
115
+ end
116
+
117
+ it 'should call the read_settings method of each widget which provides it' do
118
+ dlg = Ruber::SettingsDialog.new @cont, [], @widgets
119
+ widgets = dlg.instance_variable_get(:@widgets)
120
+
121
+ widgets['C1'][0].instance_eval do
122
+ def read_settings
123
+ end
124
+ end
125
+ flexmock(widgets['C1'][0]).should_receive(:read_settings).once
126
+
127
+ widgets['C1'][1].instance_eval do
128
+ def read_settings
129
+ end
130
+ end
131
+ flexmock(widgets['C1'][1]).should_receive(:read_settings).once
132
+
133
+ widgets['C2'][0].instance_eval do
134
+ def read_settings
135
+ end
136
+ end
137
+ flexmock(widgets['C2'][0]).should_receive(:read_settings).once
138
+
139
+ dlg.read_settings
140
+ end
141
+
142
+ it 'should call the read_settings method of the option manager' do
143
+ dlg = Ruber::SettingsDialog.new @cont, [], @widgets
144
+ flexmock(dlg.instance_variable_get(:@manager)).should_receive(:read_settings).once
145
+ dlg.read_settings
146
+ end
147
+
148
+ end
149
+
150
+ describe 'Ruber::SettingsDialog#store_settings' do
151
+
152
+ before do
153
+ @mw = Qt::Widget.new
154
+ flexmock(Ruber).should_receive(:[]).with(:main_window).by_default.and_return @mw
155
+ @back = flexmock('backend'){|m| m.should_ignore_missing}
156
+ @cont = Object.new
157
+ @cont.extend Ruber::SettingsContainer
158
+ @cont.send :setup_container, @back
159
+ @widgets = [
160
+ OS.new({:caption => 'C1', :class_obj => Qt::CheckBox}),
161
+ OS.new({:caption => 'C2', :class_obj => Qt::LineEdit}),
162
+ OS.new({:caption => 'C2', :code => 'Qt::PushButton.new("test")'}),
163
+ OS.new({:caption => 'C1', :class_obj => Qt::RadioButton, :code => 'Qt::ComboBox.new'})
164
+ ]
165
+ end
166
+
167
+ it 'should call the store_settings method of each widget which provides it' do
168
+ dlg = Ruber::SettingsDialog.new @cont, [], @widgets
169
+ widgets = dlg.instance_variable_get(:@widgets)
170
+
171
+ widgets['C1'][0].instance_eval do
172
+ def store_settings
173
+ end
174
+ end
175
+ flexmock(widgets['C1'][0]).should_receive(:store_settings).once
176
+
177
+ widgets['C1'][1].instance_eval do
178
+ def store_settings
179
+ end
180
+ end
181
+ flexmock(widgets['C1'][1]).should_receive(:store_settings).once
182
+
183
+ widgets['C2'][0].instance_eval do
184
+ def store_settings
185
+ end
186
+ end
187
+ flexmock(widgets['C2'][0]).should_receive(:store_settings).once
188
+
189
+ dlg.store_settings
190
+ end
191
+
192
+ it 'should call the store_settings method of the option manager' do
193
+ dlg = Ruber::SettingsDialog.new @cont, [], @widgets
194
+ flexmock(dlg.instance_variable_get(:@manager)).should_receive(:store_settings).once
195
+ dlg.store_settings
196
+ end
197
+
198
+ it 'should call the "write" method of the container, after all the store_settings methods have been called' do
199
+ dlg = Ruber::SettingsDialog.new @cont, [], @widgets
200
+ widgets = dlg.instance_variable_get(:@widgets)
201
+ widgets['C1'][0].instance_eval do
202
+ def store_settings
203
+ end
204
+ end
205
+ flexmock(dlg.instance_variable_get(:@manager)).should_receive(:store_settings).once.globally.ordered
206
+ flexmock(widgets['C1'][0]).should_receive(:store_settings).once.globally.ordered
207
+ flexmock(@cont).should_receive(:write).once.globally.ordered
208
+ dlg.store_settings
209
+ end
210
+
211
+ it 'should be called when the Ok button is clicked' do
212
+ dlg = Ruber::SettingsDialog.new @cont, [], @widgets
213
+ flexmock(dlg).should_receive(:store_settings).once
214
+ dlg.instance_eval{emit okClicked}
215
+ end
216
+
217
+ it 'should be called when the Apply button is clicked' do
218
+ dlg = Ruber::SettingsDialog.new @cont, [], @widgets
219
+ flexmock(dlg).should_receive(:store_settings).once
220
+ dlg.instance_eval{emit applyClicked}
221
+ end
222
+
223
+ end
224
+
225
+ describe 'Ruber::SettingsDialog#read_default_settings' do
226
+
227
+ before do
228
+ @mw = Qt::Widget.new
229
+ flexmock(Ruber).should_receive(:[]).with(:main_window).by_default.and_return @mw
230
+ @back = flexmock('backend'){|m| m.should_ignore_missing}
231
+ @cont = Object.new
232
+ @cont.extend Ruber::SettingsContainer
233
+ @cont.send :setup_container, @back
234
+ @widgets = [
235
+ OS.new({:caption => 'C1', :class_obj => Qt::CheckBox}),
236
+ OS.new({:caption => 'C2', :class_obj => Qt::LineEdit}),
237
+ OS.new({:caption => 'C2', :code => 'Qt::PushButton.new("test")'}),
238
+ OS.new({:caption => 'C1', :class_obj => Qt::RadioButton, :code => 'Qt::ComboBox.new'})
239
+ ]
240
+ end
241
+
242
+ it 'should call the read_default_settings method of each widget which provides it' do
243
+ dlg = Ruber::SettingsDialog.new @cont, [], @widgets
244
+ widgets = dlg.instance_variable_get(:@widgets)
245
+
246
+ widgets['C1'][0].instance_eval do
247
+ def read_default_settings
248
+ end
249
+ end
250
+ flexmock(widgets['C1'][0]).should_receive(:read_default_settings).once
251
+
252
+ widgets['C1'][1].instance_eval do
253
+ def read_default_settings
254
+ end
255
+ end
256
+ flexmock(widgets['C1'][1]).should_receive(:read_default_settings).once
257
+
258
+ widgets['C2'][0].instance_eval do
259
+ def read_default_settings
260
+ end
261
+ end
262
+ flexmock(widgets['C2'][0]).should_receive(:read_default_settings).once
263
+
264
+ dlg.read_default_settings
265
+ end
266
+
267
+ it 'should call the read_default_settings method of the option manager' do
268
+ dlg = Ruber::SettingsDialog.new @cont, [], @widgets
269
+ flexmock(dlg.instance_variable_get(:@manager)).should_receive(:read_default_settings).once
270
+ dlg.read_default_settings
271
+ end
272
+
273
+ it 'should be called when the Default button is clicked' do
274
+ dlg = Ruber::SettingsDialog.new @cont, [], @widgets
275
+ flexmock(dlg).should_receive(:read_default_settings).once
276
+ dlg.instance_eval{emit defaultClicked}
277
+ end
278
+
279
+ end
280
+
281
+ describe 'Ruber::SettingsDialog#exec' do
282
+
283
+ before(:all) do
284
+ class ::KDE::PageDialog
285
+ def exec
286
+ end
287
+ end
288
+ end
289
+
290
+ after(:all) do
291
+ class ::KDE::PageDialog
292
+ undef_method :exec
293
+ end
294
+ end
295
+
296
+ before do
297
+ @mw = Qt::Widget.new
298
+ flexmock(Ruber).should_receive(:[]).with(:main_window).by_default.and_return @mw
299
+ @back = flexmock('backend'){|m| m.should_ignore_missing}
300
+ @cont = Object.new
301
+ @cont.extend Ruber::SettingsContainer
302
+ @cont.send :setup_container, @back
303
+ @widgets = [
304
+ OS.new({:caption => 'C1', :class_obj => Qt::CheckBox}),
305
+ OS.new({:caption => 'C2', :class_obj => Qt::LineEdit}),
306
+ OS.new({:caption => 'C2', :code => 'Qt::PushButton.new("test")'}),
307
+ OS.new({:caption => 'C1', :class_obj => Qt::RadioButton, :code => 'Qt::ComboBox.new'})
308
+ ]
309
+ end
310
+
311
+ it 'should call the read_settings method' do
312
+ dlg = Ruber::SettingsDialog.new @cont, [], @widgets
313
+ flexmock(dlg).should_receive(:read_settings).once
314
+ dlg.exec
315
+ end
316
+
317
+ it 'should make the first page current' do
318
+ dlg = Ruber::SettingsDialog.new @cont, [], @widgets
319
+ # It seems that comparing the objects themselves doesn't work, as they seem to
320
+ # have different object_id s. To avoid problems, we give a name to each
321
+ dlg.instance_variable_get(:@page_items).each_with_index{|w, i| w.object_name = i.to_s}
322
+ dlg.current_page = dlg.instance_variable_get(:@page_items)[1]
323
+ dlg.exec
324
+ dlg.current_page.object_name.should == '0'
325
+ end
326
+
327
+ it 'should give focus to the first widget in the page' do
328
+ dlg = Ruber::SettingsDialog.new @cont, [], @widgets
329
+ flexmock(dlg.instance_variable_get(:@widgets)['C1'][0]).should_receive(:set_focus).once
330
+ dlg.exec
331
+ end
332
+
333
+ it 'shouldn\'t attempt to make the first page current if there are no pages' do
334
+ dlg = Ruber::SettingsDialog.new @cont, [], []
335
+ lambda{dlg.exec}.should_not raise_error
336
+ end
337
+
338
+ end
339
+
340
+ describe 'Ruber::SettingsDialog#show' do
341
+
342
+ before(:all) do
343
+ class ::KDE::PageDialog
344
+ def show
345
+ end
346
+ end
347
+ end
348
+
349
+ after(:all) do
350
+ class ::KDE::PageDialog
351
+ undef_method :show
352
+ end
353
+ end
354
+
355
+ before do
356
+ @mw = Qt::Widget.new
357
+ flexmock(Ruber).should_receive(:[]).with(:main_window).by_default.and_return @mw
358
+ @back = flexmock('backend'){|m| m.should_ignore_missing}
359
+ @cont = Object.new
360
+ @cont.extend Ruber::SettingsContainer
361
+ @cont.send :setup_container, @back
362
+ @widgets = [
363
+ OS.new({:caption => 'C1', :class_obj => Qt::CheckBox}),
364
+ OS.new({:caption => 'C2', :class_obj => Qt::LineEdit}),
365
+ OS.new({:caption => 'C2', :code => 'Qt::PushButton.new("test")'}),
366
+ OS.new({:caption => 'C1', :class_obj => Qt::RadioButton, :code => 'Qt::ComboBox.new'})
367
+ ]
368
+ end
369
+
370
+ it 'should call the read_settings method' do
371
+ dlg = Ruber::SettingsDialog.new @cont, [], @widgets
372
+ flexmock(dlg).should_receive(:read_settings).once
373
+ dlg.show
374
+ end
375
+
376
+ it 'should make the first page current' do
377
+ dlg = Ruber::SettingsDialog.new @cont, [], @widgets
378
+ # It seems that comparing the objects themselves doesn't work, as they seem to
379
+ # have different object_id s. To avoid problems, we give a name to each
380
+ dlg.instance_variable_get(:@page_items).each_with_index{|w, i| w.object_name = i.to_s}
381
+ dlg.current_page = dlg.instance_variable_get(:@page_items)[1]
382
+ dlg.show
383
+ dlg.current_page.object_name.should == '0'
384
+ end
385
+
386
+ it 'should give focus to the first widget in the page' do
387
+ dlg = Ruber::SettingsDialog.new @cont, [], @widgets
388
+ flexmock(dlg.instance_variable_get(:@widgets)['C1'][0]).should_receive(:set_focus).once
389
+ dlg.show
390
+ end
391
+
392
+ end
393
+
394
+ describe 'SettingsDialog#widgets' do
395
+
396
+ it 'should return an array containing all the added widgets' do
397
+ @mw = Qt::Widget.new
398
+ flexmock(Ruber).should_receive(:[]).with(:main_window).by_default.and_return @mw
399
+ @back = flexmock('backend'){|m| m.should_ignore_missing}
400
+ @cont = Object.new
401
+ @cont.extend Ruber::SettingsContainer
402
+ @cont.send :setup_container, @back
403
+ @widgets = [
404
+ OS.new({:caption => 'C1', :class_obj => Qt::CheckBox}),
405
+ OS.new({:caption => 'C2', :class_obj => Qt::LineEdit}),
406
+ OS.new({:caption => 'C2', :code => 'Qt::PushButton.new("test")'}),
407
+ OS.new({:caption => 'C1', :class_obj => Qt::RadioButton, :code => 'Qt::ComboBox.new'})
408
+ ]
409
+ dlg = Ruber::SettingsDialog.new @cont, [], @widgets
410
+ res = dlg.widgets
411
+ internal = dlg.instance_variable_get(:@widgets)
412
+ res.size.should == 4
413
+ res.should include(internal['C1'][0])
414
+ res.should include(internal['C1'][1])
415
+ res.should include(internal['C2'][0])
416
+ res.should include(internal['C2'][1])
417
+ end
418
+
419
+ end
@@ -0,0 +1,991 @@
1
+ require 'spec/common'
2
+
3
+ require 'tempfile'
4
+ require 'fileutils'
5
+
6
+ require 'ruber/plugin_specification'
7
+ require 'ruber/editor/document'
8
+
9
+ require 'plugins/state/state'
10
+
11
+ describe Ruber::State::Plugin do
12
+
13
+ before do
14
+ #Needed because the Qt::Object connect method doesn't like @components not being a
15
+ #Qt::Object
16
+ class Ruber::State::Plugin
17
+ def connect *args
18
+ end
19
+ end
20
+ @components = flexmock('components'){|m| m.should_ignore_missing}
21
+ @config = flexmock('config'){|m| m.should_ignore_missing}
22
+ flexmock(Ruber).should_receive(:[]).with(:components).and_return(@components).by_default
23
+ flexmock(Ruber).should_receive(:[]).with(:app).and_return(KDE::Application.instance).by_default
24
+ flexmock(Ruber).should_receive(:[]).with(:config).and_return(@config).by_default
25
+ pdf = Ruber::PluginSpecification.full :name => :state
26
+ @plug = Ruber::State::Plugin.new pdf
27
+ end
28
+
29
+ after do
30
+ class Ruber::State::Plugin
31
+ remove_method :connect rescue nil
32
+ end
33
+ end
34
+
35
+ it 'inherits Ruber::Plugin' do
36
+ Ruber::State::Plugin.ancestors.should include(Ruber::Plugin)
37
+ end
38
+
39
+ describe '#when created' do
40
+
41
+ it 'sets the @force_restore_project_files instance variable to nil' do
42
+ @plug.instance_variables.should include(:@force_restore_project_files)
43
+ @plug.instance_variable_get(:@force_restore_project_files).should be_nil
44
+ end
45
+
46
+ it 'sets the @force_restore_cursor_position instance variable to nil' do
47
+ @plug.instance_variables.should include(:@force_restore_cursor_position)
48
+ @plug.instance_variable_get(:@force_restore_cursor_position).should be_nil
49
+ end
50
+
51
+ end
52
+
53
+ describe '#delayed_initialize' do
54
+
55
+ before do
56
+ @documents = flexmock('documents')
57
+ @projects = flexmock('projects')
58
+ flexmock(KDE::Application.instance).should_receive(:starting?).and_return(true).by_default
59
+ flexmock(Ruber).should_receive(:[]).with(:docs).and_return(@documents).by_default
60
+ flexmock(Ruber).should_receive(:[]).with(:projects).and_return(@projects).by_default
61
+ end
62
+
63
+ it 'calls the restore_last_state method if there\'s no open project and the only open document is pristine' do
64
+ doc = flexmock('doc', :pristine? => true)
65
+ @documents.should_receive(:to_a).once.and_return [doc]
66
+ @documents.should_receive(:[]).with(0).once.and_return doc
67
+ @projects.should_receive(:to_a).once.and_return []
68
+ flexmock(@plug).should_receive(:restore_last_state).once
69
+ @plug.send :delayed_initialize
70
+ end
71
+
72
+ it 'doesn\'t call the restore_last_state method if there are open projects' do
73
+ prj = flexmock('project')
74
+ @projects.should_receive(:to_a).once.and_return [prj]
75
+ flexmock(@plug).should_receive(:restore_last_state).never
76
+ @plug.send :delayed_initialize
77
+ end
78
+
79
+ it 'doesn\'t call the restore_last_state method if there is more than one open document' do
80
+ @documents.should_receive(:to_a).once.and_return 2.times.map{flexmock}
81
+ @projects.should_receive(:to_a).once.and_return []
82
+ flexmock(@plug).should_receive(:restore_last_state).never
83
+ @plug.send :delayed_initialize
84
+ end
85
+
86
+ it 'doesn\'t call the restore_last_state method if there aren\'t open documents' do
87
+ @documents.should_receive(:to_a).once.and_return []
88
+ @projects.should_receive(:to_a).once.and_return []
89
+ flexmock(@plug).should_receive(:restore_last_state).never
90
+ @plug.send :delayed_initialize
91
+ end
92
+
93
+ it 'doesn\'t call the restore_last_state method if the only open document isn\'t pristine' do
94
+ doc = flexmock('doc', :pristine? => false)
95
+ @documents.should_receive(:to_a).once.and_return [doc]
96
+ @documents.should_receive(:[]).with(0).once.and_return doc
97
+ @projects.should_receive(:to_a).once.and_return []
98
+ flexmock(@plug).should_receive(:restore_last_state).never
99
+ @plug.send :delayed_initialize
100
+ end
101
+
102
+ it 'does nothing if the application is already running' do
103
+ doc = flexmock('doc', :pristine? => true)
104
+ @documents.should_receive(:to_a).and_return [doc]
105
+ @documents.should_receive(:[]).with(0).and_return doc
106
+ @projects.should_receive(:to_a).and_return []
107
+ flexmock(KDE::Application.instance).should_receive(:starting?).and_return false
108
+ flexmock(@plug).should_receive(:restore_last_state).never
109
+ @plug.send :delayed_initialize
110
+ end
111
+
112
+ end
113
+
114
+ describe '#gather_settings' do
115
+
116
+ before do
117
+ @projects = flexmock('projects') do |m|
118
+ m.should_receive(:projects).and_return([]).by_default
119
+ m.should_receive(:current).and_return(nil).by_default
120
+ end
121
+ @documents = flexmock('documents') do |m|
122
+ m.should_receive(:documents).and_return([]).by_default
123
+ m.should_receive(:current).and_return(nil).by_default
124
+ end
125
+ @mw = flexmock('main window'){|m| m.should_ignore_missing}
126
+ flexmock(Ruber).should_receive(:[]).with(:projects).and_return(@projects).by_default
127
+ flexmock(Ruber).should_receive(:[]).with(:docs).and_return(@documents).by_default
128
+ flexmock(Ruber).should_receive(:[]).with(:main_window).and_return(@mw).by_default
129
+ end
130
+
131
+ it 'stores a list with the project file of each open project under the :open_projects key' do
132
+ prjs = 5.times.map{|i| flexmock(i.to_s){|m| m.should_receive(:project_file).and_return i.to_s}}
133
+ @projects.should_receive(:projects).once.and_return(prjs)
134
+ @projects.should_receive(:current).once.and_return(nil)
135
+ @plug.send(:gather_settings).should have_entries(:open_projects => (0...5).map(&:to_s))
136
+ end
137
+
138
+ it 'puts the file corresponding to the open project at the beginning of the :open_projects entry' do
139
+ prjs = 5.times.map{|i| flexmock(i.to_s, :project_file => i.to_s)}
140
+ @projects.should_receive(:projects).once.and_return(prjs)
141
+ @projects.should_receive(:current).once.and_return prjs[2]
142
+ @plug.send(:gather_settings).should have_entries(:open_projects => %w[2 0 1 3 4])
143
+ end
144
+
145
+ it 'stores the project files in an arbitrary order if there\'s no active project' do
146
+ prjs = 5.times.map{|i| flexmock(i.to_s){|m| m.should_receive(:project_file).and_return i.to_s}}
147
+ @projects.should_receive(:projects).once.and_return(prjs)
148
+ @projects.should_receive(:current).once.and_return nil
149
+ @plug.send(:gather_settings).should have_entries(:open_projects => (0...5).map(&:to_s))
150
+ end
151
+
152
+ it 'stores an empty array under the :open_projects key if there are no open projects' do
153
+ @plug.send(:gather_settings).should have_entries(:open_projects => [])
154
+ end
155
+
156
+ it 'stores a list of the paths of the files associated with all open documents under the :open_files key' do
157
+ docs = 5.times.map{|i| flexmock(i.to_s){|m| m.should_receive(:path).and_return i.to_s}}
158
+ @documents.should_receive(:documents).once.and_return(docs)
159
+ @plug.send(:gather_settings).should have_entries(:open_documents => (0...5).map(&:to_s))
160
+ end
161
+
162
+ it 'ignores documents which aren\'t associated with a file' do
163
+ docs = 5.times.map do |i|
164
+ flexmock(i.to_s) do |m|
165
+ m.should_receive(:path).and_return(i % 2 == 0 ? i.to_s : '')
166
+ end
167
+ end
168
+ @documents.should_receive(:documents).once.and_return(docs)
169
+ @plug.send(:gather_settings).should have_entries(:open_documents => %w[0 2 4])
170
+ end
171
+
172
+ it 'stores an empty array under the :open_files key if there are no open documents or if no open document is associated with a file' do
173
+ docs = 5.times.map{flexmock(:path => '')}
174
+ @documents.should_receive(:documents).once.and_return(docs).once
175
+ @documents.should_receive(:documents).once.and_return([]).once
176
+ @plug.send(:gather_settings).should have_entries(:open_documents => [])
177
+ @plug.send(:gather_settings).should have_entries(:open_documents => [])
178
+ end
179
+
180
+ it 'stores the path of the active document under the :active_document key' do
181
+ docs = 5.times.map{|i| flexmock(i.to_s){|m| m.should_receive(:path).and_return i.to_s}}
182
+ @documents.should_receive(:documents).once.and_return(docs)
183
+ @mw.should_receive(:current_document).once.and_return(docs[1])
184
+ @plug.send(:gather_settings).should have_entries(:active_document => "1")
185
+ end
186
+
187
+ it 'stores nil under the :active_document key if there\'s no current document' do
188
+ @mw.should_receive(:current_document).once.and_return nil
189
+ @plug.send(:gather_settings).should have_entries(:active_document => nil)
190
+ end
191
+
192
+ it 'stores nil under the :active_document key if the current document isn\'t associated with a file' do
193
+ doc = flexmock('doc', :path => '')
194
+ @mw.should_receive(:current_document).once.and_return doc
195
+ @plug.send(:gather_settings).should have_entries(:active_document => nil)
196
+ end
197
+
198
+ end
199
+
200
+ describe '#save_settings' do
201
+
202
+ it 'stores the value corresponding to the :open_projects key in the hash returned by gather_settings in the state/open_projects setting' do
203
+ flexmock(@plug).should_receive(:gather_settings).once.and_return(:open_projects => %w[x y z])
204
+ @config.should_receive(:[]=).with(:state, :open_projects, %w[x y z]).once
205
+ @config.should_receive(:[]=)
206
+ @plug.save_settings
207
+ end
208
+
209
+ it 'stores the value corresponding to the :open_documents key in the hash returned by gather_settings in the state/open_documents setting' do
210
+ flexmock(@plug).should_receive(:gather_settings).once.and_return(:open_documents => %w[x y z])
211
+ @config.should_receive(:[]=).with(:state, :open_documents, %w[x y z]).once
212
+ @config.should_receive(:[]=)
213
+ @plug.save_settings
214
+ end
215
+
216
+ it 'stores the value corresponding to the :active_document key in the hash returned by gather_settings in the state/active_document setting' do
217
+ flexmock(@plug).should_receive(:gather_settings).once.and_return(:active_document => 'x')
218
+ @config.should_receive(:[]=).with(:state, :active_document, 'x').once
219
+ @config.should_receive(:[]=)
220
+ @plug.save_settings
221
+ end
222
+
223
+ end
224
+
225
+ describe '#restore_cursor_position?' do
226
+
227
+ it 'returns the value of the state/restore_cursor_position config entry if the @force_restore_cursor_position instance variable is nil' do
228
+ @config.should_receive(:[]).with(:state, :restore_cursor_position).once.and_return(true)
229
+ @config.should_receive(:[]).with(:state, :restore_cursor_position).once.and_return(false)
230
+ @plug.instance_variable_set :@force_restore_cursor_position, nil
231
+ @plug.restore_cursor_position?.should == true
232
+ @plug.restore_cursor_position?.should == false
233
+ end
234
+
235
+ it 'returns the value of the @force_restore_cursor_position instance variable if it is not nil' do
236
+ @config.should_receive(:[]).with(:state, :restore_cursor_position).never
237
+ @plug.instance_variable_set :@force_restore_cursor_position, true
238
+ @plug.restore_cursor_position?.should == true
239
+ @plug.instance_variable_set :@force_restore_cursor_position, false
240
+ @plug.restore_cursor_position?.should == false
241
+ end
242
+
243
+ end
244
+
245
+ describe '#restore_project_files?' do
246
+
247
+ it 'returns the value of the state/restore_project_files config entry if the @force_restore_project_files instance variable is nil' do
248
+ @config.should_receive(:[]).with(:state, :restore_project_files).once.and_return(true)
249
+ @config.should_receive(:[]).with(:state, :restore_project_files).once.and_return(false)
250
+ @plug.instance_variable_set :@force_restore_project_files, nil
251
+ @plug.restore_project_files?.should == true
252
+ @plug.restore_project_files?.should == false
253
+ end
254
+
255
+ it 'returns the value of the @force_restore_project_files instance variable if it is not nil' do
256
+ @config.should_receive(:[]).with(:state, :restore_project_files).never
257
+ @plug.instance_variable_set :@force_restore_project_files, true
258
+ @plug.restore_project_files?.should == true
259
+ @plug.instance_variable_set :@force_restore_project_files, false
260
+ @plug.restore_project_files?.should == false
261
+ end
262
+
263
+ end
264
+
265
+ describe 'session_data' do
266
+
267
+ it 'returns a hash containing the hash returned by the gather_settings method under the "State" key' do
268
+ hash = {
269
+ :open_projects => %w[a b c],
270
+ :open_documents => %w[x y z],
271
+ :active_document => 'z'
272
+ }
273
+ flexmock(@plug).should_receive(:gather_settings).once.and_return hash
274
+ res = @plug.session_data
275
+ res['State'].should == hash
276
+ end
277
+
278
+ end
279
+
280
+ describe '#restore_session' do
281
+
282
+ it 'calls restore from within a with block with :restore_cursor_position and :restore_project_files set to true passing the hash contained in the State entry of the argument' do
283
+ hash = {
284
+ 'State' => {
285
+ :open_projects => %w[a b c],
286
+ :open_documents => %w[x y z],
287
+ :active_document => 'z'
288
+ }
289
+ }
290
+ exp_hash = {
291
+ [:state, :open_projects] => %w[a b c],
292
+ [:state, :open_documents] => %w[x y z],
293
+ [:state, :active_document] => 'z'
294
+ }
295
+ default = {:open_projects => [], :open_documents => [], :active_document => nil}
296
+ flexmock(@plug).should_receive(:with).with({:restore_cursor_position => true, :restore_project_files => true, :force => true}, FlexMock.on{|a| a.call || a.is_a?(Proc)}).once
297
+ flexmock(@plug).should_receive(:restore).with(FlexMock.on{|a| a == exp_hash and a[:state, :open_projects] == %w[a b c]}).once
298
+ @plug.restore_session hash
299
+ end
300
+
301
+ end
302
+
303
+ describe '#with' do
304
+
305
+ describe ', when the @force_restore_cursor_position instance variable is nil' do
306
+
307
+ it 'calls the given block after setting the @force_restore_project_files instance variable to the :restore_cursor_position entry if the entry is a true value' do
308
+ restore_doc = nil
309
+ @plug.with(:restore_cursor_position => 'x'){restore_doc = @plug.instance_variable_get(:@force_restore_cursor_position)}
310
+ restore_doc.should == 'x'
311
+ end
312
+
313
+ it 'calls the given block after setting the @force_restore_project_files instance variable to false if the :restore_cursor_position entry is given and is a false value' do
314
+ restore_doc = nil
315
+ @plug.with(:restore_cursor_position => false){restore_doc = @plug.instance_variable_get(:@force_restore_cursor_position)}
316
+ restore_doc.should == false
317
+ restore_doc = nil
318
+ @plug.instance_variable_set :@force_restore_cursor_position, nil
319
+ @plug.with(:restore_cursor_position => nil){restore_doc = @plug.instance_variable_get(:@force_restore_cursor_position)}
320
+ restore_doc.should == false
321
+ end
322
+
323
+ it 'calls the block without changing the @force_restore_cursor_position instance variable if the :restore_cursor_position entry isn\'t given' do
324
+ restore_doc = true
325
+ @plug.with({}){restore_doc = @plug.instance_variable_get(:@force_restore_cursor_position)}
326
+ restore_doc.should be_nil
327
+ end
328
+
329
+ it 'sets the @force_restore_cursor_position back to nil after executing the block, even if the block raises an exception' do
330
+ @plug.with(:restore_cursor_position => true){@plug.instance_variable_get(:@force_restore_cursor_position).should be_true}
331
+ @plug.instance_variable_get(:@force_restore_cursor_position).should be_nil
332
+ @plug.with(:restore_cursor_position => false){@plug.instance_variable_get(:@force_restore_cursor_position).should == false}
333
+ @plug.instance_variable_get(:@force_restore_cursor_position).should be_nil
334
+ begin @plug.with(:restore_cursor_position => true){raise Exception}
335
+ rescue Exception
336
+ end
337
+ @plug.instance_variable_get(:@force_restore_cursor_position).should be_nil
338
+ end
339
+
340
+ end
341
+
342
+ describe ', when the @force_restore_cursor_position instance variable is not nil' do
343
+
344
+ describe ' and the :force entry isn\'t true' do
345
+
346
+ it 'calls the block without changing the value of the @force_restore_cursor_position instance variable' do
347
+ restore = nil
348
+ @plug.instance_variable_set(:@force_restore_cursor_position, 'x')
349
+ @plug.with(:restore_cursor_position => 'y'){restore = @plug.instance_variable_get(:@force_restore_cursor_position)}
350
+ restore.should == 'x'
351
+ end
352
+
353
+ end
354
+
355
+ describe ' and the :force entry is true' do
356
+
357
+ before do
358
+ @plug.instance_variable_set :@force_restore_cursor_position, 'y'
359
+ end
360
+
361
+ it 'calls the given block after setting the @force_restore_project_files instance variable to the :restore_cursor_position entry if the entry is a true value' do
362
+ restore_doc = nil
363
+ @plug.with(:restore_cursor_position => 'x', :force => true){restore_doc = @plug.instance_variable_get(:@force_restore_cursor_position)}
364
+ restore_doc.should == 'x'
365
+ end
366
+
367
+ it 'calls the given block after setting the @force_restore_project_files instance variable to false if the :restore_cursor_position entry is given and is a false value' do
368
+ restore_doc = nil
369
+ @plug.with(:restore_cursor_position => false, :force => true){restore_doc = @plug.instance_variable_get(:@force_restore_cursor_position)}
370
+ restore_doc.should == false
371
+ restore_doc = nil
372
+ @plug.instance_variable_set :@force_restore_cursor_position, nil
373
+ @plug.with(:restore_cursor_position => nil, :force => true){restore_doc = @plug.instance_variable_get(:@force_restore_cursor_position)}
374
+ restore_doc.should == false
375
+ end
376
+
377
+ it 'calls the block without changing the @force_restore_cursor_position instance variable if the :restore_cursor_position entry isn\'t given' do
378
+ restore_doc = true
379
+ @plug.with({:force => true}){restore_doc = @plug.instance_variable_get(:@force_restore_cursor_position)}
380
+ restore_doc.should == 'y'
381
+ end
382
+
383
+ it 'sets the @force_restore_cursor_position back to the original value after executing the block, even if the block raises an exception' do
384
+ @plug.with(:restore_cursor_position => true, :force => true){@plug.instance_variable_get(:@force_restore_cursor_position).should be_true}
385
+ @plug.instance_variable_get(:@force_restore_cursor_position).should == 'y'
386
+ @plug.with(:restore_cursor_position => false, :force => true){@plug.instance_variable_get(:@force_restore_cursor_position).should == false}
387
+ @plug.instance_variable_get(:@force_restore_cursor_position).should == 'y'
388
+ begin @plug.with(:restore_cursor_position => true, :force => true){raise Exception}
389
+ rescue Exception
390
+ end
391
+ @plug.instance_variable_get(:@force_restore_cursor_position).should == 'y'
392
+ end
393
+
394
+ end
395
+
396
+ end
397
+
398
+ describe ', when the @force_restore_cursor_position instance variable is nil' do
399
+
400
+ it 'calls the given block after setting the @force_restore_project_files instance variable to the :restore_cursor_position entry if the entry is a true value' do
401
+ restore_doc = nil
402
+ @plug.with(:restore_cursor_position => 'x'){restore_doc = @plug.instance_variable_get(:@force_restore_cursor_position)}
403
+ restore_doc.should == 'x'
404
+ end
405
+
406
+ it 'calls the given block after setting the @force_restore_project_files instance variable to false if the :restore_cursor_position entry is given and is a false value' do
407
+ restore_doc = nil
408
+ @plug.with(:restore_cursor_position => false){restore_doc = @plug.instance_variable_get(:@force_restore_cursor_position)}
409
+ restore_doc.should == false
410
+ restore_doc = nil
411
+ @plug.instance_variable_set :@force_restore_cursor_position, nil
412
+ @plug.with(:restore_cursor_position => nil){restore_doc = @plug.instance_variable_get(:@force_restore_cursor_position)}
413
+ restore_doc.should == false
414
+ end
415
+
416
+ it 'calls the block without changing the @force_restore_cursor_position instance variable if the :restore_cursor_position entry isn\'t given' do
417
+ restore_doc = true
418
+ @plug.with({}){restore_doc = @plug.instance_variable_get(:@force_restore_cursor_position)}
419
+ restore_doc.should be_nil
420
+ end
421
+
422
+ it 'sets the @force_restore_cursor_position back to nil after executing the block, even if the block raises an exception' do
423
+ @plug.with(:restore_cursor_position => true){@plug.instance_variable_get(:@force_restore_cursor_position).should be_true}
424
+ @plug.instance_variable_get(:@force_restore_cursor_position).should be_nil
425
+ @plug.with(:restore_cursor_position => false){@plug.instance_variable_get(:@force_restore_cursor_position).should == false}
426
+ @plug.instance_variable_get(:@force_restore_cursor_position).should be_nil
427
+ begin @plug.with(:restore_cursor_position => true){raise Exception}
428
+ rescue Exception
429
+ end
430
+ @plug.instance_variable_get(:@force_restore_cursor_position).should be_nil
431
+ end
432
+
433
+ end
434
+
435
+ describe ', when the @force_restore_project_files instance variable is not nil' do
436
+
437
+ describe ' and the :force entry isn\'t true' do
438
+
439
+ it 'calls the block without changing the value of the @force_restore_project_files instance variable' do
440
+ restore = nil
441
+ @plug.instance_variable_set(:@force_restore_project_files, 'x')
442
+ @plug.with(:restore_project_files => 'y'){restore = @plug.instance_variable_get(:@force_restore_project_files)}
443
+ restore.should == 'x'
444
+ end
445
+
446
+ end
447
+
448
+ describe ' and the :force entry is true' do
449
+
450
+ before do
451
+ @plug.instance_variable_set :@force_restore_project_files, 'y'
452
+ end
453
+
454
+ it 'calls the given block after setting the @force_restore_project_files instance variable to the :restore_project_files entry if the entry is a true value' do
455
+ restore_prj = nil
456
+ @plug.with(:restore_project_files => 'x', :force => true){restore_prj = @plug.instance_variable_get(:@force_restore_project_files)}
457
+ restore_prj.should == 'x'
458
+ end
459
+
460
+ it 'calls the given block after setting the @force_restore_project_files instance variable to false if the :restore_project_files entry is given and is a false value' do
461
+ restore_prj = nil
462
+ @plug.with(:restore_project_files => false, :force => true){restore_prj = @plug.instance_variable_get(:@force_restore_project_files)}
463
+ restore_prj.should == false
464
+ restore_prj = nil
465
+ @plug.instance_variable_set :@force_restore_project_files, nil
466
+ @plug.with(:restore_project_files => nil, :force => true){restore_prj = @plug.instance_variable_get(:@force_restore_project_files)}
467
+ restore_prj.should == false
468
+ end
469
+
470
+ it 'calls the block without changing the @force_restore_project_files instance variable if the :restore_project_files entry isn\'t given' do
471
+ restore_prj = true
472
+ @plug.with({:force => true}){restore_prj = @plug.instance_variable_get(:@force_restore_project_files)}
473
+ restore_prj.should == 'y'
474
+ end
475
+
476
+ it 'sets the @force_restore_project_files back to the original value after executing the block, even if the block raises an exception' do
477
+ @plug.with(:restore_project_files => true, :force => true){@plug.instance_variable_get(:@force_restore_project_files).should be_true}
478
+ @plug.instance_variable_get(:@force_restore_project_files).should == 'y'
479
+ @plug.with(:restore_project_files => false, :force => true){@plug.instance_variable_get(:@force_restore_project_files).should == false}
480
+ @plug.instance_variable_get(:@force_restore_project_files).should == 'y'
481
+ begin @plug.with(:restore_project_files => true, :force => true){raise Exception}
482
+ rescue Exception
483
+ end
484
+ @plug.instance_variable_get(:@force_restore_project_files).should == 'y'
485
+ end
486
+
487
+ end
488
+
489
+ end
490
+
491
+ end
492
+
493
+ describe '#restore_document' do
494
+
495
+ it 'calls the document\'s state extension\'s restore method' do
496
+ ext = flexmock('extension'){|m| m.should_receive(:restore).once}
497
+ doc = flexmock('doc'){|m| m.should_receive(:extension).once.with(:state).and_return ext}
498
+ @plug.restore_document doc
499
+ end
500
+
501
+ end
502
+
503
+ describe '#restore_project' do
504
+
505
+ it 'calls the project\'s state extension\'s restore method' do
506
+ ext = flexmock('extension'){|m| m.should_receive(:restore).once}
507
+ prj = flexmock('prj'){|m| m.should_receive(:extension).once.with(:state).and_return ext}
508
+ @plug.restore_project prj
509
+ end
510
+
511
+ end
512
+
513
+ describe '#restore_projects' do
514
+
515
+ before do
516
+ @projects = flexmock('projects'){|m| m.should_ignore_missing}
517
+ flexmock(Ruber).should_receive(:[]).with(:projects).and_return(@projects).by_default
518
+ @mw = flexmock{|m| m.should_ignore_missing}
519
+ flexmock(Ruber).should_receive(:[]).with(:main_window).and_return(@mw).by_default
520
+ end
521
+
522
+ it 'closes all projects' do
523
+ prjs = 3.times.map{|i| flexmock(i.to_s)}
524
+ prjs.each{|pr| @projects.should_receive(:close_project).with(pr).once}
525
+ @projects.should_receive(:to_a).once.and_return(prjs)
526
+ @plug.restore_projects
527
+ end
528
+
529
+ it 'uses the safe_open_project method of the main window to open the first entry of the state/open_projects setting' do
530
+ @config.should_receive(:[]).with(:state, :open_projects).once.and_return %w[/x/y/z.ruprj /a/b/c.ruprj]
531
+ prj = flexmock('project')
532
+ @mw.should_receive(:safe_open_project).once.with('/x/y/z.ruprj').and_return prj
533
+ @plug.restore_projects
534
+ end
535
+
536
+ it 'activates the project returned by safe_open_project' do
537
+ @config.should_receive(:[]).with(:state, :open_projects).once.and_return %w[/x/y/z.ruprj /a/b/c.ruprj]
538
+ prj = flexmock('project')
539
+ @mw.should_receive(:safe_open_project).once.with('/x/y/z.ruprj').and_return prj
540
+ @projects.should_receive(:current_project=).once.with(prj)
541
+ @plug.restore_projects
542
+ end
543
+
544
+ it 'doesn\'t attempt to activate the project if safe_open_project returned nil' do
545
+ @config.should_receive(:[]).with(:state, :open_projects).once.and_return %w[/x/y/z.ruprj /a/b/c.ruprj]
546
+ prj = flexmock('project')
547
+ @mw.should_receive(:safe_open_project).once.with('/x/y/z.ruprj').and_return nil
548
+ @projects.should_receive(:current_project=).never
549
+ lambda{@plug.restore_projects}.should_not raise_error
550
+ end
551
+
552
+ it 'does nothing if the state/open_projects setting is empty' do
553
+ @config.should_receive(:[]).with(:state, :open_projects).once.and_return []
554
+ prj = flexmock('project')
555
+ @projects.should_receive(:project).never
556
+ @projects.should_receive(:current_project=).never
557
+ @plug.restore_projects
558
+ end
559
+
560
+ it 'reads the settings from the argument, if given, rather than from the config object' do
561
+ @config.should_receive(:[]).never
562
+ h = {[:state, :open_projects] => ['/x/y/z.ruprj']}
563
+ def h.[] group, name
564
+ super [group, name]
565
+ end
566
+ prj = flexmock('project')
567
+ @mw.should_receive(:safe_open_project).once.with('/x/y/z.ruprj').and_return prj
568
+ @projects.should_receive(:current_project=).once.with(prj)
569
+ @plug.restore_projects h
570
+ end
571
+
572
+ end
573
+
574
+ describe '#restore_documents' do
575
+
576
+ before do
577
+ @mw = flexmock('main window'){|m| m.should_ignore_missing}
578
+ @docs = flexmock('documents'){|m| m.should_ignore_missing}
579
+ flexmock(Ruber).should_receive(:[]).with(:main_window).and_return(@mw).by_default
580
+ flexmock(Ruber).should_receive(:[]).with(:docs).and_return(@docs).by_default
581
+ end
582
+
583
+ it 'closes all open documents' do
584
+ @docs.should_receive(:close_all).once
585
+ @plug.restore_documents
586
+ end
587
+
588
+ it 'creates a new document for each entry in the state/open_documents from within a block passed to the main window\'s without_activating method' do
589
+ files = %w[/x/y/f1.rb /a/b/f2.rb /f3.rb]
590
+ @config.should_receive(:[]).with(:state, :open_documents).once.and_return files
591
+ @config.should_receive(:[]).with(:state, :active_document)
592
+ files.each{|f| @mw.should_receive(:editor_for!).once.with(f).ordered}
593
+ @mw.should_receive(:without_activating).once.with(FlexMock.on{|a| a.call || a.is_a?(Proc)})
594
+ @plug.restore_documents
595
+ end
596
+
597
+ it 'activates the document corresponding to the file specified in the state/active_document setting' do
598
+ files = %w[/x/y/f1.rb /a/b/f2.rb /f3.rb]
599
+ @config.should_receive(:[]).with(:state, :open_documents).once.and_return files
600
+ @config.should_receive(:[]).with(:state, :active_document).once.and_return files[1]
601
+ 3.times{|i| @mw.should_receive(:editor_for!).once.with(files[i])}
602
+ @mw.should_receive(:display_document).once.with(files[1])
603
+ @mw.should_receive(:without_activating).once.with(FlexMock.on{|a| a.call || a.is_a?(Proc)})
604
+ @plug.restore_documents
605
+ end
606
+
607
+ it 'it activates the last document if the state/active_document setting is nil or if it doesn\'t correspond to an existing document' do
608
+ files = %w[/x/y/f1.rb /a/b/f2.rb /f3.rb]
609
+ @config.should_receive(:[]).with(:state, :open_documents).twice.and_return files
610
+ @config.should_receive(:[]).with(:state, :active_document).once.and_return nil
611
+ @config.should_receive(:[]).with(:state, :active_document).once.and_return random_string
612
+ @mw.should_receive(:display_document).twice.with(files[-1])
613
+ @mw.should_receive(:without_activating).twice.with(FlexMock.on{|a| a.call || a.is_a?(Proc)})
614
+ @plug.restore_documents
615
+ @plug.restore_documents
616
+ end
617
+
618
+ it 'does nothing if the state/open_files entry is empty' do
619
+ @config.should_receive(:[]).with(:state, :open_documents).once.and_return []
620
+ lambda{@plug.restore_documents}.should_not raise_error
621
+ end
622
+
623
+ it 'reads the settings from the argument, if given, rather than from the config object' do
624
+ @config.should_receive(:[]).never
625
+ files = %w[/x/y/f1.rb /a/b/f2.rb /f3.rb]
626
+ files.each{|f| @mw.should_receive(:editor_for!).once.with(f).ordered}
627
+ @mw.should_receive(:without_activating).once.with(FlexMock.on{|a| a.call || a.is_a?(Proc)})
628
+ h = {[:state, :open_documents] => files, [:state, :active_document] => nil}
629
+ def h.[] group, name
630
+ super [group, name]
631
+ end
632
+ @plug.restore_documents h
633
+ end
634
+
635
+ end
636
+
637
+ describe 'restore' do
638
+
639
+ it 'calls the restore_projects method if the state/open_project setting is not empty' do
640
+ @config.should_receive(:[]).with(:state, :open_projects).and_return %w[/xyz/abc.ruprj]
641
+ flexmock(@plug).should_receive(:restore_projects).once.with(@config)
642
+ @plug.restore
643
+ end
644
+
645
+ it 'calls the restore_documents method if the state/open_projects setting is empty' do
646
+ @config.should_receive(:[]).with(:state, :open_projects).and_return []
647
+ flexmock(@plug).should_receive(:restore_documents).once.with(@config)
648
+ @plug.restore
649
+ end
650
+
651
+ it 'uses the argument, rather than the config object, if one is given' do
652
+ @config.should_receive(:[]).never
653
+ h = {[:state, :open_projects] => %w[/xyz/abc.ruprj]}
654
+ def h.[](group, name)
655
+ super [group, name]
656
+ end
657
+ flexmock(@plug).should_receive(:restore_projects).once.with(h)
658
+ @plug.restore h
659
+ h[[:state, :open_projects]] = []
660
+ flexmock(@plug).should_receive(:restore_documents).once.with(h)
661
+ @plug.restore h
662
+ end
663
+
664
+ end
665
+
666
+ describe 'restore_last_state' do
667
+
668
+ describe ', when the state/startup_behaviour option is :restore_all' do
669
+
670
+ it 'calls the restore method' do
671
+ @config.should_receive(:[]).with(:state, :startup_behaviour).once.and_return :restore_all
672
+ flexmock(@plug).should_receive(:restore).once
673
+ @plug.restore_last_state
674
+ end
675
+
676
+ end
677
+
678
+ describe ', when the state/startup_behaviour option is :restore_projects_only' do
679
+
680
+ it 'calls restore_project from within a with block with :restore_project_files set to false' do
681
+ @config.should_receive(:[]).with(:state, :startup_behaviour).once.and_return :restore_projects_only
682
+ flexmock(@plug).should_receive(:restore_projects).once
683
+ flexmock(@plug).should_receive(:with).once.with({:restore_project_files => false}, FlexMock.on{|a| a.call || a.is_a?(Proc)})
684
+ @plug.restore_last_state
685
+ end
686
+
687
+ end
688
+
689
+ describe ', when the state/startup_behaviour option is :restore_documents_only' do
690
+
691
+ it 'calls restore_documents' do
692
+ @config.should_receive(:[]).with(:state, :startup_behaviour).once.and_return :restore_documents_only
693
+ flexmock(@plug).should_receive(:restore_documents).once
694
+ @plug.restore_last_state
695
+ end
696
+
697
+ end
698
+
699
+ describe ', when the state/startup_behaviour option is :restore_nothing' do
700
+
701
+ it 'does nothing' do
702
+ @config.should_receive(:[]).with(:state, :startup_behaviour).once.and_return :restore_nothing
703
+ flexmock(@plug).should_receive(:with).never
704
+ flexmock(@plug).should_receive(:restore_projects).never
705
+ flexmock(@plug).should_receive(:restore_documents).never
706
+ flexmock(@plug).should_receive(:restore).never
707
+ @plug.restore_last_state
708
+ end
709
+
710
+ end
711
+
712
+ end
713
+
714
+ end
715
+
716
+ describe Ruber::State::DocumentExtension do
717
+
718
+ it 'inherits from Qt::Object' do
719
+ Ruber::State::DocumentExtension.ancestors.should include(Qt::Object)
720
+ end
721
+
722
+ it 'includes the Ruber::Extension module' do
723
+ Ruber::State::DocumentExtension.ancestors.should include(Ruber::Extension)
724
+ end
725
+
726
+ before do
727
+ @components = flexmock{|m| m.should_ignore_missing}
728
+ flexmock(Ruber).should_receive(:[]).with(:components).and_return(@components).by_default
729
+ @doc = Ruber::Document.new nil, __FILE__
730
+ @ext = Ruber::State::DocumentExtension.new @doc.own_project
731
+ @doc.own_project.add_extension :state, @ext
732
+ end
733
+
734
+ describe ', when created' do
735
+
736
+ it 'connects the document\'s view_created(QObject*, QObject*) signal to its auto_restore slot' do
737
+ flexmock(@ext).should_receive(:auto_restore).once
738
+ @doc.create_view
739
+ end
740
+
741
+ end
742
+
743
+ describe '#restore' do
744
+
745
+ before do
746
+ #Needed to avoid the need of creating a mock State plugin
747
+ @doc.disconnect SIGNAL('view_created(QObject*, QObject*)'), @ext
748
+ end
749
+
750
+ it 'moves the cursor to the position stored in the document\'s project state/cursor_position setting' do
751
+ view = @doc.create_view
752
+ flexmock(@doc.own_project).should_receive(:[]).with(:state, :cursor_position).once.and_return([100, 20])
753
+ flexmock(@doc.view).should_receive(:go_to).with(100, 20).once
754
+ @ext.restore
755
+ end
756
+
757
+ it 'does nothing if the document doesn\'t have a view' do
758
+ lambda{@ext.restore}.should_not raise_error
759
+ end
760
+
761
+ end
762
+
763
+ describe '#save_settings' do
764
+
765
+ before do
766
+ #Needed to avoid the need of creating a mock State plugin
767
+ @doc.disconnect SIGNAL('view_created(QObject*, QObject*)'), @ext
768
+ end
769
+
770
+ it 'stores an array containing the cursor position in the document\'s project state/cursor_position setting' do
771
+ view = @doc.create_view
772
+ flexmock(@doc.own_project).should_receive(:[]=).with(:state, :cursor_position, [100, 20]).once
773
+ cur = KTextEditor::Cursor.new(100, 20)
774
+ flexmock(@doc.view).should_receive(:cursor_position).once.and_return cur
775
+ @ext.save_settings
776
+ end
777
+
778
+ it 'uses [0,0] as cursor position if the document doesn\'t have any view' do
779
+ flexmock(@doc.own_project).should_receive(:[]=).with(:state, :cursor_position, [0, 0]).once
780
+ lambda{@ext.save_settings}.should_not raise_error
781
+ end
782
+
783
+ end
784
+
785
+ describe 'auto_restore' do
786
+
787
+ before do
788
+ @plug = Object.new
789
+ @plug.instance_variable_set :@force_restore_cursor_position, nil
790
+ flexmock(Ruber).should_receive(:[]).with(:state).and_return(@plug).by_default
791
+ end
792
+
793
+ it 'calls the restore method if the State plugins wants the curesor position restored' do
794
+ flexmock(@plug).should_receive(:restore_cursor_position?).once.and_return true
795
+ flexmock(@ext).should_receive(:restore).once
796
+ @ext.send :auto_restore
797
+ end
798
+
799
+ it 'does noting if the State plugins doesn\'t want the curesor position restored' do
800
+ flexmock(@plug).should_receive(:restore_cursor_position?).once.and_return false
801
+ flexmock(@ext).should_receive(:restore).never
802
+ @ext.send :auto_restore
803
+ end
804
+
805
+ end
806
+
807
+ end
808
+
809
+ describe Ruber::State::ProjectExtension do
810
+
811
+ it 'inherits from Qt::Object' do
812
+ Ruber::State::ProjectExtension.ancestors.should include(Qt::Object)
813
+ end
814
+
815
+ it 'includes the Ruber::Extension module' do
816
+ Ruber::State::ProjectExtension.ancestors.should include(Ruber::Extension)
817
+ end
818
+
819
+ before do
820
+ @dir = File.join Dir.tmpdir, random_string(10)
821
+ FileUtils.mkdir @dir
822
+ @components = flexmock{|m| m.should_ignore_missing}
823
+ @projects = Qt::Object.new
824
+ flexmock(Ruber).should_receive(:[]).with(:components).and_return(@components).by_default
825
+ flexmock(Ruber).should_receive(:[]).with(:projects).and_return(@projects).by_default
826
+ @prj = Ruber::Project.new 'Test', File.join(@dir, 'test.ruprj')
827
+ @ext = Ruber::State::ProjectExtension.new @prj
828
+ @prj.add_extension :state, @ext
829
+ end
830
+
831
+ after do
832
+ FileUtils.rm_rf @dir
833
+ end
834
+
835
+ describe ', when created' do
836
+
837
+ it 'connects the project\'s activated() signal to its auto_restore slot' do
838
+ flexmock(@ext).should_receive(:auto_restore).once
839
+ @prj.activate
840
+ end
841
+
842
+ end
843
+
844
+ describe '#restore' do
845
+
846
+ before do
847
+ @mw = flexmock('main window'){|m| m.should_ignore_missing}
848
+ @config = flexmock('config')
849
+ @docs = flexmock('docs'){|m| m.should_ignore_missing}
850
+ flexmock(Ruber).should_receive(:[]).with(:main_window).and_return(@mw).by_default
851
+ flexmock(Ruber).should_receive(:[]).with(:config).and_return(@config).by_default
852
+ flexmock(Ruber).should_receive(:[]).with(:docs).and_return(@docs).by_default
853
+ end
854
+
855
+ it 'calls the document list\'s close_all method' do
856
+ @docs.should_receive(:close_all).once
857
+ flexmock(@prj).should_receive(:[]).with(:state, :open_documents).once.and_return []
858
+ @ext.restore
859
+ end
860
+
861
+ it 'it calls the main_window\'s editor_for! for each entry in the project\'s state/open_documents setting from within a without_activating call' do
862
+ files = %w[/a.rb /b.rb /c.rb]
863
+ flexmock(@prj).should_receive(:[]).with(:state, :open_documents).once.and_return files
864
+ flexmock(@prj).should_receive(:[]).with(:state, :active_document).once.and_return nil
865
+ files.each{|f| @mw.should_receive(:editor_for!).with(f).once}
866
+ @mw.should_receive(:without_activating).once.with(FlexMock.on{|a| a.call || a.is_a?(Proc)})
867
+ @ext.restore
868
+ end
869
+
870
+ it 'activates the editor corresponding to the file in the project\'s state/active_document entry' do
871
+ files = %w[/a.rb /b.rb /c.rb]
872
+ flexmock(@prj).should_receive(:[]).with(:state, :open_documents).once.and_return files
873
+ flexmock(@prj).should_receive(:[]).with(:state, :active_document).once.and_return files[1]
874
+ @mw.should_receive(:without_activating).once.with(FlexMock.on{|a| a.call || a.is_a?(Proc)})
875
+ @mw.should_receive(:display_document).once.with files[1]
876
+ @ext.restore
877
+ end
878
+
879
+ it 'activates the editor corresponding to the last entry file in the project\'s state/open_documents entry if the state/active_documents entry is nil' do
880
+ files = %w[/a.rb /b.rb /c.rb]
881
+ editors = 3.times.map{|i| flexmock(i.to_s)}
882
+ flexmock(@prj).should_receive(:[]).with(:state, :open_documents).once.and_return files
883
+ flexmock(@prj).should_receive(:[]).with(:state, :active_document).once.and_return nil
884
+ @mw.should_receive(:without_activating).once.with(FlexMock.on{|a| a.call || a.is_a?(Proc)})
885
+ @mw.should_receive(:display_document).once.with files[-1]
886
+ @ext.restore
887
+ end
888
+
889
+ it 'activates the editor corresponding to the last entry file in the project\'s state/open_documents entry if the state/active_documents doesn\'t correspond to one of the open files' do
890
+ files = %w[/a.rb /b.rb /c.rb]
891
+ flexmock(@prj).should_receive(:[]).with(:state, :open_documents).once.and_return files
892
+ flexmock(@prj).should_receive(:[]).with(:state, :active_document).once.and_return '/d.rb'
893
+ @mw.should_receive(:without_activating).once.with(FlexMock.on{|a| a.call || a.is_a?(Proc)})
894
+ @mw.should_receive(:display_document).once.with files[-1]
895
+ @ext.restore
896
+ end
897
+
898
+ it 'doesn\'t open any editor if the project\'s state/open_documents entry is empty' do
899
+ files = []
900
+ flexmock(@prj).should_receive(:[]).with(:state, :open_documents).once.and_return files
901
+ flexmock(@prj).should_receive(:[]).with(:state, :active_document).and_return nil
902
+ @mw.should_receive(:editor_for!).never
903
+ @mw.should_receive(:editor_for).never
904
+ @mw.should_receive(:without_activating).never
905
+ @mw.should_receive(:activate_editor).never
906
+ @ext.restore
907
+ end
908
+
909
+ end
910
+
911
+ describe '#save_settings' do
912
+
913
+ before do
914
+ @mw = flexmock('main window'){|m| m.should_ignore_missing}
915
+ @docs = flexmock('docs'){|m| m.should_ignore_missing}
916
+ flexmock(Ruber).should_receive(:[]).with(:main_window).and_return(@mw).by_default
917
+ flexmock(Ruber).should_receive(:[]).with(:docs).and_return(@docs).by_default
918
+ end
919
+
920
+ it 'stores the paths of the open documents associated with a file in the project\'s state/open_documents entry' do
921
+ docs = %w[a b c].map{|i| flexmock(i.to_s, :path => "/#{i}")}
922
+ @docs.should_receive(:documents_with_file).once.and_return docs
923
+ flexmock(@prj).should_receive(:[]=).once.with :state, :open_documents, %w[a b c].map{|i| "/#{i}"}
924
+ flexmock(@prj).should_receive(:[]=)
925
+ @ext.save_settings
926
+ end
927
+
928
+ it 'stores an empty array in the project\'s state/open_documents entry if there\'s no open file or if none of them is associated with a document' do
929
+ @docs.should_receive(:documents_with_file).once.and_return []
930
+ flexmock(@prj).should_receive(:[]=).once.with :state, :open_documents, []
931
+ flexmock(@prj).should_receive(:[]=)
932
+ @ext.save_settings
933
+ end
934
+
935
+ it 'stores the path of the current document in the project\'s state/active_document entry' do
936
+ docs = %w[a b c].map{|i| flexmock(i.to_s, :path => "/#{i}")}
937
+ active = flexmock('doc', :path => '/b')
938
+ @docs.should_receive(:documents_with_file).once.and_return docs
939
+ @mw.should_receive(:current_document).once.and_return active
940
+ flexmock(@prj).should_receive(:[]=).once.with :state, :active_document, '/b'
941
+ flexmock(@prj).should_receive(:[]=)
942
+ @ext.save_settings
943
+ end
944
+
945
+ it 'stores nil in the project\'s state/active_document entry if there\'s no active document or the active document isn\'t associated with a file' do
946
+ docs = %w[a b c].map{|i| flexmock(i.to_s, :path => "/#{i}")}
947
+ active = flexmock('doc', :path => '')
948
+ @docs.should_receive(:documents_with_file).twice.and_return docs
949
+ @mw.should_receive(:current_document).once.and_return active
950
+ @mw.should_receive(:current_document).once.and_return nil
951
+ flexmock(@prj).should_receive(:[]=).twice.with :state, :active_document, nil
952
+ flexmock(@prj).should_receive(:[]=)
953
+ @ext.save_settings
954
+ @ext.save_settings
955
+ end
956
+
957
+ end
958
+
959
+ describe 'auto_restore' do
960
+
961
+ before do
962
+ @config = flexmock('config')
963
+ flexmock(Ruber).should_receive(:[]).with(:config).and_return(@config).by_default
964
+ @plug = Object.new
965
+ @plug.instance_variable_set :@force_restore_project_files, nil
966
+ flexmock(Ruber).should_receive(:[]).with(:state).and_return(@plug).by_default
967
+ end
968
+
969
+ it 'disconnects the project\'s activated() signal from the extension' do
970
+ flexmock(@plug).should_receive(:restore_project_files?).once.and_return false
971
+ @ext.send :auto_restore
972
+ flexmock(@ext).should_receive(:auto_restore).never
973
+ flexmock(@prj).instance_eval{emit activated}
974
+ end
975
+
976
+ it 'calls the restore method if the State plugins wants the project files restored' do
977
+ flexmock(@plug).should_receive(:restore_project_files?).once.and_return true
978
+ flexmock(@ext).should_receive(:restore).once
979
+ @ext.send :auto_restore
980
+ end
981
+
982
+ it 'does noting if the State plugins doesn\'t want the project_files restored' do
983
+ flexmock(@plug).should_receive(:restore_project_files?).once.and_return false
984
+ flexmock(@ext).should_receive(:restore).never
985
+ @ext.send :auto_restore
986
+ end
987
+
988
+
989
+ end
990
+
991
+ end