Add pricing information to VPN mobile subscription CTA (Fixes #15463) (#15476)

This commit is contained in:
Alex Gibson 2024-11-12 22:28:17 +00:00 коммит произвёл GitHub
Родитель 68dee4e33b
Коммит a31f0e64c7
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: B5690EEEBB952194
6 изменённых файлов: 950 добавлений и 11 удалений

Просмотреть файл

@ -9,6 +9,7 @@
{% set android_url = play_store_url('vpn', campaign) %}
{% set ios_url = app_store_url('vpn', campaign) %}
{% set redirect_url = 'http://www.mozilla.org/products/vpn/mobile/app/?product=vpn&campaign=' + campaign %}
{% set local_currency_notice = country_code in ["UG", "SN", "UA", "KE"] and ftl_has_messages('vpn-pricing-transaction-may-be-in') %}
<section class="mzp-c-split vpn-pricing-mobile-subscription mzp-l-split-center-on-sm-md mzp-t-content-xl">
<div class="mzp-c-split-container">
@ -16,13 +17,50 @@
{% if heading %}
<h2 class="u-title-lg">{{ heading }}</h2>
{% endif %}
<p class="vpn-pricing-desktop-instruction u-body-lg">
{% if android_sub_only %}
{{ ftl('vpn-pricing-scan-qrcode-to-download-android', fallback='vpn-pricing-scan-qrcode-to-download') }}
{% else %}
{{ ftl('vpn-pricing-scan-qrcode-to-download') }}
{% endif %}
</p>
{% if switch('vpn-wave-vii-pricing') %}
<div class="c-pricing-block-mobile-wrapper">
<div class="c-pricing-block-mobile">
<p class="c-pricing-block-mobile-tag">
{{ ftl('vpn-shared-pricing-recommended-offer') }}
</p>
<h2 class="c-pricing-block-mobile-heading">
{{ ftl('vpn-pricing-annual') }}
</h2>
<h3 class="c-pricing-block-mobile-sub-heading">
{{ vpn_mobile_monthly_price(plan='12-month', country_code=country_code, lang=LANG) }}
</h3>
{% if local_currency_notice %}
<p class="c-pricing-block-mobile-currency-info">
{{ ftl('vpn-pricing-transaction-may-be-in') }}
</p>
{% endif %}
<p class="c-pricing-block-mobile-total">
{{ vpn_mobile_total_price(country_code=country_code, lang=LANG) }}
</p>
</div>
<div class="c-pricing-block-mobile">
<h2 class="c-pricing-block-mobile-heading">
{{ ftl('vpn-pricing-monthly') }}
</h2>
<h3 class="c-pricing-block-mobile-sub-heading">
{{ vpn_mobile_monthly_price(plan='monthly', country_code=country_code, lang=LANG) }}
</h3>
{% if local_currency_notice %}
<p class="c-pricing-block-mobile-currency-info">
{{ ftl('vpn-pricing-transaction-may-be-in') }}
</p>
{% endif %}
</div>
</div>
{% endif %}
<ol class="vpn-pricing-mobile-steps u-body-lg">
{% if android_sub_only %}
@ -34,6 +72,14 @@
<li><span>{{ ftl('vpn-pricing-access', servers=connect_servers, countries=connect_countries) }}</span></li>
</ol>
<p class="vpn-pricing-desktop-instruction u-body-lg">
{% if android_sub_only %}
{{ ftl('vpn-pricing-scan-qrcode-to-download-android', fallback='vpn-pricing-scan-qrcode-to-download') }}
{% else %}
{{ ftl('vpn-pricing-scan-qrcode-to-download') }}
{% endif %}
</p>
{{ picture(
url='img/products/vpn/landing-refresh/devices.svg',
sources=[

Просмотреть файл

@ -74,6 +74,15 @@ def _vpn_get_available_plans(country_code, lang):
return country_plans.get(lang, country_plans.get("default"))
def _vpn_get_mobile_plans(country_code):
"""
Get mobile only subscription plans using country_code.
Defaults to "US" if no matching country code is found.
"""
return settings.VPN_MOBILE_SUB_PRICING.get(country_code, settings.VPN_MOBILE_SUB_PRICING["US"])
def _vpn_product_link(product_url, entrypoint, link_text, class_name=None, optional_parameters=None, optional_attributes=None):
separator = "&" if "?" in product_url else "?"
client_id = settings.VPN_CLIENT_ID
@ -194,6 +203,37 @@ def vpn_monthly_price(ctx, plan=VPN_12_MONTH_PLAN, country_code=None, lang=None)
return Markup(markup)
@library.global_function
@jinja2.pass_context
def vpn_mobile_monthly_price(ctx, plan=VPN_12_MONTH_PLAN, country_code=None, lang=None):
"""
Render a localized string displaying VPN monthly plan price for a mobile subscription.
This is used for countries where a VPN subscription can only be purchased through the
Google Play Store or the Apple App Store, and uses a different pricing plan matrix to
countries that purchase through FxA / sub-plat.
Examples
========
In Template
-----------
{{ vpn_mobile_monthly_price(country_code=country_code, lang=LANG) }}
"""
available_plans = _vpn_get_mobile_plans(country_code)
selected_plan = available_plans.get(plan, VPN_12_MONTH_PLAN)
price = selected_plan.get("price")
currency = selected_plan.get("currency")
currency_locale = lang.replace("-", "_")
amount = _format_currency(price, currency, currency_locale)
price = ftl("vpn-shared-pricing-monthly", amount=amount, ftl_files=FTL_FILES)
markup = f'<span class="vpn-monthly-price-display">{price}</span>'
return Markup(markup)
@library.global_function
@jinja2.pass_context
def vpn_total_price(ctx, country_code=None, lang=None):
@ -226,6 +266,37 @@ def vpn_total_price(ctx, country_code=None, lang=None):
return Markup(markup)
@library.global_function
@jinja2.pass_context
def vpn_mobile_total_price(ctx, country_code=None, lang=None):
"""
Render a localized string displaying VPN total plan price for a mobile subscription.
This is used for countries where a VPN subscription can only be purchased through the
Google Play Store or the Apple App Store, and uses a different pricing plan matrix to
countries that purchase through FxA / sub-plat.
Examples
========
In Template
-----------
{{ vpn_mobile_total_price(country_code=country_code, lang=LANG) }}
"""
available_plans = _vpn_get_mobile_plans(country_code)
selected_plan = available_plans.get(VPN_12_MONTH_PLAN)
price = selected_plan.get("total")
currency = selected_plan.get("currency")
currency_locale = lang.replace("-", "_")
amount = _format_currency(price, currency, currency_locale)
price = ftl("vpn-shared-pricing-total", amount=amount, ftl_files=FTL_FILES)
markup = price
return Markup(markup)
@library.global_function
@jinja2.pass_context
def vpn_saving(ctx, country_code=None, lang=None, ftl_string="vpn-shared-pricing-save-percent"):

Просмотреть файл

@ -1231,7 +1231,7 @@ class TestVPNMonthlyPrice(TestCase):
def _render(self, plan, country_code, lang):
req = self.rf.get("/")
req.locale = "en-US"
req.locale = lang
return render(f"{{{{ vpn_monthly_price('{plan}', '{country_code}', '{lang}') }}}}", {"request": req})
def test_vpn_monthly_price_usd_en_us(self):
@ -1385,6 +1385,315 @@ class TestVPNMonthlyPrice(TestCase):
self.assertEqual(markup, expected)
class TestVPNMobileMonthlyPrice(TestCase):
rf = RequestFactory()
def _render(self, plan, country_code, lang):
req = self.rf.get("/")
req.locale = "en-US"
return render(f"{{{{ vpn_mobile_monthly_price('{plan}', '{country_code}', '{lang}') }}}}", {"request": req})
def test_vpn_monthly_price_au_en_us(self):
"""Should return expected markup"""
markup = self._render(plan="monthly", country_code="AU", lang="en-US")
expected = '<span class="vpn-monthly-price-display">A$14.99<span>/month</span></span>'
self.assertEqual(markup, expected)
def test_vpn_12_month_price_au_en_us(self):
"""Should return expected markup"""
markup = self._render(plan="12-month", country_code="AU", lang="en-US")
expected = '<span class="vpn-monthly-price-display">A$7.50<span>/month</span></span>'
self.assertEqual(markup, expected)
def test_vpn_monthly_price_bd_en_us(self):
"""Should return expected markup"""
markup = self._render(plan="monthly", country_code="BD", lang="en-US")
expected = '<span class="vpn-monthly-price-display">BDT1,200.00<span>/month</span></span>'
self.assertEqual(markup, expected)
def test_vpn_12_month_price_bd_en_us(self):
"""Should return expected markup"""
markup = self._render(plan="12-month", country_code="BD", lang="en-US")
expected = '<span class="vpn-monthly-price-display">BDT583.33<span>/month</span></span>'
self.assertEqual(markup, expected)
def test_vpn_monthly_price_br_en_us(self):
"""Should return expected markup"""
markup = self._render(plan="monthly", country_code="BR", lang="en-US")
expected = '<span class="vpn-monthly-price-display">R$56.00<span>/month</span></span>'
self.assertEqual(markup, expected)
def test_vpn_12_month_price_br_en_us(self):
"""Should return expected markup"""
markup = self._render(plan="12-month", country_code="BR", lang="en-US")
expected = '<span class="vpn-monthly-price-display">R$27.50<span>/month</span></span>'
self.assertEqual(markup, expected)
def test_vpn_monthly_price_cl_en_us(self):
"""Should return expected markup"""
markup = self._render(plan="monthly", country_code="CL", lang="en-US")
expected = '<span class="vpn-monthly-price-display">CLP9,300<span>/month</span></span>'
self.assertEqual(markup, expected)
def test_vpn_12_month_price_cl_en_us(self):
"""Should return expected markup"""
markup = self._render(plan="12-month", country_code="CL", lang="en-US")
expected = '<span class="vpn-monthly-price-display">CLP4,582<span>/month</span></span>'
self.assertEqual(markup, expected)
def test_vpn_monthly_price_co_en_us(self):
"""Should return expected markup"""
markup = self._render(plan="monthly", country_code="CO", lang="en-US")
expected = '<span class="vpn-monthly-price-display">COP41,900.00<span>/month</span></span>'
self.assertEqual(markup, expected)
def test_vpn_12_month_price_co_en_us(self):
"""Should return expected markup"""
markup = self._render(plan="12-month", country_code="CO", lang="en-US")
expected = '<span class="vpn-monthly-price-display">COP20,825.00<span>/month</span></span>'
self.assertEqual(markup, expected)
def test_vpn_monthly_price_eg_en_us(self):
"""Should return expected markup"""
markup = self._render(plan="monthly", country_code="EG", lang="en-US")
expected = '<span class="vpn-monthly-price-display">EGP479.99<span>/month</span></span>'
self.assertEqual(markup, expected)
def test_vpn_12_month_price_eg_en_us(self):
"""Should return expected markup"""
markup = self._render(plan="12-month", country_code="EG", lang="en-US")
expected = '<span class="vpn-monthly-price-display">EGP241.67<span>/month</span></span>'
self.assertEqual(markup, expected)
def test_vpn_monthly_price_gr_en_us(self):
"""Should return expected markup"""
markup = self._render(plan="monthly", country_code="GR", lang="en-US")
expected = '<span class="vpn-monthly-price-display">€9.99<span>/month</span></span>'
self.assertEqual(markup, expected)
def test_vpn_12_month_price_gr_en_us(self):
"""Should return expected markup"""
markup = self._render(plan="12-month", country_code="GR", lang="en-US")
expected = '<span class="vpn-monthly-price-display">€4.99<span>/month</span></span>'
self.assertEqual(markup, expected)
def test_vpn_monthly_price_id_en_us(self):
"""Should return expected markup"""
markup = self._render(plan="monthly", country_code="ID", lang="en-US")
expected = '<span class="vpn-monthly-price-display">IDR155,000.00<span>/month</span></span>'
self.assertEqual(markup, expected)
def test_vpn_12_month_price_id_en_us(self):
"""Should return expected markup"""
markup = self._render(plan="12-month", country_code="ID", lang="en-US")
expected = '<span class="vpn-monthly-price-display">IDR75,000.00<span>/month</span></span>'
self.assertEqual(markup, expected)
def test_vpn_monthly_price_in_en_us(self):
"""Should return expected markup"""
markup = self._render(plan="monthly", country_code="IN", lang="en-US")
expected = '<span class="vpn-monthly-price-display">₹839.00<span>/month</span></span>'
self.assertEqual(markup, expected)
def test_vpn_12_month_price_in_en_us(self):
"""Should return expected markup"""
markup = self._render(plan="12-month", country_code="IN", lang="en-US")
expected = '<span class="vpn-monthly-price-display">₹416.58<span>/month</span></span>'
self.assertEqual(markup, expected)
def test_vpn_monthly_price_ke_en_us(self):
"""Should return expected markup"""
markup = self._render(plan="monthly", country_code="KE", lang="en-US")
expected = '<span class="vpn-monthly-price-display">$9.99<span>/month</span></span>'
self.assertEqual(markup, expected)
def test_vpn_12_month_price_ke_en_us(self):
"""Should return expected markup"""
markup = self._render(plan="12-month", country_code="KE", lang="en-US")
expected = '<span class="vpn-monthly-price-display">$5.00<span>/month</span></span>'
self.assertEqual(markup, expected)
def test_vpn_monthly_price_kr_en_us(self):
"""Should return expected markup"""
markup = self._render(plan="monthly", country_code="KR", lang="en-US")
expected = '<span class="vpn-monthly-price-display">₩13,500<span>/month</span></span>'
self.assertEqual(markup, expected)
def test_vpn_12_month_price_kr_en_us(self):
"""Should return expected markup"""
markup = self._render(plan="12-month", country_code="KR", lang="en-US")
expected = '<span class="vpn-monthly-price-display">₩6,658<span>/month</span></span>'
self.assertEqual(markup, expected)
def test_vpn_monthly_price_ma_en_us(self):
"""Should return expected markup"""
markup = self._render(plan="monthly", country_code="MA", lang="en-US")
expected = '<span class="vpn-monthly-price-display">MAD99.00<span>/month</span></span>'
self.assertEqual(markup, expected)
def test_vpn_12_month_price_ma_en_us(self):
"""Should return expected markup"""
markup = self._render(plan="12-month", country_code="MA", lang="en-US")
expected = '<span class="vpn-monthly-price-display">MAD50.00<span>/month</span></span>'
self.assertEqual(markup, expected)
def test_vpn_monthly_price_mx_en_us(self):
"""Should return expected markup"""
markup = self._render(plan="monthly", country_code="MX", lang="en-US")
expected = '<span class="vpn-monthly-price-display">MX$189.00<span>/month</span></span>'
self.assertEqual(markup, expected)
def test_vpn_12_month_price_mx_en_us(self):
"""Should return expected markup"""
markup = self._render(plan="12-month", country_code="MX", lang="en-US")
expected = '<span class="vpn-monthly-price-display">MX$95.75<span>/month</span></span>'
self.assertEqual(markup, expected)
def test_vpn_monthly_price_ng_en_us(self):
"""Should return expected markup"""
markup = self._render(plan="monthly", country_code="NG", lang="en-US")
expected = '<span class="vpn-monthly-price-display">NGN15,900.00<span>/month</span></span>'
self.assertEqual(markup, expected)
def test_vpn_12_month_price_ng_en_us(self):
"""Should return expected markup"""
markup = self._render(plan="12-month", country_code="NG", lang="en-US")
expected = '<span class="vpn-monthly-price-display">NGN8,325.00<span>/month</span></span>'
self.assertEqual(markup, expected)
def test_vpn_monthly_price_no_en_us(self):
"""Should return expected markup"""
markup = self._render(plan="monthly", country_code="NO", lang="en-US")
expected = '<span class="vpn-monthly-price-display">NOK110.00<span>/month</span></span>'
self.assertEqual(markup, expected)
def test_vpn_12_month_price_no_en_us(self):
"""Should return expected markup"""
markup = self._render(plan="12-month", country_code="NO", lang="en-US")
expected = '<span class="vpn-monthly-price-display">NOK54.17<span>/month</span></span>'
self.assertEqual(markup, expected)
def test_vpn_monthly_price_sa_en_us(self):
"""Should return expected markup"""
markup = self._render(plan="monthly", country_code="SA", lang="en-US")
expected = '<span class="vpn-monthly-price-display">SAR36.99<span>/month</span></span>'
self.assertEqual(markup, expected)
def test_vpn_12_month_price_sa_en_us(self):
"""Should return expected markup"""
markup = self._render(plan="12-month", country_code="SA", lang="en-US")
expected = '<span class="vpn-monthly-price-display">SAR18.75<span>/month</span></span>'
self.assertEqual(markup, expected)
def test_vpn_monthly_price_sn_en_us(self):
"""Should return expected markup"""
markup = self._render(plan="monthly", country_code="SN", lang="en-US")
expected = '<span class="vpn-monthly-price-display">$9.99<span>/month</span></span>'
self.assertEqual(markup, expected)
def test_vpn_12_month_price_sn_en_us(self):
"""Should return expected markup"""
markup = self._render(plan="12-month", country_code="SN", lang="en-US")
expected = '<span class="vpn-monthly-price-display">$4.99<span>/month</span></span>'
self.assertEqual(markup, expected)
def test_vpn_monthly_price_th_en_us(self):
"""Should return expected markup"""
markup = self._render(plan="monthly", country_code="TH", lang="en-US")
expected = '<span class="vpn-monthly-price-display">THB330.00<span>/month</span></span>'
self.assertEqual(markup, expected)
def test_vpn_12_month_price_th_en_us(self):
"""Should return expected markup"""
markup = self._render(plan="12-month", country_code="TH", lang="en-US")
expected = '<span class="vpn-monthly-price-display">THB165.83<span>/month</span></span>'
self.assertEqual(markup, expected)
def test_vpn_monthly_price_tr_en_us(self):
"""Should return expected markup"""
markup = self._render(plan="monthly", country_code="TR", lang="en-US")
expected = '<span class="vpn-monthly-price-display">TRY339.99<span>/month</span></span>'
self.assertEqual(markup, expected)
def test_vpn_12_month_price_tr_en_us(self):
"""Should return expected markup"""
markup = self._render(plan="12-month", country_code="TR", lang="en-US")
expected = '<span class="vpn-monthly-price-display">TRY166.67<span>/month</span></span>'
self.assertEqual(markup, expected)
def test_vpn_monthly_price_tw_en_us(self):
"""Should return expected markup"""
markup = self._render(plan="monthly", country_code="TW", lang="en-US")
expected = '<span class="vpn-monthly-price-display">NT$320.00<span>/month</span></span>'
self.assertEqual(markup, expected)
def test_vpn_12_month_price_tw_en_us(self):
"""Should return expected markup"""
markup = self._render(plan="12-month", country_code="TW", lang="en-US")
expected = '<span class="vpn-monthly-price-display">NT$158.33<span>/month</span></span>'
self.assertEqual(markup, expected)
def test_vpn_monthly_price_ua_en_us(self):
"""Should return expected markup"""
markup = self._render(plan="monthly", country_code="UA", lang="en-US")
expected = '<span class="vpn-monthly-price-display">$9.99<span>/month</span></span>'
self.assertEqual(markup, expected)
def test_vpn_12_month_price_ua_en_us(self):
"""Should return expected markup"""
markup = self._render(plan="12-month", country_code="UA", lang="en-US")
expected = '<span class="vpn-monthly-price-display">$5.00<span>/month</span></span>'
self.assertEqual(markup, expected)
def test_vpn_monthly_price_ug_en_us(self):
"""Should return expected markup"""
markup = self._render(plan="monthly", country_code="UG", lang="en-US")
expected = '<span class="vpn-monthly-price-display">$9.99<span>/month</span></span>'
self.assertEqual(markup, expected)
def test_vpn_12_month_price_ug_en_us(self):
"""Should return expected markup"""
markup = self._render(plan="12-month", country_code="UG", lang="en-US")
expected = '<span class="vpn-monthly-price-display">$4.99<span>/month</span></span>'
self.assertEqual(markup, expected)
def test_vpn_monthly_price_vn_en_us(self):
"""Should return expected markup"""
markup = self._render(plan="monthly", country_code="VN", lang="en-US")
expected = '<span class="vpn-monthly-price-display">₫249,000<span>/month</span></span>'
self.assertEqual(markup, expected)
def test_vpn_12_month_price_vn_en_us(self):
"""Should return expected markup"""
markup = self._render(plan="12-month", country_code="VN", lang="en-US")
expected = '<span class="vpn-monthly-price-display">₫124,917<span>/month</span></span>'
self.assertEqual(markup, expected)
def test_vpn_monthly_price_za_en_us(self):
"""Should return expected markup"""
markup = self._render(plan="monthly", country_code="ZA", lang="en-US")
expected = '<span class="vpn-monthly-price-display">ZAR169.99<span>/month</span></span>'
self.assertEqual(markup, expected)
def test_vpn_12_month_price_za_en_us(self):
"""Should return expected markup"""
markup = self._render(plan="12-month", country_code="ZA", lang="en-US")
expected = '<span class="vpn-monthly-price-display">ZAR83.33<span>/month</span></span>'
self.assertEqual(markup, expected)
def test_vpn_monthly_price_unknown_en_us(self):
"""Should return expected markup"""
markup = self._render(plan="monthly", country_code="", lang="en-US")
expected = '<span class="vpn-monthly-price-display">$9.99<span>/month</span></span>'
self.assertEqual(markup, expected)
def test_vpn_12_month_price_unknown_en_us(self):
"""Should return expected markup"""
markup = self._render(plan="12-month", country_code="", lang="en-US")
expected = '<span class="vpn-monthly-price-display">$4.99<span>/month</span></span>'
self.assertEqual(markup, expected)
@override_settings(
VPN_VARIABLE_PRICING=TEST_VPN_VARIABLE_PRICING,
)
@ -1393,7 +1702,7 @@ class TestVPNTotalPrice(TestCase):
def _render(self, country_code, lang):
req = self.rf.get("/")
req.locale = "en-US"
req.locale = lang
return render(f"{{{{ vpn_total_price('{country_code}', '{lang}') }}}}", {"request": req})
def test_vpn_12_month_total_price_usd_en_us(self):
@ -1481,6 +1790,165 @@ class TestVPNTotalPrice(TestCase):
self.assertEqual(markup, expected)
class TestVPNMobileTotalPrice(TestCase):
rf = RequestFactory()
def _render(self, country_code, lang):
req = self.rf.get("/")
req.locale = lang
return render(f"{{{{ vpn_mobile_total_price('{country_code}', '{lang}') }}}}", {"request": req})
def test_vpn_12_month_total_price_au_en_us(self):
"""Should return expected markup"""
markup = self._render(country_code="AU", lang="en-US")
expected = "A$89.99 total"
self.assertEqual(markup, expected)
def test_vpn_12_month_total_price_bd_en_us(self):
"""Should return expected markup"""
markup = self._render(country_code="BD", lang="en-US")
expected = "BDT7,000.00 total"
self.assertEqual(markup, expected)
def test_vpn_12_month_total_price_br_en_us(self):
"""Should return expected markup"""
markup = self._render(country_code="BR", lang="en-US")
expected = "R$330.00 total"
self.assertEqual(markup, expected)
def test_vpn_12_month_total_price_cl_en_us(self):
"""Should return expected markup"""
markup = self._render(country_code="CL", lang="en-US")
expected = "CLP54,990 total"
self.assertEqual(markup, expected)
def test_vpn_12_month_total_price_co_en_us(self):
"""Should return expected markup"""
markup = self._render(country_code="CO", lang="en-US")
expected = "COP249,900.00 total"
self.assertEqual(markup, expected)
def test_vpn_12_month_total_price_eg_en_us(self):
"""Should return expected markup"""
markup = self._render(country_code="EG", lang="en-US")
expected = "EGP2,899.99 total"
self.assertEqual(markup, expected)
def test_vpn_12_month_total_price_gr_en_us(self):
"""Should return expected markup"""
markup = self._render(country_code="GR", lang="en-US")
expected = "€59.88 total"
self.assertEqual(markup, expected)
def test_vpn_12_month_total_price_id_en_us(self):
"""Should return expected markup"""
markup = self._render(country_code="ID", lang="en-US")
expected = "IDR900,000.00 total"
self.assertEqual(markup, expected)
def test_vpn_12_month_total_price_in_en_us(self):
"""Should return expected markup"""
markup = self._render(country_code="IN", lang="en-US")
expected = "₹4,999.00 total"
self.assertEqual(markup, expected)
def test_vpn_12_month_total_price_ke_en_us(self):
"""Should return expected markup"""
markup = self._render(country_code="KE", lang="en-US")
expected = "$59.99 total"
self.assertEqual(markup, expected)
def test_vpn_12_month_total_price_kr_en_us(self):
"""Should return expected markup"""
markup = self._render(country_code="KR", lang="en-US")
expected = "₩79,900 total"
self.assertEqual(markup, expected)
def test_vpn_12_month_total_price_ma_en_us(self):
"""Should return expected markup"""
markup = self._render(country_code="MA", lang="en-US")
expected = "MAD600.00 total"
self.assertEqual(markup, expected)
def test_vpn_12_month_total_price_mx_en_us(self):
"""Should return expected markup"""
markup = self._render(country_code="MX", lang="en-US")
expected = "MX$1,149.00 total"
self.assertEqual(markup, expected)
def test_vpn_12_month_total_price_ng_en_us(self):
"""Should return expected markup"""
markup = self._render(country_code="NG", lang="en-US")
expected = "NGN99,900.00 total"
self.assertEqual(markup, expected)
def test_vpn_12_month_total_price_no_en_us(self):
"""Should return expected markup"""
markup = self._render(country_code="NO", lang="en-US")
expected = "NOK650.00 total"
self.assertEqual(markup, expected)
def test_vpn_12_month_total_price_sa_en_us(self):
"""Should return expected markup"""
markup = self._render(country_code="SA", lang="en-US")
expected = "SAR224.99 total"
self.assertEqual(markup, expected)
def test_vpn_12_month_total_price_sn_en_us(self):
"""Should return expected markup"""
markup = self._render(country_code="SN", lang="en-US")
expected = "$59.88 total"
self.assertEqual(markup, expected)
def test_vpn_12_month_total_price_th_en_us(self):
"""Should return expected markup"""
markup = self._render(country_code="TH", lang="en-US")
expected = "THB1,990.00 total"
self.assertEqual(markup, expected)
def test_vpn_12_month_total_price_tr_en_us(self):
"""Should return expected markup"""
markup = self._render(country_code="TR", lang="en-US")
expected = "TRY1,999.99 total"
self.assertEqual(markup, expected)
def test_vpn_12_month_total_price_tw_en_us(self):
"""Should return expected markup"""
markup = self._render(country_code="TW", lang="en-US")
expected = "NT$1,900.00 total"
self.assertEqual(markup, expected)
def test_vpn_12_month_total_price_ua_en_us(self):
"""Should return expected markup"""
markup = self._render(country_code="UA", lang="en-US")
expected = "$59.99 total"
self.assertEqual(markup, expected)
def test_vpn_12_month_total_price_ug_en_us(self):
"""Should return expected markup"""
markup = self._render(country_code="UG", lang="en-US")
expected = "$59.88 total"
self.assertEqual(markup, expected)
def test_vpn_12_month_total_price_vn_en_us(self):
"""Should return expected markup"""
markup = self._render(country_code="VN", lang="en-US")
expected = "₫1,499,000 total"
self.assertEqual(markup, expected)
def test_vpn_12_month_total_price_za_en_us(self):
"""Should return expected markup"""
markup = self._render(country_code="ZA", lang="en-US")
expected = "ZAR999.99 total"
self.assertEqual(markup, expected)
def test_vpn_12_month_total_price_unknown_en_us(self):
"""Should return expected markup"""
markup = self._render(country_code="", lang="en-US")
expected = "$59.88 total"
self.assertEqual(markup, expected)
@override_settings(
VPN_VARIABLE_PRICING=TEST_VPN_VARIABLE_PRICING,
)
@ -1489,7 +1957,7 @@ class TestVPNSaving(TestCase):
def _render(self, country_code, lang):
req = self.rf.get("/")
req.locale = "en-US"
req.locale = lang
return render(f"{{{{ vpn_saving('{country_code}', '{lang}') }}}}", {"request": req})
def test_vpn_12_month_saving_usd(self):

Просмотреть файл

@ -1736,6 +1736,286 @@ VPN_VARIABLE_PRICING = {
},
}
# Simplified pricing matrix for countries that can
# only purchase a subscription through the app store.
VPN_MOBILE_SUB_PRICING = {
"AU": { # Australia
"12-month": {
"price": "7.5",
"total": "89.99",
"currency": "AUD",
},
"monthly": {
"price": "14.99",
"currency": "AUD",
},
},
"BD": { # Bangladesh
"12-month": {
"price": "583.33",
"total": "7000",
"currency": "BDT",
},
"monthly": {
"price": "1200",
"currency": "BDT",
},
},
"BR": { # Brazil
"12-month": {
"price": "27.50",
"total": "330",
"currency": "BRL",
},
"monthly": {
"price": "56",
"currency": "BRL",
},
},
"CL": { # Chile
"12-month": {
"price": "4582.50",
"total": "54990",
"currency": "CLP",
},
"monthly": {
"price": "9300",
"currency": "CLP",
},
},
"CO": { # Colombia
"12-month": {
"price": "20825",
"total": "249900",
"currency": "COP",
},
"monthly": {
"price": "41900",
"currency": "COP",
},
},
"EG": { # Egypt
"12-month": {
"price": "241.67",
"total": "2899.99",
"currency": "EGP",
},
"monthly": {
"price": "479.99",
"currency": "EGP",
},
},
"GR": { # Greece
"12-month": {
"price": "4.99",
"total": "59.88",
"currency": "EUR",
},
"monthly": {
"price": "9.99",
"currency": "EUR",
},
},
"ID": { # Indonesia
"12-month": {
"price": "75000",
"total": "900000",
"currency": "IDR",
},
"monthly": {
"price": "155000",
"currency": "IDR",
},
},
"IN": { # India
"12-month": {
"price": "416.58",
"total": "4999",
"currency": "INR",
},
"monthly": {
"price": "839",
"currency": "INR",
},
},
"KE": { # Kenya
"12-month": {
"price": "5.00",
"total": "59.99",
"currency": "USD",
},
"monthly": {
"price": "9.99",
"currency": "USD",
},
},
"KR": { # South Korea
"12-month": {
"price": "6658.33",
"total": "79900",
"currency": "KRW",
},
"monthly": {
"price": "13500",
"currency": "KRW",
},
},
"MA": { # Morocco
"12-month": {
"price": "50",
"total": "600",
"currency": "MAD",
},
"monthly": {
"price": "99",
"currency": "MAD",
},
},
"MX": { # Mexico
"12-month": {
"price": "95.75",
"total": "1149",
"currency": "MXN",
},
"monthly": {
"price": "189",
"currency": "MXN",
},
},
"NG": { # Nigeria
"12-month": {
"price": "8325",
"total": "99900",
"currency": "NGN",
},
"monthly": {
"price": "15900",
"currency": "NGN",
},
},
"NO": { # Norway
"12-month": {
"price": "54.17",
"total": "650",
"currency": "NOK",
},
"monthly": {
"price": "110",
"currency": "NOK",
},
},
"SA": { # Saudi Arabia
"12-month": {
"price": "18.75",
"total": "224.99",
"currency": "SAR",
},
"monthly": {
"price": "36.99",
"currency": "SAR",
},
},
"SN": { # Senegal
"12-month": {
"price": "4.99",
"total": "59.88",
"currency": "USD",
},
"monthly": {
"price": "9.99",
"currency": "USD",
},
},
"TH": { # Thailand
"12-month": {
"price": "165.83",
"total": "1990",
"currency": "THB",
},
"monthly": {
"price": "330",
"currency": "THB",
},
},
"TR": { # Turkey
"12-month": {
"price": "166.67",
"total": "1999.99",
"currency": "TRY",
},
"monthly": {
"price": "339.99",
"currency": "TRY",
},
},
"TW": { # Taiwan
"12-month": {
"price": "158.33",
"total": "1900",
"currency": "TWD",
},
"monthly": {
"price": "320",
"currency": "TWD",
},
},
"UA": { # Ukraine
"12-month": {
"price": "5.00",
"total": "59.99",
"currency": "USD",
},
"monthly": {
"price": "9.99",
"currency": "USD",
},
},
"UG": { # Uganda
"12-month": {
"price": "4.99",
"total": "59.88",
"currency": "USD",
},
"monthly": {
"price": "9.99",
"currency": "USD",
},
},
"US": { # United States (only used as a fallback should a country match not be found).
"12-month": {
"price": "4.99",
"total": "59.88",
"currency": "USD",
},
"monthly": {
"price": "9.99",
"currency": "USD",
},
},
"VN": { # Vietnam
"12-month": {
"price": "124917",
"total": "1499000",
"currency": "VND",
},
"monthly": {
"price": "249000",
"currency": "VND",
},
},
"ZA": { # South Africa
"12-month": {
"price": "83.33",
"total": "999.99",
"currency": "ZAR",
},
"monthly": {
"price": "169.99",
"currency": "ZAR",
},
},
}
# Mozilla VPN Geo restrictions
# https://github.com/mozilla-services/guardian-website/blob/master/server/constants.ts

Просмотреть файл

@ -67,3 +67,4 @@ vpn-pricing-scan-qrcode-to-download-android = To download the app, scan the QR C
vpn-pricing-sign-up-on-your-mobile-device = Sign up for a { -brand-name-mozilla-vpn } subscription on your mobile device
vpn-pricing-sign-up-on-your-android-device = Sign up for a { -brand-name-mozilla-vpn } subscription on your Android device
vpn-pricing-download-the-app = Download the app
vpn-pricing-transaction-may-be-in = * Transaction may be in local currency equivalent.

Просмотреть файл

@ -247,7 +247,7 @@ $image-path: '/media/protocol/img';
}
@media #{$mq-md} {
margin: $spacing-2xl 0;
margin: $spacing-xl 0 $spacing-2xl;
}
}
@ -340,3 +340,76 @@ html.android {
padding-top: 0;
margin-top: -$spacing-2xl;
}
// Mobile subscription pricing display
.c-pricing-block-mobile-wrapper {
margin-top: $spacing-2xl;
@media #{$mq-xl} {
display: grid;
grid-gap: $spacing-lg;
grid-template-columns: repeat(2, 1fr);
}
}
.c-pricing-block-mobile {
background: $color-marketing-gray-20;
border-radius: $border-radius-md;
margin-bottom: $spacing-lg;
padding: $spacing-md;
position: relative;
@include bidi(((text-align, left, right),));
}
.c-pricing-block-mobile-tag {
background: $color-vpn-brand-refresh-purple-20;
border-radius: $border-radius-md;
color: $color-white;
display: inline-block;
font-weight: bold;
padding: $spacing-xs $spacing-md;
@include text-body-sm;
html[lang^='en'] & {
text-transform: uppercase;
}
@media #{$mq-xl} {
position: absolute;
top: $spacing-md;
@include bidi(((left, $spacing-md, right, auto),));
}
}
.c-pricing-block-mobile-heading {
border-bottom: 2px solid $color-black;
padding-bottom: $spacing-md;
@include text-title-xs;
@media #{$mq-xl} {
margin-top: $spacing-2xl;
}
}
.c-pricing-block-mobile-sub-heading {
margin-bottom: 0;
@include text-title-xs;
.vpn-monthly-price-display span {
display: inline-block;
font-weight: normal;
@include text-body-md;
}
}
.c-pricing-block-mobile-currency-info {
margin: $spacing-lg 0 0;
@include text-body-sm;
}
.c-pricing-block-mobile-total {
color: $color-vpn-brand-refresh-gray;
font-weight: bold;
margin: $spacing-lg 0 0;
}