Test_Framework1.0 1.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE +19 -0
- data/README.md +41 -0
- data/lib/MediTAF.rb +14 -0
- data/lib/MediTAF/services.rb +22 -0
- data/lib/MediTAF/services/clients.rb +7 -0
- data/lib/MediTAF/services/clients/euresource_adapter.rb +115 -0
- data/lib/MediTAF/services/clients/mauth_adapter.rb +125 -0
- data/lib/MediTAF/services/resources_mgr.rb +110 -0
- data/lib/MediTAF/ui.rb +25 -0
- data/lib/MediTAF/ui/application.rb +72 -0
- data/lib/MediTAF/ui/applications.rb +60 -0
- data/lib/MediTAF/utils/configuration.rb +84 -0
- data/lib/MediTAF/utils/exceptions.rb +21 -0
- data/lib/MediTAF/utils/logger.rb +63 -0
- data/lib/MediTAF/utils/mail.rb +118 -0
- data/lib/MediTAF/utils/meditaf_faker.rb +122 -0
- data/lib/MediTAF/utils/sticky.rb +31 -0
- data/lib/MediTAF/version.rb +3 -0
- metadata +147 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 03e552c62291411f5305cad227dedfff3fc2a85e
|
4
|
+
data.tar.gz: 45dbb238a2a92e8adc5b4f542b65dee646007780
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 702918fb710b1d20b89c19478a77a776611eac6f8061a9da245ca6e5fa20e7f4ba74bb2de4d0aca9bac750f19db4fbe50c1c22975915f980d40e03d63b6f8da7
|
7
|
+
data.tar.gz: e517fbf5f86ec9c2f61b8d826256705d068fd5718b9437fe94a6743a89c601bda78996ff220aeddbfe57469057b224d93b5eddca0855b4ab54a23ce0c2e4f651
|
data/LICENSE
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
Copyright (c) 2013 Medidata Solutions Worldwide
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
of this software and associated documentation files (the "Software"), to deal
|
5
|
+
in the Software without restriction, including without limitation the rights
|
6
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
copies of the Software, and to permit persons to whom the Software is
|
8
|
+
furnished to do so, subject to the following conditions:
|
9
|
+
|
10
|
+
The above copyright notice and this permission notice shall be included in
|
11
|
+
all copies or substantial portions of the Software.
|
12
|
+
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
# MediTAF
|
2
|
+
|
3
|
+
Test frameworks are one of the key requirements for implementing a successful automated software testing solution. A good test framework reduces maintenance costs, and speeds up test development. Currently at Medidata, we have several test frameworks that are successfully used in various projects. However, they have been designed with a focus on a product or a project, rendering them unusable in cross-product or multi-interface automation projects.
|
4
|
+
|
5
|
+
MediTAF is a generic ruby-based test automation framework intended to allow automation engineers and testers to design end-to-end automated integration tests for distributed systems. Specifically, MediTAF will allow testers to automate using two different interfaces i.e. UI and web services.
|
6
|
+
|
7
|
+
|
8
|
+
## Key Features
|
9
|
+
|
10
|
+
* **UI testing:** MediTAF uses Selenium to allow users to write tests for the web user interface. For Selenium implementation, the framework uses the Page Object pattern. The Page Object pattern represents screens of a web application in a series of objects and encapsulates the features represented by a web page. It reduces the duplication of code and improves the maintainability of the automated tests. MediTAF uses a ruby gem called **site_prism** (an extension to **Capybara**) as an interface to **selenium-webdriver** to implement the Page Object pattern.
|
11
|
+
* **Services testing:** MediTAF provides an interface to connect with the services. Testers will be able to make calls to the service APIs, save results and perform comparisons with the expected results. Framework provides wrapper classes so nothing changes in the implementation. The framework also allows for future expansion to other services without affecting existing implementations.
|
12
|
+
* **Logging and Exception Handling:** The framework has an exception handler with multiple severity levels that can be logged to a configured file.
|
13
|
+
|
14
|
+
|
15
|
+
## Advantages of using MediTAF
|
16
|
+
|
17
|
+
* Enables testers to automate tests across multiple Medidata interfaces and applications.
|
18
|
+
* The framework interprets the **Cucumber/Gherkin** language for the creation and execution of requirement/feature files.
|
19
|
+
* Allows for central location repository of features and step definitions - [MIST](https://github.com/mdsol/MIST.git) ( MediTAF Integration Steps and Tests )
|
20
|
+
* Enhances collaboration among testers, developers, and product managers to facilitate and simplify cross-team and cross-platform testing efforts.
|
21
|
+
* Reduces maintenance by minimizing duplication of code.
|
22
|
+
* Provides a way for standardized logging and validation output across multiple products.
|
23
|
+
* Allows easy execution of end-to-end automated tests.
|
24
|
+
|
25
|
+
|
26
|
+
## Home Page
|
27
|
+
[https://github.com/mdsol/MediTAF.git](https://github.com/mdsol/MediTAF.git)
|
28
|
+
|
29
|
+
## Documentation
|
30
|
+
[Medinet - MediTAF](https://sites.google.com/a/mdsol.com/knowledgebase/home/departments/r-d/sqa/utilities/meditaf)
|
31
|
+
|
32
|
+
## Report Issues
|
33
|
+
Refer to JIRA Story [MCC-96074](https://medidata.atlassian.net/browse/MCC-96074) and add sub-tasks for issues.
|
34
|
+
|
35
|
+
## Installation Instructions
|
36
|
+
|
37
|
+
MediTAF is released privately as a gem, and it works with MIST. For more information and installation instructions for MIST, please refer to the git repository at [https://github.com/mdsol/MIST.git](https://github.com/mdsol/MIST.git).
|
38
|
+
|
39
|
+
## Copyright
|
40
|
+
|
41
|
+
Copyright © 2013-2015 Medidata Solutions, Inc. All Rights Reserved.
|
data/lib/MediTAF.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
$:.unshift File.dirname(__FILE__)
|
2
|
+
|
3
|
+
module MediTAF
|
4
|
+
def self.root
|
5
|
+
File.expand_path '../..', __FILE__
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
require 'MediTAF/version'
|
10
|
+
require 'MediTAF/services'
|
11
|
+
require 'MediTAF/ui'
|
12
|
+
require 'MediTAF/utils/meditaf_faker'
|
13
|
+
require 'MediTAF/utils/sticky'
|
14
|
+
require 'MediTAF/utils/mail'
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'MediTAF/utils/exceptions'
|
2
|
+
|
3
|
+
module MediTAF
|
4
|
+
# Enables MediTAF to interact with available resources. It depends on resource adapters that implement
|
5
|
+
# a set of require methods. The underlying adapters have the knowledge of the type resource with which
|
6
|
+
# it communicates.
|
7
|
+
module Services
|
8
|
+
# @return [ResourcesMgr] a new instance of ResourceMgr
|
9
|
+
def self.new
|
10
|
+
ResourcesMgr.new
|
11
|
+
end
|
12
|
+
|
13
|
+
class ServiceConfigurationMissing < MediTAF::Utils::Exceptions::MediTAFException; end
|
14
|
+
class ResourceAdapterLoadError < MediTAF::Utils::Exceptions::MediTAFException; end
|
15
|
+
class ResourceAdapterMissing < MediTAF::Utils::Exceptions::MediTAFException; end
|
16
|
+
class ResourceAdapterMethodMissing < MediTAF::Utils::Exceptions::MediTAFException; end
|
17
|
+
class ResourceAdapterConfigurationMissing < MediTAF::Utils::Exceptions::MediTAFException; end
|
18
|
+
class ResourceAdapterRequestError < MediTAF::Utils::Exceptions::MediTAFException; end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
require_relative 'services/resources_mgr'
|
@@ -0,0 +1,115 @@
|
|
1
|
+
require 'euresource'
|
2
|
+
|
3
|
+
module MediTAF
|
4
|
+
module Services
|
5
|
+
module Clients
|
6
|
+
# The specific resource adapter for Euresource. It depends on the following configurations
|
7
|
+
# * services.euresource
|
8
|
+
# * mauth_url
|
9
|
+
# * app_uuid
|
10
|
+
# * key_file : location of file containing private key
|
11
|
+
# * eureka_url
|
12
|
+
# * stage
|
13
|
+
# * mauth_logger (optional)
|
14
|
+
# * eureka_logger (optional)
|
15
|
+
# * authenticate_responses (optional)
|
16
|
+
class EuresourceAdapter
|
17
|
+
|
18
|
+
# verifies needs configuration items exist for eureka-client
|
19
|
+
def initialize
|
20
|
+
errs = []
|
21
|
+
errs << 'euresource configuration' unless euresource_config
|
22
|
+
if errs.empty?
|
23
|
+
errs << 'eureka_url' unless euresource_config['eureka_url']
|
24
|
+
errs << 'mauth_url' unless euresource_config['mauth_url']
|
25
|
+
errs << 'app_uuid' unless euresource_config['app_uuid']
|
26
|
+
errs << 'key_file' unless euresource_config['key_file']
|
27
|
+
errs << 'stage' unless euresource_config['stage']
|
28
|
+
errs << 'authenticate_responses' if euresource_config['authenticate_responses'].nil?
|
29
|
+
end
|
30
|
+
unless errs.empty?
|
31
|
+
raise ResourceAdapterConfigurationMissing, 'Euresource Adapter Configurations: cannot find ' + errs.join(', ')
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
# require configurations for eureka-client
|
36
|
+
def configure
|
37
|
+
cfg = euresource_config
|
38
|
+
Euresource.configure do
|
39
|
+
config.stage_defaults do |defaults|
|
40
|
+
defaults.mauth(cfg['mauth_url']) do |mauth_config|
|
41
|
+
mauth_config.app_uuid cfg['app_uuid']
|
42
|
+
mauth_config.private_key_file cfg['key_file']
|
43
|
+
|
44
|
+
# Only set if you want different logger for MAuth
|
45
|
+
mauth_config.logger cfg['mauth_logger'].constantize.new if cfg['mauth_logger']
|
46
|
+
end
|
47
|
+
defaults.use MAuth::Faraday::RequestSigner, defaults.mauth_config
|
48
|
+
|
49
|
+
# Turns on develop mode for local development, which adds extra logging and forces API deployments to Eureka
|
50
|
+
# without having to delete prior versions of an API document for local development while making changes to an
|
51
|
+
# API document.
|
52
|
+
defaults.develop_mode false
|
53
|
+
|
54
|
+
# Rails logger will be used for all logging if this is not set in Rails.
|
55
|
+
defaults.logger EuresourceLogger.new if cfg['eureka_logger']
|
56
|
+
|
57
|
+
#Un-comment this option if you want to skip authenticating eureka responses
|
58
|
+
defaults.mauth_authenticate_responses cfg['authenticate_responses']
|
59
|
+
|
60
|
+
defaults.use FaradayMiddleware::RackCompatible, CacheComplainer::Complainer
|
61
|
+
end
|
62
|
+
|
63
|
+
# This applies all default from above to configure a Eureka::Client instance for a specific eureka stage
|
64
|
+
config.stage(cfg['eureka_url'], cfg['stage']) do |builder|
|
65
|
+
builder.deployment_base_uri 'http://localhost:3000'
|
66
|
+
builder.faraday_adapter :typhoeus
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
# @param resource [Symbol] the resource to get
|
72
|
+
# @return [Euresource::Base] The anonymous class.
|
73
|
+
def load(resource)
|
74
|
+
Euresource.class_for_resource(resource)
|
75
|
+
rescue => e
|
76
|
+
raise ResourceAdapterLoadError, "Can't load resource #{resource}. Inner Exception: #{e.to_s}"
|
77
|
+
end
|
78
|
+
|
79
|
+
# @note not implemented
|
80
|
+
# checks if the resource is deployed within eureka
|
81
|
+
# @param resource [Symbol] the resource to check
|
82
|
+
def deployed?(resource)
|
83
|
+
end
|
84
|
+
|
85
|
+
# @note not implemented
|
86
|
+
# check if the resource is consumable
|
87
|
+
# @param resource [Symbol] the resource to check
|
88
|
+
def connected?(resource)
|
89
|
+
end
|
90
|
+
|
91
|
+
# @return [String] the stage value from the configuration
|
92
|
+
def stage
|
93
|
+
euresource_config['stage']
|
94
|
+
end
|
95
|
+
|
96
|
+
# @return [Symbol] the euresource clients by stage from euresource configuration
|
97
|
+
def clients_by_stage
|
98
|
+
Euresource.config.clients_by_stage
|
99
|
+
end
|
100
|
+
|
101
|
+
# @return [Symbol] the default stage from euresource configuration
|
102
|
+
def default_stage
|
103
|
+
Euresource.config.default_stage
|
104
|
+
end
|
105
|
+
|
106
|
+
private
|
107
|
+
|
108
|
+
def euresource_config
|
109
|
+
raise ServiceConfigurationMissing, "services not found in configuration" unless MediTAF::Utils::Configuration['services']
|
110
|
+
MediTAF::Utils::Configuration['services']['euresource']
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
@@ -0,0 +1,125 @@
|
|
1
|
+
require 'mauth-client'
|
2
|
+
require 'faraday'
|
3
|
+
require 'faraday_middleware'
|
4
|
+
|
5
|
+
module MediTAF
|
6
|
+
module Services
|
7
|
+
module Clients
|
8
|
+
# The specific resource adapter for MAuthClient. It depends on the following configurations
|
9
|
+
# * services.mauth
|
10
|
+
# * mauth_url
|
11
|
+
# * mauth_api_version
|
12
|
+
# * app_uuid
|
13
|
+
# * key_file : location of file containing private key
|
14
|
+
# * mauth_logger (optional)
|
15
|
+
# * authenticate_responses (optional)
|
16
|
+
class MauthAdapter
|
17
|
+
|
18
|
+
# verifies needed configuration items exist for mauth-client
|
19
|
+
# @raise [ResourceAdapterConfigurationMissing] lists the missing required configuration items
|
20
|
+
def initialize
|
21
|
+
errs = []
|
22
|
+
errs << 'mauth configuration' unless mauth_config
|
23
|
+
if errs.empty?
|
24
|
+
errs << 'mauth_api_version' unless mauth_config[:mauth_api_version]
|
25
|
+
errs << 'mauth_url' unless mauth_config[:mauth_baseurl]
|
26
|
+
errs << 'app_uuid' unless mauth_config[:app_uuid]
|
27
|
+
errs << 'key_file' unless mauth_config[:private_key_file]
|
28
|
+
errs << 'authenticate_responses' if mauth_config[:authenticate_response].nil?
|
29
|
+
end
|
30
|
+
unless errs.empty?
|
31
|
+
raise ResourceAdapterConfigurationMissing, 'Mauth Adapter Configurations: cannot find ' + errs.join(', ')
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
# configure a new MAuth::Client based on configuration items
|
36
|
+
# @note configures MAuth::Client to return all response in JSON format
|
37
|
+
def configure
|
38
|
+
@mauth_client = ::MAuth::Client.new(mauth_config)
|
39
|
+
|
40
|
+
@connection = Faraday.new do |builder|
|
41
|
+
builder.use MAuth::Faraday::MAuthClientUserAgent, "MediTAF Mauth Client Adapter"
|
42
|
+
builder.use MAuth::Faraday::RequestSigner, :mauth_client => @mauth_client
|
43
|
+
builder.use MAuth::Faraday::ResponseAuthenticator, :mauth_client => @mauth_client if mauth_config[:authenticate_response]
|
44
|
+
builder.use FaradayMiddleware::ParseJson, content_type: /\bjson$/
|
45
|
+
builder.use FaradayMiddleware::ParseXml, content_type: /\bxml$/
|
46
|
+
builder.adapter Faraday.default_adapter
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
# loads a new MauthClient object for request on base_url
|
51
|
+
# @param args [Hash] arguments
|
52
|
+
# @option args [String] :baseurl the base url of this resource
|
53
|
+
# @return [MediTAF::Services::Clients::MauthClient]
|
54
|
+
# @raise [ResourceAdapterLoadError] when instantiating a new MauthClient
|
55
|
+
def load(args)
|
56
|
+
raise MauthClientBaseURLMissing, "supply a base url" unless args.is_a?(Hash) && args.has_key?(:baseurl)
|
57
|
+
MauthClient.new(@connection, args[:baseurl])
|
58
|
+
end
|
59
|
+
|
60
|
+
private
|
61
|
+
|
62
|
+
def mauth_config
|
63
|
+
raise ServiceConfigurationMissing, "services not found in configuration" unless MediTAF::Utils::Configuration['services']
|
64
|
+
raise ServiceConfigurationMissing, "euresource not found in configuration" unless MediTAF::Utils::Configuration['services']['mauth']
|
65
|
+
unless @mauth_config
|
66
|
+
cfg = MediTAF::Utils::Configuration['services']['mauth']
|
67
|
+
@mauth_config = {}
|
68
|
+
@mauth_config[:mauth_baseurl] = cfg['mauth_url']
|
69
|
+
@mauth_config[:private_key_file] = cfg['key_file']
|
70
|
+
@mauth_config[:app_uuid] = cfg['app_uuid']
|
71
|
+
@mauth_config[:mauth_api_version] = cfg['mauth_api_version']
|
72
|
+
@mauth_config[:authenticate_response] = cfg['authenticate_responses']
|
73
|
+
end
|
74
|
+
@mauth_config
|
75
|
+
rescue => e
|
76
|
+
nil
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
# A MauthClient object set to a specific base_url and uses the common MAuth::Client object
|
81
|
+
# @note only MauthAdapter object instantiate objects of this type
|
82
|
+
class MauthClient
|
83
|
+
# @param connection [Faraday] defines the MAuth::Faraday parameters/handlers/response formats
|
84
|
+
# @param base_url [String] the base url for all paths
|
85
|
+
# @raise [MauthClientBaseURLMissing] when the no base url is given
|
86
|
+
def initialize(connection, base_url)
|
87
|
+
@connection, @base_url = connection, base_url
|
88
|
+
end
|
89
|
+
|
90
|
+
# @param [Hash] opts the arguments to do an HTTP request
|
91
|
+
# @option opts [Symbol] :verb :get, :post, :put, or :delete
|
92
|
+
# @option opts [Symbol] :resource
|
93
|
+
# @option opts [Symbol] :body
|
94
|
+
# @option opts [Symbol] :content_type
|
95
|
+
# @return [Faraday::Response]
|
96
|
+
# @raise [ResourceAdapterRequestError]
|
97
|
+
def request(opts)
|
98
|
+
headers = {}
|
99
|
+
headers['Content-Type'] = opts[:content_type] if opts[:content_type]
|
100
|
+
headers['Content-Type'] = 'application/json' if opts[:content_type].nil? && opts[:body]
|
101
|
+
headers['Accept'] = opts[:accept] || 'text/html,application/xhtml+xml,application/xml,application/json'
|
102
|
+
@connection.run_request(opts[:verb], @base_url + '/' + opts[:resource], opts[:body], headers)
|
103
|
+
rescue MAuth::InauthenticError, MAuth::UnableToAuthenticateError => e
|
104
|
+
raise ResourceAdapterRequestError, "Failed to #{opts[:verb]} #{opts[:resource]}. Inner Exception: #{e.to_s}"
|
105
|
+
rescue => e
|
106
|
+
raise ResourceAdapterRequestError, "#{opts}. Inner Exception: #{e.to_s}"
|
107
|
+
end
|
108
|
+
|
109
|
+
# @note not implemented
|
110
|
+
# checks if the resource is deployed within eureka
|
111
|
+
# @param resource [Symbol] the resource to check
|
112
|
+
def deployed?(resource)
|
113
|
+
end
|
114
|
+
|
115
|
+
# @note not implemented
|
116
|
+
# check if the resource is consumable
|
117
|
+
# @param resource [Symbol] the resource to check
|
118
|
+
def connected?(resource)
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
class MauthClientBaseURLMissing < MediTAF::Utils::Exceptions::MediTAFException; end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
@@ -0,0 +1,110 @@
|
|
1
|
+
# ResourcesMgr manages the requested resources.
|
2
|
+
# the manager needs a specific adapter from where it will interact with resources
|
3
|
+
# if no adapter is specified in the configuration i.e. ['services']['adapter']
|
4
|
+
# then 'euresource' adapter is used the default
|
5
|
+
# all resources are expressed as method
|
6
|
+
# each accessed resources exposes the underlying adapter implementation
|
7
|
+
|
8
|
+
require 'MediTAF/utils/configuration'
|
9
|
+
require 'active_support/core_ext/string/inflections'
|
10
|
+
|
11
|
+
module MediTAF
|
12
|
+
module Services
|
13
|
+
class ResourcesMgr
|
14
|
+
include Logging
|
15
|
+
|
16
|
+
attr_reader :adapters
|
17
|
+
attr_reader :resources
|
18
|
+
attr_reader :stage
|
19
|
+
|
20
|
+
# @note loads euresource adapter by default, otherwise attempts to load a specific adapter. adapters are
|
21
|
+
# specified in *MediTAF_configuration.services.adapter* value. the location of the adapter defaults
|
22
|
+
# to services/clients within MediTAF, otherwise it can be specified in *MediTAF_configuration.services.adapter_home*
|
23
|
+
# value. when MediTAF attempts to load the adapter and no location has been specified, MediTAF assumes that the
|
24
|
+
# adapter has been load into the environment.
|
25
|
+
# @note the adapter must be in namespace *MediTAF::Services::Clients*
|
26
|
+
# @raise [ResourceAdapterMethodMissing] when adapter does not respond to configure
|
27
|
+
# @raise [ResourceAdapterLoadError] when adapter could not be loaded
|
28
|
+
def initialize
|
29
|
+
@resources = {}
|
30
|
+
@adapters = {}
|
31
|
+
|
32
|
+
raise ServiceConfigurationMissing, "services not found in configuration" unless MediTAF::Utils::Configuration['services']
|
33
|
+
|
34
|
+
adapter_home = MediTAF::Utils::Configuration['services']['adapter_home']
|
35
|
+
adapter_home ||= "#{MediTAF.root}/lib/MediTAF/services/clients"
|
36
|
+
|
37
|
+
adapters = MediTAF::Utils::Configuration['services']['adapters']
|
38
|
+
|
39
|
+
if adapters
|
40
|
+
adapters.split(/ *, */).each do |adapter|
|
41
|
+
begin
|
42
|
+
require "#{adapter_home}/#{adapter}_adapter" if File.exist? "#{adapter_home}/#{adapter}_adapter.rb"
|
43
|
+
@adapters[adapter.to_sym] = "MediTAF::Services::Clients::#{adapter.camelize}Adapter".constantize.new
|
44
|
+
@adapters[adapter.to_sym].configure
|
45
|
+
rescue NoMethodError => e
|
46
|
+
raise ResourceAdapterMethodMissing, %Q|"#{adapter.camelize}Adapter" is missing required configure method|
|
47
|
+
rescue NameError => e
|
48
|
+
raise ResourceAdapterLoadError, %Q|Couldn't load resource adapter "#{adapter.camelize}Adapter". Inner Exception: #{e.to_s}|
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
# removes all or one resource from the resources hash
|
55
|
+
# @param resource [Symbol] the resource to remove
|
56
|
+
def delete(resource=nil)
|
57
|
+
if resource
|
58
|
+
@resources.delete(resource) if @resources.include?(resource)
|
59
|
+
else
|
60
|
+
@resources.clear
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
# checks if a resource has been deployed
|
65
|
+
# @note not implemented
|
66
|
+
# @param resource [Symbol] the resource to check
|
67
|
+
def deployed?(resource)
|
68
|
+
raise "not implemented"
|
69
|
+
end
|
70
|
+
|
71
|
+
# checks if a resource is consumable
|
72
|
+
# @note not implemented
|
73
|
+
# @param resource [Symbol] the resource to check
|
74
|
+
def connected?(resource)
|
75
|
+
raise "not implemented"
|
76
|
+
end
|
77
|
+
|
78
|
+
# @param adapter [Symbol] the adapter to get the stage from
|
79
|
+
# @return [Symbol] gets the current stage set for the adapter
|
80
|
+
def stage(adapter=:euresource)
|
81
|
+
@adapters[adapter].stage.to_sym if @adapters.has_key? adapter
|
82
|
+
end
|
83
|
+
|
84
|
+
# @param adapter [Symbol] the adapter to get the stage from
|
85
|
+
# @return [Symbol] gets the default stage set for the adapter
|
86
|
+
def default_stage(adapter=:euresource)
|
87
|
+
@adapters[adapter].default_stage if @adapters.has_key? adapter
|
88
|
+
end
|
89
|
+
|
90
|
+
# @param resource [Symbol] resource as a method name
|
91
|
+
# @param args [Object] args are passed to underlying adapter
|
92
|
+
# @return [Object] the specific resource adapter object
|
93
|
+
# @raise [ResourceAdapterMethodMissing] when adapter does not respond to load
|
94
|
+
def method_missing(resource, *args, &block)
|
95
|
+
opts = args[0] || {}
|
96
|
+
unless @resources.include?(resource)
|
97
|
+
unless @adapters.has_key? opts[:adapter]
|
98
|
+
raise ResourceAdapterMissing, %Q/'#{opts[:adapter]}' adapter not found/
|
99
|
+
end
|
100
|
+
adapter = @adapters[ opts[:adapter] ]
|
101
|
+
opts.delete(:adapter)
|
102
|
+
@resources[resource] = ( opts.nil? || opts.empty?) ? adapter.load(resource) : adapter.load(opts)
|
103
|
+
end
|
104
|
+
@resources[resource]
|
105
|
+
rescue NoMethodError => e
|
106
|
+
raise ResourceAdapterMethodMissing, "required load method missing"
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
data/lib/MediTAF/ui.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
# Module ui namespace for all ui related capabilities
|
2
|
+
require 'MediTAF/utils/exceptions'
|
3
|
+
|
4
|
+
module MediTAF
|
5
|
+
# Enables MediTAF to interact with the UI via the page object model design pattern. It manages applications and their
|
6
|
+
# associated pages (i.e. page objects).
|
7
|
+
module UI
|
8
|
+
# @param pages_root [String] specifies location of applications' pages. default location: pages
|
9
|
+
def self.new(pages_root='pages')
|
10
|
+
Applications.new('./' + Dir.glob(File.join("**", pages_root)).first)
|
11
|
+
end
|
12
|
+
|
13
|
+
# Applications manager was unable to find a directory with the name of the application
|
14
|
+
class AppLoadError < MediTAF::Utils::Exceptions::MediTAFException; end
|
15
|
+
|
16
|
+
# Pages Manager (i.e. the Application) was unable to find a file presentation the page model
|
17
|
+
class PageLoadError < MediTAF::Utils::Exceptions::MediTAFException; end
|
18
|
+
|
19
|
+
# BaseURL for launching the application is missing.
|
20
|
+
class BaseURLMissing < MediTAF::Utils::Exceptions::MediTAFException; end
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
require_relative 'ui/applications'
|
@@ -0,0 +1,72 @@
|
|
1
|
+
require 'active_support/core_ext/string/inflections'
|
2
|
+
|
3
|
+
module MediTAF
|
4
|
+
module UI
|
5
|
+
# Manages all of the application's pages in the application's root directory
|
6
|
+
class Application
|
7
|
+
attr_reader :app_root
|
8
|
+
attr_reader :pages
|
9
|
+
attr_reader :current_page
|
10
|
+
|
11
|
+
# @param app_root [String] path to the application's page models
|
12
|
+
def initialize(app_root)
|
13
|
+
@pages = {}
|
14
|
+
@app_root = app_root
|
15
|
+
end
|
16
|
+
|
17
|
+
# references the page as a method name
|
18
|
+
# @param page [Symbol] the page name as a symbol
|
19
|
+
# @return [Object] the current page
|
20
|
+
def method_missing(page, *args, &block)
|
21
|
+
@current_page =
|
22
|
+
if @pages.include?(page)
|
23
|
+
@pages[page]
|
24
|
+
elsif in_namespace?(page)
|
25
|
+
new_page(@app_root + '/' + page.to_s)
|
26
|
+
else
|
27
|
+
load_page(page)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
# iterates over the loaded pages collection
|
32
|
+
# @param block [Proc]
|
33
|
+
def each(&block)
|
34
|
+
@pages.each(&block) if @pages
|
35
|
+
end
|
36
|
+
|
37
|
+
# @return [Symbol] the current page in use
|
38
|
+
def current_page
|
39
|
+
@current_page
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
# @param page [Symbol] the page name as a symbol
|
45
|
+
# @return [MediTAF::UI:BasePage] the newly accessed page
|
46
|
+
# @raise [PageLoadError] when manager cannot fully load the requested page
|
47
|
+
def load_page(page)
|
48
|
+
raise "File #{@app_root}/#{page.to_s}.rb not found" unless Dir["#{@app_root}/#{page.to_s}.rb"].detect do |f|
|
49
|
+
!File.directory?(f) && File.basename(f, ".*").downcase.to_sym == page
|
50
|
+
end
|
51
|
+
class_path = @app_root + '/' + page.to_s
|
52
|
+
require class_path
|
53
|
+
new_page(class_path)
|
54
|
+
rescue => e
|
55
|
+
raise PageLoadError, "Couldn't load page #{page.to_s}. Inner Exception: #{e.to_s}"
|
56
|
+
end
|
57
|
+
|
58
|
+
def new_page(class_path)
|
59
|
+
@pages[class_path.split('/').last.to_sym] = /^.+\/([^\/]+\/[^\/]+)$/.match(class_path)[1].camelize.constantize.new
|
60
|
+
rescue => e
|
61
|
+
raise PageLoadError, "Couldn't instantiate page #{page.to_s}. Inner Exception #{e.to_s}"
|
62
|
+
end
|
63
|
+
|
64
|
+
def in_namespace?(page)
|
65
|
+
ns = /^.+\/[^\/]+\/([^\/]+)$/.match(@app_root)[1].camelize.constantize
|
66
|
+
ns.constants.detect { |c| ns.const_get(c).is_a?(Class) && c == page.to_s.camelize.to_sym }
|
67
|
+
rescue => e
|
68
|
+
nil
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
# Class Applications manages all configured applications in a single browser session
|
2
|
+
|
3
|
+
require_relative '../ui/application'
|
4
|
+
|
5
|
+
module MediTAF
|
6
|
+
module UI
|
7
|
+
# Manages all of the applications in the applications root directory
|
8
|
+
class Applications
|
9
|
+
include Enumerable
|
10
|
+
|
11
|
+
attr_reader :apps_root
|
12
|
+
attr_reader :apps
|
13
|
+
attr_reader :current_app
|
14
|
+
|
15
|
+
# @param apps_root [String] root location of applications with their defined pages
|
16
|
+
def initialize(apps_root)
|
17
|
+
@apps = {}
|
18
|
+
@apps_root = apps_root
|
19
|
+
end
|
20
|
+
|
21
|
+
# only empties the applications internal apps collection
|
22
|
+
def close
|
23
|
+
@apps.clear
|
24
|
+
end
|
25
|
+
|
26
|
+
# references an application as a method name
|
27
|
+
# @param app [Symbol] the application name as a symbol
|
28
|
+
# @return [Application] the current application
|
29
|
+
def method_missing(app, *args, &block)
|
30
|
+
@current_app = @apps.include?(app) ? @apps[app] : load_app(app)
|
31
|
+
end
|
32
|
+
|
33
|
+
# iterates over the loaded applications collection
|
34
|
+
# @param block [Proc]
|
35
|
+
def each(&block)
|
36
|
+
@apps.each(&block) if @apps
|
37
|
+
end
|
38
|
+
|
39
|
+
# @return [Symbol] the current application in use
|
40
|
+
def current_app
|
41
|
+
@current_app
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
# @param app [Symbol] the application name as a symbol
|
47
|
+
# @return [Application] the newly accessed application
|
48
|
+
# @raise [AppLoadError] when manager cannot fully load the requested app
|
49
|
+
def load_app(app)
|
50
|
+
raise "Directory #{@apps_root}/#{app} not found" unless Dir["#{@apps_root}/*"].detect do |f|
|
51
|
+
File.directory?(f) && File.basename(f).downcase.to_sym == app
|
52
|
+
end
|
53
|
+
new_app = Application.new("#{@apps_root}/#{app.to_s.downcase}")
|
54
|
+
@apps[app] = new_app
|
55
|
+
rescue => e
|
56
|
+
raise AppLoadError, "Couldn't load #{app}. Inner Exception: #{e.to_s}"
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
require 'MediTAF/utils/exceptions'
|
2
|
+
|
3
|
+
module MediTAF
|
4
|
+
# Representation of the meditaf_config.yml configuration file.
|
5
|
+
module Utils
|
6
|
+
module Configuration
|
7
|
+
|
8
|
+
class << self
|
9
|
+
# @param filepath [String] path/to/file
|
10
|
+
# @raise [ConfigurationNotFoundError] when YAML cannot load the file
|
11
|
+
def new(filepath = nil)
|
12
|
+
filepath ||= Dir.glob(File.join("**", "meditaf_config.yml")).first
|
13
|
+
yml_hashes = []
|
14
|
+
|
15
|
+
# load main yaml file
|
16
|
+
yml_hashes << YAML.load_file(filepath)
|
17
|
+
raise FileEmpty, "#{filepath} is empty. Nothing to config, YAY!" unless yml_hashes[0]
|
18
|
+
|
19
|
+
# load additional yml files
|
20
|
+
if yml_hashes[0]['modules']['config_files']
|
21
|
+
yml_hashes[0]['modules']['config_files'].split(/ *, */).each { |f| yml_hashes << YAML.load_file(f) }
|
22
|
+
modules = yml_hashes.shift
|
23
|
+
added = yml_hashes.each_with_object({}) { |oh, nh| nh.merge!(oh) }
|
24
|
+
modules['modules'].merge!(added)
|
25
|
+
end
|
26
|
+
modules ||= yml_hashes[0]
|
27
|
+
|
28
|
+
# merge all yml hashes into one hash
|
29
|
+
@modules = Settings.new('modules', modules['modules'] )
|
30
|
+
rescue Errno::ENOENT => e
|
31
|
+
raise FileNotFound, "missing configuration. check you have meditaf_config in the 'config' or " +
|
32
|
+
"project root directory and is valid."
|
33
|
+
rescue Psych::SyntaxError => e
|
34
|
+
raise Error, "Configuration Error : #{e}"
|
35
|
+
end
|
36
|
+
|
37
|
+
# backward compatibility for older style references of Configuration['modules']['xxx']
|
38
|
+
def [](key)
|
39
|
+
(key == 'modules') ? @modules : @modules['modules'][key]
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
class Settings
|
44
|
+
def initialize(key, settings)
|
45
|
+
@key = key
|
46
|
+
@settings = settings
|
47
|
+
self
|
48
|
+
end
|
49
|
+
|
50
|
+
def [](key)
|
51
|
+
# backward compatibility for older style references of $config['modules']['xxx']
|
52
|
+
return self if key == 'modules' && @key == 'modules'
|
53
|
+
(@settings[key].is_a?(Hash)) ? Settings.new(@key + '/' + key, @settings[key]) : @settings[key] if @settings.has_key?(key)
|
54
|
+
end
|
55
|
+
|
56
|
+
def include?(key)
|
57
|
+
@settings.has_key?(key)
|
58
|
+
end
|
59
|
+
|
60
|
+
private
|
61
|
+
|
62
|
+
def []=(key, value)
|
63
|
+
@settings[key] = value
|
64
|
+
end
|
65
|
+
|
66
|
+
def delete(key)
|
67
|
+
@settings.delete(key) if @settings.has_key?(key)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
# When the specified configuration file has not configuration items i.e. EMPTY
|
72
|
+
class FileEmpty < StandardError; end
|
73
|
+
|
74
|
+
# Specified configuration file or meditaf_config.yml file not in config directory or project root directory
|
75
|
+
class FileNotFound < StandardError; end
|
76
|
+
|
77
|
+
# General configuration error: usually invalid YAML syntax
|
78
|
+
class Error < StandardError; end
|
79
|
+
|
80
|
+
# When request modules key is not found in configuration
|
81
|
+
class ItemNotFound < StandardError; end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'MediTAF/utils/logger'
|
2
|
+
|
3
|
+
module MediTAF
|
4
|
+
module Utils
|
5
|
+
module Exceptions
|
6
|
+
|
7
|
+
# MediTAF Exception with logging
|
8
|
+
class MediTAFException < StandardError
|
9
|
+
include MediTAF::Utils::Logger
|
10
|
+
|
11
|
+
# @param message [String] error message.
|
12
|
+
def initialize(message = 'MediTAF Exception') # Default Message
|
13
|
+
log.error message
|
14
|
+
super(message)
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
|
2
|
+
require 'logging'
|
3
|
+
|
4
|
+
module MediTAF
|
5
|
+
module Utils
|
6
|
+
# Logging Mechanism based on Logging gem
|
7
|
+
module Logger
|
8
|
+
|
9
|
+
# @return [Logging::Logger]
|
10
|
+
def log
|
11
|
+
@log ||= Logger.logger_for(self.class.name)
|
12
|
+
end
|
13
|
+
|
14
|
+
attr_reader :loggers
|
15
|
+
@loggers = {}
|
16
|
+
|
17
|
+
class << self
|
18
|
+
|
19
|
+
# for unit testing purposes only
|
20
|
+
def loggers
|
21
|
+
@loggers
|
22
|
+
end
|
23
|
+
|
24
|
+
# @param classname [Class] the class for which to log
|
25
|
+
# @return [Logging::Logger]
|
26
|
+
def logger_for(classname)
|
27
|
+
@loggers[classname] ||= configure_logger_for(classname)
|
28
|
+
end
|
29
|
+
|
30
|
+
# @param classname [Class] the class for which to log
|
31
|
+
# @return [Logging::Logger]
|
32
|
+
def configure_logger_for(classname)
|
33
|
+
raise LoggingConfigurationMissing, 'logging not found in configuration' unless MediTAF::Utils::Configuration['logging']
|
34
|
+
raise LoggingFilePathMissing, 'logging filepath not found in configuration' unless MediTAF::Utils::Configuration['logging']['filepath']
|
35
|
+
raise LoggingLevelMissing, 'logging level not found in configuration' unless MediTAF::Utils::Configuration['logging']['level']
|
36
|
+
|
37
|
+
config = MediTAF::Utils::Configuration['logging']
|
38
|
+
log = Logging.logger[classname]
|
39
|
+
|
40
|
+
log.add_appenders(
|
41
|
+
Logging.appenders.stdout('stdout', :layout => Logging.layouts.pattern(:pattern => '[%d] %-5l %c: %m\n')),
|
42
|
+
Logging.appenders.file("#{config['filepath']}", :layout => Logging.layouts.pattern(:pattern => '[%d] %-5l %c: %m\n'))
|
43
|
+
)
|
44
|
+
|
45
|
+
# valid levels are debug, info, warn, error, fatal
|
46
|
+
log.level = config['level'].to_sym
|
47
|
+
log
|
48
|
+
rescue LoggingConfigurationMissing, LoggingFilePathMissing, LoggingLevelMissing => e
|
49
|
+
raise e
|
50
|
+
rescue => e
|
51
|
+
raise LoggingConfigurationError, "Inner Exception: #{e.to_s}"
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
55
|
+
|
56
|
+
class LoggingConfigurationError < StandardError; end
|
57
|
+
class LoggingConfigurationMissing < StandardError; end
|
58
|
+
class LoggingFilePathMissing < StandardError; end
|
59
|
+
class LoggingLevelMissing < StandardError; end
|
60
|
+
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,118 @@
|
|
1
|
+
require 'gmail'
|
2
|
+
require 'MediTAF/utils/exceptions'
|
3
|
+
|
4
|
+
module MediTAF
|
5
|
+
module Utils
|
6
|
+
module Email
|
7
|
+
class Mail < Gmail::Client::Base
|
8
|
+
|
9
|
+
attr_reader :gmail
|
10
|
+
|
11
|
+
def initialize(username, options = {})
|
12
|
+
@gmail = Gmail.new(username, options)
|
13
|
+
end
|
14
|
+
|
15
|
+
# finds the unread invite email from iMedidata
|
16
|
+
# @param from [String] the from email address.
|
17
|
+
# @param subject [String] the subject of the email.
|
18
|
+
# @param newest [Boolean] the subject of the email.
|
19
|
+
# @param date [String] the date of the email. Defaults to today's date.
|
20
|
+
# @param to [String] the recepient email address.
|
21
|
+
def find_email(from, subject=nil, newest=true, date=Time.now, to=nil)
|
22
|
+
email_options={}
|
23
|
+
email_options[:from]= "#{from}" if from
|
24
|
+
email_options[:to]= "#{to}" if to
|
25
|
+
email_options[:on]= Date.parse("#{date}") if date
|
26
|
+
Message.new do
|
27
|
+
|
28
|
+
@gmail.inbox.find(:unread,email_options).each do |email|
|
29
|
+
subject.nil? || email.message.subject == subject
|
30
|
+
end.send(newest ? :last : :first)
|
31
|
+
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
# finds and deletes the email
|
36
|
+
# @param from [String] the from email address.
|
37
|
+
# @param subject [String] the subject of the email.
|
38
|
+
# @param date [String] the date of the email. Defaults to today's date.
|
39
|
+
def delete(from, subject=nil, date=Time.now)
|
40
|
+
raise SubjectNil if subject.nil?
|
41
|
+
@gmail.inbox.find(:all, on: Date.parse("#{date}"), from: "#{from}", subject: subject).each do |email|
|
42
|
+
email.delete!
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
# logs out of Mail
|
47
|
+
def logout
|
48
|
+
@gmail.logout
|
49
|
+
end
|
50
|
+
|
51
|
+
# whether or not you are logged in
|
52
|
+
def logged_in?
|
53
|
+
@gmail.logged_in?
|
54
|
+
end
|
55
|
+
|
56
|
+
# sends mail using configured email address
|
57
|
+
# @param addr [String] the address to send to
|
58
|
+
# @param title [String] the subject of the email
|
59
|
+
# @param contents [String] the glob of the email
|
60
|
+
def send_mail(addr, title, contents)
|
61
|
+
if logged_in?
|
62
|
+
@gmail.deliver do
|
63
|
+
to addr
|
64
|
+
subject title
|
65
|
+
html_part do
|
66
|
+
content_type 'text/html; charset=UTF-8'
|
67
|
+
body contents
|
68
|
+
end
|
69
|
+
delivery_method :smtp, {address: 'smtp.lab1.hdc.mdsol.com', port: 80} if `hostname` =~ /hdc505lb/
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
75
|
+
|
76
|
+
class Message
|
77
|
+
attr_reader :email, :url, :body
|
78
|
+
|
79
|
+
def initialize()
|
80
|
+
if block_given?
|
81
|
+
@email = yield
|
82
|
+
raise InviteEmailNotFoundError, 'Invitation email was not found' if @email.nil?
|
83
|
+
@body = @email.html_part.body.dup
|
84
|
+
end
|
85
|
+
self
|
86
|
+
end
|
87
|
+
|
88
|
+
def email
|
89
|
+
@email
|
90
|
+
end
|
91
|
+
|
92
|
+
def subject
|
93
|
+
@email.message.subject
|
94
|
+
end
|
95
|
+
|
96
|
+
def body
|
97
|
+
raise InviteBodyNotFoundError, 'Invitation body was not found' if @body.nil?
|
98
|
+
@body.decoded
|
99
|
+
end
|
100
|
+
|
101
|
+
def url
|
102
|
+
body.scan(/https?:\/\/\S+imedidata\.\S+\/users\S+\/activation/).first.delete("'")
|
103
|
+
rescue => e
|
104
|
+
raise URLNotFoundError, "URL is missing or does not contain a valid invite link. Inner Exception: #{e.to_s}"
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
class InviteEmailNotFoundError < MediTAF::Utils::Exceptions::MediTAFException;
|
109
|
+
end
|
110
|
+
class InviteBodyNotFoundError < MediTAF::Utils::Exceptions::MediTAFException;
|
111
|
+
end
|
112
|
+
class URLNotFoundError < MediTAF::Utils::Exceptions::MediTAFException;
|
113
|
+
end
|
114
|
+
class SubjectNil < MediTAF::Utils::Exceptions::MediTAFException;
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
@@ -0,0 +1,122 @@
|
|
1
|
+
# MeditafFaker is a module that provides random fake data for uid codes, random numbers, timestamp based on the Faker gem
|
2
|
+
#
|
3
|
+
#*********************************************************************************************************************S**c*#
|
4
|
+
require 'MediTAF/utils/configuration'
|
5
|
+
require 'faker'
|
6
|
+
|
7
|
+
require 'i18n'
|
8
|
+
|
9
|
+
I18n.enforce_available_locales = true
|
10
|
+
I18n.reload!
|
11
|
+
|
12
|
+
module MediTAF
|
13
|
+
module Utils
|
14
|
+
class Base < Faker::Base
|
15
|
+
|
16
|
+
class << self
|
17
|
+
def stringify(param, *params)
|
18
|
+
"#{param}#{params.join()}"
|
19
|
+
end
|
20
|
+
|
21
|
+
protected
|
22
|
+
def random_generator
|
23
|
+
rand(1000..9999)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
# TimeStamp: a class that provides the current date time format
|
29
|
+
class MediTAFFaker < Base
|
30
|
+
class << self
|
31
|
+
|
32
|
+
##using Faker address
|
33
|
+
def address
|
34
|
+
Faker::Address
|
35
|
+
end
|
36
|
+
|
37
|
+
# using Faker name
|
38
|
+
def name
|
39
|
+
Faker::Name
|
40
|
+
end
|
41
|
+
|
42
|
+
# using Faker code
|
43
|
+
def code
|
44
|
+
Faker::Code
|
45
|
+
end
|
46
|
+
|
47
|
+
# using Faker number
|
48
|
+
def number
|
49
|
+
Faker::Number
|
50
|
+
end
|
51
|
+
|
52
|
+
# using Faker phone_number
|
53
|
+
def phone_number
|
54
|
+
Faker::PhoneNumber
|
55
|
+
end
|
56
|
+
|
57
|
+
# Default representation of the current date format
|
58
|
+
def timestamp
|
59
|
+
DateTime.now.strftime()
|
60
|
+
end
|
61
|
+
|
62
|
+
# Default representation of the current date format
|
63
|
+
def medidata_date_format
|
64
|
+
DateTime.now.strftime("%d-%b-%Y")
|
65
|
+
end
|
66
|
+
|
67
|
+
# Long representation of the current date format - Missing Year
|
68
|
+
def timestamp_long
|
69
|
+
DateTime.now.strftime("%m%d%H%M%S%6N")
|
70
|
+
end
|
71
|
+
|
72
|
+
# Short representation of the current date format with minutes, seconds and micro seconds
|
73
|
+
def timestamp_short
|
74
|
+
DateTime.now.strftime("%M%S%6N")
|
75
|
+
end
|
76
|
+
|
77
|
+
# Complete representation of the current date format including picosecons
|
78
|
+
def timestamp_complete
|
79
|
+
DateTime.now.strftime("%m-%d-%Y:%H%M%S.%12N")
|
80
|
+
end
|
81
|
+
|
82
|
+
# Random: a class that displays a random string in the MD5 format based on DateTime as string
|
83
|
+
def random
|
84
|
+
random_generator.to_s
|
85
|
+
end
|
86
|
+
|
87
|
+
# UID: a class that displays a random string in the MD5 format based on DateTime as string
|
88
|
+
def uid
|
89
|
+
Digest::MD5.hexdigest(DateTime.now.strftime("%m-%d-%Y:%H%M%S.%12N")).to_s
|
90
|
+
end
|
91
|
+
|
92
|
+
# Code: a class that inherits from Faker:Code. It provides UID (32/40-bit length).
|
93
|
+
def uid_md5(no_dash=true)
|
94
|
+
no_dash ? generate_32_bit_checkmateUID_without_dash : generate_32_bit_checkmateUID_with_dash
|
95
|
+
end
|
96
|
+
|
97
|
+
def uid_sha1(no_dash=true)
|
98
|
+
no_dash ? generate_40_bit_checkmateUID_without_dash : generate_40_bit_checkmateUID_with_dash
|
99
|
+
end
|
100
|
+
|
101
|
+
private
|
102
|
+
|
103
|
+
def generate_32_bit_checkmateUID_with_dash
|
104
|
+
regexify(/[a-f0-9]{8}-([a-f0-9]{4}-){3}[a-f0-9]{12}/)
|
105
|
+
end
|
106
|
+
|
107
|
+
def generate_32_bit_checkmateUID_without_dash
|
108
|
+
regexify(/[a-f0-9]{32}/)
|
109
|
+
end
|
110
|
+
|
111
|
+
def generate_40_bit_checkmateUID_with_dash
|
112
|
+
regexify(/[a-f0-9]{12}-([a-f0-9]{4}-){4}[a-f0-9]{12}/)
|
113
|
+
end
|
114
|
+
|
115
|
+
def generate_40_bit_checkmateUID_without_dash
|
116
|
+
regexify(/[a-f0-9]{40}/)
|
117
|
+
end
|
118
|
+
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module MediTAF
|
2
|
+
module Utils
|
3
|
+
class Sticky < Hash
|
4
|
+
|
5
|
+
def initialize(default_value=nil)
|
6
|
+
super default_value
|
7
|
+
end
|
8
|
+
|
9
|
+
def [](key)
|
10
|
+
raise MediTAF::Utils::StickyKeyNotFound, "I don't have '#{key}' key" unless has_key? key
|
11
|
+
super key
|
12
|
+
end
|
13
|
+
|
14
|
+
def set_value(key, value)
|
15
|
+
self[key] = value
|
16
|
+
end
|
17
|
+
|
18
|
+
# @param data [String] reference to stored value
|
19
|
+
# @return [Object] the stored value at reference
|
20
|
+
# @raise [] when the reference is not found
|
21
|
+
def get_value(data)
|
22
|
+
result = data.dup
|
23
|
+
result.scan(/(\w+|\w)\s*/).each { |memo| result.sub!("#{memo[0]}", self["#{memo[0]}"]) if self["#{memo[0]}"] } if result.is_a? String
|
24
|
+
result
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
class StickyKeyNotFound < MediTAF::Utils::Exceptions::MediTAFException; end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
metadata
ADDED
@@ -0,0 +1,147 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: Test_Framework1.0
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.6.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Medidata Test Automation Framework Team
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-07-16 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: require_all
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 1.3.2
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 1.3.2
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: logging
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 1.8.2
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 1.8.2
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: faker
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '1.3'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '1.3'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: gmail
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: multi_xml
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: selenium-webdriver
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '2.46'
|
90
|
+
type: :runtime
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '2.46'
|
97
|
+
description: " Test Automation Framework"
|
98
|
+
email:
|
99
|
+
- chriwilliams_23@yahoo.com
|
100
|
+
executables: []
|
101
|
+
extensions: []
|
102
|
+
extra_rdoc_files: []
|
103
|
+
files:
|
104
|
+
- LICENSE
|
105
|
+
- README.md
|
106
|
+
- lib/MediTAF.rb
|
107
|
+
- lib/MediTAF/services.rb
|
108
|
+
- lib/MediTAF/services/clients.rb
|
109
|
+
- lib/MediTAF/services/clients/euresource_adapter.rb
|
110
|
+
- lib/MediTAF/services/clients/mauth_adapter.rb
|
111
|
+
- lib/MediTAF/services/resources_mgr.rb
|
112
|
+
- lib/MediTAF/ui.rb
|
113
|
+
- lib/MediTAF/ui/application.rb
|
114
|
+
- lib/MediTAF/ui/applications.rb
|
115
|
+
- lib/MediTAF/utils/configuration.rb
|
116
|
+
- lib/MediTAF/utils/exceptions.rb
|
117
|
+
- lib/MediTAF/utils/logger.rb
|
118
|
+
- lib/MediTAF/utils/mail.rb
|
119
|
+
- lib/MediTAF/utils/meditaf_faker.rb
|
120
|
+
- lib/MediTAF/utils/sticky.rb
|
121
|
+
- lib/MediTAF/version.rb
|
122
|
+
homepage: ''
|
123
|
+
licenses:
|
124
|
+
- MIT
|
125
|
+
- LICENSE
|
126
|
+
metadata: {}
|
127
|
+
post_install_message:
|
128
|
+
rdoc_options: []
|
129
|
+
require_paths:
|
130
|
+
- lib
|
131
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
132
|
+
requirements:
|
133
|
+
- - ">="
|
134
|
+
- !ruby/object:Gem::Version
|
135
|
+
version: '0'
|
136
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
137
|
+
requirements:
|
138
|
+
- - ">="
|
139
|
+
- !ruby/object:Gem::Version
|
140
|
+
version: '0'
|
141
|
+
requirements: []
|
142
|
+
rubyforge_project:
|
143
|
+
rubygems_version: 2.4.5.1
|
144
|
+
signing_key:
|
145
|
+
specification_version: 4
|
146
|
+
summary: Test Automation Framework
|
147
|
+
test_files: []
|