UNPKG

@rsweeten/dropbox-sync

Version:

Reusable Dropbox synchronization module with framework adapters

241 lines (195 loc) 8.36 kB
import { useNextDropboxSync, getCredentialsFromCookies, handleOAuthCallback, createNextDropboxApiHandlers, } from '../next' import { createDropboxSyncClient } from '../../core/client' import { cookies } from 'next/headers' import { NextRequest, NextResponse } from 'next/server' // Mock dependencies jest.mock('../../core/client') jest.mock('next/headers') jest.mock('next/server') describe('Next.js adapter', () => { beforeEach(() => { jest.clearAllMocks() // Mock process.env process.env.DROPBOX_APP_KEY = 'test-app-key' process.env.DROPBOX_APP_SECRET = 'test-app-secret' process.env.NEXT_PUBLIC_APP_URL = 'https://example.com' }) describe('useNextDropboxSync', () => { it('should create a Dropbox sync client with provided credentials', () => { const mockCredentials = { clientId: 'custom-client-id', clientSecret: 'custom-client-secret', } ;(createDropboxSyncClient as jest.Mock).mockReturnValue({ mock: 'client', }) const result = useNextDropboxSync(mockCredentials) expect(createDropboxSyncClient).toHaveBeenCalledWith( mockCredentials ) expect(result).toEqual({ mock: 'client' }) }) }) describe('getCredentialsFromCookies', () => { it('should get credentials from cookies', async () => { const mockCookieStore = { get: jest.fn((name) => { if (name === 'dropbox_access_token') return { value: 'test-access-token' } if (name === 'dropbox_refresh_token') return { value: 'test-refresh-token' } return null }), } ;(cookies as jest.Mock).mockResolvedValue(mockCookieStore) const credentials = await getCredentialsFromCookies() expect(cookies).toHaveBeenCalled() expect(credentials).toEqual({ clientId: 'test-app-key', clientSecret: 'test-app-secret', accessToken: 'test-access-token', refreshToken: 'test-refresh-token', }) }) it('should handle missing cookie values', async () => { const mockCookieStore = { get: jest.fn().mockReturnValue(null), } ;(cookies as jest.Mock).mockResolvedValue(mockCookieStore) const credentials = await getCredentialsFromCookies() expect(credentials).toEqual({ clientId: 'test-app-key', clientSecret: 'test-app-secret', accessToken: undefined, refreshToken: undefined, }) }) }) describe('handleOAuthCallback', () => { it('should handle successful OAuth callback', async () => { // Mock URL with auth code const mockRequest = { url: 'https://example.com/callback?code=test-auth-code', } as unknown as NextRequest // Mock URL constructor behavior ;(global as any).URL = jest.fn().mockImplementation(() => { return { searchParams: { get: jest.fn().mockReturnValue('test-auth-code'), }, } }) // Mock Dropbox client const mockClient = { auth: { exchangeCodeForToken: jest.fn().mockResolvedValue({ accessToken: 'new-access-token', refreshToken: 'new-refresh-token', expiresAt: Date.now() + 14400 * 1000, }), }, } ;(createDropboxSyncClient as jest.Mock).mockReturnValue(mockClient) // Mock NextResponse const mockResponseCookies = { set: jest.fn(), } const mockResponse = { cookies: mockResponseCookies, } ;(NextResponse.redirect as jest.Mock).mockReturnValue(mockResponse) await handleOAuthCallback(mockRequest) expect(createDropboxSyncClient).toHaveBeenCalled() expect(mockClient.auth.exchangeCodeForToken).toHaveBeenCalledWith( 'test-auth-code', expect.any(String) ) expect(NextResponse.redirect).toHaveBeenCalled() expect(mockResponseCookies.set).toHaveBeenCalledTimes(3) // Access, refresh, and connected cookies }) it('should redirect to error page if code is missing', async () => { const mockRequest = { url: 'https://example.com/callback', } as unknown as NextRequest ;(global as any).URL = jest.fn().mockImplementation(() => { return { searchParams: { get: jest.fn().mockReturnValue(null), }, } }) // Create a proper URL string for the mock response const errorUrl = 'https://example.com/auth/error' // Mock the redirect implementation to return this URL ;(NextResponse.redirect as jest.Mock).mockReturnValue({ url: errorUrl, }) const result = await handleOAuthCallback(mockRequest) // Now we'll check that the redirect was called, and the result contains our URL expect(NextResponse.redirect).toHaveBeenCalled() expect(result.url).toBe(errorUrl) }) }) describe('createNextDropboxApiHandlers', () => { it('should create API handlers with necessary methods', () => { const handlers = createNextDropboxApiHandlers() expect(handlers).toHaveProperty('status') expect(handlers).toHaveProperty('oauthStart') expect(handlers).toHaveProperty('logout') }) it('should check status from cookies', async () => { const mockCookieStore = { get: jest.fn().mockReturnValue({ value: 'test-token' }), } ;(cookies as jest.Mock).mockResolvedValue(mockCookieStore) ;(NextResponse.json as jest.Mock).mockReturnValue({ json: 'response', }) const handlers = createNextDropboxApiHandlers() const response = await handlers.status() expect(cookies).toHaveBeenCalled() expect(mockCookieStore.get).toHaveBeenCalledWith( 'dropbox_access_token' ) expect(NextResponse.json).toHaveBeenCalledWith({ connected: true }) }) it('should start OAuth flow', async () => { const mockClient = { auth: { getAuthUrl: jest .fn() .mockResolvedValue('https://dropbox.com/oauth'), }, } ;(createDropboxSyncClient as jest.Mock).mockReturnValue(mockClient) ;(NextResponse.redirect as jest.Mock).mockReturnValue({ redirect: 'response', }) const handlers = createNextDropboxApiHandlers() const response = await handlers.oauthStart() expect(createDropboxSyncClient).toHaveBeenCalled() expect(mockClient.auth.getAuthUrl).toHaveBeenCalled() expect(NextResponse.redirect).toHaveBeenCalledWith( 'https://dropbox.com/oauth' ) }) it('should handle logout', async () => { const mockResponseCookies = { delete: jest.fn(), } const mockResponse = { cookies: mockResponseCookies, } ;(NextResponse.json as jest.Mock).mockReturnValue(mockResponse) const handlers = createNextDropboxApiHandlers() const response = await handlers.logout() expect(NextResponse.json).toHaveBeenCalledWith({ success: true }) expect(mockResponseCookies.delete).toHaveBeenCalledTimes(3) // Should delete three cookies }) }) })