fit_parser 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. checksums.yaml +7 -0
  2. data/.document +5 -0
  3. data/.rspec +1 -0
  4. data/Gemfile +15 -0
  5. data/Gemfile.lock +105 -0
  6. data/LICENSE.txt +20 -0
  7. data/README.md +27 -0
  8. data/Rakefile +38 -0
  9. data/lib/fit_parser/file/data.rb +99 -0
  10. data/lib/fit_parser/file/definition.rb +120 -0
  11. data/lib/fit_parser/file/definitions.rb +705 -0
  12. data/lib/fit_parser/file/header.rb +18 -0
  13. data/lib/fit_parser/file/record.rb +37 -0
  14. data/lib/fit_parser/file/record_header.rb +27 -0
  15. data/lib/fit_parser/file/type.rb +41 -0
  16. data/lib/fit_parser/file/types.rb +954 -0
  17. data/lib/fit_parser/file.rb +29 -0
  18. data/lib/fit_parser/version.rb +3 -0
  19. data/lib/fit_parser.rb +19 -0
  20. data/spec/file/data_spec.rb +111 -0
  21. data/spec/file/definition_spec.rb +26 -0
  22. data/spec/file/definitions_spec.rb +81 -0
  23. data/spec/file/header_spec.rb +28 -0
  24. data/spec/file/record_header_spec.rb +20 -0
  25. data/spec/file/record_spec.rb +56 -0
  26. data/spec/file/type_spec.rb +99 -0
  27. data/spec/file/types_spec.rb +100 -0
  28. data/spec/file_spec.rb +21 -0
  29. data/spec/fit_spec.rb +10 -0
  30. data/spec/spec_helper.rb +19 -0
  31. data/spec/support/examples/file/full_file_with_wrong_crc.fit +0 -0
  32. data/spec/support/examples/file/header +0 -0
  33. data/spec/support/examples/file/header_14b.fit +0 -0
  34. data/spec/support/examples/record/data_record_2.fit +0 -0
  35. data/spec/support/examples/record/data_record_2bis.fit +0 -0
  36. data/spec/support/examples/record/definition_record +0 -0
  37. data/spec/support/examples/record/definition_record_2.fit +0 -0
  38. data/spec/support/examples/record/message/data_dynamic_fields.fit +0 -0
  39. data/spec/support/examples/record/message/data_field_array.fit +0 -0
  40. data/spec/support/examples/record/message/data_file_capabilities_activities.fit +0 -0
  41. data/spec/support/examples/record/message/data_file_capabilities_settings.fit +0 -0
  42. data/spec/support/examples/record/message/definition +0 -0
  43. data/spec/support/examples/record/message/definition_dynamic_fields.fit +0 -0
  44. data/spec/support/examples/record/message/definition_field_array.fit +0 -0
  45. data/spec/support/examples/record/message/definition_file_capabilities.fit +0 -0
  46. data/spec/support/examples/record/normal_header +1 -0
  47. metadata +230 -0
@@ -0,0 +1,29 @@
1
+ module FitParser
2
+ class File
3
+
4
+ def self.read(io)
5
+ new.read(io)
6
+ end
7
+
8
+ attr_reader :header, :records, :crc
9
+
10
+ def initialize
11
+ @records = []
12
+ end
13
+
14
+ def read(io)
15
+ @header = Header.read(io)
16
+
17
+ Record.clear_definitions!
18
+
19
+ while io.pos < @header.end_pos
20
+ @records << Record.read(io)
21
+ end
22
+
23
+ @crc = io.read(2)
24
+
25
+ self
26
+ end
27
+
28
+ end
29
+ end
@@ -0,0 +1,3 @@
1
+ module FitParser
2
+ VERSION = '0.0.1'
3
+ end
data/lib/fit_parser.rb ADDED
@@ -0,0 +1,19 @@
1
+ require 'bindata'
2
+ require 'active_support'
3
+ require 'active_support/core_ext/class'
4
+ require 'fit_parser/file'
5
+ require 'fit_parser/file/header'
6
+ require 'fit_parser/file/record'
7
+ require 'fit_parser/file/record_header'
8
+ require 'fit_parser/file/types'
9
+ require 'fit_parser/file/type'
10
+ require 'fit_parser/file/definition'
11
+ require 'fit_parser/file/data'
12
+ require 'fit_parser/file/definitions'
13
+ require 'fit_parser/version'
14
+
15
+ module FitParser
16
+ def self.load_file(path)
17
+ File.read ::File.open(path)
18
+ end
19
+ end
@@ -0,0 +1,111 @@
1
+ require 'spec_helper'
2
+
3
+ describe Fit::File::Data do
4
+ describe ".generate" do
5
+ context 'standard definition' do
6
+ let(:definition) do
7
+ Fit::File::Definition.read example_file('record/message/definition')
8
+ end
9
+
10
+ subject { described_class.generate(definition) }
11
+
12
+ its(:ancestors) { should include(BinData::Record) }
13
+ its("new.record_type") { should eq(:file_id) }
14
+ end
15
+
16
+ context 'definition with multiple time the same field' do
17
+ before :all do
18
+ @fields = Fit::File::Definitions.class_variable_get :@@fields
19
+ @dyn_fields = Fit::File::Definitions.class_variable_get :@@dyn_fields
20
+ # force a fake definition for scaling of arrays
21
+ Fit::File::Definitions.add_field 2, 2, "field_array", :type => 6, :scale => 10, :offset => 0
22
+ end
23
+
24
+ after :all do
25
+ Fit::File::Definitions.class_variable_set :@@fields, @fields
26
+ Fit::File::Definitions.class_variable_set :@@dyn_fields, @dyn_fields
27
+ end
28
+
29
+ before :each do
30
+ def_file = example_file('record/message/definition_field_array.fit')
31
+ data_file = example_file('record/message/data_field_array.fit')
32
+ definition = described_class.generate(Fit::File::Definition.read def_file)
33
+ @result = definition.read( data_file )
34
+ end
35
+
36
+ it "reads the entire record" do
37
+ # read first the record definition
38
+ expect(@result.raw_field_array).to be == [ 123456789, 987654321 ]
39
+ expect(@result.raw_field_4).to be == [ 1, 3 ]
40
+ expect(@result.raw_field_8).to be == 1539
41
+ expect(@result.raw_active_time_zone).to be == 0
42
+ end
43
+
44
+ it "does not apply the scale equal to 1 for integer" do
45
+ expect(@result.raw_active_time_zone).to be == 0
46
+ expect(@result.active_time_zone.to_s).to be_eql '0'
47
+ end
48
+
49
+ it "does not apply the scale equal to 1 for arrays" do
50
+ expect(@result.raw_field_4).to be == [ 1, 3 ]
51
+ expect(@result.field_4.to_s).to be_eql '[1, 3]'
52
+ end
53
+
54
+ it "does apply scale on each element of an array" do
55
+ expect(@result.raw_field_array).to be == [ 123456789, 987654321 ]
56
+ expect(@result.field_array.to_s).to be_eql '[12345678.9, 98765432.1]'
57
+ end
58
+ end
59
+
60
+ context 'definition with dynamic fields' do
61
+ before :each do
62
+ def_file = example_file('record/message/definition_dynamic_fields.fit')
63
+ data_file = example_file('record/message/data_dynamic_fields.fit')
64
+ definition = described_class.generate(Fit::File::Definition.read def_file)
65
+ @result = definition.read( data_file )
66
+ end
67
+
68
+ it 'uses dynamic field value' do
69
+ expect(@result.raw_product).to be == 1499
70
+ expect(@result.product).to be == 'swim'
71
+ end
72
+ end
73
+
74
+ context 'definition with non basic types' do
75
+ before :each do
76
+ def_file = example_file('record/message/definition_dynamic_fields.fit')
77
+ data_file = example_file('record/message/data_dynamic_fields.fit')
78
+ definition = described_class.generate(Fit::File::Definition.read def_file)
79
+ @result = definition.read( data_file )
80
+ end
81
+
82
+ it 'returns the real value' do
83
+ expect(@result.raw_type).to be == 1
84
+ expect(@result.type).to be == 'device'
85
+ end
86
+ end
87
+
88
+ context 'definition with bit field types' do
89
+ before :each do
90
+ def_file = example_file('record/message/definition_file_capabilities.fit')
91
+ @definition = described_class.generate(Fit::File::Definition.read def_file)
92
+ end
93
+
94
+ context 'when only 1 bit set' do
95
+ it 'returns the single value' do
96
+ res = @definition.read( example_file('record/message/data_file_capabilities_activities.fit') )
97
+ expect(res.raw_flags).to eq(2)
98
+ expect(res.flags).to eq('read')
99
+ end
100
+ end
101
+
102
+ context 'when several bits set' do
103
+ it 'returns the compound value' do
104
+ res = @definition.read( example_file('record/message/data_file_capabilities_settings.fit') )
105
+ expect(res.raw_flags).to eq(6)
106
+ expect(res.flags).to eq('read/write')
107
+ end
108
+ end
109
+ end
110
+ end
111
+ end
@@ -0,0 +1,26 @@
1
+ require 'spec_helper'
2
+
3
+ describe Fit::File::Definition do
4
+ context "given a sample definition message" do
5
+ describe ".read" do
6
+ subject do
7
+ described_class.read example_file('record/message/definition')
8
+ end
9
+
10
+ its(:architecture) { should == 0 }
11
+ its(:global_message_number) { should == 0 }
12
+ its(:field_count) { should == 6 }
13
+ it { expect(subject.fields.size).to eq(subject.field_count) }
14
+
15
+ its(:record_type) { should == :definition }
16
+ it 'returns the real type for fields' do
17
+ expect(subject.fields[0].real_type).to be == :uint32z
18
+ expect(subject.fields[1].real_type).to be == :date_time
19
+ expect(subject.fields[2].real_type).to be == :manufacturer
20
+ expect(subject.fields[3].real_type).to be == :uint16 # product
21
+ expect(subject.fields[4].real_type).to be == :uint16 # number
22
+ expect(subject.fields[5].real_type).to be == :file
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,81 @@
1
+ require 'spec_helper'
2
+
3
+ # we use undefined numbers for field otherwise we interfere
4
+ # with already defined fields in definitions.rb and test are
5
+ # not really independant of the code
6
+ describe Fit::File::Definitions do
7
+ describe ".add_field" do
8
+ before :all do
9
+ @fields = described_class.class_variable_get :@@fields
10
+ @dyn_fields = described_class.class_variable_get :@@dyn_fields
11
+ end
12
+
13
+ after :all do
14
+ Fit::File::Definitions.class_variable_set(:@@fields, @fields)
15
+ Fit::File::Definitions.class_variable_set(:@@dyn_fields, @dyn_fields)
16
+ end
17
+
18
+ context "without additional options" do
19
+ before :each do
20
+ Fit::File::Definitions.class_variable_set(:@@fields, Hash.new { |h,k| h[k]={} })
21
+ Fit::File::Definitions.class_variable_set(:@@dyn_fields, Hash.new { |h,k| h[k]={} })
22
+ described_class.add_field(999, 999, 'rspec_test')
23
+ end
24
+
25
+ it "adds field data" do
26
+ expect(described_class.get_field(999,999)).to be_a(Hash)
27
+ expect(described_class.get_field(999,999)).to eql({ :name => 'rspec_test'})
28
+ end
29
+
30
+ it 'raised an error for dynamic field data' do
31
+ expect { described_class.add_field(999, 999, 'rspec_test_dyn') }.to raise_error
32
+ end
33
+ end
34
+
35
+ context "with additional options" do
36
+ before :each do
37
+ Fit::File::Definitions.class_variable_set(:@@fields, Hash.new { |h,k| h[k]={} })
38
+ Fit::File::Definitions.class_variable_set(:@@dyn_fields, Hash.new { |h,k| h[k]={} })
39
+
40
+ described_class.add_field(999, 999, 'rspec_test', :scale => 100, :units => 'm')
41
+ described_class.add_field(999, 999, 'rspec_test_dyn', :type => 4, :scale => 10, :offset => 10, :ref_field_name => nil, :ref_field_values => nil)
42
+ end
43
+
44
+ it "adds field data" do
45
+ expect(described_class.get_field(999, 999)).to be_a(Hash)
46
+ expect(described_class.get_field(999, 999)).to eql({ :name => 'rspec_test', :scale => 100, :units => 'm'})
47
+ end
48
+
49
+ it 'adds dynamic field data' do
50
+ expect(described_class.get_dynamic_fields(999, 999)).to be_a(Hash)
51
+ expect(described_class.get_dynamic_fields(999, 999)).to eql({ :rspec_test_dyn => {:type => 4, :scale => 10, :offset => 10, :ref_field_name => nil, :ref_field_values => nil} })
52
+ end
53
+ end
54
+ end
55
+
56
+ describe ".get_field" do
57
+ it "returns nil if no field exists" do
58
+ expect(described_class.get_field(100,100)).to be_nil
59
+ end
60
+ end
61
+
62
+ describe '.get_dynamic_field' do
63
+ it 'returns nil if no dynamic field exists' do
64
+ described_class.add_field(100, 100, 'rspec')
65
+ expect(described_class.get_dynamic_fields(100, 100)).to be_nil
66
+ end
67
+ end
68
+
69
+ describe ".add_name" do
70
+ it "adds a name" do
71
+ described_class.add_name(20, 'record')
72
+ expect(described_class.get_name(20)).to eql('record')
73
+ end
74
+ end
75
+
76
+ describe ".get_name" do
77
+ it "returns nil if no name exists" do
78
+ expect(described_class.get_name(100)).to be_nil
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,28 @@
1
+ require 'spec_helper'
2
+
3
+ describe Fit::File::Header do
4
+ context "given a sample FIT header" do
5
+ subject do
6
+ described_class.read example_file('file/header')
7
+ end
8
+
9
+ its(:header_size) { should == 12 }
10
+ its(:protocol_version) { should == 16 }
11
+ its(:profile_version) { should == 64 }
12
+ its(:data_size) { should == 36069 }
13
+ its(:data_type) { should == ".FIT" }
14
+ end
15
+
16
+ context "given a sample header file of 14 bytes length" do
17
+ subject do
18
+ described_class.read example_file('file/header_14b.fit')
19
+ end
20
+
21
+ its(:header_size) { should == 14 }
22
+ its(:protocol_version) { should == 16 }
23
+ its(:profile_version) { should == 411 }
24
+ its(:data_size) { should == 325 }
25
+ its(:data_type) { should == ".FIT" }
26
+ its(:crc) { should == 17101 }
27
+ end
28
+ end
@@ -0,0 +1,20 @@
1
+ require 'spec_helper'
2
+
3
+ describe Fit::File::RecordHeader do
4
+ context "given a sample normal header" do
5
+ subject do
6
+ described_class.read example_file('record/normal_header')
7
+ end
8
+
9
+ its(:header_type) { should == 0 }
10
+ its(:message_type) { should == 1 }
11
+ its(:local_message_type) { should == 0 }
12
+
13
+ it { is_expected.to be_normal }
14
+ it { is_expected.not_to be_a_compressed_timestamp }
15
+ end
16
+
17
+ context "given a sample compressed timestamp header" do
18
+ # TODO
19
+ end
20
+ end
@@ -0,0 +1,56 @@
1
+ require 'spec_helper'
2
+
3
+ describe Fit::File::Record do
4
+ before do
5
+ described_class.clear_definitions!
6
+ described_class.read(example_file('record/definition_record_2.fit'))
7
+ end
8
+
9
+ describe ".read" do
10
+ subject { described_class.read(file) }
11
+
12
+ context "given a sample definition record" do
13
+ let(:file) { example_file('record/definition_record') }
14
+
15
+ it { expect(subject.header).to be_a Fit::File::RecordHeader }
16
+ it { expect(subject.content).to be_a Fit::File::Definition }
17
+
18
+ end
19
+
20
+ context "given a sample data record" do
21
+ let(:file) { nil }
22
+ end
23
+
24
+ context "given a sample data record with a string non null terminated" do
25
+
26
+ context 'string length is equal to field size' do
27
+
28
+ let(:file) { example_file('record/data_record_2.fit') }
29
+
30
+ its(:header) { should be_a(Fit::File::RecordHeader) }
31
+ it { expect(subject.content.raw_version).to be == 250 }
32
+ it { expect(subject.content.raw_part_number).to be == '123-A1234-00' }
33
+ end
34
+
35
+ context 'string length is smaller than field size' do
36
+
37
+ let(:file) { example_file('record/data_record_2bis.fit') }
38
+
39
+ its(:header) { should be_a(Fit::File::RecordHeader) }
40
+ it { expect(subject.content.raw_version).to be == 251 }
41
+ it { expect(subject.content.version).to be == 2.51 }
42
+ it { expect(subject.content.raw_part_number).to be == '123-A1234' }
43
+ it { expect(subject.content.part_number).to be == '123-A1234' }
44
+ end
45
+ end
46
+ end
47
+
48
+ describe ".clear_definitions" do
49
+ it "should clear the definitions class variable" do
50
+ described_class.read example_file('record/definition_record')
51
+ expect(described_class.definitions).to_not be_empty
52
+ described_class.clear_definitions!
53
+ expect(described_class.definitions).to be_empty
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,99 @@
1
+ require 'spec_helper'
2
+
3
+ describe Fit::File::Type do
4
+ before :all do
5
+ @types = Fit::File::Types.class_variable_get :@@types
6
+ Fit::File::Types.add_type(:int_type, :sint8)
7
+ Fit::File::Types.add_type(:int_type_with_val, :uint8, :values => {1 => 'one', 2 => 'two', 3 => 'three'})
8
+ end
9
+
10
+ after :all do
11
+ Fit::File::Types.class_variable_set(:@@types, @types)
12
+ end
13
+
14
+ describe '.get_type' do
15
+ context 'when valid name' do
16
+ it 'returns a type' do
17
+ expect(described_class.get_type(:int_type)).to be_a Fit::File::Type
18
+ end
19
+
20
+ it 'returns always the same instance' do
21
+ expect(described_class.get_type(:int_type)).to equal described_class.get_type(:int_type)
22
+ end
23
+ end
24
+
25
+ context 'when invalid name' do
26
+ it 'returns nil' do
27
+ expect(described_class.get_type(:unknown_type)).to be_nil
28
+ end
29
+ end
30
+ end
31
+
32
+ describe '#value' do
33
+ context 'when type has values' do
34
+
35
+ let(:type) { described_class.get_type(:int_type_with_val) }
36
+
37
+ context 'known value requested' do
38
+ it 'returns the value' do
39
+ expect(type.value(2)).to eql 'two'
40
+ end
41
+ end
42
+
43
+ context 'unknown value requested' do
44
+ it 'returns the input value' do
45
+ expect(type.value(999)).to eql 999
46
+ end
47
+ end
48
+
49
+ context 'when invalid value is requested' do
50
+ it 'returns nil' do
51
+ expect(type.value(255)).to be_nil
52
+ expect(type.value(0xFF)).to be_nil
53
+ end
54
+ end
55
+ end
56
+
57
+ context 'when type has date_time value' do
58
+ let(:type) { described_class.get_type(:date_time) }
59
+ it 'returns the date' do
60
+ expect(type.value(790509304)).to eq('2015-01-18 09:55:04 UTC')
61
+ end
62
+ end
63
+
64
+ context 'when type has message_index value' do
65
+ let(:type) { described_class.get_type(:message_index) }
66
+
67
+ it 'returns the message_index' do
68
+ expect(type.value(10)).to eq(10)
69
+ expect(type.value(32778)).to eq(10)
70
+ expect(type.value(28682)).to eq(10)
71
+ end
72
+
73
+ end
74
+
75
+ context 'when type has file_flags value' do
76
+ let(:type) { described_class.get_type(:file_flags) }
77
+ it 'returns the file_flags' do
78
+ expect(type.value(10)).to eq('read/erase')
79
+ expect(type.value(0x0A)).to eq('read/erase')
80
+ end
81
+ end
82
+
83
+ context 'when type has bool value' do
84
+ let(:type) { described_class.get_type(:bool) }
85
+ it 'returns the boolean value' do
86
+ expect(type.value(0)).to eq(false)
87
+ expect(type.value(1)).to eq(true)
88
+ expect(type.value(255)).to be_nil
89
+ end
90
+ end
91
+
92
+ context 'when type has no value' do
93
+ it 'returns nil' do
94
+ type = described_class.get_type(:int_type)
95
+ expect(type.value(1)).to eql 1
96
+ end
97
+ end
98
+ end
99
+ end
@@ -0,0 +1,100 @@
1
+ require 'spec_helper'
2
+
3
+ describe Fit::File::Types do
4
+ before :all do
5
+ @types = described_class.class_variable_get :@@types
6
+ end
7
+
8
+ after :all do
9
+ Fit::File::Types.class_variable_set(:@@types, @types)
10
+ end
11
+
12
+ describe '.add_type' do
13
+ before :each do
14
+ Fit::File::Types.class_variable_set(:@@types, Hash.new { |h,k| h[k]={} })
15
+ end
16
+
17
+ context 'for enum type' do
18
+ it 'add enum data' do
19
+ val = {:values => { 1 => 'val1', 2=> 'val2', 3 => 'val3'}}
20
+ described_class.add_type(:test_enum, :enum, val)
21
+ expect(described_class.get_type_definition(:test_enum)).to eql val.merge({:basic_type => :enum})
22
+ end
23
+ end
24
+ end
25
+
26
+ describe '.get_type_definition' do
27
+ it 'returns nil when type does not exist' do
28
+ expect(described_class.get_type_definition(:rspec_unknown)).to be_nil
29
+ end
30
+ end
31
+
32
+ describe '.date_time_value' do
33
+ context 'wen value below min' do
34
+ it 'returns system time in second' do
35
+ expect(described_class.date_time_value(9999, {268435456 => 'min'}, {:utc => true})).to eql '9999'
36
+ expect(described_class.date_time_value(9999, {268435456 => 'min'}, {:utc => false})).to eql '9999'
37
+ end
38
+ end
39
+
40
+ context 'when value is above min' do
41
+ context 'with UTC mode' do
42
+ it 'returns exact date UTC' do
43
+ expect(described_class.date_time_value(790509304, {268435456 => 'min'}, {:utc => true})).to eql '2015-01-18 09:55:04 UTC'
44
+ end
45
+ end
46
+
47
+ context 'with local mode' do
48
+ it 'returns exact date in locale time zone' do
49
+ # TODO: manage answer based on current system local
50
+ expect(described_class.date_time_value(790509304, {268435456 => 'min'}, {:utc => false})).not_to match(/UTC$/)
51
+ end
52
+ end
53
+
54
+ end
55
+ end
56
+
57
+ describe '.message_index_value' do
58
+ let(:values) { {32768 => 'selected', 28672 => 'reserved', 4095 => 'mask' } }
59
+
60
+ context 'when value is not reserved or selected' do
61
+ it 'returns the message index' do
62
+ expect(described_class.message_index_value(10, values)).to eq(10)
63
+ end
64
+ end
65
+
66
+ context 'when value is reserved' do
67
+ it 'returns real message index' do
68
+ expect(described_class.message_index_value(28682, values)).to eq(10)
69
+ end
70
+ end
71
+
72
+ context 'when value is selected' do
73
+ it 'returns real message index' do
74
+ expect(described_class.message_index_value(32778, values)).to eq(10)
75
+ end
76
+ end
77
+
78
+ end
79
+
80
+ describe '.bitfield_value' do
81
+ let(:values) { {0x02 => 'read', 0x04 => 'write', 0x08 => 'erase'} }
82
+
83
+ context 'when value is a single bit' do
84
+ it 'returns the single value' do
85
+ expect(described_class.bitfield_value(2, values)).to eq('read')
86
+ expect(described_class.bitfield_value(4, values)).to eq('write')
87
+ expect(described_class.bitfield_value(8, values)).to eq('erase')
88
+ end
89
+ end
90
+
91
+ context 'when value is several bits' do
92
+ it 'returns the values separated by a slash' do
93
+ expect(described_class.bitfield_value(6, values)).to eq('read/write')
94
+ expect(described_class.bitfield_value(12, values)).to eq('write/erase')
95
+ end
96
+ end
97
+ end
98
+
99
+ end
100
+
data/spec/file_spec.rb ADDED
@@ -0,0 +1,21 @@
1
+ require 'spec_helper'
2
+
3
+ describe Fit::File do
4
+ let(:file) { described_class.read( example_file('file/full_file_with_wrong_crc.fit') ) }
5
+
6
+ it 'should have a header' do
7
+ expect(file.header).to be_a Fit::File::Header
8
+ end
9
+
10
+ it 'should have records' do
11
+ expect(file.records).to be_a Array
12
+ expect(file.records[0]).to be_a Fit::File::Record
13
+ end
14
+
15
+ it 'should have a CRC' do
16
+ # warning this file is not having a consistent CRC compare to
17
+ # its content. To be used only for test.
18
+ expect(file.crc).to be_a String
19
+ expect(BinData::Uint16le.read(file.crc)).to be == 34100
20
+ end
21
+ end
data/spec/fit_spec.rb ADDED
@@ -0,0 +1,10 @@
1
+ require 'spec_helper'
2
+
3
+ describe Fit do
4
+ describe "VERSION" do
5
+ subject{ Fit::VERSION }
6
+
7
+ it { is_expected.to be_a(String) }
8
+ it { is_expected.to match(/\d{1,2}\.\d{1,2}\.\d{1,2}/) }
9
+ end
10
+ end
@@ -0,0 +1,19 @@
1
+ require 'simplecov'
2
+ SimpleCov.add_filter '/spec/'
3
+ SimpleCov.start
4
+
5
+ SPEC_ROOT = File.dirname(__FILE__)
6
+
7
+ $LOAD_PATH.unshift SPEC_ROOT, File.join(SPEC_ROOT, '..', 'lib')
8
+
9
+ require 'rspec'
10
+ require 'rspec/its'
11
+ require 'fit'
12
+
13
+ RSpec.configure do |config|
14
+ config.raise_errors_for_deprecations!
15
+ end
16
+
17
+ def example_file(filename)
18
+ File.open File.join(SPEC_ROOT, 'support', 'examples', filename)
19
+ end
Binary file