line-message-builder 0.2.0 → 0.3.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 +4 -4
- data/.release-please-manifest.json +1 -1
- data/CHANGELOG.md +7 -0
- data/README.md +27 -4
- data/lib/line/message/builder/flex/builder.rb +5 -3
- data/lib/line/message/builder/version.rb +1 -1
- data/lib/line/message/rspec/matchers/have_flex_component.rb +26 -17
- data/lib/line/message/rspec/matchers/have_flex_message.rb +4 -3
- data/lib/line/message/rspec/matchers/have_quick_reply.rb +5 -4
- data/lib/line/message/rspec/matchers/have_text_message.rb +4 -3
- data/lib/line/message/rspec/matchers/utils.rb +26 -0
- data/lib/line/message/rspec/matchers.rb +1 -1
- metadata +2 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: aa7a2c0c112ef20086d81a2c1cf4b1c430ffe291c07ccfc92dfe8d81db1ea980
|
4
|
+
data.tar.gz: 163eb284640eeec1e5a035492ebca95b34d703d372f5d472e4330a762d7b2ceb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bcadb195ad72f851fcc648f6641ab547fc2a1885583f64be97f08288f43025246d2a14dd311103a5c64521e636dfb2bd0f89f61deccedec75ebe8bebdc528d2c
|
7
|
+
data.tar.gz: 1d612904e46b6e3e87590edf414b7839fa18412fe1c4734cdb961aacc8c1ed2e87a87a425b3cf563cc1eff4ec7337deaf0ff81592b75520dabba78363ec67629
|
@@ -1 +1 @@
|
|
1
|
-
{".":"0.
|
1
|
+
{".":"0.3.0"}
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,12 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## [0.3.0](https://github.com/elct9620/line-message-builder/compare/v0.2.0...v0.3.0) (2025-04-05)
|
4
|
+
|
5
|
+
|
6
|
+
### Miscellaneous Chores
|
7
|
+
|
8
|
+
* release 0.3.0 ([2f0b00c](https://github.com/elct9620/line-message-builder/commit/2f0b00c875a2d547c576e383aaeeae3bf777e898))
|
9
|
+
|
3
10
|
## [0.2.0](https://github.com/elct9620/line-message-builder/compare/v0.1.0...v0.2.0) (2025-04-05)
|
4
11
|
|
5
12
|
|
data/README.md
CHANGED
@@ -62,8 +62,8 @@ For Rails, you can use `view_context` to make `Builder` to access Rails helpers.
|
|
62
62
|
builder = Line::MessageBuilder::Builder.with(view_context) do
|
63
63
|
text "Anything you want?" do
|
64
64
|
quick_reply do
|
65
|
-
|
66
|
-
|
65
|
+
message "Yes", label: "Yes", image_url: image_url("yes.png")
|
66
|
+
message "No", label: "No", image_url: image_url("no.png")
|
67
67
|
end
|
68
68
|
end
|
69
69
|
end
|
@@ -82,8 +82,8 @@ context = ActionView::Base.new(
|
|
82
82
|
builder = Line::MessageBuilder::Builder.with(context) do
|
83
83
|
text "Anything you want?" do
|
84
84
|
quick_reply do
|
85
|
-
|
86
|
-
|
85
|
+
message "Yes", label: "Yes", image_url: image_url("yes.png")
|
86
|
+
message "No", label: "No", image_url: image_url("no.png")
|
87
87
|
end
|
88
88
|
end
|
89
89
|
end
|
@@ -91,6 +91,16 @@ end
|
|
91
91
|
|
92
92
|
### RSpec Matcher
|
93
93
|
|
94
|
+
| Matcher | Description |
|
95
|
+
| --------------------------- | ------------------------------------ |
|
96
|
+
| `have_line_text_message` | Match a text message |
|
97
|
+
| `have_line_flex_message` | Match a flex message |
|
98
|
+
| `have_line_flex_text` | Match a flex message with text |
|
99
|
+
| `have_line_flex_image` | Match a flex message with image |
|
100
|
+
| `have_line_flex_button` | Match a flex message with button |
|
101
|
+
| `have_line_flex_box` | Match a flex message with box |
|
102
|
+
|
103
|
+
|
94
104
|
Add `line/message/rspec` to your `spec_helper.rb` or `rails_helper.rb`:
|
95
105
|
|
96
106
|
```ruby
|
@@ -121,6 +131,19 @@ it { is_expected.to have_line_text_message("Hello, world!") }
|
|
121
131
|
it { is_expected.to have_line_text_message(/Nice to meet you!/) }
|
122
132
|
```
|
123
133
|
|
134
|
+
The matchers can work with webmock `a_request`:
|
135
|
+
|
136
|
+
```ruby
|
137
|
+
it "reply with message" do
|
138
|
+
expect(a_request(:post, "https://api.line.me/v2/bot/message/reply")
|
139
|
+
.with(
|
140
|
+
body: hash_including({
|
141
|
+
messages: have_line_text_message(/Hello, world!/),
|
142
|
+
},
|
143
|
+
))).to have_been_made.once
|
144
|
+
end
|
145
|
+
```
|
146
|
+
|
124
147
|
## Capabilities
|
125
148
|
|
126
149
|
- ✅ Supported
|
@@ -9,20 +9,22 @@ module Line
|
|
9
9
|
option :alt_text, default: nil
|
10
10
|
|
11
11
|
def initialize(context: nil, **options, &)
|
12
|
-
@contents =
|
12
|
+
@contents = nil
|
13
13
|
|
14
14
|
super
|
15
15
|
end
|
16
16
|
|
17
17
|
def bubble(&)
|
18
|
-
@contents
|
18
|
+
@contents = Line::Message::Builder::Flex::Bubble.new(context: context, &)
|
19
19
|
end
|
20
20
|
|
21
21
|
def to_h
|
22
|
+
raise Error, "contents should be bubble or carousel" if @contents.nil?
|
23
|
+
|
22
24
|
{
|
23
25
|
type: "flex",
|
24
26
|
altText: @alt_text,
|
25
|
-
contents: @contents.
|
27
|
+
contents: @contents.to_h,
|
26
28
|
quickReply: @quick_reply&.to_h
|
27
29
|
}.compact
|
28
30
|
end
|
@@ -20,9 +20,10 @@ module Line
|
|
20
20
|
end
|
21
21
|
|
22
22
|
def matches?(actual)
|
23
|
-
@actual = actual
|
23
|
+
@actual = Utils.stringify_keys!(actual, deep: true)
|
24
24
|
@actual.any? { |message| match_flex_component?(message) }
|
25
25
|
end
|
26
|
+
alias == matches?
|
26
27
|
|
27
28
|
def failure_message
|
28
29
|
return "expected to find a flex component" if @expected.nil?
|
@@ -34,16 +35,16 @@ module Line
|
|
34
35
|
private
|
35
36
|
|
36
37
|
def match_flex_component?(message)
|
37
|
-
return false unless message[
|
38
|
+
return false unless message["type"] == "flex"
|
38
39
|
|
39
|
-
message[
|
40
|
+
match_content?(message["contents"])
|
40
41
|
end
|
41
42
|
|
42
43
|
def match_content?(content)
|
43
|
-
return match_bubble?(content) if content[
|
44
|
+
return match_bubble?(content) if content["type"] == "bubble"
|
44
45
|
|
45
|
-
if content[
|
46
|
-
return content[
|
46
|
+
if content["contents"]
|
47
|
+
return content["contents"].any? do |nested_content|
|
47
48
|
match_content?(nested_content)
|
48
49
|
end || @expected.call(content)
|
49
50
|
end
|
@@ -52,7 +53,7 @@ module Line
|
|
52
53
|
end
|
53
54
|
|
54
55
|
def match_bubble?(content)
|
55
|
-
%
|
56
|
+
%w[header hero body footer].any? do |key|
|
56
57
|
block = content[key]
|
57
58
|
next unless block
|
58
59
|
|
@@ -61,7 +62,7 @@ module Line
|
|
61
62
|
end
|
62
63
|
|
63
64
|
def match_bubble_block?(block)
|
64
|
-
return block[
|
65
|
+
return block["contents"].any? { |nested_content| match_content?(nested_content) } if block["contents"]
|
65
66
|
|
66
67
|
match_content?(block)
|
67
68
|
end
|
@@ -72,37 +73,45 @@ module Line
|
|
72
73
|
end
|
73
74
|
|
74
75
|
def have_line_flex_box(**options) # rubocop:disable Naming/PredicateName
|
76
|
+
options = Utils.stringify_keys!(options, deep: true)
|
77
|
+
|
75
78
|
HaveFlexComponent.new(expected_desc: "box(#{options.inspect})") do |content|
|
76
|
-
next false unless content[
|
79
|
+
next false unless content["type"] == "box"
|
77
80
|
|
78
81
|
::RSpec::Matchers::BuiltIn::Include.new(options).matches?(content)
|
79
82
|
end
|
80
83
|
end
|
81
84
|
|
82
85
|
def have_line_flex_text(text, **options) # rubocop:disable Naming/PredicateName
|
86
|
+
options = Utils.stringify_keys!(options, deep: true)
|
87
|
+
|
83
88
|
HaveFlexComponent.new(expected_desc: "text(#{text.inspect})") do |content|
|
84
|
-
next false unless content[
|
89
|
+
next false unless content["type"] == "text"
|
85
90
|
|
86
|
-
content[
|
91
|
+
content["text"].match?(text) && ::RSpec::Matchers::BuiltIn::Include.new(options).matches?(content)
|
87
92
|
end
|
88
93
|
end
|
89
94
|
|
90
95
|
def have_line_flex_button(type, **options) # rubocop:disable Naming/PredicateName
|
96
|
+
options = Utils.stringify_keys!(options, deep: true)
|
97
|
+
|
91
98
|
HaveFlexComponent.new(expected_desc: "#{type} button(#{options.inspect})") do |content|
|
92
|
-
next false unless content[
|
99
|
+
next false unless content["type"] == "button"
|
93
100
|
|
94
|
-
::RSpec::Matchers::BuiltIn::Include.new({ type
|
95
|
-
::RSpec::Matchers::BuiltIn::Include.new({ **options, action
|
96
|
-
type
|
101
|
+
::RSpec::Matchers::BuiltIn::Include.new({ "type" => type, **options }).matches?(content["action"]) ||
|
102
|
+
::RSpec::Matchers::BuiltIn::Include.new({ **options, "action" => ::RSpec::Matchers::BuiltIn::Include.new(
|
103
|
+
"type" => type
|
97
104
|
) }).matches?(content)
|
98
105
|
end
|
99
106
|
end
|
100
107
|
|
101
108
|
def have_line_flex_image(url, **options) # rubocop:disable Naming/PredicateName
|
109
|
+
options = Utils.stringify_keys!(options, deep: true)
|
110
|
+
|
102
111
|
HaveFlexComponent.new(expected_desc: "image(#{url.inspect})") do |content|
|
103
|
-
next false unless content[
|
112
|
+
next false unless content["type"] == "image"
|
104
113
|
|
105
|
-
::RSpec::Matchers::BuiltIn::Include.new({ url
|
114
|
+
::RSpec::Matchers::BuiltIn::Include.new({ "url" => url, **options }).matches?(content)
|
106
115
|
end
|
107
116
|
end
|
108
117
|
end
|
@@ -18,9 +18,10 @@ module Line
|
|
18
18
|
end
|
19
19
|
|
20
20
|
def matches?(actual)
|
21
|
-
@actual = actual
|
21
|
+
@actual = Utils.stringify_keys!(actual, deep: true)
|
22
22
|
@actual.any? { |message| match_alt_text?(message) }
|
23
23
|
end
|
24
|
+
alias == matches?
|
24
25
|
|
25
26
|
def failure_message
|
26
27
|
"expected to find a flex message alt text matching #{@expected}"
|
@@ -29,10 +30,10 @@ module Line
|
|
29
30
|
private
|
30
31
|
|
31
32
|
def match_alt_text?(message)
|
32
|
-
return false unless message[
|
33
|
+
return false unless message["type"] == "flex"
|
33
34
|
return true if @expected.nil?
|
34
35
|
|
35
|
-
message[
|
36
|
+
message["altText"].match?(@expected)
|
36
37
|
end
|
37
38
|
end
|
38
39
|
|
@@ -8,7 +8,7 @@ module Line
|
|
8
8
|
# The quick reply matcher for RSpec to search for quick reply action in the message array.
|
9
9
|
class HaveQuickReply
|
10
10
|
def initialize(expected)
|
11
|
-
@expected = expected
|
11
|
+
@expected = Utils.stringify_keys!(expected, deep: true)
|
12
12
|
end
|
13
13
|
|
14
14
|
def description
|
@@ -18,9 +18,10 @@ module Line
|
|
18
18
|
end
|
19
19
|
|
20
20
|
def matches?(actual)
|
21
|
-
@actual = actual
|
21
|
+
@actual = Utils.stringify_keys!(actual, deep: true)
|
22
22
|
@actual.any? { |message| match_message(message) }
|
23
23
|
end
|
24
|
+
alias == matches?
|
24
25
|
|
25
26
|
def failure_message
|
26
27
|
"expected to find a quick reply message matching #{@expected}"
|
@@ -29,10 +30,10 @@ module Line
|
|
29
30
|
private
|
30
31
|
|
31
32
|
def match_message(message)
|
32
|
-
reply = message[
|
33
|
+
reply = message["quickReply"]
|
33
34
|
return false unless reply
|
34
35
|
|
35
|
-
reply[
|
36
|
+
reply["items"].any? { |item| match_action(item["action"]) }
|
36
37
|
end
|
37
38
|
|
38
39
|
def match_action(action)
|
@@ -18,15 +18,16 @@ module Line
|
|
18
18
|
end
|
19
19
|
|
20
20
|
def matches?(actual)
|
21
|
-
@actual = actual
|
21
|
+
@actual = Utils.stringify_keys!(actual, deep: true)
|
22
22
|
@actual.each do |message|
|
23
|
-
next unless message[
|
23
|
+
next unless message["type"] == "text"
|
24
24
|
|
25
|
-
return true if message[
|
25
|
+
return true if message["text"].match?(@expected)
|
26
26
|
end
|
27
27
|
|
28
28
|
false
|
29
29
|
end
|
30
|
+
alias == matches?
|
30
31
|
|
31
32
|
def failure_message
|
32
33
|
"expected to find a text message matching #{@expected}"
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Line
|
4
|
+
module Message
|
5
|
+
module RSpec
|
6
|
+
module Matchers
|
7
|
+
# :nodoc:
|
8
|
+
module Utils
|
9
|
+
def self.stringify_keys!(arg, deep: false) # rubocop:disable Metrics/CyclomaticComplexity, Metrics/MethodLength
|
10
|
+
case arg
|
11
|
+
when Hash
|
12
|
+
Hash[
|
13
|
+
*arg.map { |key, value| [key.to_s, deep ? stringify_keys!(value, deep: deep) : value] }
|
14
|
+
.inject([]) { |memo, pair| memo + pair }
|
15
|
+
]
|
16
|
+
when Array
|
17
|
+
arg.map { |item| deep ? stringify_keys!(item, deep: deep) : item }
|
18
|
+
else
|
19
|
+
arg
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: line-message-builder
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Aotokitsuruya
|
@@ -47,6 +47,7 @@ files:
|
|
47
47
|
- lib/line/message/rspec/matchers/have_flex_message.rb
|
48
48
|
- lib/line/message/rspec/matchers/have_quick_reply.rb
|
49
49
|
- lib/line/message/rspec/matchers/have_text_message.rb
|
50
|
+
- lib/line/message/rspec/matchers/utils.rb
|
50
51
|
- release-please-config.json
|
51
52
|
- sig/line/message/builder.rbs
|
52
53
|
homepage: https://github.com/elct9620/line-message-builder
|