-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[#IP-292] Add override on isEmailEnabled value for old profiles (#137)
- Loading branch information
Showing
11 changed files
with
436 additions
and
53 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,18 +5,16 @@ | |
|
||
import { TableService } from "azure-storage"; | ||
import * as dateFmt from "date-fns"; | ||
import * as endOfTomorrow from "date-fns/end_of_tomorrow"; | ||
import * as startOfYesterday from "date-fns/start_of_yesterday"; | ||
import { FiscalCodeHash } from "../../generated/definitions/FiscalCodeHash"; | ||
import { GetSubscriptionsFeedHandler } from "../handler"; | ||
|
||
import { anIncompleteService, aValidService } from "../../__mocks__/mocks"; | ||
|
||
const tomorrow = endOfTomorrow(); | ||
const tomorrow = dateFmt.endOfTomorrow(); | ||
|
||
const yesterday = startOfYesterday(); | ||
const yesterday = dateFmt.startOfYesterday(); | ||
|
||
const yesterdayUTC = dateFmt.format(yesterday, "YYYY-MM-DD"); | ||
const yesterdayUTC = dateFmt.format(yesterday, "yyyy-MM-dd"); | ||
|
||
const userAttrs = { | ||
email: "[email protected]", | ||
|
@@ -82,7 +80,7 @@ describe("GetSubscriptionsFeedHandler", () => { | |
{} as any, | ||
{} as any, | ||
userAttrs as any, | ||
dateFmt.format(tomorrow, "YYYY-MM-DD") | ||
dateFmt.format(tomorrow, "yyyy-MM-dd") | ||
); | ||
expect(result.kind).toBe("IResponseErrorNotFound"); | ||
}); | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,263 @@ | ||
/* eslint-disable no-console */ | ||
/* eslint-disable @typescript-eslint/no-explicit-any */ | ||
import { BlockedInboxOrChannelEnum } from "@pagopa/io-functions-commons/dist/generated/definitions/BlockedInboxOrChannel"; | ||
import { ServiceId } from "@pagopa/io-functions-commons/dist/generated/definitions/ServiceId"; | ||
import { CreatedMessageEvent } from "@pagopa/io-functions-commons/dist/src/models/created_message_event"; | ||
import { UTCISODateFromString } from "@pagopa/ts-commons/lib/dates"; | ||
import { NonNegativeNumber } from "@pagopa/ts-commons/lib/numbers"; | ||
import { fromLeft } from "fp-ts/lib/IOEither"; | ||
import { none, some } from "fp-ts/lib/Option"; | ||
import { taskEither } from "fp-ts/lib/TaskEither"; | ||
import { | ||
aCreatedMessageEventSenderMetadata, | ||
aMessageContent, | ||
aNewMessageWithoutContent, | ||
aRetrievedMessage, | ||
aRetrievedProfile | ||
} from "../../__mocks__/mocks"; | ||
import { getStoreMessageContentActivityHandler } from "../handler"; | ||
|
||
const mockContext = { | ||
// eslint-disable no-console | ||
log: { | ||
error: console.error, | ||
info: console.log, | ||
verbose: console.log, | ||
warn: console.warn | ||
} | ||
} as any; | ||
|
||
const findLastVersionByModelIdMock = jest | ||
.fn() | ||
.mockImplementation(() => taskEither.of(some(aRetrievedProfile))); | ||
const profileModelMock = { | ||
findLastVersionByModelId: jest.fn(findLastVersionByModelIdMock) | ||
}; | ||
|
||
const aBlobResult = { | ||
name: "ABlobName" | ||
}; | ||
|
||
const storeContentAsBlobMock = jest | ||
.fn() | ||
.mockImplementation(() => taskEither.of(some(aBlobResult))); | ||
const upsertMessageMock = jest | ||
.fn() | ||
.mockImplementation(() => taskEither.of(aRetrievedMessage)); | ||
const messageModelMock = { | ||
storeContentAsBlob: jest.fn(storeContentAsBlobMock), | ||
upsert: jest.fn(upsertMessageMock) | ||
}; | ||
|
||
const anOptOutEmailSwitchDate = UTCISODateFromString.decode( | ||
"2021-07-08T23:59:59Z" | ||
).getOrElseL(() => fail("wrong date value")); | ||
|
||
const aPastOptOutEmailSwitchDate = UTCISODateFromString.decode( | ||
"2000-07-08T23:59:59Z" | ||
).getOrElseL(() => fail("wrong date value")); | ||
|
||
const aCreatedMessageEvent: CreatedMessageEvent = { | ||
content: aMessageContent, | ||
message: aNewMessageWithoutContent, | ||
senderMetadata: aCreatedMessageEventSenderMetadata, | ||
serviceVersion: 1 as NonNegativeNumber | ||
}; | ||
|
||
const aRetrievedProfileWithAValidTimestamp = { | ||
...aRetrievedProfile, | ||
_ts: 1625172947000 | ||
}; | ||
describe("getStoreMessageContentActivityHandler", () => { | ||
it("should respond success with a retrieved profile with isEmailEnabled to false", async () => { | ||
const storeMessageContentActivityHandler = getStoreMessageContentActivityHandler( | ||
profileModelMock as any, | ||
messageModelMock as any, | ||
{} as any, | ||
// limit date is after profile timestamp | ||
anOptOutEmailSwitchDate | ||
); | ||
|
||
const result = await storeMessageContentActivityHandler( | ||
mockContext, | ||
aCreatedMessageEvent | ||
); | ||
|
||
expect(result.kind).toBe("SUCCESS"); | ||
if (result.kind === "SUCCESS") { | ||
expect(result.blockedInboxOrChannels).toEqual([]); | ||
expect(result.profile).toEqual({ | ||
...aRetrievedProfile, | ||
isEmailEnabled: false | ||
}); | ||
} | ||
}); | ||
|
||
it("should respond success with a retrieved profile mantaining its original isEmailEnabled property", async () => { | ||
findLastVersionByModelIdMock.mockImplementationOnce(() => | ||
taskEither.of(some(aRetrievedProfileWithAValidTimestamp)) | ||
); | ||
const storeMessageContentActivityHandler = getStoreMessageContentActivityHandler( | ||
profileModelMock as any, | ||
messageModelMock as any, | ||
{} as any, | ||
// limit date is before profile timestamp | ||
aPastOptOutEmailSwitchDate | ||
); | ||
|
||
const result = await storeMessageContentActivityHandler( | ||
mockContext, | ||
aCreatedMessageEvent | ||
); | ||
|
||
expect(result.kind).toBe("SUCCESS"); | ||
if (result.kind === "SUCCESS") { | ||
expect(result.blockedInboxOrChannels).toEqual([]); | ||
expect(result.profile).toEqual(aRetrievedProfileWithAValidTimestamp); | ||
} | ||
}); | ||
|
||
it("should fail if activity input cannot be decoded", async () => { | ||
const storeMessageContentActivityHandler = getStoreMessageContentActivityHandler( | ||
profileModelMock as any, | ||
messageModelMock as any, | ||
{} as any, | ||
aPastOptOutEmailSwitchDate | ||
); | ||
|
||
const result = await storeMessageContentActivityHandler( | ||
mockContext, | ||
{} as any | ||
); | ||
|
||
expect(result.kind).toBe("FAILURE"); | ||
if (result.kind === "FAILURE") { | ||
expect(result.reason).toEqual("BAD_DATA"); | ||
} | ||
}); | ||
|
||
it("should throw an Error if there is an error while fetching profile", async () => { | ||
findLastVersionByModelIdMock.mockImplementationOnce(() => | ||
fromLeft("Profile fetch error") | ||
); | ||
const storeMessageContentActivityHandler = getStoreMessageContentActivityHandler( | ||
profileModelMock as any, | ||
messageModelMock as any, | ||
{} as any, | ||
aPastOptOutEmailSwitchDate | ||
); | ||
|
||
await expect( | ||
storeMessageContentActivityHandler(mockContext, aCreatedMessageEvent) | ||
).rejects.toThrow(); | ||
}); | ||
|
||
it("should return a failure if no profile was found", async () => { | ||
findLastVersionByModelIdMock.mockImplementationOnce(() => | ||
taskEither.of(none) | ||
); | ||
const storeMessageContentActivityHandler = getStoreMessageContentActivityHandler( | ||
profileModelMock as any, | ||
messageModelMock as any, | ||
{} as any, | ||
aPastOptOutEmailSwitchDate | ||
); | ||
|
||
const result = await storeMessageContentActivityHandler( | ||
mockContext, | ||
aCreatedMessageEvent | ||
); | ||
|
||
expect(result.kind).toBe("FAILURE"); | ||
if (result.kind === "FAILURE") { | ||
expect(result.reason).toEqual("PROFILE_NOT_FOUND"); | ||
} | ||
}); | ||
|
||
it("should return a failure if inbox is not enabled", async () => { | ||
findLastVersionByModelIdMock.mockImplementationOnce(() => | ||
taskEither.of(some({ ...aRetrievedProfile, isInboxEnabled: false })) | ||
); | ||
const storeMessageContentActivityHandler = getStoreMessageContentActivityHandler( | ||
profileModelMock as any, | ||
messageModelMock as any, | ||
{} as any, | ||
aPastOptOutEmailSwitchDate | ||
); | ||
|
||
const result = await storeMessageContentActivityHandler( | ||
mockContext, | ||
aCreatedMessageEvent | ||
); | ||
|
||
expect(result.kind).toBe("FAILURE"); | ||
if (result.kind === "FAILURE") { | ||
expect(result.reason).toEqual("MASTER_INBOX_DISABLED"); | ||
} | ||
}); | ||
|
||
it("should return a failure if message sender is blocked", async () => { | ||
findLastVersionByModelIdMock.mockImplementationOnce(() => | ||
taskEither.of( | ||
some({ | ||
...aRetrievedProfile, | ||
blockedInboxOrChannels: { myService: [BlockedInboxOrChannelEnum.INBOX] } | ||
}) | ||
) | ||
); | ||
const storeMessageContentActivityHandler = getStoreMessageContentActivityHandler( | ||
profileModelMock as any, | ||
messageModelMock as any, | ||
{} as any, | ||
aPastOptOutEmailSwitchDate | ||
); | ||
|
||
const result = await storeMessageContentActivityHandler( | ||
mockContext, | ||
{ | ||
...aCreatedMessageEvent, | ||
message: { | ||
...aNewMessageWithoutContent, | ||
senderServiceId: "myService" as ServiceId | ||
} | ||
} | ||
); | ||
|
||
expect(result.kind).toBe("FAILURE"); | ||
if (result.kind === "FAILURE") { | ||
expect(result.reason).toEqual("SENDER_BLOCKED"); | ||
} | ||
}); | ||
|
||
it("should throw an Error if message store operation fails", async () => { | ||
storeContentAsBlobMock.mockImplementationOnce(() => | ||
fromLeft(new Error("Error while storing message content")) | ||
); | ||
const storeMessageContentActivityHandler = getStoreMessageContentActivityHandler( | ||
profileModelMock as any, | ||
messageModelMock as any, | ||
{} as any, | ||
aPastOptOutEmailSwitchDate | ||
); | ||
|
||
await expect( | ||
storeMessageContentActivityHandler(mockContext, aCreatedMessageEvent) | ||
).rejects.toThrow(); | ||
}); | ||
|
||
it("should throw an Error if message upsert fails", async () => { | ||
upsertMessageMock.mockImplementationOnce(() => | ||
fromLeft(new Error("Error while upserting message")) | ||
); | ||
const storeMessageContentActivityHandler = getStoreMessageContentActivityHandler( | ||
profileModelMock as any, | ||
messageModelMock as any, | ||
{} as any, | ||
aPastOptOutEmailSwitchDate | ||
); | ||
|
||
await expect( | ||
storeMessageContentActivityHandler(mockContext, aCreatedMessageEvent) | ||
).rejects.toThrow(); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.