fusuma 1.11.1 → 2.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (93) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +49 -7
  3. data/fusuma.gemspec +6 -16
  4. data/lib/fusuma.rb +91 -28
  5. data/lib/fusuma/config.rb +34 -62
  6. data/lib/fusuma/config/index.rb +39 -6
  7. data/lib/fusuma/config/searcher.rb +166 -0
  8. data/lib/fusuma/custom_process.rb +13 -0
  9. data/lib/fusuma/device.rb +22 -7
  10. data/lib/fusuma/environment.rb +6 -4
  11. data/lib/fusuma/hash_support.rb +40 -0
  12. data/lib/fusuma/libinput_command.rb +17 -21
  13. data/lib/fusuma/multi_logger.rb +2 -6
  14. data/lib/fusuma/plugin/base.rb +18 -15
  15. data/lib/fusuma/plugin/buffers/buffer.rb +3 -2
  16. data/lib/fusuma/plugin/buffers/gesture_buffer.rb +34 -25
  17. data/lib/fusuma/plugin/buffers/timer_buffer.rb +46 -0
  18. data/lib/fusuma/plugin/detectors/detector.rb +26 -5
  19. data/lib/fusuma/plugin/detectors/pinch_detector.rb +109 -58
  20. data/lib/fusuma/plugin/detectors/rotate_detector.rb +91 -50
  21. data/lib/fusuma/plugin/detectors/swipe_detector.rb +93 -56
  22. data/lib/fusuma/plugin/events/event.rb +5 -4
  23. data/lib/fusuma/plugin/events/records/context_record.rb +27 -0
  24. data/lib/fusuma/plugin/events/records/gesture_record.rb +9 -6
  25. data/lib/fusuma/plugin/events/records/index_record.rb +46 -14
  26. data/lib/fusuma/plugin/events/records/record.rb +1 -1
  27. data/lib/fusuma/plugin/events/records/text_record.rb +2 -1
  28. data/lib/fusuma/plugin/executors/command_executor.rb +21 -6
  29. data/lib/fusuma/plugin/executors/executor.rb +45 -3
  30. data/lib/fusuma/plugin/filters/filter.rb +1 -1
  31. data/lib/fusuma/plugin/filters/libinput_device_filter.rb +6 -7
  32. data/lib/fusuma/plugin/filters/libinput_timeout_filter.rb +2 -2
  33. data/lib/fusuma/plugin/inputs/input.rb +64 -8
  34. data/lib/fusuma/plugin/inputs/libinput_command_input.rb +19 -9
  35. data/lib/fusuma/plugin/inputs/timer_input.rb +63 -0
  36. data/lib/fusuma/plugin/manager.rb +22 -29
  37. data/lib/fusuma/plugin/parsers/libinput_gesture_parser.rb +10 -8
  38. data/lib/fusuma/plugin/parsers/parser.rb +8 -9
  39. data/lib/fusuma/string_support.rb +16 -0
  40. data/lib/fusuma/version.rb +1 -1
  41. data/spec/helpers/config_helper.rb +20 -0
  42. data/spec/lib/config/searcher_spec.rb +97 -0
  43. data/spec/lib/config_spec.rb +112 -0
  44. data/spec/lib/custom_process_spec.rb +28 -0
  45. data/spec/lib/device_spec.rb +98 -0
  46. data/spec/lib/dummy_config.yml +31 -0
  47. data/spec/lib/fusuma_spec.rb +103 -0
  48. data/spec/lib/libinput-list-devices_iberianpig-XPS-9360.txt +181 -0
  49. data/spec/lib/libinput-list-devices_magic_trackpad.txt +51 -0
  50. data/spec/lib/libinput-list-devices_razer_razer_blade.txt +252 -0
  51. data/spec/lib/libinput-list-devices_thejinx0r.txt +361 -0
  52. data/spec/lib/libinput-list-devices_unavailable.txt +36 -0
  53. data/spec/lib/libinput_command_spec.rb +167 -0
  54. data/spec/lib/plugin/base_spec.rb +74 -0
  55. data/spec/lib/plugin/buffers/buffer_spec.rb +80 -0
  56. data/spec/lib/plugin/buffers/dummy_buffer.rb +20 -0
  57. data/spec/lib/plugin/buffers/gesture_buffer_spec.rb +172 -0
  58. data/spec/lib/plugin/detectors/detector_spec.rb +43 -0
  59. data/spec/lib/plugin/detectors/dummy_detector.rb +24 -0
  60. data/spec/lib/plugin/detectors/pinch_detector_spec.rb +119 -0
  61. data/spec/lib/plugin/detectors/rotate_detector_spec.rb +125 -0
  62. data/spec/lib/plugin/detectors/swipe_detector_spec.rb +118 -0
  63. data/spec/lib/plugin/events/event_spec.rb +30 -0
  64. data/spec/lib/plugin/events/records/gesture_record_spec.rb +22 -0
  65. data/spec/lib/plugin/events/records/record_spec.rb +31 -0
  66. data/spec/lib/plugin/events/records/text_record_spec.rb +26 -0
  67. data/spec/lib/plugin/executors/command_executor_spec.rb +57 -0
  68. data/spec/lib/plugin/executors/executor_spec.rb +160 -0
  69. data/spec/lib/plugin/filters/filter_spec.rb +92 -0
  70. data/spec/lib/plugin/filters/libinput_filter_spec.rb +120 -0
  71. data/spec/lib/plugin/inputs/input_spec.rb +70 -0
  72. data/spec/lib/plugin/inputs/libinput_command_input_spec.rb +120 -0
  73. data/spec/lib/plugin/inputs/timer_input_spec.rb +40 -0
  74. data/spec/lib/plugin/manager_spec.rb +27 -0
  75. data/spec/lib/plugin/parsers/parser_spec.rb +45 -0
  76. data/spec/spec_helper.rb +20 -0
  77. metadata +90 -167
  78. data/.github/FUNDING.yml +0 -8
  79. data/.github/ISSUE_TEMPLATE/bug_report.md +0 -32
  80. data/.github/ISSUE_TEMPLATE/feature_request.md +0 -17
  81. data/.github/pull_request_template.md +0 -9
  82. data/.github/stale.yml +0 -18
  83. data/.gitignore +0 -17
  84. data/.reek.yml +0 -96
  85. data/.rspec +0 -2
  86. data/.rubocop.yml +0 -37
  87. data/.rubocop_todo.yml +0 -40
  88. data/.travis.yml +0 -11
  89. data/CHANGELOG.md +0 -456
  90. data/CODE_OF_CONDUCT.md +0 -74
  91. data/CONTRIBUTING.md +0 -72
  92. data/Gemfile +0 -6
  93. data/Rakefile +0 -15
@@ -0,0 +1,36 @@
1
+ Device: AT Translated Set 2 keyboard
2
+ Kernel: /dev/input/event4
3
+ Group: 9
4
+ Seat: seat0, default
5
+ Capabilities: keyboard
6
+ Tap-to-click: n/a
7
+ Tap-and-drag: n/a
8
+ Tap drag lock: n/a
9
+ Left-handed: n/a
10
+ Nat.scrolling: n/a
11
+ Middle emulation: n/a
12
+ Calibration: n/a
13
+ Scroll methods: none
14
+ Click methods: none
15
+ Disable-w-typing: n/a
16
+ Accel profiles: n/a
17
+ Rotation: n/a
18
+
19
+ Device: Dell WMI hotkeys
20
+ Kernel: /dev/input/event9
21
+ Group: 10
22
+ Seat: seat0, default
23
+ Capabilities: keyboard
24
+ Tap-to-click: n/a
25
+ Tap-and-drag: n/a
26
+ Tap drag lock: n/a
27
+ Left-handed: n/a
28
+ Nat.scrolling: n/a
29
+ Middle emulation: n/a
30
+ Calibration: n/a
31
+ Scroll methods: none
32
+ Click methods: none
33
+ Disable-w-typing: n/a
34
+ Accel profiles: n/a
35
+ Rotation: n/a
36
+
@@ -0,0 +1,167 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+ require './lib/fusuma/libinput_command'
5
+
6
+ module Fusuma
7
+ RSpec.describe LibinputCommand do
8
+ let(:libinput_command) { described_class.new(libinput_options: libinput_options, commands: commands) }
9
+ let(:libinput_options) { [] }
10
+ let(:commands) { {} }
11
+ describe '#version' do
12
+ subject { libinput_command.version }
13
+
14
+ context 'when libinput-list-device is available' do
15
+ before do
16
+ allow(libinput_command).to receive('which')
17
+ .with('libinput') { false }
18
+ allow(libinput_command).to receive('which')
19
+ .with('libinput-list-devices') { true }
20
+ allow_any_instance_of(Kernel).to receive(:`)
21
+ .with('libinput-list-devices --version') { "1.6.3\n" }
22
+ end
23
+
24
+ it { is_expected.to eq '1.6.3' }
25
+ it { expect(libinput_command.new_cli_option_available?).to be false }
26
+ end
27
+
28
+ context 'when libinput is available' do
29
+ before do
30
+ allow(libinput_command).to receive('which')
31
+ .with('libinput') { true }
32
+ allow(libinput_command).to receive('which')
33
+ .with('libinput-list-devices') { false }
34
+ allow_any_instance_of(Kernel).to receive(:`)
35
+ .with('libinput --version') { "1.8\n" }
36
+ end
37
+
38
+ it { is_expected.to eq '1.8' }
39
+ it { expect(libinput_command.new_cli_option_available?).to be true }
40
+ end
41
+
42
+ context 'when libinput command is not found' do
43
+ before do
44
+ allow(libinput_command).to receive('which')
45
+ .with('libinput') { false }
46
+ allow(libinput_command).to receive('which')
47
+ .with('libinput-list-devices') { false }
48
+ end
49
+
50
+ it 'shold print error and exit 1' do
51
+ expect(MultiLogger).to receive(:error)
52
+ expect { subject }.to raise_error(SystemExit)
53
+ end
54
+ end
55
+ end
56
+
57
+ describe '#new_cli_option_available?' do
58
+ subject { libinput_command.new_cli_option_available? }
59
+ context 'with NEW_CLI_OPTION_VERSION' do
60
+ before do
61
+ allow(libinput_command).to receive(:version)
62
+ .and_return(LibinputCommand::NEW_CLI_OPTION_VERSION)
63
+ end
64
+ it { is_expected.to eq true }
65
+ end
66
+ context 'without NEW_CLI_OPTION_VERSION' do
67
+ before do
68
+ allow(libinput_command).to receive(:version)
69
+ .and_return(LibinputCommand::NEW_CLI_OPTION_VERSION - 0.1)
70
+ end
71
+ it { is_expected.to eq false }
72
+ end
73
+ end
74
+
75
+ describe 'list_devices' do
76
+ subject { libinput_command.list_devices }
77
+ after { subject }
78
+
79
+ before do
80
+ dummy_io = StringIO.new('dummy')
81
+ io = StringIO.new('dummy output')
82
+ allow(POSIX::Spawn).to receive(:popen4).with(anything).and_return([nil, dummy_io, io, dummy_io])
83
+ allow(Process).to receive(:waitpid).and_return(nil)
84
+ end
85
+
86
+ context 'with the alternative command' do
87
+ let(:commands) { { list_devices_command: 'dummy_list_devices' } }
88
+
89
+ it 'should call dummy events' do
90
+ expect(POSIX::Spawn).to receive(:popen4).with(/dummy_list_devices/)
91
+ end
92
+ end
93
+
94
+ context 'with new cli version' do
95
+ before do
96
+ allow(libinput_command).to receive(:new_cli_option_available?)
97
+ .and_return(true)
98
+ end
99
+
100
+ it 'call `libinput list-devices`' do
101
+ command = 'libinput list-devices'
102
+ expect(POSIX::Spawn).to receive(:popen4)
103
+ .with(command)
104
+ end
105
+ end
106
+ context 'with old cli version' do
107
+ before do
108
+ allow(libinput_command).to receive(:new_cli_option_available?)
109
+ .and_return(false)
110
+ end
111
+
112
+ it 'call `libinput-list-devices`' do
113
+ command = 'libinput-list-devices'
114
+ expect(POSIX::Spawn).to receive(:popen4)
115
+ .with(command)
116
+ end
117
+ end
118
+ end
119
+
120
+ describe 'debug_events' do
121
+ subject { libinput_command.debug_events }
122
+ before do
123
+ dummy_io = StringIO.new('dummy')
124
+ allow(POSIX::Spawn).to receive(:popen4).with(anything).and_return([nil, dummy_io, dummy_io, dummy_io])
125
+ end
126
+
127
+ context 'with the alternative command' do
128
+ let(:commands) { { debug_events_command: 'dummy_debug_events' } }
129
+
130
+ it 'should call dummy events' do
131
+ expect(POSIX::Spawn).to receive(:popen4).with(/dummy_debug_events/).once
132
+ subject
133
+ end
134
+ end
135
+
136
+ context 'with new cli version' do
137
+ before do
138
+ allow(libinput_command)
139
+ .to receive(:new_cli_option_available?)
140
+ .and_return(true)
141
+ end
142
+
143
+ it 'should call `libinput debug-events`' do
144
+ command = 'libinput debug-events'
145
+ expect(POSIX::Spawn).to receive(:popen4)
146
+ .with("stdbuf -oL -- #{command}")
147
+ subject
148
+ end
149
+ end
150
+
151
+ context 'with old cli version' do
152
+ before do
153
+ allow(libinput_command)
154
+ .to receive(:new_cli_option_available?)
155
+ .and_return(false)
156
+ end
157
+
158
+ it 'should call `libinput-debug-events`' do
159
+ command = 'libinput-debug-events'
160
+ expect(POSIX::Spawn).to receive(:popen4)
161
+ .with("stdbuf -oL -- #{command}")
162
+ subject
163
+ end
164
+ end
165
+ end
166
+ end
167
+ end
@@ -0,0 +1,74 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+ require './lib/fusuma/plugin/base'
5
+ require './lib/fusuma/plugin/manager'
6
+
7
+ module Fusuma
8
+ module Plugin
9
+ class DummyPlugin < Base
10
+ def config_param_types
11
+ {
12
+ dummy_string: String,
13
+ dummy_list: Array,
14
+ dummy_bool: [TrueClass, FalseClass]
15
+ }
16
+ end
17
+ end
18
+
19
+ class DummyChildPlugin < DummyPlugin
20
+ end
21
+
22
+ RSpec.describe DummyPlugin do
23
+ before do
24
+ @dummy_plugin = DummyPlugin.new
25
+ @dummy_child_plugin = DummyChildPlugin.new
26
+
27
+ ConfigHelper.load_config_yml = <<-CONFIG
28
+ plugin:
29
+ dummy_plugin:
30
+ dummy_string: dummy
31
+ dummy_list:
32
+ - 1
33
+ - 2
34
+ - 3
35
+ dummy_bool: true
36
+ CONFIG
37
+ end
38
+
39
+ after do
40
+ Config.custom_path = nil
41
+ end
42
+ describe '.inherited' do
43
+ it 'should add required class to subclass on Manager' do
44
+ expect(Manager.plugins[Base.name]).to include(DummyPlugin)
45
+ end
46
+ end
47
+
48
+ describe '.plugins' do
49
+ it 'should list plugins' do
50
+ expect(DummyPlugin.plugins).to eq([DummyChildPlugin])
51
+ end
52
+ end
53
+
54
+ describe '#config_param_types' do
55
+ it 'should define class for config params' do
56
+ expect(@dummy_plugin.config_param_types).to be_a Hash
57
+ end
58
+ end
59
+
60
+ describe '#config_params' do
61
+ it 'should fetch options from config' do
62
+ expect(@dummy_plugin.config_params).to be_a Hash
63
+ expect(@dummy_plugin.config_params(:dummy_string)).to be_a String
64
+ end
65
+ end
66
+
67
+ describe '#config_index' do
68
+ it 'should return index' do
69
+ expect(@dummy_plugin.config_index).to be_a Config::Index
70
+ end
71
+ end
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,80 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ require './lib/fusuma/plugin/events/event'
6
+ require_relative './dummy_buffer'
7
+
8
+ module Fusuma
9
+ module Plugin
10
+ module Buffers
11
+ RSpec.describe DummyBuffer do
12
+ before do
13
+ @buffer = DummyBuffer.new
14
+ end
15
+
16
+ describe '#type' do
17
+ subject { @buffer.type }
18
+ it { is_expected.to eq 'dummy' }
19
+ end
20
+
21
+ describe '#buffer' do
22
+ it 'should buffer event' do
23
+ event = Events::Event.new(tag: 'dummy', record: 'dummy record')
24
+ expect(@buffer.buffer(event)).to eq [event]
25
+ expect(@buffer.events).to eq [event]
26
+ end
27
+
28
+ it 'should NOT buffer event' do
29
+ event = Events::Event.new(tag: 'SHOULD NOT BUFFER', record: 'dummy record')
30
+ @buffer.buffer(event)
31
+ expect(@buffer.events).to eq []
32
+ end
33
+ end
34
+
35
+ describe '#source' do
36
+ subject { @buffer.source }
37
+
38
+ it { is_expected.to eq DummyBuffer::DEFAULT_SOURCE }
39
+
40
+ context 'with config' do
41
+ around do |example|
42
+ @source = 'custom_event'
43
+
44
+ ConfigHelper.load_config_yml = <<~CONFIG
45
+ plugin:
46
+ buffers:
47
+ dummy_buffer:
48
+ source: #{@source}
49
+ CONFIG
50
+
51
+ example.run
52
+
53
+ Config.custom_path = nil
54
+ end
55
+
56
+ it { is_expected.to eq @source }
57
+ end
58
+ end
59
+
60
+ describe '#config_params' do
61
+ around do |example|
62
+ ConfigHelper.load_config_yml = <<~CONFIG
63
+ plugin:
64
+ buffers:
65
+ dummy_buffer:
66
+ dummy: dummy
67
+ CONFIG
68
+
69
+ example.run
70
+
71
+ Config.custom_path = nil
72
+ end
73
+
74
+ subject { @buffer.config_params }
75
+ it { is_expected.to eq(dummy: 'dummy') }
76
+ end
77
+ end
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ require './lib/fusuma/plugin/buffers/buffer'
4
+
5
+ module Fusuma
6
+ module Plugin
7
+ module Buffers
8
+ class DummyBuffer < Buffer
9
+ DEFAULT_SOURCE = 'dummy'
10
+
11
+ def config_param_types
12
+ {
13
+ source: String,
14
+ dummy: String
15
+ }
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,172 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ require './lib/fusuma/plugin/events/event'
6
+ require './lib/fusuma/plugin/events/records/gesture_record'
7
+ require './lib/fusuma/plugin/buffers/gesture_buffer'
8
+
9
+ module Fusuma
10
+ module Plugin
11
+ module Buffers
12
+ RSpec.describe GestureBuffer do
13
+ before do
14
+ @buffer = GestureBuffer.new
15
+ delta = Events::Records::GestureRecord::Delta.new(-1, 0, 0, 0, 0, 0)
16
+ @event_generator = lambda { |time = nil, status = 'updating'|
17
+ Events::Event.new(time: time,
18
+ tag: 'libinput_gesture_parser',
19
+ record: Events::Records::GestureRecord.new(
20
+ status: status,
21
+ gesture: 'SWIPE',
22
+ finger: 3,
23
+ delta: delta
24
+ ))
25
+ }
26
+ end
27
+
28
+ describe '#type' do
29
+ it { expect(@buffer.type).to eq 'gesture' }
30
+ end
31
+
32
+ describe '#buffer' do
33
+ it 'should buffer gesture event' do
34
+ event = @event_generator.call
35
+ @buffer.buffer(event)
36
+ expect(@buffer.events).to eq [event]
37
+ end
38
+
39
+ it 'should NOT buffer other event' do
40
+ event = Events::Event.new(tag: 'SHOULD NOT BUFFER', record: 'dummy record')
41
+ @buffer.buffer(event)
42
+ expect(@buffer.events).to eq []
43
+ end
44
+
45
+ it 'should buffer begin/end' do
46
+ begin_event = @event_generator.call(nil, 'begin')
47
+ @buffer.buffer(begin_event)
48
+ expect(@buffer.events).to eq [begin_event]
49
+ end_event = @event_generator.call(nil, 'end')
50
+ @buffer.buffer(end_event)
51
+ expect(@buffer.events).to eq [begin_event, end_event]
52
+ end
53
+ end
54
+
55
+ describe '#clear_expired' do
56
+ it 'should keep only events generated within 30 seconds' do
57
+ time = Time.now
58
+ event1 = @event_generator.call(time)
59
+ @buffer.buffer(event1)
60
+ event2 = @event_generator.call(time + 100)
61
+ event3 = @event_generator.call(time + 100)
62
+ @buffer.buffer(event2)
63
+ @buffer.buffer(event3)
64
+
65
+ @buffer.clear_expired(current_time: time + 100.1)
66
+
67
+ expect(@buffer.events).to eq [event2, event3]
68
+ end
69
+
70
+ context 'change seconds to keep' do
71
+ around do |example|
72
+ ConfigHelper.load_config_yml = <<~CONFIG
73
+ plugin:
74
+ buffers:
75
+ gesture_buffer:
76
+ seconds_to_keep: 0.3
77
+ CONFIG
78
+
79
+ example.run
80
+
81
+ Config.custom_path = nil
82
+ end
83
+
84
+ it 'should keep only events generated within 0.3 seconds' do
85
+ expect(@buffer.config_params).to eq(seconds_to_keep: 0.3)
86
+ time = Time.now
87
+ event1 = @event_generator.call(time)
88
+ @buffer.buffer(event1)
89
+ event2 = @event_generator.call(time + 0.1)
90
+ @buffer.buffer(event2)
91
+ event3 = @event_generator.call(time + 0.2)
92
+ @buffer.buffer(event3)
93
+ @buffer.clear_expired(current_time: time + 0.29)
94
+ expect(@buffer.events).to eq [event1, event2, event3]
95
+
96
+ @buffer.clear_expired(current_time: time + 0.3)
97
+ expect(@buffer.events).to eq [event2, event3]
98
+ end
99
+ end
100
+ end
101
+
102
+ describe '#source' do
103
+ it { expect(@buffer.source).to eq GestureBuffer::DEFAULT_SOURCE }
104
+
105
+ context 'with config' do
106
+ around do |example|
107
+ @source = 'custom_event'
108
+
109
+ ConfigHelper.load_config_yml = <<~CONFIG
110
+ plugin:
111
+ buffers:
112
+ gesture_buffer:
113
+ source: #{@source}
114
+ CONFIG
115
+
116
+ example.run
117
+
118
+ Config.custom_path = nil
119
+ end
120
+
121
+ it { expect(@buffer.source).to eq @source }
122
+ end
123
+ end
124
+
125
+ describe '#sum_attrs' do
126
+ it 'should calculate the sum of each attribute'
127
+ end
128
+
129
+ describe '#avg_attrs' do
130
+ it 'should calculate the average of each attribute'
131
+ end
132
+
133
+ describe '#finger' do
134
+ it 'should return number of fingers in gestures'
135
+ end
136
+
137
+ describe '#gesture' do
138
+ it 'should return string of gesture type'
139
+ end
140
+
141
+ describe '#empty?' do
142
+ context 'no gestures in buffer' do
143
+ before { @buffer.clear }
144
+ it { expect(@buffer.empty?).to be true }
145
+ end
146
+
147
+ context 'buffered some gestures' do
148
+ before { @buffer.buffer(@event_generator.call) }
149
+ it { expect(@buffer.empty?).to be false }
150
+ end
151
+ end
152
+
153
+ describe '#slect_by_events' do
154
+ context 'without block' do
155
+ it { expect(@buffer.select_by_events).to be_a Enumerator }
156
+ end
157
+
158
+ context 'with block' do
159
+ before do
160
+ @e1 = @event_generator.call(nil, 'hoge')
161
+ @e2 = @event_generator.call(nil, 'hoge')
162
+ @e3 = @event_generator.call(nil, 'fuga')
163
+ [@e1, @e2, @e3].each { |event| @buffer.buffer(event) }
164
+ end
165
+ it { expect(@buffer.select_by_events { |e| e.record.status == 'hoge' }).to be_a GestureBuffer }
166
+ it { expect(@buffer.select_by_events { |e| e.record.status == 'hoge' }.events).to eq [@e1, @e2] }
167
+ end
168
+ end
169
+ end
170
+ end
171
+ end
172
+ end