spectro 0.2 → 0.3
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/LICENSE +21 -0
- data/README.md +51 -1
- data/lib/spectro.rb +14 -7
- data/lib/spectro/client.rb +12 -2
- data/lib/spectro/compiler.rb +53 -12
- data/lib/spectro/config.rb +22 -4
- data/lib/spectro/database.rb +22 -6
- data/lib/spectro/http_client.rb +26 -0
- data/lib/spectro/mock.rb +3 -5
- data/lib/spectro/spec.rb +16 -4
- data/lib/spectro/spec/parser.rb +36 -14
- data/lib/spectro/spec/rule.rb +8 -1
- data/lib/spectro/spec/signature.rb +12 -4
- data/spectro.png +0 -0
- metadata +22 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: dc30381812690e2250df10dfb5ae634da7856afc
|
4
|
+
data.tar.gz: 74972d706ae592c219e262dcac13cc6962b1bfeb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8287affb8337e7db19ff8f349e7e0739e8ee62677f930b29335053d5302ce41847adacb6ed0eae1a8206c07297d53e744c741f30d89ac6c789b344fee46b396f
|
7
|
+
data.tar.gz: 716ad339a11b90203172115493295589bf6ee454f2b73d21c01392bb6da5f0d8b3aaaf6b7782b76f8fe3f735c72798fae4372a9989520b1296229040915ec46b
|
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2015 Roberto Decurnex
|
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/README.md
CHANGED
@@ -1,7 +1,9 @@
|
|
1
|
-
|
1
|
+

|
2
2
|
|
3
3
|
Specs driven social meta-programming
|
4
4
|
|
5
|
+
[](http://badge.fury.io/rb/spectro)
|
6
|
+
[](https://gitter.im/robertodecurnex/spectro?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
|
5
7
|
[](https://travis-ci.org/robertodecurnex/spectro)
|
6
8
|
[](https://codeclimate.com/github/robertodecurnex/spectro)
|
7
9
|
[](https://codeclimate.com/github/robertodecurnex/spectro)
|
@@ -9,6 +11,8 @@ Specs driven social meta-programming
|
|
9
11
|
|
10
12
|
## Prototype
|
11
13
|
|
14
|
+
Spectro will fetch an algorithm to cover the given spec form its DB and will then define the `#hello` method using it.
|
15
|
+
|
12
16
|
```ruby
|
13
17
|
require 'spectro'
|
14
18
|
|
@@ -29,5 +33,51 @@ spec_for hello String -> String
|
|
29
33
|
```
|
30
34
|
|
31
35
|
```ruby
|
36
|
+
sample = Sample.new
|
37
|
+
|
32
38
|
sample.hello 'Eddie' #=> 'Say Hello to Eddie'
|
33
39
|
```
|
40
|
+
|
41
|
+
## Working with Mocks
|
42
|
+
|
43
|
+
### Scenarios
|
44
|
+
|
45
|
+
* Keep coding while waiting for an algorithm that covers your specs
|
46
|
+
* Using **Spectro** just to mock stuff
|
47
|
+
|
48
|
+
```ruby
|
49
|
+
require 'spectro'
|
50
|
+
|
51
|
+
class EmailValidator
|
52
|
+
|
53
|
+
include Spectro
|
54
|
+
|
55
|
+
implements \
|
56
|
+
valid?: [:email]
|
57
|
+
|
58
|
+
end
|
59
|
+
|
60
|
+
__END__
|
61
|
+
spec_for valid? String -> TrueClass|FalseClass
|
62
|
+
"valid@email.com" -> true
|
63
|
+
"invalidATemail.com" -> false
|
64
|
+
```
|
65
|
+
|
66
|
+
```ruby
|
67
|
+
require 'email_validator' #=> Spectro::Exception::UndefinedMethodDefinition
|
68
|
+
```
|
69
|
+
|
70
|
+
```ruby
|
71
|
+
Spectro.configure do |config|
|
72
|
+
config.enable_mocks!
|
73
|
+
end
|
74
|
+
|
75
|
+
require 'email_validator'
|
76
|
+
|
77
|
+
email_validator = EmailValidator.new
|
78
|
+
|
79
|
+
email_validator.valid?("valid@email.com") #=> true
|
80
|
+
email_validator.valid?("invalidATemail.com") #=> false
|
81
|
+
email_validator.valid?("unknown_param@email.com") #=> raise Spectro::Exception::UnkwnonMockResponse
|
82
|
+
|
83
|
+
```
|
data/lib/spectro.rb
CHANGED
@@ -1,11 +1,16 @@
|
|
1
|
+
require 'colorize'
|
1
2
|
require 'digest'
|
2
3
|
require 'forwardable'
|
4
|
+
require 'net/http'
|
3
5
|
require 'singleton'
|
6
|
+
require 'uri'
|
4
7
|
require 'yaml'
|
5
8
|
|
9
|
+
require 'spectro/compiler'
|
6
10
|
require 'spectro/config'
|
7
11
|
require 'spectro/database'
|
8
12
|
require 'spectro/exception'
|
13
|
+
require 'spectro/http_client'
|
9
14
|
require 'spectro/mock'
|
10
15
|
require 'spectro/spec'
|
11
16
|
|
@@ -16,27 +21,27 @@ module Spectro
|
|
16
21
|
def self.included klass
|
17
22
|
klass.extend(ClassMethods)
|
18
23
|
end
|
19
|
-
|
24
|
+
|
20
25
|
# Gives access to the Spectro::Config instance insde the given block
|
21
26
|
#
|
22
27
|
# Usage:
|
23
28
|
# Spectro.configure do |config|
|
24
29
|
# config.enable_mocks!
|
25
30
|
# end
|
26
|
-
def self.configure
|
31
|
+
def self.configure
|
27
32
|
yield Spectro::Config.instance
|
28
33
|
end
|
29
|
-
|
34
|
+
|
30
35
|
module ClassMethods
|
31
36
|
|
32
37
|
# Register the given method name supporting the given parameters.
|
33
38
|
#
|
34
|
-
# Whenever Spectro::Config.mocks_enabled? is true it will try to cover unfulfilled
|
35
|
-
# specs using the
|
39
|
+
# Whenever Spectro::Config.mocks_enabled? is true it will try to cover unfulfilled
|
40
|
+
# specs using the known rules as mocks.
|
36
41
|
#
|
37
|
-
# @param [{String, Symbol=><String, Symbol>}] interfaces hash of method names and required param names
|
42
|
+
# @param [{String, Symbol=><String, Symbol>}] interfaces hash of method names and required param names supported by the method
|
38
43
|
def implements interfaces
|
39
|
-
file_path = caller.first.match(
|
44
|
+
file_path = caller.first.match(/(?:^|#{Dir.pwd}\/)([^\/].*):\d+:in .+/)[1]
|
40
45
|
interfaces.each do |method_name, required_params|
|
41
46
|
λ = Spectro::Database.fetch(file_path, method_name, *required_params) || Spectro::Mock.create(file_path, method_name)
|
42
47
|
|
@@ -50,3 +55,5 @@ module Spectro
|
|
50
55
|
|
51
56
|
end
|
52
57
|
|
58
|
+
# Loads the current project config, if present
|
59
|
+
load '.spectro/config' if File.exist?('.spectro/config')
|
data/lib/spectro/client.rb
CHANGED
@@ -4,13 +4,23 @@ require 'thor'
|
|
4
4
|
module Spectro
|
5
5
|
|
6
6
|
class Client < Thor
|
7
|
-
|
7
|
+
|
8
8
|
desc 'compile', 'Parses the current project looking for unfulfilled specs and looks for suitable lambdas in the repos. It then updates the cache with them.'
|
9
9
|
def compile
|
10
|
-
require 'spectro/compiler'
|
11
10
|
Spectro::Compiler.compile
|
12
11
|
end
|
13
12
|
|
13
|
+
desc 'init', 'Initialize the current folder as an Spectro project, creating all the required files and folders.'
|
14
|
+
option :f, type: :boolean
|
15
|
+
def init
|
16
|
+
Spectro::Compiler.init options
|
17
|
+
end
|
18
|
+
|
19
|
+
desc 'upload', 'Uploads the undefined specs to the Hivein order to let the comunnity work and discuss over them.'
|
20
|
+
def upload
|
21
|
+
Spectro::HTTPClient.upload_undefined_specs
|
22
|
+
end
|
23
|
+
|
14
24
|
end
|
15
25
|
|
16
26
|
end
|
data/lib/spectro/compiler.rb
CHANGED
@@ -4,8 +4,8 @@ require 'yaml/store'
|
|
4
4
|
|
5
5
|
module Spectro
|
6
6
|
|
7
|
-
# Spectro
|
8
|
-
# updating the
|
7
|
+
# Spectro::Compiler is in charge of scan the projects and parse its files,
|
8
|
+
# updating the Spectroi's index and dumping information about the missing
|
9
9
|
# implementations (specs without an associated lambda)
|
10
10
|
class Compiler
|
11
11
|
|
@@ -13,32 +13,73 @@ module Spectro
|
|
13
13
|
|
14
14
|
class << self
|
15
15
|
extend Forwardable
|
16
|
-
def_delegators :instance, :compile
|
16
|
+
def_delegators :instance, :compile, :init
|
17
17
|
end
|
18
18
|
|
19
|
-
# Filters the project files keeping those
|
20
|
-
# It
|
21
|
-
# and creates an .spectro/undefined.yml with
|
19
|
+
# Filters the project files keeping those that make use of Spectro.
|
20
|
+
# It then parses them, check for missing implementations
|
21
|
+
# and creates an .spectro/undefined.yml with their specs.
|
22
22
|
#
|
23
23
|
# @return [Spectro::Compiler] self
|
24
|
-
def compile
|
24
|
+
def compile
|
25
|
+
if !Dir.exist?('.spectro')
|
26
|
+
abort "\n" + "This folder has not been initialzed as an Spectro project. Please run ".white.on_red + " spectro init ".white.on_light_black + " before compiling.".white.on_red + "\n\n"
|
27
|
+
end
|
28
|
+
|
25
29
|
undefined_yaml = YAML::Store.new(".spectro/undefined.yml")
|
26
30
|
undefined_yaml.transaction do
|
27
31
|
targets().map do |path|
|
28
32
|
missing_specs = missing_specs_from_file(path)
|
29
33
|
|
30
34
|
next if missing_specs.empty?
|
31
|
-
|
35
|
+
|
32
36
|
undefined_yaml[path] = missing_specs
|
33
37
|
end
|
34
38
|
end
|
35
|
-
|
39
|
+
|
36
40
|
return self
|
37
41
|
end
|
38
42
|
|
43
|
+
# Init the current folder as an Spectro project, creating all the required files and folders
|
44
|
+
# `.spectro` confg file
|
45
|
+
# `.spectro/index.yml` which will hold the mappings between Files/Method names and defined lambdas
|
46
|
+
# `.spectro/undefined.yml` which will hold the collection of spec definitions not yet fulfilled
|
47
|
+
# `.spectro/cache` folder that will hold the source code of the retrieved lambdas
|
48
|
+
#
|
49
|
+
# @return [Spectro::Compiler] self
|
50
|
+
def init options={}
|
51
|
+
if File.exist?('.spectro/config') && !options[:f]
|
52
|
+
abort "\n" + "Project already initialized. If you want to reset the curret setup you can run ".black.on_yellow + " spectro init -f ".white.on_light_black + "\n\n"
|
53
|
+
end
|
54
|
+
|
55
|
+
Dir.exist?('.spectro') || Dir.mkdir('.spectro')
|
56
|
+
Dir.exist?('.spectro/cache') || Dir.mkdir('.spectro/cache')
|
57
|
+
File.open('.spectro/config', 'w') do |file|
|
58
|
+
file.write <<-CONFIG
|
59
|
+
#!/usr/bin/env ruby
|
60
|
+
|
61
|
+
Spectro.configure do |config|
|
62
|
+
# Sets a custom API Hostname if needed
|
63
|
+
# config.api_hostname = 'localhost:9292'
|
64
|
+
#
|
65
|
+
# Instead of failing in case of unfulfilled functions it will try to use the local specs to get a result
|
66
|
+
# config.enable_mocks!
|
67
|
+
end
|
68
|
+
CONFIG
|
69
|
+
end
|
70
|
+
File.open('.spectro/index.yml', 'w') do |file|
|
71
|
+
end
|
72
|
+
File.open('.spectro/undefined.yml', 'w') do |file|
|
73
|
+
end
|
74
|
+
|
75
|
+
puts "\n" + "The project has been successfully initialized".black.on_blue + "\n\n"
|
76
|
+
|
77
|
+
return self
|
78
|
+
end
|
79
|
+
|
39
80
|
private
|
40
81
|
|
41
|
-
# Parse the specs on the given file path and return those
|
82
|
+
# Parse the specs on the given file path and return those
|
42
83
|
# that have not been fulfilled or need to be updated.
|
43
84
|
#
|
44
85
|
# @param [String] path target file path
|
@@ -50,13 +91,13 @@ module Spectro
|
|
50
91
|
end
|
51
92
|
end
|
52
93
|
|
53
|
-
# Filter project's rb files returning an Array of files
|
94
|
+
# Filter project's rb files returning an Array of files
|
54
95
|
# containinig specs to be parsed.
|
55
96
|
#
|
56
97
|
# @return [<String>] array of files to be parsed
|
57
98
|
def targets
|
58
99
|
return %x[ grep -Pzrl --include="*.rb" "^__END__.*\\n.*spec_for" . ].split("\n").collect do |path|
|
59
|
-
path[2..-1]
|
100
|
+
path[2..-1]
|
60
101
|
end
|
61
102
|
end
|
62
103
|
|
data/lib/spectro/config.rb
CHANGED
@@ -2,15 +2,33 @@ module Spectro
|
|
2
2
|
|
3
3
|
class Config
|
4
4
|
|
5
|
+
API_HOSTNAME = 'localhost:9292'
|
6
|
+
|
5
7
|
attr_accessor :mocks_enabled
|
6
|
-
|
8
|
+
|
7
9
|
include Singleton
|
8
10
|
|
9
11
|
class << self
|
10
12
|
extend Forwardable
|
11
|
-
def_delegators :instance, :enable_mocks!, :mocks_enabled?
|
13
|
+
def_delegators :instance, :api_hostname, :api_hostname=, :enable_mocks!, :mocks_enabled?
|
14
|
+
end
|
15
|
+
|
16
|
+
# Returns the API Hostname from the config
|
17
|
+
# or the default if missin
|
18
|
+
#
|
19
|
+
# @return [String] the API Hostname
|
20
|
+
def api_hostname
|
21
|
+
return @api_hostname || API_HOSTNAME
|
12
22
|
end
|
13
|
-
|
23
|
+
|
24
|
+
# Sets a custom API Hostname
|
25
|
+
#
|
26
|
+
# @param [String|NilClass] hostname the custom hostname or `nil` for the default
|
27
|
+
# @return [String|NilClass]
|
28
|
+
def api_hostname= hostname
|
29
|
+
@api_hostname = hostname
|
30
|
+
end
|
31
|
+
|
14
32
|
# Sets mocks_enabled to true
|
15
33
|
#
|
16
34
|
# @return [Spectro::Config] self
|
@@ -25,7 +43,7 @@ module Spectro
|
|
25
43
|
def mocks_enabled?
|
26
44
|
return !!self.mocks_enabled
|
27
45
|
end
|
28
|
-
|
46
|
+
|
29
47
|
end
|
30
48
|
|
31
49
|
end
|
data/lib/spectro/database.rb
CHANGED
@@ -2,9 +2,9 @@ module Spectro
|
|
2
2
|
|
3
3
|
# Gives access to the current collection of
|
4
4
|
# algorithms (lambdas) providing several ways
|
5
|
-
# to fetch specific elements by different
|
5
|
+
# to fetch specific elements by different criteria.
|
6
6
|
class Database
|
7
|
-
|
7
|
+
|
8
8
|
include Singleton
|
9
9
|
|
10
10
|
class << self
|
@@ -17,15 +17,21 @@ module Spectro
|
|
17
17
|
def initialize
|
18
18
|
self.cache = {}
|
19
19
|
end
|
20
|
-
|
20
|
+
|
21
21
|
# Lazy loads the index.yml and returns it
|
22
22
|
#
|
23
23
|
# @return [Hash] the parsed index.yml
|
24
24
|
def index
|
25
|
-
@index ||=
|
25
|
+
return @index ||= load_index()
|
26
26
|
end
|
27
|
-
|
28
|
-
#
|
27
|
+
|
28
|
+
# Sets the index cache to nil
|
29
|
+
# Just in case you want the database to parse the file once again
|
30
|
+
def reset_index
|
31
|
+
@index = nil
|
32
|
+
end
|
33
|
+
|
34
|
+
# Fetches and returns the target lambda based on the
|
29
35
|
# given class, method name and required aprameters.
|
30
36
|
#
|
31
37
|
# @param [String] file_path relative path of the file that requests the lambda
|
@@ -40,6 +46,16 @@ module Spectro
|
|
40
46
|
return self.cache[λ_id] ||= eval(File.read(".spectro/cache/#{λ_id}.rb"))
|
41
47
|
end
|
42
48
|
|
49
|
+
private
|
50
|
+
|
51
|
+
# Loads and returns the current project index or returns
|
52
|
+
# an empty one if not found
|
53
|
+
def load_index
|
54
|
+
return {} if !File.exist?('.spectro/index.yml')
|
55
|
+
|
56
|
+
return YAML.load_file('.spectro/index.yml') || {}
|
57
|
+
end
|
58
|
+
|
43
59
|
end
|
44
60
|
|
45
61
|
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Spectro
|
2
|
+
|
3
|
+
# Interact with the API exchanging specs and functions
|
4
|
+
class HTTPClient
|
5
|
+
|
6
|
+
include Singleton
|
7
|
+
|
8
|
+
class << self
|
9
|
+
extend Forwardable
|
10
|
+
def_delegators :instance, :upload_undefined_specs
|
11
|
+
end
|
12
|
+
|
13
|
+
def upload_undefined_specs
|
14
|
+
uri = URI.parse('http://' + Spectro::Config.api_hostname + '/api/specs')
|
15
|
+
file_path = '.spectro/undefined.yml'
|
16
|
+
|
17
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
18
|
+
request = Net::HTTP::Post.new(uri.request_uri)
|
19
|
+
request.body = File.read(file_path)
|
20
|
+
|
21
|
+
http.request(request)
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
data/lib/spectro/mock.rb
CHANGED
@@ -16,9 +16,7 @@ module Spectro
|
|
16
16
|
spec.signature.name == method_name.to_s
|
17
17
|
end
|
18
18
|
|
19
|
-
param_names =
|
20
|
-
('a'.ord+index).chr
|
21
|
-
end
|
19
|
+
param_names = ('a'..'z').first(spec.signature.params_types.count)
|
22
20
|
|
23
21
|
responses = spec.rules.inject({}) do |memo, rule|
|
24
22
|
memo[rule.params] = rule.output
|
@@ -26,13 +24,13 @@ module Spectro
|
|
26
24
|
end
|
27
25
|
|
28
26
|
return eval "
|
29
|
-
|
27
|
+
->(#{param_names.join(',')}) {
|
30
28
|
if !responses.has_key?([#{param_names.join(',')}])
|
31
29
|
raise Spectro::Exception::UnknownMockResponse.new(file_path, method_name)
|
32
30
|
end
|
33
31
|
|
34
32
|
return responses[[#{param_names.join(',')}]]
|
35
|
-
|
33
|
+
}
|
36
34
|
"
|
37
35
|
end
|
38
36
|
|
data/lib/spectro/spec.rb
CHANGED
@@ -5,13 +5,15 @@ require 'spectro/spec/signature'
|
|
5
5
|
module Spectro
|
6
6
|
|
7
7
|
class Spec
|
8
|
-
|
9
|
-
attr_accessor :md5, :rules, :signature
|
10
|
-
|
8
|
+
|
9
|
+
attr_accessor :md5, :description, :rules, :signature
|
10
|
+
|
11
11
|
# @param [String] spec md5
|
12
12
|
# @param [Spectro::Spec::Signature] signature spec signature
|
13
|
+
# @param [String] description spec's description
|
13
14
|
# @param [<Spectro::Spec::Rule>] rules collection of spec rules
|
14
|
-
def initialize md5, signature, rules
|
15
|
+
def initialize md5, signature, description, rules
|
16
|
+
self.description = description
|
15
17
|
self.md5 = md5
|
16
18
|
self.rules = rules
|
17
19
|
self.signature = signature
|
@@ -19,10 +21,20 @@ module Spectro
|
|
19
21
|
|
20
22
|
def == spec
|
21
23
|
return \
|
24
|
+
self.description == spec.description && \
|
22
25
|
self.signature == spec.signature && \
|
23
26
|
self.rules == spec.rules
|
24
27
|
end
|
25
28
|
|
29
|
+
def to_hash
|
30
|
+
return {
|
31
|
+
md5: self.md5,
|
32
|
+
description: self.description,
|
33
|
+
rules: self.rules.collect(&:to_hash),
|
34
|
+
signature: self.signature.to_hash
|
35
|
+
}
|
36
|
+
end
|
37
|
+
|
26
38
|
end
|
27
39
|
|
28
40
|
end
|
data/lib/spectro/spec/parser.rb
CHANGED
@@ -6,16 +6,16 @@ module Spectro
|
|
6
6
|
|
7
7
|
# Parser to get Spectro::Spec instances from the metadata on the program's files
|
8
8
|
class Parser
|
9
|
-
|
9
|
+
|
10
10
|
attr_accessor :file_path
|
11
|
-
|
11
|
+
|
12
12
|
# @param [String] file_path the path of the file to parse
|
13
13
|
def initialize file_path
|
14
14
|
self.file_path = file_path
|
15
15
|
end
|
16
16
|
|
17
17
|
# Create an instance of Spectro::Spec::Parser for the given file path
|
18
|
-
# and
|
18
|
+
# and returns the #parse response (the collection of Spectro::Spec instances
|
19
19
|
# for the given file)
|
20
20
|
#
|
21
21
|
# @param [String] file_path the path of the file to parse
|
@@ -24,7 +24,7 @@ module Spectro
|
|
24
24
|
Spectro::Spec::Parser.new(file_path).parse
|
25
25
|
end
|
26
26
|
|
27
|
-
#
|
27
|
+
# Looks for specs on the given file and parses them as Spectro::Specs
|
28
28
|
#
|
29
29
|
# @return [<Spectro::Spec>] collection of specs found in the given file path
|
30
30
|
def parse
|
@@ -32,33 +32,55 @@ module Spectro
|
|
32
32
|
return raw_specs.split('spec_for')[1..-1].map do |raw_spec|
|
33
33
|
self.parse_spec raw_spec
|
34
34
|
end
|
35
|
-
end
|
36
|
-
|
35
|
+
end
|
36
|
+
|
37
37
|
# Parses a raw spec and returns an Spectro::Spec instance
|
38
38
|
#
|
39
39
|
# @param [String] raw_spec raw spec
|
40
40
|
# @return [Spectro::Spec] the Spectro::Spec instance
|
41
41
|
def parse_spec raw_spec
|
42
|
-
spec_raw_signature, *
|
43
|
-
|
42
|
+
spec_raw_signature, *spec_raw_desc_and_rules = raw_spec.split("\n").reject(&:empty?)
|
43
|
+
|
44
44
|
spec_signature = self.parse_spec_signature(spec_raw_signature)
|
45
45
|
|
46
|
+
spec_raw_description = spec_raw_desc_and_rules.take_while do |desc_or_rule|
|
47
|
+
desc_or_rule.match(/^`/)
|
48
|
+
end
|
49
|
+
|
50
|
+
spec_description = self.parse_spec_description(spec_raw_description)
|
51
|
+
|
52
|
+
spec_raw_rules = spec_raw_desc_and_rules - spec_raw_description
|
53
|
+
|
46
54
|
spec_rules = spec_raw_rules.map do |spec_raw_rule|
|
47
55
|
self.parse_spec_rule(spec_raw_rule)
|
48
56
|
end
|
49
57
|
|
50
58
|
spec_md5 = Digest::MD5.hexdigest(raw_spec)
|
51
59
|
|
52
|
-
return Spectro::Spec.new(spec_md5, spec_signature, spec_rules)
|
60
|
+
return Spectro::Spec.new(spec_md5, spec_signature, spec_description, spec_rules)
|
61
|
+
end
|
62
|
+
|
63
|
+
# Returns the spec description from the raw spec description
|
64
|
+
#
|
65
|
+
# @param [String] spec_raw_description spec's raw description
|
66
|
+
# @return [String] spec description
|
67
|
+
def parse_spec_description(spec_raw_description)
|
68
|
+
return spec_raw_description.collect do |raw_description|
|
69
|
+
if raw_description[1..-1].empty?
|
70
|
+
next "\n"
|
71
|
+
end
|
72
|
+
|
73
|
+
next raw_description[1..-1].strip
|
74
|
+
end.join(' ').strip.gsub("\n ", "\n")
|
53
75
|
end
|
54
76
|
|
55
|
-
# Returns
|
77
|
+
# Returns an Spectro::Spec::Rule instance from the raw spec rule
|
56
78
|
#
|
57
|
-
# @param [String] spec_raw_rule raw rule
|
58
|
-
# @return [Spectro::Spec::Rule]
|
79
|
+
# @param [String] spec_raw_rule raw rule of the spec
|
80
|
+
# @return [Spectro::Spec::Rule] spec rule instance
|
59
81
|
def parse_spec_rule spec_raw_rule
|
60
82
|
# REGEX HERE PLEASE, F%#&!@* EASY
|
61
|
-
raw_params, raw_output = spec_raw_rule.split('->').map(&:strip)
|
83
|
+
raw_params, raw_output = spec_raw_rule.split('->').map(&:strip)
|
62
84
|
output = eval(raw_output)
|
63
85
|
params = raw_params.split(/,\s+/).map do |raw_param|
|
64
86
|
eval(raw_param)
|
@@ -70,7 +92,7 @@ module Spectro
|
|
70
92
|
# Returns a Spectro::Spec::Signature from the raw spec signature
|
71
93
|
#
|
72
94
|
# @param [String] spec_raw_signature raw signature of the spec
|
73
|
-
# @param [<Spectro::Spec::Signature]
|
95
|
+
# @param [<Spectro::Spec::Signature] spec signature instance
|
74
96
|
def parse_spec_signature spec_raw_signature
|
75
97
|
# REGEX HERE PLEASE, F%#&!@* EASY
|
76
98
|
raw_name_and_params_types, output_type = spec_raw_signature.split('->').map(&:strip)
|
data/lib/spectro/spec/rule.rb
CHANGED
@@ -7,7 +7,7 @@ module Spectro
|
|
7
7
|
class Rule
|
8
8
|
|
9
9
|
attr_accessor :output, :params
|
10
|
-
|
10
|
+
|
11
11
|
# @param [<Object>] parmas set of input params
|
12
12
|
# @param [<Object>] output expected result
|
13
13
|
def initialize params, output
|
@@ -21,6 +21,13 @@ module Spectro
|
|
21
21
|
self.params == rule.params
|
22
22
|
end
|
23
23
|
|
24
|
+
def to_hash
|
25
|
+
return {
|
26
|
+
output: self.output,
|
27
|
+
params: self.params
|
28
|
+
}
|
29
|
+
end
|
30
|
+
|
24
31
|
end
|
25
32
|
|
26
33
|
end
|
@@ -1,12 +1,12 @@
|
|
1
1
|
module Spectro
|
2
2
|
|
3
3
|
class Spec
|
4
|
-
|
5
|
-
# Representation of the required input/output types
|
4
|
+
|
5
|
+
# Representation of the required input/output types
|
6
6
|
class Signature
|
7
|
-
|
7
|
+
|
8
8
|
attr_accessor :name, :output_type, :params_types
|
9
|
-
|
9
|
+
|
10
10
|
# @param [String] name local name of the algorith (not sure if needed)
|
11
11
|
# @param [<String>] param_types types of the expected input params
|
12
12
|
# @param [String] output_type type of the expected output
|
@@ -23,6 +23,14 @@ module Spectro
|
|
23
23
|
self.params_types == signature.params_types
|
24
24
|
end
|
25
25
|
|
26
|
+
def to_hash
|
27
|
+
return {
|
28
|
+
name: self.name,
|
29
|
+
output_type: self.output_type,
|
30
|
+
params_type: self.params_types
|
31
|
+
}
|
32
|
+
end
|
33
|
+
|
26
34
|
end
|
27
35
|
|
28
36
|
end
|
data/spectro.png
ADDED
Binary file
|
metadata
CHANGED
@@ -1,15 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: spectro
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: '0.
|
4
|
+
version: '0.3'
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Roberto Decurnex
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2016-04-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: colorize
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
13
27
|
- !ruby/object:Gem::Dependency
|
14
28
|
name: thor
|
15
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -114,8 +128,11 @@ executables:
|
|
114
128
|
- spectro
|
115
129
|
extensions: []
|
116
130
|
extra_rdoc_files:
|
131
|
+
- LICENSE
|
117
132
|
- README.md
|
133
|
+
- spectro.png
|
118
134
|
files:
|
135
|
+
- LICENSE
|
119
136
|
- README.md
|
120
137
|
- bin/spectro
|
121
138
|
- lib/spectro.rb
|
@@ -126,11 +143,13 @@ files:
|
|
126
143
|
- lib/spectro/exception.rb
|
127
144
|
- lib/spectro/exception/undefined_method_definition.rb
|
128
145
|
- lib/spectro/exception/unknown_mock_response.rb
|
146
|
+
- lib/spectro/http_client.rb
|
129
147
|
- lib/spectro/mock.rb
|
130
148
|
- lib/spectro/spec.rb
|
131
149
|
- lib/spectro/spec/parser.rb
|
132
150
|
- lib/spectro/spec/rule.rb
|
133
151
|
- lib/spectro/spec/signature.rb
|
152
|
+
- spectro.png
|
134
153
|
homepage: http://github.com/robertodecurnex/spectro
|
135
154
|
licenses:
|
136
155
|
- MIT
|
@@ -151,7 +170,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
151
170
|
version: '0'
|
152
171
|
requirements: []
|
153
172
|
rubyforge_project:
|
154
|
-
rubygems_version: 2.
|
173
|
+
rubygems_version: 2.6.2
|
155
174
|
signing_key:
|
156
175
|
specification_version: 4
|
157
176
|
summary: Specs driven social meta-programming
|