fix: broken email embed for rating question (#5890)

Co-authored-by: Piyush Gupta <piyushguptaa2z123@gmail.com>
This commit is contained in:
Dhruwang Jariwala
2025-06-16 17:19:19 +05:30
committed by GitHub
parent bebe29815d
commit c8e9194ab6
16 changed files with 121 additions and 637 deletions
@@ -61,20 +61,20 @@ describe("RatingSmiley", () => {
cleanup();
});
const activeClass = "fill-rating-fill";
const activeClass = "bg-rating-fill";
// Test branch: range === 10 => iconsIdx = [0,1,2,...,9]
test("renders correct icon for range 10 when active", () => {
// For idx 0, iconsIdx[0] === 0, which corresponds to TiredFace.
const { getByTestId } = render(<RatingSmiley active={true} idx={0} range={10} addColors={true} />);
const icon = getByTestId("TiredFace");
const icon = getByTestId("tired");
expect(icon).toBeDefined();
expect(icon.className).toContain(activeClass);
});
test("renders correct icon for range 10 when inactive", () => {
const { getByTestId } = render(<RatingSmiley active={false} idx={0} range={10} />);
const icon = getByTestId("TiredFace");
const icon = getByTestId("tired");
expect(icon).toBeDefined();
expect(icon.className).toContain("fill-none");
});
@@ -83,7 +83,7 @@ describe("RatingSmiley", () => {
test("renders correct icon for range 7 when active", () => {
// For idx 0, iconsIdx[0] === 1, which corresponds to WearyFace.
const { getByTestId } = render(<RatingSmiley active={true} idx={0} range={7} addColors={true} />);
const icon = getByTestId("WearyFace");
const icon = getByTestId("weary");
expect(icon).toBeDefined();
expect(icon.className).toContain(activeClass);
});
@@ -92,7 +92,7 @@ describe("RatingSmiley", () => {
test("renders correct icon for range 5 when active", () => {
// For idx 0, iconsIdx[0] === 3, which corresponds to FrowningFace.
const { getByTestId } = render(<RatingSmiley active={true} idx={0} range={5} addColors={true} />);
const icon = getByTestId("FrowningFace");
const icon = getByTestId("frowning");
expect(icon).toBeDefined();
expect(icon.className).toContain(activeClass);
});
@@ -101,7 +101,7 @@ describe("RatingSmiley", () => {
test("renders correct icon for range 4 when active", () => {
// For idx 0, iconsIdx[0] === 4, corresponding to ConfusedFace.
const { getByTestId } = render(<RatingSmiley active={true} idx={0} range={4} addColors={true} />);
const icon = getByTestId("ConfusedFace");
const icon = getByTestId("confused");
expect(icon).toBeDefined();
expect(icon.className).toContain(activeClass);
});
@@ -110,7 +110,7 @@ describe("RatingSmiley", () => {
test("renders correct icon for range 3 when active", () => {
// For idx 0, iconsIdx[0] === 4, corresponding to ConfusedFace.
const { getByTestId } = render(<RatingSmiley active={true} idx={0} range={3} addColors={true} />);
const icon = getByTestId("ConfusedFace");
const icon = getByTestId("confused");
expect(icon).toBeDefined();
expect(icon.className).toContain(activeClass);
});
@@ -1,93 +1,89 @@
import type { JSX } from "react";
import {
ConfusedFace,
FrowningFace,
GrinningFaceWithSmilingEyes,
GrinningSquintingFace,
NeutralFace,
PerseveringFace,
SlightlySmilingFace,
SmilingFaceWithSmilingEyes,
TiredFace,
WearyFace,
} from "../SingleResponseCard/components/Smileys";
interface RatingSmileyProps {
active: boolean;
idx: number;
range: number;
addColors?: boolean;
baseUrl?: string;
}
const getSmileyColor = (range: number, idx: number) => {
if (range > 5) {
if (range - idx < 3) return "fill-emerald-100";
if (range - idx < 5) return "fill-orange-100";
return "fill-rose-100";
if (range - idx < 3) return "bg-emerald-100";
if (range - idx < 5) return "bg-orange-100";
return "bg-rose-100";
} else if (range < 5) {
if (range - idx < 2) return "fill-emerald-100";
if (range - idx < 3) return "fill-orange-100";
return "fill-rose-100";
if (range - idx < 2) return "bg-emerald-100";
if (range - idx < 3) return "bg-orange-100";
return "bg-rose-100";
} else {
if (range - idx < 3) return "fill-emerald-100";
if (range - idx < 4) return "fill-orange-100";
return "fill-rose-100";
if (range - idx < 3) return "bg-emerald-100";
if (range - idx < 4) return "bg-orange-100";
return "bg-rose-100";
}
};
const getSmiley = (iconIdx: number, idx: number, range: number, active: boolean, addColors: boolean) => {
const activeColor = "fill-rating-fill";
const inactiveColor = addColors ? getSmileyColor(range, idx) : "fill-none";
// Helper function to get smiley image URL based on index and range
const getSmiley = (
iconIdx: number,
idx: number,
range: number,
active: boolean,
addColors: boolean,
baseUrl?: string
): JSX.Element => {
const activeColor = "bg-rating-fill";
const inactiveColor = addColors ? getSmileyColor(range, idx) : "bg-fill-none";
const icons = [
<TiredFace className={active ? activeColor : inactiveColor} data-testid="TiredFace" key="tired-face" />,
<WearyFace className={active ? activeColor : inactiveColor} data-testid="WearyFace" key="weary-face" />,
<PerseveringFace
className={active ? activeColor : inactiveColor}
data-testid="PerseveringFace"
key="perserving-face"
/>,
<FrowningFace
className={active ? activeColor : inactiveColor}
data-testid="FrowningFace"
key="frowning-face"
/>,
<ConfusedFace
className={active ? activeColor : inactiveColor}
data-testid="ConfusedFace"
key="confused-face"
/>,
<NeutralFace
className={active ? activeColor : inactiveColor}
data-testid="NeutralFace"
key="neutral-face"
/>,
<SlightlySmilingFace
className={active ? activeColor : inactiveColor}
data-testid="SlightlySmilingFace"
key="slightly-smiling-face"
/>,
<SmilingFaceWithSmilingEyes
className={active ? activeColor : inactiveColor}
data-testid="SmilingFaceWithSmilingEyes"
key="smiling-face-with-smiling-eyes"
/>,
<GrinningFaceWithSmilingEyes
className={active ? activeColor : inactiveColor}
data-testid="GrinningFaceWithSmilingEyes"
key="grinning-face-with-smiling-eyes"
/>,
<GrinningSquintingFace
className={active ? activeColor : inactiveColor}
data-testid="GrinningSquintingFace"
key="grinning-squinting-face"
/>,
const faceIcons = [
"tired",
"weary",
"persevering",
"frowning",
"confused",
"neutral",
"slightly-smiling",
"smiling-face-with-smiling-eyes",
"grinning-face-with-smiling-eyes",
"grinning-squinting",
];
return icons[iconIdx];
const icon = (
<img
data-testid={faceIcons[iconIdx]}
src={
baseUrl
? `${baseUrl}/smiley-icons/${faceIcons[iconIdx]}-face.png`
: `/smiley-icons/${faceIcons[iconIdx]}-face.png`
}
alt={faceIcons[iconIdx]}
width={24}
height={24}
className={`${active ? activeColor : inactiveColor} rounded-full`}
/>
);
return (
<table style={{ width: "48px", height: "48px" }}>
{" "}
{/* NOSONAR S5256 - Need table layout for email compatibility (gmail) */}
<tr>
<td align="center" valign="middle">
{icon}
</td>
</tr>
</table>
);
};
export const RatingSmiley = ({ active, idx, range, addColors = false }: RatingSmileyProps): JSX.Element => {
export const RatingSmiley = ({
active,
idx,
range,
addColors = false,
baseUrl,
}: RatingSmileyProps): JSX.Element => {
let iconsIdx: number[] = [];
if (range === 10) iconsIdx = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
else if (range === 7) iconsIdx = [1, 3, 4, 5, 6, 8, 9];
@@ -96,5 +92,5 @@ export const RatingSmiley = ({ active, idx, range, addColors = false }: RatingSm
else if (range === 4) iconsIdx = [4, 5, 6, 7];
else if (range === 3) iconsIdx = [4, 5, 7];
return getSmiley(iconsIdx[idx], idx, range, active, addColors);
return getSmiley(iconsIdx[idx], idx, range, active, addColors, baseUrl);
};
@@ -1,60 +0,0 @@
import { cleanup, render } from "@testing-library/react";
import { afterEach, describe, expect, test } from "vitest";
import {
ConfusedFace,
FrowningFace,
GrinningFaceWithSmilingEyes,
GrinningSquintingFace,
NeutralFace,
PerseveringFace,
SlightlySmilingFace,
SmilingFaceWithSmilingEyes,
TiredFace,
WearyFace,
} from "./Smileys";
const checkSvg = (Component: React.FC<React.SVGProps<SVGElement>>) => {
const { container } = render(<Component />);
const svg = container.querySelector("svg");
expect(svg).toBeTruthy();
expect(svg).toHaveAttribute("viewBox", "0 0 72 72");
expect(svg).toHaveAttribute("width", "36");
expect(svg).toHaveAttribute("height", "36");
};
describe("Smileys", () => {
afterEach(() => {
cleanup();
});
test("renders TiredFace", () => {
checkSvg(TiredFace);
});
test("renders WearyFace", () => {
checkSvg(WearyFace);
});
test("renders PerseveringFace", () => {
checkSvg(PerseveringFace);
});
test("renders FrowningFace", () => {
checkSvg(FrowningFace);
});
test("renders ConfusedFace", () => {
checkSvg(ConfusedFace);
});
test("renders NeutralFace", () => {
checkSvg(NeutralFace);
});
test("renders SlightlySmilingFace", () => {
checkSvg(SlightlySmilingFace);
});
test("renders SmilingFaceWithSmilingEyes", () => {
checkSvg(SmilingFaceWithSmilingEyes);
});
test("renders GrinningFaceWithSmilingEyes", () => {
checkSvg(GrinningFaceWithSmilingEyes);
});
test("renders GrinningSquintingFace", () => {
checkSvg(GrinningSquintingFace);
});
});
@@ -1,462 +0,0 @@
export const TiredFace: React.FC<React.SVGProps<SVGCircleElement>> = (props) => {
return (
<svg viewBox="0 0 72 72" xmlns="http://www.w3.org/2000/svg" width={36} height={36}>
<g id="line">
<circle
cx="36"
cy="36"
r="23"
fill="none"
stroke="currentColor"
strokeMiterlimit="10"
strokeWidth="2"
{...props}
/>
<path
fill="none"
stroke="currentColor"
strokeLinecap="round"
strokeLinejoin="round"
strokeMiterlimit="10"
strokeWidth="2"
d="m21.88 23.92c5.102-0.06134 7.273-1.882 8.383-3.346"
/>
<path
stroke="currentColor"
strokeMiterlimit="10"
strokeWidth="2"
d="m46.24 47.56c0-2.592-2.867-7.121-10.25-6.93-6.974 0.1812-10.22 4.518-10.22 7.111s4.271-1.611 10.05-1.492c6.317 0.13 10.43 3.903 10.43 1.311z"
/>
<path
fill="none"
stroke="currentColor"
strokeLinecap="round"
strokeLinejoin="round"
strokeMiterlimit="10"
strokeWidth="2"
d="m23.16 28.47c5.215 1.438 5.603 0.9096 8.204 1.207 1.068 0.1221-2.03 2.67-7.282 4.397"
/>
<path
fill="none"
stroke="currentColor"
strokeLinecap="round"
strokeLinejoin="round"
strokeMiterlimit="10"
strokeWidth="2"
d="m50.12 23.92c-5.102-0.06134-7.273-1.882-8.383-3.346"
/>
<path
fill="none"
stroke="currentColor"
strokeLinecap="round"
strokeLinejoin="round"
strokeMiterlimit="10"
strokeWidth="2"
d="m48.84 28.47c-5.215 1.438-5.603 0.9096-8.204 1.207-1.068 0.1221 2.03 2.67 7.282 4.397"
/>
</g>
</svg>
);
};
export const WearyFace: React.FC<React.SVGProps<SVGCircleElement>> = (props) => {
return (
<svg viewBox="0 0 72 72" xmlns="http://www.w3.org/2000/svg" width={36} height={36}>
<g id="line">
<circle
cx="36"
cy="36"
r="23"
fill="none"
stroke="currentColor"
strokeMiterlimit="10"
strokeWidth="2"
{...props}
/>
<path
fill="none"
stroke="currentColor"
strokeLinecap="round"
strokeLinejoin="round"
strokeMiterlimit="10"
strokeWidth="2"
d="m22.88 23.92c5.102-0.06134 7.273-1.882 8.383-3.346"
/>
<path
stroke="currentColor"
strokeMiterlimit="10"
strokeWidth="2"
d="m46.24 47.56c0-2.592-2.867-7.121-10.25-6.93-6.974 0.1812-10.22 4.518-10.22 7.111s4.271-1.611 10.05-1.492c6.317 0.13 10.43 3.903 10.43 1.311z"
/>
<path
fill="none"
stroke="currentColor"
strokeLinecap="round"
strokeLinejoin="round"
strokeMiterlimit="10"
strokeWidth="2"
d="m49.12 23.92c-5.102-0.06134-7.273-1.882-8.383-3.346"
/>
<path
fill="none"
stroke="currentColor"
strokeLinecap="round"
strokeLinejoin="round"
strokeMiterlimit="10"
strokeWidth="2"
d="m48.24 30.51c-6.199 1.47-7.079 1.059-8.868-1.961"
/>
<path
fill="none"
stroke="currentColor"
strokeLinecap="round"
strokeLinejoin="round"
strokeMiterlimit="10"
strokeWidth="2"
d="m23.76 30.51c6.199 1.47 7.079 1.059 8.868-1.961"
/>
</g>
</svg>
);
};
export const PerseveringFace: React.FC<React.SVGProps<SVGCircleElement>> = (props) => {
return (
<svg viewBox="0 0 72 72" xmlns="http://www.w3.org/2000/svg" width={36} height={36}>
<g id="line">
<circle
cx="36"
cy="36"
r="23"
fill="none"
stroke="currentColor"
strokeMiterlimit="10"
strokeWidth="2"
{...props}
/>
<line
x1="44.5361"
x2="50.9214"
y1="21.4389"
y2="24.7158"
fill="none"
stroke="currentColor"
strokeLinecap="round"
strokeLinejoin="round"
strokeMiterlimit="10"
strokeWidth="2"
/>
<line
x1="26.9214"
x2="20.5361"
y1="21.4389"
y2="24.7158"
fill="none"
stroke="currentColor"
strokeLinecap="round"
strokeLinejoin="round"
strokeMiterlimit="10"
strokeWidth="2"
/>
<path
fill="none"
stroke="currentColor"
strokeLinecap="round"
strokeLinejoin="round"
strokeMiterlimit="10"
strokeWidth="2"
d="M24,28c2.3334,1.3333,4.6666,2.6667,7,4c-2.3334,1.3333-4.6666,2.6667-7,4"
/>
<path
fill="none"
stroke="currentColor"
strokeLinecap="round"
strokeLinejoin="round"
strokeMiterlimit="10"
strokeWidth="2"
d="M48,28c-2.3334,1.3333-4.6666,2.6667-7,4c2.3334,1.3333,4.6666,2.6667,7,4"
/>
<path
fill="none"
stroke="currentColor"
strokeLinecap="round"
strokeLinejoin="round"
strokeMiterlimit="10"
strokeWidth="2"
d="M28,51c0.2704-0.3562,1-8,8.4211-8.0038C43,42.9929,43.6499,50.5372,44,51C38.6667,51,33.3333,51,28,51z"
/>
</g>
</svg>
);
};
export const FrowningFace: React.FC<React.SVGProps<SVGCircleElement>> = (props) => {
return (
<svg viewBox="0 0 72 72" xmlns="http://www.w3.org/2000/svg" width={36} height={36}>
<g id="line">
<circle
cx="36"
cy="36"
r="23"
fill="none"
stroke="currentColor"
strokeMiterlimit="10"
strokeWidth="2"
{...props}
/>
<path
fill="none"
stroke="currentColor"
strokeLinecap="round"
strokeLinejoin="round"
strokeMiterlimit="10"
strokeWidth="2"
d="M26.5,48c1.8768-3.8326,5.8239-6.1965,10-6c3.8343,0.1804,7.2926,2.4926,9,6"
/>
<path d="M30,31c0,1.6568-1.3448,3-3,3c-1.6553,0-3-1.3433-3-3c0-1.6552,1.3447-3,3-3C28.6552,28,30,29.3448,30,31" />
<path d="M48,31c0,1.6568-1.3447,3-3,3s-3-1.3433-3-3c0-1.6552,1.3447-3,3-3S48,29.3448,48,31" />
</g>
</svg>
);
};
export const ConfusedFace: React.FC<React.SVGProps<SVGCircleElement>> = (props) => {
return (
<svg viewBox="0 0 72 72" xmlns="http://www.w3.org/2000/svg" width={36} height={36}>
<g id="line">
<circle
cx="36"
cy="36"
r="23"
fill="none"
stroke="currentColor"
strokeMiterlimit="10"
strokeWidth="2"
{...props}
/>
<path
fill="none"
stroke="currentColor"
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
d="m44.7 43.92c-6.328-1.736-11.41-0.906-17.4 1.902"
/>
<path d="M30,31c0,1.6568-1.3448,3-3,3c-1.6553,0-3-1.3433-3-3c0-1.6552,1.3447-3,3-3C28.6552,28,30,29.3448,30,31" />
<path d="M48,31c0,1.6568-1.3447,3-3,3s-3-1.3433-3-3c0-1.6552,1.3447-3,3-3S48,29.3448,48,31" />
</g>
</svg>
);
};
export const NeutralFace: React.FC<React.SVGProps<SVGCircleElement>> = (props) => {
return (
<svg viewBox="0 0 72 72" xmlns="http://www.w3.org/2000/svg" width={36} height={36}>
<g id="line">
<circle
cx="36"
cy="36"
r="23"
fill="none"
stroke="currentColor"
strokeMiterlimit="10"
strokeWidth="2"
{...props}
/>
<line
x1="27"
x2="45"
y1="43"
y2="43"
fill="none"
stroke="currentColor"
strokeLinecap="round"
strokeLinejoin="round"
strokeMiterlimit="10"
strokeWidth="2"
/>
<path d="M30,31c0,1.6568-1.3448,3-3,3c-1.6553,0-3-1.3433-3-3c0-1.6552,1.3447-3,3-3C28.6552,28,30,29.3448,30,31" />
<path d="M48,31c0,1.6568-1.3447,3-3,3s-3-1.3433-3-3c0-1.6552,1.3447-3,3-3S48,29.3448,48,31" />
</g>
</svg>
);
};
export const SlightlySmilingFace: React.FC<React.SVGProps<SVGCircleElement>> = (props) => {
return (
<svg viewBox="0 0 72 72" xmlns="http://www.w3.org/2000/svg" width={36} height={36}>
<g id="line">
<circle
cx="36"
cy="36"
r="23"
fill="none"
stroke="currentColor"
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
{...props}
/>
<path
fill="none"
stroke="currentColor"
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
d="M45.8149,44.9293 c-2.8995,1.6362-6.2482,2.5699-9.8149,2.5699s-6.9153-0.9336-9.8149-2.5699"
/>
<path d="M30,31c0,1.6568-1.3448,3-3,3c-1.6553,0-3-1.3433-3-3c0-1.6552,1.3447-3,3-3C28.6552,28,30,29.3448,30,31" />
<path d="M48,31c0,1.6568-1.3447,3-3,3s-3-1.3433-3-3c0-1.6552,1.3447-3,3-3S48,29.3448,48,31" />
</g>
</svg>
);
};
export const SmilingFaceWithSmilingEyes: React.FC<React.SVGProps<SVGCircleElement>> = (props) => {
return (
<svg viewBox="0 0 72 72" xmlns="http://www.w3.org/2000/svg" width={36} height={36}>
<g id="line">
<circle
cx="36"
cy="36"
r="23"
fill="none"
stroke="currentColor"
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
{...props}
/>
<path
fill="none"
stroke="currentColor"
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
d="M45.8147,45.2268a15.4294,15.4294,0,0,1-19.6294,0"
/>
<path
fill="none"
stroke="currentColor"
strokeLinecap="round"
strokeMiterlimit="10"
strokeWidth="2"
d="M31.6941,33.4036a4.7262,4.7262,0,0,0-8.6382,0"
/>
<path
fill="none"
stroke="currentColor"
strokeLinecap="round"
strokeMiterlimit="10"
strokeWidth="2"
d="M48.9441,33.4036a4.7262,4.7262,0,0,0-8.6382,0"
/>
</g>
</svg>
);
};
export const GrinningFaceWithSmilingEyes: React.FC<React.SVGProps<SVGCircleElement>> = (props) => {
return (
<svg viewBox="0 0 72 72" xmlns="http://www.w3.org/2000/svg" width={36} height={36}>
<g id="line">
<circle
cx="36"
cy="36"
r="23"
fill="none"
stroke="currentColor"
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
{...props}
/>
<path
fill="none"
stroke="currentColor"
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
d="M50.595,41.64a11.5554,11.5554,0,0,1-.87,4.49c-12.49,3.03-25.43.34-27.49-.13a11.4347,11.4347,0,0,1-.83-4.36h.11s14.8,3.59,28.89.07Z"
/>
<path
fill="none"
stroke="currentColor"
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
d="M49.7251,46.13c-1.79,4.27-6.35,7.23-13.69,7.23-7.41,0-12.03-3.03-13.8-7.36C24.2951,46.47,37.235,49.16,49.7251,46.13Z"
/>
<path
fill="none"
stroke="currentColor"
strokeLinecap="round"
strokeMiterlimit="10"
strokeWidth="2"
d="M31.6941,32.4036a4.7262,4.7262,0,0,0-8.6382,0"
/>
<path
fill="none"
stroke="currentColor"
strokeLinecap="round"
strokeMiterlimit="10"
strokeWidth="2"
d="M48.9441,32.4036a4.7262,4.7262,0,0,0-8.6382,0"
/>
</g>
</svg>
);
};
export const GrinningSquintingFace: React.FC<React.SVGProps<SVGCircleElement>> = (props) => {
return (
<svg viewBox="0 0 72 72" xmlns="http://www.w3.org/2000/svg" width={36} height={36}>
<g id="line">
<circle
cx="36"
cy="36"
r="23"
fill="none"
stroke="currentColor"
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
{...props}
/>
<polyline
fill="none"
stroke="currentColor"
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
points="25.168 27.413 31.755 31.427 25.168 35.165"
/>
<polyline
fill="none"
stroke="currentColor"
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
points="46.832 27.413 40.245 31.427 46.832 35.165"
/>
<path
fill="none"
stroke="currentColor"
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
d="M50.595,41.64a11.5554,11.5554,0,0,1-.87,4.49c-12.49,3.03-25.43.34-27.49-.13a11.4347,11.4347,0,0,1-.83-4.36h.11s14.8,3.59,28.89.07Z"
/>
<path
fill="none"
stroke="currentColor"
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
d="M49.7251,46.13c-1.79,4.27-6.35,7.23-13.69,7.23-7.41,0-12.03-3.03-13.8-7.36C24.2951,46.47,37.235,49.16,49.7251,46.13Z"
/>
</g>
</svg>
);
};