cadfa70e60
* #708 apply strictier linting rules and fix simple eslint bugs * #708 fix eslint errors relate to promise * #708 fix eslint import/no-extraneous-dependencies * #708 fix eslint errors of react-hook * #708 enable eslint check for typescript --------- Co-authored-by: lethemanh <lethemanh@lethemanhs-MacBook-Pro.local>
232 lines
6.7 KiB
TypeScript
232 lines
6.7 KiB
TypeScript
import {
|
|
eventToFullCalendarFormat,
|
|
getCalendarVisibility
|
|
} from '@/components/Calendar/utils/calendarUtils'
|
|
import { Calendar, DelegationAccess } from '@/features/Calendars/CalendarTypes'
|
|
import { AclEntry } from '@/features/Calendars/types/CalendarData'
|
|
import { CalendarEvent } from '@/features/Events/EventsTypes'
|
|
import { userOrganiser } from '@/features/User/userDataTypes'
|
|
|
|
describe('getCalendarVisibility', () => {
|
|
it("returns 'public' when {DAV:}authenticated has {DAV:}read", () => {
|
|
const acl: AclEntry[] = [
|
|
{
|
|
privilege: '{DAV:}read',
|
|
principal: '{DAV:}authenticated',
|
|
protected: true
|
|
}
|
|
]
|
|
expect(getCalendarVisibility(acl)).toBe('public')
|
|
})
|
|
|
|
it("returns 'private' when {DAV:}authenticated only has read-free-busy", () => {
|
|
const acl: AclEntry[] = [
|
|
{
|
|
privilege: '{urn:ietf:params:xml:ns:caldav}read-free-busy',
|
|
principal: '{DAV:}authenticated',
|
|
protected: true
|
|
}
|
|
]
|
|
expect(getCalendarVisibility(acl)).toBe('private')
|
|
})
|
|
|
|
it("returns 'private' when {DAV:}authenticated is not present", () => {
|
|
const acl: AclEntry[] = [
|
|
{
|
|
privilege: '{DAV:}read',
|
|
principal: 'principals/users/123',
|
|
protected: true
|
|
}
|
|
]
|
|
expect(getCalendarVisibility(acl)).toBe('private')
|
|
})
|
|
|
|
it("ignores non-authenticated principals and still returns 'private'", () => {
|
|
const acl: AclEntry[] = [
|
|
{
|
|
privilege: '{DAV:}read',
|
|
principal: 'principals/users/other',
|
|
protected: true
|
|
},
|
|
{
|
|
privilege: '{DAV:}write',
|
|
principal: 'principals/users/other',
|
|
protected: true
|
|
}
|
|
]
|
|
expect(getCalendarVisibility(acl)).toBe('private')
|
|
})
|
|
|
|
it('stops early when it finds a {DAV:}read for {DAV:}authenticated', () => {
|
|
const acl: AclEntry[] = [
|
|
{
|
|
privilege: '{DAV:}read',
|
|
principal: '{DAV:}authenticated',
|
|
protected: true
|
|
},
|
|
{
|
|
privilege: '{DAV:}write',
|
|
principal: '{DAV:}authenticated',
|
|
protected: true
|
|
}
|
|
]
|
|
expect(getCalendarVisibility(acl)).toBe('public')
|
|
})
|
|
})
|
|
|
|
jest.mock('twake-i18n', () => ({
|
|
useI18n: () => ({ t: (key: string) => key })
|
|
}))
|
|
|
|
const baseEvent: CalendarEvent = {
|
|
uid: 'event-1',
|
|
calId: 'user1/cal1',
|
|
title: 'Test Event',
|
|
start: '2024-01-15T10:00:00',
|
|
end: '2024-01-15T11:00:00',
|
|
allday: false,
|
|
organizer: { cal_address: 'owner@example.com' } as userOrganiser,
|
|
color: { light: '#FF0000' },
|
|
class: 'PUBLIC'
|
|
} as unknown as CalendarEvent
|
|
|
|
const makeCalendar = (overrides: Partial<Calendar> = {}): Calendar =>
|
|
({
|
|
id: 'user1/cal1',
|
|
name: 'Test Calendar',
|
|
delegated: false,
|
|
access: {} as DelegationAccess,
|
|
owner: { emails: ['alice@example.com'], firstname: 'Alice' },
|
|
color: { light: '#FF0000' },
|
|
events: {},
|
|
...overrides
|
|
}) as Calendar
|
|
|
|
const callFormat = (
|
|
event: CalendarEvent,
|
|
calendars: Record<string, Calendar>,
|
|
userAddress = 'alice@example.com',
|
|
userId = 'user1'
|
|
) =>
|
|
eventToFullCalendarFormat([event], [], userId, userAddress, false, calendars)
|
|
|
|
describe('eventToFullCalendarFormat - editable flag', () => {
|
|
describe('personal calendar (non-delegated)', () => {
|
|
const calendar = makeCalendar({ delegated: false })
|
|
|
|
it('is editable when user is organizer', () => {
|
|
const event = {
|
|
...baseEvent,
|
|
organizer: { cal_address: 'alice@example.com' }
|
|
} as CalendarEvent
|
|
const [result] = callFormat(event, { 'user1/cal1': calendar })
|
|
expect(result.editable).toBe(true)
|
|
})
|
|
|
|
it('is not editable when user is not organizer', () => {
|
|
const event = {
|
|
...baseEvent,
|
|
organizer: { cal_address: 'other@example.com' }
|
|
} as CalendarEvent
|
|
const [result] = callFormat(event, { 'user1/cal1': calendar })
|
|
expect(result.editable).toBe(false)
|
|
})
|
|
|
|
it('is not editable when pending', () => {
|
|
const event = {
|
|
...baseEvent,
|
|
organizer: { cal_address: 'alice@example.com' }
|
|
} as CalendarEvent
|
|
const [result] = eventToFullCalendarFormat(
|
|
[event],
|
|
[],
|
|
'user1',
|
|
'alice@example.com',
|
|
true,
|
|
{ 'user1/cal1': calendar }
|
|
)
|
|
expect(result.editable).toBe(false)
|
|
})
|
|
})
|
|
|
|
describe('delegated calendar', () => {
|
|
const writeDelegatedCalendar = makeCalendar({
|
|
id: 'user2/cal1',
|
|
delegated: true,
|
|
access: { write: true } as DelegationAccess,
|
|
owner: { emails: ['owner@example.com'], firstname: 'Owner' }
|
|
})
|
|
const readDelegatedCalendar = makeCalendar({
|
|
id: 'user2/cal1',
|
|
delegated: true,
|
|
access: { read: true } as DelegationAccess,
|
|
owner: { emails: ['owner@example.com'], firstname: 'Owner' }
|
|
})
|
|
const event = { ...baseEvent, calId: 'user2/cal1' }
|
|
|
|
it('is editable when owner is organizer and delegated user has write rights', () => {
|
|
const [result] = callFormat(
|
|
{
|
|
...event,
|
|
organizer: { cal_address: 'owner@example.com' }
|
|
} as CalendarEvent,
|
|
{ 'user2/cal1': writeDelegatedCalendar }
|
|
)
|
|
expect(result.editable).toBe(true)
|
|
})
|
|
|
|
it('is not editable when owner is organizer but delegated user only has read access', () => {
|
|
const [result] = callFormat(
|
|
{
|
|
...event,
|
|
organizer: { cal_address: 'owner@example.com' }
|
|
} as CalendarEvent,
|
|
{ 'user2/cal1': readDelegatedCalendar }
|
|
)
|
|
expect(result.editable).toBe(false)
|
|
})
|
|
|
|
it('is not editable when owner is not organizer', () => {
|
|
const [result] = callFormat(
|
|
{
|
|
...event,
|
|
organizer: { cal_address: 'someone-else@example.com' }
|
|
} as CalendarEvent,
|
|
{ 'user2/cal1': writeDelegatedCalendar }
|
|
)
|
|
expect(result.editable).toBe(false)
|
|
})
|
|
|
|
it('is not editable when pending even if owner is organizer', () => {
|
|
const [result] = eventToFullCalendarFormat(
|
|
[
|
|
{
|
|
...event,
|
|
organizer: { cal_address: 'owner@example.com' }
|
|
} as CalendarEvent
|
|
],
|
|
[],
|
|
'user1',
|
|
'alice@example.com',
|
|
true,
|
|
{ 'user2/cal1': writeDelegatedCalendar }
|
|
)
|
|
expect(result.editable).toBe(false)
|
|
})
|
|
|
|
it('uses owner email not logged-in user email for organizer check', () => {
|
|
// logged-in user is alice, owner is owner@example.com
|
|
// organizer matches owner → editable
|
|
const [result] = callFormat(
|
|
{
|
|
...event,
|
|
organizer: { cal_address: 'owner@example.com' }
|
|
} as CalendarEvent,
|
|
{ 'user2/cal1': writeDelegatedCalendar },
|
|
'alice@example.com' // logged-in user, should NOT be used for delegated
|
|
)
|
|
expect(result.editable).toBe(true)
|
|
})
|
|
})
|
|
})
|