device_map 0.0.1 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,44 @@
1
+ require 'device_map'
2
+
3
+ RSpec.describe DeviceMap::Classifier do
4
+ describe '#find_device' do
5
+ let(:user_agent) { 'test' }
6
+
7
+ let(:classifier) do
8
+ described_class.instance
9
+ end
10
+
11
+ let(:device) do
12
+ DeviceMap::DeviceData::Device.new(id: 'device_id')
13
+ end
14
+
15
+ context 'when device is found' do
16
+ before do
17
+ pattern = DeviceMap::Pattern.new(user_agent, device.id, 1)
18
+ expect(classifier.patterns).to receive(:find) do
19
+ Set.new [pattern]
20
+ end
21
+ end
22
+
23
+ it 'returns device object' do
24
+ expect(classifier.devices).to receive(:find).with(device.id) { device }
25
+
26
+ found_device = classifier.find_device(user_agent)
27
+ expect(found_device).to eq device
28
+ end
29
+ end
30
+
31
+ context 'when device is not found' do
32
+ before do
33
+ expect(classifier.patterns).to receive(:find) do
34
+ Set.new
35
+ end
36
+ end
37
+
38
+ it 'returns unknown device object' do
39
+ found_device = classifier.find_device(user_agent)
40
+ expect(found_device).to eq DeviceMap::DeviceData::Device.unknown
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,65 @@
1
+ require 'device_map'
2
+
3
+ RSpec.describe DeviceMap::DeviceData::Builder do
4
+ let(:builder_node_class) { 'builder_node_class' }
5
+
6
+ let(:device_id) { 'device_id' }
7
+ let(:keywords) { ['keyword1', 'keyword2'] }
8
+
9
+ def builder
10
+ default_priority = 1
11
+ described_class.new(default_priority)
12
+ end
13
+
14
+ describe '.find' do
15
+ it 'returns builder object' do
16
+ builder_stub = double(:builder)
17
+ described_class.register(builder_stub, builder_node_class)
18
+
19
+ builder = described_class.find(builder_node_class)
20
+
21
+ expect(builder).to eq builder_stub
22
+ end
23
+
24
+ it 'raises exception if builder node class is unknown' do
25
+ expect do
26
+ described_class.find('unknown')
27
+ end.to raise_error(DeviceMap::DeviceData::Builder::BuilderNotFound)
28
+ end
29
+ end
30
+
31
+ describe DeviceMap::DeviceData::Builder::Simple do
32
+ before do
33
+ DeviceMap::DeviceData::Builder.register(
34
+ described_class, builder_node_class)
35
+ end
36
+
37
+ describe '#patterns' do
38
+ it 'maps single pattern object to each device keyword' do
39
+ patterns = builder.patterns(device_id, keywords)
40
+
41
+ expect(patterns.size).to eq keywords.size
42
+ pattern_keywords = patterns.flat_map(&:keywords)
43
+ expect(pattern_keywords).to eq keywords
44
+ end
45
+ end
46
+ end
47
+
48
+ describe DeviceMap::DeviceData::Builder::TwoStep do
49
+ before do
50
+ DeviceMap::DeviceData::Builder.register(
51
+ described_class, builder_node_class)
52
+ end
53
+
54
+ describe '#patterns' do
55
+ it 'maps all device keywords to single pattern object' do
56
+ patterns = builder.patterns(device_id, keywords)
57
+
58
+ expect(patterns.size).to eq 2
59
+ pattern_keywords = patterns.flat_map(&:keywords)
60
+ expect(pattern_keywords).to include(*keywords)
61
+ expect(pattern_keywords).to include(keywords.join)
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,26 @@
1
+ require 'device_map'
2
+
3
+ RSpec.describe DeviceMap::DeviceData::Device do
4
+ describe '.parse' do
5
+ it 'returns new instance of this class' do
6
+ properties = { id: 'iphone', vendor: 'Apple' }
7
+ device_node = generate_device_node(properties)
8
+ device = described_class.parse(device_node)
9
+
10
+ expect(device.id).to eq properties.fetch(:id)
11
+ expect(device.vendor).to eq properties.fetch(:vendor)
12
+ end
13
+
14
+ def generate_device_node(properties)
15
+ builder = Nokogiri::XML::Builder.new do |xml|
16
+ xml.device(id: properties.fetch(:id)) do
17
+ properties.each do |name, value|
18
+ xml.property(name: name, value: value)
19
+ end
20
+ end
21
+ end
22
+
23
+ builder.doc.child
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,37 @@
1
+ require 'device_map'
2
+
3
+ RSpec.describe DeviceMap::DeviceData::Devices do
4
+ describe '#find' do
5
+ it 'finds device by its id' do
6
+ device_stub = double(id: 'device_id')
7
+ devices = described_class.new(Array(device_stub))
8
+ device = devices.find(device_stub.id)
9
+ expect(device.id).to eq device_stub.id
10
+ end
11
+
12
+ it 'raises exception if device is not found' do
13
+ devices = described_class.new([])
14
+ expect do
15
+ devices.find('anything')
16
+ end.to raise_error(DeviceMap::DeviceData::Devices::DeviceNotFound)
17
+ end
18
+ end
19
+
20
+ describe '.parse' do
21
+ it 'returns new instance of this class' do
22
+ devices_xml = generate_devices_xml.to_xml
23
+ devices = described_class.parse(devices_xml)
24
+ expect(devices).to be_a(described_class)
25
+ end
26
+ end
27
+
28
+ def generate_devices_xml
29
+ Nokogiri::XML::Builder.new do |xml|
30
+ xml.ODDR do
31
+ xml.Devices do
32
+ xml.device
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,52 @@
1
+ require 'device_map'
2
+
3
+ RSpec.describe DeviceMap::DeviceData::Patterns do
4
+ let(:keyword) { 'keyword' }
5
+
6
+ let(:pattern) do
7
+ DeviceMap::Pattern.new(keyword, 'device_id', 1)
8
+ end
9
+
10
+ # FIXME: Bad specs
11
+ describe '.parse' do
12
+ it 'returns instance of patterns class' do
13
+ builder_stub = double(:builder, patterns: Array(pattern))
14
+ expect(DeviceMap::DeviceData::Builder).to receive(:find) { builder_stub }
15
+
16
+ openddr_builder = Nokogiri::XML::Builder.new do |xml|
17
+ xml.ODDR do
18
+ xml.Builders do
19
+ xml.builder do
20
+ xml.device do
21
+ xml.list do
22
+ xml.value_ 'test'
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+
30
+ patterns = described_class.parse(openddr_builder.to_xml)
31
+
32
+ expect(patterns).to be_a(described_class)
33
+ expect(patterns.find(keyword)).to include pattern
34
+ end
35
+ end
36
+
37
+ describe '#find' do
38
+ it 'returns list of patterns for the given keyword' do
39
+ patterns = described_class.new(Array(pattern))
40
+ search_results = patterns.find(keyword)
41
+
42
+ expect(search_results).to include pattern
43
+ end
44
+
45
+ it 'returns empty list if keyword is not found' do
46
+ all_patterns = []
47
+ patterns = described_class.new(all_patterns)
48
+ devices = patterns.find('anything')
49
+ expect(devices).to be_empty
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,10 @@
1
+ require 'device_map'
2
+
3
+ RSpec.describe DeviceMap do
4
+ describe '.classify' do
5
+ it 'returns device' do
6
+ device = described_class.classify('android')
7
+ expect(device).to be_a(DeviceMap::DeviceData::Device)
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,32 @@
1
+ require 'device_map'
2
+
3
+ RSpec.describe DeviceMap::Keyword do
4
+ describe '.normalize' do
5
+ it 'strips all non-alphanumeric characters' do
6
+ normalized_keywords = described_class.normalize ['test-123', 'test_123']
7
+ expect(normalized_keywords).to eq ['test123', 'test123']
8
+ end
9
+
10
+ it 'convers all characters to lower case' do
11
+ normalized_keywords = described_class.normalize ['Test', 'TEST']
12
+ expect(normalized_keywords).to eq ['test', 'test']
13
+ end
14
+
15
+ example do
16
+ normalized_keywords = described_class.normalize ['[Bb]lack.?[Bb]erry']
17
+ expect(normalized_keywords).to eq ['blackberry']
18
+ end
19
+ end
20
+
21
+ describe '.join' do
22
+ example do
23
+ joined_keywords = described_class.join ['test', '123']
24
+ expect(joined_keywords).to eq 'test123'
25
+ end
26
+
27
+ example do
28
+ joined_keywords = described_class.join ['test', 'test123']
29
+ expect(joined_keywords).to eq 'test123'
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,49 @@
1
+ require 'device_map'
2
+
3
+ RSpec.describe DeviceMap::Pattern do
4
+ let(:priority) { 1 }
5
+ let(:higher_priority) { priority + 1 }
6
+
7
+ let(:keyword) { 'keyword' }
8
+ let(:longer_keyword) { 'longer_keyword' }
9
+
10
+ let(:device_id) { 'device_id' }
11
+
12
+ it 'is comparable by keyword size' do
13
+ pattern1 = described_class.new(keyword, device_id, priority)
14
+ pattern2 = described_class.new(longer_keyword, device_id, priority)
15
+
16
+ expect(pattern1).to be < pattern2
17
+ end
18
+
19
+ it 'is comparable by priority' do
20
+ pattern1 = described_class.new(keyword, device_id, higher_priority)
21
+ pattern2 = described_class.new(longer_keyword, device_id, priority)
22
+
23
+ expect(pattern1).to be > pattern2
24
+ end
25
+
26
+ it 'can be equal to other pattern' do
27
+ pattern1 = described_class.new(keyword, device_id, priority)
28
+ pattern2 = described_class.new(keyword, device_id, priority)
29
+
30
+ expect(pattern1).to eq pattern2
31
+ end
32
+
33
+ describe '#matches?' do
34
+ let(:pattern) do
35
+ described_class.new(keyword, device_id, priority)
36
+ end
37
+
38
+ let(:other_keywords) { ['anything', 'else'] }
39
+
40
+ it 'returns true if given keywords contain all pattern keywords' do
41
+ given_keywords = other_keywords + pattern.keywords
42
+ expect(pattern.matches?(given_keywords)).to eq true
43
+ end
44
+
45
+ it 'returns false if given keywords do not contain all pattern keywords' do
46
+ expect(pattern.matches?(other_keywords)).to eq false
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,61 @@
1
+ require 'device_map'
2
+
3
+ RSpec.describe DeviceMap::Properties::DSL do
4
+ describe '.property' do
5
+ let(:model) do
6
+ Class.new do
7
+ include DeviceMap::Properties::DSL
8
+ end
9
+ end
10
+
11
+ it 'defines class attribute' do
12
+ property_value = 'test'
13
+ model.property :property
14
+ model_instance = model.new('property' => property_value)
15
+
16
+ expect(model_instance.property).to eq property_value
17
+ end
18
+
19
+ it 'allows to change attribute name' do
20
+ property_value = 'test'
21
+ model.property :property, attr_name: :other_property
22
+ model_instance = model.new('property' => property_value)
23
+ expect(model_instance.other_property).to eq property_value
24
+ end
25
+
26
+ it 'can cast property value to integer' do
27
+ model.property :property, type: :integer
28
+ model_instance = model.new('property' => '8')
29
+ expect(model_instance.property).to eq 8
30
+ end
31
+
32
+ it 'can cast property value to boolean' do
33
+ model.property :property, type: :boolean
34
+ model_instance = model.new('property' => 'false')
35
+ expect(model_instance.property).to eq false
36
+ end
37
+
38
+ it 'raises exception during initialization if given param is unknown' do
39
+ expect do
40
+ model.new('unknown_param' => 'value')
41
+ end.to raise_error(DeviceMap::Properties::UnknownProperty)
42
+ end
43
+
44
+ it 'is equal to other object if it has the same properties' do
45
+ property_value = 'test'
46
+ model.property :property
47
+ model_instance1 = model.new('property' => property_value)
48
+ model_instance2 = model.new('property' => property_value)
49
+
50
+ expect(model_instance1).to eq model_instance2
51
+ end
52
+
53
+ it 'is not equal to other object if it has different properties' do
54
+ model.property :property
55
+ model_instance1 = model.new('property' => 'test1')
56
+ model_instance2 = model.new('property' => 'test2')
57
+
58
+ expect(model_instance1).not_to eq model_instance2
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,46 @@
1
+ require 'device_map'
2
+
3
+ RSpec.describe DeviceMap::UserAgent do
4
+ describe '#keyword_ngrams' do
5
+ example do
6
+ user_agent = described_class.new('iphone')
7
+ ngrams = user_agent.keyword_ngrams(1)
8
+
9
+ expect(ngrams.size).to eq 1
10
+ expect(ngrams).to include ['iphone']
11
+ end
12
+
13
+ example do
14
+ user_agent = described_class.new('iPhone; U')
15
+ ngrams = user_agent.keyword_ngrams(2)
16
+
17
+ expect(ngrams.size).to eq 3
18
+ expect(ngrams).to include ['iphone']
19
+ expect(ngrams).to include ['iphone', 'u']
20
+ expect(ngrams).to include ['u']
21
+ end
22
+
23
+ example do
24
+ user_agent = described_class.new('Mozilla/5.0')
25
+ ngrams = user_agent.keyword_ngrams(3)
26
+
27
+ expect(ngrams.size).to eq 3
28
+ expect(ngrams).to include ['mozilla']
29
+ expect(ngrams).to include ['mozilla', '50']
30
+ expect(ngrams).to include ['50']
31
+ end
32
+
33
+ example do
34
+ user_agent = described_class.new('Mozilla/5.0 (iPhone)')
35
+ ngrams = user_agent.keyword_ngrams(3)
36
+
37
+ expect(ngrams.size).to eq 6
38
+ expect(ngrams).to include ['mozilla']
39
+ expect(ngrams).to include ['mozilla', '50']
40
+ expect(ngrams).to include ['mozilla', '50', 'iphone']
41
+ expect(ngrams).to include ['50']
42
+ expect(ngrams).to include ['50', 'iphone']
43
+ expect(ngrams).to include ['iphone']
44
+ end
45
+ end
46
+ end
metadata CHANGED
@@ -1,15 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: device_map
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Konstantin Papkovskiy
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-12-21 00:00:00.000000000 Z
11
+ date: 2015-01-17 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: nokogiri
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.6'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.6'
13
27
  - !ruby/object:Gem::Dependency
14
28
  name: bundler
15
29
  requirement: !ruby/object:Gem::Requirement
@@ -38,22 +52,97 @@ dependencies:
38
52
  - - "~>"
39
53
  - !ruby/object:Gem::Version
40
54
  version: '10.0'
41
- description: Ruby client for Apache DeviceMap
55
+ - !ruby/object:Gem::Dependency
56
+ name: rspec
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '3.1'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '3.1'
69
+ - !ruby/object:Gem::Dependency
70
+ name: pry
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '0.10'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '0.10'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rubocop
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '0.28'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '0.28'
97
+ description: |2
98
+ Ruby implementation of client for Apache DeviceMap repository
99
+ containing device information, images and other relevant
100
+ information for all sorts of mobile devices.
42
101
  email:
43
102
  - konstantin@papkovskiy.com
44
103
  executables: []
45
- extensions: []
104
+ extensions:
105
+ - ext/Rakefile
46
106
  extra_rdoc_files: []
47
107
  files:
48
108
  - ".gitignore"
109
+ - ".rspec"
110
+ - ".rubocop.yml"
111
+ - ".travis.yml"
49
112
  - Gemfile
50
113
  - LICENSE.txt
114
+ - README.md
115
+ - Rakefile
51
116
  - device_map.gemspec
117
+ - ext/Rakefile
52
118
  - lib/device_map.rb
119
+ - lib/device_map/classifier.rb
120
+ - lib/device_map/device_data/builder.rb
121
+ - lib/device_map/device_data/device.rb
122
+ - lib/device_map/device_data/devices.rb
123
+ - lib/device_map/device_data/patterns.rb
124
+ - lib/device_map/keyword.rb
125
+ - lib/device_map/pattern.rb
126
+ - lib/device_map/properties/dsl.rb
127
+ - lib/device_map/properties/property.rb
128
+ - lib/device_map/properties/types.rb
129
+ - lib/device_map/user_agent.rb
53
130
  - lib/device_map/version.rb
54
- homepage: ''
131
+ - lib/resources/BuilderDataSource.xml
132
+ - lib/resources/DeviceDataSource.xml
133
+ - spec/classifier_spec.rb
134
+ - spec/device_data/builder_spec.rb
135
+ - spec/device_data/device_spec.rb
136
+ - spec/device_data/devices_spec.rb
137
+ - spec/device_data/patterns_spec.rb
138
+ - spec/device_map_spec.rb
139
+ - spec/keyword_spec.rb
140
+ - spec/pattern_spec.rb
141
+ - spec/properties/dsl_spec.rb
142
+ - spec/user_agent_spec.rb
143
+ homepage: https://github.com/soylent/device_map
55
144
  licenses:
56
- - MIT
145
+ - Apache-2.0
57
146
  metadata: {}
58
147
  post_install_message:
59
148
  rdoc_options: []
@@ -71,8 +160,18 @@ required_rubygems_version: !ruby/object:Gem::Requirement
71
160
  version: '0'
72
161
  requirements: []
73
162
  rubyforge_project:
74
- rubygems_version: 2.2.2
163
+ rubygems_version: 2.4.5
75
164
  signing_key:
76
165
  specification_version: 4
77
166
  summary: Ruby client for Apache DeviceMap
78
- test_files: []
167
+ test_files:
168
+ - spec/classifier_spec.rb
169
+ - spec/device_data/builder_spec.rb
170
+ - spec/device_data/device_spec.rb
171
+ - spec/device_data/devices_spec.rb
172
+ - spec/device_data/patterns_spec.rb
173
+ - spec/device_map_spec.rb
174
+ - spec/keyword_spec.rb
175
+ - spec/pattern_spec.rb
176
+ - spec/properties/dsl_spec.rb
177
+ - spec/user_agent_spec.rb