chemistrykit 3.7.0 → 3.8.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.rubocop.yml +6 -0
- data/CHANGELOG.md +21 -0
- data/Gemfile +13 -0
- data/Guardfile +9 -0
- data/README.md +59 -2
- data/Rakefile +34 -6
- data/chemistrykit.gemspec +3 -11
- data/exceptions.reek +3 -0
- data/features/chemists.feature +123 -0
- data/features/new.feature +2 -0
- data/lib/chemistrykit/chemist.rb +34 -0
- data/lib/chemistrykit/chemist/repository/csv_chemist_repository.rb +79 -0
- data/lib/chemistrykit/cli/cli.rb +14 -9
- data/lib/chemistrykit/configuration.rb +2 -2
- data/lib/chemistrykit/formula/chemist_aware.rb +10 -0
- data/lib/chemistrykit/formula/formula_lab.rb +99 -0
- data/lib/chemistrykit/parallel_tests_mods.rb +1 -1
- data/lib/templates/chemistrykit/chemists/chemists.csv +1 -0
- data/lib/templates/formula.tt +2 -0
- data/spec/integration/lib/chemistrykit/formula/formula_lab_spec.rb +59 -0
- data/spec/spec_helper.rb +3 -0
- data/spec/support/bad_chemists.csv +3 -0
- data/spec/support/chemists.csv +6 -0
- data/spec/support/default_chemists.csv +1 -0
- data/spec/support/formulas/sub_module/basic_formula.rb +13 -0
- data/spec/support/formulas/sub_module/chemist_formula.rb +15 -0
- data/spec/support/keyless_chemists.csv +3 -0
- data/spec/support/other_chemists.csv +2 -0
- data/spec/unit/lib/chemistrykit/chemist/repository/csv_chemist_repository_spec.rb +99 -0
- data/spec/unit/lib/chemistrykit/chemist_spec.rb +43 -0
- data/spec/unit/lib/chemistrykit/formula/chemist_aware_spec.rb +25 -0
- data/spec/unit/lib/chemistrykit/formula/formula_lab_spec.rb +63 -0
- metadata +39 -119
data/.rubocop.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,24 @@
|
|
1
|
+
#3.8.0 (2013-08-05)
|
2
|
+
Implemented the chemists feature to add user data management as well as a simplified strategy for loading formulas
|
3
|
+
|
4
|
+
- Bumped version to 3.8.0 to prepare for release.
|
5
|
+
- cleaned up docs a little and ensured the default chemists csv file wouldnt cause a failure if left unpopulated
|
6
|
+
- added a uuid injector for a token in csv files
|
7
|
+
- integrated the fomula lab into the suite runner and added basic cucumber tests
|
8
|
+
- built out the rest of the formula lab and integration tests
|
9
|
+
- updated templates to create the default chemists folder
|
10
|
+
- upped the flog limits... still need to understand how that will help
|
11
|
+
- updated chemist and chemist repository to include key, as well as selection by key, random, or first of type
|
12
|
+
- updated documentation of new changes
|
13
|
+
- built out the rest of the csv chemist repository
|
14
|
+
- started building out the user data repository from a csv file.
|
15
|
+
- built out a basic chemist class
|
16
|
+
- added module to define chemist aware for the formulas to include
|
17
|
+
- added reek and rubocop to the guard file
|
18
|
+
- moved dev dependencies to gemfile, added in new code quality checks, fixed some code issues found by rubocop, updated rake tasks
|
19
|
+
- updated selenium connect version
|
20
|
+
- added animoto mention to friends section
|
21
|
+
|
1
22
|
#3.7.0 (2013-07-24)
|
2
23
|
updated evidence to put in test based folders and added configuration for the retry functionality
|
3
24
|
|
data/Gemfile
CHANGED
@@ -2,3 +2,16 @@ source "https://rubygems.org"
|
|
2
2
|
|
3
3
|
# Specify dependencies in chemistrykit.gemspec
|
4
4
|
gemspec
|
5
|
+
|
6
|
+
gem 'aruba', '~> 0.5.1'
|
7
|
+
gem 'cucumber', '~> 1.2.1'
|
8
|
+
gem 'rake', '~> 10.0.3'
|
9
|
+
gem 'rubocop', git: 'https://github.com/bbatsov/rubocop.git', branch: 'master'
|
10
|
+
gem 'guard-rspec', '~> 3.0.2'
|
11
|
+
gem 'coveralls', '~> 0.6.7'
|
12
|
+
gem 'flog'
|
13
|
+
gem 'flay'
|
14
|
+
gem 'ruby2ruby'
|
15
|
+
gem 'reek', '1.3.1'
|
16
|
+
gem 'guard-reek'
|
17
|
+
gem 'guard-rubocop'
|
data/Guardfile
CHANGED
@@ -1,5 +1,14 @@
|
|
1
|
+
# Encoding: utf-8
|
2
|
+
|
1
3
|
guard :rspec do
|
2
4
|
watch(%r{^spec/unit/.+_spec\.rb$})
|
5
|
+
watch(%r{^spec/integration/.+_spec\.rb$})
|
3
6
|
watch(%r{^lib/(.+)\.rb$}) { |m| "spec/unit/lib/#{m[1]}_spec.rb" }
|
7
|
+
watch(%r{^lib/(.+)\.rb$}) { |m| "spec/integration/lib/#{m[1]}_spec.rb" }
|
4
8
|
watch('spec/spec_helper.rb') { "spec" }
|
5
9
|
end
|
10
|
+
|
11
|
+
guard :rubocop, all_on_start: false do
|
12
|
+
watch(%r{^spec/.+\.rb$})
|
13
|
+
watch(%r{^lib/.+\.rb$})
|
14
|
+
end
|
data/README.md
CHANGED
@@ -1,10 +1,10 @@
|
|
1
|
-
#ChemistryKit 3.
|
1
|
+
#ChemistryKit 3.8.0 (2013-08-05)
|
2
2
|
|
3
3
|
[![Gem Version](https://badge.fury.io/rb/chemistrykit.png)](http://badge.fury.io/rb/chemistrykit) [![Build Status](https://travis-ci.org/arrgyle/chemistrykit.png?branch=develop)](https://travis-ci.org/jrobertfox/chef-broiler-platter) [![Code Climate](https://codeclimate.com/github/arrgyle/chemistrykit.png)](https://codeclimate.com/github/arrgyle/chemistrykit) [![Coverage Status](https://coveralls.io/repos/arrgyle/chemistrykit/badge.png?branch=develop)](https://coveralls.io/r/arrgyle/chemistrykit?branch=develop)
|
4
4
|
|
5
5
|
### A simple and opinionated web testing framework for Selenium WebDriver
|
6
6
|
|
7
|
-
This framework was designed to help you get started with Selenium WebDriver quickly, to grow as needed, and to avoid common pitfalls by following convention over configuration. To checkout the user group go [here](https://groups.google.com/forum/#!forum/chemistrykit-users).
|
7
|
+
This framework was designed to help you get started with Selenium WebDriver quickly, to grow as needed, and to avoid common pitfalls by following convention over configuration. To checkout the user group go [here](https://groups.google.com/forum/#!forum/chemistrykit-users). For more usage examples check out our [Friends](#friends) section!
|
8
8
|
|
9
9
|
|
10
10
|
ChemistryKit's inspiration comes from the Saunter Selenium framework which is available in Python and PHP. You can find more about it [here](http://element34.ca/products/saunter).
|
@@ -17,6 +17,7 @@ All the documentation for ChemistryKit can be found in this README, organized as
|
|
17
17
|
- [Command Line Usage](#command-line-usage)
|
18
18
|
- [Contribution Guidelines](#contribution-guidelines)
|
19
19
|
- [Deployment](#deployment)
|
20
|
+
- [Friends](#friends)
|
20
21
|
|
21
22
|
##Getting Started
|
22
23
|
|
@@ -84,6 +85,54 @@ Code in the `formula` directory can be used to build out page objects and helper
|
|
84
85
|
|
85
86
|
So for example if you have a `alpha_page.rb` file in your formulas directory that depends on a `helpers.rb` file, then you best put the `helpers.rb` file in the `lib` directory so it is loaded before the file that depends on it.
|
86
87
|
|
88
|
+
###Chemists! The Users of your System Under Test
|
89
|
+
With ChemistryKit we made it simple to encapsulate data about a particular user that is "using" your application that you are testing. We call them chemists. When you create a new test harness there will be a `chemists` folder that contains an empty `chemists.csv` file with only the words `key` and `type` at the top. In this folder you can create any number of files with arbitrary user data, **just make sure to include the `key` and`type` headings!** such as:
|
90
|
+
|
91
|
+
/chemists/my_valid_users.csv
|
92
|
+
/chemists/my_bad_users.csv
|
93
|
+
|
94
|
+
An example file might look like this:
|
95
|
+
|
96
|
+
Key,Type,Email,Name,Password
|
97
|
+
admin1,admin,admin@email.com,Mr. Admin,abc123$
|
98
|
+
normal1,normal,normal@email.com,Ms. Normal,test123%
|
99
|
+
normal2,normal,normal2@email.com,Ms. Normals,test123%
|
100
|
+
|
101
|
+
The `key` should be unique so you can pick a specific user, the type, allows you to group users to aid in their selection ad detailed below.
|
102
|
+
|
103
|
+
You can also put a special token in your csv files: `{{UUID}}` which will be replaced on runtime with a unique identifier. This can be helpful for ensuring certain date is unique across your tests, especially with concurrent runs.
|
104
|
+
|
105
|
+
Chemists are made available to your formulas simply by including the `ChemistAware` module in your formula, and loading the formula with the instance of `FormulaLab` provided to your beakers:
|
106
|
+
|
107
|
+
```Ruby
|
108
|
+
# my_formula.rb
|
109
|
+
module Formulas
|
110
|
+
class MyFormula < Formula
|
111
|
+
include ChemistryKit::Formula::ChemistAware
|
112
|
+
...
|
113
|
+
if chemist.email ...
|
114
|
+
...
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
|
119
|
+
# my_beaker.rb
|
120
|
+
describe "my beaker", :depth => 'shallow' do
|
121
|
+
let(:my_formula) { @formula_lab.using('my_formula').with('admin1').mix }
|
122
|
+
# or
|
123
|
+
let(:my_other_formula) { @formula_lab.formula.mix('my_other_formula') }
|
124
|
+
...
|
125
|
+
end
|
126
|
+
```
|
127
|
+
|
128
|
+
Here is a summary of the other methods available:
|
129
|
+
|
130
|
+
- `.with(key)` - Load a specific chemist by the key.
|
131
|
+
- `.with_random(type)` - Load a chemist at random from all those matching `type`
|
132
|
+
- `.with_first(type)` - Load whatever chemist is first matched by `type`
|
133
|
+
|
134
|
+
The FormulaLab will handle the heavy lifting of assembling your formal with a driver and correct user (if the formula needs one).
|
135
|
+
|
87
136
|
###Execution Order
|
88
137
|
Chemistry Kit executes specs in a random order. This is intentional. Knowing the order a spec will be executed in allows for dependencies between them to creep in. Sometimes unintentionally. By having them go in a random order parallelization becomes a much easier.
|
89
138
|
|
@@ -211,3 +260,11 @@ And another to finish the release:
|
|
211
260
|
rake release_finish['A helpful tag message that will be included in the gemspec.']
|
212
261
|
|
213
262
|
This handles updating the change log, committing, and tagging the release.
|
263
|
+
|
264
|
+
## Friends
|
265
|
+
|
266
|
+
Below you can find some honorable mentions of those friends that are using ChemistryKit:
|
267
|
+
|
268
|
+
![image](http://d14f1fnryngsxt.cloudfront.net/images/logo/animotologotext_f78c60cbbd36837c7aad596e3b3bb019.svg)
|
269
|
+
|
270
|
+
We are proud that [Animoto](http://animoto.com/) uses ChemistryKit to help them test their awesome web app.
|
data/Rakefile
CHANGED
@@ -4,14 +4,21 @@ require 'bundler/gem_tasks'
|
|
4
4
|
require 'cucumber'
|
5
5
|
require 'cucumber/rake/task'
|
6
6
|
require 'rspec/core/rake_task'
|
7
|
+
require 'rubocop/rake_task'
|
8
|
+
require 'flog_task'
|
9
|
+
require 'flay_task'
|
10
|
+
require 'reek/rake/task'
|
7
11
|
|
8
12
|
task default: :build
|
9
13
|
|
10
14
|
desc 'Runs standard build activities.'
|
11
|
-
task build: [:clean, :prepare, :
|
15
|
+
task build: [:clean, :prepare, :quality, :unit, :integration]
|
12
16
|
|
13
|
-
desc 'Runs
|
14
|
-
task build_full: [:clean, :prepare, :
|
17
|
+
desc 'Runs full build activities.'
|
18
|
+
task build_full: [:clean, :prepare, :quality, :unit, :integration, :system]
|
19
|
+
|
20
|
+
desc 'Runs quality checks.'
|
21
|
+
task quality: [:rubocop, :reek, :flog_total, :flog_average, :flay]
|
15
22
|
|
16
23
|
desc 'Removes the build directory.'
|
17
24
|
task :clean do
|
@@ -40,9 +47,30 @@ end
|
|
40
47
|
|
41
48
|
Cucumber::Rake::Task.new(:system)
|
42
49
|
|
43
|
-
|
44
|
-
|
45
|
-
|
50
|
+
Rubocop::RakeTask.new
|
51
|
+
|
52
|
+
# TODO: lower the quality score and improve the code!
|
53
|
+
FlogTask.new :flog_total, 2000 do |t|
|
54
|
+
t.method = :total_score
|
55
|
+
t.verbose = true
|
56
|
+
end
|
57
|
+
|
58
|
+
# TODO: lower the quality score and improve the code!
|
59
|
+
FlogTask.new :flog_average, 20 do |t|
|
60
|
+
t.method = :average
|
61
|
+
t.verbose = true
|
62
|
+
end
|
63
|
+
|
64
|
+
# TODO: lower the quality score and improve the code!
|
65
|
+
FlayTask.new :flay, 2000 do |t|
|
66
|
+
t.verbose = true
|
67
|
+
end
|
68
|
+
|
69
|
+
# TODO: fix all the smells and turn on failing on error
|
70
|
+
Reek::Rake::Task.new do |t|
|
71
|
+
t.fail_on_error = false
|
72
|
+
t.verbose = false
|
73
|
+
t.reek_opts = '--quiet'
|
46
74
|
end
|
47
75
|
|
48
76
|
# TODO This could probably be more cleanly automated
|
data/chemistrykit.gemspec
CHANGED
@@ -2,13 +2,13 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = 'chemistrykit'
|
5
|
-
s.version = '3.
|
5
|
+
s.version = '3.8.0'
|
6
6
|
s.platform = Gem::Platform::RUBY
|
7
7
|
s.authors = ['Dave Haeffner', 'Jason Fox']
|
8
8
|
s.email = ['dave@arrgyle.com', 'jason@arrgyle.com']
|
9
9
|
s.homepage = 'https://github.com/arrgyle/chemistrykit'
|
10
10
|
s.summary = 'A simple and opinionated web testing framework for Selenium that follows convention over configuration.'
|
11
|
-
s.description = '
|
11
|
+
s.description = 'Implemented the chemists feature to add user data management as well as a simplified strategy for loading formulas'
|
12
12
|
s.license = 'MIT'
|
13
13
|
|
14
14
|
s.files = `git ls-files`.split($/)
|
@@ -24,16 +24,8 @@ Gem::Specification.new do |s|
|
|
24
24
|
s.add_dependency 'builder', '~> 3.2.2'
|
25
25
|
s.add_dependency 'selenium-webdriver', '~> 2.29.0'
|
26
26
|
s.add_dependency 'rest-client', '~> 1.6.7'
|
27
|
-
s.add_dependency 'selenium-connect', '~> 3.
|
27
|
+
s.add_dependency 'selenium-connect', '~> 3.4.0'
|
28
28
|
s.add_dependency 'parallel_tests', '~> 0.15.0'
|
29
29
|
s.add_dependency 'parallel', '~> 0.7.0'
|
30
30
|
s.add_dependency 'rspec-retry', '~> 0.2.1'
|
31
|
-
|
32
|
-
s.add_development_dependency 'rspec', '~> 2.14.1'
|
33
|
-
s.add_development_dependency 'aruba', '~> 0.5.1'
|
34
|
-
s.add_development_dependency 'cucumber', '~> 1.2.1'
|
35
|
-
s.add_development_dependency 'rake', '~> 10.0.3'
|
36
|
-
s.add_development_dependency 'rubocop', '~> 0.9.0'
|
37
|
-
s.add_development_dependency 'guard-rspec', '~> 3.0.2'
|
38
|
-
s.add_development_dependency 'coveralls', '~> 0.6.7'
|
39
31
|
end
|
data/exceptions.reek
ADDED
@@ -0,0 +1,123 @@
|
|
1
|
+
Feature: Brewing a ChemistryKit project
|
2
|
+
|
3
|
+
Background: Setup the project
|
4
|
+
Given I run `ckit new chemists-test`
|
5
|
+
And I cd to "chemists-test"
|
6
|
+
And a file named "chemists/chemists.csv" with:
|
7
|
+
"""
|
8
|
+
Key,Type,Email,Name,Password
|
9
|
+
admin1,admin,admin@email.com,Mr. Admin,abc123$
|
10
|
+
normal1,normal,normal@email.com,Ms. Normal,test123%
|
11
|
+
ran1,random,normal@email.com,Ms. Normal,test123%
|
12
|
+
ran2,random,normal@email.com,Ms. Normal,test123%
|
13
|
+
"""
|
14
|
+
And a file named "formulas/basic_formula.rb" with:
|
15
|
+
"""
|
16
|
+
module Formulas
|
17
|
+
class BasicFormula < Formula
|
18
|
+
def open(url)
|
19
|
+
@driver.get url
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
"""
|
24
|
+
And a file named "formulas/chemist_formula.rb" with:
|
25
|
+
"""
|
26
|
+
require 'chemistrykit/formula/chemist_aware'
|
27
|
+
|
28
|
+
module Formulas
|
29
|
+
class ChemistFormula < Formula
|
30
|
+
include ChemistryKit::Formula::ChemistAware
|
31
|
+
def open(url)
|
32
|
+
@driver.get url
|
33
|
+
end
|
34
|
+
|
35
|
+
def search
|
36
|
+
search_box = find id: 'gbqfq'
|
37
|
+
search_box.send_keys chemist.type
|
38
|
+
search_box.send_keys :enter
|
39
|
+
end
|
40
|
+
|
41
|
+
def search_results_found?
|
42
|
+
wait_for(5) { displayed? id: 'search' }
|
43
|
+
search_results = find id: 'search'
|
44
|
+
search_results.text.include?(chemist.type)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
"""
|
49
|
+
And a file named "formulas/lib/formula.rb" with:
|
50
|
+
"""
|
51
|
+
module Formulas
|
52
|
+
class Formula < ChemistryKit::Formula::Base
|
53
|
+
|
54
|
+
def open(url)
|
55
|
+
@driver.get url
|
56
|
+
end
|
57
|
+
|
58
|
+
def find(locator)
|
59
|
+
@driver.find_element locator
|
60
|
+
end
|
61
|
+
|
62
|
+
def displayed?(locator)
|
63
|
+
begin
|
64
|
+
find(locator).displayed?
|
65
|
+
rescue
|
66
|
+
false
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def wait_for(seconds=2)
|
71
|
+
Selenium::WebDriver::Wait.new(:timeout => seconds).until { yield }
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
"""
|
76
|
+
|
77
|
+
Scenario: Simple formula loading with formula_lab
|
78
|
+
Given a file named "beakers/chemist_beaker.rb" with:
|
79
|
+
"""
|
80
|
+
describe "Chemist Beaker", :depth => 'shallow' do
|
81
|
+
let(:basic) { @formula_lab.mix('basic_formula') }
|
82
|
+
|
83
|
+
it "loads an external web page" do
|
84
|
+
basic.open "http://www.google.com"
|
85
|
+
end
|
86
|
+
end
|
87
|
+
"""
|
88
|
+
When I run `ckit brew`
|
89
|
+
Then the stdout should contain "1 example, 0 failures"
|
90
|
+
|
91
|
+
Scenario: Chemist formula loading with formula_lab
|
92
|
+
Given a file named "beakers/chemist_beaker.rb" with:
|
93
|
+
"""
|
94
|
+
describe "Chemist Beaker", :depth => 'shallow' do
|
95
|
+
let(:chem) { @formula_lab.using('chemist_formula').with('admin1').mix }
|
96
|
+
|
97
|
+
it "loads an external web page" do
|
98
|
+
chem.open "http://www.google.com"
|
99
|
+
chem.search
|
100
|
+
chem.search_results_found?.should eq true
|
101
|
+
end
|
102
|
+
end
|
103
|
+
"""
|
104
|
+
When I run `ckit brew`
|
105
|
+
Then the stdout should contain "1 example, 0 failures"
|
106
|
+
|
107
|
+
Scenario: Loading multiple formulas in a beaker
|
108
|
+
Given a file named "beakers/chemist_beaker.rb" with:
|
109
|
+
"""
|
110
|
+
describe "Chemist Beaker", :depth => 'shallow' do
|
111
|
+
let(:basic) { @formula_lab.mix('basic_formula') }
|
112
|
+
let(:chem) { @formula_lab.using('chemist_formula').with('admin1').mix }
|
113
|
+
|
114
|
+
it "loads an external web page" do
|
115
|
+
basic.open "http://www.google.com"
|
116
|
+
chem.search
|
117
|
+
chem.search_results_found?.should eq true
|
118
|
+
end
|
119
|
+
end
|
120
|
+
"""
|
121
|
+
When I run `ckit brew`
|
122
|
+
Then the stdout should contain "1 example, 0 failures"
|
123
|
+
|
data/features/new.feature
CHANGED
@@ -0,0 +1,34 @@
|
|
1
|
+
# Encoding: utf-8
|
2
|
+
|
3
|
+
module ChemistryKit
|
4
|
+
# representation of the user object for interacting with the system under test
|
5
|
+
class Chemist
|
6
|
+
|
7
|
+
attr_reader :key, :type, :data
|
8
|
+
|
9
|
+
def initialize(key, type)
|
10
|
+
@key = key.to_s
|
11
|
+
@type = type.to_s
|
12
|
+
@data = {}
|
13
|
+
end
|
14
|
+
|
15
|
+
def data=(data)
|
16
|
+
data.each do |key, value|
|
17
|
+
send("#{key}=", value)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
# allow this object to be set with arbitrary key value data
|
22
|
+
def method_missing(name, *arguments)
|
23
|
+
value = arguments[0]
|
24
|
+
name = name.to_s
|
25
|
+
if name[-1, 1] == '='
|
26
|
+
key = name[/(.+)\s?=/, 1]
|
27
|
+
@data[key.to_sym] = value unless instance_variables.include? "@#{key}".to_sym
|
28
|
+
else
|
29
|
+
@data[name.to_sym]
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
# Encoding: utf-8
|
2
|
+
|
3
|
+
require 'csv'
|
4
|
+
require 'securerandom'
|
5
|
+
require 'chemistrykit/chemist'
|
6
|
+
|
7
|
+
module ChemistryKit
|
8
|
+
# Chemist namespace
|
9
|
+
class Chemist
|
10
|
+
module Repository
|
11
|
+
# Provides the ability to load a chemist by type identifyer from a csv file
|
12
|
+
class CsvChemistRepository
|
13
|
+
|
14
|
+
def initialize(csv_path)
|
15
|
+
@tables = []
|
16
|
+
files = csv_path.kind_of?(String) ? [csv_path] : csv_path
|
17
|
+
|
18
|
+
files.each do |file|
|
19
|
+
raise ArgumentError, 'Supplied file does not exist!' unless File.exist? file
|
20
|
+
table = CSV.read(file, { headers: true, converters: :all, header_converters: :symbol })
|
21
|
+
[:key, :type].each do |header|
|
22
|
+
unless table.headers.include?(header) || table.headers.length == 0
|
23
|
+
raise ArgumentError, "You must define a #{header.to_s} field!"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
@tables.push table
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
# Required Method
|
31
|
+
# Load a specific chemist by the unique key
|
32
|
+
def load_chemist_by_key(key)
|
33
|
+
@tables.each do |table|
|
34
|
+
chemist_data = table.find { |row| row[:key] == key }
|
35
|
+
return make_chemist(key, chemist_data[:type], chemist_data) if chemist_data
|
36
|
+
end
|
37
|
+
raise ArgumentError, "Chemist for type \"#{key}\" not found!"
|
38
|
+
end
|
39
|
+
|
40
|
+
# Required Method
|
41
|
+
# Load the first chemist found for a given type
|
42
|
+
def load_first_chemist_of_type(type)
|
43
|
+
load_chemists_of_type(type)[0]
|
44
|
+
end
|
45
|
+
|
46
|
+
# Required Method
|
47
|
+
# Loads a chemist at random from all those found with a given type
|
48
|
+
def load_random_chemist_of_type(type)
|
49
|
+
load_chemists_of_type(type).sample
|
50
|
+
end
|
51
|
+
|
52
|
+
protected
|
53
|
+
|
54
|
+
def load_chemists_of_type(type)
|
55
|
+
chemists = []
|
56
|
+
@tables.each do |table|
|
57
|
+
chemist_data = table.select { |row| row[:type] == type }
|
58
|
+
if chemist_data
|
59
|
+
chemist_data.each do |data|
|
60
|
+
chemists << make_chemist(data[:key], type, data)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
raise ArgumentError, "Chemist for type \"#{type}\" not found!" if chemists.empty?
|
65
|
+
chemists
|
66
|
+
end
|
67
|
+
|
68
|
+
def make_chemist(key, type, data)
|
69
|
+
chemist = Chemist.new(key, type)
|
70
|
+
data_hash = data.to_hash
|
71
|
+
data_hash.map { |index, value| value.gsub!(/{{UUID}}/, SecureRandom.uuid) }
|
72
|
+
chemist.data = data_hash
|
73
|
+
chemist
|
74
|
+
end
|
75
|
+
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|