Class: NewmanScenario::Scenario

Inherits:
Object
  • Object
show all
Defined in:
lib/newman_scenario/scenario.rb

Constant Summary collapse

DEFAULT_CUSTOM_SCENARIOS_FILE_PATH =
'newman_scenarios.json'.freeze
DEFAULT_LAST_SCENARIO_FILE_PATH =
'/tmp/last_newman_scenario.json'.freeze
DEBUG =
false

Class Attribute Summary collapse

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(collection_id: nil, environments: nil, api_key: nil, custom_collection_file_path: nil, last_scenario_file_path: nil) ⇒ Scenario

Returns a new instance of Scenario.



98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
# File 'lib/newman_scenario/scenario.rb', line 98

def initialize(collection_id: nil, environments: nil, api_key: nil, custom_collection_file_path: nil, last_scenario_file_path: nil)
  self.collection_id ||= self.class.default_collection_id
  raise ConfigurationError, 'Missing Collection Id' unless self.collection_id

  self.environments ||= self.class.default_environments
  self.environments ||= JSON.parse(ENV['NEWMAN_SCENARIO_ENVIRONMENTS'], symbolize_names: true) if ENV['NEWMAN_SCENARIO_ENVIRONMENTS']
  raise ConfigurationError, 'Missing Environment Ids' unless self.environments

  self.api_key ||= self.class.default_api_key
  raise ConfigurationError, 'Missing Postman API Key' unless self.api_key

  self.custom_collection_file_path ||= self.class.default_custom_scenarios_file_path
  raise ConfigurationError, 'Missing Custom collection file path' unless self.custom_collection_file_path

  self.last_scenario_file_path ||= self.class.default_last_scenario_file_path
  raise ConfigurationError, 'Missing Last scenario file path' unless self.last_scenario_file_path
rescue ConfigurationError => e
  prompt.warn e
  if prompt.yes?('Configure?')
    self.class.configure
    retry
  end
end

Class Attribute Details

.default_api_keyObject

Returns the value of attribute default_api_key.



22
23
24
# File 'lib/newman_scenario/scenario.rb', line 22

def default_api_key
  @default_api_key
end

.default_collection_idObject

Returns the value of attribute default_collection_id.



23
24
25
# File 'lib/newman_scenario/scenario.rb', line 23

def default_collection_id
  @default_collection_id
end

.default_custom_scenarios_file_pathObject

Returns the value of attribute default_custom_scenarios_file_path.



25
26
27
# File 'lib/newman_scenario/scenario.rb', line 25

def default_custom_scenarios_file_path
  @default_custom_scenarios_file_path
end

.default_environmentsObject

Returns the value of attribute default_environments.



24
25
26
# File 'lib/newman_scenario/scenario.rb', line 24

def default_environments
  @default_environments
end

.default_last_scenario_file_pathObject

Returns the value of attribute default_last_scenario_file_path.



26
27
28
# File 'lib/newman_scenario/scenario.rb', line 26

def default_last_scenario_file_path
  @default_last_scenario_file_path
end

Instance Attribute Details

#api_keyObject

Returns the value of attribute api_key.



94
95
96
# File 'lib/newman_scenario/scenario.rb', line 94

def api_key
  @api_key
end

#collection_idObject

Returns the value of attribute collection_id.



92
93
94
# File 'lib/newman_scenario/scenario.rb', line 92

def collection_id
  @collection_id
end

#custom_collection_file_pathObject

Returns the value of attribute custom_collection_file_path.



95
96
97
# File 'lib/newman_scenario/scenario.rb', line 95

def custom_collection_file_path
  @custom_collection_file_path
end

#environmentsObject

Returns the value of attribute environments.



93
94
95
# File 'lib/newman_scenario/scenario.rb', line 93

def environments
  @environments
end

#last_scenario_file_pathObject

Returns the value of attribute last_scenario_file_path.



96
97
98
# File 'lib/newman_scenario/scenario.rb', line 96

def last_scenario_file_path
  @last_scenario_file_path
end

Class Method Details

.configure(default_api_key: nil, default_collection_id: nil, default_environments: nil, default_custom_scenarios_file_path: nil, default_last_scenario_file_path: nil) ⇒ Object



28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/newman_scenario/scenario.rb', line 28

def configure(default_api_key: nil, default_collection_id: nil, default_environments: nil, default_custom_scenarios_file_path: nil, default_last_scenario_file_path: nil)
  self.default_api_key = default_api_key || prompt.mask('Postman API Key (https://YOURPOSTMAN.postman.co/settings/me/api-keys):', value: ENV['POSTMAN_API_KEY'].to_s)
  collections = nil
  environments = nil
  if prompt.yes?('Using workspace?')
    workspaces = fetch_postman('/workspaces', api_key: self.default_api_key).parsed_response&.fetch('workspaces', nil) || []
    workspaces = workspaces.map { |workspace| workspace.slice('name', 'id').values }.to_h
    workspace = prompt.select('Workspace', workspaces)
    workspace = fetch_postman("/workspaces/#{workspace}", api_key: self.default_api_key).parsed_response&.fetch('workspace', nil) || {}
    collections = workspace['collections']
    environments = workspace['environments']
  end
  collections ||= fetch_postman('/collections', api_key: self.default_api_key).parsed_response&.fetch('collections', nil) || []
  collections = collections.map { |collection| collection.slice('name', 'id').values }.to_h
  self.default_collection_id = default_collection_id || prompt.select('Postman Collection', collections, default: 1)
  self.default_environments = default_environments
  unless self.default_environments
    environments ||= fetch_postman('/environments', api_key: self.default_api_key).parsed_response&.fetch('environments', nil) || []
    environments = environments.map { |environment| environment.slice('name', 'id').values }.to_h
    environment_ids = prompt.multi_select('Environment', environments)
    self.default_environments = environments.select { |_, id| environment_ids.include?(id) }
  end
  self.default_custom_scenarios_file_path = default_custom_scenarios_file_path || prompt.ask('Custom scenarios file path:', value: DEFAULT_CUSTOM_SCENARIOS_FILE_PATH)
  self.default_last_scenario_file_path = default_last_scenario_file_path || prompt.ask('Last scenario file path:', value: DEFAULT_LAST_SCENARIO_FILE_PATH)
  if (env_path = prompt.ask('Save to: [enter to not save]', value: '.env'))
    envs = {
      POSTMAN_API_KEY: self.default_api_key,
      NEWMAN_SCENARIO_COLLECTION_ID: self.default_collection_id,
      NEWMAN_SCENARIO_ENVIRONMENTS: self.default_environments.to_json,
      NEWMAN_SCENARIO_CUSTOM_COLLECTION_FILE_PATH: self.default_custom_scenarios_file_path,
      NEWMAN_SCENARIO_LAST_SCENARIO_FILE_PATH: self.default_last_scenario_file_path,
    }
    existing_lines = []
    if File.exists?(env_path)
      existing_lines = File.readlines(env_path).reject { |line| envs.keys.include?(line.split(':').first.to_sym) }
    else
      existing_lines = []
    end
    File.open(env_path, 'w+') do |file|
      existing_lines.each { |line| file.puts line }
      file.puts "POSTMAN_API_KEY: #{self.default_api_key}"
      file.puts "NEWMAN_SCENARIO_COLLECTION_ID: #{self.default_collection_id}"
      file.puts "NEWMAN_SCENARIO_ENVIRONMENTS: #{self.default_environments.to_json}"
      file.puts "NEWMAN_SCENARIO_CUSTOM_COLLECTION_FILE_PATH: #{self.default_custom_scenarios_file_path}"
      file.puts "NEWMAN_SCENARIO_LAST_SCENARIO_FILE_PATH: #{self.default_last_scenario_file_path}"
    end
  end
end

.fetch_postman(url_path, expected_response_codes: [200], api_key: nil) ⇒ Object

Raises:



77
78
79
80
81
82
83
# File 'lib/newman_scenario/scenario.rb', line 77

def fetch_postman(url_path, expected_response_codes: [200], api_key: nil)
  puts "fetching #{url_path}" if DEBUG
  response = HTTParty.get("https://api.getpostman.com#{url_path}", headers: { 'X-Api-Key' => api_key})
  raise Error, "Invalid response code: #{response.code}" unless expected_response_codes.include?(response.code)

  response
end

Instance Method Details

#run(environment_name: nil, scenario_name: nil, bail: true, no_prompt: false) ⇒ Object



122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
# File 'lib/newman_scenario/scenario.rb', line 122

def run(environment_name: nil, scenario_name: nil, bail: true, no_prompt: false)
  return if `which newman`.empty? && !prompt_to_install_newman

  environment = environments[environment_name.to_sym] if environment_name
  environment ||= prompt.select('Environment', environments, default: 1)
  load_postman_environment(environment, no_prompt: no_prompt)
  collection = JSON.parse(File.read("/tmp/postman-collection-#{collection_id}.json"), symbolize_names: true)[:collection]
  unless File.exist?(last_scenario_file_path) && (!scenario_name && prompt.yes?('Replay last scenario?'))
    scenarii = read_from_json_file(custom_collection_file_path) || {}
    scenario_name ||= prompt.select('Scenario', ['Custom Scenario'] + scenarii.keys.sort)
    scenario_requests = (scenario_name == 'Custom Scenario' && []) || scenarii[scenario_name]
    if scenario_requests.empty?
      scenario_requests = []
      extract_all_requests = lambda do |item, prefix|
        request_name = "#{prefix.empty? ? '' : "#{prefix}/" }#{item[:name]}"
        request_names = [request_name] + (item[:item]&.map { |child_item| extract_all_requests.call(child_item, request_name) } || [])
        request_names
      end
      all_request_names = extract_all_requests.call(collection, '')
      loop do
        scenario_requests.delete('duplicate')
        scenario_requests += prompt.multi_select('Requests (type to filter prefix, choose duplicate to perform action multiple times)', ['duplicate'] + all_request_names, cycle: true, filter: true)
        break unless scenario_requests.include?('duplicate')

      end
      if prompt.yes?('Save this custom scenario?')
        name = prompt.ask('Name?')
        new_or_overwrite = !scenarii.key?(name) || !prompt.no?('This scenario exist, overwrite it?')
        if new_or_overwrite
          prompt.ok "Adding/Updating #{name} to scenarii"
          scenarii[name] = scenario_requests
          write_to_json_file(custom_collection_file_path, scenarii, pretty: true)
        end
      end
    end
    find_request = lambda do |request_path, items|
      item = items.find { |i| i[:name] == request_path.last }
      if item
        item
      else
        child_item = items.find { |i| i[:name] == request_path.first }
        if child_item
          request_path = request_path.drop(1)
          if request_path.empty?
            child_item
          else
            find_request.call(request_path, child_item[:item])
          end
        end
      end
    end
    requests = scenario_requests.map do |scenario_request|
      find_request.call(scenario_request.split('/'), collection[:item])
    end
    new_collection = {
      collection: {
        info: {
          name: scenario_name,
          schema: 'https://schema.getpostman.com/json/collection/v2.1.0/collection.json'
        },
        item: requests
      }
    }
    write_to_json_file(last_scenario_file_path, new_collection)
  end
  exec("newman run #{last_scenario_file_path} -e /tmp/postman-environment-#{environment}.json#{bail ? ' --bail' : ''}")
end