* #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>
This commit is contained in:
@@ -1,12 +1,12 @@
|
||||
import * as calAPI from "@/features/Calendars/CalendarApi";
|
||||
import * as calAPI from '@/features/Calendars/CalendarApi'
|
||||
import reducer, {
|
||||
addEvent,
|
||||
createCalendar,
|
||||
removeEvent,
|
||||
removeTempCal,
|
||||
updateEventLocal,
|
||||
} from "@/features/Calendars/CalendarSlice";
|
||||
import { Calendar } from "@/features/Calendars/CalendarTypes";
|
||||
updateEventLocal
|
||||
} from '@/features/Calendars/CalendarSlice'
|
||||
import { Calendar } from '@/features/Calendars/CalendarTypes'
|
||||
import {
|
||||
addSharedCalendarAsync,
|
||||
createCalendarAsync,
|
||||
@@ -14,523 +14,523 @@ import {
|
||||
getCalendarsListAsync,
|
||||
getEventAsync,
|
||||
getTempCalendarsListAsync,
|
||||
patchACLCalendarAsync,
|
||||
} from "@/features/Calendars/services";
|
||||
import { CalendarEvent } from "@/features/Events/EventsTypes";
|
||||
import * as userAPI from "@/features/User/userAPI";
|
||||
import userReducer, { setUserData } from "@/features/User/userSlice";
|
||||
import { configureStore } from "@reduxjs/toolkit";
|
||||
patchACLCalendarAsync
|
||||
} from '@/features/Calendars/services'
|
||||
import { CalendarEvent } from '@/features/Events/EventsTypes'
|
||||
import * as userAPI from '@/features/User/userAPI'
|
||||
import userReducer, { setUserData } from '@/features/User/userSlice'
|
||||
import { configureStore } from '@reduxjs/toolkit'
|
||||
|
||||
jest.mock("@/features/Calendars/CalendarApi");
|
||||
jest.mock("@/features/User/userAPI");
|
||||
jest.mock("@/features/Events/EventApi");
|
||||
jest.mock("@/features/Events/utils");
|
||||
jest.mock("@/utils/apiUtils");
|
||||
jest.mock('@/features/Calendars/CalendarApi')
|
||||
jest.mock('@/features/User/userAPI')
|
||||
jest.mock('@/features/Events/EventApi')
|
||||
jest.mock('@/features/Events/utils')
|
||||
jest.mock('@/utils/apiUtils')
|
||||
|
||||
describe("CalendarSlice", () => {
|
||||
describe('CalendarSlice', () => {
|
||||
const initialState = {
|
||||
list: {},
|
||||
templist: {},
|
||||
pending: false,
|
||||
error: null,
|
||||
};
|
||||
error: null
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
jest.resetAllMocks();
|
||||
});
|
||||
jest.resetAllMocks()
|
||||
})
|
||||
|
||||
describe("reducers", () => {
|
||||
it("createCalendar adds new calendar", () => {
|
||||
describe('reducers', () => {
|
||||
it('createCalendar adds new calendar', () => {
|
||||
const action = createCalendar({
|
||||
name: "Test Cal",
|
||||
color: "#ff0000",
|
||||
description: "desc",
|
||||
});
|
||||
const state = reducer(initialState, action);
|
||||
const values = Object.values(state.list);
|
||||
expect(values[0].name).toBe("Test Cal");
|
||||
expect(values[0].color).toBe("#ff0000");
|
||||
});
|
||||
name: 'Test Cal',
|
||||
color: '#ff0000',
|
||||
description: 'desc'
|
||||
})
|
||||
const state = reducer(initialState, action)
|
||||
const values = Object.values(state.list)
|
||||
expect(values[0].name).toBe('Test Cal')
|
||||
expect(values[0].color).toBe('#ff0000')
|
||||
})
|
||||
|
||||
it("addEvent adds event to calendar", () => {
|
||||
const calId = "user/cal";
|
||||
const event = { uid: "event1", title: "My Event" } as any;
|
||||
it('addEvent adds event to calendar', () => {
|
||||
const calId = 'user/cal'
|
||||
const event = { uid: 'event1', title: 'My Event' } as any
|
||||
const stateWithCal = {
|
||||
...initialState,
|
||||
list: { [calId]: { id: calId, events: {} } as any },
|
||||
};
|
||||
list: { [calId]: { id: calId, events: {} } as any }
|
||||
}
|
||||
const state = reducer(
|
||||
stateWithCal,
|
||||
addEvent({ calendarUid: calId, event })
|
||||
);
|
||||
expect(state.list[calId].events["event1"]).toEqual(
|
||||
expect.objectContaining({ uid: "event1" })
|
||||
);
|
||||
});
|
||||
)
|
||||
expect(state.list[calId].events['event1']).toEqual(
|
||||
expect.objectContaining({ uid: 'event1' })
|
||||
)
|
||||
})
|
||||
|
||||
it("removeEvent deletes event", () => {
|
||||
const calId = "user/cal";
|
||||
it('removeEvent deletes event', () => {
|
||||
const calId = 'user/cal'
|
||||
const stateWithEvent = {
|
||||
...initialState,
|
||||
list: {
|
||||
[calId]: {
|
||||
id: calId,
|
||||
events: { e1: { uid: "e1" } },
|
||||
} as unknown as Calendar,
|
||||
},
|
||||
};
|
||||
events: { e1: { uid: 'e1' } }
|
||||
} as unknown as Calendar
|
||||
}
|
||||
}
|
||||
const state = reducer(
|
||||
stateWithEvent,
|
||||
removeEvent({ calendarUid: calId, eventUid: "e1" })
|
||||
);
|
||||
expect(state.list[calId].events).toEqual({});
|
||||
});
|
||||
removeEvent({ calendarUid: calId, eventUid: 'e1' })
|
||||
)
|
||||
expect(state.list[calId].events).toEqual({})
|
||||
})
|
||||
|
||||
it("updateEventLocal updates an event", () => {
|
||||
const calId = "user/cal";
|
||||
it('updateEventLocal updates an event', () => {
|
||||
const calId = 'user/cal'
|
||||
const stateWithEvent = {
|
||||
...initialState,
|
||||
list: {
|
||||
[calId]: {
|
||||
id: calId,
|
||||
events: { e1: { uid: "e1", title: "Old" } },
|
||||
} as unknown as Calendar,
|
||||
},
|
||||
};
|
||||
events: { e1: { uid: 'e1', title: 'Old' } }
|
||||
} as unknown as Calendar
|
||||
}
|
||||
}
|
||||
const state = reducer(
|
||||
stateWithEvent,
|
||||
updateEventLocal({ calId, event: { uid: "e1", title: "New" } as any })
|
||||
);
|
||||
expect(state.list[calId].events.e1.title).toBe("New");
|
||||
});
|
||||
updateEventLocal({ calId, event: { uid: 'e1', title: 'New' } as any })
|
||||
)
|
||||
expect(state.list[calId].events.e1.title).toBe('New')
|
||||
})
|
||||
|
||||
it("removeTempCal deletes temp calendar", () => {
|
||||
it('removeTempCal deletes temp calendar', () => {
|
||||
const stateWithTemp = {
|
||||
...initialState,
|
||||
templist: { temp1: { id: "temp1" } as any },
|
||||
};
|
||||
const state = reducer(stateWithTemp, removeTempCal("temp1"));
|
||||
expect(state.templist).toEqual({});
|
||||
});
|
||||
});
|
||||
templist: { temp1: { id: 'temp1' } as any }
|
||||
}
|
||||
const state = reducer(stateWithTemp, removeTempCal('temp1'))
|
||||
expect(state.templist).toEqual({})
|
||||
})
|
||||
})
|
||||
|
||||
describe("extraReducers (thunks)", () => {
|
||||
describe('extraReducers (thunks)', () => {
|
||||
const storeFactory = () =>
|
||||
configureStore({
|
||||
reducer: { calendars: reducer, user: userReducer },
|
||||
});
|
||||
reducer: { calendars: reducer, user: userReducer }
|
||||
})
|
||||
beforeEach(() => {
|
||||
jest.resetAllMocks();
|
||||
});
|
||||
it("getCalendarsListAsync.fulfilled replaces list", async () => {
|
||||
(userAPI.getOpenPaasUser as jest.Mock).mockResolvedValue({ id: "u1" });
|
||||
(calAPI.getCalendars as jest.Mock).mockResolvedValue({
|
||||
_embedded: { "dav:calendar": [] },
|
||||
});
|
||||
(userAPI.getUserDetails as jest.Mock).mockResolvedValue({
|
||||
firstname: "Alice",
|
||||
lastname: "Smith",
|
||||
emails: ["a@b.com"],
|
||||
});
|
||||
jest.resetAllMocks()
|
||||
})
|
||||
it('getCalendarsListAsync.fulfilled replaces list', async () => {
|
||||
;(userAPI.getOpenPaasUser as jest.Mock).mockResolvedValue({ id: 'u1' })
|
||||
;(calAPI.getCalendars as jest.Mock).mockResolvedValue({
|
||||
_embedded: { 'dav:calendar': [] }
|
||||
})
|
||||
;(userAPI.getUserDetails as jest.Mock).mockResolvedValue({
|
||||
firstname: 'Alice',
|
||||
lastname: 'Smith',
|
||||
emails: ['a@b.com']
|
||||
})
|
||||
|
||||
const store = storeFactory();
|
||||
await store.dispatch(getCalendarsListAsync() as any);
|
||||
const state = store.getState().calendars;
|
||||
expect(state.list).toEqual({});
|
||||
});
|
||||
const store = storeFactory()
|
||||
await store.dispatch(getCalendarsListAsync() as any)
|
||||
const state = store.getState().calendars
|
||||
expect(state.list).toEqual({})
|
||||
})
|
||||
|
||||
it("getCalendarsListAsync loads user details in parallel for multiple owners", async () => {
|
||||
it('getCalendarsListAsync loads user details in parallel for multiple owners', async () => {
|
||||
const mockCalendars = [
|
||||
{
|
||||
_links: { self: { href: "/calendars/u1/cal1.json" } },
|
||||
"dav:name": "Calendar 1",
|
||||
"apple:color": "#FF0000",
|
||||
acl: [],
|
||||
_links: { self: { href: '/calendars/u1/cal1.json' } },
|
||||
'dav:name': 'Calendar 1',
|
||||
'apple:color': '#FF0000',
|
||||
acl: []
|
||||
},
|
||||
{
|
||||
_links: { self: { href: "/calendars/u2/cal2.json" } },
|
||||
"dav:name": "Calendar 2",
|
||||
"apple:color": "#00FF00",
|
||||
acl: [],
|
||||
_links: { self: { href: '/calendars/u2/cal2.json' } },
|
||||
'dav:name': 'Calendar 2',
|
||||
'apple:color': '#00FF00',
|
||||
acl: []
|
||||
},
|
||||
{
|
||||
_links: { self: { href: "/calendars/u3/cal3.json" } },
|
||||
"dav:name": "Calendar 3",
|
||||
"apple:color": "#0000FF",
|
||||
acl: [],
|
||||
},
|
||||
];
|
||||
_links: { self: { href: '/calendars/u3/cal3.json' } },
|
||||
'dav:name': 'Calendar 3',
|
||||
'apple:color': '#0000FF',
|
||||
acl: []
|
||||
}
|
||||
]
|
||||
|
||||
(userAPI.getOpenPaasUser as jest.Mock).mockResolvedValue({ id: "u1" });
|
||||
(calAPI.getCalendars as jest.Mock).mockResolvedValue({
|
||||
_embedded: { "dav:calendar": mockCalendars },
|
||||
});
|
||||
;(userAPI.getOpenPaasUser as jest.Mock).mockResolvedValue({ id: 'u1' })
|
||||
;(calAPI.getCalendars as jest.Mock).mockResolvedValue({
|
||||
_embedded: { 'dav:calendar': mockCalendars }
|
||||
})
|
||||
|
||||
const getUserDetailsMock = userAPI.getUserDetails as jest.Mock;
|
||||
const getUserDetailsMock = userAPI.getUserDetails as jest.Mock
|
||||
getUserDetailsMock
|
||||
.mockResolvedValueOnce({
|
||||
firstname: "Alice",
|
||||
lastname: "Smith",
|
||||
emails: ["alice@example.com"],
|
||||
firstname: 'Alice',
|
||||
lastname: 'Smith',
|
||||
emails: ['alice@example.com']
|
||||
})
|
||||
.mockResolvedValueOnce({
|
||||
firstname: "Bob",
|
||||
lastname: "Jones",
|
||||
emails: ["bob@example.com"],
|
||||
firstname: 'Bob',
|
||||
lastname: 'Jones',
|
||||
emails: ['bob@example.com']
|
||||
})
|
||||
.mockResolvedValueOnce({
|
||||
firstname: "Charlie",
|
||||
lastname: "Brown",
|
||||
emails: ["charlie@example.com"],
|
||||
});
|
||||
firstname: 'Charlie',
|
||||
lastname: 'Brown',
|
||||
emails: ['charlie@example.com']
|
||||
})
|
||||
|
||||
const store = storeFactory();
|
||||
await store.dispatch(getCalendarsListAsync() as any);
|
||||
const store = storeFactory()
|
||||
await store.dispatch(getCalendarsListAsync() as any)
|
||||
|
||||
expect(getUserDetailsMock).toHaveBeenCalledTimes(3);
|
||||
expect(getUserDetailsMock).toHaveBeenCalledWith("u1");
|
||||
expect(getUserDetailsMock).toHaveBeenCalledWith("u2");
|
||||
expect(getUserDetailsMock).toHaveBeenCalledWith("u3");
|
||||
expect(getUserDetailsMock).toHaveBeenCalledTimes(3)
|
||||
expect(getUserDetailsMock).toHaveBeenCalledWith('u1')
|
||||
expect(getUserDetailsMock).toHaveBeenCalledWith('u2')
|
||||
expect(getUserDetailsMock).toHaveBeenCalledWith('u3')
|
||||
|
||||
const state = store.getState().calendars;
|
||||
expect(state.list["u1/cal1"].owner.firstname).toContain("Alice");
|
||||
expect(state.list["u2/cal2"].owner.firstname).toContain("Bob");
|
||||
expect(state.list["u3/cal3"].owner.firstname).toContain("Charlie");
|
||||
});
|
||||
const state = store.getState().calendars
|
||||
expect(state.list['u1/cal1'].owner.firstname).toContain('Alice')
|
||||
expect(state.list['u2/cal2'].owner.firstname).toContain('Bob')
|
||||
expect(state.list['u3/cal3'].owner.firstname).toContain('Charlie')
|
||||
})
|
||||
|
||||
it("getCalendarsListAsync deduplicates getUserDetails calls for same ownerId", async () => {
|
||||
it('getCalendarsListAsync deduplicates getUserDetails calls for same ownerId', async () => {
|
||||
const mockCalendars = [
|
||||
{
|
||||
_links: { self: { href: "/calendars/u1/cal1.json" } },
|
||||
"dav:name": "Calendar 1",
|
||||
"apple:color": "#FF0000",
|
||||
acl: [],
|
||||
_links: { self: { href: '/calendars/u1/cal1.json' } },
|
||||
'dav:name': 'Calendar 1',
|
||||
'apple:color': '#FF0000',
|
||||
acl: []
|
||||
},
|
||||
{
|
||||
_links: { self: { href: "/calendars/u1/cal2.json" } },
|
||||
"dav:name": "Calendar 2",
|
||||
"apple:color": "#00FF00",
|
||||
acl: [],
|
||||
_links: { self: { href: '/calendars/u1/cal2.json' } },
|
||||
'dav:name': 'Calendar 2',
|
||||
'apple:color': '#00FF00',
|
||||
acl: []
|
||||
},
|
||||
{
|
||||
_links: { self: { href: "/calendars/u1/cal3.json" } },
|
||||
"dav:name": "Calendar 3",
|
||||
"apple:color": "#0000FF",
|
||||
acl: [],
|
||||
},
|
||||
];
|
||||
_links: { self: { href: '/calendars/u1/cal3.json' } },
|
||||
'dav:name': 'Calendar 3',
|
||||
'apple:color': '#0000FF',
|
||||
acl: []
|
||||
}
|
||||
]
|
||||
|
||||
(userAPI.getOpenPaasUser as jest.Mock).mockResolvedValue({ id: "u1" });
|
||||
(calAPI.getCalendars as jest.Mock).mockResolvedValue({
|
||||
_embedded: { "dav:calendar": mockCalendars },
|
||||
});
|
||||
;(userAPI.getOpenPaasUser as jest.Mock).mockResolvedValue({ id: 'u1' })
|
||||
;(calAPI.getCalendars as jest.Mock).mockResolvedValue({
|
||||
_embedded: { 'dav:calendar': mockCalendars }
|
||||
})
|
||||
|
||||
const getUserDetailsMock = userAPI.getUserDetails as jest.Mock;
|
||||
const getUserDetailsMock = userAPI.getUserDetails as jest.Mock
|
||||
getUserDetailsMock.mockResolvedValue({
|
||||
firstname: "Alice",
|
||||
lastname: "Smith",
|
||||
emails: ["alice@example.com"],
|
||||
});
|
||||
firstname: 'Alice',
|
||||
lastname: 'Smith',
|
||||
emails: ['alice@example.com']
|
||||
})
|
||||
|
||||
const store = storeFactory();
|
||||
await store.dispatch(getCalendarsListAsync() as any);
|
||||
const store = storeFactory()
|
||||
await store.dispatch(getCalendarsListAsync() as any)
|
||||
|
||||
expect(getUserDetailsMock).toHaveBeenCalledTimes(1);
|
||||
expect(getUserDetailsMock).toHaveBeenCalledWith("u1");
|
||||
});
|
||||
expect(getUserDetailsMock).toHaveBeenCalledTimes(1)
|
||||
expect(getUserDetailsMock).toHaveBeenCalledWith('u1')
|
||||
})
|
||||
|
||||
it("getCalendarsListAsync processes owners in batches of 20", async () => {
|
||||
it('getCalendarsListAsync processes owners in batches of 20', async () => {
|
||||
const mockCalendars = Array.from({ length: 45 }, (_, i) => ({
|
||||
_links: { self: { href: `/calendars/u${i + 1}/cal${i + 1}.json` } },
|
||||
"dav:name": `Calendar ${i + 1}`,
|
||||
"apple:color": "#FF0000",
|
||||
acl: [],
|
||||
}));
|
||||
'dav:name': `Calendar ${i + 1}`,
|
||||
'apple:color': '#FF0000',
|
||||
acl: []
|
||||
}))
|
||||
|
||||
(userAPI.getOpenPaasUser as jest.Mock).mockResolvedValue({ id: "u1" });
|
||||
(calAPI.getCalendars as jest.Mock).mockResolvedValue({
|
||||
_embedded: { "dav:calendar": mockCalendars },
|
||||
});
|
||||
;(userAPI.getOpenPaasUser as jest.Mock).mockResolvedValue({ id: 'u1' })
|
||||
;(calAPI.getCalendars as jest.Mock).mockResolvedValue({
|
||||
_embedded: { 'dav:calendar': mockCalendars }
|
||||
})
|
||||
|
||||
const getUserDetailsMock = userAPI.getUserDetails as jest.Mock;
|
||||
const getUserDetailsMock = userAPI.getUserDetails as jest.Mock
|
||||
getUserDetailsMock.mockImplementation((ownerId: string) =>
|
||||
Promise.resolve({
|
||||
firstname: "User",
|
||||
firstname: 'User',
|
||||
lastname: ownerId,
|
||||
emails: [`${ownerId}@example.com`],
|
||||
emails: [`${ownerId}@example.com`]
|
||||
})
|
||||
);
|
||||
)
|
||||
|
||||
const store = storeFactory();
|
||||
await store.dispatch(getCalendarsListAsync() as any);
|
||||
const store = storeFactory()
|
||||
await store.dispatch(getCalendarsListAsync() as any)
|
||||
|
||||
expect(getUserDetailsMock).toHaveBeenCalledTimes(45);
|
||||
const state = store.getState().calendars;
|
||||
expect(Object.keys(state.list)).toHaveLength(45);
|
||||
});
|
||||
expect(getUserDetailsMock).toHaveBeenCalledTimes(45)
|
||||
const state = store.getState().calendars
|
||||
expect(Object.keys(state.list)).toHaveLength(45)
|
||||
})
|
||||
|
||||
it("getCalendarsListAsync doesnt call getUserDetails if userdata exist in store", async () => {
|
||||
it('getCalendarsListAsync doesnt call getUserDetails if userdata exist in store', async () => {
|
||||
const existingCalendars = {
|
||||
"u1/cal1": {
|
||||
id: "u1/cal1",
|
||||
name: "Existing Calendar",
|
||||
events: {},
|
||||
} as Calendar,
|
||||
};
|
||||
'u1/cal1': {
|
||||
id: 'u1/cal1',
|
||||
name: 'Existing Calendar',
|
||||
events: {}
|
||||
} as Calendar
|
||||
}
|
||||
|
||||
const store = storeFactory();
|
||||
const store = storeFactory()
|
||||
store.dispatch({
|
||||
type: "calendars/getCalendars/fulfilled",
|
||||
payload: { importedCalendars: existingCalendars, errors: "" },
|
||||
});
|
||||
store.dispatch(setUserData({ openpaasId: "bla" }));
|
||||
const getUserDetailsMock = userAPI.getUserDetails as jest.Mock;
|
||||
type: 'calendars/getCalendars/fulfilled',
|
||||
payload: { importedCalendars: existingCalendars, errors: '' }
|
||||
})
|
||||
store.dispatch(setUserData({ openpaasId: 'bla' }))
|
||||
const getUserDetailsMock = userAPI.getUserDetails as jest.Mock
|
||||
|
||||
await store.dispatch(getCalendarsListAsync() as any);
|
||||
await store.dispatch(getCalendarsListAsync() as any)
|
||||
|
||||
expect(getUserDetailsMock).not.toHaveBeenCalled();
|
||||
expect(getUserDetailsMock).not.toHaveBeenCalled()
|
||||
|
||||
const state = store.getState().calendars;
|
||||
expect(state.list).toEqual(existingCalendars);
|
||||
});
|
||||
const state = store.getState().calendars
|
||||
expect(state.list).toEqual(existingCalendars)
|
||||
})
|
||||
|
||||
it("getCalendarsListAsync handles errors in getUserDetails gracefully", async () => {
|
||||
it('getCalendarsListAsync handles errors in getUserDetails gracefully', async () => {
|
||||
const mockCalendars = [
|
||||
{
|
||||
_links: { self: { href: "/calendars/u1/cal1.json" } },
|
||||
"dav:name": "Calendar 1",
|
||||
"apple:color": "#FF0000",
|
||||
acl: [],
|
||||
_links: { self: { href: '/calendars/u1/cal1.json' } },
|
||||
'dav:name': 'Calendar 1',
|
||||
'apple:color': '#FF0000',
|
||||
acl: []
|
||||
},
|
||||
{
|
||||
_links: { self: { href: "/calendars/u2/cal2.json" } },
|
||||
"dav:name": "Calendar 2",
|
||||
"apple:color": "#00FF00",
|
||||
acl: [],
|
||||
},
|
||||
];
|
||||
_links: { self: { href: '/calendars/u2/cal2.json' } },
|
||||
'dav:name': 'Calendar 2',
|
||||
'apple:color': '#00FF00',
|
||||
acl: []
|
||||
}
|
||||
]
|
||||
|
||||
(userAPI.getOpenPaasUser as jest.Mock).mockResolvedValue({ id: "u1" });
|
||||
(calAPI.getCalendars as jest.Mock).mockResolvedValue({
|
||||
_embedded: { "dav:calendar": mockCalendars },
|
||||
});
|
||||
;(userAPI.getOpenPaasUser as jest.Mock).mockResolvedValue({ id: 'u1' })
|
||||
;(calAPI.getCalendars as jest.Mock).mockResolvedValue({
|
||||
_embedded: { 'dav:calendar': mockCalendars }
|
||||
})
|
||||
|
||||
const getUserDetailsMock = userAPI.getUserDetails as jest.Mock;
|
||||
const getUserDetailsMock = userAPI.getUserDetails as jest.Mock
|
||||
getUserDetailsMock
|
||||
.mockResolvedValueOnce({
|
||||
firstname: "Alice",
|
||||
lastname: "Smith",
|
||||
emails: ["alice@example.com"],
|
||||
firstname: 'Alice',
|
||||
lastname: 'Smith',
|
||||
emails: ['alice@example.com']
|
||||
})
|
||||
.mockRejectedValueOnce(new Error("Failed to fetch user"));
|
||||
.mockRejectedValueOnce(new Error('Failed to fetch user'))
|
||||
|
||||
const store = storeFactory();
|
||||
const result = await store.dispatch(getCalendarsListAsync() as any);
|
||||
const store = storeFactory()
|
||||
const result = await store.dispatch(getCalendarsListAsync() as any)
|
||||
|
||||
expect(getUserDetailsMock).toHaveBeenCalledTimes(2);
|
||||
const state = store.getState().calendars;
|
||||
expect(state.list["u1/cal1"].owner.firstname).toContain("Alice");
|
||||
expect(state.list["u2/cal2"].owner.lastname).toContain("Unknown User");
|
||||
expect(result.payload.errors).toBeTruthy();
|
||||
});
|
||||
expect(getUserDetailsMock).toHaveBeenCalledTimes(2)
|
||||
const state = store.getState().calendars
|
||||
expect(state.list['u1/cal1'].owner.firstname).toContain('Alice')
|
||||
expect(state.list['u2/cal2'].owner.lastname).toContain('Unknown User')
|
||||
expect(result.payload.errors).toBeTruthy()
|
||||
})
|
||||
|
||||
it("patchACLCalendarAsync.fulfilled sets visibility", () => {
|
||||
it('patchACLCalendarAsync.fulfilled sets visibility', () => {
|
||||
const prev = {
|
||||
...initialState,
|
||||
list: { c1: { id: "c1", visibility: "public" } as any },
|
||||
};
|
||||
list: { c1: { id: 'c1', visibility: 'public' } as any }
|
||||
}
|
||||
const state = reducer(
|
||||
prev,
|
||||
patchACLCalendarAsync.fulfilled(
|
||||
{ calId: "c1", calLink: "l", request: "" },
|
||||
"req3",
|
||||
{ calId: "c1", calLink: "l", request: "" }
|
||||
{ calId: 'c1', calLink: 'l', request: '' },
|
||||
'req3',
|
||||
{ calId: 'c1', calLink: 'l', request: '' }
|
||||
)
|
||||
);
|
||||
expect(state.list.c1.visibility).toBe("private");
|
||||
});
|
||||
)
|
||||
expect(state.list.c1.visibility).toBe('private')
|
||||
})
|
||||
|
||||
it("createCalendarAsync.fulfilled adds a new calendar", () => {
|
||||
it('createCalendarAsync.fulfilled adds a new calendar', () => {
|
||||
const payload = {
|
||||
userData: {
|
||||
openpaasId: "u1",
|
||||
family_name: "Owner",
|
||||
email: "o@example.com",
|
||||
sid: "",
|
||||
sub: "",
|
||||
given_name: "Test",
|
||||
name: "Test Owner",
|
||||
openpaasId: 'u1',
|
||||
family_name: 'Owner',
|
||||
email: 'o@example.com',
|
||||
sid: '',
|
||||
sub: '',
|
||||
given_name: 'Test',
|
||||
name: 'Test Owner'
|
||||
},
|
||||
calId: "cal1",
|
||||
color: { "apple:color": "#f00" },
|
||||
name: "Test",
|
||||
desc: "Desc",
|
||||
};
|
||||
calId: 'cal1',
|
||||
color: { 'apple:color': '#f00' },
|
||||
name: 'Test',
|
||||
desc: 'Desc'
|
||||
}
|
||||
|
||||
const payloadResponse = {
|
||||
userId: "u1",
|
||||
calId: "cal1",
|
||||
color: { "apple:color": "#f00" },
|
||||
name: "Test",
|
||||
desc: "Desc",
|
||||
owner: { firstname: "Owner", emails: ["o@example.com"] },
|
||||
};
|
||||
userId: 'u1',
|
||||
calId: 'cal1',
|
||||
color: { 'apple:color': '#f00' },
|
||||
name: 'Test',
|
||||
desc: 'Desc',
|
||||
owner: { firstname: 'Owner', emails: ['o@example.com'] }
|
||||
}
|
||||
const state = reducer(
|
||||
initialState,
|
||||
createCalendarAsync.fulfilled(payloadResponse, "req4", payload)
|
||||
);
|
||||
expect(state.list["u1/cal1"].name).toBe("Test");
|
||||
expect(state.list["u1/cal1"].color?.["apple:color"]).toBe("#f00");
|
||||
});
|
||||
createCalendarAsync.fulfilled(payloadResponse, 'req4', payload)
|
||||
)
|
||||
expect(state.list['u1/cal1'].name).toBe('Test')
|
||||
expect(state.list['u1/cal1'].color?.['apple:color']).toBe('#f00')
|
||||
})
|
||||
|
||||
it("addSharedCalendarAsync.fulfilled adds shared calendar", () => {
|
||||
it('addSharedCalendarAsync.fulfilled adds shared calendar', () => {
|
||||
const payload = {
|
||||
calId: "c1",
|
||||
color: { "apple:color": "#0f0" },
|
||||
link: "/calendars/u1/c1.json",
|
||||
name: "Shared",
|
||||
desc: "Shared Desc",
|
||||
owner: { firstname: "O", emails: ["o@example.com"] },
|
||||
};
|
||||
calId: 'c1',
|
||||
color: { 'apple:color': '#0f0' },
|
||||
link: '/calendars/u1/c1.json',
|
||||
name: 'Shared',
|
||||
desc: 'Shared Desc',
|
||||
owner: { firstname: 'O', emails: ['o@example.com'] }
|
||||
}
|
||||
const mockCal = {
|
||||
cal: {
|
||||
_links: { self: { href: "/calendars/u1/c1.json" } },
|
||||
"apple:color": "#0f0",
|
||||
"caldav:description": "Shared Desc",
|
||||
"dav:name": "Shared",
|
||||
},
|
||||
};
|
||||
_links: { self: { href: '/calendars/u1/c1.json' } },
|
||||
'apple:color': '#0f0',
|
||||
'caldav:description': 'Shared Desc',
|
||||
'dav:name': 'Shared'
|
||||
}
|
||||
}
|
||||
const state = reducer(
|
||||
initialState,
|
||||
addSharedCalendarAsync.fulfilled(payload, "req5", {
|
||||
userId: "u1",
|
||||
calId: "c1",
|
||||
cal: mockCal,
|
||||
addSharedCalendarAsync.fulfilled(payload, 'req5', {
|
||||
userId: 'u1',
|
||||
calId: 'c1',
|
||||
cal: mockCal
|
||||
})
|
||||
);
|
||||
expect(state.list["c1"].name).toBe("Shared");
|
||||
});
|
||||
)
|
||||
expect(state.list['c1'].name).toBe('Shared')
|
||||
})
|
||||
|
||||
it("getTempCalendarsListAsync.fulfilled updates templist", () => {
|
||||
it('getTempCalendarsListAsync.fulfilled updates templist', () => {
|
||||
const payload = {
|
||||
t1: {
|
||||
id: "t1",
|
||||
name: "Temp",
|
||||
color: { "apple:color": "#aaa" },
|
||||
id: 't1',
|
||||
name: 'Temp',
|
||||
color: { 'apple:color': '#aaa' },
|
||||
events: {},
|
||||
visibility: "public",
|
||||
owner: { firstname: "O", emails: ["o@o.com"] },
|
||||
link: "/calendars/t1.json",
|
||||
description: "desc",
|
||||
} as Calendar,
|
||||
};
|
||||
visibility: 'public',
|
||||
owner: { firstname: 'O', emails: ['o@o.com'] },
|
||||
link: '/calendars/t1.json',
|
||||
description: 'desc'
|
||||
} as Calendar
|
||||
}
|
||||
const state = reducer(
|
||||
initialState,
|
||||
getTempCalendarsListAsync.fulfilled(payload, "req7", {
|
||||
openpaasId: "u1",
|
||||
color: { "apple:color": "#aaa" },
|
||||
displayName: "test",
|
||||
avatarUrl: "",
|
||||
email: "test@test.com",
|
||||
getTempCalendarsListAsync.fulfilled(payload, 'req7', {
|
||||
openpaasId: 'u1',
|
||||
color: { 'apple:color': '#aaa' },
|
||||
displayName: 'test',
|
||||
avatarUrl: '',
|
||||
email: 'test@test.com'
|
||||
})
|
||||
);
|
||||
expect(state.templist.t1.name).toBe("Temp");
|
||||
});
|
||||
)
|
||||
expect(state.templist.t1.name).toBe('Temp')
|
||||
})
|
||||
|
||||
it("getEventAsync.fulfilled adds single event", () => {
|
||||
const payload = { calId: "c1", event: { uid: "e1" } as any };
|
||||
it('getEventAsync.fulfilled adds single event', () => {
|
||||
const payload = { calId: 'c1', event: { uid: 'e1' } as any }
|
||||
const state = reducer(
|
||||
initialState,
|
||||
getEventAsync.fulfilled(payload, "req9", { uid: "e1" } as any)
|
||||
);
|
||||
expect(state.list.c1.events.e1.uid).toBe("e1");
|
||||
});
|
||||
getEventAsync.fulfilled(payload, 'req9', { uid: 'e1' } as any)
|
||||
)
|
||||
expect(state.list.c1.events.e1.uid).toBe('e1')
|
||||
})
|
||||
|
||||
it("getCalendarDetailAsync.fulfilled adds calendar events", () => {
|
||||
const payload = { calId: "c1", events: [{ uid: "e1" }] as any[] };
|
||||
it('getCalendarDetailAsync.fulfilled adds calendar events', () => {
|
||||
const payload = { calId: 'c1', events: [{ uid: 'e1' }] as any[] }
|
||||
const state = reducer(
|
||||
{
|
||||
...initialState,
|
||||
list: {
|
||||
["c1"]: {
|
||||
id: "c1",
|
||||
events: {},
|
||||
} as unknown as Calendar,
|
||||
},
|
||||
['c1']: {
|
||||
id: 'c1',
|
||||
events: {}
|
||||
} as unknown as Calendar
|
||||
}
|
||||
},
|
||||
getCalendarDetailAsync.fulfilled(payload, "req11", {
|
||||
calId: "c1",
|
||||
match: { start: "", end: "" },
|
||||
getCalendarDetailAsync.fulfilled(payload, 'req11', {
|
||||
calId: 'c1',
|
||||
match: { start: '', end: '' }
|
||||
})
|
||||
);
|
||||
expect(state.list.c1.events.e1.uid).toBe("e1");
|
||||
});
|
||||
)
|
||||
expect(state.list.c1.events.e1.uid).toBe('e1')
|
||||
})
|
||||
|
||||
it("getEventAsync.fulfilled doesnt create new events when there are already event with base UID", () => {
|
||||
const baseUid = "recurring-event-base";
|
||||
it('getEventAsync.fulfilled doesnt create new events when there are already event with base UID', () => {
|
||||
const baseUid = 'recurring-event-base'
|
||||
const existingEvent = {
|
||||
uid: `${baseUid}/20240115`,
|
||||
title: "Existing Recurring Event",
|
||||
recurrenceId: null,
|
||||
} as unknown as CalendarEvent;
|
||||
title: 'Existing Recurring Event',
|
||||
recurrenceId: null
|
||||
} as unknown as CalendarEvent
|
||||
|
||||
const newEventInstance = {
|
||||
uid: baseUid,
|
||||
title: "Fetched Master Event",
|
||||
recurrenceId: "20240115",
|
||||
} as CalendarEvent;
|
||||
title: 'Fetched Master Event',
|
||||
recurrenceId: '20240115'
|
||||
} as CalendarEvent
|
||||
|
||||
const stateWithEvent = {
|
||||
...initialState,
|
||||
list: {
|
||||
c1: {
|
||||
id: "c1",
|
||||
events: { [`${baseUid}/20240115`]: existingEvent },
|
||||
} as unknown as Calendar,
|
||||
},
|
||||
};
|
||||
id: 'c1',
|
||||
events: { [`${baseUid}/20240115`]: existingEvent }
|
||||
} as unknown as Calendar
|
||||
}
|
||||
}
|
||||
|
||||
const payload = { calId: "c1", event: newEventInstance };
|
||||
const payload = { calId: 'c1', event: newEventInstance }
|
||||
const state = reducer(
|
||||
stateWithEvent,
|
||||
getEventAsync.fulfilled(payload, "req", newEventInstance)
|
||||
);
|
||||
getEventAsync.fulfilled(payload, 'req', newEventInstance)
|
||||
)
|
||||
|
||||
// Should still only have the base event, not the instance
|
||||
expect(Object.keys(state.list.c1.events)).toHaveLength(1);
|
||||
expect(state.list.c1.events[`${baseUid}/20240115`]).toBeDefined();
|
||||
expect(state.list.c1.events[baseUid]).toBeUndefined();
|
||||
});
|
||||
expect(Object.keys(state.list.c1.events)).toHaveLength(1)
|
||||
expect(state.list.c1.events[`${baseUid}/20240115`]).toBeDefined()
|
||||
expect(state.list.c1.events[baseUid]).toBeUndefined()
|
||||
})
|
||||
|
||||
it("getEventAsync.fulfilled create new event when there isn't any event with base UID", () => {
|
||||
const eventUid = "new-event-uid";
|
||||
const eventUid = 'new-event-uid'
|
||||
const newEvent = {
|
||||
uid: eventUid,
|
||||
title: "New Event",
|
||||
recurrenceId: null,
|
||||
} as unknown as CalendarEvent;
|
||||
title: 'New Event',
|
||||
recurrenceId: null
|
||||
} as unknown as CalendarEvent
|
||||
|
||||
const stateWithoutEvent = {
|
||||
...initialState,
|
||||
list: {
|
||||
c1: {
|
||||
id: "c1",
|
||||
events: {},
|
||||
} as unknown as Calendar,
|
||||
},
|
||||
};
|
||||
id: 'c1',
|
||||
events: {}
|
||||
} as unknown as Calendar
|
||||
}
|
||||
}
|
||||
|
||||
const payload = { calId: "c1", event: newEvent };
|
||||
const payload = { calId: 'c1', event: newEvent }
|
||||
const state = reducer(
|
||||
stateWithoutEvent,
|
||||
getEventAsync.fulfilled(payload, "req", newEvent)
|
||||
);
|
||||
getEventAsync.fulfilled(payload, 'req', newEvent)
|
||||
)
|
||||
|
||||
// Should create the new event
|
||||
expect(Object.keys(state.list.c1.events)).toHaveLength(1);
|
||||
expect(state.list.c1.events[eventUid]).toBeDefined();
|
||||
expect(state.list.c1.events[eventUid].uid).toBe(eventUid);
|
||||
expect(state.list.c1.events[eventUid].title).toBe("New Event");
|
||||
});
|
||||
});
|
||||
});
|
||||
expect(Object.keys(state.list.c1.events)).toHaveLength(1)
|
||||
expect(state.list.c1.events[eventUid]).toBeDefined()
|
||||
expect(state.list.c1.events[eventUid].uid).toBe(eventUid)
|
||||
expect(state.list.c1.events[eventUid].title).toBe('New Event')
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user