embulk-input-jira 0.2.5 → 0.2.6
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/.gitignore +10 -5
- data/.travis.yml +4 -34
- data/CHANGELOG.md +4 -0
- data/LICENSE.txt +21 -0
- data/README.md +5 -4
- data/build.gradle +116 -0
- data/config/checkstyle/checkstyle.xml +128 -0
- data/config/checkstyle/default.xml +108 -0
- data/gradle/wrapper/gradle-wrapper.jar +0 -0
- data/gradle/wrapper/gradle-wrapper.properties +5 -0
- data/gradlew +172 -0
- data/gradlew.bat +84 -0
- data/lib/embulk/guess/jira.rb +24 -0
- data/lib/embulk/input/jira.rb +3 -169
- data/src/main/java/org/embulk/input/jira/AuthenticateMethod.java +27 -0
- data/src/main/java/org/embulk/input/jira/Constant.java +17 -0
- data/src/main/java/org/embulk/input/jira/Issue.java +150 -0
- data/src/main/java/org/embulk/input/jira/JiraInputPlugin.java +226 -0
- data/src/main/java/org/embulk/input/jira/client/JiraClient.java +254 -0
- data/src/main/java/org/embulk/input/jira/util/JiraException.java +18 -0
- data/src/main/java/org/embulk/input/jira/util/JiraUtil.java +264 -0
- data/src/test/java/org/embulk/input/jira/IssueTest.java +278 -0
- data/src/test/java/org/embulk/input/jira/JiraInputPluginTest.java +204 -0
- data/src/test/java/org/embulk/input/jira/JiraPluginTestRuntime.java +133 -0
- data/src/test/java/org/embulk/input/jira/TestHelpers.java +41 -0
- data/src/test/java/org/embulk/input/jira/client/JiraClientTest.java +222 -0
- data/src/test/java/org/embulk/input/jira/util/JiraUtilTest.java +318 -0
- data/src/test/resources/config.yml +13 -0
- data/src/test/resources/issue_flatten.json +129 -0
- data/src/test/resources/issue_flatten_expected.json +73 -0
- data/src/test/resources/issue_get.json +36 -0
- data/src/test/resources/issue_get_expected.json +62 -0
- data/src/test/resources/jira_client.json +81 -0
- data/src/test/resources/jira_input_plugin.json +114 -0
- data/src/test/resources/jira_util.json +26 -0
- metadata +55 -175
- data/Gemfile +0 -3
- data/LICENSE +0 -13
- data/Rakefile +0 -15
- data/embulk-input-jira.gemspec +0 -27
- data/gemfiles/embulk-0.8.0-latest +0 -4
- data/gemfiles/embulk-0.8.7 +0 -4
- data/gemfiles/embulk-0.8.8 +0 -4
- data/gemfiles/embulk-latest +0 -4
- data/gemfiles/template.erb +0 -4
- data/lib/embulk/input/jira_api.rb +0 -9
- data/lib/embulk/input/jira_api/client.rb +0 -144
- data/lib/embulk/input/jira_api/issue.rb +0 -133
- data/lib/embulk/input/jira_input_plugin_utils.rb +0 -58
- data/spec/embulk/input/jira-input-plugin-utils_spec.rb +0 -89
- data/spec/embulk/input/jira_api/client_spec.rb +0 -224
- data/spec/embulk/input/jira_api/issue_spec.rb +0 -394
- data/spec/embulk/input/jira_spec.rb +0 -322
- data/spec/embulk_spec.rb +0 -32
- data/spec/spec_helper.rb +0 -26
- data/spec/support/stdout_and_err_capture.rb +0 -45
data/Gemfile
DELETED
data/LICENSE
DELETED
@@ -1,13 +0,0 @@
|
|
1
|
-
Copyright 2015 Everyleaf Corporation
|
2
|
-
|
3
|
-
Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
-
you may not use this file except in compliance with the License.
|
5
|
-
You may obtain a copy of the License at
|
6
|
-
|
7
|
-
http://www.apache.org/licenses/LICENSE-2.0
|
8
|
-
|
9
|
-
Unless required by applicable law or agreed to in writing, software
|
10
|
-
distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
-
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
-
See the License for the specific language governing permissions and
|
13
|
-
limitations under the License.
|
data/Rakefile
DELETED
@@ -1,15 +0,0 @@
|
|
1
|
-
require "bundler/gem_tasks"
|
2
|
-
require 'rspec/core/rake_task'
|
3
|
-
require "everyleaf/embulk_helper/tasks"
|
4
|
-
|
5
|
-
Everyleaf::EmbulkHelper::Tasks.install({
|
6
|
-
gemspec: "./embulk-input-jira.gemspec",
|
7
|
-
github_name: "treasure-data/embulk-input-jira",
|
8
|
-
})
|
9
|
-
|
10
|
-
task default: :spec
|
11
|
-
|
12
|
-
desc "Run all examples"
|
13
|
-
RSpec::Core::RakeTask.new(:spec) do |t|
|
14
|
-
t.rspec_opts = %w[--color]
|
15
|
-
end
|
data/embulk-input-jira.gemspec
DELETED
@@ -1,27 +0,0 @@
|
|
1
|
-
Gem::Specification.new do |spec|
|
2
|
-
spec.name = "embulk-input-jira"
|
3
|
-
spec.version = "0.2.5"
|
4
|
-
spec.authors = ["uu59", "yoshihara"]
|
5
|
-
spec.summary = "Jira input plugin for Embulk"
|
6
|
-
spec.description = "Loads records from Jira."
|
7
|
-
spec.email = ["k@uu59.org", "h.yoshihara@everyleaf.com"]
|
8
|
-
spec.licenses = ["Apache2"]
|
9
|
-
spec.homepage = "https://github.com/treasure-data/embulk-input-jira"
|
10
|
-
|
11
|
-
spec.files = `git ls-files`.split("\n") + Dir["classpath/*.jar"]
|
12
|
-
spec.test_files = spec.files.grep(%r{^(test|spec)/})
|
13
|
-
spec.require_paths = ["lib"]
|
14
|
-
|
15
|
-
spec.add_dependency 'jiralicious', ['~> 0.5.0']
|
16
|
-
spec.add_dependency 'parallel', ['~> 1.6.0']
|
17
|
-
spec.add_dependency 'ruby-limiter', ['~> 1.0']
|
18
|
-
spec.add_dependency 'perfect_retry', ['~> 0.3']
|
19
|
-
spec.add_development_dependency 'bundler', ['~> 1.0']
|
20
|
-
spec.add_development_dependency 'rake', ['< 11.0']
|
21
|
-
spec.add_development_dependency 'rspec', "~> 3.2.0"
|
22
|
-
spec.add_development_dependency 'embulk', ["~> 0.8.7"]
|
23
|
-
spec.add_development_dependency 'simplecov'
|
24
|
-
spec.add_development_dependency 'pry'
|
25
|
-
spec.add_development_dependency 'codeclimate-test-reporter'
|
26
|
-
spec.add_development_dependency 'everyleaf-embulk_helper'
|
27
|
-
end
|
data/gemfiles/embulk-0.8.7
DELETED
data/gemfiles/embulk-0.8.8
DELETED
data/gemfiles/embulk-latest
DELETED
data/gemfiles/template.erb
DELETED
@@ -1,144 +0,0 @@
|
|
1
|
-
require "jiralicious"
|
2
|
-
require "parallel"
|
3
|
-
require "limiter"
|
4
|
-
require "embulk/input/jira_api/issue"
|
5
|
-
require "timeout"
|
6
|
-
|
7
|
-
module Embulk
|
8
|
-
module Input
|
9
|
-
module JiraApi
|
10
|
-
class Client
|
11
|
-
MAX_RATE_LIMIT = 50
|
12
|
-
MIN_RATE_LIMIT = 2
|
13
|
-
# Normal http request timeout is 300s
|
14
|
-
SEARCH_ISSUES_TIMEOUT_SECONDS = 300
|
15
|
-
DEFAULT_SEARCH_RETRY_TIMES = 10
|
16
|
-
|
17
|
-
def initialize
|
18
|
-
@rate_limiter = Limiter::RateQueue.new(MAX_RATE_LIMIT, interval: 2)
|
19
|
-
end
|
20
|
-
|
21
|
-
def self.setup(&block)
|
22
|
-
Jiralicious.configure(&block)
|
23
|
-
new
|
24
|
-
end
|
25
|
-
|
26
|
-
def search_issues(jql, options={})
|
27
|
-
issues_raw = search(jql, options).issues_raw
|
28
|
-
# Maximum number of issues to retrieve is 50
|
29
|
-
rate_limit = MAX_RATE_LIMIT
|
30
|
-
success_items = []
|
31
|
-
fail_items = []
|
32
|
-
error_object = nil
|
33
|
-
timeout_and_retry(SEARCH_ISSUES_TIMEOUT_SECONDS * MAX_RATE_LIMIT ) do
|
34
|
-
retry_count = 0
|
35
|
-
semaphore = Mutex.new
|
36
|
-
@rate_limiter = Limiter::RateQueue.new(rate_limit, interval: 2)
|
37
|
-
error_object = nil
|
38
|
-
while issues_raw.length > 0 && retry_count <= DEFAULT_SEARCH_RETRY_TIMES do
|
39
|
-
Parallel.each(issues_raw, in_threads: rate_limit) do |issue_raw|
|
40
|
-
# https://github.com/dorack/jiralicious/blob/v0.4.0/lib/jiralicious/search_result.rb#L32-34
|
41
|
-
begin
|
42
|
-
issue = find_issue(issue_raw["key"])
|
43
|
-
semaphore.synchronize {
|
44
|
-
success_items.push(JiraApi::Issue.new(issue))
|
45
|
-
}
|
46
|
-
rescue MultiJson::ParseError => e
|
47
|
-
html = e.message
|
48
|
-
title = html[%r|<title>(.*?)</title>|, 1]
|
49
|
-
# 401 due to high number of concurrent requests with current account
|
50
|
-
# The number of concurrent requests is not fixed by every account
|
51
|
-
# Hence catch the error item and retry later
|
52
|
-
raise title if title != "Unauthorized (401)"
|
53
|
-
semaphore.synchronize {
|
54
|
-
fail_items.push(issue_raw)
|
55
|
-
error_object = e
|
56
|
-
}
|
57
|
-
end
|
58
|
-
end
|
59
|
-
retry_count += 1
|
60
|
-
rate_limit = calculate_rate_limit(rate_limit, issues_raw.length, fail_items.length, retry_count)
|
61
|
-
issues_raw = fail_items
|
62
|
-
fail_items = []
|
63
|
-
raise error_object if retry_count > DEFAULT_SEARCH_RETRY_TIMES && !error_object.nil?
|
64
|
-
# Sleep after some seconds for JIRA API perhaps under the overload
|
65
|
-
sleep retry_count if fail_items.length > 0
|
66
|
-
end
|
67
|
-
success_items
|
68
|
-
end
|
69
|
-
end
|
70
|
-
|
71
|
-
def search(jql, options={})
|
72
|
-
timeout_and_retry(SEARCH_ISSUES_TIMEOUT_SECONDS) do
|
73
|
-
Jiralicious.search(jql, options)
|
74
|
-
end
|
75
|
-
end
|
76
|
-
|
77
|
-
def total_count(jql)
|
78
|
-
search(jql, max_results: 1).num_results
|
79
|
-
end
|
80
|
-
|
81
|
-
def check_user_credential(username)
|
82
|
-
Jiralicious::User.search(username)
|
83
|
-
rescue Jiralicious::JqlError, Jiralicious::AuthenticationError, Jiralicious::NotLoggedIn, Jiralicious::InvalidLogin => e
|
84
|
-
raise Embulk::ConfigError.new(e.message)
|
85
|
-
rescue ::SocketError => e
|
86
|
-
# wrong `uri` option given
|
87
|
-
raise Embulk::ConfigError.new(e.message)
|
88
|
-
rescue MultiJson::ParseError => e
|
89
|
-
html = e.message
|
90
|
-
title = html[%r|<title>(.*?)</title>|, 1] #=> e.g. "Unauthorized (401)"
|
91
|
-
raise ConfigError.new("Can not authorize with your credential.") if title == 'Unauthorized (401)'
|
92
|
-
end
|
93
|
-
|
94
|
-
# Calculate rate limit based on previous run result
|
95
|
-
# Return 2 MIN_RATE_LIMIT in case turning from the 5th times or success_items is less than 2
|
96
|
-
# Otherwise return the min number between fail_items, success_items and current_limit
|
97
|
-
def calculate_rate_limit(current_limit, all_items, fail_items, times)
|
98
|
-
success_items = all_items - fail_items
|
99
|
-
return MIN_RATE_LIMIT if times >= DEFAULT_SEARCH_RETRY_TIMES/2 || success_items < MIN_RATE_LIMIT
|
100
|
-
return [fail_items, success_items, current_limit].min
|
101
|
-
end
|
102
|
-
|
103
|
-
private
|
104
|
-
|
105
|
-
def timeout_and_retry(wait, retry_times = DEFAULT_SEARCH_RETRY_TIMES, &block)
|
106
|
-
count = 0
|
107
|
-
begin
|
108
|
-
Timeout.timeout(wait) do
|
109
|
-
yield
|
110
|
-
end
|
111
|
-
rescue Jiralicious::JqlError, Jiralicious::AuthenticationError, Jiralicious::NotLoggedIn, Jiralicious::InvalidLogin => e
|
112
|
-
raise Embulk::ConfigError.new(e.message)
|
113
|
-
rescue ::SocketError => e
|
114
|
-
# wrong `uri` option given
|
115
|
-
raise Embulk::ConfigError.new(e.message)
|
116
|
-
rescue MultiJson::ParseError => e
|
117
|
-
# same as this Mailchimp plugin issue: https://github.com/treasure-data/embulk-output-mailchimp/issues/10
|
118
|
-
# (a) JIRA returns error as HTML, but HTTParty try to parse it as JSON.
|
119
|
-
# And (b) `search_issues` method has race-condition bug. If it occurred, MultiJson::ParseError raised too.
|
120
|
-
html = e.message
|
121
|
-
title = html[%r|<title>(.*?)</title>|, 1] #=> e.g. "Unauthorized (401)"
|
122
|
-
raise title if title == "Atlassian Cloud Notifications - Page Unavailable"
|
123
|
-
count += 1
|
124
|
-
raise title.nil? ? "Unknown Error" : title if count > retry_times
|
125
|
-
Embulk.logger.warn "JIRA returns error: #{title == 'Unauthorized (401)' ? title + " due to overloading API requests. Retrying on failed items only" : title}."
|
126
|
-
sleep count
|
127
|
-
retry
|
128
|
-
rescue Timeout::Error => e
|
129
|
-
count += 1
|
130
|
-
raise e if count > retry_times
|
131
|
-
Embulk.logger.warn "Time out error."
|
132
|
-
sleep count # retry after some seconds for JIRA API perhaps under the overload
|
133
|
-
retry
|
134
|
-
end
|
135
|
-
end
|
136
|
-
|
137
|
-
def find_issue(issue_key)
|
138
|
-
@rate_limiter.shift
|
139
|
-
Jiralicious::Issue.find(issue_key)
|
140
|
-
end
|
141
|
-
end
|
142
|
-
end
|
143
|
-
end
|
144
|
-
end
|
@@ -1,133 +0,0 @@
|
|
1
|
-
module Embulk
|
2
|
-
module Input
|
3
|
-
module JiraApi
|
4
|
-
class Issue
|
5
|
-
attr_reader :id, :key, :fields
|
6
|
-
|
7
|
-
def initialize(attributes)
|
8
|
-
@id = attributes.fetch("id")
|
9
|
-
|
10
|
-
# https://github.com/dorack/jiralicious/blob/404b7b6d5b7020f42064cf8d7a745ab02057e728/lib/jiralicious/issue.rb#L11-L12
|
11
|
-
@key = attributes.fetch("jira_key")
|
12
|
-
@fields = attributes.fetch("fields")
|
13
|
-
end
|
14
|
-
|
15
|
-
def [](attribute)
|
16
|
-
case attribute
|
17
|
-
when "id"
|
18
|
-
return id
|
19
|
-
when "key"
|
20
|
-
return key
|
21
|
-
end
|
22
|
-
|
23
|
-
attribute_keys = attribute.split('.')
|
24
|
-
|
25
|
-
fetch(fields, attribute_keys)
|
26
|
-
end
|
27
|
-
|
28
|
-
def to_record
|
29
|
-
@record = {}
|
30
|
-
|
31
|
-
@record["id"] = id
|
32
|
-
@record["key"] = key
|
33
|
-
|
34
|
-
generate_record(fields, "")
|
35
|
-
|
36
|
-
@record
|
37
|
-
end
|
38
|
-
|
39
|
-
private
|
40
|
-
|
41
|
-
def fetch(fields, keys)
|
42
|
-
return fields if fields.nil? || (fields.is_a?(Array) && fields.empty?)
|
43
|
-
|
44
|
-
if keys.empty?
|
45
|
-
case fields
|
46
|
-
when Array
|
47
|
-
values = fields.map do |field|
|
48
|
-
if field.is_a?(String)
|
49
|
-
field.to_s
|
50
|
-
else
|
51
|
-
field.to_json
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
return values.join(",")
|
56
|
-
when Hash
|
57
|
-
return fields.to_json
|
58
|
-
else
|
59
|
-
return fields
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
target_key = keys.shift
|
64
|
-
if fields.is_a?(Array)
|
65
|
-
values = fields.map do |field|
|
66
|
-
if field.is_a?(Hash)
|
67
|
-
field[target_key]
|
68
|
-
else
|
69
|
-
field.to_json
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
|
-
fetch(values, keys)
|
74
|
-
else
|
75
|
-
fetch(fields[target_key], keys)
|
76
|
-
end
|
77
|
-
end
|
78
|
-
|
79
|
-
def generate_record(value, prefix_key)
|
80
|
-
case value
|
81
|
-
when Hash
|
82
|
-
# NOTE: If you want to flatten JSON completely, please
|
83
|
-
# remove this if...end and #add_heuristic_value.
|
84
|
-
if prefix_key.count(".") > 1
|
85
|
-
add_heuristic_value(value, prefix_key)
|
86
|
-
return
|
87
|
-
end
|
88
|
-
|
89
|
-
value.each_pair do |_key, _value|
|
90
|
-
generate_record(_value, record_key(prefix_key, _key))
|
91
|
-
end
|
92
|
-
when Array
|
93
|
-
if value.empty? || value.any? {|v| !v.is_a?(Hash) }
|
94
|
-
@record[prefix_key] = "\"#{value.map(&:to_s).join(',')}\""
|
95
|
-
return
|
96
|
-
end
|
97
|
-
|
98
|
-
# gathering values from each Hash
|
99
|
-
keys = value.map(&:keys).inject([]) {|sum, key| sum + key }.uniq
|
100
|
-
values = value.inject({}) do |sum, elem|
|
101
|
-
keys.each {|key| sum[key] = (sum[key] || []) << elem[key] }
|
102
|
-
sum
|
103
|
-
end
|
104
|
-
|
105
|
-
generate_record(values, prefix_key)
|
106
|
-
else
|
107
|
-
@record[prefix_key] = value
|
108
|
-
end
|
109
|
-
end
|
110
|
-
|
111
|
-
def record_key(prefix, key)
|
112
|
-
return key if prefix.empty?
|
113
|
-
|
114
|
-
"#{prefix}.#{key}"
|
115
|
-
end
|
116
|
-
|
117
|
-
def add_heuristic_value(hash, prefix_key)
|
118
|
-
heuristic_values = hash.select do |key, value|
|
119
|
-
["name", "key", "id"].include?(key) && !value.nil?
|
120
|
-
end
|
121
|
-
|
122
|
-
if heuristic_values.empty?
|
123
|
-
@record[prefix_key] = hash.to_json
|
124
|
-
else
|
125
|
-
heuristic_values.each do |key, value|
|
126
|
-
@record[record_key(prefix_key, key)] = value
|
127
|
-
end
|
128
|
-
end
|
129
|
-
end
|
130
|
-
end
|
131
|
-
end
|
132
|
-
end
|
133
|
-
end
|
@@ -1,58 +0,0 @@
|
|
1
|
-
# This module contains methods for Plugin.
|
2
|
-
|
3
|
-
module Embulk::Guess
|
4
|
-
module SchemaGuess
|
5
|
-
class << self
|
6
|
-
|
7
|
-
# NOTE: Original #from_hash_records uses keys of the first record only,
|
8
|
-
# but JSON from JIRA API has fields which of value is sometimes nil,
|
9
|
-
# sometimes JSON,
|
10
|
-
# so the first record doesn't have all key for guess always.
|
11
|
-
# original Embulk::Guess::SchemaGuess is https://github.com/embulk/embulk/blob/57b42c31d1d539177e1e818f294550cde5b69e1f/lib/embulk/guess/schema_guess.rb#L16-L24
|
12
|
-
def from_hash_records(array_of_hash)
|
13
|
-
array_of_hash = Array(array_of_hash)
|
14
|
-
if array_of_hash.empty?
|
15
|
-
raise "SchemaGuess Can't guess schema from no records"
|
16
|
-
end
|
17
|
-
column_names = array_of_hash.map(&:keys).inject([]) {|r, a| r + a }.uniq.sort
|
18
|
-
samples = array_of_hash.to_a.map {|hash| column_names.map {|name| hash[name] } }
|
19
|
-
from_array_records(column_names, samples)
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
module Embulk
|
26
|
-
module Input
|
27
|
-
module JiraInputPluginUtils
|
28
|
-
# Guess::SchemaGuess.from_hash_records returns Columns
|
29
|
-
# containing 'index' key, but it is needless.
|
30
|
-
def self.guess_columns(records)
|
31
|
-
schema = Guess::SchemaGuess.from_hash_records(records)
|
32
|
-
|
33
|
-
schema.map do |c|
|
34
|
-
column = {name: c.name, type: c.type}
|
35
|
-
column[:format] = c.format if c.format
|
36
|
-
column
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
def self.cast(value, type)
|
41
|
-
return value if value.nil?
|
42
|
-
|
43
|
-
case type.to_sym
|
44
|
-
when :long
|
45
|
-
Integer(value)
|
46
|
-
when :double
|
47
|
-
Float(value)
|
48
|
-
when :timestamp
|
49
|
-
Time.parse(value)
|
50
|
-
when :boolean
|
51
|
-
!!value
|
52
|
-
else
|
53
|
-
value.to_s
|
54
|
-
end
|
55
|
-
end
|
56
|
-
end
|
57
|
-
end
|
58
|
-
end
|
@@ -1,89 +0,0 @@
|
|
1
|
-
require "spec_helper"
|
2
|
-
|
3
|
-
describe Embulk::Input::JiraInputPluginUtils do
|
4
|
-
describe ".guess_columns" do
|
5
|
-
subject do
|
6
|
-
Embulk::Input::JiraInputPluginUtils.guess_columns(records)
|
7
|
-
end
|
8
|
-
|
9
|
-
let(:records) do
|
10
|
-
[
|
11
|
-
{"project.key" => "FOO-1", "comment.total" => 3, "created" => "2015-03-01T00:12:00"},
|
12
|
-
{"project.id" => "1", "project.key" => "FOO", "comment.total" => 3, "created" => "2015-03-01T00:12:00"}
|
13
|
-
]
|
14
|
-
end
|
15
|
-
|
16
|
-
let(:expected) do
|
17
|
-
[
|
18
|
-
{name: "comment.total", type: :long},
|
19
|
-
{name: "created", type: :timestamp, format: "%Y-%m-%dT%H:%M:%S"},
|
20
|
-
{name: "project.id", type: :long},
|
21
|
-
{name: "project.key", type: :string},
|
22
|
-
]
|
23
|
-
end
|
24
|
-
|
25
|
-
it "returns Array containing columns without 'index' key from each record" do
|
26
|
-
expect(subject).to eq expected
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
describe ".cast" do
|
31
|
-
subject do
|
32
|
-
Embulk::Input::JiraInputPluginUtils.cast(value, type)
|
33
|
-
end
|
34
|
-
|
35
|
-
context "when value is nil" do
|
36
|
-
let(:value) { nil }
|
37
|
-
let(:type) { :string }
|
38
|
-
|
39
|
-
it "returns nil" do
|
40
|
-
expect(subject).to be_nil
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
context "when value is not nil" do
|
45
|
-
let(:value) { 123 }
|
46
|
-
|
47
|
-
context "and type is :string" do
|
48
|
-
let(:type) { :string }
|
49
|
-
|
50
|
-
it "returns '123'" do
|
51
|
-
expect(subject).to eq "123"
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
context "and type is :long" do
|
56
|
-
let(:type) { :long }
|
57
|
-
|
58
|
-
it "returns 123" do
|
59
|
-
expect(subject).to eq 123
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
context "and type is :double" do
|
64
|
-
let(:type) { :double }
|
65
|
-
|
66
|
-
it "returns 123.0" do
|
67
|
-
expect(subject).to eq 123.0
|
68
|
-
end
|
69
|
-
end
|
70
|
-
|
71
|
-
context "and type is :timestamp" do
|
72
|
-
let(:value) { "2015-03-01T00:12:00" }
|
73
|
-
let(:type) { :timestamp }
|
74
|
-
|
75
|
-
it "returns Time object" do
|
76
|
-
expect(subject).to eq Time.new(2015, 3, 1, 0, 12, 0)
|
77
|
-
end
|
78
|
-
end
|
79
|
-
|
80
|
-
context "and type is :boolean" do
|
81
|
-
let(:type) { :boolean }
|
82
|
-
|
83
|
-
it "returns true" do
|
84
|
-
expect(subject).to be true
|
85
|
-
end
|
86
|
-
end
|
87
|
-
end
|
88
|
-
end
|
89
|
-
end
|