saharspec 0.0.4 → 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 320e576aeec4fa534c88058a6f93a617adffa1ef
4
- data.tar.gz: 3bb428585c9c78cb5da1ee565fbf7cfd1e5d8ea4
3
+ metadata.gz: 627f1f82b546e7a3e096497b74f25cab346d0fa2
4
+ data.tar.gz: d7efe0bcc330cdd47d426fb502b5114fbffa85e6
5
5
  SHA512:
6
- metadata.gz: 67c2f6364699e87103723d7a679e07da03a4b53a6a7b57f43cc2c9bd93b496453d3ebfe4923440df94a7d6c61176308aba164254cbcea386e762864af483034a
7
- data.tar.gz: c5cbcf7972f063618e66ee9feea61ba80005942cf38cbe9a4735e30cd2a603f623bc25d5bd19b4553cdb21d573f46cac371cbb722aa5fd0e25016e56b3138997
6
+ metadata.gz: e2249769358166c5b72bee55ca94b9b0ed698715afc71e439e7687fba8f745b63641312e4cb7d52340c3e4f6a805458c0f7e0b7be9b23e4eeccb90487d6699a2
7
+ data.tar.gz: 945e11582fd5c21b7cb7fd8b0d7f1021611d546bb957446df2f8b1c7b2d5c1b060e19dfd80956b5dec8a0d6a4949cda0981e216d1093d9084d44e005cf25dd49
data/LICENSE.txt CHANGED
@@ -1,6 +1,6 @@
1
1
  The MIT License (MIT)
2
2
 
3
- Copyright (c) 2014-15 Victor 'Zverok' Shepelev
3
+ Copyright (c) 2017-18 Victor 'Zverok' Shepelev
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining
6
6
  a copy of this software and associated documentation files (the
data/README.md CHANGED
@@ -9,7 +9,8 @@ specs dry as a desert.
9
9
 
10
10
  ## Usage
11
11
 
12
- Install it as a usual gem `saharspec`.
12
+ Install it as a usual gem `saharspec` with `gem install` or `gem "saharspec"` in `:test` group of
13
+ your `Gemfile`.
13
14
 
14
15
  Then, probably in your `spec_helper.rb`
15
16
 
@@ -102,6 +103,27 @@ end
102
103
 
103
104
  Plays really well with `its_call` shown below.
104
105
 
106
+ #### `be_json(value)` and `be_json_sym(value)` matchers
107
+
108
+ Simple matcher to check if string is valid JSON and optionally if it matches to expected values:
109
+
110
+ ```ruby
111
+ expect('{}').to be_json # ok
112
+ expect('garbage').to be_json
113
+ # expected value to be a valid JSON string but failed: 765: unexpected token at 'garbage'
114
+
115
+ expect('{"foo": "bar"}').to be_json('foo' => 'bar') # ok
116
+
117
+ # be_json_sym is more convenient to check with hash keys, parses JSON to symbols
118
+ expect('{"foo": "bar"}').to be_json_sym(foo: 'bar')
119
+
120
+ # nested matchers work, too
121
+ expect('{"foo": [1, 2, 3]').to be_json_sym(foo: array_including(3))
122
+
123
+ # We need to go deeper!
124
+ expect(something_large).to be_json_sym(include(meta: include(next_page: Integer)))
125
+ ```
126
+
105
127
  #### `eq_multiline(text)` matcher
106
128
 
107
129
  Dedicated to checking some multiline text generators.
@@ -241,4 +263,4 @@ checking them). Stay tuned.
241
263
 
242
264
  ## License
243
265
 
244
- [MIT](https://github.com/zverok/time_math2/blob/master/LICENSE.txt).
266
+ [MIT](https://github.com/zverok/saharspec/blob/master/LICENSE.txt).
data/lib/saharspec/its.rb CHANGED
@@ -3,9 +3,29 @@ module Saharspec
3
3
  #
4
4
  # See:
5
5
  #
6
- # * {Map#its_map #its_map}
7
- # * {Block#its_block #its_block}
8
- # * {Call#its_call #its_call}
6
+ # ## {Map#its_map #its_map}
7
+ #
8
+ # ```ruby
9
+ # subject { %w[1 2 3] }
10
+ # its_map(:to_s) { is_expected.to eq [1, 2, 3] }
11
+ # ```
12
+ #
13
+ # ## {Call#its_call #its_call}
14
+ #
15
+ # ```ruby
16
+ # subject { [1, 2, 3].method(:[]) }
17
+ # its_call(2) { is_expected.to ret 3 }
18
+ # its_call('foo') { is_expected.to raise_error }
19
+ # ```
20
+ #
21
+ # ## {Block#its_block #its_block}
22
+ #
23
+ # ```ruby
24
+ # subject { something_action }
25
+ # its_block { is_expected.not_to raise_error }
26
+ # its_block { is_expected.to change(some, :value).by(1) }
27
+ # ```
28
+ #
9
29
  module Its
10
30
  end
11
31
  end
@@ -11,7 +11,7 @@ module Saharspec
11
11
  # its_map(:length) { is_expected.to eq [4, 2, 6] }
12
12
  #
13
13
  # # with attribute chain
14
- # its_map(:'reverse.upcase') { is_expected.to eq %w[TSET EM ESAELP] }
14
+ # its_map('reverse.upcase') { is_expected.to eq %w[TSET EM ESAELP] }
15
15
  #
16
16
  # # with Hash (or any other object responding to `#[]`)
17
17
  # subject {
@@ -35,8 +35,8 @@ module Saharspec
35
35
  # TODO: better desciption for different cases
36
36
  describe("map(&:#{attribute})") do
37
37
  let(:__its_map_subject) do
38
- if Array === attribute # rubocop:disable Style/CaseEquality
39
- if subject.all? { |s| Hash === s } # rubocop:disable Style/CaseEquality
38
+ if Array === attribute
39
+ if subject.all? { |s| Hash === s }
40
40
  subject.map do |s|
41
41
  attribute.inject(s) { |inner, attr| inner[attr] }
42
42
  end
@@ -3,10 +3,11 @@ module Saharspec
3
3
  #
4
4
  # See:
5
5
  #
6
- # * {RSpec::Matchers#dont #dont}
7
- # * {RSpec::Matchers#send_message #send_message}
8
- # * {RSpec::Matchers#eq_multiline #eq_multiline}
9
- # * {RSpec::Matchers#ret #ret}
6
+ # * {RSpec::Matchers#dont #dont}: `expect { block }.to change(this).and dont.change(that)`
7
+ # * {RSpec::Matchers#send_message #send_message}: `expect { block }.to send_message(File, :write)`
8
+ # * {RSpec::Matchers#ret #ret}: `expect { block }.to ret value`
9
+ # * {RSpec::Matchers#be_json #be_json}: `expect(response.body).to be_json('foo' => 'bar')`
10
+ # * {RSpec::Matchers#eq_multiline #eq_multiline}: multiline equality akin to squiggly heredoc
10
11
  #
11
12
  module Matchers
12
13
  end
@@ -15,3 +16,5 @@ end
15
16
  require_relative 'matchers/eq_multiline'
16
17
  require_relative 'matchers/send_message'
17
18
  require_relative 'matchers/ret'
19
+ require_relative 'matchers/dont'
20
+ require_relative 'matchers/be_json'
@@ -0,0 +1,99 @@
1
+ require 'json'
2
+
3
+ module Saharspec
4
+ module Matchers
5
+ # @private
6
+ class BeJson
7
+ NONE = Object.new.freeze
8
+ include RSpec::Matchers::Composable
9
+ include RSpec::Matchers # to have #match
10
+
11
+ attr_reader :actual, :expected
12
+
13
+ def initialize(expected, **parse_opts)
14
+ @expected_matcher = @expected = expected
15
+ # wrap to make be_json('foo' => matcher) work, too
16
+ @expected_matcher = match(expected) unless expected == NONE || expected.respond_to?(:matches?)
17
+ @parse_opts = parse_opts
18
+ end
19
+
20
+ def matches?(json)
21
+ @actual = JSON.parse(json, **@parse_opts)
22
+ @expected_matcher == NONE || @expected_matcher === @actual
23
+ rescue JSON::ParserError => parse_error
24
+ @parser_error = parse_error
25
+ false
26
+ end
27
+
28
+ def does_not_match?(*args)
29
+ !matches?(*args)
30
+ end
31
+
32
+ def diffable?
33
+ true
34
+ end
35
+
36
+ def description
37
+ if @expected == NONE
38
+ 'be a valid JSON string'
39
+ else
40
+ expected = @expected.respond_to?(:description) ? @expected.description : @expected
41
+ "be a valid JSON matching (#{expected})"
42
+ end
43
+ end
44
+
45
+ def failure_message
46
+ failed =
47
+ case
48
+ when @parser_error
49
+ "failed: #{@parser_error}"
50
+ when @expected != NONE
51
+ "was #{@actual}"
52
+ end
53
+ "expected value to #{description} but #{failed}"
54
+ end
55
+
56
+ def failure_message_when_negated
57
+ 'expected value not to be parsed as JSON, but succeeded'
58
+ end
59
+ end
60
+ end
61
+ end
62
+
63
+ module RSpec
64
+ module Matchers
65
+ # `be_json` checks if provided value is JSON, and optionally checks it contents.
66
+ #
67
+ # If you need to check against some hashes, it is more convenient to use `be_json_sym`, which
68
+ # parses JSON with `symbolize_names: true`.
69
+ #
70
+ # @example
71
+ #
72
+ # expect('{}').to be_json # ok
73
+ # expect('garbage').to be_json
74
+ # # expected value to be a valid JSON string but failed: 765: unexpected token at 'garbage'
75
+ #
76
+ # expect('{"foo": "bar"}').to be_json('foo' => 'bar') # ok
77
+ # expect('{"foo": "bar"}').to be_json_sym(foo: 'bar') # more convenient
78
+ #
79
+ # expect('{"foo": [1, 2, 3]').to be_json_sym(foo: array_including(3)) # nested matchers work
80
+ # expect(something_large).to be_json_sym(include(meta: include(next_page: Integer)))
81
+ #
82
+ # @param expected Value or matcher to check JSON against. It should implement `#===` method,
83
+ # so all standard and custom RSpec matchers work.
84
+ def be_json(expected = Saharspec::Matchers::BeJson::NONE)
85
+ Saharspec::Matchers::BeJson.new(expected)
86
+ end
87
+
88
+ # `be_json_sym` checks if value is a valid JSON and parses it with `symbolize_names: true`. This
89
+ # way, it is convenient to check hashes content with Ruby's short symbolic keys syntax.
90
+ #
91
+ # See {#be_json_sym} for examples.
92
+ #
93
+ # @param expected Value or matcher to check JSON against. It should implement `#===` method,
94
+ # so all standard and custom RSpec matchers work.
95
+ def be_json_sym(expected = Saharspec::Matchers::BeJson::NONE)
96
+ Saharspec::Matchers::BeJson.new(expected, symbolize_names: true)
97
+ end
98
+ end
99
+ end
@@ -4,6 +4,8 @@ module Saharspec
4
4
  class Ret
5
5
  include RSpec::Matchers::Composable
6
6
 
7
+ attr_reader :actual, :expected
8
+
7
9
  def initialize(expected)
8
10
  @expected = expected
9
11
  end
@@ -12,13 +14,17 @@ module Saharspec
12
14
  @subject = subject
13
15
  return false unless subject.respond_to?(:call)
14
16
  @actual = subject.call
15
- @expected === @actual # rubocop:disable Style/CaseEquality
17
+ @expected === @actual
16
18
  end
17
19
 
18
20
  def supports_block_expectations?
19
21
  true
20
22
  end
21
23
 
24
+ def diffable?
25
+ true
26
+ end
27
+
22
28
  def description
23
29
  "return #{@expected.respond_to?(:description) ? @expected.description : @expected.inspect}"
24
30
  end
@@ -42,7 +48,8 @@ module RSpec
42
48
  # It should be considered instead of simple value matchers (like `eq`) in the situations:
43
49
  #
44
50
  # 1. Several block behaviors tested in the same test, joined with `.and`, or in separate tests
45
- # 2. You test what some block or method returns with arguments, using {Call#its_call #its_call}
51
+ # 2. You test what some block or method returns with arguments, using
52
+ # {Saharspec::Its::Call#its_call #its_call}
46
53
  #
47
54
  # Values are tested with `===`, which allows chaining other matchers and patterns to the check.
48
55
  #
@@ -16,8 +16,8 @@ module Saharspec
16
16
  self
17
17
  end
18
18
 
19
- def returning(res)
20
- @res = res
19
+ def returning(*res)
20
+ @res = [*res]
21
21
  self
22
22
  end
23
23
 
@@ -91,7 +91,7 @@ module Saharspec
91
91
 
92
92
  def allower
93
93
  receive(@method).tap do |a|
94
- a.and_return(@res) if @res
94
+ a.and_return(*@res) if @res
95
95
  a.and_call_original if @call_original
96
96
  end
97
97
  end
@@ -1,9 +1,6 @@
1
1
  module Saharspec
2
- # @private
3
2
  MAJOR = 0
4
- # @private
5
3
  MINOR = 0
6
- # @private
7
- PATCH = 4
4
+ PATCH = 5
8
5
  VERSION = [MAJOR, MINOR, PATCH].join('.')
9
6
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: saharspec
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.4
4
+ version: 0.0.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Victor Shepelev
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-11-07 00:00:00.000000000 Z
11
+ date: 2018-03-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rubocop
@@ -125,6 +125,7 @@ files:
125
125
  - lib/saharspec/its/call.rb
126
126
  - lib/saharspec/its/map.rb
127
127
  - lib/saharspec/matchers.rb
128
+ - lib/saharspec/matchers/be_json.rb
128
129
  - lib/saharspec/matchers/dont.rb
129
130
  - lib/saharspec/matchers/eq_multiline.rb
130
131
  - lib/saharspec/matchers/request_webmock.rb
@@ -153,7 +154,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
153
154
  version: '0'
154
155
  requirements: []
155
156
  rubyforge_project:
156
- rubygems_version: 2.6.10
157
+ rubygems_version: 2.6.14
157
158
  signing_key:
158
159
  specification_version: 4
159
160
  summary: Several additions for DRYer RSpec code