prestashop-automation 0.5
Sign up to get free protection for your applications and to get access to all the features.
- 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: []
|