ffi-gphoto2 0.2.0
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.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/.rspec +2 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +90 -0
- data/Rakefile +6 -0
- data/examples/intervalometer.rb +12 -0
- data/examples/live_view.rb +21 -0
- data/ffi-gphoto2.gemspec +30 -0
- data/lib/ffi/gphoto2.rb +85 -0
- data/lib/ffi/gphoto2/camera.rb +12 -0
- data/lib/ffi/gphoto2/camera_abilities.rb +37 -0
- data/lib/ffi/gphoto2/camera_abilities_list.rb +15 -0
- data/lib/ffi/gphoto2/camera_capture_type.rb +8 -0
- data/lib/ffi/gphoto2/camera_driver_status.rb +9 -0
- data/lib/ffi/gphoto2/camera_event_type.rb +10 -0
- data/lib/ffi/gphoto2/camera_file.rb +28 -0
- data/lib/ffi/gphoto2/camera_file_access_type.rb +8 -0
- data/lib/ffi/gphoto2/camera_file_operation.rb +11 -0
- data/lib/ffi/gphoto2/camera_file_path.rb +9 -0
- data/lib/ffi/gphoto2/camera_file_type.rb +11 -0
- data/lib/ffi/gphoto2/camera_folder_operation.rb +10 -0
- data/lib/ffi/gphoto2/camera_list.rb +15 -0
- data/lib/ffi/gphoto2/camera_operation.rb +12 -0
- data/lib/ffi/gphoto2/camera_widget.rb +33 -0
- data/lib/ffi/gphoto2/camera_widget_type.rb +14 -0
- data/lib/ffi/gphoto2/entry.rb +9 -0
- data/lib/ffi/gphoto2/gp_context.rb +31 -0
- data/lib/ffi/gphoto2/gphoto_device_type.rb +7 -0
- data/lib/ffi/gphoto2_port.rb +31 -0
- data/lib/ffi/gphoto2_port/gp_port_info.rb +11 -0
- data/lib/ffi/gphoto2_port/gp_port_info_list.rb +14 -0
- data/lib/ffi/gphoto2_port/gp_port_result.rb +35 -0
- data/lib/ffi/gphoto2_port/gp_port_type.rb +12 -0
- data/lib/gphoto2.rb +41 -0
- data/lib/gphoto2/camera.rb +219 -0
- data/lib/gphoto2/camera_abilities.rb +44 -0
- data/lib/gphoto2/camera_abilities_list.rb +64 -0
- data/lib/gphoto2/camera_file.rb +69 -0
- data/lib/gphoto2/camera_file_path.rb +21 -0
- data/lib/gphoto2/camera_folder.rb +82 -0
- data/lib/gphoto2/camera_list.rb +43 -0
- data/lib/gphoto2/camera_widgets/camera_widget.rb +112 -0
- data/lib/gphoto2/camera_widgets/date_camera_widget.rb +19 -0
- data/lib/gphoto2/camera_widgets/menu_camera_widget.rb +4 -0
- data/lib/gphoto2/camera_widgets/radio_camera_widget.rb +41 -0
- data/lib/gphoto2/camera_widgets/range_camera_widget.rb +37 -0
- data/lib/gphoto2/camera_widgets/section_camera_widget.rb +4 -0
- data/lib/gphoto2/camera_widgets/text_camera_widget.rb +14 -0
- data/lib/gphoto2/camera_widgets/toggle_camera_widget.rb +18 -0
- data/lib/gphoto2/camera_widgets/window_camera_widget.rb +4 -0
- data/lib/gphoto2/context.rb +31 -0
- data/lib/gphoto2/entry.rb +38 -0
- data/lib/gphoto2/port_info.rb +70 -0
- data/lib/gphoto2/port_info_list.rb +46 -0
- data/lib/gphoto2/port_result.rb +7 -0
- data/lib/gphoto2/version.rb +3 -0
- data/spec/gphoto2/camera_abilities_list_spec.rb +45 -0
- data/spec/gphoto2/camera_abilities_spec.rb +38 -0
- data/spec/gphoto2/camera_file_path_spec.rb +27 -0
- data/spec/gphoto2/camera_file_spec.rb +71 -0
- data/spec/gphoto2/camera_folder_spec.rb +110 -0
- data/spec/gphoto2/camera_list_spec.rb +35 -0
- data/spec/gphoto2/camera_spec.rb +292 -0
- data/spec/gphoto2/camera_widgets/date_camera_widget_spec.rb +15 -0
- data/spec/gphoto2/camera_widgets/radio_camera_widget_spec.rb +31 -0
- data/spec/gphoto2/camera_widgets/range_camera_widget_spec.rb +27 -0
- data/spec/gphoto2/camera_widgets/text_camera_widget_spec.rb +15 -0
- data/spec/gphoto2/camera_widgets/toggle_camera_widget_spec.rb +21 -0
- data/spec/gphoto2/context_spec.rb +17 -0
- data/spec/gphoto2/entry_spec.rb +27 -0
- data/spec/gphoto2/port_info_list_spec.rb +33 -0
- data/spec/gphoto2/port_info_spec.rb +53 -0
- data/spec/spec_helper.rb +12 -0
- data/spec/support/shared_examples/camera_widget_examples.rb +89 -0
- metadata +194 -0
@@ -0,0 +1,71 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module GPhoto2
|
4
|
+
describe CameraFile do
|
5
|
+
let(:camera) { double('camera') }
|
6
|
+
let(:folder) { '/store_00010001' }
|
7
|
+
let(:name) { 'capt0100.jpg' }
|
8
|
+
let(:data_and_size) { ['data', 384] }
|
9
|
+
|
10
|
+
before do
|
11
|
+
CameraFile.any_instance.stub(:new)
|
12
|
+
CameraFile.any_instance.stub(:data_and_size).and_return(data_and_size)
|
13
|
+
end
|
14
|
+
|
15
|
+
describe '#preview' do
|
16
|
+
context 'when a folder and file are set' do
|
17
|
+
it 'returns false' do
|
18
|
+
file = CameraFile.new(camera, folder, name)
|
19
|
+
expect(file.preview?).to be_false
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
context 'when no folder or file is set' do
|
24
|
+
it 'returns true' do
|
25
|
+
file = CameraFile.new(camera)
|
26
|
+
expect(file.preview?).to be_true
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe '#save' do
|
32
|
+
let(:file) { CameraFile.new(camera, folder, name) }
|
33
|
+
let(:data) { data_and_size.first }
|
34
|
+
|
35
|
+
before do
|
36
|
+
File.stub(:binwrite)
|
37
|
+
end
|
38
|
+
|
39
|
+
context 'when a pathname is passed' do
|
40
|
+
it 'saves the data to the passed pathname' do
|
41
|
+
pathname = '/tmp/capt0100.jpg'
|
42
|
+
expect(File).to receive(:binwrite).with(pathname, data)
|
43
|
+
file.save(pathname)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
context 'when no arguments are passed' do
|
48
|
+
it 'saves the data to the working directory using file path name' do
|
49
|
+
expect(File).to receive(:binwrite).with(name, data)
|
50
|
+
file.save
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
describe '#data' do
|
56
|
+
it 'returns the data of the camera file' do
|
57
|
+
file = CameraFile.new(camera, folder, name)
|
58
|
+
file.stub(:data_and_size).and_return(data_and_size)
|
59
|
+
expect(file.data).to eq(data_and_size.first)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
describe '#size' do
|
64
|
+
it 'returns the size of the camera file' do
|
65
|
+
file = CameraFile.new(camera, folder, name)
|
66
|
+
file.stub(:data_and_size).and_return(data_and_size)
|
67
|
+
expect(file.size).to eq(data_and_size.last)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,110 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module GPhoto2
|
4
|
+
describe CameraFolder do
|
5
|
+
let(:camera) { double('camera') }
|
6
|
+
|
7
|
+
describe '#root?' do
|
8
|
+
it 'returns true if the folder is the root' do
|
9
|
+
folder = CameraFolder.new(camera, '/')
|
10
|
+
expect(folder).to be_root
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
describe '#name' do
|
15
|
+
context 'when the folder is the root' do
|
16
|
+
it 'returns /' do
|
17
|
+
folder = CameraFolder.new(camera, '/')
|
18
|
+
expect(folder.name).to eq('/')
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
context 'when the folder is not the root' do
|
23
|
+
it 'returns the current folder name' do
|
24
|
+
folder = CameraFolder.new(camera, '/store_00010001/DCIM')
|
25
|
+
expect(folder.name).to eq('DCIM')
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe '#folders' do
|
31
|
+
it 'returns a list of subfolders' do
|
32
|
+
folder = CameraFolder.new(camera)
|
33
|
+
|
34
|
+
folders = 2.times.map { folder }
|
35
|
+
folder.stub(:folder_list_folders).and_return(folders)
|
36
|
+
|
37
|
+
expect(folder.folders).to eq(folders)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
describe '#files' do
|
42
|
+
it 'returns a list of files in the folder' do
|
43
|
+
folder = CameraFolder.new(camera)
|
44
|
+
|
45
|
+
file = double('camera_file')
|
46
|
+
files = 2.times.map { file }
|
47
|
+
folder.stub(:folder_list_files).and_return(files)
|
48
|
+
|
49
|
+
expect(folder.files).to eq(files)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
describe '#cd' do
|
54
|
+
let(:folder) { CameraFolder.new(camera, '/store_00010001') }
|
55
|
+
|
56
|
+
context 'when passed "."' do
|
57
|
+
it 'returns self' do
|
58
|
+
expect(folder.cd('.')).to be(folder)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
context 'when passed ".."' do
|
63
|
+
it 'returns the parent folder' do
|
64
|
+
parent = folder.cd('..')
|
65
|
+
expect(parent.path).to eq('/')
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
context 'when passed a normal folder name' do
|
70
|
+
it 'returns a new folder changed to the new path' do
|
71
|
+
child = folder.cd('DCIM')
|
72
|
+
expect(child.path).to eq('/store_00010001/DCIM')
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
describe '#open' do
|
78
|
+
it 'returns a new CameraFile of a file in the folder' do
|
79
|
+
file = double('camera_file')
|
80
|
+
CameraFile.stub(:new).and_return(file)
|
81
|
+
|
82
|
+
folder = CameraFolder.new(camera)
|
83
|
+
expect(folder.open('capt0001.jpg')).to eq(file)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
describe '#up' do
|
88
|
+
context 'when the folder is root' do
|
89
|
+
it 'returns self' do
|
90
|
+
folder = CameraFolder.new(camera, '/')
|
91
|
+
expect(folder.up).to be(folder)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
context 'when the folder is not root' do
|
96
|
+
it 'returns the parent folder' do
|
97
|
+
folder = CameraFolder.new(camera, '/store_00010001')
|
98
|
+
expect(folder.up.path).to eq('/')
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
describe '#to_s' do
|
104
|
+
it 'returns the name of the folder' do
|
105
|
+
folder = CameraFolder.new(camera, '/store_00010001')
|
106
|
+
expect(folder.to_s).to eq('store_00010001')
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module GPhoto2
|
4
|
+
describe CameraList do
|
5
|
+
before do
|
6
|
+
CameraList.any_instance.stub(:new)
|
7
|
+
end
|
8
|
+
|
9
|
+
describe '#size' do
|
10
|
+
it 'returns the number of camera entries in the list' do
|
11
|
+
size = 2
|
12
|
+
|
13
|
+
list = CameraList.new
|
14
|
+
list.stub(:count).and_return(size)
|
15
|
+
|
16
|
+
expect(list.size).to eq(size)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
describe '#to_a' do
|
21
|
+
it 'returns an array of camera entries' do
|
22
|
+
size = 2
|
23
|
+
|
24
|
+
list = CameraList.new
|
25
|
+
list.stub(:size).and_return(size)
|
26
|
+
|
27
|
+
ary = list.to_a
|
28
|
+
|
29
|
+
expect(ary.size).to eq(size)
|
30
|
+
|
31
|
+
ary.each { |e| expect(e).to be_kind_of(Entry) }
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,292 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module GPhoto2
|
4
|
+
describe Camera do
|
5
|
+
let(:port) { double('entry', name: 'model', value: 'usb:250,006') }
|
6
|
+
|
7
|
+
describe '.all' do
|
8
|
+
let(:abilities_list) { double('camera_abilities_list') }
|
9
|
+
let(:camera_list) { double('camera_list') }
|
10
|
+
let(:camera) { Camera.new(port) }
|
11
|
+
|
12
|
+
before do
|
13
|
+
Context.stub(:stub)
|
14
|
+
CameraAbilitiesList.stub(:new).and_return(abilities_list)
|
15
|
+
abilities_list.stub(:detect).and_return(camera_list)
|
16
|
+
camera_list.stub(:to_a).and_return([port])
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'returns a list of device entries' do
|
20
|
+
list = Camera.all
|
21
|
+
expect(list).to be_kind_of(Array)
|
22
|
+
expect(list.first).to be_kind_of(Camera)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
describe '.first' do
|
27
|
+
context 'when devices are automatically detected' do
|
28
|
+
it 'returns a new Camera using the first entry' do
|
29
|
+
camera = Camera.new(port)
|
30
|
+
Camera.stub(:all).and_return([camera])
|
31
|
+
expect(Camera.first).to be_kind_of(Camera)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
context 'when no devices are detected' do
|
36
|
+
it 'raises a RuntimeError' do
|
37
|
+
Camera.stub(:all).and_return([])
|
38
|
+
expect { Camera.first }.to raise_error(RuntimeError)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
describe '.open' do
|
44
|
+
let(:camera) { double('camera') }
|
45
|
+
before { Camera.stub(:new).and_return(camera) }
|
46
|
+
|
47
|
+
context 'when a block is given' do
|
48
|
+
it 'yeilds a new camera instance' do
|
49
|
+
expect(Camera).to receive(:open).and_yield(camera)
|
50
|
+
Camera.open(port) { |c| }
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'finalizes the camera when the block terminates' do
|
54
|
+
expect(camera).to receive(:finalize)
|
55
|
+
Camera.open(port) { |c| }
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
context 'when no block is given' do
|
60
|
+
it 'returns a new camera instance' do
|
61
|
+
expect(Camera.open(port)).to eq(camera)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
describe '.where' do
|
67
|
+
it 'filters all detected cameras by model' do
|
68
|
+
cameras = %w[cheese toast wine].map { |model| double('camera', model: model) }
|
69
|
+
Camera.stub(:all).and_return(cameras)
|
70
|
+
expect(Camera.where(/e/)).to match_array([cameras[0], cameras[2]])
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
describe '#exit' do
|
75
|
+
it 'closes the camera connection' do
|
76
|
+
camera = Camera.new(port)
|
77
|
+
camera.stub(:_exit)
|
78
|
+
expect(camera).to receive(:_exit)
|
79
|
+
camera.exit
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
describe '#capture' do
|
84
|
+
let(:camera) { Camera.new(port) }
|
85
|
+
let(:path) { double('camera_file_path', folder: 'folder', name: 'name') }
|
86
|
+
|
87
|
+
before do
|
88
|
+
camera.stub(:_capture).and_return(path)
|
89
|
+
end
|
90
|
+
|
91
|
+
it 'saves the camera configuration' do
|
92
|
+
expect(camera).to receive(:save)
|
93
|
+
camera.capture
|
94
|
+
end
|
95
|
+
|
96
|
+
it 'returns a new CameraFile' do
|
97
|
+
expect(camera).to receive(:_capture)
|
98
|
+
expect(camera.capture).to be_kind_of(CameraFile)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
describe '#preview' do
|
103
|
+
let(:camera) { Camera.new(port) }
|
104
|
+
let(:file) { double('camera_file') }
|
105
|
+
|
106
|
+
before do
|
107
|
+
camera.stub(:save)
|
108
|
+
camera.stub(:capture_preview).and_return(file)
|
109
|
+
end
|
110
|
+
|
111
|
+
it 'saves the camera configuration' do
|
112
|
+
expect(camera).to receive(:save)
|
113
|
+
camera.preview
|
114
|
+
end
|
115
|
+
|
116
|
+
it 'returns a new CameraFile' do
|
117
|
+
expect(camera.preview).to eq(file)
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
describe '#wait' do
|
122
|
+
let(:camera) { Camera.new(port) }
|
123
|
+
let(:event) { :capture_complete }
|
124
|
+
|
125
|
+
before do
|
126
|
+
camera.stub(:wait_for_event).and_return(event)
|
127
|
+
end
|
128
|
+
|
129
|
+
it 'waits for a camera event' do
|
130
|
+
expect(camera).to receive(:wait_for_event)
|
131
|
+
camera.wait
|
132
|
+
end
|
133
|
+
|
134
|
+
it 'returns an event symbol' do
|
135
|
+
expect(camera.wait).to eq(event)
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
describe '#window' do
|
140
|
+
let(:camera) { Camera.new(port) }
|
141
|
+
let(:window) { double('camera_widget') }
|
142
|
+
|
143
|
+
it 'always returns the same CameraWidget instance' do
|
144
|
+
camera.stub(:get_config).and_return(window)
|
145
|
+
expect(camera.window).to eq(window)
|
146
|
+
expect(camera.window).to eq(window)
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
describe '#config' do
|
151
|
+
it 'returns a map of configuration widgets' do
|
152
|
+
camera = Camera.new(port)
|
153
|
+
window = double('camera_widget')
|
154
|
+
camera.stub(:window).and_return(window)
|
155
|
+
window.stub(:flatten).and_return({ 'iso' => window })
|
156
|
+
|
157
|
+
expect(camera.config).to eq({ 'iso' => window })
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
describe '#filesystem' do
|
162
|
+
let(:camera) { Camera.new(port) }
|
163
|
+
|
164
|
+
context 'when a path is passed' do
|
165
|
+
let(:path) { '/store_00010001' }
|
166
|
+
|
167
|
+
it 'assumes the path is absolute' do
|
168
|
+
fs = camera.filesystem(path[1..-1])
|
169
|
+
expect(fs.path).to eq(path)
|
170
|
+
end
|
171
|
+
|
172
|
+
it 'returns a folder at the path that was passed' do
|
173
|
+
fs = camera.filesystem(path)
|
174
|
+
expect(fs.path).to eq(path)
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
context 'when no path is passed' do
|
179
|
+
it 'returns a folder at the root of the filesystem' do
|
180
|
+
fs = camera.filesystem
|
181
|
+
expect(fs.path).to eq('/')
|
182
|
+
end
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
describe '#file' do
|
187
|
+
it 'retrieves a file from the camera' do
|
188
|
+
camera = Camera.new(port)
|
189
|
+
camera.stub(:file_get)
|
190
|
+
expect(camera).to receive(:file_get)
|
191
|
+
camera.file(double('camera_file'))
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
describe '#[]' do
|
196
|
+
let(:window) { double('camera_widget') }
|
197
|
+
|
198
|
+
let(:camera) do
|
199
|
+
camera = Camera.new(port)
|
200
|
+
camera.stub(:config).and_return({ 'iso' => window })
|
201
|
+
camera
|
202
|
+
end
|
203
|
+
|
204
|
+
context 'when the specified key exists' do
|
205
|
+
it 'returns a CameraWidget' do
|
206
|
+
expect(camera['iso']).to eq(window)
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
210
|
+
context 'when the specified key does not exist' do
|
211
|
+
it 'returns nil' do
|
212
|
+
expect(camera['shutterspeed2']).to be_nil
|
213
|
+
end
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
describe '#[]=' do
|
218
|
+
let(:window) do
|
219
|
+
window = double('camera_widget')
|
220
|
+
expect(window).to receive(:value=).with(400)
|
221
|
+
window
|
222
|
+
end
|
223
|
+
|
224
|
+
let(:camera) do
|
225
|
+
camera = Camera.new(port)
|
226
|
+
camera.stub(:[]).and_return(window)
|
227
|
+
camera
|
228
|
+
end
|
229
|
+
|
230
|
+
it "set a widget's value" do
|
231
|
+
camera['iso'] = 400
|
232
|
+
end
|
233
|
+
|
234
|
+
it 'marks the camera as dirty' do
|
235
|
+
camera['iso'] = 400
|
236
|
+
expect(camera).to be_dirty
|
237
|
+
end
|
238
|
+
|
239
|
+
it 'returns the passed value' do
|
240
|
+
expect(camera['iso'] = 400).to eq(400)
|
241
|
+
end
|
242
|
+
end
|
243
|
+
|
244
|
+
describe '#dirty?' do
|
245
|
+
context 'when the configuration changed' do
|
246
|
+
it 'returns true' do
|
247
|
+
camera = Camera.new(port)
|
248
|
+
camera.stub_chain(:[], :value=)
|
249
|
+
|
250
|
+
camera['iso'] = 400
|
251
|
+
|
252
|
+
expect(camera).to be_dirty
|
253
|
+
end
|
254
|
+
end
|
255
|
+
|
256
|
+
context 'when the configuration has not changed' do
|
257
|
+
it 'returns false' do
|
258
|
+
camera = Camera.new(port)
|
259
|
+
expect(camera).not_to be_dirty
|
260
|
+
end
|
261
|
+
end
|
262
|
+
end
|
263
|
+
|
264
|
+
describe '#save' do
|
265
|
+
let(:camera) do
|
266
|
+
camera = Camera.new(port)
|
267
|
+
camera.stub_chain(:[], :value=)
|
268
|
+
camera.stub(:set_config)
|
269
|
+
camera
|
270
|
+
end
|
271
|
+
|
272
|
+
context 'when the camera is marked as dirty' do
|
273
|
+
it 'returns true' do
|
274
|
+
camera['iso'] = 400
|
275
|
+
expect(camera.save).to be_true
|
276
|
+
end
|
277
|
+
|
278
|
+
it 'marks the camera as not dirty' do
|
279
|
+
camera['iso'] = 400
|
280
|
+
camera.save
|
281
|
+
expect(camera).not_to be_dirty
|
282
|
+
end
|
283
|
+
end
|
284
|
+
|
285
|
+
context 'when the camera is not marked as dirty' do
|
286
|
+
it 'returns false' do
|
287
|
+
expect(camera.save).to be_false
|
288
|
+
end
|
289
|
+
end
|
290
|
+
end
|
291
|
+
end
|
292
|
+
end
|