feat(05-07): cloud connections Pinia store + API client functions
- Create useCloudConnectionsStore with connections/loading/error refs - fetchConnections, disconnect(id), disconnectAll() actions - Append listCloudConnections, disconnectCloud, connectWebDav, updateDefaultStorage to api/client.js - Add vitest test script to package.json - 4 unit tests passing (W4 — CLAUDE.md)
This commit is contained in:
@@ -0,0 +1,59 @@
|
||||
import { describe, it, expect, vi, beforeEach } from 'vitest'
|
||||
import { setActivePinia, createPinia } from 'pinia'
|
||||
|
||||
// Mock api/client.js — no real HTTP calls in unit tests (CLAUDE.md W4)
|
||||
vi.mock('../../api/client.js', () => ({
|
||||
listCloudConnections: vi.fn(),
|
||||
disconnectCloud: vi.fn(),
|
||||
connectWebDav: vi.fn(),
|
||||
updateDefaultStorage: vi.fn(),
|
||||
}))
|
||||
|
||||
import { useCloudConnectionsStore } from '../cloudConnections.js'
|
||||
import * as api from '../../api/client.js'
|
||||
|
||||
beforeEach(() => {
|
||||
setActivePinia(createPinia())
|
||||
vi.clearAllMocks()
|
||||
})
|
||||
|
||||
describe('useCloudConnectionsStore', () => {
|
||||
it('fetchConnections sets connections from API response', async () => {
|
||||
api.listCloudConnections.mockResolvedValue({
|
||||
items: [{ id: '1', provider: 'google_drive', status: 'ACTIVE' }],
|
||||
})
|
||||
const store = useCloudConnectionsStore()
|
||||
await store.fetchConnections()
|
||||
expect(store.connections).toHaveLength(1)
|
||||
expect(store.connections[0].provider).toBe('google_drive')
|
||||
expect(store.loading).toBe(false)
|
||||
})
|
||||
|
||||
it('fetchConnections sets error on API failure', async () => {
|
||||
api.listCloudConnections.mockRejectedValue(new Error('Network error'))
|
||||
const store = useCloudConnectionsStore()
|
||||
await store.fetchConnections()
|
||||
expect(store.error).toBeTruthy()
|
||||
expect(store.connections).toHaveLength(0)
|
||||
})
|
||||
|
||||
it('disconnect removes connection from state after API call', async () => {
|
||||
api.disconnectCloud.mockResolvedValue(null)
|
||||
const store = useCloudConnectionsStore()
|
||||
store.connections = [{ id: 'conn-1', provider: 'google_drive', status: 'ACTIVE' }]
|
||||
await store.disconnect('conn-1')
|
||||
expect(store.connections).toHaveLength(0)
|
||||
expect(api.disconnectCloud).toHaveBeenCalledWith('conn-1')
|
||||
})
|
||||
|
||||
it('disconnectAll clears all connections', async () => {
|
||||
api.disconnectCloud.mockResolvedValue(null)
|
||||
const store = useCloudConnectionsStore()
|
||||
store.connections = [
|
||||
{ id: 'a', provider: 'google_drive', status: 'ACTIVE' },
|
||||
{ id: 'b', provider: 'onedrive', status: 'ACTIVE' },
|
||||
]
|
||||
await store.disconnectAll()
|
||||
expect(store.connections).toHaveLength(0)
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,39 @@
|
||||
import { defineStore } from 'pinia'
|
||||
import { ref } from 'vue'
|
||||
import * as api from '../api/client.js'
|
||||
|
||||
export const useCloudConnectionsStore = defineStore('cloudConnections', () => {
|
||||
const connections = ref([])
|
||||
const loading = ref(false)
|
||||
const error = ref(null)
|
||||
|
||||
async function fetchConnections() {
|
||||
loading.value = true
|
||||
error.value = null
|
||||
try {
|
||||
const data = await api.listCloudConnections()
|
||||
connections.value = data.items ?? []
|
||||
} catch (e) {
|
||||
error.value = e.message || 'Failed to load cloud connections'
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
async function disconnect(id) {
|
||||
try {
|
||||
await api.disconnectCloud(id)
|
||||
connections.value = connections.value.filter(c => c.id !== id)
|
||||
} catch (e) {
|
||||
throw e
|
||||
}
|
||||
}
|
||||
|
||||
async function disconnectAll() {
|
||||
const ids = connections.value.map(c => c.id)
|
||||
for (const id of ids) await disconnect(id)
|
||||
connections.value = []
|
||||
}
|
||||
|
||||
return { connections, loading, error, fetchConnections, disconnect, disconnectAll }
|
||||
})
|
||||
Reference in New Issue
Block a user