screenplay 0.1.1

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 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: []