Skip to content

Commit 7f8dd8b

Browse files
authored
Merge pull request #122 from imaginer-dev/121----strategy-pattern
121 strategy pattern
2 parents 9767313 + 1bd266b commit 7f8dd8b

File tree

8 files changed

+6896
-8191
lines changed

8 files changed

+6896
-8191
lines changed

โ€Ždocs/design/jalee_validation_design_point.mdโ€Ž

Whitespace-only changes.

โ€Ždocs/design/validation_design_point.mdโ€Ž

Whitespace-only changes.

โ€Žpnpm-lock.yamlโ€Ž

Lines changed: 6834 additions & 8170 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

โ€Žsrc/components/login/EmailInput.tsxโ€Ž

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
import InputForm from '../common/InputForm.tsx';
22
import { useLoginState } from '../../stores/loginStore.ts';
3-
import { isValidEmail } from '../../utils/authUtils.ts';
3+
import { LooseValidation, ValidateProcessor } from '@/utils/authUtils.ts';
44

55
const EmailInput = () => {
66
const { email, emailHandler } = useLoginState();
7+
const validator = new ValidateProcessor(new LooseValidation());
78

89
return (
910
<InputForm
@@ -16,7 +17,7 @@ const EmailInput = () => {
1617
name={'email'}
1718
id={'email-input'}
1819
aria-label={'login-email-input'}
19-
error={!isValidEmail(email)}
20+
error={!validator.isValidEmail(email)}
2021
errorText={'์˜ฌ๋ฐ”๋ฅธ ์ด๋ฉ”์ผ์„ ์ž…๋ ฅํ•ด ์ฃผ์„ธ์š”.'}
2122
/>
2223
);

โ€Žsrc/components/login/LoginButton.tsxโ€Ž

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { useLoginState } from '@/stores/loginStore.ts';
2-
import { isValidEmail, isValidPassword } from '@/utils/authUtils.ts';
2+
import { LooseValidation, ValidateProcessor } from '@/utils/authUtils.ts';
33
import { useRef, useState } from 'react';
44
import useSignIn from '../../react-queries/useSignIn.ts';
55
import { isAuthError } from '@supabase/supabase-js';
@@ -14,7 +14,7 @@ interface DialogElement {
1414

1515
const messages = {
1616
ISVAILD_ERROR: '์ด๋ฉ”์ผ ๋˜๋Š” ๋น„๋ฐ€๋ฒˆํ˜ธ ํ˜•์‹์ด ์ž˜๋ชป๋˜์—ˆ์Šต๋‹ˆ๋‹ค.',
17-
AUTH_ERROR: '์ด๋ฉ”์ผ ๋˜๋Š” ๋น„๋ฐ€๋ฒˆํ˜ธ๊ฐ€ ์ •ํ™•ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.',
17+
AUTH_ERROR: '์ธ์ฆ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค. ๋‹ค์‹œ ์‹œ๋„ํ•ด์ฃผ์„ธ์š”.',
1818
};
1919

2020
const LoginButton = () => {
@@ -24,8 +24,10 @@ const LoginButton = () => {
2424
const dialogRef = useRef<DialogElement | null>(null);
2525
const [dialogMessage, setDialogMessage] = useState('');
2626

27+
const validator = new ValidateProcessor(new LooseValidation());
28+
2729
const onClick = () => {
28-
if (!isValidEmail(email) || !isValidPassword(password)) {
30+
if (!validator.isValidEmail(email) || !validator.isValidPassword(password)) {
2931
setDialogMessage(messages.ISVAILD_ERROR);
3032
dialogRef.current?.openModal();
3133
return;

โ€Žsrc/components/login/PasswordInput.tsxโ€Ž

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
import InputForm from '../common/InputForm.tsx';
22
import { useLoginState } from '../../stores/loginStore.ts';
3-
import { isValidPassword } from '../../utils/authUtils.ts';
3+
import { LooseValidation, ValidateProcessor } from '@/utils/authUtils.ts';
44

55
const PasswordInput = () => {
66
const { password, passwordHandler } = useLoginState();
77

8+
const validator = new ValidateProcessor(new LooseValidation());
9+
810
return (
911
<InputForm
1012
defaultValue={password}
@@ -16,7 +18,7 @@ const PasswordInput = () => {
1618
type={'password'}
1719
id={'password-input'}
1820
aria-label={'login-password-input'}
19-
error={!isValidPassword(password)}
21+
error={!validator.isValidPassword(password)}
2022
errorText={'๋น„๋ฐ€๋ฒˆํ˜ธ๋Š” 6์ž๋ฆฌ ์ด์ƒ์ด์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.'}
2123
/>
2224
);
Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,21 @@
11
import { describe, expect, it } from 'vitest';
2-
import { isValidEmail, isValidPassword } from '../authUtils.ts';
2+
import { LooseValidation, ValidateProcessor } from '@/utils/authUtils.ts';
3+
4+
const validator = new ValidateProcessor(new LooseValidation());
35

46
describe('์ด๋ฉ”์ผ ๊ฒ€์ฆ ์œ ํ‹ธ๋ฆฌํ‹ฐ ํ•จ์ˆ˜ ํ…Œ์ŠคํŠธ', () => {
57
it('์ด๋ฉ”์ผ์ด ์œ ํšจํ•  ๊ฒฝ์šฐ true ๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.', () => {
6-
expect(isValidEmail('[email protected]')).toBe(true);
7-
expect(isValidEmail('[email protected]')).toBe(true);
8+
expect(validator.isValidEmail('[email protected]')).toBe(true);
9+
expect(validator.isValidEmail('[email protected]')).toBe(true);
810
});
911
it('์ด๋ฉ”์ผ์ด ์œ ์š”ํ•˜์ง€ ์•Š์„ ๊ฒฝ์šฐ false ๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.', () => {
10-
expect(isValidEmail('test.com')).toBe(false);
11-
expect(isValidEmail('test@test')).toBe(false);
12+
expect(validator.isValidEmail('test.com')).toBe(false);
13+
expect(validator.isValidEmail('test@test')).toBe(false);
1214
});
1315
});
1416

1517
describe('๋น„๋ฐ€๋ฒˆํ˜ธ ๊ฒ€์ฆ ์œ ํ‹ธ๋ฆฌํ‹ฐ ํ•จ์ˆ˜ ํ…Œ์ŠคํŠธ', () => {
1618
it('๋น„๋ฐ€๋ฒˆํ˜ธ๊ฐ€ 6์ž๋ฆฌ ์ด์ƒ์ด ์•„๋‹ ๊ฒฝ์šฐ false ๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.', () => {
17-
expect(isValidPassword('some')).toBe(false);
19+
expect(validator.isValidPassword('some')).toBe(false);
1820
});
1921
});

โ€Žsrc/utils/authUtils.tsโ€Ž

Lines changed: 42 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,42 @@
1-
export const isValidEmail = (email: string): boolean => {
2-
const regex = /^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,6}$/;
3-
return regex.test(email);
4-
};
5-
6-
export const isValidPassword = (password: string) => {
7-
return password.length >= 6;
8-
};
1+
export interface ValidationStrategy {
2+
emailValidate(input: string): boolean;
3+
passwordValidate(input: string): boolean;
4+
}
5+
6+
export class LooseValidation implements ValidationStrategy {
7+
emailValidate(email: string): boolean {
8+
return /^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,6}$/.test(email);
9+
}
10+
passwordValidate(input: string): boolean {
11+
return input.length >= 6;
12+
}
13+
}
14+
15+
export class StrongValidation implements ValidationStrategy {
16+
emailValidate(password: string): boolean {
17+
return password.length >= 6;
18+
}
19+
passwordValidate(input: string): boolean {
20+
const regex = /^(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[a-zA-Z]).{8,}$/;
21+
return regex.test(input);
22+
}
23+
}
24+
25+
export class ValidateProcessor {
26+
#validator: ValidationStrategy;
27+
constructor(validator: ValidationStrategy) {
28+
this.#validator = validator;
29+
}
30+
31+
setValidator(validator: ValidationStrategy) {
32+
this.#validator = validator;
33+
}
34+
35+
isValidEmail(email: string) {
36+
return this.#validator.emailValidate(email);
37+
}
38+
39+
isValidPassword(password: string) {
40+
return this.#validator.passwordValidate(password);
41+
}
42+
}

0 commit comments

Comments
ย (0)