feat(pleno-vue): add driver/subuser login button (mobile-visible) (TRU-61) (#321)
## Why
Drivers (sub-users) could not reliably reach the driver login from the
customer login page (/login) on mobile devices. The form contained an
internal driver button, but it sat below the QR code and passkey
buttons, making it easy to miss on small screens. The desktop sidebar
layout further reduced discoverability.
## What changed
- **src/views/auth/Login.vue** — Add a page-level .driver-entry block
below the customer login form, with a router-link to { name:
'subuserlogin' }. Distinct color (#1584BC) and a truck icon match the
existing LandingPage driver entry pattern. Full-width on mobile (<768px)
so it's impossible to miss.
- **i18n** — Add auth.driver_login_help to en, da, de, no, sv locale
files + global shared auth index. auth.driver_login_button already
existed in all locales.
- **tests/unit/login-driver-entry.spec.js** — 5 Vitest tests verifying
the driver entry block, router-link, button label, help text, and
placement (not in sidebar).
## CI
- Vitest unit tests pass (5/5 new tests, existing tests unaffected)
- ESLint clean
- Text encoding check clean
- i18n v2 source check + compile clean
Co-authored-by: Pleno Bugfix Bot <bugfix-bot@pleno.local>
This commit is contained in:
co-authored by
Pleno Bugfix Bot
parent
2401ebb674
commit
cafe671e85
@@ -2143,6 +2143,7 @@
|
|||||||
"customer_login_title": "@:{'templates.generated.compat.global.login'}",
|
"customer_login_title": "@:{'templates.generated.compat.global.login'}",
|
||||||
"driver_entry_intro": "@.capitalize:{'words.generated.er'} @:{'words.generated.du'} @:{'words.generated.chauffør'}? @.capitalize:{'words.generated.log'} @:{'words.generated.ind'} @:{'words.generated.her'} @:{'words.generated.for'} @:{'words.generated.at'} @:{'words.generated.fa'} @:{'words.generated.adgang'} @:{'words.generated.til'} @:{'words.generated.dine'} @:{'words.generated.vaske'}.",
|
"driver_entry_intro": "@.capitalize:{'words.generated.er'} @:{'words.generated.du'} @:{'words.generated.chauffør'}? @.capitalize:{'words.generated.log'} @:{'words.generated.ind'} @:{'words.generated.her'} @:{'words.generated.for'} @:{'words.generated.at'} @:{'words.generated.fa'} @:{'words.generated.adgang'} @:{'words.generated.til'} @:{'words.generated.dine'} @:{'words.generated.vaske'}.",
|
||||||
"driver_login_button": "@.capitalize:{'words.generated.log'} @:{'words.generated.ind'} @.lower:{'words.generated.som'} @:{'words.generated.chauffør'}",
|
"driver_login_button": "@.capitalize:{'words.generated.log'} @:{'words.generated.ind'} @.lower:{'words.generated.som'} @:{'words.generated.chauffør'}",
|
||||||
|
"driver_login_help": "Chauffører (underbrugere) logger ind her for at registrere en vask.",
|
||||||
"driver_login_title": "@.capitalize:{'words.generated.chauffør'} @.capitalize:{'words.generated.login'}",
|
"driver_login_title": "@.capitalize:{'words.generated.chauffør'} @.capitalize:{'words.generated.login'}",
|
||||||
"forgot_password": "Glemt @:{'words.generated.adgangskode'}",
|
"forgot_password": "Glemt @:{'words.generated.adgangskode'}",
|
||||||
"operator_tagline": "@.capitalize:{'words.generated.truckwash'}.@:{'words.generated.io'} – @:{'words.generated.digitale'} @:{'words.generated.løsninger'} @:{'words.generated.til'} @:{'words.generated.lastbilvask'}",
|
"operator_tagline": "@.capitalize:{'words.generated.truckwash'}.@:{'words.generated.io'} – @:{'words.generated.digitale'} @:{'words.generated.løsninger'} @:{'words.generated.til'} @:{'words.generated.lastbilvask'}",
|
||||||
|
|||||||
@@ -2260,6 +2260,7 @@
|
|||||||
"username": "@:{'words.generated.benutzername'}",
|
"username": "@:{'words.generated.benutzername'}",
|
||||||
"your_username": "@:{'words.generated.ihr'} @:{'words.generated.benutzername'}",
|
"your_username": "@:{'words.generated.ihr'} @:{'words.generated.benutzername'}",
|
||||||
"driver_login_button": "Fahrer-Login",
|
"driver_login_button": "Fahrer-Login",
|
||||||
|
"driver_login_help": "Fahrer (Unterbenutzer) melden sich hier an, um eine Wäsche zu registrieren.",
|
||||||
"driver_entry_intro": "Sind Sie Fahrer? Melden Sie sich hier an, um eine Wäsche zu registrieren."
|
"driver_entry_intro": "Sind Sie Fahrer? Melden Sie sich hier an, um eine Wäsche zu registrieren."
|
||||||
},
|
},
|
||||||
"book_wash": {
|
"book_wash": {
|
||||||
|
|||||||
@@ -1974,6 +1974,7 @@
|
|||||||
"customer_login_title": "@.capitalize:{'words.generated.customer'} @.capitalize:{'words.generated.login'}",
|
"customer_login_title": "@.capitalize:{'words.generated.customer'} @.capitalize:{'words.generated.login'}",
|
||||||
"driver_entry_intro": "@.capitalize:{'words.generated.are'} @:{'words.generated.you'} @:{'words.generated.a'} @:{'words.generated.driver'}? @.capitalize:{'words.generated.log'} @:{'words.generated.in'} @:{'words.generated.here'} @:{'words.generated.to'} @:{'words.generated.register'} @:{'words.generated.a'} @:{'words.generated.wash'}.",
|
"driver_entry_intro": "@.capitalize:{'words.generated.are'} @:{'words.generated.you'} @:{'words.generated.a'} @:{'words.generated.driver'}? @.capitalize:{'words.generated.log'} @:{'words.generated.in'} @:{'words.generated.here'} @:{'words.generated.to'} @:{'words.generated.register'} @:{'words.generated.a'} @:{'words.generated.wash'}.",
|
||||||
"driver_login_button": "@.capitalize:{'words.generated.driver'} @.capitalize:{'words.generated.login'}",
|
"driver_login_button": "@.capitalize:{'words.generated.driver'} @.capitalize:{'words.generated.login'}",
|
||||||
|
"driver_login_help": "Drivers (sub-users) log in here to register a wash.",
|
||||||
"driver_login_title": "@.capitalize:{'words.generated.driver'} @.capitalize:{'words.generated.login'}",
|
"driver_login_title": "@.capitalize:{'words.generated.driver'} @.capitalize:{'words.generated.login'}",
|
||||||
"forgot_password": "Forgot @.capitalize:{'words.generated.password'}",
|
"forgot_password": "Forgot @.capitalize:{'words.generated.password'}",
|
||||||
"operator_tagline": "@.capitalize:{'words.generated.truckwash'}.@:{'words.generated.io'} - @:{'words.generated.digital'} @:{'words.generated.solutions'} @:{'words.generated.for'} @:{'words.generated.truck'} @:{'words.generated.washing'}",
|
"operator_tagline": "@.capitalize:{'words.generated.truckwash'}.@:{'words.generated.io'} - @:{'words.generated.digital'} @:{'words.generated.solutions'} @:{'words.generated.for'} @:{'words.generated.truck'} @:{'words.generated.washing'}",
|
||||||
|
|||||||
@@ -786,6 +786,7 @@
|
|||||||
"customer_number": "@:{'templates.generated.compat.objects.columns.customer_number'}",
|
"customer_number": "@:{'templates.generated.compat.objects.columns.customer_number'}",
|
||||||
"driver_entry_intro": "@:{'templates.generated.compat.auth.driver_entry_intro'}",
|
"driver_entry_intro": "@:{'templates.generated.compat.auth.driver_entry_intro'}",
|
||||||
"driver_login_button": "@:{'templates.generated.compat.auth.driver_login_button'}",
|
"driver_login_button": "@:{'templates.generated.compat.auth.driver_login_button'}",
|
||||||
|
"driver_login_help": "@:{'templates.generated.compat.auth.driver_login_help'}",
|
||||||
"driver_login_title": "@:{'templates.generated.compat.auth.driver_login_title'}",
|
"driver_login_title": "@:{'templates.generated.compat.auth.driver_login_title'}",
|
||||||
"forgot_password": "@:{'templates.generated.compat.auth.forgot_password'}",
|
"forgot_password": "@:{'templates.generated.compat.auth.forgot_password'}",
|
||||||
"login_as_customer": "@:{'templates.generated.compat.global.login_as_customer'}",
|
"login_as_customer": "@:{'templates.generated.compat.global.login_as_customer'}",
|
||||||
|
|||||||
@@ -2263,6 +2263,7 @@
|
|||||||
"username": "@.capitalize:{'words.generated.brukernavn'}",
|
"username": "@.capitalize:{'words.generated.brukernavn'}",
|
||||||
"your_username": "@.capitalize:{'words.generated.ditt'} @:{'words.generated.brukernavn'}",
|
"your_username": "@.capitalize:{'words.generated.ditt'} @:{'words.generated.brukernavn'}",
|
||||||
"driver_login_button": "Sjåfør-innlogging",
|
"driver_login_button": "Sjåfør-innlogging",
|
||||||
|
"driver_login_help": "Sjåfører (underbrukere) logger inn her for å registrere en vask.",
|
||||||
"driver_entry_intro": "Er du sjåfør? Logg inn her for å registrere en vask."
|
"driver_entry_intro": "Er du sjåfør? Logg inn her for å registrere en vask."
|
||||||
},
|
},
|
||||||
"book_wash": {
|
"book_wash": {
|
||||||
|
|||||||
@@ -2313,6 +2313,7 @@
|
|||||||
"username": "@.capitalize:{'words.generated.anvandarnamn'}",
|
"username": "@.capitalize:{'words.generated.anvandarnamn'}",
|
||||||
"your_username": "@.capitalize:{'words.generated.ditt'} @:{'words.generated.anvandarnamn'}",
|
"your_username": "@.capitalize:{'words.generated.ditt'} @:{'words.generated.anvandarnamn'}",
|
||||||
"driver_login_button": "Förarinloggning",
|
"driver_login_button": "Förarinloggning",
|
||||||
|
"driver_login_help": "Förare (underanvändare) loggar in här för att registrera en tvätt.",
|
||||||
"driver_entry_intro": "Är du förare? Logga in här för att registrera en tvätt."
|
"driver_entry_intro": "Är du förare? Logga in här för att registrera en tvätt."
|
||||||
},
|
},
|
||||||
"book_wash": {
|
"book_wash": {
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
"customer_login_title": "@:{'phrases.compat.global.login'}",
|
"customer_login_title": "@:{'phrases.compat.global.login'}",
|
||||||
"driver_entry_intro": "@.capitalize:{'terms.glossary.er'} @:{'terms.glossary.du'} @:{'terms.glossary.chauffør'}? @.capitalize:{'terms.glossary.log'} @:{'terms.glossary.ind'} @:{'terms.glossary.her'} @:{'terms.glossary.for'} @:{'terms.glossary.at'} @:{'terms.glossary.fa'} @:{'terms.glossary.adgang'} @:{'terms.glossary.til'} @:{'terms.glossary.dine'} @:{'terms.glossary.vaske'}.",
|
"driver_entry_intro": "@.capitalize:{'terms.glossary.er'} @:{'terms.glossary.du'} @:{'terms.glossary.chauffør'}? @.capitalize:{'terms.glossary.log'} @:{'terms.glossary.ind'} @:{'terms.glossary.her'} @:{'terms.glossary.for'} @:{'terms.glossary.at'} @:{'terms.glossary.fa'} @:{'terms.glossary.adgang'} @:{'terms.glossary.til'} @:{'terms.glossary.dine'} @:{'terms.glossary.vaske'}.",
|
||||||
"driver_login_button": "@.capitalize:{'terms.glossary.log'} @:{'terms.glossary.ind'} @.lower:{'terms.glossary.som'} @:{'terms.glossary.chauffør'}",
|
"driver_login_button": "@.capitalize:{'terms.glossary.log'} @:{'terms.glossary.ind'} @.lower:{'terms.glossary.som'} @:{'terms.glossary.chauffør'}",
|
||||||
|
"driver_login_help": "Chauffører (underbrugere) logger ind her for at registrere en vask.",
|
||||||
"driver_login_title": "@.capitalize:{'terms.glossary.chauffør'} @.capitalize:{'terms.glossary.login'}",
|
"driver_login_title": "@.capitalize:{'terms.glossary.chauffør'} @.capitalize:{'terms.glossary.login'}",
|
||||||
"forgot_password": "Glemt @:{'terms.glossary.adgangskode'}",
|
"forgot_password": "Glemt @:{'terms.glossary.adgangskode'}",
|
||||||
"operator_tagline": "@.capitalize:{'terms.glossary.truckwash'}.@:{'terms.glossary.io'} – @:{'terms.glossary.digitale'} @:{'terms.glossary.løsninger'} @:{'terms.glossary.til'} @:{'terms.glossary.lastbilvask'}",
|
"operator_tagline": "@.capitalize:{'terms.glossary.truckwash'}.@:{'terms.glossary.io'} – @:{'terms.glossary.digitale'} @:{'terms.glossary.løsninger'} @:{'terms.glossary.til'} @:{'terms.glossary.lastbilvask'}",
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
"username": "@:{'terms.glossary.benutzername'}",
|
"username": "@:{'terms.glossary.benutzername'}",
|
||||||
"your_username": "@:{'terms.glossary.ihr'} @:{'terms.glossary.benutzername'}",
|
"your_username": "@:{'terms.glossary.ihr'} @:{'terms.glossary.benutzername'}",
|
||||||
"driver_login_button": "Fahrer-Login",
|
"driver_login_button": "Fahrer-Login",
|
||||||
|
"driver_login_help": "Fahrer (Unterbenutzer) melden sich hier an, um eine Wäsche zu registrieren.",
|
||||||
"driver_entry_intro": "Sind Sie Fahrer? Melden Sie sich hier an, um eine Wäsche zu registrieren."
|
"driver_entry_intro": "Sind Sie Fahrer? Melden Sie sich hier an, um eine Wäsche zu registrieren."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
"customer_login_title": "@.capitalize:{'terms.glossary.customer'} @.capitalize:{'terms.glossary.login'}",
|
"customer_login_title": "@.capitalize:{'terms.glossary.customer'} @.capitalize:{'terms.glossary.login'}",
|
||||||
"driver_entry_intro": "@.capitalize:{'terms.glossary.are'} @:{'terms.glossary.you'} @:{'terms.glossary.a'} @:{'terms.glossary.driver'}? @.capitalize:{'terms.glossary.log'} @:{'terms.glossary.in'} @:{'terms.glossary.here'} @:{'terms.glossary.to'} @:{'terms.glossary.register'} @:{'terms.glossary.a'} @:{'terms.glossary.wash'}.",
|
"driver_entry_intro": "@.capitalize:{'terms.glossary.are'} @:{'terms.glossary.you'} @:{'terms.glossary.a'} @:{'terms.glossary.driver'}? @.capitalize:{'terms.glossary.log'} @:{'terms.glossary.in'} @:{'terms.glossary.here'} @:{'terms.glossary.to'} @:{'terms.glossary.register'} @:{'terms.glossary.a'} @:{'terms.glossary.wash'}.",
|
||||||
"driver_login_button": "@.capitalize:{'terms.glossary.driver'} @.capitalize:{'terms.glossary.login'}",
|
"driver_login_button": "@.capitalize:{'terms.glossary.driver'} @.capitalize:{'terms.glossary.login'}",
|
||||||
|
"driver_login_help": "Drivers (sub-users) log in here to register a wash.",
|
||||||
"driver_login_title": "@.capitalize:{'terms.glossary.driver'} @.capitalize:{'terms.glossary.login'}",
|
"driver_login_title": "@.capitalize:{'terms.glossary.driver'} @.capitalize:{'terms.glossary.login'}",
|
||||||
"forgot_password": "Forgot @.capitalize:{'terms.glossary.password'}",
|
"forgot_password": "Forgot @.capitalize:{'terms.glossary.password'}",
|
||||||
"operator_tagline": "@.capitalize:{'terms.glossary.truckwash'}.@:{'terms.glossary.io'} - @:{'terms.glossary.digital'} @:{'terms.glossary.solutions'} @:{'terms.glossary.for'} @:{'terms.glossary.truck'} @:{'terms.glossary.washing'}",
|
"operator_tagline": "@.capitalize:{'terms.glossary.truckwash'}.@:{'terms.glossary.io'} - @:{'terms.glossary.digital'} @:{'terms.glossary.solutions'} @:{'terms.glossary.for'} @:{'terms.glossary.truck'} @:{'terms.glossary.washing'}",
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
"customer_number": "@:{'phrases.compat.objects.columns.customer_number'}",
|
"customer_number": "@:{'phrases.compat.objects.columns.customer_number'}",
|
||||||
"driver_entry_intro": "@:{'phrases.compat.auth.driver_entry_intro'}",
|
"driver_entry_intro": "@:{'phrases.compat.auth.driver_entry_intro'}",
|
||||||
"driver_login_button": "@:{'phrases.compat.auth.driver_login_button'}",
|
"driver_login_button": "@:{'phrases.compat.auth.driver_login_button'}",
|
||||||
|
"driver_login_help": "@:{'phrases.compat.auth.driver_login_help'}",
|
||||||
"driver_login_title": "@:{'phrases.compat.auth.driver_login_title'}",
|
"driver_login_title": "@:{'phrases.compat.auth.driver_login_title'}",
|
||||||
"forgot_password": "@:{'phrases.compat.auth.forgot_password'}",
|
"forgot_password": "@:{'phrases.compat.auth.forgot_password'}",
|
||||||
"login_as_customer": "@:{'phrases.compat.global.login_as_customer'}",
|
"login_as_customer": "@:{'phrases.compat.global.login_as_customer'}",
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
"username": "@.capitalize:{'terms.glossary.brukernavn'}",
|
"username": "@.capitalize:{'terms.glossary.brukernavn'}",
|
||||||
"your_username": "@.capitalize:{'terms.glossary.ditt'} @:{'terms.glossary.brukernavn'}",
|
"your_username": "@.capitalize:{'terms.glossary.ditt'} @:{'terms.glossary.brukernavn'}",
|
||||||
"driver_login_button": "Sjåfør-innlogging",
|
"driver_login_button": "Sjåfør-innlogging",
|
||||||
|
"driver_login_help": "Sjåfører (underbrukere) logger inn her for å registrere en vask.",
|
||||||
"driver_entry_intro": "Er du sjåfør? Logg inn her for å registrere en vask."
|
"driver_entry_intro": "Er du sjåfør? Logg inn her for å registrere en vask."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
"username": "@.capitalize:{'terms.glossary.anvandarnamn'}",
|
"username": "@.capitalize:{'terms.glossary.anvandarnamn'}",
|
||||||
"your_username": "@.capitalize:{'terms.glossary.ditt'} @:{'terms.glossary.anvandarnamn'}",
|
"your_username": "@.capitalize:{'terms.glossary.ditt'} @:{'terms.glossary.anvandarnamn'}",
|
||||||
"driver_login_button": "Förarinloggning",
|
"driver_login_button": "Förarinloggning",
|
||||||
|
"driver_login_help": "Förare (underanvändare) loggar in här för att registrera en tvätt.",
|
||||||
"driver_entry_intro": "Är du förare? Logga in här för att registrera en tvätt."
|
"driver_entry_intro": "Är du förare? Logga in här för att registrera en tvätt."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,6 +31,23 @@ const { hasPendingStoredSession } = useStoredSessionGuestRedirect();
|
|||||||
<LoginForm />
|
<LoginForm />
|
||||||
</ConnectivityIssue>
|
</ConnectivityIssue>
|
||||||
<p>{{ $t('auth.terms_acceptance') }}</p>
|
<p>{{ $t('auth.terms_acceptance') }}</p>
|
||||||
|
|
||||||
|
<!-- Driver discoverability: page-level entry so sub-users (drivers) can
|
||||||
|
reach the driver login from the customer login page — especially
|
||||||
|
on mobile where the desktop sidebar layout obscures the form's
|
||||||
|
internal driver button. -->
|
||||||
|
<div class="driver-entry" data-testid="login-driver-entry">
|
||||||
|
<p class="driver-entry__help">{{ $t('auth.driver_login_help') }}</p>
|
||||||
|
<router-link
|
||||||
|
:to="{ name: 'subuserlogin' }"
|
||||||
|
class="submit driver-login-link"
|
||||||
|
id="login-driver-login-button"
|
||||||
|
data-testid="login-driver-login-link"
|
||||||
|
>
|
||||||
|
<span class="icon"><i class="fas fa-truck"></i></span>
|
||||||
|
<span>{{ $t('auth.driver_login_button') }}</span>
|
||||||
|
</router-link>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
@@ -158,6 +175,55 @@ const { hasPendingStoredSession } = useStoredSessionGuestRedirect();
|
|||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Driver entry block — page-level, always visible on every viewport.
|
||||||
|
The internal LoginForm driver button lives inside the customer login
|
||||||
|
form and can be missed on small screens; this block guarantees the
|
||||||
|
driver login path is discoverable from the Login page. */
|
||||||
|
.login-section .wrapper .main .driver-entry {
|
||||||
|
max-width: 400px;
|
||||||
|
width: 100%;
|
||||||
|
margin-top: 24px;
|
||||||
|
padding: 16px 20px;
|
||||||
|
background-color: #F2F8FC;
|
||||||
|
border: 1px solid #BFE0EF;
|
||||||
|
border-radius: 12px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
gap: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-section .wrapper .main .driver-entry__help {
|
||||||
|
max-width: none;
|
||||||
|
margin: 0;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #13324C;
|
||||||
|
text-align: center;
|
||||||
|
line-height: 1.4;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-section .wrapper .main .driver-entry .driver-login-link {
|
||||||
|
background-color: #1584BC;
|
||||||
|
color: #fff;
|
||||||
|
border: 0;
|
||||||
|
border-radius: 30px;
|
||||||
|
min-height: 43px;
|
||||||
|
font-size: 16px;
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 8px;
|
||||||
|
text-decoration: none;
|
||||||
|
margin: 0;
|
||||||
|
width: auto;
|
||||||
|
padding: 0 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-section .wrapper .main .driver-entry .driver-login-link:hover {
|
||||||
|
background-color: #1a99d6;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
@media (max-width: 1250px) {
|
@media (max-width: 1250px) {
|
||||||
.login-section .wrapper .sidebar h1{
|
.login-section .wrapper .sidebar h1{
|
||||||
font-size: 2.3em;
|
font-size: 2.3em;
|
||||||
@@ -187,5 +253,20 @@ const { hasPendingStoredSession } = useStoredSessionGuestRedirect();
|
|||||||
padding: 70px 10px;
|
padding: 70px 10px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Mobile (<768px): ensure the driver entry block is always visible and
|
||||||
|
takes full width so it's impossible to miss on phones. */
|
||||||
|
@media (max-width: 767px) {
|
||||||
|
.login-section .wrapper .main .driver-entry {
|
||||||
|
margin-top: 20px;
|
||||||
|
padding: 14px 16px;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-section .wrapper .main .driver-entry .driver-login-link {
|
||||||
|
width: 100%;
|
||||||
|
padding: 0 16px;
|
||||||
|
}
|
||||||
|
}
|
||||||
/*end login-section*/
|
/*end login-section*/
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -0,0 +1,134 @@
|
|||||||
|
// @vitest-environment jsdom
|
||||||
|
|
||||||
|
import { defineComponent, h, nextTick } from "vue";
|
||||||
|
import { mount } from "@vue/test-utils";
|
||||||
|
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
||||||
|
|
||||||
|
const mocks = vi.hoisted(() => ({
|
||||||
|
hasStoredSessionToken: vi.fn(),
|
||||||
|
}));
|
||||||
|
|
||||||
|
vi.mock("@/services/sessionStorage.js", () => ({
|
||||||
|
hasStoredSessionToken: mocks.hasStoredSessionToken,
|
||||||
|
}));
|
||||||
|
|
||||||
|
vi.mock("@/composables/useStoredSessionGuestRedirect.js", () => ({
|
||||||
|
useStoredSessionGuestRedirect: () => ({
|
||||||
|
hasPendingStoredSession: mocks.hasStoredSessionToken(),
|
||||||
|
}),
|
||||||
|
}));
|
||||||
|
|
||||||
|
vi.mock("@/components/forms/auth/LoginForm.vue", () => ({
|
||||||
|
default: defineComponent({
|
||||||
|
name: "MockLoginForm",
|
||||||
|
setup() {
|
||||||
|
return () => h("form", { "data-testid": "login-form" });
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
}));
|
||||||
|
|
||||||
|
vi.mock("@/views/errors/ConnectivityIssue.vue", () => ({
|
||||||
|
default: defineComponent({
|
||||||
|
name: "MockConnectivityIssue",
|
||||||
|
setup(_, { slots }) {
|
||||||
|
return () => h("div", { "data-testid": "connectivity-wrapper" }, slots.default?.());
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
}));
|
||||||
|
|
||||||
|
vi.mock("@/components/global/BrandedLoadingScreen.vue", () => ({
|
||||||
|
default: defineComponent({
|
||||||
|
name: "MockBrandedLoadingScreen",
|
||||||
|
props: {
|
||||||
|
testId: { type: String, default: "branded-loading-screen" },
|
||||||
|
},
|
||||||
|
setup(props) {
|
||||||
|
return () => h("div", { "data-testid": props.testId });
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
}));
|
||||||
|
|
||||||
|
import Login from "@/views/auth/Login.vue";
|
||||||
|
|
||||||
|
const routerLinkStub = defineComponent({
|
||||||
|
name: "RouterLinkStub",
|
||||||
|
props: {
|
||||||
|
to: {
|
||||||
|
type: [String, Object],
|
||||||
|
default: "",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
setup(_, { slots, attrs }) {
|
||||||
|
return () => h("a", attrs, slots.default?.());
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const mountLogin = () =>
|
||||||
|
mount(Login, {
|
||||||
|
global: {
|
||||||
|
mocks: {
|
||||||
|
$t: (key) => key,
|
||||||
|
},
|
||||||
|
stubs: {
|
||||||
|
RouterLink: routerLinkStub,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("Login.vue — driver entry block (TRU-61)", () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
mocks.hasStoredSessionToken.mockReset();
|
||||||
|
mocks.hasStoredSessionToken.mockReturnValue(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
document.body.innerHTML = "";
|
||||||
|
});
|
||||||
|
|
||||||
|
it("renders the page-level driver entry block on the customer login page", async () => {
|
||||||
|
const wrapper = mountLogin();
|
||||||
|
await nextTick();
|
||||||
|
|
||||||
|
const entry = wrapper.find('[data-testid="login-driver-entry"]');
|
||||||
|
expect(entry.exists()).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("renders a router-link to the subuser login route inside the driver entry block", async () => {
|
||||||
|
const wrapper = mountLogin();
|
||||||
|
await nextTick();
|
||||||
|
|
||||||
|
const link = wrapper.find('[data-testid="login-driver-login-link"]');
|
||||||
|
expect(link.exists()).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("renders the driver login button with the localized driver_login_button label", async () => {
|
||||||
|
const wrapper = mountLogin();
|
||||||
|
await nextTick();
|
||||||
|
|
||||||
|
const link = wrapper.find('[data-testid="login-driver-login-link"]');
|
||||||
|
expect(link.text()).toContain("auth.driver_login_button");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("renders the driver login help text inside the entry block", async () => {
|
||||||
|
const wrapper = mountLogin();
|
||||||
|
await nextTick();
|
||||||
|
|
||||||
|
const entry = wrapper.find('[data-testid="login-driver-entry"]');
|
||||||
|
expect(entry.text()).toContain("auth.driver_login_help");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("places the driver entry block in the main content area (not the sidebar)", async () => {
|
||||||
|
const wrapper = mountLogin();
|
||||||
|
await nextTick();
|
||||||
|
|
||||||
|
// The sidebar should NOT contain the driver entry — it must be in main
|
||||||
|
const html = wrapper.html();
|
||||||
|
const entryHtml = wrapper.find('[data-testid="login-driver-entry"]').html();
|
||||||
|
// Find the sidebar's outer container and ensure the entry is not inside it
|
||||||
|
const sidebarMatch = html.match(/<div class="sidebar">[\s\S]*?<\/div>\s*<div class="main">/);
|
||||||
|
if (sidebarMatch) {
|
||||||
|
expect(sidebarMatch[0]).not.toContain("login-driver-entry");
|
||||||
|
}
|
||||||
|
expect(entryHtml).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user