@getmicdrop/svelte-components 2.0.6 → 2.0.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -3,10 +3,10 @@
3
3
  import { writable } from "svelte/store";
4
4
  import { jwtDecode } from "jwt-decode";
5
5
  import QuarterView from "../../Calendar/QuarterView.svelte";
6
- import { timeAgo } from "../../utils/utils/utils";
7
- import { buildApiUrl, API_ENDPOINTS } from "../../utils/apiConfig.js";
8
- import { auth, initializeAuthState } from "../../stores/auth.js";
9
- import microphonePlaceholder from "../../assets/images/microphone.png";
6
+ import { timeAgo } from "../../../utils/utils/utils";
7
+ import { buildApiUrl, API_ENDPOINTS } from "../../../utils/apiConfig.js";
8
+ import { auth, initializeAuthState } from "../../../stores/auth.js";
9
+ import microphonePlaceholder from "../../../assets/images/microphone.png";
10
10
 
11
11
  export let show = false;
12
12
  export let venue = null;
@@ -1,5 +1,5 @@
1
1
  <script>
2
- import { microphonePlaceholder } from "../../utils/utils";
2
+ import { microphonePlaceholder } from "../../../utils/utils";
3
3
 
4
4
  export let image;
5
5
  export let title;
@@ -3,14 +3,14 @@
3
3
  import Icon from "../../Icons/Icon.svelte";
4
4
  import Input from "../../Input/Input.svelte";
5
5
  import Modal from "../../Modal/Modal.svelte";
6
- import { showToast } from "../../stores/toaster";
7
- import { microphonePlaceholder, getUserDetails } from "../../utils/utils";
6
+ import { showToast } from "../../../stores/toaster";
7
+ import { microphonePlaceholder, getUserDetails } from "../../../utils/utils";
8
8
  import {
9
9
  formatHour,
10
10
  formattedDate,
11
11
  formattedFullDate,
12
12
  timeAgo,
13
- } from "../../utils/utils/utils";
13
+ } from "../../../utils/utils/utils";
14
14
  import {
15
15
  acceptInvite,
16
16
  declineInvite,
@@ -1,5 +1,5 @@
1
1
  <script>
2
- import { parseLocation, microphonePlaceholder } from "../../utils/utils";
2
+ import { parseLocation, microphonePlaceholder } from "../../../utils/utils";
3
3
 
4
4
  export let name = "";
5
5
  export let image = "";
@@ -2,10 +2,10 @@
2
2
  import Input from "../../Input/Input.svelte";
3
3
  import Modal from "../../Modal/Modal.svelte";
4
4
  import VenueInfo from "./VenueInfo.svelte";
5
- import { showToast } from "../../stores/toaster";
6
- import { getPerformerToken } from "../../utils/utils";
7
- import { timeAgo } from "../../utils/utils/utils";
8
- import { buildApiUrl, API_ENDPOINTS } from "../../utils/apiConfig";
5
+ import { showToast } from "../../../stores/toaster";
6
+ import { getPerformerToken } from "../../../utils/utils";
7
+ import { timeAgo } from "../../../utils/utils/utils";
8
+ import { buildApiUrl, API_ENDPOINTS } from "../../../utils/apiConfig";
9
9
  import { Dropdown, DropdownItem } from "flowbite-svelte";
10
10
  import { DotsHorizontalOutline } from "flowbite-svelte-icons";
11
11
  import Button from "../../Button/Button.svelte";
@@ -4,10 +4,10 @@
4
4
  export let readonly = false;
5
5
  export let shape = "default";
6
6
  export let label = "";
7
- import CancelIcon from "../../../assets/svg/cancel.svg";
7
+ import CancelIcon from "../../../../assets/svg/cancel.svg";
8
8
 
9
- import AddMain from "../../../assets/svg/add-main-01.svg";
10
- import CloudUpload from "../../../assets/svg/cloud-upload.svg";
9
+ import AddMain from "../../../../assets/svg/add-main-01.svg";
10
+ import CloudUpload from "../../../../assets/svg/cloud-upload.svg";
11
11
 
12
12
  let images = [];
13
13
  let error = "";
@@ -0,0 +1,5 @@
1
+ export function fetchEventsFromAPI(): Promise<any>;
2
+ export function fetchEventsForMonth(year: any, month: any): Promise<any>;
3
+ export function fetchEventsForWeek(date: any): Promise<any>;
4
+ export function fetchEventsForDay(date: any): Promise<any>;
5
+ //# sourceMappingURL=EventService.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"EventService.d.ts","sourceRoot":"","sources":["../../src/lib/services/EventService.js"],"names":[],"mappings":"AAIA,mDAkBC;AAED,yEAYC;AAED,4DAkBC;AAED,2DAgBC"}
@@ -0,0 +1,75 @@
1
+ import { addDays, startOfWeek } from "date-fns";
2
+
3
+ let mockEvents = [];
4
+
5
+ export async function fetchEventsFromAPI() {
6
+ try {
7
+ const response = await fetch("https://get-micdrop.com/api/public/getEventsForVenue");
8
+ if (response.ok) {
9
+ const events = await response.json();
10
+ return events.map((event) => ({
11
+ id: event.ID,
12
+ date: event.startDateTime,
13
+ title: event.title,
14
+ }));
15
+ } else {
16
+ console.error("Failed to load events:", response.status);
17
+ return [];
18
+ }
19
+ } catch (error) {
20
+ console.error("Error fetching events:", error);
21
+ return [];
22
+ }
23
+ }
24
+
25
+ export async function fetchEventsForMonth(year, month) {
26
+ mockEvents = await fetchEventsFromAPI();
27
+
28
+ return new Promise((resolve) => {
29
+ setTimeout(() => {
30
+ resolve(
31
+ mockEvents.filter((event) =>
32
+ event.date.startsWith(`${year}-${String(month).padStart(2, "0")}`)
33
+ )
34
+ );
35
+ }, 500);
36
+ });
37
+ }
38
+
39
+ export async function fetchEventsForWeek(date) {
40
+ mockEvents = await fetchEventsFromAPI();
41
+
42
+ const startOfWeekDate = startOfWeek(date, { weekStartsOn: 1 });
43
+ const endOfWeekDate = addDays(startOfWeekDate, 6);
44
+
45
+ return new Promise((resolve) => {
46
+ setTimeout(() => {
47
+ const filteredEvents = mockEvents.filter((event) => {
48
+ const eventDate = new Date(event.date).getTime();
49
+ return (
50
+ eventDate >= startOfWeekDate.getTime() &&
51
+ eventDate <= endOfWeekDate.getTime()
52
+ );
53
+ });
54
+ resolve(filteredEvents);
55
+ }, 500);
56
+ });
57
+ }
58
+
59
+ export async function fetchEventsForDay(date) {
60
+ mockEvents = await fetchEventsFromAPI();
61
+
62
+ return new Promise((resolve) => {
63
+ setTimeout(() => {
64
+ const filteredEvents = mockEvents.filter((event) => {
65
+ const eventDate = new Date(event.date);
66
+ return (
67
+ eventDate.getUTCDate() === date.getUTCDate() &&
68
+ eventDate.getUTCMonth() === date.getUTCMonth() &&
69
+ eventDate.getUTCFullYear() === date.getUTCFullYear()
70
+ );
71
+ });
72
+ resolve(filteredEvents);
73
+ }, 500);
74
+ });
75
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=EventService.spec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"EventService.spec.d.ts","sourceRoot":"","sources":["../../src/lib/services/EventService.spec.js"],"names":[],"mappings":""}
@@ -0,0 +1,217 @@
1
+ import { describe, it, expect, vi, beforeEach } from 'vitest';
2
+
3
+ // Create mock functions we'll spy on
4
+ const mockEvents = [
5
+ { ID: 1, startDateTime: '2025-01-15T20:00:00', title: 'Comedy Night' },
6
+ { ID: 2, startDateTime: '2025-01-15T21:00:00', title: 'Open Mic' },
7
+ { ID: 3, startDateTime: '2025-02-10T19:00:00', title: 'Improv Show' },
8
+ ];
9
+
10
+ import {
11
+ fetchEventsFromAPI,
12
+ fetchEventsForMonth,
13
+ fetchEventsForWeek,
14
+ fetchEventsForDay,
15
+ } from './EventService';
16
+
17
+ describe('EventService', () => {
18
+ beforeEach(() => {
19
+ vi.clearAllMocks();
20
+ global.fetch = vi.fn();
21
+ });
22
+
23
+ describe('fetchEventsFromAPI', () => {
24
+ it('fetches events from the API', async () => {
25
+ global.fetch.mockResolvedValue({
26
+ ok: true,
27
+ json: () => Promise.resolve(mockEvents),
28
+ });
29
+
30
+ const events = await fetchEventsFromAPI();
31
+
32
+ expect(global.fetch).toHaveBeenCalledWith(
33
+ 'https://get-micdrop.com/api/public/getEventsForVenue'
34
+ );
35
+ expect(events).toHaveLength(3);
36
+ });
37
+
38
+ it('transforms event data correctly', async () => {
39
+ global.fetch.mockResolvedValue({
40
+ ok: true,
41
+ json: () => Promise.resolve([mockEvents[0]]),
42
+ });
43
+
44
+ const events = await fetchEventsFromAPI();
45
+
46
+ expect(events[0]).toEqual({
47
+ id: 1,
48
+ date: '2025-01-15T20:00:00',
49
+ title: 'Comedy Night',
50
+ });
51
+ });
52
+
53
+ it('returns empty array on failed response', async () => {
54
+ const consoleSpy = vi.spyOn(console, 'error').mockImplementation(() => {});
55
+ global.fetch.mockResolvedValue({
56
+ ok: false,
57
+ status: 500,
58
+ });
59
+
60
+ const events = await fetchEventsFromAPI();
61
+
62
+ expect(events).toEqual([]);
63
+ consoleSpy.mockRestore();
64
+ });
65
+
66
+ it('returns empty array on network error', async () => {
67
+ const consoleSpy = vi.spyOn(console, 'error').mockImplementation(() => {});
68
+ global.fetch.mockRejectedValue(new Error('Network error'));
69
+
70
+ const events = await fetchEventsFromAPI();
71
+
72
+ expect(events).toEqual([]);
73
+ consoleSpy.mockRestore();
74
+ });
75
+ });
76
+
77
+ describe('fetchEventsForMonth', () => {
78
+ it('filters events by year and month', async () => {
79
+ global.fetch.mockResolvedValue({
80
+ ok: true,
81
+ json: () => Promise.resolve(mockEvents),
82
+ });
83
+
84
+ const events = await fetchEventsForMonth(2025, 1);
85
+
86
+ expect(events.length).toBe(2);
87
+ expect(events[0].title).toBe('Comedy Night');
88
+ expect(events[1].title).toBe('Open Mic');
89
+ }, 10000);
90
+
91
+ it('returns empty for month with no events', async () => {
92
+ global.fetch.mockResolvedValue({
93
+ ok: true,
94
+ json: () => Promise.resolve(mockEvents),
95
+ });
96
+
97
+ const events = await fetchEventsForMonth(2025, 3);
98
+
99
+ expect(events).toEqual([]);
100
+ }, 10000);
101
+
102
+ it('pads single digit months correctly', async () => {
103
+ global.fetch.mockResolvedValue({
104
+ ok: true,
105
+ json: () => Promise.resolve(mockEvents),
106
+ });
107
+
108
+ const events = await fetchEventsForMonth(2025, 2);
109
+
110
+ expect(events.length).toBe(1);
111
+ expect(events[0].title).toBe('Improv Show');
112
+ }, 10000);
113
+
114
+ it('handles double digit months', async () => {
115
+ const decemberEvents = [
116
+ { ID: 4, startDateTime: '2025-12-25T20:00:00', title: 'Holiday Show' },
117
+ ];
118
+ global.fetch.mockResolvedValue({
119
+ ok: true,
120
+ json: () => Promise.resolve(decemberEvents),
121
+ });
122
+
123
+ const events = await fetchEventsForMonth(2025, 12);
124
+
125
+ expect(events.length).toBe(1);
126
+ }, 10000);
127
+ });
128
+
129
+ describe('fetchEventsForWeek', () => {
130
+ it('filters events within the week', async () => {
131
+ // Events on Jan 13-14, 2025 (Monday-Tuesday of that week)
132
+ const weekEvents = [
133
+ { ID: 1, startDateTime: '2025-01-13T20:00:00', title: 'Monday Show' },
134
+ { ID: 2, startDateTime: '2025-01-14T19:00:00', title: 'Tuesday Show' },
135
+ { ID: 3, startDateTime: '2025-01-20T20:00:00', title: 'Next Week Show' },
136
+ ];
137
+ global.fetch.mockResolvedValue({
138
+ ok: true,
139
+ json: () => Promise.resolve(weekEvents),
140
+ });
141
+
142
+ // Jan 15, 2025 is a Wednesday
143
+ const date = new Date('2025-01-15');
144
+ const events = await fetchEventsForWeek(date);
145
+
146
+ // Should include Monday and Tuesday shows (same week)
147
+ expect(events.length).toBe(2);
148
+ }, 10000);
149
+
150
+ it('uses Monday as week start', async () => {
151
+ const events = [
152
+ { ID: 1, startDateTime: '2025-01-12T20:00:00', title: 'Sunday Show' },
153
+ { ID: 2, startDateTime: '2025-01-13T20:00:00', title: 'Monday Show' },
154
+ ];
155
+ global.fetch.mockResolvedValue({
156
+ ok: true,
157
+ json: () => Promise.resolve(events),
158
+ });
159
+
160
+ // Pass a date in the week starting Jan 13
161
+ const date = new Date('2025-01-15');
162
+ const result = await fetchEventsForWeek(date);
163
+
164
+ // Sunday should be excluded, Monday included
165
+ expect(result.some((e) => e.title === 'Monday Show')).toBe(true);
166
+ }, 10000);
167
+ });
168
+
169
+ describe('fetchEventsForDay', () => {
170
+ it('filters events for specific day', async () => {
171
+ // Use Z suffix for UTC dates to avoid timezone issues
172
+ const dayEvents = [
173
+ { ID: 1, startDateTime: '2025-01-15T14:00:00Z', title: 'Afternoon Show' },
174
+ { ID: 2, startDateTime: '2025-01-15T20:00:00Z', title: 'Evening Show' },
175
+ { ID: 3, startDateTime: '2025-01-16T20:00:00Z', title: 'Next Day Show' },
176
+ ];
177
+ global.fetch.mockResolvedValue({
178
+ ok: true,
179
+ json: () => Promise.resolve(dayEvents),
180
+ });
181
+
182
+ const date = new Date(Date.UTC(2025, 0, 15)); // Jan 15, 2025 UTC
183
+ const events = await fetchEventsForDay(date);
184
+
185
+ expect(events.length).toBe(2);
186
+ expect(events[0].title).toBe('Afternoon Show');
187
+ expect(events[1].title).toBe('Evening Show');
188
+ }, 10000);
189
+
190
+ it('returns empty array for day with no events', async () => {
191
+ global.fetch.mockResolvedValue({
192
+ ok: true,
193
+ json: () => Promise.resolve(mockEvents),
194
+ });
195
+
196
+ const date = new Date(Date.UTC(2025, 0, 20)); // Jan 20, 2025
197
+ const events = await fetchEventsForDay(date);
198
+
199
+ expect(events).toEqual([]);
200
+ }, 10000);
201
+
202
+ it('matches dates using UTC methods', async () => {
203
+ const dayEvents = [
204
+ { ID: 1, startDateTime: '2025-06-15T23:00:00Z', title: 'Late Show' },
205
+ ];
206
+ global.fetch.mockResolvedValue({
207
+ ok: true,
208
+ json: () => Promise.resolve(dayEvents),
209
+ });
210
+
211
+ const date = new Date(Date.UTC(2025, 5, 15)); // June 15, 2025 UTC
212
+ const events = await fetchEventsForDay(date);
213
+
214
+ expect(events.length).toBe(1);
215
+ }, 10000);
216
+ });
217
+ });
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Accept an event performer invitation
3
+ * @param {string|number} inviteId - The invitation ID
4
+ * @param {string} message - Optional message to include
5
+ * @returns {Promise<{ok: boolean, result?: any}>}
6
+ */
7
+ export function acceptInvite(inviteId: string | number, message?: string): Promise<{
8
+ ok: boolean;
9
+ result?: any;
10
+ }>;
11
+ /**
12
+ * Decline an event performer invitation
13
+ * @param {string|number} inviteId - The invitation ID
14
+ * @param {string} message - Optional message to include
15
+ * @returns {Promise<{ok: boolean, result?: any}>}
16
+ */
17
+ export function declineInvite(inviteId: string | number, message?: string): Promise<{
18
+ ok: boolean;
19
+ result?: any;
20
+ }>;
21
+ /**
22
+ * Cancel an event performer invitation
23
+ * @param {string|number} inviteId - The invitation ID
24
+ * @param {string} message - Optional message to include
25
+ * @returns {Promise<{ok: boolean, result?: any}>}
26
+ */
27
+ export function cancelInvite(inviteId: string | number, message?: string): Promise<{
28
+ ok: boolean;
29
+ result?: any;
30
+ }>;
31
+ /**
32
+ * Send a message to a venue
33
+ * @param {string|number} inviteId - The invitation/event ID
34
+ * @param {string} message - The message to send
35
+ * @returns {Promise<{ok: boolean, result?: any}>}
36
+ */
37
+ export function sendVenueMessage(inviteId: string | number, message: string): Promise<{
38
+ ok: boolean;
39
+ result?: any;
40
+ }>;
41
+ /**
42
+ * Get the ticketing event URL
43
+ * @param {string|number} venueId - The venue/event ID
44
+ * @returns {string}
45
+ */
46
+ export function getEventUrl(venueId: string | number): string;
47
+ //# sourceMappingURL=ShowService.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ShowService.d.ts","sourceRoot":"","sources":["ShowService.js"],"names":[],"mappings":"AAGA;;;;;GAKG;AACH,uCAJW,MAAM,GAAC,MAAM,YACb,MAAM,GACJ,OAAO,CAAC;IAAC,EAAE,EAAE,OAAO,CAAC;IAAC,MAAM,CAAC,EAAE,GAAG,CAAA;CAAC,CAAC,CAwBhD;AAED;;;;;GAKG;AACH,wCAJW,MAAM,GAAC,MAAM,YACb,MAAM,GACJ,OAAO,CAAC;IAAC,EAAE,EAAE,OAAO,CAAC;IAAC,MAAM,CAAC,EAAE,GAAG,CAAA;CAAC,CAAC,CAwBhD;AAED;;;;;GAKG;AACH,uCAJW,MAAM,GAAC,MAAM,YACb,MAAM,GACJ,OAAO,CAAC;IAAC,EAAE,EAAE,OAAO,CAAC;IAAC,MAAM,CAAC,EAAE,GAAG,CAAA;CAAC,CAAC,CAwBhD;AAED;;;;;GAKG;AACH,2CAJW,MAAM,GAAC,MAAM,WACb,MAAM,GACJ,OAAO,CAAC;IAAC,EAAE,EAAE,OAAO,CAAC;IAAC,MAAM,CAAC,EAAE,GAAG,CAAA;CAAC,CAAC,CAoChD;AAED;;;;GAIG;AACH,qCAHW,MAAM,GAAC,MAAM,GACX,MAAM,CAIlB"}
@@ -0,0 +1,143 @@
1
+ import { API_BASE_URL, API_ENDPOINTS, buildApiUrl } from "../../utils/apiConfig";
2
+ import { getPerformerToken } from "../../utils/utils";
3
+
4
+ /**
5
+ * Accept an event performer invitation
6
+ * @param {string|number} inviteId - The invitation ID
7
+ * @param {string} message - Optional message to include
8
+ * @returns {Promise<{ok: boolean, result?: any}>}
9
+ */
10
+ export async function acceptInvite(inviteId, message = "") {
11
+ try {
12
+ const response = await fetch(
13
+ buildApiUrl(`${API_ENDPOINTS.ACCEPT_EVENT_PERFORMER_INVITE}/${inviteId}`),
14
+ {
15
+ method: "PUT",
16
+ headers: {
17
+ "Content-Type": "application/json",
18
+ },
19
+ body: JSON.stringify({ message }),
20
+ }
21
+ );
22
+
23
+ if (response.ok) {
24
+ const result = await response.json();
25
+ return { ok: true, result };
26
+ }
27
+ return { ok: false };
28
+ } catch (error) {
29
+ console.error("Error accepting invite:", error);
30
+ return { ok: false };
31
+ }
32
+ }
33
+
34
+ /**
35
+ * Decline an event performer invitation
36
+ * @param {string|number} inviteId - The invitation ID
37
+ * @param {string} message - Optional message to include
38
+ * @returns {Promise<{ok: boolean, result?: any}>}
39
+ */
40
+ export async function declineInvite(inviteId, message = "") {
41
+ try {
42
+ const response = await fetch(
43
+ buildApiUrl(`${API_ENDPOINTS.DECLINE_EVENT_PERFORMER_INVITE}/${inviteId}`),
44
+ {
45
+ method: "PUT",
46
+ headers: {
47
+ "Content-Type": "application/json",
48
+ },
49
+ body: JSON.stringify({ message }),
50
+ }
51
+ );
52
+
53
+ if (response.ok) {
54
+ const result = await response.json();
55
+ return { ok: true, result };
56
+ }
57
+ return { ok: false };
58
+ } catch (error) {
59
+ console.error("Error declining invite:", error);
60
+ return { ok: false };
61
+ }
62
+ }
63
+
64
+ /**
65
+ * Cancel an event performer invitation
66
+ * @param {string|number} inviteId - The invitation ID
67
+ * @param {string} message - Optional message to include
68
+ * @returns {Promise<{ok: boolean, result?: any}>}
69
+ */
70
+ export async function cancelInvite(inviteId, message = "") {
71
+ try {
72
+ const response = await fetch(
73
+ buildApiUrl(`${API_ENDPOINTS.CANCEL_EVENT_PERFORMER_INVITE}/${inviteId}`),
74
+ {
75
+ method: "PUT",
76
+ headers: {
77
+ "Content-Type": "application/json",
78
+ },
79
+ body: JSON.stringify({ message }),
80
+ }
81
+ );
82
+
83
+ if (response.ok) {
84
+ const result = await response.json();
85
+ return { ok: true, result };
86
+ }
87
+ return { ok: false };
88
+ } catch (error) {
89
+ console.error("Error cancelling invite:", error);
90
+ return { ok: false };
91
+ }
92
+ }
93
+
94
+ /**
95
+ * Send a message to a venue
96
+ * @param {string|number} inviteId - The invitation/event ID
97
+ * @param {string} message - The message to send
98
+ * @returns {Promise<{ok: boolean, result?: any}>}
99
+ */
100
+ export async function sendVenueMessage(inviteId, message) {
101
+ try {
102
+ const token = getPerformerToken();
103
+
104
+ const response = await fetch(
105
+ buildApiUrl(`${API_ENDPOINTS.SEND_VENUE_MESSAGE}/${inviteId}`),
106
+ {
107
+ method: "POST",
108
+ headers: {
109
+ "Content-Type": "application/json",
110
+ Authorization: `Bearer ${token}`,
111
+ },
112
+ credentials: "include",
113
+ body: JSON.stringify({ message }),
114
+ }
115
+ );
116
+
117
+ if (response.ok) {
118
+ const text = await response.text();
119
+ let result = { message: "Email sent successfully" };
120
+ if (text) {
121
+ try {
122
+ result = JSON.parse(text);
123
+ } catch (e) {
124
+ // Empty response is fine
125
+ }
126
+ }
127
+ return { ok: true, result };
128
+ }
129
+ return { ok: false };
130
+ } catch (error) {
131
+ console.error("Error sending venue message:", error);
132
+ return { ok: false };
133
+ }
134
+ }
135
+
136
+ /**
137
+ * Get the ticketing event URL
138
+ * @param {string|number} venueId - The venue/event ID
139
+ * @returns {string}
140
+ */
141
+ export function getEventUrl(venueId) {
142
+ return `${API_BASE_URL}/ticketing/events/${venueId}`;
143
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=ShowService.spec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ShowService.spec.d.ts","sourceRoot":"","sources":["../../src/lib/services/ShowService.spec.js"],"names":[],"mappings":""}
@@ -0,0 +1,342 @@
1
+ import { describe, it, expect, vi, beforeEach } from 'vitest';
2
+
3
+ // Mock the utility modules before imports
4
+ vi.mock('@/utils/apiConfig', () => ({
5
+ API_BASE_URL: 'https://api.example.com',
6
+ API_ENDPOINTS: {
7
+ ACCEPT_EVENT_PERFORMER_INVITE: '/accept-invite',
8
+ DECLINE_EVENT_PERFORMER_INVITE: '/decline-invite',
9
+ CANCEL_EVENT_PERFORMER_INVITE: '/cancel-invite',
10
+ SEND_VENUE_MESSAGE: '/send-message',
11
+ },
12
+ buildApiUrl: (path) => `https://api.example.com${path}`,
13
+ }));
14
+
15
+ vi.mock('@/utils/utils', () => ({
16
+ getPerformerToken: () => 'test-token',
17
+ }));
18
+
19
+ import {
20
+ acceptInvite,
21
+ declineInvite,
22
+ cancelInvite,
23
+ sendVenueMessage,
24
+ getEventUrl,
25
+ } from './ShowService';
26
+
27
+ describe('ShowService', () => {
28
+ beforeEach(() => {
29
+ vi.clearAllMocks();
30
+ global.fetch = vi.fn();
31
+ });
32
+
33
+ describe('acceptInvite', () => {
34
+ it('makes PUT request to accept invite endpoint', async () => {
35
+ global.fetch.mockResolvedValue({
36
+ ok: true,
37
+ json: () => Promise.resolve({ success: true }),
38
+ });
39
+
40
+ await acceptInvite('123');
41
+
42
+ expect(global.fetch).toHaveBeenCalledWith(
43
+ 'https://api.example.com/accept-invite/123',
44
+ expect.objectContaining({
45
+ method: 'PUT',
46
+ headers: { 'Content-Type': 'application/json' },
47
+ })
48
+ );
49
+ });
50
+
51
+ it('returns ok: true on successful response', async () => {
52
+ global.fetch.mockResolvedValue({
53
+ ok: true,
54
+ json: () => Promise.resolve({ id: 123 }),
55
+ });
56
+
57
+ const result = await acceptInvite('123');
58
+
59
+ expect(result.ok).toBe(true);
60
+ expect(result.result).toEqual({ id: 123 });
61
+ });
62
+
63
+ it('returns ok: false on failed response', async () => {
64
+ global.fetch.mockResolvedValue({
65
+ ok: false,
66
+ });
67
+
68
+ const result = await acceptInvite('123');
69
+
70
+ expect(result.ok).toBe(false);
71
+ });
72
+
73
+ it('returns ok: false on network error', async () => {
74
+ const consoleSpy = vi.spyOn(console, 'error').mockImplementation(() => {});
75
+ global.fetch.mockRejectedValue(new Error('Network error'));
76
+
77
+ const result = await acceptInvite('123');
78
+
79
+ expect(result.ok).toBe(false);
80
+ consoleSpy.mockRestore();
81
+ });
82
+
83
+ it('includes message in request body', async () => {
84
+ global.fetch.mockResolvedValue({
85
+ ok: true,
86
+ json: () => Promise.resolve({}),
87
+ });
88
+
89
+ await acceptInvite('123', 'Thanks for the invite!');
90
+
91
+ expect(global.fetch).toHaveBeenCalledWith(
92
+ expect.any(String),
93
+ expect.objectContaining({
94
+ body: JSON.stringify({ message: 'Thanks for the invite!' }),
95
+ })
96
+ );
97
+ });
98
+
99
+ it('sends empty message by default', async () => {
100
+ global.fetch.mockResolvedValue({
101
+ ok: true,
102
+ json: () => Promise.resolve({}),
103
+ });
104
+
105
+ await acceptInvite('123');
106
+
107
+ expect(global.fetch).toHaveBeenCalledWith(
108
+ expect.any(String),
109
+ expect.objectContaining({
110
+ body: JSON.stringify({ message: '' }),
111
+ })
112
+ );
113
+ });
114
+ });
115
+
116
+ describe('declineInvite', () => {
117
+ it('makes PUT request to decline invite endpoint', async () => {
118
+ global.fetch.mockResolvedValue({
119
+ ok: true,
120
+ json: () => Promise.resolve({}),
121
+ });
122
+
123
+ await declineInvite('456');
124
+
125
+ expect(global.fetch).toHaveBeenCalledWith(
126
+ 'https://api.example.com/decline-invite/456',
127
+ expect.objectContaining({
128
+ method: 'PUT',
129
+ })
130
+ );
131
+ });
132
+
133
+ it('returns ok: true on success', async () => {
134
+ global.fetch.mockResolvedValue({
135
+ ok: true,
136
+ json: () => Promise.resolve({ declined: true }),
137
+ });
138
+
139
+ const result = await declineInvite('456');
140
+
141
+ expect(result.ok).toBe(true);
142
+ expect(result.result).toEqual({ declined: true });
143
+ });
144
+
145
+ it('returns ok: false on failure', async () => {
146
+ global.fetch.mockResolvedValue({
147
+ ok: false,
148
+ });
149
+
150
+ const result = await declineInvite('456');
151
+
152
+ expect(result.ok).toBe(false);
153
+ });
154
+
155
+ it('returns ok: false on error', async () => {
156
+ const consoleSpy = vi.spyOn(console, 'error').mockImplementation(() => {});
157
+ global.fetch.mockRejectedValue(new Error('Error'));
158
+
159
+ const result = await declineInvite('456');
160
+
161
+ expect(result.ok).toBe(false);
162
+ consoleSpy.mockRestore();
163
+ });
164
+
165
+ it('includes decline message in body', async () => {
166
+ global.fetch.mockResolvedValue({
167
+ ok: true,
168
+ json: () => Promise.resolve({}),
169
+ });
170
+
171
+ await declineInvite('456', 'Schedule conflict');
172
+
173
+ expect(global.fetch).toHaveBeenCalledWith(
174
+ expect.any(String),
175
+ expect.objectContaining({
176
+ body: JSON.stringify({ message: 'Schedule conflict' }),
177
+ })
178
+ );
179
+ });
180
+ });
181
+
182
+ describe('cancelInvite', () => {
183
+ it('makes PUT request to cancel invite endpoint', async () => {
184
+ global.fetch.mockResolvedValue({
185
+ ok: true,
186
+ json: () => Promise.resolve({}),
187
+ });
188
+
189
+ await cancelInvite('789');
190
+
191
+ expect(global.fetch).toHaveBeenCalledWith(
192
+ 'https://api.example.com/cancel-invite/789',
193
+ expect.objectContaining({
194
+ method: 'PUT',
195
+ })
196
+ );
197
+ });
198
+
199
+ it('returns ok: true on success', async () => {
200
+ global.fetch.mockResolvedValue({
201
+ ok: true,
202
+ json: () => Promise.resolve({ cancelled: true }),
203
+ });
204
+
205
+ const result = await cancelInvite('789');
206
+
207
+ expect(result.ok).toBe(true);
208
+ });
209
+
210
+ it('returns ok: false on failure', async () => {
211
+ global.fetch.mockResolvedValue({
212
+ ok: false,
213
+ });
214
+
215
+ const result = await cancelInvite('789');
216
+
217
+ expect(result.ok).toBe(false);
218
+ });
219
+
220
+ it('returns ok: false on error', async () => {
221
+ const consoleSpy = vi.spyOn(console, 'error').mockImplementation(() => {});
222
+ global.fetch.mockRejectedValue(new Error('Error'));
223
+
224
+ const result = await cancelInvite('789');
225
+
226
+ expect(result.ok).toBe(false);
227
+ consoleSpy.mockRestore();
228
+ });
229
+ });
230
+
231
+ describe('sendVenueMessage', () => {
232
+ it('makes POST request with auth token', async () => {
233
+ global.fetch.mockResolvedValue({
234
+ ok: true,
235
+ text: () => Promise.resolve(''),
236
+ });
237
+
238
+ await sendVenueMessage('123', 'Hello!');
239
+
240
+ expect(global.fetch).toHaveBeenCalledWith(
241
+ 'https://api.example.com/send-message/123',
242
+ expect.objectContaining({
243
+ method: 'POST',
244
+ headers: {
245
+ 'Content-Type': 'application/json',
246
+ Authorization: 'Bearer test-token',
247
+ },
248
+ credentials: 'include',
249
+ })
250
+ );
251
+ });
252
+
253
+ it('sends message in request body', async () => {
254
+ global.fetch.mockResolvedValue({
255
+ ok: true,
256
+ text: () => Promise.resolve(''),
257
+ });
258
+
259
+ await sendVenueMessage('123', 'Hello venue!');
260
+
261
+ expect(global.fetch).toHaveBeenCalledWith(
262
+ expect.any(String),
263
+ expect.objectContaining({
264
+ body: JSON.stringify({ message: 'Hello venue!' }),
265
+ })
266
+ );
267
+ });
268
+
269
+ it('returns ok: true with default message on empty response', async () => {
270
+ global.fetch.mockResolvedValue({
271
+ ok: true,
272
+ text: () => Promise.resolve(''),
273
+ });
274
+
275
+ const result = await sendVenueMessage('123', 'Hello');
276
+
277
+ expect(result.ok).toBe(true);
278
+ expect(result.result).toEqual({ message: 'Email sent successfully' });
279
+ });
280
+
281
+ it('parses JSON response when present', async () => {
282
+ global.fetch.mockResolvedValue({
283
+ ok: true,
284
+ text: () => Promise.resolve(JSON.stringify({ sent: true, id: 456 })),
285
+ });
286
+
287
+ const result = await sendVenueMessage('123', 'Hello');
288
+
289
+ expect(result.ok).toBe(true);
290
+ expect(result.result).toEqual({ sent: true, id: 456 });
291
+ });
292
+
293
+ it('handles invalid JSON in response gracefully', async () => {
294
+ global.fetch.mockResolvedValue({
295
+ ok: true,
296
+ text: () => Promise.resolve('not json'),
297
+ });
298
+
299
+ const result = await sendVenueMessage('123', 'Hello');
300
+
301
+ expect(result.ok).toBe(true);
302
+ expect(result.result).toEqual({ message: 'Email sent successfully' });
303
+ });
304
+
305
+ it('returns ok: false on failure', async () => {
306
+ global.fetch.mockResolvedValue({
307
+ ok: false,
308
+ });
309
+
310
+ const result = await sendVenueMessage('123', 'Hello');
311
+
312
+ expect(result.ok).toBe(false);
313
+ });
314
+
315
+ it('returns ok: false on error', async () => {
316
+ const consoleSpy = vi.spyOn(console, 'error').mockImplementation(() => {});
317
+ global.fetch.mockRejectedValue(new Error('Network error'));
318
+
319
+ const result = await sendVenueMessage('123', 'Hello');
320
+
321
+ expect(result.ok).toBe(false);
322
+ consoleSpy.mockRestore();
323
+ });
324
+ });
325
+
326
+ describe('getEventUrl', () => {
327
+ it('returns ticketing URL for venue', () => {
328
+ const url = getEventUrl('123');
329
+ expect(url).toBe('https://api.example.com/ticketing/events/123');
330
+ });
331
+
332
+ it('handles numeric venue ID', () => {
333
+ const url = getEventUrl(456);
334
+ expect(url).toBe('https://api.example.com/ticketing/events/456');
335
+ });
336
+
337
+ it('handles string venue ID', () => {
338
+ const url = getEventUrl('venue-abc');
339
+ expect(url).toBe('https://api.example.com/ticketing/events/venue-abc');
340
+ });
341
+ });
342
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@getmicdrop/svelte-components",
3
- "version": "2.0.6",
3
+ "version": "2.0.8",
4
4
  "description": "Shared component library for Micdrop applications",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",