first_and_only 1.0.0 → 2.0.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 2b4c91e830188491065f0ce936d55c0cfee7757e
4
- data.tar.gz: 9d85444ffd3680109fb97e7ebfa49289681cbabc
3
+ metadata.gz: 9f854f3edf7c69ae6b88c87c29678b91678ed91c
4
+ data.tar.gz: c2d49e72515a4d1bac8367c76ecfaa473efed78c
5
5
  SHA512:
6
- metadata.gz: 7c00ff20741d3eac47a38b9815a87a3fd2e270dcf194f6155e9e702466909c7d2c877eb53d2e598940790aaa0743eede95650eb01fc57ac81c486bb10ed4a383
7
- data.tar.gz: 0ebc077a6d80d5e47de14de7d5c1e3d17c71e07be4ec4a7972958815c3a57a07a03435733b88f17045d2aeee4b8d3e992aed643922bff4a95444fa4009db83b0
6
+ metadata.gz: a477760c26ecaabfc516a8968ccab37467bcba33ee5197d15eae078f56f235a71acb02868c0932bc0203cef3bf99a44f3d17c71b0e72e349aaf4c50b5de921c2
7
+ data.tar.gz: cd2cd50bbed8f4f40ed478f5d20ade952272a5047cc7f6144c17657374e177a13df713f918bb8687947bab43ea946e03e14b107839e29e582d508fa800056eab
@@ -0,0 +1,7 @@
1
+ language: ruby
2
+ rvm:
3
+ - "1.9.3"
4
+ - "2.0.0"
5
+ - "2.1.0"
6
+ - "2.2.3"
7
+ script: bundle exec rspec
data/README.md CHANGED
@@ -1,24 +1,52 @@
1
1
  # FirstAndOnly
2
2
 
3
- TODO: Write a gem description
3
+ Get the first element from an enumerable, and assert that there is only one element to take.
4
+
5
+ ```
6
+ [:just_one].first_and_only! # => :just_one
7
+ ```
8
+
9
+ ```
10
+ [].first_and_only! # => 0 (Enumerable::FirstAndOnly::CountNotOne)
11
+ ```
12
+
13
+ ```
14
+ [:one, :and_two].first_and_only! # => 2 (Enumerable::FirstAndOnly::CountNotOne)
15
+ ```
16
+
17
+ ## Why?
18
+
19
+ Sometimes in a spec you have a collection object that you know only has one element. You set it up this way. Later spec refactors may accidentally introduce a second element. To prevent accidental false positives, and to make fixing failures introduced by this easier, you can use `#first_and_only!` to codify the "there is only one" assumption.
20
+
21
+ Another common use case for `#first_and_only` is `id` assertions on HTML documents. A valid HTML document can only have one occurrence of each `id` attribute, but authoring tools and browsers don't typically enforce this. If you hang your JavaScript of the "only one" assumption of `id` attributes, you should enforce this with a specification.
22
+
23
+ This gem follows the same line of thinking as the [fetching gem](https://github.com/covermymeds/fetching-gem)
4
24
 
5
25
  ## Installation
6
26
 
7
27
  Add this line to your application's Gemfile:
8
28
 
9
- gem 'first_and_only'
29
+ ```
30
+ gem 'first_and_only'
31
+ ```
10
32
 
11
33
  And then execute:
12
34
 
13
- $ bundle
35
+ ```
36
+ $ bundle
37
+ ```
14
38
 
15
39
  Or install it yourself as:
16
40
 
17
- $ gem install first_and_only
41
+ ```
42
+ $ gem install first_and_only
43
+ ```
18
44
 
19
- ## Usage
45
+ ## Running specs
20
46
 
21
- TODO: Write usage instructions here
47
+ ```
48
+ bundle exec rspec
49
+ ```
22
50
 
23
51
  ## Contributing
24
52
 
@@ -17,11 +17,11 @@ Get the first element from an enumerable, and assert that there is only one elem
17
17
  ```
18
18
 
19
19
  ```
20
- [].first_and_only! # => 0 (Enumerable::FirstAndOnly::LengthNotOne)
20
+ [].first_and_only! # => 0 (Enumerable::FirstAndOnly::CountNotOne)
21
21
  ```
22
22
 
23
23
  ```
24
- [:one, :and_two].first_and_only! # => 2 (Enumerable::FirstAndOnly::LengthNotOne)
24
+ [:one, :and_two].first_and_only! # => 2 (Enumerable::FirstAndOnly::CountNotOne)
25
25
  ```
26
26
  SUMMARY
27
27
  spec.homepage = "https://github.com/dapplebeforedawn/first-and-only-gem"
@@ -34,4 +34,5 @@ Get the first element from an enumerable, and assert that there is only one elem
34
34
 
35
35
  spec.add_development_dependency "bundler", "~> 1.3"
36
36
  spec.add_development_dependency "rake"
37
+ spec.add_development_dependency "rspec", "~> 2.14.1"
37
38
  end
@@ -2,11 +2,15 @@ require "first_and_only/version"
2
2
 
3
3
  module Enumerable
4
4
  def first_and_only!
5
- fail(FirstAndOnly::LengthNotOne, count) if first(2).count != 1
5
+ fail(FirstAndOnly::CountNotOne.new count) if first(2).count != 1
6
6
  first
7
7
  end
8
8
 
9
9
  module FirstAndOnly
10
- LengthNotOne = Class.new(StandardError)
10
+ class CountNotOne < StandardError
11
+ def initialize(count)
12
+ super("Expected the count to be 1, but it was #{count}.")
13
+ end
14
+ end
11
15
  end
12
16
  end
@@ -1,3 +1,3 @@
1
1
  module FirstAndOnly
2
- VERSION = "1.0.0"
2
+ VERSION = "2.0.0"
3
3
  end
@@ -0,0 +1,79 @@
1
+ require "spec_helper"
2
+
3
+ describe "Enumerable#first_and_only!" do
4
+
5
+ shared_examples_for "it_has_one_element" do
6
+ specify { expect(subject.first_and_only!).to eq(:element) }
7
+ end
8
+
9
+ shared_examples_for "it_is_empty" do
10
+ specify do
11
+ expect { subject.first_and_only! }.to raise_error(
12
+ Enumerable::FirstAndOnly::CountNotOne,
13
+ "Expected the count to be 1, but it was 0."
14
+ )
15
+ end
16
+ end
17
+
18
+ shared_examples_for "it_has_more_than_one_element" do
19
+ specify do
20
+ fail "bad example" if subject.count < 2
21
+
22
+ expect { subject.first_and_only! }.to raise_error(
23
+ Enumerable::FirstAndOnly::CountNotOne,
24
+ "Expected the count to be 1, but it was #{subject.count}."
25
+ )
26
+ end
27
+ end
28
+
29
+ describe "an array" do
30
+
31
+ context "with one element" do
32
+ subject { [:element] }
33
+ it_behaves_like "it_has_one_element"
34
+ end
35
+
36
+ context "that is empty" do
37
+ subject { [] }
38
+ it_behaves_like "it_is_empty"
39
+ end
40
+
41
+ context "with two elements" do
42
+ subject { [:element, :element] }
43
+ it_behaves_like "it_has_more_than_one_element"
44
+ end
45
+ end
46
+
47
+ describe "any enumerable" do
48
+ let(:my_enumerable) do
49
+ Class.new do
50
+ include Enumerable
51
+
52
+ def initialize *args
53
+ @args = args
54
+ end
55
+
56
+ def each
57
+ @args.each { |arg| yield(arg) }
58
+ end
59
+ end
60
+ end
61
+
62
+ context "with one element" do
63
+ subject { my_enumerable.new(:element) }
64
+ it_behaves_like "it_has_one_element"
65
+ end
66
+
67
+ context "empty" do
68
+ subject { my_enumerable.new() }
69
+ it_behaves_like "it_is_empty"
70
+ end
71
+
72
+ context "with more than on element" do
73
+ subject { my_enumerable.new(:element, :element) }
74
+ it_behaves_like "it_has_more_than_one_element"
75
+ end
76
+
77
+ end
78
+
79
+ end
@@ -0,0 +1,13 @@
1
+ require "first_and_only"
2
+ require "rspec/autorun"
3
+ require "pathname"
4
+
5
+ Pathname(__FILE__).dirname.join("support").each_child { |f| require f }
6
+
7
+ RSpec.configure do |config|
8
+ # Run specs in random order to surface order dependencies. If you find an
9
+ # order dependency and want to debug it, you can fix the order by providing
10
+ # the seed, which is printed after each run.
11
+ # --seed 1234
12
+ config.order = "random"
13
+ end
@@ -0,0 +1,35 @@
1
+ # Adapted from https://github.com/bronson/vim-runtest/blob/master/rspec_formatter.rb.
2
+ require "rspec/core/formatters/base_text_formatter"
3
+
4
+ class VimFormatter < RSpec::Core::Formatters::BaseTextFormatter
5
+
6
+ def example_failed example
7
+ exception = example.execution_result[:exception]
8
+ path = Regexp.last_match[1] if exception.backtrace.find do |frame|
9
+ frame =~ %r{\b(spec/.*_spec\.rb:\d+)(?::|\z)}
10
+ end
11
+ message = format_message exception.message
12
+ path = format_caller(path || " ")
13
+ output.puts "#{path}: #{example.example_group.description.strip} " \
14
+ "#{example.description.strip}: #{message.strip}" if path
15
+ end
16
+
17
+ def example_pending *_args; end
18
+
19
+ def dump_failures *_args; end
20
+
21
+ def dump_pending *_args; end
22
+
23
+ def message _msg; end
24
+
25
+ def dump_summary *_args; end
26
+
27
+ def seed *_args; end
28
+
29
+ private
30
+
31
+ def format_message msg
32
+ msg.gsub("\n", " ")[0, 80]
33
+ end
34
+
35
+ end
metadata CHANGED
@@ -1,43 +1,57 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: first_and_only
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mark Lorenz
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-07-05 00:00:00.000000000 Z
11
+ date: 2015-10-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - ~>
17
+ - - "~>"
18
18
  - !ruby/object:Gem::Version
19
19
  version: '1.3'
20
20
  type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - ~>
24
+ - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: '1.3'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: rake
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - '>='
31
+ - - ">="
32
32
  - !ruby/object:Gem::Version
33
33
  version: '0'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - '>='
38
+ - - ">="
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: 2.14.1
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: 2.14.1
41
55
  description: |
42
56
  Get the first element from an enumerable, and assert that there is only one element to take.
43
57
  email:
@@ -46,7 +60,8 @@ executables: []
46
60
  extensions: []
47
61
  extra_rdoc_files: []
48
62
  files:
49
- - .gitignore
63
+ - ".gitignore"
64
+ - ".travis.yml"
50
65
  - Gemfile
51
66
  - LICENSE.txt
52
67
  - README.md
@@ -54,6 +69,9 @@ files:
54
69
  - first_and_only.gemspec
55
70
  - lib/first_and_only.rb
56
71
  - lib/first_and_only/version.rb
72
+ - spec/first_and_only_spec.rb
73
+ - spec/spec_helper.rb
74
+ - spec/support/vim_formatter.rb
57
75
  homepage: https://github.com/dapplebeforedawn/first-and-only-gem
58
76
  licenses:
59
77
  - MIT
@@ -64,20 +82,23 @@ require_paths:
64
82
  - lib
65
83
  required_ruby_version: !ruby/object:Gem::Requirement
66
84
  requirements:
67
- - - '>='
85
+ - - ">="
68
86
  - !ruby/object:Gem::Version
69
87
  version: '0'
70
88
  required_rubygems_version: !ruby/object:Gem::Requirement
71
89
  requirements:
72
- - - '>='
90
+ - - ">="
73
91
  - !ruby/object:Gem::Version
74
92
  version: '0'
75
93
  requirements: []
76
94
  rubyforge_project:
77
- rubygems_version: 2.2.2
95
+ rubygems_version: 2.4.8
78
96
  signing_key:
79
97
  specification_version: 4
80
- summary: '``` [:just_one].first_and_only! # => :just_one ``` ``` [].first_and_only! #
81
- => 0 (Enumerable::FirstAndOnly::LengthNotOne) ``` ``` [:one, :and_two].first_and_only! #
82
- => 2 (Enumerable::FirstAndOnly::LengthNotOne) ```'
83
- test_files: []
98
+ summary: "``` [:just_one].first_and_only! # => :just_one ``` ``` [].first_and_only!
99
+ \ # => 0 (Enumerable::FirstAndOnly::CountNotOne) ``` ``` [:one, :and_two].first_and_only!
100
+ \ # => 2 (Enumerable::FirstAndOnly::CountNotOne) ```"
101
+ test_files:
102
+ - spec/first_and_only_spec.rb
103
+ - spec/spec_helper.rb
104
+ - spec/support/vim_formatter.rb