@@ -43,11 +43,58 @@ describe('release-notes thunks', () => {
4343 expect ( success . payload . notes [ 0 ] . id ) . toBe ( 2 ) ;
4444 expect ( success . payload . notes [ 0 ] ) . toEqual ( expect . objectContaining ( { description : '<p>b</p>' , published_at : expect . any ( String ) , created_by : 'b@x' } ) ) ;
4545 expect ( success . payload . hasAccess ) . toBe ( false ) ;
46+ expect ( success . payload . canSendReleaseNoteEmails ) . toBe ( false ) ;
4647 const last = actions [ actions . length - 1 ] ;
4748 expect ( last . type ) . toBe ( updateLoadingStatuses . type ) ;
4849 expect ( last . payload . status . fetchReleaseNotesQuery ) . toBe ( RequestStatus . SUCCESSFUL ) ;
4950 } ) ;
5051
52+ test ( 'fetchReleaseNotesQuery maps sendEmailOnPublish to sendEmail' , async ( ) => {
53+ jest . spyOn ( api , 'getReleaseNotes' ) . mockResolvedValue ( [
54+ {
55+ id : 1 ,
56+ title : 'a' ,
57+ rawHtmlContent : '<p>a</p>' ,
58+ publishedAt : '2025-01-01T00:00:00Z' ,
59+ createdBy : 'a@x' ,
60+ sendEmailOnPublish : true ,
61+ } ,
62+ {
63+ id : 2 ,
64+ title : 'b' ,
65+ rawHtmlContent : '<p>b</p>' ,
66+ publishedAt : '2025-01-02T00:00:00Z' ,
67+ createdBy : 'b@x' ,
68+ sendEmailOnPublish : false ,
69+ } ,
70+ ] ) ;
71+ const { actions, dispatch } = collectActions ( ) ;
72+
73+ await fetchReleaseNotesQuery ( ) ( dispatch ) ;
74+
75+ const success = actions . find ( a => a . type === fetchReleaseNotesSuccess . type ) ;
76+ expect ( success . payload . notes . find ( n => n . id === 1 ) . sendEmail ) . toBe ( true ) ;
77+ expect ( success . payload . notes . find ( n => n . id === 2 ) . sendEmail ) . toBe ( false ) ;
78+ } ) ;
79+
80+ test ( 'fetchReleaseNotesQuery reads hasAccess and canSendReleaseNoteEmails from paginated response' , async ( ) => {
81+ jest . spyOn ( api , 'getReleaseNotes' ) . mockResolvedValue ( {
82+ results : [ {
83+ id : 1 , title : 'a' , rawHtmlContent : '<p>a</p>' , publishedAt : '2025-01-01T00:00:00Z' , createdBy : 'a@x' ,
84+ } ] ,
85+ hasAccess : true ,
86+ canSendReleaseNoteEmails : true ,
87+ } ) ;
88+ const { actions, dispatch } = collectActions ( ) ;
89+
90+ await fetchReleaseNotesQuery ( ) ( dispatch ) ;
91+
92+ const success = actions . find ( a => a . type === fetchReleaseNotesSuccess . type ) ;
93+ expect ( success . payload . hasAccess ) . toBe ( true ) ;
94+ expect ( success . payload . canSendReleaseNoteEmails ) . toBe ( true ) ;
95+ expect ( success . payload . notes ) . toHaveLength ( 1 ) ;
96+ } ) ;
97+
5198 test ( 'fetchReleaseNotesQuery failure sets FAILED' , async ( ) => {
5299 jest . spyOn ( api , 'getReleaseNotes' ) . mockRejectedValue ( new Error ( 'boom' ) ) ;
53100 const { actions, dispatch } = collectActions ( ) ;
@@ -60,11 +107,20 @@ describe('release-notes thunks', () => {
60107
61108 test ( 'createReleaseNoteQuery success creates note and sets SUCCESSFUL' , async ( ) => {
62109 jest . spyOn ( api , 'createReleaseNote' ) . mockResolvedValue ( {
63- id : 9 , title : 't' , rawHtmlContent : '<p>x</p>' , publishedAt : '2025-01-01T00:00:00Z' , createdBy : 'u' ,
110+ id : 9 ,
111+ title : 't' ,
112+ rawHtmlContent : '<p>x</p>' ,
113+ publishedAt : '2025-01-01T00:00:00Z' ,
114+ createdBy : 'u' ,
115+ sendEmailOnPublish : true ,
64116 } ) ;
65117 const { actions, dispatch } = collectActions ( ) ;
66- await createReleaseNoteQuery ( { id : 9 , title : 't' , description : '<p>x</p>' } ) ( dispatch ) ;
67- expect ( actions . find ( a => a . type === createReleaseNoteAction . type ) ) . toBeTruthy ( ) ;
118+ await createReleaseNoteQuery ( {
119+ id : 9 , title : 't' , description : '<p>x</p>' , sendEmail : true ,
120+ } ) ( dispatch ) ;
121+ const created = actions . find ( a => a . type === createReleaseNoteAction . type ) ;
122+ expect ( created ) . toBeTruthy ( ) ;
123+ expect ( created . payload . sendEmail ) . toBe ( true ) ;
68124 const last = actions [ actions . length - 1 ] ;
69125 expect ( last . type ) . toBe ( updateSavingStatuses . type ) ;
70126 expect ( last . payload . status . createReleaseNoteQuery ) . toBe ( RequestStatus . SUCCESSFUL ) ;
@@ -92,11 +148,20 @@ describe('release-notes thunks', () => {
92148
93149 test ( 'editReleaseNoteQuery success edits note and sets SUCCESSFUL' , async ( ) => {
94150 jest . spyOn ( api , 'editReleaseNote' ) . mockResolvedValue ( {
95- id : 5 , title : 't2' , rawHtmlContent : '<p>y</p>' , publishedAt : '2025-01-03T00:00:00Z' , createdBy : 'v' ,
151+ id : 5 ,
152+ title : 't2' ,
153+ rawHtmlContent : '<p>y</p>' ,
154+ publishedAt : '2025-01-03T00:00:00Z' ,
155+ createdBy : 'v' ,
156+ sendEmailOnPublish : true ,
96157 } ) ;
97158 const { actions, dispatch } = collectActions ( ) ;
98- await editReleaseNoteQuery ( { id : 5 , title : 't2' , description : '<p>y</p>' } ) ( dispatch ) ;
99- expect ( actions . find ( a => a . type === editReleaseNoteAction . type ) ) . toBeTruthy ( ) ;
159+ await editReleaseNoteQuery ( {
160+ id : 5 , title : 't2' , description : '<p>y</p>' , sendEmail : true ,
161+ } ) ( dispatch ) ;
162+ const edited = actions . find ( a => a . type === editReleaseNoteAction . type ) ;
163+ expect ( edited ) . toBeTruthy ( ) ;
164+ expect ( edited . payload . sendEmail ) . toBe ( true ) ;
100165 const last = actions [ actions . length - 1 ] ;
101166 expect ( last . type ) . toBe ( updateSavingStatuses . type ) ;
102167 expect ( last . payload . status . editReleaseNoteQuery ) . toBe ( RequestStatus . SUCCESSFUL ) ;
@@ -157,4 +222,38 @@ describe('release-notes thunks', () => {
157222 expect ( spy ) . toHaveBeenCalledWith ( expect . objectContaining ( { raw_html_content : '<p>y</p>' } ) ) ;
158223 expect ( spy ) . toHaveBeenCalledWith ( expect . not . objectContaining ( { description : expect . anything ( ) } ) ) ;
159224 } ) ;
225+
226+ test ( 'createReleaseNoteQuery maps sendEmail to send_email_on_publish (true)' , async ( ) => {
227+ const spy = jest . spyOn ( api , 'createReleaseNote' ) . mockResolvedValue ( { id : 1 , title : 't' , rawHtmlContent : '<p>x</p>' } ) ;
228+ const { dispatch } = collectActions ( ) ;
229+ await createReleaseNoteQuery ( {
230+ id : 1 , title : 't' , description : '<p>x</p>' , sendEmail : true ,
231+ } ) ( dispatch ) ;
232+ expect ( spy ) . toHaveBeenCalledWith ( expect . objectContaining ( { send_email_on_publish : true } ) ) ;
233+ expect ( spy ) . toHaveBeenCalledWith ( expect . not . objectContaining ( { sendEmail : expect . anything ( ) } ) ) ;
234+ } ) ;
235+
236+ test ( 'createReleaseNoteQuery defaults send_email_on_publish to false when sendEmail absent' , async ( ) => {
237+ const spy = jest . spyOn ( api , 'createReleaseNote' ) . mockResolvedValue ( { id : 1 , title : 't' , rawHtmlContent : '<p>x</p>' } ) ;
238+ const { dispatch } = collectActions ( ) ;
239+ await createReleaseNoteQuery ( { id : 1 , title : 't' , description : '<p>x</p>' } ) ( dispatch ) ;
240+ expect ( spy ) . toHaveBeenCalledWith ( expect . objectContaining ( { send_email_on_publish : false } ) ) ;
241+ } ) ;
242+
243+ test ( 'editReleaseNoteQuery maps sendEmail to send_email_on_publish (true)' , async ( ) => {
244+ const spy = jest . spyOn ( api , 'editReleaseNote' ) . mockResolvedValue ( { id : 2 , title : 't2' , rawHtmlContent : '<p>y</p>' } ) ;
245+ const { dispatch } = collectActions ( ) ;
246+ await editReleaseNoteQuery ( {
247+ id : 2 , title : 't2' , description : '<p>y</p>' , sendEmail : true ,
248+ } ) ( dispatch ) ;
249+ expect ( spy ) . toHaveBeenCalledWith ( expect . objectContaining ( { send_email_on_publish : true } ) ) ;
250+ expect ( spy ) . toHaveBeenCalledWith ( expect . not . objectContaining ( { sendEmail : expect . anything ( ) } ) ) ;
251+ } ) ;
252+
253+ test ( 'editReleaseNoteQuery defaults send_email_on_publish to false when sendEmail absent' , async ( ) => {
254+ const spy = jest . spyOn ( api , 'editReleaseNote' ) . mockResolvedValue ( { id : 2 , title : 't2' , rawHtmlContent : '<p>y</p>' } ) ;
255+ const { dispatch } = collectActions ( ) ;
256+ await editReleaseNoteQuery ( { id : 2 , title : 't2' , description : '<p>y</p>' } ) ( dispatch ) ;
257+ expect ( spy ) . toHaveBeenCalledWith ( expect . objectContaining ( { send_email_on_publish : false } ) ) ;
258+ } ) ;
160259} ) ;
0 commit comments