@@ -163,6 +163,54 @@ component extends="tests.resources.ModuleIntegrationSpec" appMapping="/app" {
163163 } );
164164 } );
165165
166+ it ( " builds resubscribe requests for each valid subscriber" , function () {
167+ var result = variables .client .resubscribe (
168+ subscribers = [ " person1@example.com" , " person2@example.com" ],
169+ concurrencyLimit = 2
170+ );
171+
172+ expect ( result .total ).toBe ( 2 );
173+ expect ( result .success ).toBeTrue ();
174+ expect ( result .succeeded ).toBe ( 2 );
175+ expect ( result .failed ).toBe ( 0 );
176+ expect ( result .results ).toHaveLength ( 2 );
177+ expect ( result .results [ 1 ].subscriber ).toBe ( " person1@example.com" );
178+ expect ( result .results [ 1 ].success ).toBeTrue ();
179+ expect ( result .results [ 1 ].statusCode ).toBeGTE ( 200 );
180+ expect ( result .results [ 1 ].statusCode ).toBeLT ( 300 );
181+ expect ( result .results [ 2 ].subscriber ).toBe ( " person2@example.com" );
182+ expect ( result .results [ 2 ].success ).toBeTrue ();
183+ expect ( result .results [ 2 ].statusCode ).toBeGTE ( 200 );
184+ expect ( result .results [ 2 ].statusCode ).toBeLT ( 300 );
185+ expect ( variables .hyper ).toHaveSentCount ( 2 );
186+
187+ expect ( variables .hyper ).toHaveSentRequest ( function ( req ) {
188+ var body = req .getBody ();
189+ return req .getMethod () == " PUT"
190+ && req .getUrl ().startsWith ( " /v2/contacts/email:" )
191+ && findNoCase ( " person1" , req .getUrl () )
192+ && body .forceSubscribe == true
193+ && body .channels .email .subscribeStatus == " subscribed" ;
194+ } );
195+ } );
196+
197+ it ( " url encodes special characters for resubscribe endpoint email key" , function () {
198+ var result = variables .client .resubscribe ( subscribers = [ " first.last+promo%tag@example.com" ] );
199+
200+ expect ( result .total ).toBe ( 1 );
201+ expect ( result .success ).toBeTrue ();
202+ expect ( variables .hyper ).toHaveSentCount ( 1 );
203+
204+ expect ( variables .hyper ).toHaveSentRequest ( function ( req ) {
205+ var requestURL = req .getUrl ();
206+ return req .getMethod () == " PUT"
207+ && requestURL .startsWith ( " /v2/contacts/email:" )
208+ && ! requestURL .endsWith ( " /unsubscribe/email" )
209+ && findNoCase ( " %25" , requestURL )
210+ && ( findNoCase ( " %2B" , requestURL ) || findNoCase ( " +" , requestURL ) );
211+ } );
212+ } );
213+
166214 it ( " throws for an empty list key" , function () {
167215 expect ( function () {
168216 variables .client .create ( listKey = " " , subscribers = [ " person@example.com" ] );
@@ -187,6 +235,12 @@ component extends="tests.resources.ModuleIntegrationSpec" appMapping="/app" {
187235 } ).toThrow ( type = " cordial-sdk.InvalidSubscribers" );
188236 } );
189237
238+ it ( " throws for an empty subscriber array when resubscribing" , function () {
239+ expect ( function () {
240+ variables .client .resubscribe ( subscribers = [] );
241+ } ).toThrow ( type = " cordial-sdk.InvalidSubscribers" );
242+ } );
243+
190244 it ( " returns failed results for blank subscriber values while still processing valid emails" , function () {
191245 var result = variables .client .create (
192246 listKey = " myList" ,
@@ -243,6 +297,21 @@ component extends="tests.resources.ModuleIntegrationSpec" appMapping="/app" {
243297 expect ( variables .hyper ).toHaveSentCount ( 1 );
244298 } );
245299
300+ it ( " returns mixed success and failure details for resubscribe when a subscriber is blank" , function () {
301+ var result = variables .client .resubscribe ( subscribers = [ " person@example.com" , " " ] );
302+
303+ expect ( result .total ).toBe ( 2 );
304+ expect ( result .success ).toBeFalse ();
305+ expect ( result .succeeded ).toBe ( 1 );
306+ expect ( result .failed ).toBe ( 1 );
307+ expect ( result .results ).toHaveLength ( 2 );
308+ expect ( result .results [ 1 ].subscriber ).toBe ( " " );
309+ expect ( result .results [ 1 ].exceptionType ).toBe ( " InvalidSubscriber" );
310+ expect ( result .results [ 2 ].subscriber ).toBe ( " person@example.com" );
311+ expect ( result .results [ 2 ].success ).toBeTrue ();
312+ expect ( variables .hyper ).toHaveSentCount ( 1 );
313+ } );
314+
246315 it ( " returns only preflight failures for cancel when all subscribers are blank" , function () {
247316 var result = variables .client .cancel ( listKey = " myList" , subscribers = [ " " , " " ] );
248317
@@ -269,6 +338,19 @@ component extends="tests.resources.ModuleIntegrationSpec" appMapping="/app" {
269338 expect ( variables .hyper ).toHaveSentNothing ();
270339 } );
271340
341+ it ( " returns only preflight failures for resubscribe when all subscribers are blank" , function () {
342+ var result = variables .client .resubscribe ( subscribers = [ " " , " " ] );
343+
344+ expect ( result .total ).toBe ( 2 );
345+ expect ( result .success ).toBeFalse ();
346+ expect ( result .succeeded ).toBe ( 0 );
347+ expect ( result .failed ).toBe ( 2 );
348+ expect ( result .results ).toHaveLength ( 2 );
349+ expect ( result .results [ 1 ].exceptionType ).toBe ( " InvalidSubscriber" );
350+ expect ( result .results [ 2 ].exceptionType ).toBe ( " InvalidSubscriber" );
351+ expect ( variables .hyper ).toHaveSentNothing ();
352+ } );
353+
272354 it ( " returns only preflight failures when all subscribers are blank and sends no requests" , function () {
273355 var result = variables .client .create ( listKey = " myList" , subscribers = [ " " , " " ] );
274356
@@ -387,6 +469,26 @@ component extends="tests.resources.ModuleIntegrationSpec" appMapping="/app" {
387469 expect ( result .results [ 1 ].statusCode ).toBe ( 503 );
388470 } );
389471
472+ it ( " marks resubscribe results as failed when Cordial returns non-2xx" , function () {
473+ variables .hyper
474+ .fake ( {
475+ " */v2/contacts/email:*" : function ( newFakeResponse , req ) {
476+ return newFakeResponse ( 503 , " Service Unavailable" , " {}" );
477+ }
478+ } )
479+ .preventStrayRequests ();
480+
481+ var result = variables .client .resubscribe ( subscribers = [ " person@example.com" ] );
482+
483+ expect ( result .total ).toBe ( 1 );
484+ expect ( result .success ).toBeFalse ();
485+ expect ( result .succeeded ).toBe ( 0 );
486+ expect ( result .failed ).toBe ( 1 );
487+ expect ( result .results [ 1 ].subscriber ).toBe ( " person@example.com" );
488+ expect ( result .results [ 1 ].success ).toBeFalse ();
489+ expect ( result .results [ 1 ].statusCode ).toBe ( 503 );
490+ } );
491+
390492 it ( " handles async future failures and returns mixed results" , function () {
391493 variables .hyper
392494 .fake ( {
0 commit comments