Skip to content

Commit 78a4569

Browse files
authored
Merge pull request #423 from LetsGetTechnical/develop
Release 5/19/25
2 parents 21b16e2 + 5c8be6f commit 78a4569

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

50 files changed

+1362
-281
lines changed

.eslintignore

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
**/*.test.tsx
55
**/*.test.js
66
**/*.test.jsx
7-
app/api/gift-exchanges/route.ts
87
app/api/gift-exchanges/\[id\]/draw/route.ts
98
app/api/gift-exchanges/\[id\]/giftSuggestions/route.ts
109
app/api/gift-exchanges/\[id\]/members/route.ts
@@ -37,9 +36,7 @@ components/Avatar/AvatarBody.tsx
3736
components/Button/button.tsx
3837
components/Calendar/calendar.tsx
3938
components/GiftDetailsView/GiftDetailsView.tsx
40-
components/GiftExchangeHeader/GiftExchangeHeader.tsx
4139
components/GiftSuggestionCard/GiftSuggestionCard.tsx
42-
components/GlobalGiftSpinner/GlobalGiftSpinner.tsx
4340
components/GlobalHeader/GlobalHeader.tsx
4441
components/GroupCard/GroupCard.tsx
4542
components/ImageSelector/ImageSelector.tsx
@@ -61,11 +58,9 @@ components/SnowOverlayToggle/SnowOverlayToggle.tsx
6158
components/SnowOverlayWrapper/react-snow-overlay.d.ts
6259
lib/drawGiftExchange.ts
6360
lib/generateAndStoreSuggestion.ts
64-
lib/generateAndUpdateNewGiftSuggestion.ts
6561
lib/getAmazonImage.ts
6662
lib/getUserAvatar.ts
6763
lib/getUserAvatar.ts
68-
lib/supabase/client.ts
6964
lib/supabase/middleware.ts
7065
lib/supabase/server.ts
7166
lib/utils.ts

CODEOWNERS

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
# Code Owners File
22

33
# All files are owned by the entire team
4-
* @kepsteen @alexappleget @jennifertieu @HoldUpFjord @shashilo
4+
* @kepsteen @alexappleget @jennifertieu @HoldUpFjord @shashilo @nickytonline @bethanyann
5+

app/api/gift-exchanges/route.ts

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,16 @@
1+
// Copyright (c) Gridiron Survivor.
2+
// Licensed under the MIT License.
3+
14
import { createClient } from '@/lib/supabase/server';
25
import { NextResponse } from 'next/server';
36
import { CreateGiftExchangeRequest } from '@/app/types/giftExchange';
47
import { validateGroupExchangeDates } from '@/lib/utils';
58

6-
// Get all gift exchanges for the current user
7-
export async function GET() {
9+
/**
10+
* Get all gift exchanges for the current user
11+
* @returns {Promise<NextResponse>} Promise that resolved to a Response object
12+
*/
13+
export async function GET(): Promise<NextResponse> {
814
try {
915
const supabase = await createClient();
1016
const {
@@ -24,7 +30,7 @@ export async function GET() {
2430
}
2531
return NextResponse.json(data);
2632
} catch (error) {
27-
console.log(error);
33+
console.error(error);
2834

2935
return NextResponse.json(
3036
{ error: 'Internal server error' },
@@ -33,7 +39,12 @@ export async function GET() {
3339
}
3440
}
3541

36-
export async function POST(req: Request) {
42+
/**
43+
* Create a new gift exchange
44+
* @param {Request} req The request object
45+
* @returns {Promise<NextResponse>} Promise that resolved to a Response object
46+
*/
47+
export async function POST(req: Request): Promise<NextResponse> {
3748
try {
3849
const supabase = await createClient();
3950
const {
@@ -77,7 +88,7 @@ export async function POST(req: Request) {
7788

7889
return NextResponse.json(data);
7990
} catch (error) {
80-
console.log(error);
91+
console.error(error);
8192

8293
return NextResponse.json(
8394
{ error: 'Internal server error' },
@@ -86,7 +97,12 @@ export async function POST(req: Request) {
8697
}
8798
}
8899

89-
export async function PATCH(req: Request) {
100+
/**
101+
* Update a gift exchange
102+
* @param {Request} req The request object
103+
* @returns {Promise<NextResponse>} Promise that resolved to a Response object
104+
*/
105+
export async function PATCH(req: Request): Promise<NextResponse> {
90106
try {
91107
const supabase = await createClient();
92108
const {
@@ -132,7 +148,8 @@ export async function PATCH(req: Request) {
132148

133149
return NextResponse.json(data);
134150
} catch (error) {
135-
console.log(error);
151+
console.error(error);
152+
136153
return NextResponse.json(
137154
{ error: 'Internal server error' },
138155
{ status: 500 },

app/onboarding/page.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ import {
3131
SelectItem,
3232
SelectTrigger,
3333
SelectValue,
34-
} from '@/components/Select/select';
34+
} from '@/components/Select';
3535
import { MultiSelect } from '@/components/MultiSelect/multi-select-input';
3636
import { Textarea } from '@/components/TextArea/textarea';
3737
import { Slider } from '@/components/Slider/slider';

components/Avatar/Avatar.tsx

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,19 @@
44
import { JSX } from 'react';
55

66
import { AvatarImage } from './AvatarImage';
7-
import { AvatarFallback } from './AvatarFallback';
8-
import { AvatarBody } from './AvatarBody';
7+
import { AvatarFallback } from './AvatarFallback/AvatarFallback';
8+
import { AvatarBody } from './AvatarBody/AvatarBody';
99

1010
/**
1111
* An Avatar component that displays a provided image URL or a default image if not provided.
1212
* @param {string} userAvatar - URL string for the avatar image. If undefined, the AvatarFallback img will be used.
1313
* @returns {JSX.Element} - The rendered Avatar element.
1414
*/
15-
const Avatar = ({ userAvatar }: { userAvatar: string | undefined }) : JSX.Element => {
15+
const Avatar = ({
16+
userAvatar,
17+
}: {
18+
userAvatar: string | undefined;
19+
}): JSX.Element => {
1620
return (
1721
<AvatarBody>
1822
<AvatarImage src={userAvatar} alt="" />
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
// Copyright (c) Gridiron Survivor.
2+
// Licensed under the MIT License.
3+
4+
import { AvatarBody } from './AvatarBody';
5+
import { render, screen } from '@testing-library/react';
6+
7+
describe('AvatarBody Component', () => {
8+
it('renders correctly with passed children', () => {
9+
render(
10+
<AvatarBody>
11+
<div>Test child</div>
12+
</AvatarBody>,
13+
);
14+
15+
const avatarBodyElement = screen.getByTestId('avatar-body');
16+
const testChild = screen.getByText('Test child');
17+
18+
expect(avatarBodyElement).toBeInTheDocument();
19+
expect(testChild).toBeInTheDocument();
20+
});
21+
22+
it('renders the component with custom classes', () => {
23+
render(
24+
<AvatarBody className="custom-class">
25+
<div>Test child</div>
26+
</AvatarBody>,
27+
);
28+
29+
const avatarBodyElement = screen.getByTestId('avatar-body');
30+
31+
expect(avatarBodyElement).toHaveClass('custom-class');
32+
});
33+
34+
it('renders correctly with no children', () => {
35+
render(<AvatarBody />);
36+
37+
const avatarBodyElement = screen.getByTestId('avatar-body');
38+
39+
expect(avatarBodyElement).toBeEmptyDOMElement();
40+
});
41+
42+
it('renders with custom attributes', () => {
43+
render(<AvatarBody data-custom-prop="customProp" />);
44+
45+
const avatarBodyElement = screen.getByTestId('avatar-body');
46+
47+
expect(avatarBodyElement).toHaveAttribute('data-custom-prop', 'customProp');
48+
});
49+
});

components/Avatar/AvatarBody.tsx renamed to components/Avatar/AvatarBody/AvatarBody.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ const AvatarBody = forwardRef<
2323
'relative flex h-10 w-10 shrink-0 overflow-hidden rounded-full',
2424
className,
2525
)}
26+
data-testid="avatar-body"
2627
{...props}
2728
/>
2829
));
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
// Copyright (c) Gridiron Survivor.
2+
// Licensed under the MIT License.
3+
4+
import { AvatarFallback } from './AvatarFallback';
5+
import { Root as AvatarPrimitiveRoot } from '@radix-ui/react-avatar';
6+
import { render, screen } from '@testing-library/react';
7+
8+
describe('AvatarFallback Component', () => {
9+
it('renders the component with image as child', () => {
10+
render(
11+
<AvatarPrimitiveRoot>
12+
<AvatarFallback>
13+
<img
14+
src="fallback-image.jpg"
15+
alt="default avatar"
16+
data-testid="fallback-image"
17+
/>
18+
</AvatarFallback>
19+
</AvatarPrimitiveRoot>,
20+
);
21+
22+
const avatarFallbackElement = screen.getByTestId('avatar-fallback');
23+
const imgElement = screen.getByTestId('fallback-image');
24+
25+
expect(avatarFallbackElement).toBeInTheDocument();
26+
expect(imgElement).toBeInTheDocument();
27+
});
28+
29+
it('renders the component with custom classes', () => {
30+
render(
31+
<AvatarPrimitiveRoot>
32+
<AvatarFallback className="custom-class">
33+
<img src="fallback-image.jpg" alt="default avatar" />
34+
</AvatarFallback>
35+
</AvatarPrimitiveRoot>,
36+
);
37+
38+
const avatarFallbackElement = screen.getByTestId('avatar-fallback');
39+
40+
expect(avatarFallbackElement).toHaveClass('custom-class');
41+
});
42+
43+
it('renders the component with no children', () => {
44+
render(
45+
<AvatarPrimitiveRoot>
46+
<AvatarFallback />
47+
</AvatarPrimitiveRoot>,
48+
);
49+
50+
const avatarFallbackElement = screen.getByTestId('avatar-fallback');
51+
52+
expect(avatarFallbackElement).toBeEmptyDOMElement();
53+
});
54+
});

components/Avatar/AvatarFallback.tsx renamed to components/Avatar/AvatarFallback/AvatarFallback.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ const AvatarFallback = forwardRef<
2323
'flex h-full w-full items-center justify-center rounded-full bg-muted',
2424
className,
2525
)}
26+
data-testid="avatar-fallback"
2627
{...props}
2728
/>
2829
));

components/Badge/Badge.test.tsx

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
// Copyright (c) Gridiron Survivor.
2+
// Licensed under the MIT License.
3+
4+
import { Badge, BadgeProps, badgeVariants } from './Badge';
5+
import { render, screen } from '@testing-library/react';
6+
import { variants } from './Badge';
7+
8+
const variantNames = Object.keys(variants.variant) as NonNullable<
9+
BadgeProps['variant']
10+
>[];
11+
12+
describe('Badge', () => {
13+
it('renders the component with default variant', () => {
14+
render(<Badge />);
15+
16+
const badge = screen.getByTestId('badge');
17+
18+
expect(badge).toBeInTheDocument();
19+
20+
const classNames = badgeVariants({ variant: 'default' });
21+
expect(badge).toHaveClass(classNames);
22+
});
23+
24+
for (let i = 0; i < variantNames.length; i++) {
25+
const variant = variantNames[i];
26+
it(`renders with the "${variant}" variant and applies correct styles`, () => {
27+
render(<Badge variant={variant} />);
28+
29+
const badge = screen.getByTestId('badge');
30+
31+
const classNames = badgeVariants({ variant });
32+
expect(badge).toHaveClass(classNames);
33+
});
34+
}
35+
36+
it('renders the provided children inside the badge', () => {
37+
render(<Badge>children</Badge>);
38+
39+
const badge = screen.getByTestId('badge');
40+
41+
expect(badge).toHaveTextContent('children');
42+
});
43+
44+
it('renders with custom className alongside variant styles', () => {
45+
render(<Badge className="custom-class" />);
46+
47+
const badge = screen.getByTestId('badge');
48+
49+
const classNames = badgeVariants({ variant: 'default' });
50+
expect(badge).toHaveClass(classNames);
51+
expect(badge).toHaveClass('custom-class');
52+
});
53+
54+
it('renders with aria-label attribute', () => {
55+
render(<Badge aria-label="test" />);
56+
57+
const badge = screen.getByTestId('badge');
58+
59+
expect(badge).toHaveAttribute('aria-label', 'test');
60+
});
61+
});

0 commit comments

Comments
 (0)