All checks were successful
Chore App Build, Test, and Push Docker Images / build-and-push (push) Successful in 2m6s
fix: update login token expiration to 62 days chore: bump version to 1.0.5RC1 test: add isParentPersistent to LoginButton.spec.ts refactor: rename Assign Tasks button to Assign Chores in ParentView.vue refactor: rename Assign Tasks to Assign Chores in TaskAssignView.vue feat: add stay in parent mode checkbox and badge in LoginButton.vue test: enhance LoginButton.spec.ts with persistent mode tests test: add authGuard.spec.ts for logoutParent and enforceParentExpiry feat: implement parent mode expiry logic in auth.ts test: add auth.expiry.spec.ts for parent mode expiry tests chore: create template for feature specs
110 lines
3.0 KiB
TypeScript
110 lines
3.0 KiB
TypeScript
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'
|
|
import { mount, VueWrapper } from '@vue/test-utils'
|
|
import { nextTick } from 'vue'
|
|
import LoginButton from '../shared/LoginButton.vue'
|
|
|
|
// Mock dependencies
|
|
vi.mock('vue-router', () => ({
|
|
useRouter: vi.fn(() => ({ push: vi.fn() })),
|
|
}))
|
|
|
|
vi.mock('../../stores/auth', () => ({
|
|
authenticateParent: vi.fn(),
|
|
isParentAuthenticated: { value: false },
|
|
isParentPersistent: { value: false },
|
|
logoutParent: vi.fn(),
|
|
logoutUser: vi.fn(),
|
|
}))
|
|
|
|
vi.mock('@/common/imageCache', () => ({
|
|
getCachedImageUrl: vi.fn(),
|
|
getCachedImageBlob: vi.fn(),
|
|
}))
|
|
|
|
vi.mock('@/common/eventBus', () => ({
|
|
eventBus: {
|
|
on: vi.fn(),
|
|
off: vi.fn(),
|
|
emit: vi.fn(),
|
|
},
|
|
}))
|
|
|
|
import { eventBus } from '@/common/eventBus'
|
|
|
|
describe('LoginButton', () => {
|
|
let wrapper: VueWrapper<any>
|
|
let mockFetch: any
|
|
|
|
beforeEach(() => {
|
|
vi.clearAllMocks()
|
|
mockFetch = vi.fn()
|
|
vi.stubGlobal('fetch', mockFetch)
|
|
})
|
|
|
|
afterEach(() => {
|
|
if (wrapper) {
|
|
wrapper.unmount()
|
|
}
|
|
vi.unstubAllGlobals()
|
|
})
|
|
|
|
describe('Event Listeners', () => {
|
|
it('registers event listeners on mount', () => {
|
|
mockFetch.mockResolvedValue({
|
|
ok: true,
|
|
json: () => Promise.resolve({ first_name: '', last_name: '', email: '', image_id: null }),
|
|
})
|
|
|
|
wrapper = mount(LoginButton)
|
|
|
|
expect(eventBus.on).toHaveBeenCalledWith('open-login', expect.any(Function))
|
|
expect(eventBus.on).toHaveBeenCalledWith('profile_updated', expect.any(Function))
|
|
})
|
|
|
|
it('unregisters event listeners on unmount', () => {
|
|
mockFetch.mockResolvedValue({
|
|
ok: true,
|
|
json: () => Promise.resolve({ first_name: '', last_name: '', email: '', image_id: null }),
|
|
})
|
|
|
|
wrapper = mount(LoginButton)
|
|
wrapper.unmount()
|
|
|
|
expect(eventBus.off).toHaveBeenCalledWith('open-login', expect.any(Function))
|
|
expect(eventBus.off).toHaveBeenCalledWith('profile_updated', expect.any(Function))
|
|
})
|
|
|
|
it('refetches profile when profile_updated event is received', async () => {
|
|
mockFetch
|
|
.mockResolvedValueOnce({
|
|
ok: true,
|
|
json: () => Promise.resolve({ first_name: '', last_name: '', email: '', image_id: null }),
|
|
})
|
|
.mockResolvedValueOnce({
|
|
ok: true,
|
|
json: () =>
|
|
Promise.resolve({
|
|
first_name: 'Updated',
|
|
last_name: 'User',
|
|
email: 'updated@example.com',
|
|
image_id: 'new-image-id',
|
|
}),
|
|
})
|
|
|
|
wrapper = mount(LoginButton)
|
|
|
|
// Get the profile_updated callback
|
|
const profileUpdatedCall = eventBus.on.mock.calls.find(
|
|
(call) => call[0] === 'profile_updated',
|
|
)
|
|
const profileUpdatedCallback = profileUpdatedCall[1]
|
|
|
|
// Call the callback
|
|
await profileUpdatedCallback()
|
|
|
|
// Check that fetch was called for profile
|
|
expect(mockFetch).toHaveBeenCalledWith('/api/user/profile', { credentials: 'include' })
|
|
})
|
|
})
|
|
})
|