Invitations: migrate send to typed path param; update settings view and tests; spec reflects new OpenAPI and migration plan
This commit is contained in:
parent
3b421106bc
commit
630c6dabcf
3 changed files with 16 additions and 18 deletions
|
|
@ -1,4 +1,4 @@
|
|||
import { fetchApi } from '@/api/client'
|
||||
import { api, fetchApi } from '@/api/client'
|
||||
|
||||
export type Household = { id: number; name: string; slug: string }
|
||||
|
||||
|
|
@ -40,11 +40,10 @@ export async function acceptInvitation(token: string): Promise<Household> {
|
|||
return { id: h.id, name: h.name, slug: h.slug }
|
||||
}
|
||||
|
||||
export async function sendInvitation(email: string): Promise<void> {
|
||||
const resp = await fetchApi('/api/v1/invitations', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ email }),
|
||||
export async function sendInvitation(householdSlug: string, email: string): Promise<void> {
|
||||
const res = await api.POST('/api/v1/households/{householdSlug}/invitations', {
|
||||
params: { path: { householdSlug } },
|
||||
body: { email },
|
||||
})
|
||||
if (!resp.ok && resp.status !== 204) throw new Error(`${resp.status} ${resp.statusText || 'HTTP error'}`)
|
||||
if (!res.response.ok) throw new Error(`${res.response.status} ${res.response.statusText || 'HTTP error'}`)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -54,15 +54,18 @@
|
|||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted } from 'vue'
|
||||
import { ref, onMounted, computed } from 'vue'
|
||||
import { sendInvitation } from '@/api/invitations'
|
||||
import { listMembers, type Member } from '@/api/households'
|
||||
import { useRoute } from 'vue-router'
|
||||
|
||||
const email = ref('')
|
||||
const submitting = ref(false)
|
||||
const message = ref('')
|
||||
const error = ref('')
|
||||
const members = ref<Member[]>([])
|
||||
const route = useRoute()
|
||||
const householdSlug = computed(() => (typeof route.params.householdSlug === 'string' ? route.params.householdSlug : null))
|
||||
|
||||
onMounted(async () => {
|
||||
try {
|
||||
|
|
@ -77,7 +80,9 @@ async function onInvite() {
|
|||
error.value = ''
|
||||
submitting.value = true
|
||||
try {
|
||||
await sendInvitation(email.value.trim())
|
||||
const slug = householdSlug.value
|
||||
if (!slug) throw new Error('No household selected')
|
||||
await sendInvitation(slug, email.value.trim())
|
||||
message.value = 'Invitation sent.'
|
||||
email.value = ''
|
||||
} catch (e) {
|
||||
|
|
|
|||
|
|
@ -2,10 +2,9 @@ import { describe, it, expect } from 'vitest'
|
|||
import { server, http, HttpResponse } from './test-setup'
|
||||
import { loginWithPassword } from '@/api/auth'
|
||||
import { sendInvitation } from '@/api/invitations'
|
||||
import { setHouseholdSlugProvider } from '@/api/client'
|
||||
|
||||
describe('invitations api (send invite)', () => {
|
||||
it('posts email with Authorization and X-Household-Slug', async () => {
|
||||
it('posts email with Authorization and householdSlug path param', async () => {
|
||||
// Simulate auth token
|
||||
server.use(
|
||||
http.post('*/api/v1/auth/login', () =>
|
||||
|
|
@ -14,21 +13,16 @@ describe('invitations api (send invite)', () => {
|
|||
)
|
||||
await loginWithPassword('x@y', 'pw')
|
||||
|
||||
// Provide a household slug for header injection
|
||||
setHouseholdSlugProvider(() => 'the-smiths')
|
||||
|
||||
server.use(
|
||||
http.post('*/api/v1/invitations', async ({ request }) => {
|
||||
http.post('*/api/v1/households/the-smiths/invitations', async ({ request, requestId, cookies, params }) => {
|
||||
const body = await request.json()
|
||||
expect(body).toEqual({ email: 'invite@example.com' })
|
||||
const auth = request.headers.get('authorization')
|
||||
expect(auth?.toLowerCase()).toBe('bearer tokabc')
|
||||
const slug = request.headers.get('x-household-slug')
|
||||
expect(slug).toBe('the-smiths')
|
||||
return HttpResponse.json({}, { status: 204 })
|
||||
})
|
||||
)
|
||||
|
||||
await expect(sendInvitation('invite@example.com')).resolves.toBeUndefined()
|
||||
await expect(sendInvitation('the-smiths', 'invite@example.com')).resolves.toBeUndefined()
|
||||
})
|
||||
})
|
||||
|
|
|
|||
Loading…
Reference in a new issue