Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 49 additions & 0 deletions src/core/classes/Iterable.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,55 @@ describe('Iterable', () => {
});
});

describe('logout', () => {
it('should call setEmail with null', () => {
// GIVEN no parameters
// WHEN Iterable.logout is called
const setEmailSpy = jest.spyOn(Iterable, 'setEmail');
Iterable.logout();
// THEN Iterable.setEmail is called with null
expect(setEmailSpy).toBeCalledWith(null);
setEmailSpy.mockRestore();
});

it('should call setUserId with null', () => {
// GIVEN no parameters
// WHEN Iterable.logout is called
const setUserIdSpy = jest.spyOn(Iterable, 'setUserId');
Iterable.logout();
// THEN Iterable.setUserId is called with null
expect(setUserIdSpy).toBeCalledWith(null);
setUserIdSpy.mockRestore();
});

it('should clear email and userId', async () => {
// GIVEN a user is logged in
Iterable.setEmail('user@example.com');
Iterable.setUserId('user123');
// WHEN Iterable.logout is called
Comment on lines +103 to +105
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

email and userId usually dont go together.
When email is set and we call setUserId, it goes through logging out user with email id and then tries to log in.
So it should ideally be setEmail > logout > assernull for email

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I know.. this doesn't call the internal functionality for setting user id
and email, so I'm just doing this as a test to make sure that both are cleared
later. I'll add a comment to address this.

Iterable.logout();
// THEN email and userId are set to null
const email = await Iterable.getEmail();
const userId = await Iterable.getUserId();
expect(email).toBeNull();
expect(userId).toBeNull();
});

it('should call setEmail and setUserId with null', () => {
// GIVEN no parameters
const setEmailSpy = jest.spyOn(Iterable, 'setEmail');
const setUserIdSpy = jest.spyOn(Iterable, 'setUserId');
// WHEN Iterable.logout is called
Iterable.logout();
// THEN both methods are called with null
expect(setEmailSpy).toBeCalledWith(null);
expect(setUserIdSpy).toBeCalledWith(null);
// Clean up
setEmailSpy.mockRestore();
setUserIdSpy.mockRestore();
});
});

describe('disableDeviceForCurrentUser', () => {
it('should disable the device for the current user', () => {
// GIVEN no parameters
Expand Down
37 changes: 30 additions & 7 deletions src/core/classes/Iterable.ts
Original file line number Diff line number Diff line change
Expand Up @@ -890,6 +890,34 @@ export class Iterable {
});
}

/**
* Logs out the current user from the Iterable SDK.
*
* This method will remove all event listeners for the Iterable SDK and set the email and user ID to null.
*
* @example
* ```typescript
* Iterable.logout();
* ```
*/
static logout() {
Iterable.removeAllEventListeners();
Iterable.setEmail(null);
Iterable.setUserId(null);
}

/**
* Removes all event listeners for the Iterable SDK.
*/
private static removeAllEventListeners() {
RNEventEmitter.removeAllListeners(IterableEventName.handleUrlCalled);
RNEventEmitter.removeAllListeners(IterableEventName.handleInAppCalled);
RNEventEmitter.removeAllListeners(IterableEventName.handleCustomActionCalled);
RNEventEmitter.removeAllListeners(IterableEventName.handleAuthCalled);
RNEventEmitter.removeAllListeners(IterableEventName.handleAuthSuccessCalled);
RNEventEmitter.removeAllListeners(IterableEventName.handleAuthFailureCalled);
}
Comment on lines +903 to +919
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good


/**
* Sets up event handlers for various Iterable events.
*
Expand All @@ -912,12 +940,7 @@ export class Iterable {
*/
private static setupEventHandlers() {
// Remove all listeners to avoid duplicate listeners
RNEventEmitter.removeAllListeners(IterableEventName.handleUrlCalled);
RNEventEmitter.removeAllListeners(IterableEventName.handleInAppCalled);
RNEventEmitter.removeAllListeners(
IterableEventName.handleCustomActionCalled
);
RNEventEmitter.removeAllListeners(IterableEventName.handleAuthCalled);
Iterable.removeAllEventListeners();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catching all in one

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!


if (Iterable.savedConfig.urlHandler) {
RNEventEmitter.addListener(IterableEventName.handleUrlCalled, (dict) => {
Expand Down Expand Up @@ -966,7 +989,7 @@ export class Iterable {
// Asks frontend of the client/app to pass authToken
Iterable.savedConfig.authHandler!()
.then((promiseResult) => {
// Promise result can be either just String OR of type AuthResponse.
// Promise result can be either just String OR of type AuthRespronse.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Spell mistake

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ha! I'm guessing that I pressed r to refresh the app, but was focused here
instead of the terminal

// If type AuthReponse, authToken will be parsed looking for `authToken` within promised object. Two additional listeners will be registered for success and failure callbacks sent by native bridge layer.
// Else it will be looked for as a String.
if (isIterableAuthResponse(promiseResult)) {
Expand Down