fix(guest): route homepage CTA to guest checkout when unauthenticated
Guest checkout was unreachable: the homepage CTA "Fortsatt till brevet" always linked to /compose (requiresAuth), so anonymous users hit the router guard and got redirected to /logga-in instead of reaching the guest checkout flow. Changes: - HomePage.vue: compute CTA target based on auth state. Authenticated users still go to /compose; unauthenticated users go to /gast-bestallning with the plate as a query param. - GuestCheckoutPage.vue: accept plate from route.query.plate so the user does not have to re-enter it after looking it up on the homepage. - HomePage.spec.ts: add Pinia setup + guest-checkout route; update CTA assertion to expect /gast-bestallning?plate=... when unauthenticated. All 318 frontend tests pass, vue-tsc clean (exit 0).
This commit is contained in:
parent
8b7e1d5ce2
commit
48c2a50c5d
3 changed files with 34 additions and 7 deletions
|
|
@ -1,8 +1,10 @@
|
|||
import { describe, it, expect, vi } from 'vitest'
|
||||
import { describe, it, expect, vi, beforeEach } from 'vitest'
|
||||
import { mount } from '@vue/test-utils'
|
||||
import { createPinia, setActivePinia } from 'pinia'
|
||||
import { createRouter, createMemoryHistory } from 'vue-router'
|
||||
import HomePage from '@/pages/HomePage.vue'
|
||||
import ComposePage from '@/pages/ComposePage.vue'
|
||||
import GuestCheckoutPage from '@/pages/GuestCheckoutPage.vue'
|
||||
|
||||
vi.mock('@/api/vehicles', () => ({
|
||||
lookupVehicle: vi.fn(),
|
||||
|
|
@ -17,6 +19,11 @@ function createTestRouter() {
|
|||
routes: [
|
||||
{ path: '/', name: 'home', component: HomePage },
|
||||
{ path: '/compose', name: 'compose', component: ComposePage },
|
||||
{
|
||||
path: '/gast-bestallning',
|
||||
name: 'guest-checkout',
|
||||
component: GuestCheckoutPage,
|
||||
},
|
||||
],
|
||||
})
|
||||
}
|
||||
|
|
@ -28,6 +35,12 @@ function mountHome(router: ReturnType<typeof createTestRouter>) {
|
|||
}
|
||||
|
||||
describe('HomePage', () => {
|
||||
beforeEach(() => {
|
||||
setActivePinia(createPinia())
|
||||
localStorage.removeItem('auth_token')
|
||||
vi.clearAllMocks()
|
||||
})
|
||||
|
||||
it('renders headline', () => {
|
||||
const router = createTestRouter()
|
||||
const wrapper = mountHome(router)
|
||||
|
|
@ -88,7 +101,7 @@ describe('HomePage', () => {
|
|||
expect(cta.text()).toBe('Fortsätt till brevet')
|
||||
})
|
||||
|
||||
it('CTA links to compose page with plate query param', async () => {
|
||||
it('CTA links to guest checkout with plate query param when unauthenticated', async () => {
|
||||
mockLookupVehicle.mockResolvedValue({
|
||||
make: 'Volvo',
|
||||
model: 'V70',
|
||||
|
|
@ -107,6 +120,6 @@ describe('HomePage', () => {
|
|||
|
||||
const cta = wrapper.find('.btn--primary')
|
||||
const href = cta.attributes('href')
|
||||
expect(href).toBe('/compose?plate=ABC123')
|
||||
expect(href).toBe('/gast-bestallning?plate=ABC123')
|
||||
})
|
||||
})
|
||||
|
|
|
|||
|
|
@ -1,11 +1,12 @@
|
|||
<script setup lang="ts">
|
||||
import { ref, computed } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { useRouter, useRoute } from 'vue-router'
|
||||
import { createGuestOrder } from '@/api/guestOrders'
|
||||
|
||||
const router = useRouter()
|
||||
const route = useRoute()
|
||||
|
||||
const plate = ref('')
|
||||
const plate = ref((route.query.plate as string) || '')
|
||||
const letterText = ref('')
|
||||
const email = ref('')
|
||||
const submitting = ref(false)
|
||||
|
|
|
|||
|
|
@ -1,10 +1,23 @@
|
|||
<script setup lang="ts">
|
||||
import { ref } from 'vue'
|
||||
import { ref, computed } from 'vue'
|
||||
import { RouterLink } from 'vue-router'
|
||||
import PlateInput from '@/components/PlateInput.vue'
|
||||
import VehicleInfo from '@/components/VehicleInfo.vue'
|
||||
import type { VehicleInfo as VehicleData } from '@/components/VehicleInfo.vue'
|
||||
import { lookupVehicle } from '@/api/vehicles'
|
||||
import { useAuthStore } from '@/stores/authStore'
|
||||
|
||||
const auth = useAuthStore()
|
||||
|
||||
// When unauthenticated, the homepage CTA sends the user to the guest
|
||||
// checkout page instead of the auth-protected /compose route.
|
||||
// Without this, anonymous users hit the router guard and are bounced
|
||||
// to /logga-in — the guest flow we built was unreachable from the UI.
|
||||
const ctaTarget = computed(() =>
|
||||
auth.isAuthenticated
|
||||
? { name: 'compose' as const, query: { plate: plate.value } }
|
||||
: { name: 'guest-checkout' as const, query: { plate: plate.value } },
|
||||
)
|
||||
|
||||
const useCases = [
|
||||
{
|
||||
|
|
@ -204,7 +217,7 @@ async function handleLookup(lookedUpPlate: string) {
|
|||
|
||||
<RouterLink
|
||||
v-if="vehicle"
|
||||
:to="{ name: 'compose', query: { plate } }"
|
||||
:to="ctaTarget"
|
||||
class="btn btn--primary btn--lg home__cta"
|
||||
>
|
||||
Fortsätt till brevet
|
||||
|
|
|
|||
Loading…
Reference in a new issue