Skip to content

Commit

Permalink
Remove length limits for all interactive messages
Browse files Browse the repository at this point in the history
  • Loading branch information
haomingli2020 committed Mar 21, 2024
1 parent d89b532 commit 272dd45
Show file tree
Hide file tree
Showing 11 changed files with 12 additions and 154 deletions.
2 changes: 1 addition & 1 deletion local-testing/amazon-connect-chat-interface.js

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import PT from "prop-types";
import { RichMessageRenderer } from "../../../RichMessageComponents";
import { InteractiveMessage, MessageBody } from "../InteractiveMessage";
import { Button } from "connect-core";
import { truncateStrFromCharLimit, truncateElementFromLimit } from "../../../../../utils/helper";
import { truncateStrFromCharLimit } from "../../../../../utils/helper";
import isJSON from "is-json";
import { InteractiveMessageType } from "../../../datamodel/Model";

Expand Down Expand Up @@ -142,7 +142,6 @@ export default function Carousel({ content, addMessage }) {

// Frontend field validations
const title = truncateStrFromCharLimit(inputTitle, InteractiveMessageType.CAROUSEL, "titleCharLimit");
const elements = truncateElementFromLimit(inputElems, InteractiveMessageType.CAROUSEL, "elementsRenderedMax");

return (
<>
Expand All @@ -160,7 +159,7 @@ export default function Carousel({ content, addMessage }) {
</ScrollButton>

<ResponsesSection ref={scrollerRef} data-testid='interactive-carousel-response-section'>
<NestedInteractiveMessages elements={elements} addMessage={addMessage} />
<NestedInteractiveMessages elements={inputElems} addMessage={addMessage} />
</ResponsesSection>

<ScrollButton
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -177,22 +177,6 @@ describe("<Carousel />", () => {
});
});

it("Should only render up to 5 nested pickers", () => {
const carouselOverFiveLimit = {
...mockCarouselContent,
elements: [
...mockCarouselContent.elements,
mockNestedPanelPickerFlights,
mockNestedPanelPickerHotels,
mockNestedListPickerDining,
mockNestedPanelPickerFlights,
],
};
renderElement({ ...mockProps, content: carouselOverFiveLimit });

expect(screen.getAllByText("Select an option:")).toHaveLength(5);
});

it("Should render reply option buttons and be accessible", () => {
renderElement(mockProps);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import {
PickerOptionTitle,
PickerElementLinkOption
} from "../InteractiveMessage";
import { createInteractiveMessagePayload, truncateElementFromLimit, truncateStrFromCharLimit } from "../../../../../utils/helper";
import { createInteractiveMessagePayload, truncateStrFromCharLimit } from "../../../../../utils/helper";
import { InteractiveMessageSelectionType, InteractiveMessageType } from "../../../datamodel/Model";
import { RichMessageRenderer } from "../../../RichMessageComponents";

Expand Down Expand Up @@ -147,7 +147,6 @@ export default function ListPicker({
// Frontend field validations
const title = truncateStrFromCharLimit(inputTitle, InteractiveMessageType.LIST_PICKER, "titleCharLimit");
const subtitle = truncateStrFromCharLimit(inputSubtitle, InteractiveMessageType.LIST_PICKER, "subtitleCharLimit");
const elements = truncateElementFromLimit(inputElements, InteractiveMessageType.LIST_PICKER, "elementsRenderedMax");

const [imageLoaded, setImageLoaded] = useState(false);
const [elementImagesLoadedCount, setElementImagesLoadedCount] = useState(0);
Expand All @@ -161,7 +160,7 @@ export default function ListPicker({
}

function onItemClick(index) {
const selectedElement = elements[index];
const selectedElement = inputElements[index];
const payload = createInteractiveMessagePayload(
selectedElement,
preIndex,
Expand All @@ -177,10 +176,10 @@ export default function ListPicker({
}

const showElementImages = () => {
const actionBtnCount = elements.filter((ele) => {
const actionBtnCount = inputElements.filter((ele) => {
return ele.actionDetail;
}).length;
return elementImagesLoadedCount === elements.length - actionBtnCount;
return elementImagesLoadedCount === inputElements.length - actionBtnCount;
};

return (
Expand All @@ -197,7 +196,7 @@ export default function ListPicker({
<HeaderText title={title} subtitle={subtitle} />
<ResponsesSection isCarouselElem={isCarouselElem}>
<div>
{elements.map((listPickerElement, index) => (
{inputElements.map((listPickerElement, index) => (
<ListPickerElement
key={"element-" + index}
element={listPickerElement}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,23 +96,6 @@ describe("<ListPicker />", () => {
createMsgPayloadSpy.mockRestore();
});

it("Should only render max number of elements", () => {
const { elementsRenderedMax } = LIST_PICKER_CONSTRAINTS;

const listPickerOverElementLimit = {
...mockListPickerContent,
elements: Array.apply(null, Array(elementsRenderedMax + 3)).map((e, index) => ({ title: `ListPickerElement${index}` })),
};
renderElement({ ...mockProps, content: listPickerOverElementLimit });

const elementOptions = screen.getAllByRole("button");
expect(elementOptions).toHaveLength(elementsRenderedMax);
expect(() => screen.getByText(`ListPickerElement${elementsRenderedMax}`)).toThrow(
"Unable to find an element"
);
expect(() => screen.getByText(`ListPickerElement${elementsRenderedMax - 1}`)).not.toThrow();
});

it.each([
["title", LIST_PICKER_CONSTRAINTS.titleCharLimit],
["subtitle", LIST_PICKER_CONSTRAINTS.subtitleCharLimit]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import {
import styled from "styled-components";
import PT from "prop-types";
import { InteractiveMessageSelectionType, InteractiveMessageType } from "../../../datamodel/Model";
import { createInteractiveMessagePayload, truncateElementFromLimit, truncateStrFromCharLimit } from "../../../../../utils/helper";
import { createInteractiveMessagePayload, truncateStrFromCharLimit } from "../../../../../utils/helper";

//#region Styled Components
const ImageContainer = styled.div`
Expand Down Expand Up @@ -96,7 +96,6 @@ export default function Panel({
// Frontend field validations
const title = truncateStrFromCharLimit(inputTitle, InteractiveMessageType.PANEL, "titleCharLimit");
const subtitle = truncateStrFromCharLimit(inputSubtitle, InteractiveMessageType.PANEL, "subtitleCharLimit");
const elements = truncateElementFromLimit(inputElements, InteractiveMessageType.PANEL, "elementsRenderedMax");

const [imageLoaded, setImageLoaded] = useState(false);

Expand All @@ -105,7 +104,7 @@ export default function Panel({
}

function onItemClick(index) {
const selectedElement = elements[index];
const selectedElement = inputElements[index];
const payload = createInteractiveMessagePayload(
selectedElement,
preIndex,
Expand Down Expand Up @@ -134,7 +133,7 @@ export default function Panel({
<HeaderText title={title} subtitle={subtitle} />
<ResponsesSection isCarouselElem={isCarouselElem}>
<div>
{elements.map((element, index) => (
{inputElements.map((element, index) => (
<PanelPickerElement
key={"element-" + index}
handleButtonClick={() => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,23 +72,6 @@ describe("<Panel />", () => {
createMsgPayloadSpy.mockRestore();
});

it("Should only render max number of elements", () => {
const { elementsRenderedMax } = PANEL_CONSTRAINTS;

const panelOverElementLimit = {
...mockPanelContent,
elements: Array.apply(null, Array(elementsRenderedMax + 3)).map((e, index) => ({ title: `PanelElement${index}` })),
};
renderElement({ ...mockProps, content: panelOverElementLimit });

const elementOptions = screen.getAllByRole("button");
expect(elementOptions).toHaveLength(elementsRenderedMax);
expect(() => screen.getByText(`PanelElement${elementsRenderedMax}`)).toThrow(
"Unable to find an element"
);
expect(() => screen.getByText(`PanelElement${elementsRenderedMax - 1}`)).not.toThrow();
});

it.each([
["title", PANEL_CONSTRAINTS.titleCharLimit],
["subtitle", PANEL_CONSTRAINTS.subtitleCharLimit]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ export default function QuickReply({ content, addMessage }) {
<RichMessageRenderer content={title} />
</MessageBody>
<ResponsesSection data-testid="interactive-quickreply-response-section">
{elements.slice(0, 5).map((element, index) => (
{elements.map((element, index) => (
<ReplyElement
element={element}
handleSelection={addMessage}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,25 +97,6 @@ describe("<QuickReply />", () => {
});
});

it("Should only render up to 5 elements", () => {
const { elementsRenderedMax } = QUICK_REPLY_CONSTRAINTS;

const quickReplyOverFiveLimit = {
...mockQuickReplyContent,
elements: [
...mockQuickReplyContent.elements,
{ title: "Ignored Option #6!" },
],
};
renderElement({ ...mockProps, content: quickReplyOverFiveLimit });

const quickReplyOptions = screen.getAllByRole("button");
expect(quickReplyOptions).toHaveLength(elementsRenderedMax);
expect(() => screen.getByText("Ignored Option #6!")).toThrow(
"Unable to find an element"
);
});

it("Should truncate a title over the character limit", () => {
const { titleCharLimit } = QUICK_REPLY_CONSTRAINTS;

Expand Down
24 changes: 0 additions & 24 deletions src/utils/helper.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,13 +76,11 @@ export const INTERACTIVE_MESSAGE_CONSTRAINTS = {
[InteractiveMessageType.PANEL]: {
titleCharLimit: 400,
subtitleCharLimit: 400,
elementsRenderedMax: 10,
elementTitleCharLimit: 400
},
[InteractiveMessageType.LIST_PICKER]: {
titleCharLimit: 400,
subtitleCharLimit: 400,
elementsRenderedMax: 6,
elementTitleCharLimit: 400,
elementSubtitleCharLimit: 400,
},
Expand All @@ -92,11 +90,9 @@ export const INTERACTIVE_MESSAGE_CONSTRAINTS = {
},
[InteractiveMessageType.CAROUSEL]: {
titleCharLimit: 400,
elementsRenderedMax: 5,
},
[InteractiveMessageType.QUICK_REPLY]: {
titleCharLimit: 400,
elementsRenderedMax: 5,
replyOptionCharLimit: 200,
}
}
Expand Down Expand Up @@ -132,23 +128,3 @@ export const truncateStrFromCharLimit = (str, InteractiveMessageType, fieldLimit
return sanitizedStr.substring(0, MAX_LENGTH) + "...";
}
}

/**
* Truncates an array of elements based on the specified minimum and maximum limits.
*
* @param {Array} elements - The array of elements to truncate.
* @param {string} InteractiveMessageType - interactive message templateType.
* @param {string} elementsRenderedMaxKey - key to retrieve max constraint from INTERACTIVE_MESSAGE_CONSTRAINTS.
* @returns {Array} The truncated array of elements.
*/
export const truncateElementFromLimit = (elements, InteractiveMessageType, elementsRenderedMaxKey) => {
const templateContraints = INTERACTIVE_MESSAGE_CONSTRAINTS[InteractiveMessageType] || {};
const MAX_LIMIT = templateContraints[elementsRenderedMaxKey] || elements.length ;

if (elements.length > MAX_LIMIT) {
console.warn(`[${InteractiveMessageType} template] ${elementsRenderedMaxKey} of ${MAX_LIMIT} was exceeded`)
return elements.slice(0, MAX_LIMIT);
}

return elements;
}
46 changes: 0 additions & 46 deletions src/utils/helper.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,6 @@ describe("Interactive Message Constraints", () => {
it("should include constraints matching public documentation", () => {
expect(PANEL_CONSTRAINTS).toHaveProperty("titleCharLimit", 400);
expect(PANEL_CONSTRAINTS).toHaveProperty("subtitleCharLimit", 400);
expect(PANEL_CONSTRAINTS).toHaveProperty("elementsRenderedMax", 10);
expect(PANEL_CONSTRAINTS).toHaveProperty("elementTitleCharLimit", 400);
});
});
Expand All @@ -80,7 +79,6 @@ describe("Interactive Message Constraints", () => {
it("should include constraints matching public documentation", () => {
expect(LIST_PICKER_CONSTRAINTS).toHaveProperty("titleCharLimit", 400);
expect(LIST_PICKER_CONSTRAINTS).toHaveProperty("subtitleCharLimit", 400);
expect(LIST_PICKER_CONSTRAINTS).toHaveProperty("elementsRenderedMax", 6);
expect(LIST_PICKER_CONSTRAINTS).toHaveProperty("elementTitleCharLimit", 400);
expect(LIST_PICKER_CONSTRAINTS).toHaveProperty("elementSubtitleCharLimit", 400);
});
Expand All @@ -100,7 +98,6 @@ describe("Interactive Message Constraints", () => {

it("should include constraints matching public documentation", () => {
expect(CAROUSEL_CONSTRAINTS).toHaveProperty("titleCharLimit", 400);
expect(CAROUSEL_CONSTRAINTS).toHaveProperty("elementsRenderedMax", 5);
});
});

Expand All @@ -109,7 +106,6 @@ describe("Interactive Message Constraints", () => {

it("should include constraints matching public documentation", () => {
expect(QUICK_REPLY_CONSTRAINTS).toHaveProperty("titleCharLimit", 400);
expect(QUICK_REPLY_CONSTRAINTS).toHaveProperty("elementsRenderedMax", 5);
expect(QUICK_REPLY_CONSTRAINTS).toHaveProperty("replyOptionCharLimit", 200);
});
});
Expand Down Expand Up @@ -187,45 +183,3 @@ describe("truncateStrFromCharLimit util", () => {
expect(truncateStrFromCharLimit(rawStr, InteractiveMessageType.PANEL, "titleCharLimit")).toEqual(expectedCleanStr);
});
});

describe("truncateElementFromLimit util", () => {
it("should return the original array when the length is within the limits", () => {
const elements = [1, 2, 3];
const result = truncateElementFromLimit(
elements,
"Carousel",
"elementsRenderedMax"
);
expect(result).toEqual(elements);
});

it("should truncate the array when the length is below the minimum limit", () => {
const elements = [1];
const result = truncateElementFromLimit(
elements,
"Carousel",
"elementsRenderedMax"
);
expect(result).toEqual(elements.slice(0, 2));
});

it("should truncate the array when the length exceeds the maximum limit", () => {
const elements = [1, 2, 3, 4, 5, 6];
const result = truncateElementFromLimit(
elements,
"Carousel",
"elementsRenderedMax"
);
expect(result).toEqual(elements.slice(0, 5));
});

it("should handle missing limits gracefully", () => {
const elements = [1, 2];
const result = truncateElementFromLimit(
elements,
"InvalidMessageType",
"elementsRenderedMax"
);
expect(result).toEqual(elements);
});
});

0 comments on commit 272dd45

Please sign in to comment.