screenplay 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: dbb612ed6af3abe140b84a1f5ff9f260c7d9b682
4
+ data.tar.gz: 6a7606ad77ba8dd2999d676b92d8b580b85759cb
5
+ SHA512:
6
+ metadata.gz: 1ae0e7d50879140a9f208e3ff93bdc3c27fa0b20ff01b2bd70df4529fe1aafab406c7d846be6e5c0f03a8a8bb32656d7539069de6b46c3bee2ea570bad1853e4
7
+ data.tar.gz: 4f3c5df6e4d8221f1b9950b9f76e1ff7164774e0098341680f3d5fe943fcc66fb8ae40c827061c73fdac718ce6c7bcfcf7ffad375796ac84664ac38b1755218d
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source 'http://rubygems.org'
2
+
3
+ gem 'rest-client', '~> 1.7.2'
4
+ gem 'highline', '~> 1.6.21'
5
+
6
+
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2014 Taco Jan Osinga
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/bin/screenplay ADDED
@@ -0,0 +1,61 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $:.unshift(File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib')))
4
+
5
+ require 'screenplay'
6
+ require 'optparse'
7
+
8
+ $SCREENPLAY_OPTIONS = {}
9
+
10
+ $ARGV_PARSER = OptionParser.new { | opts |
11
+ opts.banner = 'Usage: screenplay command [-c|--config FILE] [-a|--actors DIR] [-s|--scenarios DIR] [-v|--verbose] [-h|--human-friendly]'
12
+ opts.separator('')
13
+
14
+ opts.separator('Available commands:')
15
+ opts.separator('- play: Plays all scenarios.')
16
+ opts.separator('- actors: Lists all known actors.')
17
+ opts.separator('- scenarios: Lists all found scenarios.')
18
+ opts.separator('')
19
+
20
+ opts.separator('Specific options:')
21
+ opts.on('-c FILE', '--config FILE', 'Filename of the configuration file.') { | f | $SCREENPLAY_CONFIGFILE = f }
22
+ opts.on('-a DIR', '--actors DIR', 'Directory where custom actors can be found. By default in the ./actors directory near the config file.') { | d | $SCREENPLAY_ACTORS_DIR = d }
23
+ opts.on('-s DIR', '--scenarios DIR', 'Directory where the scenarios can be found. By default in the ./scenarios director near the config file.') { | d | $SCREENPLAY_SCENARIOS_DIR = d }
24
+ opts.on('-d', '--debug', 'Shows full stack trace on when failed. Especially usefull when developing new actors or other information.') { $SCREENPLAY_OPTIONS[:debug] = true }
25
+ opts.on('-q', '--quiet', 'Doesn\'t show the output of the scenes.') { $SCREENPLAY_OPTIONS[:quiet] = true }
26
+ opts.on('-h', '--human-friendly', 'Formats outputted JSON.') { $SCREENPLAY_OPTIONS[:human_friendly] = true }
27
+ opts.separator('')
28
+ }
29
+ command = $ARGV_PARSER.parse![0] rescue ''
30
+
31
+ def usage
32
+ STDOUT << $ARGV_PARSER.help
33
+ end
34
+
35
+ def play
36
+ Screenplay.prepare
37
+ begin
38
+ Screenplay.play($SCREENPLAY_OPTIONS)
39
+ rescue Exception => e
40
+ raise if $SCREENPLAY_OPTIONS[:debug]
41
+ abort(e.message)
42
+ end
43
+ end
44
+
45
+ def actors
46
+ Screenplay.prepare
47
+ Screenplay::Cast.each { | actor | puts actor.name }
48
+ end
49
+
50
+ def scenarios
51
+ Screenplay.prepare
52
+ Screenplay::Scenarios.each { | scenario | puts scenario.name }
53
+ end
54
+
55
+ case command
56
+ when 'play' then play
57
+ when 'actors' then actors
58
+ when 'scenarios' then scenarios
59
+ else usage
60
+ end
61
+
data/lib/screenplay.rb ADDED
@@ -0,0 +1,59 @@
1
+ $:.unshift(File.expand_path(File.dirname(__FILE__)))
2
+
3
+ require 'json'
4
+
5
+ require 'screenplay/datatype-extensions'
6
+ require 'screenplay/configuration'
7
+ require 'screenplay/cast'
8
+ require 'screenplay/actor'
9
+ require 'screenplay/scenarios'
10
+
11
+ module Screenplay
12
+ extend self
13
+
14
+ def prepare
15
+ Configuration.load
16
+ Cast.autoload
17
+ Scenarios.autoload
18
+ end
19
+
20
+ def play(options = {})
21
+ options[:quiet] ||= false
22
+ options[:human_friendly] ||= false
23
+
24
+ raise Exception.new('ERROR: Couldn\'t find any scenarios to play.') if Scenarios.size == 0
25
+
26
+ # First check if we know all needed actors
27
+ each_scene { | scenario_name, actor_name |
28
+ raise UnknownActorException.new(scenario_name, actor_name) if Cast.get(actor_name).nil?
29
+ }
30
+
31
+ each_scene { | scenario, actor_name, params, input, index |
32
+ puts "##### #{scenario.name} - #{actor_name}: #####" unless (options[:quiet])
33
+ begin
34
+ output = Cast.get(actor_name).play(params, input)
35
+ rescue Exception => e
36
+ raise ScenarioFailedException.new(scenario, index, actor_name, e.message)
37
+ end
38
+ output.symbolize_keys!
39
+ unless (options[:quiet])
40
+ output_str = options[:human_friendly] ? JSON.pretty_generate(output) : output.to_s
41
+ puts "output = #{output_str}"
42
+ puts ''
43
+ end
44
+ output
45
+ }
46
+ end
47
+
48
+ def each_scene
49
+ Scenarios.each { | scenario |
50
+ input = {}
51
+ index = 1
52
+ scenario.each { | actor_name, params |
53
+ input = yield scenario, actor_name, params, input, index
54
+ index += 1
55
+ }
56
+ }
57
+ end
58
+
59
+ end
@@ -0,0 +1,46 @@
1
+ require 'screenplay/cast'
2
+ require 'screenplay/configuration'
3
+
4
+ module Screenplay
5
+
6
+ class MethodNotImplemented < Exception
7
+
8
+ def initialize(name)
9
+ super("Method #{name} is not implemented.")
10
+ end
11
+
12
+ end
13
+
14
+
15
+ class UnknownActorException < Exception
16
+
17
+ def initialize(scenario, name)
18
+ super("The scenario #{scenario} uses unknown actor #{name}.")
19
+ end
20
+
21
+ end
22
+
23
+ class Actor
24
+
25
+ attr_reader :name
26
+
27
+ def initialize(name)
28
+ @name = name.to_sym
29
+ configure(Configuration[@name] || {})
30
+ end
31
+
32
+ def self.descendants
33
+ ObjectSpace.each_object(Class).select { | klass | klass < self }
34
+ end
35
+
36
+ def configure(config = {})
37
+ # Not needed to override this, but might be useful
38
+ end
39
+
40
+ def play(params, input)
41
+ raise MethodNotImplemented.new('play')
42
+ end
43
+
44
+ end
45
+
46
+ end
@@ -0,0 +1,64 @@
1
+ require 'rest_client'
2
+ require File.join(File.dirname(__FILE__), '..', 'actor')
3
+
4
+ module Screenplay
5
+
6
+ class WrongResponseCodeException < Exception
7
+ def initialize(expected, actual)
8
+ super("Expected HTTP response code #{expected}, but received #{actual}.")
9
+ end
10
+ end
11
+
12
+ class ApiActor < Actor
13
+
14
+ attr_reader :cookies
15
+
16
+ def configure(config)
17
+ @url = config[:url].to_s
18
+ @url += '/' unless @url.end_with?('/')
19
+ @request_headers = config[:request_headers] || {}
20
+ @cookies = nil
21
+ end
22
+
23
+ def play(params, input)
24
+ raise Exception.new('Missing configuration api.url') if @url == '/'
25
+ path = params[:path]
26
+ method = params[:method].downcase.to_sym rescue :get
27
+ expects = (params[:expect] || 200).to_i
28
+ data = params[:data] || {} rescue {}
29
+ data = input if (data.is_a?(String)) && (data == '$input')
30
+ data.stringify_keys!
31
+ headers = @request_headers
32
+ headers[:cookie] = @cookies unless @cookies.nil?
33
+ url = @url + path.to_s.replace_vars(input)
34
+ if ([:get, :head, :delete].include?(method))
35
+ headers[:params] = data
36
+ data = {}
37
+ end
38
+
39
+ begin
40
+ response = RestClient::Request.execute({
41
+ url: url,
42
+ method: method,
43
+ headers: headers,
44
+ payload: data
45
+ })
46
+ rescue => e
47
+ response = e.response
48
+ end
49
+
50
+ if response.code != expects
51
+ raise WrongResponseCodeException.new(expects, response.code)
52
+ end
53
+
54
+ unless response.nil?
55
+ output = JSON.parse(response.body) rescue {}
56
+ @cookies = response.headers[:set_cookie][0] rescue nil
57
+ end
58
+
59
+ return output || {}
60
+ end
61
+
62
+ end
63
+
64
+ end
@@ -0,0 +1,32 @@
1
+ require File.join(File.dirname(__FILE__), '..', 'actor')
2
+
3
+ module Screenplay
4
+
5
+ class CacheActor < Actor
6
+
7
+ attr_reader :cache
8
+
9
+ def play(params = {}, input = {})
10
+ @cache ||= {}
11
+ output = {}
12
+ params.each { | action, values |
13
+ output = input.dup if action == :merge
14
+
15
+ if action == :clear
16
+ @cache.clear
17
+ elsif action == :set
18
+ values.each { | input_key, cache_key |
19
+ @cache[cache_key.to_sym] = (input_key == '$input'.to_sym) ? input : input[input_key]
20
+ }
21
+ elsif (action == :merge || action == :get)
22
+ values.each { | cache_key, input_key |
23
+ output[input_key.to_sym] = @cache[cache_key.to_sym]
24
+ }
25
+ end
26
+ }
27
+ return output
28
+ end
29
+
30
+ end
31
+
32
+ end
@@ -0,0 +1,14 @@
1
+ require File.join(File.dirname(__FILE__), '..', 'actor')
2
+
3
+ module Screenplay
4
+
5
+ class DataActor < Actor
6
+
7
+ def play(params, input)
8
+ input.merge!(params)
9
+ return input
10
+ end
11
+
12
+ end
13
+
14
+ end
@@ -0,0 +1,18 @@
1
+ require File.join(File.dirname(__FILE__), '..', 'actor')
2
+ require 'highline/import'
3
+
4
+ module Screenplay
5
+
6
+ class PromptActor < Actor
7
+
8
+ def play(params, input)
9
+ output = input
10
+ params.each { | key, title |
11
+ output[key] = ask(title.replace_vars(input) + ': ') #{ | q | q.echo = true }
12
+ }
13
+ return output
14
+ end
15
+
16
+ end
17
+
18
+ end
@@ -0,0 +1,94 @@
1
+ require File.join(File.dirname(__FILE__), '..', 'actor')
2
+
3
+ module Screenplay
4
+
5
+ class TestFailedException < Exception
6
+ def initialize(test, a, b)
7
+ super("#{test} on #{a.to_s} failed. Expected: #{b.to_s}.")
8
+ end
9
+ end
10
+
11
+ class UnknownTestException < Exception
12
+ def initialize(test)
13
+ super("Unknown test #{test}")
14
+ end
15
+ end
16
+
17
+ class UnsupportedTypeTestException < Exception
18
+ def initialize(test, a)
19
+ super("Unsupported data type for test #{test}: #{a.to_s}")
20
+ end
21
+ end
22
+
23
+ class UnknownInputKeyException < Exception
24
+ def initialize(test, key)
25
+ super("Couldn't find #{key} in the input for test #{test}.")
26
+ end
27
+ end
28
+
29
+ class TestActor < Actor
30
+
31
+ def play(params, input)
32
+ params.each { | key, values |
33
+ values.each { | test, b |
34
+ expects = !test.to_s.start_with?('not-')
35
+ test = test.to_s[4..-1] unless expects
36
+ method = "test_#{test}".to_sym
37
+ raise UnknownTestException.new(test) if !respond_to?(method)
38
+ raise UnknownInputKeyException.new(test, key) unless input.include?(key.to_sym)
39
+ a = input[key.to_sym]
40
+ raise TestFailedException.new(test, a, b) unless (public_send(method, a, b) == expects)
41
+ }
42
+ }
43
+ return input
44
+ end
45
+
46
+ def test_lt(a, b)
47
+ a < b
48
+ end
49
+
50
+ def test_lte(a, b)
51
+ a <= b
52
+ end
53
+
54
+ def test_eq(a, b)
55
+ a === b
56
+ end
57
+
58
+ def test_gte(a, b)
59
+ a >= b
60
+ end
61
+
62
+ def test_gt(a, b)
63
+ a > b
64
+ end
65
+
66
+ def test_in(a, b)
67
+ if (b.is_a?(String))
68
+ b.index(a) != nil
69
+ elsif (b.is_a?(Array))
70
+ b.to_a.include?(a)
71
+ elsif (b.is_a?(Hash))
72
+ b.include?(a.to_sym)
73
+ else
74
+ raise UnsupportedTypeTestException.new(:in, b)
75
+ end
76
+ end
77
+
78
+ def test_size(a, b)
79
+ if (a.respond_to?(:size))
80
+ a.size == b
81
+ else
82
+ raise UnsupportedTypeTestException.new(:size, a)
83
+ end
84
+ end
85
+
86
+ def test_regexp(a, b)
87
+ b = Regexp.new(b.to_s) if b.is_a?(String) || b.is_a?(Symbol)
88
+ raise UnsupportedTypeTestException.new(:regexp, b) unless b.is_a?(Regexp)
89
+ raise UnsupportedTypeTestException.new(:regexp, a) unless a.is_a?(String)
90
+ !a.match(b).nil?
91
+ end
92
+ end
93
+
94
+ end
@@ -0,0 +1,49 @@
1
+ module Screenplay
2
+
3
+ # The Cast module is a singleton which is available for actors to register themselves and make themselves available.
4
+ module Cast
5
+ extend self
6
+
7
+ @actors = []
8
+
9
+ include Enumerable
10
+
11
+ def register(actor)
12
+ raise Exception.new("Actor #{actor.name} is already registered.") if @actors.include?(actor.name)
13
+ @actors.push(actor)
14
+ @actors.sort_by!{ | actor | actor.name }
15
+ end
16
+
17
+ def each
18
+ @actors.each { | actor | yield actor }
19
+ end
20
+
21
+ def get(actor_name)
22
+ @actors.each { | actor |
23
+ return actor if actor.name == actor_name.to_sym
24
+ }
25
+ return nil
26
+ end
27
+
28
+ def autoload
29
+ # Require all standard actors
30
+ Dir[File.dirname(__FILE__) + '/actors/*.rb'].each { | filename |
31
+ require filename
32
+ }
33
+ ## Require custom actors
34
+ @actors_path = $SCREENPLAY_ACTORS_DIR || Configuration[:general][:actors_dir] rescue File.join(Configuration.path, 'actors')
35
+ Dir[@actors_path + '/**/*.rb'].each { | filename |
36
+ require filename
37
+ }
38
+
39
+ ## Create an instance of each actor and register it to the cast
40
+ Actor.descendants.each { | klass |
41
+ name = klass.name.match(/(\w+)(Actor)?$/)[0].gsub(/Actor$/, '').snake_case
42
+ register(klass.new(name))
43
+ }
44
+ end
45
+
46
+
47
+ end
48
+
49
+ end
@@ -0,0 +1,38 @@
1
+ require 'yaml'
2
+ require 'screenplay/datatype-extensions'
3
+
4
+ module Screenplay
5
+
6
+ module Configuration
7
+ extend self
8
+
9
+ include Enumerable
10
+
11
+ @config = {}
12
+
13
+ def each
14
+ @config.each { | k, v | yield k, v }
15
+ end
16
+
17
+ def [](key)
18
+ @config[key]
19
+ end
20
+
21
+ def load(reload = false)
22
+ return unless @config.empty? || reload
23
+ @filename = $SCREENPLAY_CONFIGFILE || './config.yml'
24
+ @config = YAML.load_file(@filename) if File.exists?(@filename)
25
+ @config.symbolize_keys!
26
+ end
27
+
28
+ def path
29
+ File.dirname(@filename) || './'
30
+ end
31
+
32
+ def to_h
33
+ @config.to_h
34
+ end
35
+
36
+ end
37
+
38
+ end
@@ -0,0 +1,125 @@
1
+ # encoding: utf-8
2
+ # The classes in this file extend common datatypes with some extra functionality.
3
+
4
+ # The Boolean module is used to mixin in the TrueClass and FalseClass for easy comparison.
5
+ # This way fields can be given the Boolean datatype instead of a TrueClass or a FalseClass.
6
+ module Boolean
7
+ end
8
+
9
+
10
+ # Adds the Boolean module into the TrueClass as mixin
11
+ class TrueClass
12
+ include Boolean
13
+ end
14
+
15
+
16
+ # Adds the Boolean module into the FalseClass as mixin
17
+ class FalseClass
18
+ include Boolean
19
+ end
20
+
21
+
22
+ # Adds a few extra methods to the standard Hash
23
+ class Hash
24
+
25
+ # Removes all nil values from the hash. If the value is an array or hash, it will do this recursively.
26
+ def remove_nil_values!
27
+ self.delete_if { |_, v| v.nil? }
28
+ self.each { |_, v| v.remove_nil_values! if (v.is_a?(Hash) || v.is_a?(Array)) }
29
+ end
30
+
31
+ # Changes all keys to symbols. If the value is an array or hash, it will do this recursively.
32
+ def symbolize_keys!(recursive = true)
33
+ self.keys.each { | key |
34
+ if !key.is_a?(Symbol)
35
+ val = self.delete(key)
36
+ val.symbolize_keys! if (recursive && (val.is_a?(Hash) || val.is_a?(Array)))
37
+ self[(key.to_sym rescue key) || key] = val
38
+ end
39
+ self[key.to_sym].symbolize_keys! if (recursive && (self[key.to_sym].is_a?(Hash) || self[key.to_sym].is_a?(Array)))
40
+ }
41
+ end
42
+
43
+ # Changes all keys to strings. If the value is an array or hash, it will do this recursively.
44
+ def stringify_keys!(recursive = true)
45
+ self.keys.each do |key|
46
+ if !key.is_a?(String)
47
+ val = self.delete(key)
48
+ val.stringify_keys! if (recursive && (val.is_a?(Hash) || val.is_a?(Array)))
49
+ self[(key.to_s rescue key) || key] = val
50
+ end
51
+ end
52
+ end
53
+
54
+ end
55
+
56
+
57
+ # Adds a few extra methods to the standard Hash
58
+ class Array
59
+
60
+ # Removes all nil values from the hash. If the value is an array or hash, it will do this recursively.
61
+ def remove_nil_values!
62
+ self.compact!
63
+ self.each { |val| val.remove_nil_values! if (val.is_a?(Hash) || val.is_a?(Array)) }
64
+ end
65
+
66
+ # Changes all keys to symbols. If the value is an array or hash, it will do this recursively.
67
+ def symbolize_keys!(recursive = true)
68
+ self.map! { |val| val.symbolize_keys! if (recursive && (val.is_a?(Hash) || val.is_a?(Array))); val }
69
+ end
70
+
71
+ # Changes all keys to strings. If the value is an array or hash, it will do this recursively.
72
+ def stringify_keys!(recursive = true)
73
+ self.map! { |val| val.stringify_keys! if (recursive && (val.is_a?(Hash) || val.is_a?(Array))); val }
74
+ end
75
+
76
+ end
77
+
78
+
79
+ # Adds a few extra methods to the standard String
80
+ class String
81
+
82
+ # Returns true if a string is numeric.
83
+ def numeric?
84
+ self.to_i.to_s == self
85
+ end
86
+
87
+ # Strips single or double quotes at the start and end of the given string.
88
+ def strip_quotes
89
+ gsub(/\A['"]+|['"]+\Z/, '')
90
+ end
91
+
92
+ # Normalizes a string, remove diacritics (accents)
93
+ def normalize
94
+ tr(
95
+ "ÀÁÂÃÄÅàáâãäåĀāĂ㥹ÇçĆćĈĉĊċČčÐðĎďĐđÈÉÊËèéêëĒēĔĕĖėĘęĚěĜĝĞğĠġĢģĤĥĦħÌÍÎÏìíîïĨĩĪīĬĭĮįİıĴĵĶķĸĹĺĻļĽľĿŀŁłÑñŃńŅņŇňʼnŊŋÒÓÔÕÖØòóôõöøŌōŎŏŐőŔŕŖŗŘřŚśŜŝŞşŠšſŢţŤťŦŧÙÚÛÜùúûüŨũŪūŬŭŮůŰűŲųŴŵÝýÿŶŷŸŹźŻżŽž",
96
+ "AAAAAAaaaaaaAaAaAaCcCcCcCcCcDdDdDdEEEEeeeeEeEeEeEeEeGgGgGgGgHhHhIIIIiiiiIiIiIiIiIiJjKkkLlLlLlLlLlNnNnNnNnnNnOOOOOOooooooOoOoOoRrRrRrSsSsSsSssTtTtTtUUUUuuuuUuUuUuUuUuUuWwYyyYyYZzZzZz")
97
+ end
98
+
99
+ def truncate(max_length, ellipses = '...')
100
+ (self.length > max_length) ? self.to_s[0..max_length].gsub(/[^\w]\w+\s*$/, '...') : self.to_s
101
+ end
102
+
103
+ def replace_vars!(input)
104
+ input = {} unless input.is_a?(Hash)
105
+ return if input.empty?
106
+ matches = {}
107
+ input.each { | k, v | matches['#{' + k.to_s + '}'] = v.to_s }
108
+ self.gsub!(/\#({\w+})/, matches)
109
+ end
110
+
111
+ def replace_vars(input)
112
+ result = self.dup
113
+ result.replace_vars!(input)
114
+ return result
115
+ end
116
+
117
+ def snake_case
118
+ self.gsub(/::/, '/').gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').gsub(/([a-z\d])([A-Z])/,'\1_\2').tr('-', '_').downcase
119
+ end
120
+
121
+ def camel_case
122
+ self.split('_').collect(&:capitalize).join
123
+ end
124
+
125
+ end
@@ -0,0 +1,37 @@
1
+ require 'yaml'
2
+
3
+ module Screenplay
4
+
5
+ class ScenarioFailedException < Exception
6
+ def initialize(scenario, index, actor_name, message)
7
+ super("FAILED: Scenario #{scenario.name}, scene #{index} of #{scenario.size}, actor #{actor_name}: #{message}")
8
+ end
9
+ end
10
+
11
+ class Scenario
12
+
13
+ include Enumerable
14
+
15
+ attr_reader :name
16
+
17
+ def initialize(name, filename)
18
+ @name = name
19
+ @actions = YAML.load_file(filename)
20
+ @actions.symbolize_keys!
21
+ end
22
+
23
+ def each
24
+ @actions.each { | action |
25
+ actor = action.keys[0]
26
+ data = action[actor]
27
+ yield actor, data
28
+ }
29
+ end
30
+
31
+ def size
32
+ @actions.size
33
+ end
34
+
35
+ end
36
+
37
+ end
@@ -0,0 +1,38 @@
1
+ require 'screenplay/scenario'
2
+
3
+ module Screenplay
4
+
5
+ module Scenarios
6
+ extend self
7
+
8
+ include Enumerable
9
+
10
+ @scenarios = []
11
+
12
+ def register(filename)
13
+ name = filename.gsub(@path, '').gsub(/^\//, '') unless @path.empty?
14
+ @scenarios.push(Scenario.new(name, filename))
15
+ @scenarios.sort_by{ | actor | actor.name }
16
+ end
17
+
18
+ def autoload
19
+ @path = $SCREENPLAY_SCENARIOS_DIR || Configuration[:general][:scenarios_dir] rescue File.join(Configuration.path, 'scenarios')
20
+ load_path(@path)
21
+ end
22
+
23
+ def load_path(path)
24
+ yml_files = File.join(path, '**', '*.yml')
25
+ Dir[yml_files].each { | filename | register(filename) }
26
+ end
27
+
28
+ def size
29
+ @scenarios.size
30
+ end
31
+
32
+ def each
33
+ @scenarios.each { | k | yield k }
34
+ end
35
+
36
+ end
37
+
38
+ end
metadata ADDED
@@ -0,0 +1,88 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: screenplay
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.1
5
+ platform: ruby
6
+ authors:
7
+ - Taco Jan Osinga
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-08-31 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rest-client
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.7'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.7'
27
+ - !ruby/object:Gem::Dependency
28
+ name: highline
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.6'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.6'
41
+ description: Screenplay helps with testing data driven applications like RESTful API's
42
+ by writing scenario's in Yaml.
43
+ email: info@osingasoftware.nl
44
+ executables:
45
+ - screenplay
46
+ extensions: []
47
+ extra_rdoc_files: []
48
+ files:
49
+ - Gemfile
50
+ - LICENSE
51
+ - bin/screenplay
52
+ - lib/screenplay.rb
53
+ - lib/screenplay/actor.rb
54
+ - lib/screenplay/actors/api.rb
55
+ - lib/screenplay/actors/cache.rb
56
+ - lib/screenplay/actors/data.rb
57
+ - lib/screenplay/actors/prompt.rb
58
+ - lib/screenplay/actors/test.rb
59
+ - lib/screenplay/cast.rb
60
+ - lib/screenplay/configuration.rb
61
+ - lib/screenplay/datatype-extensions.rb
62
+ - lib/screenplay/scenario.rb
63
+ - lib/screenplay/scenarios.rb
64
+ homepage: https://github.com/tjosinga/screenplay
65
+ licenses:
66
+ - MIT
67
+ metadata: {}
68
+ post_install_message:
69
+ rdoc_options: []
70
+ require_paths:
71
+ - lib
72
+ required_ruby_version: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - ">="
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
77
+ required_rubygems_version: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - ">="
80
+ - !ruby/object:Gem::Version
81
+ version: '0'
82
+ requirements: []
83
+ rubyforge_project:
84
+ rubygems_version: 2.2.2
85
+ signing_key:
86
+ specification_version: 4
87
+ summary: Screenplay
88
+ test_files: []