prestashop-automation 0.5
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.
- data/lib/actions/carriers.rb +94 -0
- data/lib/actions/cart_rules.rb +98 -0
- data/lib/actions/general.rb +65 -0
- data/lib/actions/installer.rb +100 -0
- data/lib/actions/orders.rb +67 -0
- data/lib/actions/products.rb +55 -0
- data/lib/actions/settings.rb +37 -0
- data/lib/actions/taxes.rb +62 -0
- data/lib/helpers/general.rb +75 -0
- data/lib/prestashop-automation.rb +59 -0
- data/test/all.rb +130 -0
- metadata +59 -0
@@ -0,0 +1,94 @@
|
|
1
|
+
module PrestaShopAutomation
|
2
|
+
module CarriersActions
|
3
|
+
def create_carrier options
|
4
|
+
goto_admin_tab 'AdminCarriers'
|
5
|
+
find('#page-header-desc-carrier-new_carrier').click
|
6
|
+
|
7
|
+
fill_in 'name', :with => options[:name]
|
8
|
+
fill_in 'delay_1', :with => options[:delay] || 'Turtle'
|
9
|
+
fill_in 'grade', :with => options[:grade] if options[:grade]
|
10
|
+
fill_in 'url', :with => options[:tracking_url] if options[:tracking_url]
|
11
|
+
|
12
|
+
click '.buttonNext.btn.btn-default'
|
13
|
+
|
14
|
+
click_label_for "shipping_handling_#{onoff options[:with_handling_fees]}"
|
15
|
+
click_label_for "is_free_#{onoff options[:free_shipping]}"
|
16
|
+
|
17
|
+
choose options[:based_on] == :price ? 'billing_price' : 'billing_weight'
|
18
|
+
|
19
|
+
select_by_value '#id_tax_rules_group', (options[:tax_group_id] || 0)
|
20
|
+
|
21
|
+
select_by_value '#range_behavior', (options[:out_of_range_behavior] === :disable ? 1 : 0)
|
22
|
+
|
23
|
+
|
24
|
+
options[:ranges] = options[:ranges] || [{:from_included => 0, :to_excluded => 1000, :prices => {0 => 0}}]
|
25
|
+
options[:ranges].each_with_index do |range, i|
|
26
|
+
|
27
|
+
if i > 0
|
28
|
+
click '#add_new_range'
|
29
|
+
end
|
30
|
+
|
31
|
+
unless options[:free_shipping]
|
32
|
+
if i == 0
|
33
|
+
find("input[name='range_inf[#{i}]']").set range[:from_included]
|
34
|
+
find("input[name='range_sup[#{i}]']").set range[:to_excluded]
|
35
|
+
else
|
36
|
+
find("input[name='range_inf[]']:nth-of-type(#{i})").set range[:from_included]
|
37
|
+
find("input[name='range_sup[]']:nth-of-type(#{i})").set range[:to_excluded]
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
sleep 1
|
42
|
+
|
43
|
+
range[:prices].each_pair do |zone, price|
|
44
|
+
|
45
|
+
nth = i > 0 ? ":nth-of-type(#{i})" : ""
|
46
|
+
|
47
|
+
if zone == 0
|
48
|
+
find('.fees_all input[type="checkbox"]').click if i == 0
|
49
|
+
unless options[:free_shipping]
|
50
|
+
tp = all('.fees_all input[type="text"]')[i]
|
51
|
+
tp.set price
|
52
|
+
tp.native.send_keys :tab
|
53
|
+
end
|
54
|
+
sleep 4
|
55
|
+
else
|
56
|
+
check "zone_#{zone}"
|
57
|
+
sleep 1
|
58
|
+
unless options[:free_shipping]
|
59
|
+
if i == 0
|
60
|
+
find("input[name='fees[#{zone}][#{i}]']").set price
|
61
|
+
else
|
62
|
+
find("input[name='fees[#{zone}][]']"+nth).set price
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
click '.buttonNext.btn.btn-default'
|
70
|
+
|
71
|
+
fill_in 'max_height', :with => options[:max_package_height] if options[:max_package_height]
|
72
|
+
fill_in 'max_width', :with => options[:max_package_width] if options[:max_package_width]
|
73
|
+
fill_in 'max_depth', :with => options[:max_package_depth] if options[:max_package_depth]
|
74
|
+
fill_in 'max_weight', :with => options[:max_package_weight] if options[:max_package_weight]
|
75
|
+
|
76
|
+
if !options[:allowed_groups]
|
77
|
+
check 'checkme'
|
78
|
+
else
|
79
|
+
check 'checkme'
|
80
|
+
uncheck 'checkme'
|
81
|
+
options[:allowed_groups].each do |group|
|
82
|
+
check "groupBox_#{group}"
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
click '.buttonNext.btn.btn-default'
|
87
|
+
|
88
|
+
click_label_for 'active_on'
|
89
|
+
sleep 4 #this wait seems necessary, strange
|
90
|
+
click 'a.buttonFinish'
|
91
|
+
standard_success_check
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
@@ -0,0 +1,98 @@
|
|
1
|
+
module PrestaShopAutomation
|
2
|
+
module CartRulesActions
|
3
|
+
def create_cart_rule options
|
4
|
+
goto_admin_tab 'AdminCartRules'
|
5
|
+
find('#page-header-desc-cart_rule-new_cart_rule').click
|
6
|
+
fill_in 'name_1', :with => options[:name]
|
7
|
+
|
8
|
+
click_label_for "partial_use_#{onoff (options[:partial_use] != false)}"
|
9
|
+
click_label_for 'active_on'
|
10
|
+
|
11
|
+
find('#cart_rule_link_conditions').click
|
12
|
+
find('input[name="date_from"]').set '1900-01-01 00:00:00'
|
13
|
+
find('input[name="date_to"]').set '2500-01-01 00:00:00'
|
14
|
+
|
15
|
+
find('input[name="quantity"]').set 1000000
|
16
|
+
find('input[name="quantity_per_user"]').set 1000000
|
17
|
+
|
18
|
+
product_name = nil
|
19
|
+
if options[:product_id]
|
20
|
+
check 'product_restriction'
|
21
|
+
find('#product_restriction_div a').click
|
22
|
+
within '#product_rule_type_1' do
|
23
|
+
find('option[value="products"]').click
|
24
|
+
end
|
25
|
+
find('#product_rule_group_table a[href*="javascript:addProductRule("]').click
|
26
|
+
find('#product_rule_1_1_choose_link').click
|
27
|
+
within '#product_rule_select_1_1_1' do
|
28
|
+
option = find("option[value='#{options[:product_id]}']", :visible => false)
|
29
|
+
option.click
|
30
|
+
product_name = option.native.text.strip
|
31
|
+
end
|
32
|
+
addButton = find('#product_rule_select_1_1_add')
|
33
|
+
addButton.click
|
34
|
+
addButton.native.send_keys :escape
|
35
|
+
end
|
36
|
+
|
37
|
+
find('#cart_rule_link_actions').click
|
38
|
+
|
39
|
+
if options[:free_shipping]
|
40
|
+
click_label_for 'free_shipping_on'
|
41
|
+
else
|
42
|
+
click_label_for 'free_shipping_off'
|
43
|
+
end
|
44
|
+
|
45
|
+
click_label_for 'free_gift_off'
|
46
|
+
|
47
|
+
amount_exp = /^(?:(\w+)\s+)?(\d+(?:\.\d+)?)\s*(?:tax\s+(excluded|included))$/
|
48
|
+
if m = amount_exp.match(options[:amount].strip)
|
49
|
+
currency, amount, with_tax = m[1].to_s.strip, m[2].to_f, (m[3] == 'included' ? 1 : 0)
|
50
|
+
choose 'apply_discount_amount'
|
51
|
+
fill_in 'reduction_amount', :with => amount
|
52
|
+
if currency != ''
|
53
|
+
within 'select[name="reduction_currency"]' do
|
54
|
+
find(:xpath, "//option[normalize-space()='#{currency}']").click
|
55
|
+
end
|
56
|
+
end
|
57
|
+
within 'select[name="reduction_tax"]' do
|
58
|
+
find("option[value='#{with_tax}']").click
|
59
|
+
end
|
60
|
+
|
61
|
+
find('#desc-cart_rule-save-and-stay').click
|
62
|
+
standard_success_check
|
63
|
+
find('#cart_rule_link_actions').click
|
64
|
+
|
65
|
+
if options[:product_id]
|
66
|
+
choose 'apply_discount_to_product'
|
67
|
+
fill_in 'reductionProductFilter', :with => product_name
|
68
|
+
find('div.ac_results ul li').click
|
69
|
+
end
|
70
|
+
elsif m = /^(\d+(?:\.\d+)?)\s*%$/.match(options[:amount].strip)
|
71
|
+
percent = m[1]
|
72
|
+
choose 'apply_discount_percent'
|
73
|
+
fill_in 'reduction_percent', :with => percent
|
74
|
+
if options[:product_id]
|
75
|
+
choose 'apply_discount_to_selection'
|
76
|
+
else
|
77
|
+
choose 'apply_discount_to_order'
|
78
|
+
end
|
79
|
+
else
|
80
|
+
throw "Invalid cart rule amount specified!"
|
81
|
+
end
|
82
|
+
|
83
|
+
find('#desc-cart_rule-save-and-stay').click
|
84
|
+
standard_success_check
|
85
|
+
id = current_url[/\bid_cart_rule=(\d+)/, 1].to_i
|
86
|
+
id.should be > 0
|
87
|
+
return id
|
88
|
+
end
|
89
|
+
|
90
|
+
def delete_cart_rule id
|
91
|
+
goto_admin_tab 'AdminCartRules'
|
92
|
+
url = first("a[href*='&deletecart_rule&']", :visible => false)['href']
|
93
|
+
url.gsub! /\bid_cart_rule=\d+/, "id_cart_rule=#{id}"
|
94
|
+
visit url
|
95
|
+
standard_success_check
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
module PrestaShopAutomation
|
2
|
+
module GeneralActions
|
3
|
+
def login_to_back_office
|
4
|
+
visit @back_office_url
|
5
|
+
fill_in "email", :with => @admin_email
|
6
|
+
fill_in "passwd", :with => @admin_password
|
7
|
+
click_label_for 'stay_logged_in'
|
8
|
+
click_button_named 'submitLogin', :first => true
|
9
|
+
expect_to have_selector('#header_logout', :visible => false)
|
10
|
+
@logged_in_to_back_office_as = {
|
11
|
+
email: @admin_email,
|
12
|
+
password: @admin_password
|
13
|
+
}
|
14
|
+
end
|
15
|
+
|
16
|
+
def goto_back_office
|
17
|
+
visit @back_office_url
|
18
|
+
end
|
19
|
+
|
20
|
+
def goto_front_office
|
21
|
+
visit @front_office_url
|
22
|
+
end
|
23
|
+
|
24
|
+
def logout_of_back_office
|
25
|
+
visit @back_office_url
|
26
|
+
click '#employee_infos a'
|
27
|
+
click '#header_logout'
|
28
|
+
expect_to have_selector('button[name="submitLogin"]')
|
29
|
+
@logged_in_to_back_office_as = nil
|
30
|
+
end
|
31
|
+
|
32
|
+
def login_to_front_office
|
33
|
+
visit @front_office_url
|
34
|
+
click 'a.login'
|
35
|
+
within '#login_form' do
|
36
|
+
fill_in 'email', :with => @default_customer_email
|
37
|
+
fill_in 'passwd', :with => @default_customer_password
|
38
|
+
end
|
39
|
+
click '#SubmitLogin'
|
40
|
+
expect_to have_selector('p.info-account')
|
41
|
+
@logged_in_to_front_office_as = {
|
42
|
+
email: @default_customer_email,
|
43
|
+
password: @default_customer_password
|
44
|
+
}
|
45
|
+
end
|
46
|
+
|
47
|
+
def logout_of_front_office
|
48
|
+
visit @front_office_url
|
49
|
+
click 'a.logout'
|
50
|
+
expect_to have_selector 'a.login'
|
51
|
+
@logged_in_to_front_office_as = nil
|
52
|
+
end
|
53
|
+
|
54
|
+
def goto_admin_tab tab
|
55
|
+
links = Hash[all('ul.menu a', :visible => false).to_a.keep_if do |a|
|
56
|
+
a['href'] =~ /\?controller=/
|
57
|
+
end.map do |a|
|
58
|
+
[a['href'][/\?controller=(.+?)\b/, 1], a['href']]
|
59
|
+
end]
|
60
|
+
expect(links[tab]).not_to eq nil
|
61
|
+
visit links[tab]
|
62
|
+
expect(current_url).to match /\bcontroller=#{tab}\b/
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,100 @@
|
|
1
|
+
require 'mysql2'
|
2
|
+
|
3
|
+
module PrestaShopAutomation
|
4
|
+
module InstallerActions
|
5
|
+
|
6
|
+
def install options={}
|
7
|
+
if options[:prepare_database]
|
8
|
+
prepare_database
|
9
|
+
end
|
10
|
+
|
11
|
+
visit @installer_url
|
12
|
+
select_by_value '#langList', options[:language] || 'en'
|
13
|
+
click '#btNext'
|
14
|
+
click_label_for 'set_license'
|
15
|
+
click '#btNext'
|
16
|
+
|
17
|
+
fill_in 'infosShop', :with => options[:shop_name] || @database_name
|
18
|
+
find("input[name='db_mode'][value='#{options[:no_demo_products] ? 'lite' : 'full'}']").click
|
19
|
+
select_by_value_jqChosen '#infosCountry', options[:country] || 'us'
|
20
|
+
|
21
|
+
if options[:timezone]
|
22
|
+
select_by_value_jqChosen '#infosTimezone', options[:timezone]
|
23
|
+
end
|
24
|
+
|
25
|
+
fill_in 'infosFirstname', :with => options[:admin_firstname] || @admin_firstname || 'John'
|
26
|
+
fill_in 'infosName', :with => options[:admin_lastname] || @admin_lastname || 'Doe'
|
27
|
+
fill_in 'infosEmail', :with => options[:admin_email] || @admin_email || 'pub@prestashop.com'
|
28
|
+
password = options[:admin_password] || @admin_password || '123456789'
|
29
|
+
fill_in 'infosPassword', :with => password
|
30
|
+
fill_in 'infosPasswordRepeat', :with => password
|
31
|
+
|
32
|
+
if options[:newsletter]
|
33
|
+
check 'infosNotification'
|
34
|
+
else
|
35
|
+
uncheck 'infosNotification'
|
36
|
+
end
|
37
|
+
|
38
|
+
click '#btNext'
|
39
|
+
|
40
|
+
fill_in 'dbServer', :with => "#{@database_host}:#{@database_port}"
|
41
|
+
fill_in 'dbName', :with => @database_name
|
42
|
+
fill_in 'dbLogin', :with => @database_user
|
43
|
+
fill_in 'dbPassword', :with => @database_password
|
44
|
+
fill_in 'db_prefix', :with => @database_prefix
|
45
|
+
|
46
|
+
click '#btTestDB'
|
47
|
+
|
48
|
+
if options[:prepare_database]
|
49
|
+
#db should be ok if we used :prepare_database
|
50
|
+
expect_to have_selector '#dbResultCheck.okBlock'
|
51
|
+
else
|
52
|
+
check 'db_clear' if has_selector? 'db_clear'
|
53
|
+
expect_to have_selector '#dbResultCheck.errorBlock'
|
54
|
+
click '#btCreateDB'
|
55
|
+
expect_to have_selector '#dbResultCheck.okBlock'
|
56
|
+
end
|
57
|
+
|
58
|
+
click '#btNext'
|
59
|
+
|
60
|
+
wait_until do
|
61
|
+
has_selector? 'a.BO' and has_selector? 'a.FO'
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def drop_database
|
66
|
+
client.query("DROP DATABASE IF EXISTS #{safe_database_name}")
|
67
|
+
end
|
68
|
+
|
69
|
+
def prepare_database
|
70
|
+
results = client.query("SHOW DATABASES LIKE '#{client.escape @database_name}'")
|
71
|
+
expect(results.count).to be <= 1
|
72
|
+
if results.count == 0
|
73
|
+
client.query "CREATE DATABASE #{safe_database_name}"
|
74
|
+
else
|
75
|
+
tables = client.query("SHOW TABLES IN #{safe_database_name} LIKE '#{client.escape @database_prefix}%'")
|
76
|
+
tables.each do |row|
|
77
|
+
table = row.values[0]
|
78
|
+
client.query "DROP TABLE #{safe_database_name}.`#{table}`"
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
private
|
84
|
+
|
85
|
+
def safe_database_name
|
86
|
+
"`#{@database_name.gsub '`', ''}`"
|
87
|
+
end
|
88
|
+
|
89
|
+
def client
|
90
|
+
return @client if @client
|
91
|
+
|
92
|
+
@client = Mysql2::Client.new({
|
93
|
+
host: @database_host,
|
94
|
+
username: @database_user,
|
95
|
+
password: @database_password,
|
96
|
+
port: @database_port
|
97
|
+
})
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
module PrestaShopAutomation
|
2
|
+
module OrdersActions
|
3
|
+
|
4
|
+
def add_product_to_cart id, quantity=1
|
5
|
+
visit @front_office_url, "/index.php?id_product=#{id}&controller=product&id_lang=1"
|
6
|
+
fill_in 'quantity_wanted', :with => (quantity || 1)
|
7
|
+
find('#add_to_cart button').click
|
8
|
+
sleep 1
|
9
|
+
end
|
10
|
+
|
11
|
+
def add_products_to_cart products
|
12
|
+
products.each do |product|
|
13
|
+
add_product_to_cart product[:id], product[:quantity]
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def order_current_cart_5_steps options
|
18
|
+
visit @front_office_url, "/index.php?controller=order"
|
19
|
+
find('a.standard-checkout').click
|
20
|
+
find('button[name="processAddress"]').click
|
21
|
+
click_label_for "cgv"
|
22
|
+
click_label_for "gift" if options[:gift_wrapping]
|
23
|
+
find(:xpath, '//tr[contains(., "'+options[:carrier]+'")]').find('input[type=radio]', :visible => false).click
|
24
|
+
click_button_named 'processCarrier'
|
25
|
+
click 'a.bankwire'
|
26
|
+
click '#cart_navigation button'
|
27
|
+
order_id = current_url[/\bid_order=(\d+)/, 1].to_i
|
28
|
+
expect(order_id).to be > 0
|
29
|
+
return order_id
|
30
|
+
end
|
31
|
+
|
32
|
+
def order_current_cart_opc options
|
33
|
+
visit @front_office_url, "/index.php?controller=order-opc"
|
34
|
+
visit @front_office_url, "/index.php?controller=order-opc" #yeah, twice, there's a bug
|
35
|
+
click_label_for "cgv"
|
36
|
+
click_label_for "gift" if options[:gift_wrapping]
|
37
|
+
find(:xpath, '//tr[contains(., "'+options[:carrier]+'")]').find('input[type=radio]', :visible => false).click
|
38
|
+
click 'a.bankwire'
|
39
|
+
click '#cart_navigation button'
|
40
|
+
order_id = current_url[/\bid_order=(\d+)/, 1].to_i
|
41
|
+
expect(order_id).to be > 0
|
42
|
+
return order_id
|
43
|
+
end
|
44
|
+
|
45
|
+
def validate_order options
|
46
|
+
goto_admin_tab 'AdminOrders'
|
47
|
+
|
48
|
+
visit @back_office_url, first('td.pointer[onclick]')['onclick'][/\blocation\s*=\s*'(.*?)'/, 1].sub(/\bid_order=\d+/, "id_order=#{options[:id]}")
|
49
|
+
click '#id_order_state_chosen'
|
50
|
+
click 'li[data-option-array-index="6"]' #hardcoded for now: payment accepted
|
51
|
+
click_button_named 'submitState'
|
52
|
+
pdf_url = find('a[href*="generateInvoicePDF"]')['href']
|
53
|
+
|
54
|
+
if options[:dump_pdf_to]
|
55
|
+
all_cookies = page.driver.browser.manage.all_cookies
|
56
|
+
cookies = all_cookies.map do |c| "#{c[:name]}=#{c[:value]}" end.join ";"
|
57
|
+
cmd = "curl --url #{Shellwords.shellescape pdf_url} -b \"#{cookies}\" -o #{Shellwords.shellescape options[:dump_pdf_to]} 2>/dev/null"
|
58
|
+
`#{cmd}` #download the PDF
|
59
|
+
end
|
60
|
+
|
61
|
+
if options[:get_invoice_json]
|
62
|
+
visit pdf_url+'&debug=1'
|
63
|
+
return JSON.parse(page.find('body').text)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
module PrestaShopAutomation
|
2
|
+
module ProductsActions
|
3
|
+
#todo: ecotax
|
4
|
+
def create_product options
|
5
|
+
goto_admin_tab 'AdminProducts'
|
6
|
+
|
7
|
+
find('#page-header-desc-product-new_product').click
|
8
|
+
|
9
|
+
fill_in 'name_1', :with => options[:name]
|
10
|
+
sleep 2
|
11
|
+
click '#link-Seo'
|
12
|
+
expect_not_to have_field('link_rewrite_1', with: "")
|
13
|
+
|
14
|
+
click '#link-Prices'
|
15
|
+
fill_in 'priceTE', :with => options[:price]
|
16
|
+
|
17
|
+
if options[:tax_group_id]
|
18
|
+
select_by_value '#id_tax_rules_group', options[:tax_group_id]
|
19
|
+
end
|
20
|
+
|
21
|
+
if sp = options[:specific_price]
|
22
|
+
save_product
|
23
|
+
|
24
|
+
click '#show_specific_price'
|
25
|
+
|
26
|
+
if m = /^minus\s+(\d+(?:\.\d+)?)\s+tax\s+included$/.match(sp.strip)
|
27
|
+
select_by_value '#sp_reduction_type', 'amount'
|
28
|
+
fill_in 'sp_reduction', :with => m[1]
|
29
|
+
elsif m = /^minus\s+(\d+(?:\.\d+)?)\s*%$/.match(sp.strip)
|
30
|
+
select_by_value '#sp_reduction_type', 'percentage'
|
31
|
+
fill_in 'sp_reduction', :with => m[1]
|
32
|
+
else
|
33
|
+
throw "Invalid specific price: #{sp}"
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
save_product
|
38
|
+
|
39
|
+
# allow ordering if out of stock
|
40
|
+
click '#link-Quantities'
|
41
|
+
choose 'out_of_stock_2'
|
42
|
+
|
43
|
+
save_product
|
44
|
+
|
45
|
+
return current_url[/\bid_product=(\d+)/, 1].to_i
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
def save_product andWait=2
|
50
|
+
click_button_named 'submitAddproductAndStay', :first => true
|
51
|
+
standard_success_check
|
52
|
+
sleep andWait
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module PrestaShopAutomation
|
2
|
+
module SettingsActions
|
3
|
+
|
4
|
+
def set_friendly_urls on
|
5
|
+
goto_admin_tab 'AdminMeta'
|
6
|
+
if on
|
7
|
+
click_label_for 'PS_REWRITING_SETTINGS_on'
|
8
|
+
else
|
9
|
+
click_label_for 'PS_REWRITING_SETTINGS_off'
|
10
|
+
end
|
11
|
+
click_button_named 'submitOptionsmeta', :first => true
|
12
|
+
standard_success_check
|
13
|
+
end
|
14
|
+
|
15
|
+
def set_gift_wrapping_option on, options
|
16
|
+
goto_admin_tab 'AdminOrderPreferences'
|
17
|
+
if on
|
18
|
+
click_label_for 'PS_GIFT_WRAPPING_on'
|
19
|
+
find('input[name="PS_GIFT_WRAPPING_PRICE"]').set options[:price]
|
20
|
+
select_by_value '#PS_GIFT_WRAPPING_TAX_RULES_GROUP', (options[:tax_group_id] || 0)
|
21
|
+
click_label_for "PS_RECYCLABLE_PACK_#{onoff options[:recycling_option]}"
|
22
|
+
else
|
23
|
+
click_label_for 'PS_GIFT_WRAPPING_off'
|
24
|
+
end
|
25
|
+
click_button_named 'submitOptionsconfiguration', :first => true
|
26
|
+
standard_success_check
|
27
|
+
end
|
28
|
+
|
29
|
+
def set_order_process_type value
|
30
|
+
goto_admin_tab 'AdminOrderPreferences'
|
31
|
+
select_by_value '#PS_ORDER_PROCESS_TYPE', {:five_steps => 0, :opc => 1}[value]
|
32
|
+
click_button_named 'submitOptionsconfiguration', :first => true
|
33
|
+
standard_success_check
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
module PrestaShopAutomation
|
2
|
+
module TaxesActions
|
3
|
+
|
4
|
+
def create_tax options
|
5
|
+
goto_admin_tab 'AdminTaxes'
|
6
|
+
click '#page-header-desc-tax-new_tax'
|
7
|
+
fill_in 'name_1', :with => options[:name]
|
8
|
+
fill_in 'rate', :with => options[:rate]
|
9
|
+
click_label_for 'active_on'
|
10
|
+
click '#tax_form_submit_btn'
|
11
|
+
standard_success_check
|
12
|
+
return current_url[/\bid_tax=(\d+)/, 1].to_i
|
13
|
+
end
|
14
|
+
|
15
|
+
def create_tax_group options
|
16
|
+
goto_admin_tab 'AdminTaxRulesGroup'
|
17
|
+
find('#page-header-desc-tax_rules_group-new_tax_rules_group').click
|
18
|
+
fill_in 'name', :with => options[:name]
|
19
|
+
click_label_for 'active_on'
|
20
|
+
click '#tax_rules_group_form_submit_btn'
|
21
|
+
standard_success_check
|
22
|
+
|
23
|
+
options[:taxes].each do |tax|
|
24
|
+
find('#page-header-desc-tax_rule-new').click
|
25
|
+
select_by_value '#country', (tax[:country_id] || 0)
|
26
|
+
select_by_value '#behavior', {:no => 0, :sum => 1, :multiply => 2}[tax[:combine] || :no]
|
27
|
+
select_by_value '#id_tax', tax[:tax_id]
|
28
|
+
click '#tax_rule_form_submit_btn'
|
29
|
+
standard_success_check
|
30
|
+
end
|
31
|
+
|
32
|
+
return current_url[/\bid_tax_rules_group=(\d+)/, 1].to_i
|
33
|
+
end
|
34
|
+
|
35
|
+
def create_tax_group_from_rate rate
|
36
|
+
if /^(?:\d+(?:.\d+)?)$/ =~ rate
|
37
|
+
tax_id = create_tax :name => "#{rate}% Tax (Rate)", :rate => rate
|
38
|
+
create_tax_group :name => "#{rate}% Tax (Group)", :taxes => [{:tax_id => tax_id}]
|
39
|
+
elsif /(?:\d+(?:.\d+)?)(?:\s*(?:\+|\*)\s*(?:\d+(?:.\d+)?))+/ =~ rate
|
40
|
+
taxes = []
|
41
|
+
combine = {'+' => :sum, '*' => :multiply}[rate[/(\+|\*)/, 1]] || :no
|
42
|
+
rate.split(/\s+/).each do |token|
|
43
|
+
if token == '+'
|
44
|
+
combine = :sum
|
45
|
+
elsif token == '*'
|
46
|
+
combine = :multiply
|
47
|
+
else
|
48
|
+
tax_id = create_tax :name => "#{token}% Tax (Rate)", :rate => token
|
49
|
+
taxes << {
|
50
|
+
:tax_id => tax_id,
|
51
|
+
:combine => combine
|
52
|
+
}
|
53
|
+
end
|
54
|
+
end
|
55
|
+
create_tax_group :name => "Composite #{rate} Tax (Group)", :taxes => taxes
|
56
|
+
else
|
57
|
+
throw "Invalid tax rate format: #{rate}"
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
module PrestaShopAutomation
|
2
|
+
module GeneralHelpers
|
3
|
+
|
4
|
+
def onoff val
|
5
|
+
val ? 'on' : 'off'
|
6
|
+
end
|
7
|
+
|
8
|
+
def click_label_for id
|
9
|
+
find("label[for='#{id}']").click
|
10
|
+
end
|
11
|
+
|
12
|
+
def click_button_named name, options={}
|
13
|
+
selector = "button[name='#{name}']"
|
14
|
+
if options[:first]
|
15
|
+
first(selector).click
|
16
|
+
else
|
17
|
+
find(selector).click
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def select_by_value select_selector, value
|
22
|
+
within select_selector do
|
23
|
+
find("option[value='#{value}']").click
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def select_by_value_jqChosen select_selector, value
|
28
|
+
options = Hash[all("#{select_selector} option", :visible => false).to_a.each_with_index.map do |option, i|
|
29
|
+
[option['value'], i]
|
30
|
+
end]
|
31
|
+
expect(options[value]).not_to be nil
|
32
|
+
container = find("#{select_selector} + .chosen-container")
|
33
|
+
container.click
|
34
|
+
within container do
|
35
|
+
click "li[data-option-array-index='#{options[value]}']"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def click selector
|
40
|
+
find(selector).click
|
41
|
+
end
|
42
|
+
|
43
|
+
def expect_to matcher
|
44
|
+
expect(self).to matcher
|
45
|
+
end
|
46
|
+
|
47
|
+
def expect_not_to matcher
|
48
|
+
expect(self).not_to matcher
|
49
|
+
end
|
50
|
+
|
51
|
+
def standard_success_check
|
52
|
+
expect_to have_selector '.alert.alert-success'
|
53
|
+
end
|
54
|
+
|
55
|
+
def visit base, rest=nil
|
56
|
+
if rest == nil
|
57
|
+
super base
|
58
|
+
else
|
59
|
+
super base.sub(/\/\s*/, '') + rest.sub(/^\s*\//, '')
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def wait_until options = {}, &block
|
64
|
+
elapsed = 0
|
65
|
+
dt = options[:interval] || 1
|
66
|
+
timeout = options[:timeout] || 60
|
67
|
+
until (ok = yield) or (elapsed > timeout)
|
68
|
+
elapsed += sleep dt
|
69
|
+
end
|
70
|
+
unless ok
|
71
|
+
throw "Timeout exceeded!"
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require 'rspec-expectations'
|
2
|
+
require 'capybara'
|
3
|
+
|
4
|
+
require_relative 'actions/general.rb'
|
5
|
+
require_relative 'actions/settings.rb'
|
6
|
+
require_relative 'actions/products.rb'
|
7
|
+
require_relative 'actions/taxes.rb'
|
8
|
+
require_relative 'actions/carriers.rb'
|
9
|
+
require_relative 'actions/cart_rules.rb'
|
10
|
+
require_relative 'actions/orders.rb'
|
11
|
+
require_relative 'actions/installer.rb'
|
12
|
+
|
13
|
+
require_relative 'helpers/general.rb'
|
14
|
+
|
15
|
+
module PrestaShopAutomation
|
16
|
+
class PrestaShop < Capybara::Session
|
17
|
+
|
18
|
+
include RSpec::Expectations
|
19
|
+
include RSpec::Matchers
|
20
|
+
#include Capybara::RSpecMatchers
|
21
|
+
|
22
|
+
include PrestaShopAutomation::GeneralHelpers
|
23
|
+
|
24
|
+
include PrestaShopAutomation::GeneralActions
|
25
|
+
include PrestaShopAutomation::SettingsActions
|
26
|
+
include PrestaShopAutomation::ProductsActions
|
27
|
+
include PrestaShopAutomation::TaxesActions
|
28
|
+
include PrestaShopAutomation::CarriersActions
|
29
|
+
include PrestaShopAutomation::CartRulesActions
|
30
|
+
include PrestaShopAutomation::OrdersActions
|
31
|
+
include PrestaShopAutomation::InstallerActions
|
32
|
+
|
33
|
+
def initialize options
|
34
|
+
|
35
|
+
@front_office_url = options[:front_office_url]
|
36
|
+
@back_office_url = options[:back_office_url]
|
37
|
+
@installer_url = options[:installer_url]
|
38
|
+
@admin_email = options[:admin_email] || 'pub@prestashop.com'
|
39
|
+
@admin_password = options[:admin_password] || '123456789'
|
40
|
+
@default_customer_email = options[:default_customer_email] || 'pub@prestashop.com'
|
41
|
+
@default_customer_password = options[:default_customer_password] || '123456789'
|
42
|
+
@database_user = options[:database_user] || 'root'
|
43
|
+
@database_password = options[:database_password] || ''
|
44
|
+
@database_name = options[:database_name]
|
45
|
+
@database_prefix = options[:database_prefix] || 'ps_'
|
46
|
+
@database_port = options[:database_port] || '3306'
|
47
|
+
@database_host = options[:database_host] || 'localhost'
|
48
|
+
@filesystem_path = options[:filesystem_path]
|
49
|
+
@version = options[:version]
|
50
|
+
|
51
|
+
super :selenium
|
52
|
+
end
|
53
|
+
|
54
|
+
def quit
|
55
|
+
driver.browser.quit
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
end
|
data/test/all.rb
ADDED
@@ -0,0 +1,130 @@
|
|
1
|
+
require_relative '../lib/prestashop-automation.rb'
|
2
|
+
|
3
|
+
ps = PrestaShopAutomation::PrestaShop.new({
|
4
|
+
:back_office_url => 'http://localhost/1.6/admin-dev/',
|
5
|
+
:front_office_url => 'http://localhost/1.6/',
|
6
|
+
:installer_url => 'http://localhost/1.6/install-dev',
|
7
|
+
:admin_email => 'pub@prestashop.com',
|
8
|
+
:admin_password => '123456789',
|
9
|
+
:database_name => '1.6'
|
10
|
+
})
|
11
|
+
|
12
|
+
describe 'Installing' do
|
13
|
+
it 'should use the UI to prepare the database' do
|
14
|
+
ps.drop_database
|
15
|
+
ps.install
|
16
|
+
ps.reset!
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'should prepare the database externally' do
|
20
|
+
ps.drop_database
|
21
|
+
ps.install :prepare_database => true
|
22
|
+
ps.reset!
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
describe 'Front Office Primitives' do
|
27
|
+
|
28
|
+
before :all do
|
29
|
+
ps.login_to_front_office
|
30
|
+
ps.login_to_back_office
|
31
|
+
ps.set_friendly_urls false
|
32
|
+
end
|
33
|
+
|
34
|
+
after :all do
|
35
|
+
ps.logout_of_front_office
|
36
|
+
ps.logout_of_back_office
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'should add product 1 to cart and make an order in OPC' do
|
40
|
+
ps.goto_back_office
|
41
|
+
ps.set_order_process_type :opc
|
42
|
+
ps.goto_front_office
|
43
|
+
ps.add_product_to_cart 1
|
44
|
+
order_id = ps.order_current_cart_opc :carrier => 'My carrier'
|
45
|
+
ps.goto_back_office
|
46
|
+
ps.validate_order id: order_id
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'should add product 1 to cart and make an order in 5 steps checkout' do
|
50
|
+
ps.goto_back_office
|
51
|
+
ps.set_order_process_type :five_steps
|
52
|
+
ps.goto_front_office
|
53
|
+
ps.add_product_to_cart 1
|
54
|
+
order_id = ps.order_current_cart_5_steps :carrier => 'My carrier'
|
55
|
+
ps.goto_back_office
|
56
|
+
ps.validate_order id: order_id
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
describe 'Back Office Primitives' do
|
61
|
+
|
62
|
+
before :all do
|
63
|
+
ps.login_to_back_office
|
64
|
+
end
|
65
|
+
|
66
|
+
after :all do
|
67
|
+
ps.logout_of_back_office
|
68
|
+
end
|
69
|
+
|
70
|
+
describe 'Creating And Deleting a Cart Rule' do
|
71
|
+
it 'should work with one product' do
|
72
|
+
id = ps.create_cart_rule :name => 'YiiHaaa', :product_id => 1, :amount => '10%'
|
73
|
+
ps.delete_cart_rule id
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
describe 'Creating carriers' do
|
78
|
+
it 'should work in the simplest case' do
|
79
|
+
ps.create_carrier :name => 'Turtle Bob'
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
describe 'Creating taxes' do
|
84
|
+
|
85
|
+
it 'should create a complicated tax group' do
|
86
|
+
ps.create_tax_group_from_rate '10 + 9.6'
|
87
|
+
end
|
88
|
+
|
89
|
+
it 'should create a tax and a tax group' do
|
90
|
+
tax_id = ps.create_tax :name => 'Some Tax', :rate => '20'
|
91
|
+
ps.create_tax_group :name => 'Test Tax Group', :taxes => [{:tax_id => tax_id}]
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
describe 'Creating products' do
|
96
|
+
|
97
|
+
it 'should work with a specific price' do
|
98
|
+
ps.create_product :name => 'Petit Sachet de Vis Cruciformes Pas Cher', :price => '1.92', :specific_price => 'minus 1 tax included'
|
99
|
+
end
|
100
|
+
|
101
|
+
it 'should work with just a price and a name' do
|
102
|
+
ps.create_product :name => 'Petit Sachet de Vis Cruciformes', :price => '1.85'
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
describe 'Changing a few settings' do
|
107
|
+
it 'should enable OPC' do
|
108
|
+
ps.set_order_process_type :opc
|
109
|
+
end
|
110
|
+
|
111
|
+
it 'should disable OPC' do
|
112
|
+
ps.set_order_process_type :five_steps
|
113
|
+
end
|
114
|
+
|
115
|
+
it 'shoud enable Gift Wrapping' do
|
116
|
+
ps.set_gift_wrapping_option true, :price => 2
|
117
|
+
end
|
118
|
+
|
119
|
+
it 'shoud enable Friendly URLs' do
|
120
|
+
ps.set_friendly_urls true
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
describe 'Navigating the back office' do
|
125
|
+
it 'should go to AdminOrders' do
|
126
|
+
ps.goto_admin_tab 'AdminOrders'
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
end
|
metadata
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: prestashop-automation
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: '0.5'
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- François-Marie de Jouvencel
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2014-05-14 00:00:00.000000000 Z
|
13
|
+
dependencies: []
|
14
|
+
description: ! 'A nice ruby framework to build complex selenium tests around PrestaShop.
|
15
|
+
|
16
|
+
This gem provides building blocks to create advanced scenarios in a very consise
|
17
|
+
way.'
|
18
|
+
email: fm.de.jouvencel@gmail.com
|
19
|
+
executables: []
|
20
|
+
extensions: []
|
21
|
+
extra_rdoc_files: []
|
22
|
+
files:
|
23
|
+
- lib/prestashop-automation.rb
|
24
|
+
- lib/helpers/general.rb
|
25
|
+
- lib/actions/products.rb
|
26
|
+
- lib/actions/installer.rb
|
27
|
+
- lib/actions/cart_rules.rb
|
28
|
+
- lib/actions/carriers.rb
|
29
|
+
- lib/actions/orders.rb
|
30
|
+
- lib/actions/settings.rb
|
31
|
+
- lib/actions/general.rb
|
32
|
+
- lib/actions/taxes.rb
|
33
|
+
- test/all.rb
|
34
|
+
homepage: https://github.com/djfm/prestashop-automation
|
35
|
+
licenses:
|
36
|
+
- OSL
|
37
|
+
post_install_message:
|
38
|
+
rdoc_options: []
|
39
|
+
require_paths:
|
40
|
+
- lib
|
41
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
42
|
+
none: false
|
43
|
+
requirements:
|
44
|
+
- - ! '>='
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: '0'
|
47
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
48
|
+
none: false
|
49
|
+
requirements:
|
50
|
+
- - ! '>='
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: '0'
|
53
|
+
requirements: []
|
54
|
+
rubyforge_project:
|
55
|
+
rubygems_version: 1.8.23
|
56
|
+
signing_key:
|
57
|
+
specification_version: 3
|
58
|
+
summary: Framework to test and automate tasks in PrestaShop.
|
59
|
+
test_files: []
|