@@ -3,17 +3,31 @@ import { beforeEach, describe, expect, it, vi } from 'vitest';
33import type { Plugin } from 'vite' ;
44import { makeCustomSentryVitePlugins } from '../../src/vite/sourceMaps' ;
55
6- const mockedSentryVitePlugin = {
6+ const mockedViteDebugIdUploadPlugin = {
77 name : 'sentry-vite-debug-id-upload-plugin' ,
88 writeBundle : vi . fn ( ) ,
99} ;
1010
11+ const mockedViteReleaseManagementPlugin = {
12+ name : 'sentry-release-management-plugin' ,
13+ writeBundle : vi . fn ( ) ,
14+ } ;
15+
16+ const mockedFileDeletionPlugin = {
17+ name : 'sentry-file-deletion-plugin' ,
18+ writeBundle : vi . fn ( ) ,
19+ } ;
20+
1121vi . mock ( '@sentry/vite-plugin' , async ( ) => {
1222 const original = ( await vi . importActual ( '@sentry/vite-plugin' ) ) as any ;
1323
1424 return {
1525 ...original ,
16- sentryVitePlugin : ( ) => [ mockedSentryVitePlugin ] ,
26+ sentryVitePlugin : ( ) => [
27+ mockedViteReleaseManagementPlugin ,
28+ mockedViteDebugIdUploadPlugin ,
29+ mockedFileDeletionPlugin ,
30+ ] ,
1731 } ;
1832} ) ;
1933
@@ -30,20 +44,22 @@ beforeEach(() => {
3044 vi . clearAllMocks ( ) ;
3145} ) ;
3246
33- async function getCustomSentryViteUploadSourcemapsPlugin ( ) : Promise < Plugin | undefined > {
47+ async function getSentryViteSubPlugin ( name : string ) : Promise < Plugin | undefined > {
3448 const plugins = await makeCustomSentryVitePlugins ( {
3549 authToken : 'token' ,
3650 org : 'org' ,
3751 project : 'project' ,
3852 adapter : 'other' ,
3953 } ) ;
40- return plugins . find ( plugin => plugin . name === 'sentry-upload-sveltekit-source-maps' ) ;
54+
55+ return plugins . find ( plugin => plugin . name === name ) ;
4156}
4257
4358describe ( 'makeCustomSentryVitePlugin()' , ( ) => {
4459 it ( 'returns the custom sentry source maps plugin' , async ( ) => {
45- const plugin = await getCustomSentryViteUploadSourcemapsPlugin ( ) ;
46- expect ( plugin ?. name ) . toEqual ( 'sentry-upload-sveltekit-source-maps' ) ;
60+ const plugin = await getSentryViteSubPlugin ( 'sentry-sveltekit-debug-id-upload-plugin' ) ;
61+
62+ expect ( plugin ?. name ) . toEqual ( 'sentry-sveltekit-debug-id-upload-plugin' ) ;
4763 expect ( plugin ?. apply ) . toEqual ( 'build' ) ;
4864 expect ( plugin ?. enforce ) . toEqual ( 'post' ) ;
4965
@@ -58,9 +74,9 @@ describe('makeCustomSentryVitePlugin()', () => {
5874 expect ( plugin ?. writeBundle ) . toBeUndefined ( ) ;
5975 } ) ;
6076
61- describe ( 'Custom sentry vite plugin' , ( ) => {
77+ describe ( 'Custom debug id source maps plugin plugin' , ( ) => {
6278 it ( 'enables source map generation' , async ( ) => {
63- const plugin = await getCustomSentryViteUploadSourcemapsPlugin ( ) ;
79+ const plugin = await getSentryViteSubPlugin ( 'sentry-sveltekit-debug-id-upload-plugin' ) ;
6480 // @ts -expect-error this function exists!
6581 const sentrifiedConfig = plugin . config ( { build : { foo : { } } , test : { } } ) ;
6682 expect ( sentrifiedConfig ) . toEqual ( {
@@ -73,7 +89,7 @@ describe('makeCustomSentryVitePlugin()', () => {
7389 } ) ;
7490
7591 it ( 'injects the output dir into the server hooks file' , async ( ) => {
76- const plugin = await getCustomSentryViteUploadSourcemapsPlugin ( ) ;
92+ const plugin = await getSentryViteSubPlugin ( 'sentry-sveltekit-debug-id-upload-plugin' ) ;
7793 // @ts -expect-error this function exists!
7894 const transformOutput = await plugin . transform ( 'foo' , '/src/hooks.server.ts' ) ;
7995 const transformedCode = transformOutput . code ;
@@ -84,34 +100,34 @@ describe('makeCustomSentryVitePlugin()', () => {
84100 } ) ;
85101
86102 it ( 'uploads source maps during the SSR build' , async ( ) => {
87- const plugin = await getCustomSentryViteUploadSourcemapsPlugin ( ) ;
103+ const plugin = await getSentryViteSubPlugin ( 'sentry-sveltekit-debug-id-upload-plugin' ) ;
88104 // @ts -expect-error this function exists!
89105 plugin . configResolved ( { build : { ssr : true } } ) ;
90106 // @ts -expect-error this function exists!
91107 await plugin . closeBundle ( ) ;
92- expect ( mockedSentryVitePlugin . writeBundle ) . toHaveBeenCalledTimes ( 1 ) ;
108+ expect ( mockedViteDebugIdUploadPlugin . writeBundle ) . toHaveBeenCalledTimes ( 1 ) ;
93109 } ) ;
94110
95111 it ( "doesn't upload source maps during the non-SSR builds" , async ( ) => {
96- const plugin = await getCustomSentryViteUploadSourcemapsPlugin ( ) ;
112+ const plugin = await getSentryViteSubPlugin ( 'sentry-sveltekit-debug-id-upload-plugin' ) ;
97113
98114 // @ts -expect-error this function exists!
99115 plugin . configResolved ( { build : { ssr : false } } ) ;
100116 // @ts -expect-error this function exists!
101117 await plugin . closeBundle ( ) ;
102- expect ( mockedSentryVitePlugin . writeBundle ) . not . toHaveBeenCalled ( ) ;
118+ expect ( mockedViteDebugIdUploadPlugin . writeBundle ) . not . toHaveBeenCalled ( ) ;
103119 } ) ;
104120 } ) ;
105121
106122 it ( 'catches errors while uploading source maps' , async ( ) => {
107- mockedSentryVitePlugin . writeBundle . mockImplementationOnce ( ( ) => {
123+ mockedViteDebugIdUploadPlugin . writeBundle . mockImplementationOnce ( ( ) => {
108124 throw new Error ( 'test error' ) ;
109125 } ) ;
110126
111- const consoleWarnSpy = vi . spyOn ( console , 'warn' ) . mockImplementation ( ( ) => { } ) ;
112- const consoleLogSpy = vi . spyOn ( console , 'log' ) . mockImplementation ( ( ) => { } ) ;
127+ const consoleWarnSpy = vi . spyOn ( console , 'warn' ) . mockImplementationOnce ( ( ) => { } ) ;
128+ const consoleLogSpy = vi . spyOn ( console , 'log' ) . mockImplementationOnce ( ( ) => { } ) ;
113129
114- const plugin = await getCustomSentryViteUploadSourcemapsPlugin ( ) ;
130+ const plugin = await getSentryViteSubPlugin ( 'sentry-sveltekit-debug-id-upload-plugin' ) ;
115131
116132 // @ts -expect-error this function exists!
117133 expect ( plugin . closeBundle ) . not . toThrow ( ) ;
@@ -124,4 +140,100 @@ describe('makeCustomSentryVitePlugin()', () => {
124140 expect ( consoleWarnSpy ) . toHaveBeenCalledWith ( expect . stringContaining ( 'Failed to upload source maps' ) ) ;
125141 expect ( consoleLogSpy ) . toHaveBeenCalled ( ) ;
126142 } ) ;
143+
144+ describe ( 'Custom release management plugin' , ( ) => {
145+ it ( 'has the expected hooks and properties' , async ( ) => {
146+ const plugin = await getSentryViteSubPlugin ( 'sentry-sveltekit-release-management-plugin' ) ;
147+
148+ expect ( plugin ) . toEqual ( {
149+ name : 'sentry-sveltekit-release-management-plugin' ,
150+ apply : 'build' ,
151+ enforce : 'post' ,
152+ closeBundle : expect . any ( Function ) ,
153+ } ) ;
154+ } ) ;
155+
156+ it ( 'calls the original release management plugin to start the release creation pipeline' , async ( ) => {
157+ const plugin = await getSentryViteSubPlugin ( 'sentry-sveltekit-release-management-plugin' ) ;
158+ // @ts -expect-error this function exists!
159+ await plugin . closeBundle ( ) ;
160+ expect ( mockedViteReleaseManagementPlugin . writeBundle ) . toHaveBeenCalledTimes ( 1 ) ;
161+ } ) ;
162+
163+ it ( 'catches errors during release creation' , async ( ) => {
164+ mockedViteReleaseManagementPlugin . writeBundle . mockImplementationOnce ( ( ) => {
165+ throw new Error ( 'test error' ) ;
166+ } ) ;
167+
168+ const consoleWarnSpy = vi . spyOn ( console , 'warn' ) . mockImplementationOnce ( ( ) => { } ) ;
169+
170+ const plugin = await getSentryViteSubPlugin ( 'sentry-sveltekit-release-management-plugin' ) ;
171+
172+ // @ts -expect-error this function exists!
173+ expect ( plugin . closeBundle ) . not . toThrow ( ) ;
174+
175+ // @ts -expect-error this function exists!
176+ await plugin . closeBundle ( ) ;
177+
178+ expect ( consoleWarnSpy ) . toHaveBeenCalledWith (
179+ expect . stringContaining ( 'Failed to upload release data' ) ,
180+ expect . any ( Error ) ,
181+ ) ;
182+ } ) ;
183+
184+ it ( 'also works correctly if the original release management plugin has its old name' , async ( ) => {
185+ const currentName = mockedViteReleaseManagementPlugin . name ;
186+ mockedViteReleaseManagementPlugin . name = 'sentry-debug-id-upload-plugin' ;
187+
188+ const plugin = await getSentryViteSubPlugin ( 'sentry-sveltekit-release-management-plugin' ) ;
189+
190+ // @ts -expect-error this function exists!
191+ await plugin . closeBundle ( ) ;
192+
193+ expect ( mockedViteReleaseManagementPlugin . writeBundle ) . toHaveBeenCalledTimes ( 1 ) ;
194+
195+ mockedViteReleaseManagementPlugin . name = currentName ;
196+ } ) ;
197+ } ) ;
198+
199+ describe ( 'Custom file deletion plugin' , ( ) => {
200+ it ( 'has the expected hooks and properties' , async ( ) => {
201+ const plugin = await getSentryViteSubPlugin ( 'sentry-sveltekit-file-deletion-plugin' ) ;
202+
203+ expect ( plugin ) . toEqual ( {
204+ name : 'sentry-sveltekit-file-deletion-plugin' ,
205+ apply : 'build' ,
206+ enforce : 'post' ,
207+ closeBundle : expect . any ( Function ) ,
208+ } ) ;
209+ } ) ;
210+
211+ it ( 'calls the original file deletion plugin to delete files' , async ( ) => {
212+ const plugin = await getSentryViteSubPlugin ( 'sentry-sveltekit-file-deletion-plugin' ) ;
213+ // @ts -expect-error this function exists!
214+ await plugin . closeBundle ( ) ;
215+ expect ( mockedFileDeletionPlugin . writeBundle ) . toHaveBeenCalledTimes ( 1 ) ;
216+ } ) ;
217+
218+ it ( 'catches errors during file deletion' , async ( ) => {
219+ mockedFileDeletionPlugin . writeBundle . mockImplementationOnce ( ( ) => {
220+ throw new Error ( 'test error' ) ;
221+ } ) ;
222+
223+ const consoleWarnSpy = vi . spyOn ( console , 'warn' ) . mockImplementationOnce ( ( ) => { } ) ;
224+
225+ const plugin = await getSentryViteSubPlugin ( 'sentry-sveltekit-file-deletion-plugin' ) ;
226+
227+ // @ts -expect-error this function exists!
228+ expect ( plugin . closeBundle ) . not . toThrow ( ) ;
229+
230+ // @ts -expect-error this function exists!
231+ await plugin . closeBundle ( ) ;
232+
233+ expect ( consoleWarnSpy ) . toHaveBeenCalledWith (
234+ expect . stringContaining ( 'Failed to delete source maps' ) ,
235+ expect . any ( Error ) ,
236+ ) ;
237+ } ) ;
238+ } ) ;
127239} ) ;
0 commit comments