267 lines
12 KiB
Python
267 lines
12 KiB
Python
# -*- coding: utf-8 -*-
|
|
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
|
|
|
import logging
|
|
|
|
from odoo import Command
|
|
from odoo.addons.website_sale.controllers.main import WebsiteSale
|
|
from odoo.addons.website.tools import MockRequest
|
|
from odoo.exceptions import ValidationError
|
|
from odoo.tests import HttpCase, tagged
|
|
|
|
_logger = logging.getLogger(__name__)
|
|
|
|
ATTACHMENT_DATA = [
|
|
b"iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAAEElEQVR4nGKqf3geEAAA//8EGgIyYKYzzgAAAABJRU5ErkJggg==",
|
|
b"iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAAEElEQVR4nGKqvvQEEAAA//8EBQI0GMlQsAAAAABJRU5ErkJggg==",
|
|
b"iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAAEElEQVR4nGKKLakBBAAA//8ChwFQsvFlAwAAAABJRU5ErkJggg==",
|
|
b"iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAAEElEQVR4nGJqkdoACAAA//8CfAFRzSyOUAAAAABJRU5ErkJggg==",
|
|
b"iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAAEElEQVR4nGLSfxgICAAA//8CrAFkoLBhpQAAAABJRU5ErkJggg==",
|
|
]
|
|
ATTACHMENT_COUNT = 5
|
|
|
|
|
|
@tagged('post_install', '-at_install')
|
|
class TestProductPictureController(HttpCase):
|
|
@classmethod
|
|
def setUpClass(cls):
|
|
super().setUpClass()
|
|
cls.website = cls.env['website'].browse(1)
|
|
cls.WebsiteSaleController = WebsiteSale()
|
|
cls.product = cls.env['product.product'].create({
|
|
'name': 'Storage Test Box',
|
|
'standard_price': 70.0,
|
|
'list_price': 79.0,
|
|
'website_published': True,
|
|
})
|
|
|
|
cls.attachments = cls.env['ir.attachment'].create([
|
|
{
|
|
'datas': ATTACHMENT_DATA[i],
|
|
'name': f'image0{i}.gif',
|
|
'public': True
|
|
}
|
|
for i in range(ATTACHMENT_COUNT)])
|
|
|
|
def _create_product_images(self):
|
|
with MockRequest(self.product.env, website=self.website):
|
|
self.WebsiteSaleController.add_product_images(
|
|
[{'id': attachment.id} for attachment in self.attachments],
|
|
self.product.id,
|
|
self.product.product_tmpl_id.id,
|
|
)
|
|
|
|
def _get_product_image_data(self):
|
|
return [
|
|
hasattr(image, 'video_url') and image.video_url or image.image_1920
|
|
for image in self.product._get_images()
|
|
]
|
|
|
|
def test_bulk_image_upload(self):
|
|
# Turns attachments to product_images
|
|
self._create_product_images()
|
|
|
|
# Check if the media now exists on the product :
|
|
for i, image in enumerate(self.product.product_template_image_ids):
|
|
# Check if all names are now in the product
|
|
self.assertIn(image.name, self.attachments.mapped('name'))
|
|
# Check if image datas are the same
|
|
self.assertEqual(image.image_1920, ATTACHMENT_DATA[i])
|
|
# Check if exactly ATTACHMENT_COUNT images were saved (no dupes/misses?)
|
|
self.assertEqual(ATTACHMENT_COUNT, len(self.product.product_template_image_ids))
|
|
|
|
def test_image_clear(self):
|
|
# First create some images
|
|
self._create_product_images()
|
|
self.assertEqual(ATTACHMENT_COUNT, len(self.product.product_template_image_ids))
|
|
|
|
# Remove all images
|
|
# (Exception raised if error)
|
|
with MockRequest(self.product.env, website=self.website):
|
|
self.WebsiteSaleController.clear_product_images(
|
|
self.product.id,
|
|
self.product.product_tmpl_id.id,
|
|
)
|
|
# According to the product, there are no variants images.
|
|
self.assertEqual(0, len(self.product.product_template_image_ids))
|
|
|
|
def test_extra_images_with_new_variant(self):
|
|
# Test that adding images for a variant that is not yet created works
|
|
product_attribute = self.env['product.attribute'].create({
|
|
"name": "Test attribute",
|
|
"create_variant": "dynamic",
|
|
})
|
|
product_attribute_values = self.env['product.attribute.value'].create([
|
|
{
|
|
"name" : "Test Dynamic 1",
|
|
"attribute_id": product_attribute.id,
|
|
"sequence": 1,
|
|
},
|
|
{
|
|
"name" : "Test Dynamic 2",
|
|
"attribute_id": product_attribute.id,
|
|
"sequence": 2,
|
|
}
|
|
])
|
|
product_template = self.env['product.template'].create({
|
|
"name": "test product",
|
|
"website_published": True,
|
|
})
|
|
product_template_attribute_line = self.env['product.template.attribute.line'].create({
|
|
"attribute_id": product_attribute.id,
|
|
"product_tmpl_id": product_template.id,
|
|
"value_ids": product_attribute_values,
|
|
})
|
|
self.assertEqual(0, len(product_template.product_variant_ids))
|
|
with MockRequest(product_template.env, website=self.website):
|
|
self.WebsiteSaleController.add_product_images(
|
|
[{'id': self.attachments[0].id}],
|
|
False,
|
|
product_template.id,
|
|
[product_template_attribute_line.product_template_value_ids[0].id],
|
|
)
|
|
self.assertEqual(1, len(product_template.product_variant_ids))
|
|
|
|
def test_resequence_image_first(self):
|
|
self._create_product_images()
|
|
with MockRequest(self.product.env, website=self.website):
|
|
images = self.product._get_images()
|
|
i1, i2, i3, i4, i5, i6 = self._get_product_image_data()
|
|
self.WebsiteSaleController.resequence_product_image(
|
|
images[2]._name, images[2].id, 'first',
|
|
)
|
|
# Trigger the reordering of product.image records based on their sequence.
|
|
self.env['product.image'].invalidate_model()
|
|
self.assertListEqual(self._get_product_image_data(), [i3, i1, i2, i4, i5, i6])
|
|
self.assertEqual(self.product.image_1920, i3)
|
|
|
|
def test_resequence_image_left(self):
|
|
self._create_product_images()
|
|
with MockRequest(self.product.env, website=self.website):
|
|
images = self.product._get_images()
|
|
i1, i2, i3, i4, i5, i6 = self._get_product_image_data()
|
|
self.WebsiteSaleController.resequence_product_image(
|
|
images[2]._name, images[2].id, 'left',
|
|
)
|
|
self.env['product.image'].invalidate_model()
|
|
self.assertListEqual(self._get_product_image_data(), [i1, i3, i2, i4, i5, i6])
|
|
|
|
def test_resequence_image_right(self):
|
|
self._create_product_images()
|
|
with MockRequest(self.product.env, website=self.website):
|
|
images = self.product._get_images()
|
|
i1, i2, i3, i4, i5, i6 = self._get_product_image_data()
|
|
self.WebsiteSaleController.resequence_product_image(
|
|
images[2]._name, images[2].id, 'right',
|
|
)
|
|
self.env['product.image'].invalidate_model()
|
|
self.assertListEqual(self._get_product_image_data(), [i1, i2, i4, i3, i5, i6])
|
|
|
|
def test_resequence_image_last(self):
|
|
self._create_product_images()
|
|
with MockRequest(self.product.env, website=self.website):
|
|
images = self.product._get_images()
|
|
i1, i2, i3, i4, i5, i6 = self._get_product_image_data()
|
|
self.WebsiteSaleController.resequence_product_image(
|
|
images[2]._name, images[2].id, 'last',
|
|
)
|
|
self.env['product.image'].invalidate_model()
|
|
self.assertListEqual(self._get_product_image_data(), [i1, i2, i4, i5, i6, i3])
|
|
|
|
def test_resequence_image_first_to_last(self):
|
|
""" Moving an image from first to last position is an edge case in the code. """
|
|
self._create_product_images()
|
|
with MockRequest(self.product.env, website=self.website):
|
|
images = self.product._get_images()
|
|
i1, i2, i3, i4, i5, i6 = self._get_product_image_data()
|
|
self.WebsiteSaleController.resequence_product_image(
|
|
images[0]._name, images[0].id, 'last',
|
|
)
|
|
self.env['product.image'].invalidate_model()
|
|
self.assertListEqual(self._get_product_image_data(), [i2, i3, i4, i5, i6, i1])
|
|
self.assertEqual(self.product.image_1920, i2)
|
|
|
|
def test_resequence_video_left(self):
|
|
self._create_product_images()
|
|
with MockRequest(self.product.env, website=self.website):
|
|
images = self.product._get_images()
|
|
images[2].video_url = "https://www.youtube.com/watch?v=dQw4w9WgXcQ"
|
|
i1, i2, i3, i4, i5, i6 = self._get_product_image_data()
|
|
self.WebsiteSaleController.resequence_product_image(
|
|
images[2]._name, images[2].id, 'left',
|
|
)
|
|
self.env['product.image'].invalidate_model()
|
|
self.assertListEqual(self._get_product_image_data(), [i1, i3, i2, i4, i5, i6])
|
|
|
|
def test_resequence_video_first(self):
|
|
""" A video can't be resequenced to first position. """
|
|
self._create_product_images()
|
|
with MockRequest(self.product.env, website=self.website):
|
|
images = self.product._get_images()
|
|
images[2].video_url = "https://www.youtube.com/watch?v=dQw4w9WgXcQ"
|
|
i1, i2, i3, i4, i5, i6 = self._get_product_image_data()
|
|
with self.assertRaises(ValidationError):
|
|
self.WebsiteSaleController.resequence_product_image(
|
|
images[2]._name, images[2].id, 'first',
|
|
)
|
|
self.env['product.image'].invalidate_model()
|
|
self.assertListEqual(self._get_product_image_data(), [i1, i2, i3, i4, i5, i6])
|
|
|
|
def test_resequence_video_replace_first(self):
|
|
""" A video can't replace an image that was resequenced away from first position. """
|
|
self._create_product_images()
|
|
with MockRequest(self.product.env, website=self.website):
|
|
images = self.product._get_images()
|
|
images[1].video_url = "https://www.youtube.com/watch?v=dQw4w9WgXcQ"
|
|
i1, i2, i3, i4, i5, i6 = self._get_product_image_data()
|
|
with self.assertRaises(ValidationError):
|
|
self.WebsiteSaleController.resequence_product_image(
|
|
images[0]._name, images[0].id, 'right',
|
|
)
|
|
self.env['product.image'].invalidate_model()
|
|
self.assertListEqual(self._get_product_image_data(), [i1, i2, i3, i4, i5, i6])
|
|
|
|
|
|
@tagged('post_install', '-at_install')
|
|
class TestWebsiteSaleEditor(HttpCase):
|
|
@classmethod
|
|
def setUpClass(cls):
|
|
super().setUpClass()
|
|
|
|
cls.env['res.users'].create({
|
|
'name': 'Restricted Editor',
|
|
'login': 'restricted',
|
|
'password': 'restricted',
|
|
'groups_id': [Command.set([
|
|
cls.env.ref('base.group_user').id,
|
|
cls.env.ref('sales_team.group_sale_manager').id,
|
|
cls.env.ref('website.group_website_restricted_editor').id
|
|
])]
|
|
})
|
|
|
|
def test_category_page_and_products_snippet(self):
|
|
category = self.env['product.public.category'].create({
|
|
'name': 'Test Category',
|
|
})
|
|
self.env['product.template'].create({
|
|
'name': 'Test Product',
|
|
'website_published': True,
|
|
'public_categ_ids': [
|
|
Command.link(category.id)
|
|
]
|
|
})
|
|
self.env['product.template'].create({
|
|
'name': 'Test Product Outside Category',
|
|
'website_published': True,
|
|
})
|
|
self.start_tour(self.env['website'].get_client_action_url('/shop'), 'category_page_and_products_snippet_edition', login='restricted')
|
|
self.start_tour('/shop', 'category_page_and_products_snippet_use', login=None)
|
|
|
|
def test_website_sale_restricted_editor_ui(self):
|
|
self.env['product.template'].create({
|
|
'name': 'Test Product',
|
|
'website_sequence': 0,
|
|
'website_published': True,
|
|
})
|
|
self.start_tour(self.env['website'].get_client_action_url('/shop'), 'website_sale_restricted_editor_ui', login='restricted')
|