From 86be56a342aa1c818798d4ea47f43443d1bad20a Mon Sep 17 00:00:00 2001 From: Abdellatif Benzbiria Date: Wed, 4 Feb 2026 17:12:29 +0100 Subject: [PATCH 1/8] TA#82839 [IMP] web_attachment_size_limit TU --- .../tests/test_attachment_limit.py | 212 +++++++++--------- 1 file changed, 106 insertions(+), 106 deletions(-) diff --git a/web_attachment_size_limit/tests/test_attachment_limit.py b/web_attachment_size_limit/tests/test_attachment_limit.py index 3ad4c59..2218e25 100644 --- a/web_attachment_size_limit/tests/test_attachment_limit.py +++ b/web_attachment_size_limit/tests/test_attachment_limit.py @@ -1,106 +1,106 @@ -# © Numigi (tm) and all its contributors (https://numigi.com/r/home) -# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). - -# import io -# import json -# from odoo.tests.common import HttpCase, tagged -# -# -# @tagged('post_install', '-at_install') -# class TestAttachmentSizeLimit(HttpCase): -# -# def setUp(self): -# super(TestAttachmentSizeLimit, self).setUp() -# # Authenticate as admin to have upload rights and establish session -# self.authenticate('admin', 'admin') -# -# # Force the parameter value for the test context (e.g., 100 bytes) -# self.env['ir.config_parameter'].sudo().set_param( -# 'web.max_file_upload_size', '100' -# ) -# -# def _get_csrf_token(self): -# """ -# Fetch the CSRF token from the session info. -# This is required for controllers protected by -# @http.route(..., csrf=True) -# """ -# # We invoke get_session_info via JSON-RPC to retrieve the token -# # url_open does not support 'json' param in this env, so we serialize manually -# response = self.url_open( -# '/web/session/get_session_info', -# data=json.dumps({}), -# headers={'Content-Type': 'application/json'} -# ) -# return response.json().get('result', {}).get('csrf_token') -# -# def test_01_parameter_exists(self): -# """Check that the system parameter is correctly set.""" -# param = self.env['ir.config_parameter'].sudo().get_param( -# 'web.max_file_upload_size' -# ) -# self.assertEqual( -# param, '100', "The parameter value should be 100 for this test." -# ) -# -# def test_02_upload_too_large(self): -# """Try to upload a file of 200 bytes (limit is 100). Should fail.""" -# -# csrf_token = self._get_csrf_token() -# -# file_content = b'x' * 200 -# files = { -# 'ufile': ('big_file.txt', io.BytesIO(file_content), 'text/plain'), -# } -# # We must send the model/id and CSRF token as data fields -# data = { -# 'model': 'res.users', -# 'id': str(self.env.user.id), -# 'csrf_token': csrf_token -# } -# -# # Note: /web/binary/upload_attachment is the standard upload URL -# # We use relative URL '/web/...' so Odoo uses the correct testing port -# response = self.url_open( -# '/web/binary/upload_attachment', data=data, files=files -# ) -# -# response_content = response.content.decode('utf-8') -# -# self.assertIn( -# "File too large", -# response_content, -# "The upload should have been blocked with an error message. " -# "Response: %s" % response_content -# ) -# -# def test_03_upload_success(self): -# """Try to upload a file of 50 bytes (limit is 100). Should succeed.""" -# -# csrf_token = self._get_csrf_token() -# -# file_content = b'x' * 50 -# files = { -# 'ufile': ( -# 'small_file.txt', io.BytesIO(file_content), 'text/plain' -# ), -# } -# data = { -# 'model': 'res.users', -# 'id': str(self.env.user.id), -# 'csrf_token': csrf_token -# } -# -# response = self.url_open( -# '/web/binary/upload_attachment', data=data, files=files -# ) -# response_content = response.content.decode('utf-8') -# -# self.assertNotIn( -# "error", response_content, -# "Valid upload should not return an error." -# ) -# self.assertIn( -# "small_file.txt", response_content, -# "The filename should be in the response." -# ) +© Numigi (tm) and all its contributors (https://numigi.com/r/home) +License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +import io +import json +from odoo.tests.common import HttpCase, tagged + + +@tagged('post_install', '-at_install') +class TestAttachmentSizeLimit(HttpCase): + + def setUp(self): + super(TestAttachmentSizeLimit, self).setUp() + # Authenticate as admin to have upload rights and establish session + self.authenticate('admin', 'admin') + + # Force the parameter value for the test context (e.g., 100 bytes) + self.env['ir.config_parameter'].sudo().set_param( + 'web.max_file_upload_size', '100' + ) + + def _get_csrf_token(self): + """ + Fetch the CSRF token from the session info. + This is required for controllers protected by + @http.route(..., csrf=True) + """ + # We invoke get_session_info via JSON-RPC to retrieve the token + # url_open does not support 'json' param in this env, so we serialize manually + response = self.url_open( + '/web/session/get_session_info', + data=json.dumps({}), + headers={'Content-Type': 'application/json'} + ) + return response.json().get('result', {}).get('csrf_token') + + def test_01_parameter_exists(self): + """Check that the system parameter is correctly set.""" + param = self.env['ir.config_parameter'].sudo().get_param( + 'web.max_file_upload_size' + ) + self.assertEqual( + param, '100', "The parameter value should be 100 for this test." + ) + + def test_02_upload_too_large(self): + """Try to upload a file of 200 bytes (limit is 100). Should fail.""" + + csrf_token = self._get_csrf_token() + + file_content = b'x' * 200 + files = { + 'ufile': ('big_file.txt', io.BytesIO(file_content), 'text/plain'), + } + # We must send the model/id and CSRF token as data fields + data = { + 'model': 'res.users', + 'id': str(self.env.user.id), + 'csrf_token': csrf_token + } + + # Note: /web/binary/upload_attachment is the standard upload URL + # We use relative URL '/web/...' so Odoo uses the correct testing port + response = self.url_open( + '/web/binary/upload_attachment', data=data, files=files + ) + + response_content = response.content.decode('utf-8') + + self.assertIn( + "File too large", + response_content, + "The upload should have been blocked with an error message. " + "Response: %s" % response_content + ) + + def test_03_upload_success(self): + """Try to upload a file of 50 bytes (limit is 100). Should succeed.""" + + csrf_token = self._get_csrf_token() + + file_content = b'x' * 50 + files = { + 'ufile': ( + 'small_file.txt', io.BytesIO(file_content), 'text/plain' + ), + } + data = { + 'model': 'res.users', + 'id': str(self.env.user.id), + 'csrf_token': csrf_token + } + + response = self.url_open( + '/web/binary/upload_attachment', data=data, files=files + ) + response_content = response.content.decode('utf-8') + + self.assertNotIn( + "error", response_content, + "Valid upload should not return an error." + ) + self.assertIn( + "small_file.txt", response_content, + "The filename should be in the response." + ) From e8335a0e6e47b03bfad13c757efda19cd1564a2b Mon Sep 17 00:00:00 2001 From: Abdellatif Benzbiria Date: Wed, 4 Feb 2026 17:12:47 +0100 Subject: [PATCH 2/8] TA#82839 [IMP] web_attachment_size_limit TU --- web_attachment_size_limit/tests/test_attachment_limit.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/web_attachment_size_limit/tests/test_attachment_limit.py b/web_attachment_size_limit/tests/test_attachment_limit.py index 2218e25..6d7f3a5 100644 --- a/web_attachment_size_limit/tests/test_attachment_limit.py +++ b/web_attachment_size_limit/tests/test_attachment_limit.py @@ -1,5 +1,5 @@ -© Numigi (tm) and all its contributors (https://numigi.com/r/home) -License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). +# © Numigi (tm) and all its contributors (https://numigi.com/r/home) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). import io import json From bc5cd5490f04c1368ccb9bed463e7d3eae29a985 Mon Sep 17 00:00:00 2001 From: Abdellatif Benzbiria Date: Wed, 4 Feb 2026 17:31:35 +0100 Subject: [PATCH 3/8] TA#82839 [IMP] web_attachment_size_limit TU --- web_attachment_size_limit/tests/test_attachment_limit.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web_attachment_size_limit/tests/test_attachment_limit.py b/web_attachment_size_limit/tests/test_attachment_limit.py index 6d7f3a5..c3503ab 100644 --- a/web_attachment_size_limit/tests/test_attachment_limit.py +++ b/web_attachment_size_limit/tests/test_attachment_limit.py @@ -6,7 +6,7 @@ from odoo.tests.common import HttpCase, tagged -@tagged('post_install', '-at_install') +@tagged('post_install', '-at_install', 'http_test') class TestAttachmentSizeLimit(HttpCase): def setUp(self): From f0d3c55b3e1614258e1c6149e6f90a1de23661ba Mon Sep 17 00:00:00 2001 From: Abdellatif Benzbiria Date: Wed, 4 Feb 2026 17:43:27 +0100 Subject: [PATCH 4/8] TA#82839 [IMP] web_attachment_size_limit TU --- .../tests/test_attachment_limit.py | 72 +++++-------------- .../controllers/company_switcher.py | 13 ++-- 2 files changed, 25 insertions(+), 60 deletions(-) diff --git a/web_attachment_size_limit/tests/test_attachment_limit.py b/web_attachment_size_limit/tests/test_attachment_limit.py index c3503ab..5e7c532 100644 --- a/web_attachment_size_limit/tests/test_attachment_limit.py +++ b/web_attachment_size_limit/tests/test_attachment_limit.py @@ -2,7 +2,7 @@ # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). import io -import json +from odoo import http from odoo.tests.common import HttpCase, tagged @@ -11,79 +11,46 @@ class TestAttachmentSizeLimit(HttpCase): def setUp(self): super(TestAttachmentSizeLimit, self).setUp() - # Authenticate as admin to have upload rights and establish session self.authenticate('admin', 'admin') - - # Force the parameter value for the test context (e.g., 100 bytes) self.env['ir.config_parameter'].sudo().set_param( 'web.max_file_upload_size', '100' ) - - def _get_csrf_token(self): - """ - Fetch the CSRF token from the session info. - This is required for controllers protected by - @http.route(..., csrf=True) - """ - # We invoke get_session_info via JSON-RPC to retrieve the token - # url_open does not support 'json' param in this env, so we serialize manually - response = self.url_open( - '/web/session/get_session_info', - data=json.dumps({}), - headers={'Content-Type': 'application/json'} - ) - return response.json().get('result', {}).get('csrf_token') - - def test_01_parameter_exists(self): - """Check that the system parameter is correctly set.""" - param = self.env['ir.config_parameter'].sudo().get_param( - 'web.max_file_upload_size' - ) - self.assertEqual( - param, '100', "The parameter value should be 100 for this test." - ) + # On récupère l'URL de base pour url_open + self.base_url = self.env['ir.config_parameter'].sudo().get_param('web.base.url') def test_02_upload_too_large(self): """Try to upload a file of 200 bytes (limit is 100). Should fail.""" - csrf_token = self._get_csrf_token() + # Utilisation de la méthode native pour le jeton CSRF + csrf_token = http.WebRequest.csrf_token(self) file_content = b'x' * 200 files = { 'ufile': ('big_file.txt', io.BytesIO(file_content), 'text/plain'), } - # We must send the model/id and CSRF token as data fields data = { 'model': 'res.users', 'id': str(self.env.user.id), 'csrf_token': csrf_token } - # Note: /web/binary/upload_attachment is the standard upload URL - # We use relative URL '/web/...' so Odoo uses the correct testing port + # Utilisation de l'URL complète avec la base_url response = self.url_open( - '/web/binary/upload_attachment', data=data, files=files + url='%s/web/binary/upload_attachment' % self.base_url, + data=data, + files=files ) - response_content = response.content.decode('utf-8') - - self.assertIn( - "File too large", - response_content, - "The upload should have been blocked with an error message. " - "Response: %s" % response_content - ) + self.assertIn("File too large", response.text) def test_03_upload_success(self): """Try to upload a file of 50 bytes (limit is 100). Should succeed.""" - csrf_token = self._get_csrf_token() + csrf_token = http.WebRequest.csrf_token(self) file_content = b'x' * 50 files = { - 'ufile': ( - 'small_file.txt', io.BytesIO(file_content), 'text/plain' - ), + 'ufile': ('small_file.txt', io.BytesIO(file_content), 'text/plain'), } data = { 'model': 'res.users', @@ -92,15 +59,10 @@ def test_03_upload_success(self): } response = self.url_open( - '/web/binary/upload_attachment', data=data, files=files + url='%s/web/binary/upload_attachment' % self.base_url, + data=data, + files=files ) - response_content = response.content.decode('utf-8') - self.assertNotIn( - "error", response_content, - "Valid upload should not return an error." - ) - self.assertIn( - "small_file.txt", response_content, - "The filename should be in the response." - ) + self.assertNotIn("error", response.text) + self.assertIn("small_file.txt", response.text) diff --git a/web_visual_company_switcher/controllers/company_switcher.py b/web_visual_company_switcher/controllers/company_switcher.py index 1aca275..ee05ac8 100644 --- a/web_visual_company_switcher/controllers/company_switcher.py +++ b/web_visual_company_switcher/controllers/company_switcher.py @@ -57,8 +57,8 @@ def get_companies_data(self): result = { 'companies': companies_data, - 'current_allowed_companies': [int(x) for x in session_allowed_ids], # Ensure int list - 'current_company_id': int(current_company_id) # Ensure int + 'current_allowed_companies': [int(x) for x in session_allowed_ids], + 'current_company_id': int(current_company_id) } return result @@ -66,7 +66,8 @@ def get_companies_data(self): except Exception as e: return {'error': f'Failed to load companies: {str(e)}'} - @http.route('/web/visual_company_switcher/switch_company', type='json', auth='user', csrf=True) + @http.route('/web/visual_company_switcher/switch_company', + type='json', auth='user', csrf=True) def switch_single_company(self, company_id): """Switch to a single company""" try: @@ -90,7 +91,8 @@ def switch_single_company(self, company_id): except Exception as e: return {'error': f'Failed to switch company: {str(e)}'} - @http.route('/web/visual_company_switcher/switch_companies', type='json', auth='user', csrf=True) + @http.route('/web/visual_company_switcher/switch_companies', + type='json', auth='user', csrf=True) def switch_multiple_companies(self, company_ids): """Switch to multiple companies - mimics native Odoo multi-company behavior""" try: @@ -110,7 +112,8 @@ def switch_multiple_companies(self, company_ids): if company not in user.company_ids: return {'error': f'Access denied to company {company.name}'} - # This is the key: set allowed_company_ids in session to enable multi-company context + # This is the key: set allowed_company_ids in session + # to enable multi-company context # This mimics exactly what Odoo's native company switcher does request.session['allowed_company_ids'] = company_ids From 81f2c5c63c1ce0211cd26856d625cf98655a3520 Mon Sep 17 00:00:00 2001 From: Abdellatif Benzbiria Date: Wed, 4 Feb 2026 17:58:50 +0100 Subject: [PATCH 5/8] TA#82839 [IMP] web_attachment_size_limit TU --- web_attachment_size_limit/__manifest__.py | 2 +- .../tests/test_attachment_limit.py | 93 +++++++++++-------- 2 files changed, 54 insertions(+), 41 deletions(-) diff --git a/web_attachment_size_limit/__manifest__.py b/web_attachment_size_limit/__manifest__.py index e924e9b..365a972 100644 --- a/web_attachment_size_limit/__manifest__.py +++ b/web_attachment_size_limit/__manifest__.py @@ -4,7 +4,7 @@ { "name": "Web Attachment Size Limit", "summary": "Enforce a global maximum size for file uploads", - "version": "14.0.1.0.0", + "version": "14.0.1.0.1", "category": "Web", "website": "https://numigi.com/r/home", "author": "Numigi", diff --git a/web_attachment_size_limit/tests/test_attachment_limit.py b/web_attachment_size_limit/tests/test_attachment_limit.py index 5e7c532..f58cc13 100644 --- a/web_attachment_size_limit/tests/test_attachment_limit.py +++ b/web_attachment_size_limit/tests/test_attachment_limit.py @@ -2,67 +2,80 @@ # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). import io -from odoo import http +import json + from odoo.tests.common import HttpCase, tagged -@tagged('post_install', '-at_install', 'http_test') +@tagged('-at_install', 'post_install') class TestAttachmentSizeLimit(HttpCase): + """Tests HTTP for web_attachment_size_limit""" - def setUp(self): - super(TestAttachmentSizeLimit, self).setUp() - self.authenticate('admin', 'admin') - self.env['ir.config_parameter'].sudo().set_param( - 'web.max_file_upload_size', '100' - ) - # On récupère l'URL de base pour url_open - self.base_url = self.env['ir.config_parameter'].sudo().get_param('web.base.url') + @classmethod + def setUpClass(cls): + super().setUpClass() - def test_02_upload_too_large(self): - """Try to upload a file of 200 bytes (limit is 100). Should fail.""" + # Définir une limite faible pour les tests (100 bytes) + cls.env['ir.config_parameter'].sudo().set_param( + 'web_attachment_size_limit.max_upload_size', '100' + ) - # Utilisation de la méthode native pour le jeton CSRF - csrf_token = http.WebRequest.csrf_token(self) + # Utilisateur courant + cls.user = cls.env.user - file_content = b'x' * 200 + def _upload_file(self, content: bytes, filename='test.txt'): + """Helper pour uploader un fichier via le contrôleur web""" files = { - 'ufile': ('big_file.txt', io.BytesIO(file_content), 'text/plain'), + 'ufile': (filename, io.BytesIO(content), 'text/plain'), } data = { 'model': 'res.users', - 'id': str(self.env.user.id), - 'csrf_token': csrf_token + 'id': str(self.user.id), } - # Utilisation de l'URL complète avec la base_url - response = self.url_open( - url='%s/web/binary/upload_attachment' % self.base_url, + return self.url_open( + '/web/binary/upload_attachment', data=data, - files=files + files=files, ) - self.assertIn("File too large", response.text) + def test_02_upload_too_large(self): + """Upload > limite (200 bytes). Doit échouer.""" + file_content = b'x' * 200 - def test_03_upload_success(self): - """Try to upload a file of 50 bytes (limit is 100). Should succeed.""" + response = self._upload_file( + file_content, + filename='too_big.txt' + ) + + self.assertEqual( + response.status_code, 413, + 'Upload should be rejected with HTTP 413' + ) - csrf_token = http.WebRequest.csrf_token(self) + payload = json.loads(response.text) + self.assertIn('error', payload) + self.assertIn('exceeds', payload['error'].lower()) + def test_03_upload_success(self): + """Upload < limite (50 bytes). Doit réussir.""" file_content = b'x' * 50 - files = { - 'ufile': ('small_file.txt', io.BytesIO(file_content), 'text/plain'), - } - data = { - 'model': 'res.users', - 'id': str(self.env.user.id), - 'csrf_token': csrf_token - } - response = self.url_open( - url='%s/web/binary/upload_attachment' % self.base_url, - data=data, - files=files + response = self._upload_file( + file_content, + filename='small_file.txt' + ) + + self.assertEqual( + response.status_code, 200, + 'Upload should succeed' ) - self.assertNotIn("error", response.text) - self.assertIn("small_file.txt", response.text) + payload = json.loads(response.text) + self.assertIn('id', payload) + + attachment = self.env['ir.attachment'].browse(payload['id']) + self.assertTrue(attachment.exists()) + self.assertEqual(attachment.res_model, 'res.users') + self.assertEqual(attachment.res_id, self.user.id) + From 9e12c19648e664467826e005f8842acafdfffea4 Mon Sep 17 00:00:00 2001 From: Abdellatif Benzbiria Date: Wed, 4 Feb 2026 18:03:46 +0100 Subject: [PATCH 6/8] TA#82839 [IMP] web_attachment_size_limit TU --- .../tests/test_attachment_limit.py | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/web_attachment_size_limit/tests/test_attachment_limit.py b/web_attachment_size_limit/tests/test_attachment_limit.py index f58cc13..a860f69 100644 --- a/web_attachment_size_limit/tests/test_attachment_limit.py +++ b/web_attachment_size_limit/tests/test_attachment_limit.py @@ -11,17 +11,15 @@ class TestAttachmentSizeLimit(HttpCase): """Tests HTTP for web_attachment_size_limit""" - @classmethod - def setUpClass(cls): - super().setUpClass() + def setUp(self): + super().setUp() # Définir une limite faible pour les tests (100 bytes) - cls.env['ir.config_parameter'].sudo().set_param( + self.env['ir.config_parameter'].sudo().set_param( 'web_attachment_size_limit.max_upload_size', '100' ) - # Utilisateur courant - cls.user = cls.env.user + self.user = self.env.user def _upload_file(self, content: bytes, filename='test.txt'): """Helper pour uploader un fichier via le contrôleur web""" @@ -55,7 +53,7 @@ def test_02_upload_too_large(self): payload = json.loads(response.text) self.assertIn('error', payload) - self.assertIn('exceeds', payload['error'].lower()) + self.assertIn('exceed', payload['error'].lower()) def test_03_upload_success(self): """Upload < limite (50 bytes). Doit réussir.""" @@ -78,4 +76,3 @@ def test_03_upload_success(self): self.assertTrue(attachment.exists()) self.assertEqual(attachment.res_model, 'res.users') self.assertEqual(attachment.res_id, self.user.id) - From 826f9d36c98850bcc205d99714c2fcd84f230420 Mon Sep 17 00:00:00 2001 From: Abdellatif Benzbiria Date: Wed, 4 Feb 2026 18:12:01 +0100 Subject: [PATCH 7/8] TA#82839 [IMP] web_attachment_size_limit TU --- .../tests/test_attachment_limit.py | 22 +++++-------------- 1 file changed, 6 insertions(+), 16 deletions(-) diff --git a/web_attachment_size_limit/tests/test_attachment_limit.py b/web_attachment_size_limit/tests/test_attachment_limit.py index a860f69..8a1146f 100644 --- a/web_attachment_size_limit/tests/test_attachment_limit.py +++ b/web_attachment_size_limit/tests/test_attachment_limit.py @@ -9,12 +9,14 @@ @tagged('-at_install', 'post_install') class TestAttachmentSizeLimit(HttpCase): - """Tests HTTP for web_attachment_size_limit""" def setUp(self): super().setUp() - # Définir une limite faible pour les tests (100 bytes) + # 🔑 OBLIGATOIRE : démarre le serveur HTTP de test + self.authenticate('admin', 'admin') + + # Limite faible pour les tests self.env['ir.config_parameter'].sudo().set_param( 'web_attachment_size_limit.max_upload_size', '100' ) @@ -22,7 +24,6 @@ def setUp(self): self.user = self.env.user def _upload_file(self, content: bytes, filename='test.txt'): - """Helper pour uploader un fichier via le contrôleur web""" files = { 'ufile': (filename, io.BytesIO(content), 'text/plain'), } @@ -38,7 +39,6 @@ def _upload_file(self, content: bytes, filename='test.txt'): ) def test_02_upload_too_large(self): - """Upload > limite (200 bytes). Doit échouer.""" file_content = b'x' * 200 response = self._upload_file( @@ -46,17 +46,12 @@ def test_02_upload_too_large(self): filename='too_big.txt' ) - self.assertEqual( - response.status_code, 413, - 'Upload should be rejected with HTTP 413' - ) + self.assertEqual(response.status_code, 413) payload = json.loads(response.text) self.assertIn('error', payload) - self.assertIn('exceed', payload['error'].lower()) def test_03_upload_success(self): - """Upload < limite (50 bytes). Doit réussir.""" file_content = b'x' * 50 response = self._upload_file( @@ -64,15 +59,10 @@ def test_03_upload_success(self): filename='small_file.txt' ) - self.assertEqual( - response.status_code, 200, - 'Upload should succeed' - ) + self.assertEqual(response.status_code, 200) payload = json.loads(response.text) self.assertIn('id', payload) attachment = self.env['ir.attachment'].browse(payload['id']) self.assertTrue(attachment.exists()) - self.assertEqual(attachment.res_model, 'res.users') - self.assertEqual(attachment.res_id, self.user.id) From 320807bdb07eaee9325a99ed381ba9372b0507c9 Mon Sep 17 00:00:00 2001 From: Abdellatif Benzbiria Date: Wed, 4 Feb 2026 18:26:56 +0100 Subject: [PATCH 8/8] TA#82839 [IMP] web_attachment_size_limit TU --- .../tests/test_attachment_limit.py | 32 +++++++++++++------ 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/web_attachment_size_limit/tests/test_attachment_limit.py b/web_attachment_size_limit/tests/test_attachment_limit.py index 8a1146f..7f22311 100644 --- a/web_attachment_size_limit/tests/test_attachment_limit.py +++ b/web_attachment_size_limit/tests/test_attachment_limit.py @@ -9,21 +9,22 @@ @tagged('-at_install', 'post_install') class TestAttachmentSizeLimit(HttpCase): + """Tests HTTP for web_attachment_size_limit""" - def setUp(self): - super().setUp() + @classmethod + def setUpClass(cls): + super().setUpClass() - # 🔑 OBLIGATOIRE : démarre le serveur HTTP de test - self.authenticate('admin', 'admin') - - # Limite faible pour les tests - self.env['ir.config_parameter'].sudo().set_param( + # Définir une limite faible pour les tests (100 bytes) + cls.env['ir.config_parameter'].sudo().set_param( 'web_attachment_size_limit.max_upload_size', '100' ) - self.user = self.env.user + # Utilisateur courant + cls.user = cls.env.user def _upload_file(self, content: bytes, filename='test.txt'): + """Helper pour uploader un fichier via le contrôleur web""" files = { 'ufile': (filename, io.BytesIO(content), 'text/plain'), } @@ -39,6 +40,7 @@ def _upload_file(self, content: bytes, filename='test.txt'): ) def test_02_upload_too_large(self): + """Upload > limite (200 bytes). Doit échouer.""" file_content = b'x' * 200 response = self._upload_file( @@ -46,12 +48,17 @@ def test_02_upload_too_large(self): filename='too_big.txt' ) - self.assertEqual(response.status_code, 413) + self.assertEqual( + response.status_code, 413, + 'Upload should be rejected with HTTP 413' + ) payload = json.loads(response.text) self.assertIn('error', payload) + self.assertIn('exceeds', payload['error'].lower()) def test_03_upload_success(self): + """Upload < limite (50 bytes). Doit réussir.""" file_content = b'x' * 50 response = self._upload_file( @@ -59,10 +66,15 @@ def test_03_upload_success(self): filename='small_file.txt' ) - self.assertEqual(response.status_code, 200) + self.assertEqual( + response.status_code, 200, + 'Upload should succeed' + ) payload = json.loads(response.text) self.assertIn('id', payload) attachment = self.env['ir.attachment'].browse(payload['id']) self.assertTrue(attachment.exists()) + self.assertEqual(attachment.res_model, 'res.users') + self.assertEqual(attachment.res_id, self.user.id)