[REF] all: pass pre-commit on the whole repo
Needed for the lint job of the CI to go green. Mostly automatic hook fixes (black, isort, prettier, pyupgrade, autoflake, whitespace). By hand: - flake8: two unused imports, an ambiguous variable name `l`. - pylint-odoo mandatory: manifest keys equal to their default value (installable, application, data, external_dependencies). - end-of-file-fixer skips *.patch too, like trailing-whitespace: the upstream patches stay as git format-patch wrote them. No behaviour change. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
d9d9e8be2d
commit
fbd43bb459
45 changed files with 330 additions and 295 deletions
|
|
@ -120,4 +120,4 @@ Para reforzar la seguridad se podría sustituir el query param estático por un
|
|||
token HMAC firmado (vinculado a la sesión y al producto objetivo), de modo
|
||||
que solo el flujo de `cart_update` pueda generar un redirect válido y el
|
||||
acceso directo a `/web/signup` fuera de ese flujo quede restringido. Ver
|
||||
`requirements.md` §7 R-01.
|
||||
`requirements.md` §7 R-01.
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
from . import controllers
|
||||
from . import models
|
||||
from . import models
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
"version": "18.0.1.0.1",
|
||||
"category": "Website/Sale",
|
||||
"summary": "Force a clean /web/signup step before adding membership "
|
||||
"products to cart on a b2b website (EMES-style flow).",
|
||||
"products to cart on a b2b website (EMES-style flow).",
|
||||
"author": "Criptomart",
|
||||
"website": "https://git.criptomart.net/criptomart/addons-cm",
|
||||
"license": "AGPL-3",
|
||||
|
|
@ -25,7 +25,4 @@
|
|||
"website_membership_signup_required/static/src/js/website_membership_signup_required.js",
|
||||
],
|
||||
},
|
||||
"external_dependencies": {},
|
||||
"installable": True,
|
||||
"application": False,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
from . import main
|
||||
from . import website_sale
|
||||
from . import website_sale
|
||||
|
|
|
|||
|
|
@ -1,11 +1,13 @@
|
|||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
from odoo import _, http
|
||||
from odoo.addons.auth_signup.controllers.main import AuthSignupHome
|
||||
from odoo.addons.web.controllers.home import SIGN_UP_REQUEST_PARAMS
|
||||
from odoo import _
|
||||
from odoo import http
|
||||
from odoo.exceptions import UserError
|
||||
from odoo.http import request
|
||||
|
||||
from odoo.addons.auth_signup.controllers.main import AuthSignupHome
|
||||
from odoo.addons.web.controllers.home import SIGN_UP_REQUEST_PARAMS
|
||||
|
||||
# partner_firstname exposes `firstname` / `lastname` on res.users and
|
||||
# res.partner; we need them as accepted qcontext params so the signup form
|
||||
# roundtrips them transparently through `get_auth_signup_qcontext`.
|
||||
|
|
@ -18,7 +20,10 @@ SIGN_UP_REQUEST_PARAMS.add("lastname")
|
|||
SIGN_UP_REQUEST_PARAMS.add("accepted_terms")
|
||||
|
||||
# Session keys used by the membership signup flow.
|
||||
MEMBERSHIP_SIGNUP_SESSION_KEYS = ("membership_signup_active", "membership_signup_product_id")
|
||||
MEMBERSHIP_SIGNUP_SESSION_KEYS = (
|
||||
"membership_signup_active",
|
||||
"membership_signup_product_id",
|
||||
)
|
||||
|
||||
|
||||
class AuthSignupHomeMembership(AuthSignupHome):
|
||||
|
|
@ -71,9 +76,7 @@ class AuthSignupHomeMembership(AuthSignupHome):
|
|||
values["firstname"] = firstname
|
||||
values["lastname"] = lastname
|
||||
partner_model = request.env["res.partner"]
|
||||
values["name"] = partner_model._get_computed_name(
|
||||
lastname, firstname
|
||||
)
|
||||
values["name"] = partner_model._get_computed_name(lastname, firstname)
|
||||
return values
|
||||
|
||||
@http.route()
|
||||
|
|
@ -134,4 +137,4 @@ class AuthSignupHomeMembership(AuthSignupHome):
|
|||
# Drop the markers: the membership flow is now complete.
|
||||
for key in MEMBERSHIP_SIGNUP_SESSION_KEYS:
|
||||
request.session.pop(key, None)
|
||||
return request.redirect("/shop/cart")
|
||||
return request.redirect("/shop/cart")
|
||||
|
|
|
|||
|
|
@ -3,9 +3,10 @@
|
|||
from urllib.parse import urlencode
|
||||
|
||||
from odoo import http
|
||||
from odoo.addons.website_sale.controllers.main import WebsiteSale
|
||||
from odoo.http import request
|
||||
|
||||
from odoo.addons.website_sale.controllers.main import WebsiteSale
|
||||
|
||||
SIGNUP_FLAG = "membership_signup=1"
|
||||
|
||||
|
||||
|
|
@ -36,24 +37,37 @@ class WebsiteSaleMembershipSignup(WebsiteSale):
|
|||
|
||||
@http.route()
|
||||
def cart_update(
|
||||
self, product_id, add_qty=1, set_qty=0,
|
||||
self,
|
||||
product_id,
|
||||
add_qty=1,
|
||||
set_qty=0,
|
||||
product_custom_attribute_values=None,
|
||||
no_variant_attribute_value_ids=None, **kwargs
|
||||
no_variant_attribute_value_ids=None,
|
||||
**kwargs,
|
||||
):
|
||||
if self._membership_signup_is_required(product_id):
|
||||
self._membership_signup_mark_session(product_id)
|
||||
return request.redirect(self._membership_signup_redirect_url(product_id))
|
||||
return super().cart_update(
|
||||
product_id=product_id, add_qty=add_qty, set_qty=set_qty,
|
||||
product_id=product_id,
|
||||
add_qty=add_qty,
|
||||
set_qty=set_qty,
|
||||
product_custom_attribute_values=product_custom_attribute_values,
|
||||
no_variant_attribute_value_ids=no_variant_attribute_value_ids,
|
||||
**kwargs
|
||||
**kwargs,
|
||||
)
|
||||
|
||||
@http.route()
|
||||
def cart_update_json(
|
||||
self, product_id, line_id=None, add_qty=None, set_qty=None, display=True,
|
||||
product_custom_attribute_values=None, no_variant_attribute_value_ids=None, **kwargs
|
||||
self,
|
||||
product_id,
|
||||
line_id=None,
|
||||
add_qty=None,
|
||||
set_qty=None,
|
||||
display=True,
|
||||
product_custom_attribute_values=None,
|
||||
no_variant_attribute_value_ids=None,
|
||||
**kwargs,
|
||||
):
|
||||
if self._membership_signup_is_required(product_id):
|
||||
self._membership_signup_mark_session(product_id)
|
||||
|
|
@ -90,11 +104,14 @@ class WebsiteSaleMembershipSignup(WebsiteSale):
|
|||
"notification_info": {"lines": [], "warning": ""},
|
||||
}
|
||||
return super().cart_update_json(
|
||||
product_id=product_id, line_id=line_id, add_qty=add_qty,
|
||||
set_qty=set_qty, display=display,
|
||||
product_id=product_id,
|
||||
line_id=line_id,
|
||||
add_qty=add_qty,
|
||||
set_qty=set_qty,
|
||||
display=display,
|
||||
product_custom_attribute_values=product_custom_attribute_values,
|
||||
no_variant_attribute_value_ids=no_variant_attribute_value_ids,
|
||||
**kwargs
|
||||
**kwargs,
|
||||
)
|
||||
|
||||
def _get_mandatory_address_fields(self, country_sudo):
|
||||
|
|
@ -122,4 +139,4 @@ class WebsiteSaleMembershipSignup(WebsiteSale):
|
|||
# So even after we drop 'phone' from the address set above, the
|
||||
# portal set re-adds it for billing. We need to drop it here too.
|
||||
fields = list(super()._get_mandatory_fields())
|
||||
return [f for f in fields if f != "phone"]
|
||||
return [f for f in fields if f != "phone"]
|
||||
|
|
|
|||
|
|
@ -3,4 +3,4 @@
|
|||
from . import website
|
||||
from . import res_config_settings
|
||||
from . import res_partner
|
||||
from . import res_users
|
||||
from . import res_users
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
from odoo import fields, models
|
||||
from odoo import fields
|
||||
from odoo import models
|
||||
|
||||
|
||||
class ResConfigSettings(models.TransientModel):
|
||||
|
|
@ -9,4 +10,4 @@ class ResConfigSettings(models.TransientModel):
|
|||
membership_signup_required = fields.Boolean(
|
||||
related="website_id.membership_signup_required",
|
||||
readonly=False,
|
||||
)
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
from odoo import api, models
|
||||
from odoo import api
|
||||
from odoo import models
|
||||
|
||||
|
||||
class ResPartner(models.Model):
|
||||
|
|
@ -29,4 +30,4 @@ class ResPartner(models.Model):
|
|||
if partner:
|
||||
res["firstname"] = partner.firstname or ""
|
||||
res["lastname"] = partner.lastname or ""
|
||||
return res
|
||||
return res
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
from odoo import api, models
|
||||
from odoo import api
|
||||
from odoo import models
|
||||
from odoo.http import request
|
||||
|
||||
|
||||
|
|
@ -19,4 +20,4 @@ class ResUsers(models.Model):
|
|||
return "b2c"
|
||||
if request.session.get("membership_signup_active"):
|
||||
return "b2c"
|
||||
return super()._get_signup_invitation_scope()
|
||||
return super()._get_signup_invitation_scope()
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
from odoo import fields, models
|
||||
from odoo import fields
|
||||
from odoo import models
|
||||
|
||||
|
||||
class Website(models.Model):
|
||||
|
|
@ -9,8 +10,8 @@ class Website(models.Model):
|
|||
membership_signup_required = fields.Boolean(
|
||||
string="Force signup for membership products",
|
||||
help="When enabled, anonymous users trying to add a membership product "
|
||||
"to cart are redirected to /web/signup before the product is "
|
||||
"added. Only affects the e-commerce flow.",
|
||||
"to cart are redirected to /web/signup before the product is "
|
||||
"added. Only affects the e-commerce flow.",
|
||||
default=True,
|
||||
)
|
||||
|
||||
|
|
@ -30,4 +31,4 @@ class Website(models.Model):
|
|||
if not product_id:
|
||||
return False
|
||||
product = self.env["product.product"].sudo().browse(int(product_id)).exists()
|
||||
return bool(product and product.product_tmpl_id.membership)
|
||||
return bool(product and product.product_tmpl_id.membership)
|
||||
|
|
|
|||
|
|
@ -38,4 +38,4 @@ publicWidget.registry.WebsiteSale.include({
|
|||
}
|
||||
return data;
|
||||
},
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -64,8 +64,9 @@ registry.category("web_tour.tours").add("website_membership_signup_required_tour
|
|||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "Submit the signup form -> redirect straight to cart "
|
||||
+ "with the product already added (post-login auto-add)",
|
||||
content:
|
||||
"Submit the signup form -> redirect straight to cart " +
|
||||
"with the product already added (post-login auto-add)",
|
||||
trigger: ".oe_signup_form button[type='submit']",
|
||||
run: "click",
|
||||
expectUnloadPage: true,
|
||||
|
|
@ -108,4 +109,4 @@ registry.category("web_tour.tours").add("website_membership_signup_required_non_
|
|||
tourUtils.goToCart(),
|
||||
tourUtils.assertCartContains({ productName: "Regular Test Product" }),
|
||||
],
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
from . import test_membership_signup
|
||||
from . import test_membership_signup_tour
|
||||
from . import test_membership_signup_tour
|
||||
|
|
|
|||
|
|
@ -4,15 +4,16 @@ import werkzeug.datastructures
|
|||
|
||||
from odoo.exceptions import UserError
|
||||
from odoo.fields import Date
|
||||
from odoo.tests import TransactionCase
|
||||
from odoo.tests import tagged
|
||||
|
||||
from odoo.addons.website.tools import MockRequest
|
||||
from odoo.addons.website_membership_signup_required.controllers.main import (
|
||||
AuthSignupHomeMembership as AuthSignupHome,
|
||||
)
|
||||
from odoo.addons.website_membership_signup_required.controllers.website_sale import (
|
||||
WebsiteSaleMembershipSignup,
|
||||
)
|
||||
from odoo.addons.website.tools import MockRequest
|
||||
from odoo.tests import TransactionCase, tagged
|
||||
|
||||
|
||||
@tagged("post_install", "-at_install")
|
||||
|
|
@ -24,22 +25,28 @@ class TestMembershipSignup(TransactionCase):
|
|||
cls.website = cls.env.ref("website.default_website")
|
||||
cls.website.auth_signup_uninvited = "b2b"
|
||||
today = Date.to_date(Date.today())
|
||||
cls.membership_product = cls.env["product.product"].create({
|
||||
"name": "Membership Card",
|
||||
"membership": True,
|
||||
"list_price": 50.0,
|
||||
"membership_date_from": today.replace(month=1, day=1),
|
||||
"membership_date_to": today.replace(month=12, day=31),
|
||||
})
|
||||
cls.regular_product = cls.env["product.product"].create({
|
||||
"name": "Regular Mug",
|
||||
"membership": False,
|
||||
"list_price": 10.0,
|
||||
})
|
||||
cls.no_user_partner = cls.env["res.partner"].create({
|
||||
"firstname": "Backend",
|
||||
"lastname": "Partner",
|
||||
})
|
||||
cls.membership_product = cls.env["product.product"].create(
|
||||
{
|
||||
"name": "Membership Card",
|
||||
"membership": True,
|
||||
"list_price": 50.0,
|
||||
"membership_date_from": today.replace(month=1, day=1),
|
||||
"membership_date_to": today.replace(month=12, day=31),
|
||||
}
|
||||
)
|
||||
cls.regular_product = cls.env["product.product"].create(
|
||||
{
|
||||
"name": "Regular Mug",
|
||||
"membership": False,
|
||||
"list_price": 10.0,
|
||||
}
|
||||
)
|
||||
cls.no_user_partner = cls.env["res.partner"].create(
|
||||
{
|
||||
"firstname": "Backend",
|
||||
"lastname": "Partner",
|
||||
}
|
||||
)
|
||||
|
||||
# -- RF-07 / RF-default ------------------------------------------------
|
||||
|
||||
|
|
@ -198,13 +205,21 @@ class TestMembershipSignup(TransactionCase):
|
|||
# -- RF-08 -------------------------------------------------------------
|
||||
|
||||
def test_08_backend_sale_order_with_membership_product_without_user(self):
|
||||
order = self.env["sale.order"].create({
|
||||
"partner_id": self.no_user_partner.id,
|
||||
"order_line": [(0, 0, {
|
||||
"product_id": self.membership_product.id,
|
||||
"product_uom_qty": 1.0,
|
||||
})],
|
||||
})
|
||||
order = self.env["sale.order"].create(
|
||||
{
|
||||
"partner_id": self.no_user_partner.id,
|
||||
"order_line": [
|
||||
(
|
||||
0,
|
||||
0,
|
||||
{
|
||||
"product_id": self.membership_product.id,
|
||||
"product_uom_qty": 1.0,
|
||||
},
|
||||
)
|
||||
],
|
||||
}
|
||||
)
|
||||
self.assertTrue(order)
|
||||
self.assertEqual(order.order_line.product_id, self.membership_product)
|
||||
# Confirming the SO drives membership creation (core `membership`).
|
||||
|
|
@ -276,12 +291,14 @@ class TestMembershipSignup(TransactionCase):
|
|||
The invited partner must NOT have a user yet, otherwise the token
|
||||
payload check (`user_ids`) won't match.
|
||||
"""
|
||||
partner = self.env["res.partner"].create({
|
||||
"firstname": "Invited",
|
||||
"lastname": "Researcher",
|
||||
"email": "invited.researcher@example.com",
|
||||
"signup_type": "signup",
|
||||
})
|
||||
partner = self.env["res.partner"].create(
|
||||
{
|
||||
"firstname": "Invited",
|
||||
"lastname": "Researcher",
|
||||
"email": "invited.researcher@example.com",
|
||||
"signup_type": "signup",
|
||||
}
|
||||
)
|
||||
self.assertFalse(partner.user_ids, "test precondition: no user yet")
|
||||
token = partner._generate_signup_token()
|
||||
info = self.env["res.partner"]._signup_retrieve_info(token)
|
||||
|
|
@ -297,11 +314,13 @@ class TestMembershipSignup(TransactionCase):
|
|||
still works — the form will show empty readonly inputs for the split
|
||||
fields, which is the best we can do without re-splitting.
|
||||
"""
|
||||
partner = self.env["res.partner"].create({
|
||||
"name": "Legacy Researcher",
|
||||
"email": "legacy@example.com",
|
||||
"signup_type": "signup",
|
||||
})
|
||||
partner = self.env["res.partner"].create(
|
||||
{
|
||||
"name": "Legacy Researcher",
|
||||
"email": "legacy@example.com",
|
||||
"signup_type": "signup",
|
||||
}
|
||||
)
|
||||
# partner_firstname's post_create hook may or may not have split
|
||||
# `name` automatically; we just check the override does not crash
|
||||
# and returns the contract keys.
|
||||
|
|
@ -309,4 +328,4 @@ class TestMembershipSignup(TransactionCase):
|
|||
info = self.env["res.partner"]._signup_retrieve_info(token)
|
||||
self.assertIn("firstname", info)
|
||||
self.assertIn("lastname", info)
|
||||
self.assertEqual(info.get("name"), partner.name)
|
||||
self.assertEqual(info.get("name"), partner.name)
|
||||
|
|
|
|||
|
|
@ -7,8 +7,8 @@ import time
|
|||
from urllib.parse import unquote
|
||||
|
||||
from odoo.fields import Date
|
||||
|
||||
from odoo.tests import HttpCase, tagged
|
||||
from odoo.tests import HttpCase
|
||||
from odoo.tests import tagged
|
||||
|
||||
|
||||
@tagged("post_install", "-at_install")
|
||||
|
|
@ -21,28 +21,34 @@ class TestMembershipSignupTour(HttpCase):
|
|||
cls.website.auth_signup_uninvited = "b2b"
|
||||
cls.website.membership_signup_required = True
|
||||
today = Date.to_date(Date.today())
|
||||
cls.membership_product = cls.env["product.template"].create({
|
||||
"name": "Membership Test Product",
|
||||
"membership": True,
|
||||
"list_price": 60.0,
|
||||
"is_published": True,
|
||||
"sale_ok": True,
|
||||
"website_id": cls.website.id,
|
||||
"membership_date_from": today.replace(month=1, day=1),
|
||||
"membership_date_to": today.replace(month=12, day=31),
|
||||
})
|
||||
cls.regular_product = cls.env["product.template"].create({
|
||||
"name": "Regular Test Product",
|
||||
"membership": False,
|
||||
"list_price": 5.0,
|
||||
"is_published": True,
|
||||
"sale_ok": True,
|
||||
"website_id": cls.website.id,
|
||||
})
|
||||
cls.membership_product = cls.env["product.template"].create(
|
||||
{
|
||||
"name": "Membership Test Product",
|
||||
"membership": True,
|
||||
"list_price": 60.0,
|
||||
"is_published": True,
|
||||
"sale_ok": True,
|
||||
"website_id": cls.website.id,
|
||||
"membership_date_from": today.replace(month=1, day=1),
|
||||
"membership_date_to": today.replace(month=12, day=31),
|
||||
}
|
||||
)
|
||||
cls.regular_product = cls.env["product.template"].create(
|
||||
{
|
||||
"name": "Regular Test Product",
|
||||
"membership": False,
|
||||
"list_price": 5.0,
|
||||
"is_published": True,
|
||||
"sale_ok": True,
|
||||
"website_id": cls.website.id,
|
||||
}
|
||||
)
|
||||
# Enable the custom/transfer payment provider if it is installed so the
|
||||
# cart page renders fully (no checkout/payment is exercised by the
|
||||
# tours, but it avoids warnings during cart rendering).
|
||||
provider = cls.env.ref("payment.payment_provider_transfer", raise_if_not_found=False)
|
||||
provider = cls.env.ref(
|
||||
"payment.payment_provider_transfer", raise_if_not_found=False
|
||||
)
|
||||
if provider and provider.state != "enabled":
|
||||
provider.write({"state": "enabled", "is_published": True})
|
||||
|
||||
|
|
@ -54,20 +60,24 @@ class TestMembershipSignupTour(HttpCase):
|
|||
)
|
||||
# The tour submitted the signup form, so a new portal user must exist
|
||||
# and the cart of that user must contain the membership product.
|
||||
users = self.env["res.users"].search([
|
||||
("login", "like", "membership.tour.%@test.example.com"),
|
||||
])
|
||||
users = self.env["res.users"].search(
|
||||
[
|
||||
("login", "like", "membership.tour.%@test.example.com"),
|
||||
]
|
||||
)
|
||||
self.assertTrue(users, "Tour should have created a user via /web/signup")
|
||||
first = users.sorted("create_date")[-1]
|
||||
self.assertTrue(first.partner_id.firstname)
|
||||
self.assertTrue(first.partner_id.lastname)
|
||||
carts = self.env["sale.order"].search([
|
||||
("partner_id", "=", first.partner_id.id),
|
||||
("state", "=", "draft"),
|
||||
])
|
||||
carts = self.env["sale.order"].search(
|
||||
[
|
||||
("partner_id", "=", first.partner_id.id),
|
||||
("state", "=", "draft"),
|
||||
]
|
||||
)
|
||||
self.assertTrue(carts)
|
||||
order_lines = carts.mapped("order_line").filtered(
|
||||
lambda l: l.product_id.product_tmpl_id == self.membership_product
|
||||
lambda line: line.product_id.product_tmpl_id == self.membership_product
|
||||
)
|
||||
self.assertTrue(order_lines, "Cart must contain the membership product")
|
||||
|
||||
|
|
@ -93,7 +103,7 @@ class TestMembershipSignupTour(HttpCase):
|
|||
return None
|
||||
secret = self.env["ir.config_parameter"].sudo().get_param("database.secret")
|
||||
max_ts = int(time.time() + 31536000) # 1y, matches Odoo's default.
|
||||
msg = f"{sid}{max_ts}".encode("utf-8")
|
||||
msg = f"{sid}{max_ts}".encode()
|
||||
hm = hmac.new(secret.encode("ascii"), msg, hashlib.sha1).hexdigest()
|
||||
return f"{hm}o{max_ts}"
|
||||
|
||||
|
|
@ -106,8 +116,10 @@ class TestMembershipSignupTour(HttpCase):
|
|||
product_url = "/shop/%s" % self.env["ir.http"]._slug(product)
|
||||
page = self.url_open(product_url, allow_redirects=True)
|
||||
self.assertEqual(
|
||||
page.status_code, 200,
|
||||
"Product page must render (got %s for %s)" % (page.status_code, product_url),
|
||||
page.status_code,
|
||||
200,
|
||||
"Product page must render (got %s for %s)"
|
||||
% (page.status_code, product_url),
|
||||
)
|
||||
match = self._CSRF_RE.search(page.text)
|
||||
csrf_token = match.group(1) if match else self._compute_csrf_token()
|
||||
|
|
@ -199,4 +211,4 @@ class TestMembershipSignupTour(HttpCase):
|
|||
self.assertIn("/shop/cart", location)
|
||||
self.assertNotIn("/web/signup", location)
|
||||
finally:
|
||||
self.website.membership_signup_required = True
|
||||
self.website.membership_signup_required = True
|
||||
|
|
|
|||
|
|
@ -37,4 +37,4 @@
|
|||
</xpath>
|
||||
</template>
|
||||
|
||||
</odoo>
|
||||
</odoo>
|
||||
|
|
|
|||
|
|
@ -15,4 +15,4 @@
|
|||
</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
</odoo>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue