Clarify customer login and invoice emails (#250)
Separate Pleno login email from e-conomic invoice email, make the login-email update flow authoritative and cache-safe, clear stale economic profile state, and add focused frontend coverage.
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
<script setup>
|
||||
import { ref, watch } from 'vue';
|
||||
import { getCurrentInstance, ref, watch } from 'vue';
|
||||
import {parseError, getError} from "@/components/request/HandleGlobalError.vue";
|
||||
|
||||
const props = defineProps({
|
||||
@@ -24,6 +24,7 @@ const props = defineProps({
|
||||
});
|
||||
|
||||
const isEditting = ref(false);
|
||||
const inputId = `configuration-input-${getCurrentInstance()?.uid}`;
|
||||
|
||||
const v_model = ref(props.value);
|
||||
|
||||
@@ -45,7 +46,7 @@ const parseErrorOnSave = (error) => {
|
||||
|
||||
<template>
|
||||
<div class="field">
|
||||
<label class="label">{{ title }}</label>
|
||||
<label class="label" :for="inputId">{{ title }}</label>
|
||||
<!-- If the value is not set, show a warning message -->
|
||||
<div v-if="!props.value && showEmptyWarning && !isEditting"
|
||||
class="message is-warning">
|
||||
@@ -58,6 +59,7 @@ const parseErrorOnSave = (error) => {
|
||||
<div class="field has-addons">
|
||||
<div class="control is-expanded">
|
||||
<input
|
||||
:id="inputId"
|
||||
class="input"
|
||||
type="text"
|
||||
v-model="v_model"
|
||||
|
||||
@@ -254,6 +254,20 @@ export const refreshReleaseRuntime = async ({ throwOnError = false } = {}) => {
|
||||
}
|
||||
};
|
||||
|
||||
const resetEconomicData = () => {
|
||||
SessionUser.economicData.customerNumber.value = null;
|
||||
SessionUser.economicData.name.value = null;
|
||||
SessionUser.economicData.address.value = null;
|
||||
SessionUser.economicData.zip.value = null;
|
||||
SessionUser.economicData.city.value = null;
|
||||
SessionUser.economicData.mobilePhone.value = null;
|
||||
SessionUser.economicData.email.value = null;
|
||||
SessionUser.economicData.cvr.value = null;
|
||||
SessionUser.economicData.currency.value = null;
|
||||
SessionUser.economicData.country.value = null;
|
||||
SessionUser.economicData.cached_at.value = null;
|
||||
};
|
||||
|
||||
const resetSessionState = () => {
|
||||
SessionUser.user.id.value = null;
|
||||
SessionUser.user.customer_number.value = null;
|
||||
@@ -302,17 +316,7 @@ const resetSessionState = () => {
|
||||
}
|
||||
}
|
||||
|
||||
SessionUser.economicData.customerNumber.value = null;
|
||||
SessionUser.economicData.name.value = null;
|
||||
SessionUser.economicData.address.value = null;
|
||||
SessionUser.economicData.zip.value = null;
|
||||
SessionUser.economicData.city.value = null;
|
||||
SessionUser.economicData.mobilePhone.value = null;
|
||||
SessionUser.economicData.email.value = null;
|
||||
SessionUser.economicData.cvr.value = null;
|
||||
SessionUser.economicData.currency.value = null;
|
||||
SessionUser.economicData.country.value = null;
|
||||
SessionUser.economicData.cached_at.value = null;
|
||||
resetEconomicData();
|
||||
|
||||
SessionUser.runtimeConfig.economic.transactionDraftCustomerNumber.value = null;
|
||||
SessionUser.runtimeConfig.economic.defaultDistributionDepartmentId.value = null;
|
||||
@@ -698,6 +702,8 @@ export const getSessionData = async () => {
|
||||
SessionUser.economicData.currency.value = session.economic_customer.currency;
|
||||
SessionUser.economicData.country.value = session.economic_customer.country;
|
||||
SessionUser.economicData.cached_at.value = new Date();
|
||||
} else {
|
||||
resetEconomicData();
|
||||
}
|
||||
SessionUser.initiated.value = true;
|
||||
})
|
||||
|
||||
@@ -6908,6 +6908,9 @@
|
||||
"account_name_desc": "@:{'words.generated.kundekonto'} @:{'words.generated.navn'}",
|
||||
"account_number_desc": "@:{'words.generated.kundekonto'} @:{'words.generated.nummer'}",
|
||||
"description": "@.capitalize:{'words.generated.dine'} @:{'words.generated.fakturaoplysninger'}",
|
||||
"invoice_email_desc": "Administreres i e-conomic og ændres ikke, når du ændrer din login-e-mail.",
|
||||
"invoice_email_label": "Faktura-e-mail (e-conomic)",
|
||||
"invoice_email_missing": "Ikke angivet i e-conomic",
|
||||
"title": "@.capitalize:{'words.generated.fakturaoplysninger'}"
|
||||
},
|
||||
"microsoft_auth": {
|
||||
@@ -6935,7 +6938,9 @@
|
||||
},
|
||||
"security": {
|
||||
"description": "@.capitalize:{'words.generated.dine'} sikkerhedsindstillinger",
|
||||
"email_desc": "@.capitalize:{'words.generated.vi'} @:{'words.generated.bruger'} @:{'words.generated.denne'} @:{'words.generated.e'}-@:{'words.generated.mail'} @:{'words.generated.til'} @:{'words.generated.at'} nulstille @:{'words.generated.din'} @:{'words.generated.adgangskode'}, fremsende @:{'words.generated.vaskecertifikater'} @:{'words.generated.og'} @:{'words.generated.andre'} vigtige @:{'words.generated.oplysninger'}."
|
||||
"email_desc": "@.capitalize:{'words.generated.vi'} @:{'words.generated.bruger'} @:{'words.generated.denne'} @:{'words.generated.e'}-@:{'words.generated.mail'} @:{'words.generated.til'} @:{'words.generated.at'} nulstille @:{'words.generated.din'} @:{'words.generated.adgangskode'}, fremsende @:{'words.generated.vaskecertifikater'} @:{'words.generated.og'} @:{'words.generated.andre'} vigtige @:{'words.generated.oplysninger'}.",
|
||||
"login_email_desc": "Bruges til at logge ind og nulstille din adgangskode. Dette ændrer ikke faktura-e-mailen i e-conomic.",
|
||||
"login_email_label": "Login-e-mail"
|
||||
},
|
||||
"title": "@.capitalize:{'words.generated.brugerprofil'}"
|
||||
},
|
||||
|
||||
@@ -7018,6 +7018,9 @@
|
||||
"account_name_desc": "Kundenkontoname",
|
||||
"account_number_desc": "Kundenkontonummer",
|
||||
"description": "@.capitalize:{'words.generated.ihre'} @:{'words.generated.rechnungsinformationen'}",
|
||||
"invoice_email_desc": "Wird in e-conomic verwaltet und nicht geändert, wenn Sie Ihre Anmelde-E-Mail ändern.",
|
||||
"invoice_email_label": "Rechnungs-E-Mail (e-conomic)",
|
||||
"invoice_email_missing": "Nicht in e-conomic hinterlegt",
|
||||
"title": "@:{'words.generated.rechnungsinformationen'}"
|
||||
},
|
||||
"microsoft_auth": {
|
||||
@@ -7045,7 +7048,9 @@
|
||||
},
|
||||
"security": {
|
||||
"description": "@.capitalize:{'words.generated.ihre'} Sicherheitseinstellungen",
|
||||
"email_desc": "@.capitalize:{'words.generated.wir'} @:{'words.generated.verwenden'} @:{'words.generated.diese'} @.upper:{'words.generated.e'}-@:{'words.generated.mail'}, @:{'words.generated.um'} @:{'words.generated.ihr'} @:{'words.generated.passwort'} @:{'words.generated.zur'}?ckzusetzen, @:{'words.generated.waschzertifikate'} @:{'words.generated.und'} @:{'words.generated.weitere'} wichtige @:{'words.generated.informationen'} @:{'words.generated.zu'} @:{'words.generated.senden'}."
|
||||
"email_desc": "@.capitalize:{'words.generated.wir'} @:{'words.generated.verwenden'} @:{'words.generated.diese'} @.upper:{'words.generated.e'}-@:{'words.generated.mail'}, @:{'words.generated.um'} @:{'words.generated.ihr'} @:{'words.generated.passwort'} @:{'words.generated.zur'}?ckzusetzen, @:{'words.generated.waschzertifikate'} @:{'words.generated.und'} @:{'words.generated.weitere'} wichtige @:{'words.generated.informationen'} @:{'words.generated.zu'} @:{'words.generated.senden'}.",
|
||||
"login_email_desc": "Wird zur Anmeldung und zum Zurücksetzen Ihres Passworts verwendet. Die Rechnungs-E-Mail in e-conomic wird dadurch nicht geändert.",
|
||||
"login_email_label": "Anmelde-E-Mail"
|
||||
},
|
||||
"title": "Benutzerprofil"
|
||||
},
|
||||
|
||||
@@ -6739,6 +6739,9 @@
|
||||
"account_name_desc": "@.capitalize:{'words.generated.customer'} @:{'words.generated.account'} @:{'words.generated.name'}",
|
||||
"account_number_desc": "@.capitalize:{'words.generated.customer'} @:{'words.generated.account'} @:{'words.generated.number'}",
|
||||
"description": "@.capitalize:{'words.generated.your'} @:{'words.generated.invoice'} @:{'words.generated.information'}",
|
||||
"invoice_email_desc": "Managed in e-conomic and not changed when you change your login email.",
|
||||
"invoice_email_label": "Invoice email (e-conomic)",
|
||||
"invoice_email_missing": "Not set in e-conomic",
|
||||
"title": "@.capitalize:{'words.generated.invoice'} @.capitalize:{'words.generated.information'}"
|
||||
},
|
||||
"microsoft_auth": {
|
||||
@@ -6766,7 +6769,9 @@
|
||||
},
|
||||
"security": {
|
||||
"description": "@.capitalize:{'words.generated.your'} @:{'words.generated.security'} @:{'words.generated.settings'}",
|
||||
"email_desc": "@.capitalize:{'words.generated.we'} @:{'words.generated.use'} @:{'words.generated.this'} @:{'words.generated.email'} @:{'words.generated.to'} @:{'words.generated.reset'} @:{'words.generated.your'} @:{'words.generated.password'}, @:{'words.generated.send'} @:{'words.generated.wash'} @:{'words.generated.certificates'} @:{'words.generated.and'} @:{'words.generated.other'} important @:{'words.generated.information'}."
|
||||
"email_desc": "@.capitalize:{'words.generated.we'} @:{'words.generated.use'} @:{'words.generated.this'} @:{'words.generated.email'} @:{'words.generated.to'} @:{'words.generated.reset'} @:{'words.generated.your'} @:{'words.generated.password'}, @:{'words.generated.send'} @:{'words.generated.wash'} @:{'words.generated.certificates'} @:{'words.generated.and'} @:{'words.generated.other'} important @:{'words.generated.information'}.",
|
||||
"login_email_desc": "Used to sign in and reset your password. This does not change the invoice email in e-conomic.",
|
||||
"login_email_label": "Login email"
|
||||
},
|
||||
"title": "@.capitalize:{'words.generated.user'} @.capitalize:{'words.generated.profile'}"
|
||||
},
|
||||
|
||||
@@ -7119,6 +7119,9 @@
|
||||
"account_name_desc": "@:{'templates.generated.compat.user_dashboard.profile.invoicing.account_name_desc'}",
|
||||
"account_number_desc": "@:{'templates.generated.compat.user_dashboard.profile.invoicing.account_number_desc'}",
|
||||
"description": "@:{'templates.generated.compat.user_dashboard.profile.invoicing.description'}",
|
||||
"invoice_email_desc": "@:{'templates.generated.compat.user_dashboard.profile.invoicing.invoice_email_desc'}",
|
||||
"invoice_email_label": "@:{'templates.generated.compat.user_dashboard.profile.invoicing.invoice_email_label'}",
|
||||
"invoice_email_missing": "@:{'templates.generated.compat.user_dashboard.profile.invoicing.invoice_email_missing'}",
|
||||
"title": "@:{'templates.generated.compat.user_dashboard.profile.invoicing.title'}"
|
||||
},
|
||||
"microsoft_auth": {
|
||||
@@ -7157,6 +7160,8 @@
|
||||
"edit_email": "@:{'templates.generated.compat.global.edit'}",
|
||||
"edit_phone": "@:{'templates.generated.compat.global.edit'}",
|
||||
"email_desc": "@:{'templates.generated.compat.user_dashboard.profile.security.email_desc'}",
|
||||
"login_email_desc": "@:{'templates.generated.compat.user_dashboard.profile.security.login_email_desc'}",
|
||||
"login_email_label": "@:{'templates.generated.compat.user_dashboard.profile.security.login_email_label'}",
|
||||
"logout": "@:common.logout",
|
||||
"password_label": "@:global.password",
|
||||
"title": "@:settings.security"
|
||||
|
||||
@@ -7021,6 +7021,9 @@
|
||||
"account_name_desc": "Kundekontonavn",
|
||||
"account_number_desc": "Kundekontonummer",
|
||||
"description": "@.capitalize:{'words.generated.din'} @:{'words.generated.fakturainformasjon'}",
|
||||
"invoice_email_desc": "Administreres i e-conomic og endres ikke når du endrer innloggings-e-posten din.",
|
||||
"invoice_email_label": "Faktura-e-post (e-conomic)",
|
||||
"invoice_email_missing": "Ikke angitt i e-conomic",
|
||||
"title": "@.capitalize:{'words.generated.fakturainformasjon'}"
|
||||
},
|
||||
"microsoft_auth": {
|
||||
@@ -7048,7 +7051,9 @@
|
||||
},
|
||||
"security": {
|
||||
"description": "Sikkerhetsinnstillingene @:{'words.generated.dine'}",
|
||||
"email_desc": "@.capitalize:{'words.generated.vi'} @:{'words.generated.bruker'} @:{'words.generated.denne'} @:{'words.generated.e'}-@:{'words.generated.posten'} @:{'words.generated.til'} @:{'words.generated.a'} tilbakestille @:{'words.generated.passordet'} @:{'words.generated.ditt'}, @:{'words.generated.sende'} @:{'words.generated.vaskesertifikater'} @:{'words.generated.og'} @:{'words.generated.annen'} viktig @:{'words.generated.informasjon'}."
|
||||
"email_desc": "@.capitalize:{'words.generated.vi'} @:{'words.generated.bruker'} @:{'words.generated.denne'} @:{'words.generated.e'}-@:{'words.generated.posten'} @:{'words.generated.til'} @:{'words.generated.a'} tilbakestille @:{'words.generated.passordet'} @:{'words.generated.ditt'}, @:{'words.generated.sende'} @:{'words.generated.vaskesertifikater'} @:{'words.generated.og'} @:{'words.generated.annen'} viktig @:{'words.generated.informasjon'}.",
|
||||
"login_email_desc": "Brukes til å logge inn og tilbakestille passordet ditt. Dette endrer ikke faktura-e-posten i e-conomic.",
|
||||
"login_email_label": "Innloggings-e-post"
|
||||
},
|
||||
"title": "Brukerprofil"
|
||||
},
|
||||
|
||||
@@ -7071,6 +7071,9 @@
|
||||
"account_name_desc": "@:{'words.generated.kundens'} kontonamn",
|
||||
"account_number_desc": "@:{'words.generated.kundens'} kontonummer",
|
||||
"description": "@.capitalize:{'words.generated.din'} @:{'words.generated.fakturainformation'}",
|
||||
"invoice_email_desc": "Hanteras i e-conomic och ändras inte när du ändrar din e-postadress för inloggning.",
|
||||
"invoice_email_label": "E-post för fakturor (e-conomic)",
|
||||
"invoice_email_missing": "Inte angiven i e-conomic",
|
||||
"title": "@.capitalize:{'words.generated.fakturainformation'}"
|
||||
},
|
||||
"microsoft_auth": {
|
||||
@@ -7098,7 +7101,9 @@
|
||||
},
|
||||
"security": {
|
||||
"description": "@.capitalize:{'words.generated.dina'} säkerhetsinställningar",
|
||||
"email_desc": "@.capitalize:{'words.generated.vi'} @:{'words.generated.anvander'} @:{'words.generated.denna'} @:{'words.generated.e'}-@:{'words.generated.post'} @:{'words.generated.for'} @:{'words.generated.att'} @:{'words.generated.aterstalla'} @:{'words.generated.ditt'} @:{'words.generated.losenord'}, @:{'words.generated.skicka'} @:{'words.generated.tvattcertifikat'} @:{'words.generated.och'} @:{'words.generated.annan'} viktig @:{'words.generated.information'}."
|
||||
"email_desc": "@.capitalize:{'words.generated.vi'} @:{'words.generated.anvander'} @:{'words.generated.denna'} @:{'words.generated.e'}-@:{'words.generated.post'} @:{'words.generated.for'} @:{'words.generated.att'} @:{'words.generated.aterstalla'} @:{'words.generated.ditt'} @:{'words.generated.losenord'}, @:{'words.generated.skicka'} @:{'words.generated.tvattcertifikat'} @:{'words.generated.och'} @:{'words.generated.annan'} viktig @:{'words.generated.information'}.",
|
||||
"login_email_desc": "Används för att logga in och återställa ditt lösenord. Detta ändrar inte e-postadressen för fakturor i e-conomic.",
|
||||
"login_email_label": "E-post för inloggning"
|
||||
},
|
||||
"title": "@.capitalize:{'words.generated.user'} @.capitalize:{'words.generated.profile'}"
|
||||
},
|
||||
|
||||
@@ -147,6 +147,9 @@
|
||||
"account_name_desc": "@:{'terms.glossary.kundekonto'} @:{'terms.glossary.navn'}",
|
||||
"account_number_desc": "@:{'terms.glossary.kundekonto'} @:{'terms.glossary.nummer'}",
|
||||
"description": "@.capitalize:{'terms.glossary.dine'} @:{'terms.glossary.fakturaoplysninger'}",
|
||||
"invoice_email_desc": "Administreres i e-conomic og ændres ikke, når du ændrer din login-e-mail.",
|
||||
"invoice_email_label": "Faktura-e-mail (e-conomic)",
|
||||
"invoice_email_missing": "Ikke angivet i e-conomic",
|
||||
"title": "@.capitalize:{'terms.glossary.fakturaoplysninger'}"
|
||||
},
|
||||
"microsoft_auth": {
|
||||
@@ -174,7 +177,9 @@
|
||||
},
|
||||
"security": {
|
||||
"description": "@.capitalize:{'terms.glossary.dine'} sikkerhedsindstillinger",
|
||||
"email_desc": "@.capitalize:{'terms.glossary.vi'} @:{'terms.glossary.bruger'} @:{'terms.glossary.denne'} @:{'terms.glossary.e'}-@:{'terms.glossary.mail'} @:{'terms.glossary.til'} @:{'terms.glossary.at'} nulstille @:{'terms.glossary.din'} @:{'terms.glossary.adgangskode'}, fremsende @:{'terms.glossary.vaskecertifikater'} @:{'terms.glossary.og'} @:{'terms.glossary.andre'} vigtige @:{'terms.glossary.oplysninger'}."
|
||||
"email_desc": "@.capitalize:{'terms.glossary.vi'} @:{'terms.glossary.bruger'} @:{'terms.glossary.denne'} @:{'terms.glossary.e'}-@:{'terms.glossary.mail'} @:{'terms.glossary.til'} @:{'terms.glossary.at'} nulstille @:{'terms.glossary.din'} @:{'terms.glossary.adgangskode'}, fremsende @:{'terms.glossary.vaskecertifikater'} @:{'terms.glossary.og'} @:{'terms.glossary.andre'} vigtige @:{'terms.glossary.oplysninger'}.",
|
||||
"login_email_desc": "Bruges til at logge ind og nulstille din adgangskode. Dette ændrer ikke faktura-e-mailen i e-conomic.",
|
||||
"login_email_label": "Login-e-mail"
|
||||
},
|
||||
"title": "@.capitalize:{'terms.glossary.brugerprofil'}"
|
||||
},
|
||||
|
||||
@@ -140,6 +140,9 @@
|
||||
"account_name_desc": "Kundenkontoname",
|
||||
"account_number_desc": "Kundenkontonummer",
|
||||
"description": "@.capitalize:{'terms.glossary.ihre'} @:{'terms.glossary.rechnungsinformationen'}",
|
||||
"invoice_email_desc": "Wird in e-conomic verwaltet und nicht geändert, wenn Sie Ihre Anmelde-E-Mail ändern.",
|
||||
"invoice_email_label": "Rechnungs-E-Mail (e-conomic)",
|
||||
"invoice_email_missing": "Nicht in e-conomic hinterlegt",
|
||||
"title": "@:{'terms.glossary.rechnungsinformationen'}"
|
||||
},
|
||||
"microsoft_auth": {
|
||||
@@ -167,7 +170,9 @@
|
||||
},
|
||||
"security": {
|
||||
"description": "@.capitalize:{'terms.glossary.ihre'} Sicherheitseinstellungen",
|
||||
"email_desc": "@.capitalize:{'terms.glossary.wir'} @:{'terms.glossary.verwenden'} @:{'terms.glossary.diese'} @.upper:{'terms.glossary.e'}-@:{'terms.glossary.mail'}, @:{'terms.glossary.um'} @:{'terms.glossary.ihr'} @:{'terms.glossary.passwort'} @:{'terms.glossary.zur'}?ckzusetzen, @:{'terms.glossary.waschzertifikate'} @:{'terms.glossary.und'} @:{'terms.glossary.weitere'} wichtige @:{'terms.glossary.informationen'} @:{'terms.glossary.zu'} @:{'terms.glossary.senden'}."
|
||||
"email_desc": "@.capitalize:{'terms.glossary.wir'} @:{'terms.glossary.verwenden'} @:{'terms.glossary.diese'} @.upper:{'terms.glossary.e'}-@:{'terms.glossary.mail'}, @:{'terms.glossary.um'} @:{'terms.glossary.ihr'} @:{'terms.glossary.passwort'} @:{'terms.glossary.zur'}?ckzusetzen, @:{'terms.glossary.waschzertifikate'} @:{'terms.glossary.und'} @:{'terms.glossary.weitere'} wichtige @:{'terms.glossary.informationen'} @:{'terms.glossary.zu'} @:{'terms.glossary.senden'}.",
|
||||
"login_email_desc": "Wird zur Anmeldung und zum Zurücksetzen Ihres Passworts verwendet. Die Rechnungs-E-Mail in e-conomic wird dadurch nicht geändert.",
|
||||
"login_email_label": "Anmelde-E-Mail"
|
||||
},
|
||||
"title": "Benutzerprofil"
|
||||
},
|
||||
|
||||
@@ -147,6 +147,9 @@
|
||||
"account_name_desc": "@.capitalize:{'terms.glossary.customer'} @:{'terms.glossary.account'} @:{'terms.glossary.name'}",
|
||||
"account_number_desc": "@.capitalize:{'terms.glossary.customer'} @:{'terms.glossary.account'} @:{'terms.glossary.number'}",
|
||||
"description": "@.capitalize:{'terms.glossary.your'} @:{'terms.glossary.invoice'} @:{'terms.glossary.information'}",
|
||||
"invoice_email_desc": "Managed in e-conomic and not changed when you change your login email.",
|
||||
"invoice_email_label": "Invoice email (e-conomic)",
|
||||
"invoice_email_missing": "Not set in e-conomic",
|
||||
"title": "@.capitalize:{'terms.glossary.invoice'} @.capitalize:{'terms.glossary.information'}"
|
||||
},
|
||||
"microsoft_auth": {
|
||||
@@ -174,7 +177,9 @@
|
||||
},
|
||||
"security": {
|
||||
"description": "@.capitalize:{'terms.glossary.your'} @:{'terms.glossary.security'} @:{'terms.glossary.settings'}",
|
||||
"email_desc": "@.capitalize:{'terms.glossary.we'} @:{'terms.glossary.use'} @:{'terms.glossary.this'} @:{'terms.glossary.email'} @:{'terms.glossary.to'} @:{'terms.glossary.reset'} @:{'terms.glossary.your'} @:{'terms.glossary.password'}, @:{'terms.glossary.send'} @:{'terms.glossary.wash'} @:{'terms.glossary.certificates'} @:{'terms.glossary.and'} @:{'terms.glossary.other'} important @:{'terms.glossary.information'}."
|
||||
"email_desc": "@.capitalize:{'terms.glossary.we'} @:{'terms.glossary.use'} @:{'terms.glossary.this'} @:{'terms.glossary.email'} @:{'terms.glossary.to'} @:{'terms.glossary.reset'} @:{'terms.glossary.your'} @:{'terms.glossary.password'}, @:{'terms.glossary.send'} @:{'terms.glossary.wash'} @:{'terms.glossary.certificates'} @:{'terms.glossary.and'} @:{'terms.glossary.other'} important @:{'terms.glossary.information'}.",
|
||||
"login_email_desc": "Used to sign in and reset your password. This does not change the invoice email in e-conomic.",
|
||||
"login_email_label": "Login email"
|
||||
},
|
||||
"title": "@.capitalize:{'terms.glossary.user'} @.capitalize:{'terms.glossary.profile'}"
|
||||
},
|
||||
|
||||
@@ -184,6 +184,9 @@
|
||||
"account_name_desc": "@:{'phrases.compat.user_dashboard.profile.invoicing.account_name_desc'}",
|
||||
"account_number_desc": "@:{'phrases.compat.user_dashboard.profile.invoicing.account_number_desc'}",
|
||||
"description": "@:{'phrases.compat.user_dashboard.profile.invoicing.description'}",
|
||||
"invoice_email_desc": "@:{'phrases.compat.user_dashboard.profile.invoicing.invoice_email_desc'}",
|
||||
"invoice_email_label": "@:{'phrases.compat.user_dashboard.profile.invoicing.invoice_email_label'}",
|
||||
"invoice_email_missing": "@:{'phrases.compat.user_dashboard.profile.invoicing.invoice_email_missing'}",
|
||||
"title": "@:{'phrases.compat.user_dashboard.profile.invoicing.title'}"
|
||||
},
|
||||
"microsoft_auth": {
|
||||
@@ -222,6 +225,8 @@
|
||||
"edit_email": "@:{'phrases.compat.global.edit'}",
|
||||
"edit_phone": "@:{'phrases.compat.global.edit'}",
|
||||
"email_desc": "@:{'phrases.compat.user_dashboard.profile.security.email_desc'}",
|
||||
"login_email_desc": "@:{'phrases.compat.user_dashboard.profile.security.login_email_desc'}",
|
||||
"login_email_label": "@:{'phrases.compat.user_dashboard.profile.security.login_email_label'}",
|
||||
"logout": "@:common.logout",
|
||||
"password_label": "@:global.password",
|
||||
"title": "@:settings.security"
|
||||
|
||||
@@ -140,6 +140,9 @@
|
||||
"account_name_desc": "Kundekontonavn",
|
||||
"account_number_desc": "Kundekontonummer",
|
||||
"description": "@.capitalize:{'terms.glossary.din'} @:{'terms.glossary.fakturainformasjon'}",
|
||||
"invoice_email_desc": "Administreres i e-conomic og endres ikke når du endrer innloggings-e-posten din.",
|
||||
"invoice_email_label": "Faktura-e-post (e-conomic)",
|
||||
"invoice_email_missing": "Ikke angitt i e-conomic",
|
||||
"title": "@.capitalize:{'terms.glossary.fakturainformasjon'}"
|
||||
},
|
||||
"microsoft_auth": {
|
||||
@@ -167,7 +170,9 @@
|
||||
},
|
||||
"security": {
|
||||
"description": "Sikkerhetsinnstillingene @:{'terms.glossary.dine'}",
|
||||
"email_desc": "@.capitalize:{'terms.glossary.vi'} @:{'terms.glossary.bruker'} @:{'terms.glossary.denne'} @:{'terms.glossary.e'}-@:{'terms.glossary.posten'} @:{'terms.glossary.til'} @:{'terms.glossary.a'} tilbakestille @:{'terms.glossary.passordet'} @:{'terms.glossary.ditt'}, @:{'terms.glossary.sende'} @:{'terms.glossary.vaskesertifikater'} @:{'terms.glossary.og'} @:{'terms.glossary.annen'} viktig @:{'terms.glossary.informasjon'}."
|
||||
"email_desc": "@.capitalize:{'terms.glossary.vi'} @:{'terms.glossary.bruker'} @:{'terms.glossary.denne'} @:{'terms.glossary.e'}-@:{'terms.glossary.posten'} @:{'terms.glossary.til'} @:{'terms.glossary.a'} tilbakestille @:{'terms.glossary.passordet'} @:{'terms.glossary.ditt'}, @:{'terms.glossary.sende'} @:{'terms.glossary.vaskesertifikater'} @:{'terms.glossary.og'} @:{'terms.glossary.annen'} viktig @:{'terms.glossary.informasjon'}.",
|
||||
"login_email_desc": "Brukes til å logge inn og tilbakestille passordet ditt. Dette endrer ikke faktura-e-posten i e-conomic.",
|
||||
"login_email_label": "Innloggings-e-post"
|
||||
},
|
||||
"title": "Brukerprofil"
|
||||
},
|
||||
|
||||
@@ -140,6 +140,9 @@
|
||||
"account_name_desc": "@:{'terms.glossary.kundens'} kontonamn",
|
||||
"account_number_desc": "@:{'terms.glossary.kundens'} kontonummer",
|
||||
"description": "@.capitalize:{'terms.glossary.din'} @:{'terms.glossary.fakturainformation'}",
|
||||
"invoice_email_desc": "Hanteras i e-conomic och ändras inte när du ändrar din e-postadress för inloggning.",
|
||||
"invoice_email_label": "E-post för fakturor (e-conomic)",
|
||||
"invoice_email_missing": "Inte angiven i e-conomic",
|
||||
"title": "@.capitalize:{'terms.glossary.fakturainformation'}"
|
||||
},
|
||||
"microsoft_auth": {
|
||||
@@ -167,7 +170,9 @@
|
||||
},
|
||||
"security": {
|
||||
"description": "@.capitalize:{'terms.glossary.dina'} säkerhetsinställningar",
|
||||
"email_desc": "@.capitalize:{'terms.glossary.vi'} @:{'terms.glossary.anvander'} @:{'terms.glossary.denna'} @:{'terms.glossary.e'}-@:{'terms.glossary.post'} @:{'terms.glossary.for'} @:{'terms.glossary.att'} @:{'terms.glossary.aterstalla'} @:{'terms.glossary.ditt'} @:{'terms.glossary.losenord'}, @:{'terms.glossary.skicka'} @:{'terms.glossary.tvattcertifikat'} @:{'terms.glossary.och'} @:{'terms.glossary.annan'} viktig @:{'terms.glossary.information'}."
|
||||
"email_desc": "@.capitalize:{'terms.glossary.vi'} @:{'terms.glossary.anvander'} @:{'terms.glossary.denna'} @:{'terms.glossary.e'}-@:{'terms.glossary.post'} @:{'terms.glossary.for'} @:{'terms.glossary.att'} @:{'terms.glossary.aterstalla'} @:{'terms.glossary.ditt'} @:{'terms.glossary.losenord'}, @:{'terms.glossary.skicka'} @:{'terms.glossary.tvattcertifikat'} @:{'terms.glossary.och'} @:{'terms.glossary.annan'} viktig @:{'terms.glossary.information'}.",
|
||||
"login_email_desc": "Används för att logga in och återställa ditt lösenord. Detta ändrar inte e-postadressen för fakturor i e-conomic.",
|
||||
"login_email_label": "E-post för inloggning"
|
||||
},
|
||||
"title": "@.capitalize:{'terms.glossary.user'} @.capitalize:{'terms.glossary.profile'}"
|
||||
},
|
||||
|
||||
@@ -21,6 +21,7 @@ import { isAccountDeletionEligible } from "@/services/accountDeletion.js";
|
||||
|
||||
const { t } = useI18n();
|
||||
const isLoading = ref(false);
|
||||
const isSavingEmail = ref(false);
|
||||
const canRequestAccountDeletion = computed(
|
||||
() =>
|
||||
!SessionUser.hasSuperUserToken() &&
|
||||
@@ -197,115 +198,98 @@ const onClickVerifySubuserContact = async (channel) => {
|
||||
};
|
||||
/** Email */
|
||||
const onClickSaveEmail = async () => {
|
||||
// Get the password from Swal
|
||||
await Swal.fire({
|
||||
const passwordResult = await Swal.fire({
|
||||
title: t("profile.email.enter_password"),
|
||||
input: "password",
|
||||
inputPlaceholder: t("auth.password"),
|
||||
showCancelButton: true,
|
||||
preConfirm: () => {
|
||||
const value = Swal.getInput().value;
|
||||
if (!value) {
|
||||
preConfirm: async (password) => {
|
||||
if (!password) {
|
||||
Swal.showValidationMessage(t("profile.email.password_prompt"));
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await SessionUser.request("/account/security/validate-password", "POST", {
|
||||
password,
|
||||
});
|
||||
|
||||
if (response.status !== 200) {
|
||||
Swal.showValidationMessage(t("profile.error.validation_error"));
|
||||
return false;
|
||||
}
|
||||
|
||||
return password;
|
||||
} catch (error) {
|
||||
Swal.showValidationMessage(SessionUser.functions.parseErrorMessage(error));
|
||||
return false;
|
||||
}
|
||||
Swal.showLoading();
|
||||
return value;
|
||||
},
|
||||
inputAttributes: {
|
||||
"aria-label": t("auth.password"),
|
||||
},
|
||||
inputValidator: async (value) => {
|
||||
if (!value) {
|
||||
return t("profile.email.password_prompt");
|
||||
}
|
||||
// Validate the password
|
||||
await SessionUser.request("/account/security/validate-password", "POST", {
|
||||
password: value,
|
||||
})
|
||||
.then((result) => {
|
||||
if (result.status === 200) {
|
||||
// Show the email input dialog
|
||||
onSaveEmail(value);
|
||||
} else {
|
||||
Swal.fire({
|
||||
title: t("common.error"),
|
||||
text: t("profile.error.validation_error"),
|
||||
icon: "error",
|
||||
});
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
Swal.fire({
|
||||
title: t("common.error"),
|
||||
text: SessionUser.functions.parseErrorMessage(error),
|
||||
icon: "error",
|
||||
});
|
||||
})
|
||||
.finally(() => {
|
||||
isLoading.value = false;
|
||||
});
|
||||
},
|
||||
allowOutsideClick: () => !Swal.isLoading(),
|
||||
showLoaderOnConfirm: true,
|
||||
});
|
||||
|
||||
if (passwordResult.isConfirmed) {
|
||||
await onSaveEmail(passwordResult.value);
|
||||
}
|
||||
};
|
||||
const onSaveEmail = async (password) => {
|
||||
// Show the confirmation dialog
|
||||
await Swal.fire({
|
||||
const emailResult = await Swal.fire({
|
||||
title: t("profile.email.new_email_prompt"),
|
||||
text: t("profile.email.new_email_text"),
|
||||
icon: "warning",
|
||||
input: "text",
|
||||
inputLabel: t("profile.email.label"),
|
||||
showCancelButton: true,
|
||||
preConfirm: () => {
|
||||
const value = Swal.getInput().value;
|
||||
if (!value) {
|
||||
preConfirm: async (value) => {
|
||||
const email = String(value || "").trim();
|
||||
if (!email) {
|
||||
Swal.showValidationMessage(t("profile.email.enter_email"));
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
// Validate the email address
|
||||
|
||||
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
||||
if (!emailRegex.test(value)) {
|
||||
if (!emailRegex.test(email)) {
|
||||
Swal.showValidationMessage(t("profile.email.invalid_email"));
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
isLoading.value = true;
|
||||
Swal.showLoading();
|
||||
SessionUser.request("/account/security/change-email", "POST", {
|
||||
email: value,
|
||||
password: password,
|
||||
})
|
||||
.then((result) => {
|
||||
if (result.status === 200) {
|
||||
Swal.fire({
|
||||
title: t("profile.email.saved"),
|
||||
text: t("profile.email.saved_text"),
|
||||
icon: "success",
|
||||
});
|
||||
SessionUser.getSessionData();
|
||||
} else {
|
||||
Swal.fire({
|
||||
title: t("common.error"),
|
||||
text: t("profile.error.save_email_error"),
|
||||
icon: "error",
|
||||
});
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
Swal.fire({
|
||||
title: t("common.error"),
|
||||
text: SessionUser.functions.parseErrorMessage(error),
|
||||
icon: "error",
|
||||
});
|
||||
// Reset the password
|
||||
})
|
||||
.finally(() => {
|
||||
isLoading.value = false;
|
||||
|
||||
isSavingEmail.value = true;
|
||||
try {
|
||||
const response = await SessionUser.request("/account/security/change-email", "POST", {
|
||||
email,
|
||||
password,
|
||||
});
|
||||
|
||||
if (response.status !== 200) {
|
||||
Swal.showValidationMessage(t("profile.error.save_email_error"));
|
||||
return false;
|
||||
}
|
||||
|
||||
const savedEmail = response?.data?.data?.email || response?.data?.email || email;
|
||||
SessionUser.user.email.value = savedEmail;
|
||||
return savedEmail;
|
||||
} catch (error) {
|
||||
Swal.showValidationMessage(SessionUser.functions.parseErrorMessage(error));
|
||||
return false;
|
||||
} finally {
|
||||
isSavingEmail.value = false;
|
||||
}
|
||||
},
|
||||
allowOutsideClick: () => !Swal.isLoading(),
|
||||
showLoaderOnConfirm: true,
|
||||
});
|
||||
|
||||
if (emailResult.isConfirmed) {
|
||||
await Swal.fire({
|
||||
title: t("profile.email.saved"),
|
||||
text: t("profile.email.saved_text"),
|
||||
icon: "success",
|
||||
});
|
||||
}
|
||||
};
|
||||
/** Default department */
|
||||
const defaultDepartment = ref(null);
|
||||
@@ -732,6 +716,7 @@ const onClickSaveWashCertificateEmail = async () => {
|
||||
:title="$t('user_dashboard.profile.invoicing.title')"
|
||||
:description="$t('user_dashboard.profile.invoicing.description')"
|
||||
icon="fas fa-user"
|
||||
data-testid="user-profile-invoicing-card"
|
||||
>
|
||||
<!-- Konto navn -->
|
||||
<ConfigurationInput
|
||||
@@ -748,6 +733,15 @@ const onClickSaveWashCertificateEmail = async () => {
|
||||
:value="SessionUser.user.customer_number"
|
||||
:disabled="true"
|
||||
/>
|
||||
<ConfigurationInput
|
||||
class="mt-4"
|
||||
:title="$t('user_dashboard.profile.invoicing.invoice_email_label')"
|
||||
:description="$t('user_dashboard.profile.invoicing.invoice_email_desc')"
|
||||
:value="SessionUser.economicData.email.value || $t('user_dashboard.profile.invoicing.invoice_email_missing')"
|
||||
:disabled="true"
|
||||
:show-empty-warning="false"
|
||||
data-testid="user-profile-invoice-email"
|
||||
/>
|
||||
</ConfigurationCategory>
|
||||
|
||||
<!-- Security -->
|
||||
@@ -763,16 +757,18 @@ const onClickSaveWashCertificateEmail = async () => {
|
||||
<div class="columns is-desktop is-align-items-flex-end mb-2">
|
||||
<div class="column">
|
||||
<ConfigurationInput
|
||||
:title="SessionUser.objects.global.language.email"
|
||||
:title="$t('user_dashboard.profile.security.login_email_label')"
|
||||
:description="$t('user_dashboard.profile.security.login_email_desc')"
|
||||
:value="SessionUser.user.email"
|
||||
:disabled="true"
|
||||
data-testid="user-profile-login-email"
|
||||
/>
|
||||
</div>
|
||||
<div class="column is-narrow">
|
||||
<button
|
||||
class="button is-link is-fullwidth-mobile mb-1 is-fullwidth"
|
||||
@click="onClickSaveEmail"
|
||||
:disabled="isLoading"
|
||||
:disabled="isLoading || isSavingEmail"
|
||||
data-testid="user-profile-security-edit-email"
|
||||
>
|
||||
<span class="icon is-small"><i class="fas fa-edit"></i></span>
|
||||
|
||||
@@ -1,6 +1,92 @@
|
||||
import { expect, test } from "@playwright/test";
|
||||
import { expect, test, type Page } from "@playwright/test";
|
||||
import { loginAsUser } from "./fixtures";
|
||||
|
||||
type ProfileEmailSession = {
|
||||
loginEmail: string;
|
||||
invoiceEmail?: string | null;
|
||||
};
|
||||
|
||||
const buildProfileSession = ({ loginEmail, invoiceEmail }: ProfileEmailSession) => ({
|
||||
id: 1,
|
||||
customer_number: 12345679,
|
||||
group_id: 1,
|
||||
email: loginEmail,
|
||||
phone: {
|
||||
number: "12345678",
|
||||
country_code: 45,
|
||||
},
|
||||
notifications: {
|
||||
wash_certificate_email: null,
|
||||
email_notifications_enabled: true,
|
||||
sms_notifications_enabled: false,
|
||||
superuser_new_customer_email_notifications_enabled: false,
|
||||
},
|
||||
created_at: "2026-01-01T00:00:00.000Z",
|
||||
updated_at: "2026-01-01T00:00:00.000Z",
|
||||
display_name: "E2E User",
|
||||
permissions: ["user"],
|
||||
economic_customer: invoiceEmail
|
||||
? {
|
||||
customerNumber: 12345679,
|
||||
name: "E2E User",
|
||||
address: "Test Street 1",
|
||||
zip: "1000",
|
||||
city: "Copenhagen",
|
||||
mobilePhone: "12345678",
|
||||
email: invoiceEmail,
|
||||
corporateIdentificationNumber: "12345678",
|
||||
currency: "DKK",
|
||||
country: "DK",
|
||||
}
|
||||
: [],
|
||||
runtime_config: {
|
||||
economic: {
|
||||
transaction_draft_customer_number: null,
|
||||
default_distribution_department_id: null,
|
||||
},
|
||||
release: {},
|
||||
},
|
||||
});
|
||||
|
||||
async function openUserProfileWithEmails(page: Page, session: ProfileEmailSession) {
|
||||
await loginAsUser(page);
|
||||
|
||||
let sessionRequestCount = 0;
|
||||
await page.route("**/auth/session", async (route) => {
|
||||
sessionRequestCount += 1;
|
||||
await route.fulfill({
|
||||
status: 200,
|
||||
contentType: "application/json",
|
||||
body: JSON.stringify({ data: buildProfileSession(session) }),
|
||||
});
|
||||
});
|
||||
|
||||
await page.goto("/user/profile");
|
||||
const invoicingCard = page.getByTestId("user-profile-invoicing-card");
|
||||
const securityCard = page.getByTestId("user-profile-security-card");
|
||||
await expect(invoicingCard).toBeVisible();
|
||||
await expect(securityCard).toBeVisible();
|
||||
await invoicingCard.locator(".card-header").click();
|
||||
await securityCard.locator(".card-header").click();
|
||||
await expect(page.getByTestId("user-profile-login-email")).toBeVisible();
|
||||
await expect(page.getByTestId("user-profile-invoice-email")).toBeVisible();
|
||||
|
||||
return {
|
||||
getSessionRequestCount: () => sessionRequestCount,
|
||||
};
|
||||
}
|
||||
|
||||
const emailValue = (page: Page, testId: string) => page.getByTestId(testId).locator("input");
|
||||
|
||||
async function completePasswordStep(page: Page, password = "valid-password") {
|
||||
await page.getByTestId("user-profile-security-edit-email").click();
|
||||
const popup = page.locator(".swal2-popup");
|
||||
await expect(popup).toBeVisible();
|
||||
await popup.locator(".swal2-input").fill(password);
|
||||
await popup.locator(".swal2-confirm").click();
|
||||
await expect(popup.locator(".swal2-input")).toHaveAttribute("type", "text");
|
||||
}
|
||||
|
||||
async function openUserSecurity(page) {
|
||||
await loginAsUser(page);
|
||||
await page.goto("/user/profile");
|
||||
@@ -44,6 +130,153 @@ test("[PROFILE][User][Security] renders the current security surface", async ({
|
||||
await expect(page.getByTestId("subuser-profile-security-logout")).toHaveCount(0);
|
||||
});
|
||||
|
||||
test("[PROFILE][User][Security] shows exact login and invoice emails under distinct labels", async ({ page }) => {
|
||||
await openUserProfileWithEmails(page, {
|
||||
loginEmail: "k.sand@example.test",
|
||||
invoiceEmail: "billing+wash@example.test",
|
||||
});
|
||||
|
||||
const loginEmail = page.getByTestId("user-profile-login-email");
|
||||
const invoiceEmail = page.getByTestId("user-profile-invoice-email");
|
||||
const loginLabel = (await loginEmail.locator("label").innerText()).trim();
|
||||
const invoiceLabel = (await invoiceEmail.locator("label").innerText()).trim();
|
||||
expect(loginLabel).not.toBe("");
|
||||
expect(invoiceLabel).not.toBe("");
|
||||
expect(loginLabel).not.toBe(invoiceLabel);
|
||||
await expect(page.getByRole("textbox", { name: loginLabel, exact: true })).toHaveValue("k.sand@example.test");
|
||||
await expect(page.getByRole("textbox", { name: invoiceLabel, exact: true })).toHaveValue("billing+wash@example.test");
|
||||
await expect(emailValue(page, "user-profile-login-email")).toHaveValue("k.sand@example.test");
|
||||
await expect(emailValue(page, "user-profile-invoice-email")).toHaveValue("billing+wash@example.test");
|
||||
|
||||
for (const field of [loginEmail, invoiceEmail]) {
|
||||
const bounds = await field.boundingBox();
|
||||
const viewport = page.viewportSize();
|
||||
expect(bounds).not.toBeNull();
|
||||
expect(viewport).not.toBeNull();
|
||||
expect(bounds!.x).toBeGreaterThanOrEqual(0);
|
||||
expect(bounds!.x + bounds!.width).toBeLessThanOrEqual(viewport!.width + 1);
|
||||
}
|
||||
});
|
||||
|
||||
test("[PROFILE][User][Security] keeps equal login and invoice emails as separate fields", async ({ page }) => {
|
||||
await openUserProfileWithEmails(page, {
|
||||
loginEmail: "same.address@example.test",
|
||||
invoiceEmail: "same.address@example.test",
|
||||
});
|
||||
|
||||
await expect(emailValue(page, "user-profile-login-email")).toHaveValue("same.address@example.test");
|
||||
await expect(emailValue(page, "user-profile-invoice-email")).toHaveValue("same.address@example.test");
|
||||
await expect(page.getByTestId("user-profile-login-email").locator("label")).not.toHaveText("");
|
||||
await expect(page.getByTestId("user-profile-invoice-email").locator("label")).not.toHaveText("");
|
||||
});
|
||||
|
||||
test("[PROFILE][User][Security] shows a neutral state when the invoice email is missing", async ({ page }) => {
|
||||
await openUserProfileWithEmails(page, {
|
||||
loginEmail: "k.sand@example.test",
|
||||
invoiceEmail: null,
|
||||
});
|
||||
|
||||
const invoiceEmail = page.getByTestId("user-profile-invoice-email");
|
||||
await expect(emailValue(page, "user-profile-invoice-email")).toHaveValue(/e-conomic/i);
|
||||
await expect(invoiceEmail.locator(".message.is-warning")).toHaveCount(0);
|
||||
});
|
||||
|
||||
test("[PROFILE][User][Security] applies the confirmed login email without changing invoice email or refetching session", async ({
|
||||
page,
|
||||
}) => {
|
||||
const profile = await openUserProfileWithEmails(page, {
|
||||
loginEmail: "old.login@example.test",
|
||||
invoiceEmail: "invoice@example.test",
|
||||
});
|
||||
const sessionRequestsBeforeSave = profile.getSessionRequestCount();
|
||||
let changeEmailPayload: Record<string, unknown> | null = null;
|
||||
|
||||
await page.route("**/account/security/validate-password", async (route) => {
|
||||
await route.fulfill({
|
||||
status: 200,
|
||||
contentType: "application/json",
|
||||
body: JSON.stringify({ data: { valid: true } }),
|
||||
});
|
||||
});
|
||||
await page.route("**/account/security/change-email", async (route) => {
|
||||
changeEmailPayload = route.request().postDataJSON();
|
||||
await route.fulfill({
|
||||
status: 200,
|
||||
contentType: "application/json",
|
||||
body: JSON.stringify({ data: { message: "Email changed", email: "k.sand@example.test" } }),
|
||||
});
|
||||
});
|
||||
|
||||
await completePasswordStep(page);
|
||||
const popup = page.locator(".swal2-popup");
|
||||
await popup.locator(".swal2-input").fill("K.Sand@example.test");
|
||||
await popup.locator(".swal2-confirm").click();
|
||||
|
||||
await expect(emailValue(page, "user-profile-login-email")).toHaveValue("k.sand@example.test");
|
||||
await expect(emailValue(page, "user-profile-invoice-email")).toHaveValue("invoice@example.test");
|
||||
expect(changeEmailPayload).toEqual({ email: "K.Sand@example.test", password: "valid-password" });
|
||||
expect(profile.getSessionRequestCount()).toBe(sessionRequestsBeforeSave);
|
||||
});
|
||||
|
||||
test("[PROFILE][User][Security] falls back to the submitted email for an older success response", async ({ page }) => {
|
||||
await openUserProfileWithEmails(page, {
|
||||
loginEmail: "old.login@example.test",
|
||||
invoiceEmail: "invoice@example.test",
|
||||
});
|
||||
await page.route("**/account/security/validate-password", async (route) => {
|
||||
await route.fulfill({
|
||||
status: 200,
|
||||
contentType: "application/json",
|
||||
body: JSON.stringify({ data: { valid: true } }),
|
||||
});
|
||||
});
|
||||
await page.route("**/account/security/change-email", async (route) => {
|
||||
await route.fulfill({
|
||||
status: 200,
|
||||
contentType: "application/json",
|
||||
body: JSON.stringify({ data: { message: "Email changed" } }),
|
||||
});
|
||||
});
|
||||
|
||||
await completePasswordStep(page);
|
||||
const popup = page.locator(".swal2-popup");
|
||||
await popup.locator(".swal2-input").fill("fallback.address@example.test");
|
||||
await popup.locator(".swal2-confirm").click();
|
||||
|
||||
await expect(emailValue(page, "user-profile-login-email")).toHaveValue("fallback.address@example.test");
|
||||
await expect(emailValue(page, "user-profile-invoice-email")).toHaveValue("invoice@example.test");
|
||||
});
|
||||
|
||||
test("[PROFILE][User][Security] leaves both emails unchanged when saving fails", async ({ page }) => {
|
||||
await openUserProfileWithEmails(page, {
|
||||
loginEmail: "old.login@example.test",
|
||||
invoiceEmail: "invoice@example.test",
|
||||
});
|
||||
await page.route("**/account/security/validate-password", async (route) => {
|
||||
await route.fulfill({
|
||||
status: 200,
|
||||
contentType: "application/json",
|
||||
body: JSON.stringify({ data: { valid: true } }),
|
||||
});
|
||||
});
|
||||
await page.route("**/account/security/change-email", async (route) => {
|
||||
await route.fulfill({
|
||||
status: 422,
|
||||
contentType: "application/json",
|
||||
body: JSON.stringify({ message: "Email is already in use" }),
|
||||
});
|
||||
});
|
||||
|
||||
await completePasswordStep(page);
|
||||
const popup = page.locator(".swal2-popup");
|
||||
await popup.locator(".swal2-input").fill("duplicate@example.test");
|
||||
await popup.locator(".swal2-confirm").click();
|
||||
|
||||
await expect(popup.locator(".swal2-validation-message")).toBeVisible();
|
||||
await expect(emailValue(page, "user-profile-login-email")).toHaveValue("old.login@example.test");
|
||||
await expect(emailValue(page, "user-profile-invoice-email")).toHaveValue("invoice@example.test");
|
||||
});
|
||||
|
||||
test("[PROFILE][User][Security] opens the logout confirmation dialog", async ({ page }) => {
|
||||
await openUserSecurity(page);
|
||||
|
||||
|
||||
@@ -183,6 +183,51 @@ describe("session bootstrap failure handling", () => {
|
||||
expect(mocks.loginRedirect).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it("clears stale economic data when a refreshed session has no economic customer", async () => {
|
||||
seedStoredSession("customer-session-token");
|
||||
SessionUser.economicData.customerNumber.value = 12345679;
|
||||
SessionUser.economicData.name.value = "Stale Customer";
|
||||
SessionUser.economicData.address.value = "Old Street 1";
|
||||
SessionUser.economicData.zip.value = "1000";
|
||||
SessionUser.economicData.city.value = "Copenhagen";
|
||||
SessionUser.economicData.mobilePhone.value = "12345678";
|
||||
SessionUser.economicData.email.value = "stale.invoice@example.test";
|
||||
SessionUser.economicData.cvr.value = "12345678";
|
||||
SessionUser.economicData.currency.value = "DKK";
|
||||
SessionUser.economicData.country.value = "DK";
|
||||
SessionUser.economicData.cached_at.value = new Date();
|
||||
mocks.authenticatedRequest.mockResolvedValueOnce({
|
||||
data: {
|
||||
data: {
|
||||
id: 1,
|
||||
customer_number: 12345679,
|
||||
group_id: 1,
|
||||
email: "login@example.test",
|
||||
phone: { number: "12345678", country_code: 45 },
|
||||
notifications: {},
|
||||
display_name: "Customer",
|
||||
permissions: ["user"],
|
||||
economic_customer: null,
|
||||
runtime_config: { economic: {}, release: {} },
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
await getSessionData();
|
||||
|
||||
expect(SessionUser.economicData.customerNumber.value).toBeNull();
|
||||
expect(SessionUser.economicData.name.value).toBeNull();
|
||||
expect(SessionUser.economicData.address.value).toBeNull();
|
||||
expect(SessionUser.economicData.zip.value).toBeNull();
|
||||
expect(SessionUser.economicData.city.value).toBeNull();
|
||||
expect(SessionUser.economicData.mobilePhone.value).toBeNull();
|
||||
expect(SessionUser.economicData.email.value).toBeNull();
|
||||
expect(SessionUser.economicData.cvr.value).toBeNull();
|
||||
expect(SessionUser.economicData.currency.value).toBeNull();
|
||||
expect(SessionUser.economicData.country.value).toBeNull();
|
||||
expect(SessionUser.economicData.cached_at.value).toBeNull();
|
||||
});
|
||||
|
||||
it("clears an invalid stored session after ping confirms the API is reachable", async () => {
|
||||
seedStoredSession("invalid-token");
|
||||
mocks.authenticatedRequest.mockRejectedValueOnce(invalidSessionError());
|
||||
|
||||
Reference in New Issue
Block a user