PageRenderTime 52ms CodeModel.GetById 13ms RepoModel.GetById 1ms app.codeStats 0ms

/backend/spec/features/admin/products/products_spec.rb

https://gitlab.com/adamlwalker/spree
Ruby | 394 lines | 321 code | 60 blank | 13 comment | 1 complexity | ae8c102984162245ddd9879caf2012d1 MD5 | raw file
  1. # encoding: utf-8
  2. require 'spec_helper'
  3. describe "Products", type: :feature do
  4. context "as admin user" do
  5. stub_authorization!
  6. def build_option_type_with_values(name, values)
  7. ot = FactoryGirl.create(:option_type, name: name)
  8. values.each do |val|
  9. ot.option_values.create(name: val.downcase, presentation: val)
  10. end
  11. ot
  12. end
  13. context "listing products" do
  14. context "sorting" do
  15. before do
  16. create(:product, name: 'apache baseball cap', price: 10)
  17. create(:product, name: 'zomg shirt', price: 5)
  18. end
  19. it "should list existing products with correct sorting by name" do
  20. visit spree.admin_products_path
  21. # Name ASC
  22. within_row(1) { expect(page).to have_content('apache baseball cap') }
  23. within_row(2) { expect(page).to have_content("zomg shirt") }
  24. # Name DESC
  25. click_link "admin_products_listing_name_title"
  26. within_row(1) { expect(page).to have_content("zomg shirt") }
  27. within_row(2) { expect(page).to have_content('apache baseball cap') }
  28. end
  29. it "should list existing products with correct sorting by price" do
  30. visit spree.admin_products_path
  31. # Name ASC (default)
  32. within_row(1) { expect(page).to have_content('apache baseball cap') }
  33. within_row(2) { expect(page).to have_content("zomg shirt") }
  34. # Price DESC
  35. click_link "admin_products_listing_price_title"
  36. within_row(1) { expect(page).to have_content("zomg shirt") }
  37. within_row(2) { expect(page).to have_content('apache baseball cap') }
  38. end
  39. end
  40. context "currency displaying" do
  41. context "using Russian Rubles" do
  42. before do
  43. Spree::Config[:currency] = "RUB"
  44. end
  45. let!(:product) do
  46. create(:product, name: "Just a product", price: 19.99)
  47. end
  48. # Regression test for #2737
  49. context "uses руб as the currency symbol" do
  50. it "on the products listing page" do
  51. visit spree.admin_products_path
  52. within_row(1) { expect(page).to have_content("19.99 ₽") }
  53. end
  54. end
  55. end
  56. end
  57. end
  58. context "searching products" do
  59. it "should be able to search deleted products" do
  60. create(:product, name: 'apache baseball cap', deleted_at: "2011-01-06 18:21:13")
  61. create(:product, name: 'zomg shirt')
  62. visit spree.admin_products_path
  63. expect(page).to have_content("zomg shirt")
  64. expect(page).not_to have_content("apache baseball cap")
  65. check "Show Deleted"
  66. click_on 'Search'
  67. expect(page).to have_content("zomg shirt")
  68. expect(page).to have_content("apache baseball cap")
  69. uncheck "Show Deleted"
  70. click_on 'Search'
  71. expect(page).to have_content("zomg shirt")
  72. expect(page).not_to have_content("apache baseball cap")
  73. end
  74. it "should be able to search products by their properties" do
  75. create(:product, name: 'apache baseball cap', sku: "A100")
  76. create(:product, name: 'apache baseball cap2', sku: "B100")
  77. create(:product, name: 'zomg shirt')
  78. visit spree.admin_products_path
  79. fill_in "q_name_cont", with: "ap"
  80. click_on 'Search'
  81. expect(page).to have_content("apache baseball cap")
  82. expect(page).to have_content("apache baseball cap2")
  83. expect(page).not_to have_content("zomg shirt")
  84. fill_in "q_variants_including_master_sku_cont", with: "A1"
  85. click_on 'Search'
  86. expect(page).to have_content("apache baseball cap")
  87. expect(page).not_to have_content("apache baseball cap2")
  88. expect(page).not_to have_content("zomg shirt")
  89. end
  90. end
  91. context "creating a new product from a prototype", js: true do
  92. def build_option_type_with_values(name, values)
  93. ot = FactoryGirl.create(:option_type, name: name)
  94. values.each do |val|
  95. ot.option_values.create(name: val.downcase, presentation: val)
  96. end
  97. ot
  98. end
  99. let(:product_attributes) do
  100. # FactoryGirl.attributes_for is un-deprecated!
  101. # https://github.com/thoughtbot/factory_girl/issues/274#issuecomment-3592054
  102. FactoryGirl.attributes_for(:simple_product)
  103. end
  104. let(:prototype) do
  105. size = build_option_type_with_values("size", %w(Small Medium Large))
  106. FactoryGirl.create(:prototype, name: "Size", option_types: [ size ])
  107. end
  108. let(:option_values_hash) do
  109. hash = {}
  110. prototype.option_types.each do |i|
  111. hash[i.id.to_s] = i.option_value_ids
  112. end
  113. hash
  114. end
  115. before(:each) do
  116. @option_type_prototype = prototype
  117. @property_prototype = create(:prototype, name: "Random")
  118. @shipping_category = create(:shipping_category)
  119. visit spree.admin_products_path
  120. click_link "admin_new_product"
  121. within('#new_product') do
  122. expect(page).to have_content("SKU")
  123. end
  124. end
  125. it "should allow an admin to create a new product and variants from a prototype" do
  126. fill_in "product_name", with: "Baseball Cap"
  127. fill_in "product_sku", with: "B100"
  128. fill_in "product_price", with: "100"
  129. fill_in "product_available_on", with: "2012/01/24"
  130. # Just so the datepicker gets out of poltergeists way.
  131. page.execute_script("$('#ui-datepicker-div').hide();")
  132. select "Size", from: "Prototype"
  133. wait_for_ajax
  134. check "Large"
  135. select @shipping_category.name, from: "product_shipping_category_id"
  136. click_button "Create"
  137. expect(page).to have_content("successfully created!")
  138. expect(Spree::Product.last.variants.length).to eq(1)
  139. end
  140. it "should not display variants when prototype does not contain option types" do
  141. select "Random", from: "Prototype"
  142. fill_in "product_name", with: "Baseball Cap"
  143. expect(page).not_to have_content("Variants")
  144. end
  145. it "should keep option values selected if validation fails" do
  146. fill_in "product_name", with: "Baseball Cap"
  147. fill_in "product_sku", with: "B100"
  148. fill_in "product_price", with: "100"
  149. select "Size", from: "Prototype"
  150. wait_for_ajax
  151. check "Large"
  152. click_button "Create"
  153. expect(page).to have_content("Shipping category can't be blank")
  154. expect(field_labeled("Size")).to be_checked
  155. expect(field_labeled("Large")).to be_checked
  156. expect(field_labeled("Small")).not_to be_checked
  157. end
  158. end
  159. context "creating a new product" do
  160. before(:each) do
  161. @shipping_category = create(:shipping_category)
  162. visit spree.admin_products_path
  163. click_link "admin_new_product"
  164. within('#new_product') do
  165. expect(page).to have_content("SKU")
  166. end
  167. end
  168. it "should allow an admin to create a new product" do
  169. fill_in "product_name", with: "Baseball Cap"
  170. fill_in "product_sku", with: "B100"
  171. fill_in "product_price", with: "100"
  172. fill_in "product_available_on", with: "2012/01/24"
  173. select @shipping_category.name, from: "product_shipping_category_id"
  174. click_button "Create"
  175. expect(page).to have_content("successfully created!")
  176. click_button "Update"
  177. expect(page).to have_content("successfully updated!")
  178. end
  179. it "should show validation errors" do
  180. fill_in "product_name", with: "Baseball Cap"
  181. fill_in "product_sku", with: "B100"
  182. fill_in "product_price", with: "100"
  183. click_button "Create"
  184. expect(page).to have_content("Shipping category can't be blank")
  185. end
  186. context "using a locale with a different decimal format " do
  187. before do
  188. # change English locales separator and delimiter to match 19,99 format
  189. I18n.backend.store_translations(:en,
  190. :number => {
  191. :currency => {
  192. :format => {
  193. :separator => ",",
  194. :delimiter => "."
  195. }
  196. }
  197. })
  198. end
  199. after do
  200. # revert changes to English locale
  201. I18n.backend.store_translations(:en,
  202. :number => {
  203. :currency => {
  204. :format => {
  205. :separator => ".",
  206. :delimiter => ","
  207. }
  208. }
  209. })
  210. end
  211. it "should show localized price value on validation errors", :js => true do
  212. fill_in "product_price", :with => "19,99"
  213. click_button "Create"
  214. expect(find('input#product_price').value).to eq('19,99')
  215. end
  216. end
  217. # Regression test for #2097
  218. it "can set the count on hand to a null value" do
  219. fill_in "product_name", with: "Baseball Cap"
  220. fill_in "product_price", with: "100"
  221. select @shipping_category.name, from: "product_shipping_category_id"
  222. click_button "Create"
  223. expect(page).to have_content("successfully created!")
  224. click_button "Update"
  225. expect(page).to have_content("successfully updated!")
  226. end
  227. end
  228. context "cloning a product", js: true do
  229. it "should allow an admin to clone a product" do
  230. create(:product)
  231. visit spree.admin_products_path
  232. within_row(1) do
  233. click_icon :clone
  234. end
  235. expect(page).to have_content("Product has been cloned")
  236. end
  237. context "cloning a deleted product" do
  238. it "should allow an admin to clone a deleted product" do
  239. create(:product, name: "apache baseball cap")
  240. visit spree.admin_products_path
  241. click_on 'Filter'
  242. check "Show Deleted"
  243. click_on 'Search'
  244. expect(page).to have_content("apache baseball cap")
  245. within_row(1) do
  246. click_icon :clone
  247. end
  248. expect(page).to have_content("Product has been cloned")
  249. end
  250. end
  251. end
  252. context 'updating a product' do
  253. let(:product) { create(:product) }
  254. let(:prototype) do
  255. size = build_option_type_with_values("size", %w(Small Medium Large))
  256. FactoryGirl.create(:prototype, name: "Size", option_types: [ size ])
  257. end
  258. before(:each) do
  259. @option_type_prototype = prototype
  260. @property_prototype = create(:prototype, name: "Random")
  261. end
  262. it 'should parse correctly available_on' do
  263. visit spree.admin_product_path(product)
  264. fill_in "product_available_on", with: "2012/12/25"
  265. click_button "Update"
  266. expect(page).to have_content("successfully updated!")
  267. expect(Spree::Product.last.available_on.to_s).to eq("2012-12-25 00:00:00 UTC")
  268. end
  269. it 'should add option_types when selecting a prototype', js: true do
  270. visit spree.admin_product_path(product)
  271. click_link 'Properties'
  272. click_link "Select From Prototype"
  273. within("#prototypes tr#row_#{prototype.id}") do
  274. click_link 'Select'
  275. wait_for_ajax
  276. end
  277. within(:css, "tr.product_property:first-child") do
  278. expect(first('input[type=text]').value).to eq('baseball_cap_color')
  279. end
  280. end
  281. end
  282. context 'deleting a product', :js => true do
  283. let!(:product) { create(:product) }
  284. it "is still viewable" do
  285. visit spree.admin_products_path
  286. accept_alert do
  287. click_icon :delete
  288. wait_for_ajax
  289. end
  290. click_on 'Filter'
  291. # This will show our deleted product
  292. check "Show Deleted"
  293. click_on 'Search'
  294. click_link product.name
  295. expect(find("#product_price").value.to_f).to eq(product.price.to_f)
  296. end
  297. end
  298. end
  299. context 'with only product permissions' do
  300. before do
  301. allow_any_instance_of(Spree::Admin::BaseController).to receive(:spree_current_user).and_return(nil)
  302. end
  303. custom_authorization! do |user|
  304. can [:admin, :update, :index, :read], Spree::Product
  305. end
  306. let!(:product) { create(:product) }
  307. it "should only display accessible links on index" do
  308. visit spree.admin_products_path
  309. expect(page).to have_link('Products')
  310. expect(page).not_to have_link('Option Types')
  311. expect(page).not_to have_link('Properties')
  312. expect(page).not_to have_link('Prototypes')
  313. expect(page).not_to have_link('New Product')
  314. expect(page).not_to have_css('.icon-clone')
  315. expect(page).to have_css('.icon-edit')
  316. expect(page).not_to have_css('.delete-resource')
  317. end
  318. it "should only display accessible links on edit" do
  319. visit spree.admin_product_path(product)
  320. # product tabs should be hidden
  321. expect(page).to have_link('Details')
  322. expect(page).not_to have_link('Images')
  323. expect(page).not_to have_link('Variants')
  324. expect(page).not_to have_link('Properties')
  325. expect(page).not_to have_link('Stock Management')
  326. # no create permission
  327. expect(page).not_to have_link('New Product')
  328. end
  329. end
  330. end