tune_spec 0.1.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ba1ac17c65ab0ae068e158cc836591d4abaef024
4
- data.tar.gz: 3d92daa8e33f2d4e0a8e1ecf12bb46e76f47f969
3
+ metadata.gz: 94acadc6b27a86f11ef371aac9e2a90f180ea57b
4
+ data.tar.gz: 28eee0395583b8732170a452bec26176ecb2f1d0
5
5
  SHA512:
6
- metadata.gz: 42ac8bd3f9dffa5a88c4505ec3e9c5b0bc9294a8fd0b808641790e325f5bd165d6b3b73faa9adb0496979fc97dada22ab41d58e4c0db6d1b65f610032204dd1e
7
- data.tar.gz: 8451e1019f006a943aeadef2cae531b74d361d81b053d1d1f2d147d8414cd5c2a21a232f0afd1ed7876c24f54a9ae17ef6c3ae1c11ce5ce52452a236d8f7300a
6
+ metadata.gz: d4377597a557a0ddc9208e1fb88be8204debdced3dd17f2325f1580e0c9efa1a7a827d35dd3cd4500a15f20f35ac08a0253c6e799f528b97f673212e745becbf
7
+ data.tar.gz: 916bf7c6f7c77d25ffd7d4b0467b8991bbd6ffbc62ddcb63aa2ab8bb514a0afaadc18c1fffab1f5639ac59f86430072da8c7f89e3752777d466aad767a38972d
data/.gitignore CHANGED
@@ -1,2 +1,7 @@
1
+ *.gem
2
+ .yardoc/
3
+ doc/
4
+
1
5
  /tags
2
6
  *.swp
7
+ *.vim
data/Gemfile CHANGED
@@ -1,6 +1,8 @@
1
- source "https://rubygems.org"
1
+ # frozen_string_literal: true
2
2
 
3
- git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
3
+ source 'https://rubygems.org'
4
+
5
+ git_source(:github) { |repo_name| "https://github.com/#{repo_name}" }
4
6
 
5
7
  # Specify your gem's dependencies in tune_spec.gemspec
6
8
  gemspec
data/Gemfile.lock CHANGED
@@ -1,20 +1,43 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- tune_spec (0.1.0)
4
+ tune_spec (0.3.0)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
8
8
  specs:
9
- rake (10.5.0)
9
+ ast (2.3.0)
10
+ minitest (5.10.3)
11
+ parallel (1.12.0)
12
+ parser (2.4.0.0)
13
+ ast (~> 2.2)
14
+ powerpack (0.1.1)
15
+ rainbow (2.2.2)
16
+ rake
17
+ rake (12.1.0)
18
+ rubocop (0.50.0)
19
+ parallel (~> 1.10)
20
+ parser (>= 2.3.3.1, < 3.0)
21
+ powerpack (~> 0.1)
22
+ rainbow (>= 2.2.2, < 3.0)
23
+ ruby-progressbar (~> 1.7)
24
+ unicode-display_width (~> 1.0, >= 1.0.1)
25
+ ruby-progressbar (1.9.0)
26
+ unicode-display_width (1.3.0)
27
+ yard (0.9.9)
28
+ yard-doctest (0.1.10)
29
+ minitest
30
+ yard
10
31
 
11
32
  PLATFORMS
12
33
  ruby
13
34
 
14
35
  DEPENDENCIES
15
36
  bundler (~> 1.15)
16
- rake (~> 10.0)
37
+ rubocop (~> 0.50.0)
17
38
  tune_spec!
39
+ yard (~> 0.9.9)
40
+ yard-doctest (~> 0.1.10)
18
41
 
19
42
  BUNDLED WITH
20
- 1.15.4
43
+ 1.16.0.pre.3
data/README.md CHANGED
@@ -20,7 +20,53 @@ Or install it yourself as:
20
20
 
21
21
  ## Usage
22
22
 
23
- TODO: Write usage instructions here
23
+ To initialize framework folder structure run:
24
+
25
+ $ tune --init
26
+
27
+ It creates a folder tree within your working directory:
28
+
29
+ ```
30
+ lib
31
+ ├── groups
32
+ ├── pages
33
+ └── steps
34
+ ```
35
+
36
+ In your framework include the module:
37
+
38
+ ```ruby
39
+ include TuneSpec::Instances
40
+ ```
41
+
42
+ Then you can use TuneSpec DSL to store instances of your Groups, Steps and Page objects.
43
+ Assume that you have LoginPage object and LoginSteps and LoginGroups:
44
+ ```ruby
45
+ pages(:login).fill_in 'Email', with: 'user@example.com'
46
+ pages(:login).fill_in 'Password', with: 'password'
47
+ pages(:login).login.click
48
+ ```
49
+
50
+ Or in your LoginSteps you can describe steps as a a group of interactions and verifications on a page:
51
+ ```ruby
52
+ steps(:login).visit_page
53
+ steps(:login).login_with_valid_credentials
54
+ steps(:login).verify_login
55
+ ```
56
+
57
+ You can go further and organize your steps within a group when details don't matter
58
+ ```ruby
59
+ groups(:login).complete
60
+ ```
61
+
62
+ The default instantiation of each of your objects is configurable:
63
+ ```ruby
64
+ TuneSpec.configure do |config|
65
+ config.page_opts = { env: ENV['TEST_ENV'] }
66
+ config.steps_opts = { env: ENV['TEST_ENV'], page: :home }
67
+ config.groups_opts = {}
68
+ end
69
+ ```
24
70
 
25
71
  ## Development
26
72
 
data/bin/console CHANGED
@@ -1,7 +1,8 @@
1
1
  #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
2
3
 
3
- require "bundler/setup"
4
- require "tune_spec"
4
+ require 'bundler/setup'
5
+ require 'tune_spec'
5
6
 
6
- require "irb"
7
+ require 'irb'
7
8
  IRB.start(__FILE__)
data/doctest_helper.rb ADDED
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'tune_spec'
4
+ require 'fileutils'
5
+
6
+ include TuneSpec::Instances
7
+ TEST_ENV = 'STG'
8
+
9
+ TuneSpec.configure do |conf|
10
+ conf.directory = 'test'
11
+ conf.groups_opts = { env: TEST_ENV }
12
+ conf.steps_opts = { env: TEST_ENV }
13
+ conf.page_opts = { env: TEST_ENV }
14
+ end
15
+
16
+ def create_file(name, type)
17
+ folder_name = type == :page ? 'pages' : type.to_s
18
+ file_name = "test/#{folder_name}/#{name}_#{type}.rb"
19
+ FileUtils.mkdir_p("test/#{folder_name}")
20
+ File.open(file_name, 'w+') { |f| f << file_content(name, type) }
21
+ end
22
+
23
+ def file_content(name, type)
24
+ <<~FILE
25
+ class_name = "#{name.capitalize}#{type.capitalize}"
26
+ klass = Object.const_set(class_name, Class.new)
27
+
28
+ klass.class_eval do
29
+ case "#{type}"
30
+ when 'groups'
31
+ define_method('initialize') do |env|; end
32
+ define_method('complete') do; end
33
+ when 'steps'
34
+ define_method('initialize') do |env, page_object|; end
35
+ define_method('verify_result') do; end
36
+ when 'page'
37
+ define_method('initialize') do |env|; end
38
+ define_method('click_element') do; end
39
+ end
40
+ end
41
+ FILE
42
+ end
43
+
44
+ create_file(:login, :groups)
45
+ create_file(:calculator, :steps)
46
+ create_file(:home, :page)
47
+
48
+ YARD::Doctest.configure do |doctest|
49
+ doctest.after_run do
50
+ FileUtils.rm_rf('test')
51
+ end
52
+ end
data/exe/tune CHANGED
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
2
3
 
3
4
  require 'bundler/setup'
4
5
  require 'tune_spec/parser'
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ module TuneSpec
4
+ # Defines all configurable attributes of TuneSpec
5
+ module Configuration
6
+ VALID_CONFIG_KEYS = %i[directory page_opts steps_opts groups_opts].freeze
7
+
8
+ DEFAULT_DIRECTORY = 'lib'
9
+
10
+ DEFAULT_PAGE_OPTS = {}.freeze
11
+
12
+ DEFAULT_STEPS_OPTS = {}.freeze
13
+
14
+ DEFAULT_GROUPS_OPTS = {}.freeze
15
+
16
+ VALID_CONFIG_KEYS.each { |key| attr_accessor key }
17
+
18
+ # Make sure the default values are set when the module is 'extended'
19
+ def self.extended(base)
20
+ base.reset
21
+ end
22
+
23
+ def configure
24
+ yield self
25
+ end
26
+
27
+ def reset
28
+ VALID_CONFIG_KEYS.each do |key|
29
+ send("#{key}=", self::Configuration.const_get("DEFAULT_#{key}".upcase))
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'tuner'
4
+
5
+ module TuneSpec
6
+ module Instances
7
+ # Defines the group behavior and rules
8
+ class Groups < Tuner
9
+ class << self
10
+ # Groups specific rules
11
+ def rules_passed?(instance, _args)
12
+ instance
13
+ end
14
+
15
+ private
16
+
17
+ def file_directory
18
+ "#{TuneSpec.directory}/#{type}"
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'tuner'
4
+
5
+ module TuneSpec
6
+ module Instances
7
+ # Defines pages behavior and rules
8
+ class Page < Tuner
9
+ class << self
10
+ # Page specific rules
11
+ def rules_passed?(instance, _args)
12
+ instance
13
+ end
14
+
15
+ private
16
+
17
+ def file_directory
18
+ "#{TuneSpec.directory}/#{type}s"
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'tuner'
4
+
5
+ module TuneSpec
6
+ module Instances
7
+ # Defines the steps behavior and rules
8
+ class Steps < Tuner
9
+ class << self
10
+ # Steps specific rules
11
+ def rules_passed?(instance, args)
12
+ same_page?(instance, args[1]) if args
13
+ end
14
+
15
+ private
16
+
17
+ # Verifies if the step requires a page_object
18
+ def same_page?(instance, page)
19
+ return false unless instance
20
+ return true unless instance.respond_to?(:page_object)
21
+ return true unless general_steps?(instance)
22
+ page.instance_of?(instance.page_object.class)
23
+ end
24
+
25
+ def general_steps?(instance)
26
+ argument_required?(:page_object, instance.class)
27
+ end
28
+
29
+ def file_directory
30
+ "#{TuneSpec.directory}/#{type}"
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,62 @@
1
+ # frozen_string_literal: true
2
+
3
+ module TuneSpec
4
+ module Instances
5
+ # Abstract class for Group, Step and Page
6
+ class Tuner
7
+ class << self
8
+ def instance_method_name(name)
9
+ "#{name}_#{type}".downcase
10
+ end
11
+
12
+ # A hook to define rules by subclasses
13
+ def rules_passed?(_instance, _args)
14
+ raise "Implement a #rules_passed? method for #{self}"
15
+ end
16
+
17
+ def format_args(args, object_klass)
18
+ default_args = fetch_default_args
19
+ args.tap do |arr|
20
+ default_args.each do |key, value|
21
+ arr.insert(0, value) if argument_required?(key, object_klass)
22
+ end
23
+ end
24
+ end
25
+
26
+ def call_object(file_name)
27
+ ensure_required(file_name)
28
+ const_name = file_name.split('_').each(&:capitalize!).join('')
29
+ const_get(const_name)
30
+ end
31
+
32
+ private
33
+
34
+ def type
35
+ @type ||= itself.to_s.split('::').last.downcase
36
+ end
37
+
38
+ def fetch_default_args
39
+ TuneSpec.__send__("#{type}_opts".downcase)
40
+ end
41
+
42
+ def argument_required?(arg, klass)
43
+ klass.instance_method(:initialize).parameters.flatten.include?(arg)
44
+ end
45
+
46
+ def ensure_required(name)
47
+ path = load_files.detect { |f| f.include?("/#{name}.rb") }
48
+ path ? require("./#{path}") : raise("Unable to find #{name}.rb")
49
+ end
50
+
51
+ def load_files
52
+ @files ||= Dir.glob("#{file_directory}/**/*")
53
+ end
54
+
55
+ # A hook to implement folder name by subclass
56
+ def file_directory
57
+ raise "Implement a #folder_name method for #{self}"
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,76 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'instances/groups'
4
+ require_relative 'instances/steps'
5
+ require_relative 'instances/page'
6
+
7
+ module TuneSpec
8
+ # Maps instance variables of pages, steps and groups
9
+ # to corresponding objects under framework directory
10
+ module Instances
11
+ # Creates an instance of Group or calls an existing
12
+ #
13
+ # @param name [Symbol, String] the prefix of the Groups object class
14
+ # @param args [Any] additional optional arguments
15
+ # @param block [Block] that yields to self
16
+ # @return [GroupObject]
17
+ # @example
18
+ # groups(:login).complete
19
+ def groups(name, *args, &block)
20
+ instance_handler(name, Groups, *args, block)
21
+ end
22
+
23
+ # Creates an instance of Step or calls an existing
24
+ #
25
+ # @param name [Symbol, String] the prefix of the Step object class
26
+ # @param args [Any] additional optional arguments
27
+ # @param block [Block] that yields to self
28
+ # @return [StepObject]
29
+ # @example
30
+ # steps(:calculator, page: :home).verify_result
31
+ def steps(name, *args, page: nil, &block)
32
+ args.insert(0, pages(page)) if page
33
+ instance_handler(name, Steps, *args, block)
34
+ end
35
+
36
+ # Creates an instance of Page or calls an existing
37
+ #
38
+ # @param name [Symbol, String] the prefix of the Page object class
39
+ # @param args [Any] additional optional arguments
40
+ # @param block [Block] that yields to self
41
+ # @return [PageObject]
42
+ # @example
43
+ # pages(:home).click_element
44
+ def pages(name, *args, &block)
45
+ instance_handler(name, Page, *args, block)
46
+ end
47
+
48
+ private
49
+
50
+ # @private
51
+ def instance_handler(name, klass, *args, block)
52
+ method_name = klass.instance_method_name(name)
53
+ create_instance_method(method_name, klass)
54
+ instance_klass = klass.call_object(method_name)
55
+ formatted_args = klass.format_args(args, instance_klass)
56
+ call_instance_method(method_name, *formatted_args, block)
57
+ end
58
+
59
+ # @private
60
+ def create_instance_method(method_name, klass)
61
+ return if respond_to?(method_name)
62
+ define_singleton_method(method_name) do |*args|
63
+ instance_var = instance_variable_get("@#{method_name}")
64
+ return instance_var if klass.rules_passed?(instance_var, args)
65
+ new_instance = klass.call_object(method_name).new(*args)
66
+ instance_variable_set("@#{method_name}", new_instance)
67
+ end
68
+ end
69
+
70
+ # @private
71
+ def call_instance_method(method_name, *args, block)
72
+ return __send__(method_name, *args) unless block
73
+ __send__(method_name, *args).instance_eval(&block)
74
+ end
75
+ end
76
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'optparse'
2
4
  require 'fileutils'
3
5
 
@@ -18,7 +20,8 @@ module TuneSpec
18
20
  parser.parse!(original_args)
19
21
  end
20
22
 
21
- def parser
23
+ # rubocop:disable MethodLength
24
+ def parser
22
25
  OptionParser.new do |parser|
23
26
  parser.summary_width = 34
24
27
 
@@ -27,9 +30,9 @@ module TuneSpec
27
30
  parser.on('--init [PATH]',
28
31
  'Create framework folder structure') do |dir|
29
32
  base_path = dir || 'lib'
30
- %w[groups pages steps].each do |dir|
33
+ %w[groups pages steps].each do |folder|
31
34
  FileUtils.mkdir_p(base_path)
32
- path = "#{base_path}/#{dir}"
35
+ path = "#{base_path}/#{folder}"
33
36
  exists = directory_exists?(path)
34
37
  print_directory(path, exists)
35
38
  create_directory(path) unless exists
@@ -45,7 +48,7 @@ module TuneSpec
45
48
  end
46
49
 
47
50
  def create_directory(dir)
48
- Dir.mkdir(dir)
51
+ Dir.mkdir(dir)
49
52
  end
50
53
 
51
54
  def directory_exists?(dir)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module TuneSpec
2
- VERSION = "0.1.0"
4
+ VERSION = '0.3.0'
3
5
  end
data/lib/tune_spec.rb CHANGED
@@ -1,5 +1,12 @@
1
- require "tune_spec/version"
1
+ # frozen_string_literal: true
2
2
 
3
+ require 'tune_spec/configuration'
4
+ require 'tune_spec/version'
5
+
6
+ # Namespace for all TuneSpec objects
3
7
  module TuneSpec
4
- # Your code goes here...
8
+ extend Configuration
9
+ # TODO: Add method missing
5
10
  end
11
+
12
+ require 'tune_spec/instances'
data/tune_spec.gemspec CHANGED
@@ -1,24 +1,27 @@
1
- # coding: utf-8
2
- lib = File.expand_path("../lib", __FILE__)
1
+ # frozen_string_literal: true
2
+
3
+ lib = File.expand_path('../lib', __FILE__)
3
4
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
- require "tune_spec/version"
5
+ require 'tune_spec/version'
5
6
 
6
7
  Gem::Specification.new do |spec|
7
- spec.name = "tune_spec"
8
+ spec.name = 'tune_spec'
8
9
  spec.version = TuneSpec::VERSION
9
- spec.authors = ["Igor Starostenko"]
10
- spec.email = ["contactigorstar@gmail.com"]
10
+ spec.authors = ['Igor Starostenko']
11
+ spec.email = ['contactigorstar@gmail.com']
11
12
 
12
13
  spec.summary = "tune_spec_#{TuneSpec::VERSION}"
13
- spec.description = 'e2e Ruby tests in Page Objects'
14
- spec.homepage = "https://github.com/igor-starostenko/tune_spec"
15
- spec.license = "MIT"
14
+ spec.description = 'In Development. e2e Ruby tests in Page Objects'
15
+ spec.homepage = 'https://github.com/igor-starostenko/tune_spec'
16
+ spec.license = 'MIT'
16
17
 
17
18
  spec.files = `git ls-files -z`.split("\x0")
18
- spec.bindir = "exe"
19
+ spec.bindir = 'exe'
19
20
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
20
- spec.require_paths = ["lib"]
21
+ spec.require_paths = ['lib']
21
22
 
22
- spec.add_development_dependency "bundler", "~> 1.15"
23
- spec.add_development_dependency "rake", "~> 10.0"
23
+ spec.add_development_dependency 'bundler', '~> 1.15'
24
+ spec.add_development_dependency 'rubocop', '~> 0.50.0'
25
+ spec.add_development_dependency 'yard', '~> 0.9.9'
26
+ spec.add_development_dependency 'yard-doctest', '~> 0.1.10'
24
27
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tune_spec
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Igor Starostenko
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2017-10-07 00:00:00.000000000 Z
11
+ date: 2017-10-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -25,20 +25,48 @@ dependencies:
25
25
  - !ruby/object:Gem::Version
26
26
  version: '1.15'
27
27
  - !ruby/object:Gem::Dependency
28
- name: rake
28
+ name: rubocop
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '10.0'
33
+ version: 0.50.0
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: '10.0'
41
- description: e2e Ruby tests in Page Objects
40
+ version: 0.50.0
41
+ - !ruby/object:Gem::Dependency
42
+ name: yard
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: 0.9.9
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: 0.9.9
55
+ - !ruby/object:Gem::Dependency
56
+ name: yard-doctest
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: 0.1.10
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: 0.1.10
69
+ description: In Development. e2e Ruby tests in Page Objects
42
70
  email:
43
71
  - contactigorstar@gmail.com
44
72
  executables:
@@ -54,11 +82,17 @@ files:
54
82
  - Gemfile.lock
55
83
  - LICENSE
56
84
  - README.md
57
- - Rakefile
58
85
  - bin/console
59
86
  - bin/setup
87
+ - doctest_helper.rb
60
88
  - exe/tune
61
89
  - lib/tune_spec.rb
90
+ - lib/tune_spec/configuration.rb
91
+ - lib/tune_spec/instances.rb
92
+ - lib/tune_spec/instances/groups.rb
93
+ - lib/tune_spec/instances/page.rb
94
+ - lib/tune_spec/instances/steps.rb
95
+ - lib/tune_spec/instances/tuner.rb
62
96
  - lib/tune_spec/parser.rb
63
97
  - lib/tune_spec/version.rb
64
98
  - tune_spec.gemspec
@@ -85,5 +119,5 @@ rubyforge_project:
85
119
  rubygems_version: 2.6.12
86
120
  signing_key:
87
121
  specification_version: 4
88
- summary: tune_spec_0.1.0
122
+ summary: tune_spec_0.3.0
89
123
  test_files: []
data/Rakefile DELETED
@@ -1,2 +0,0 @@
1
- require "bundler/gem_tasks"
2
- task :default => :spec