Skip to content

Commit 65d256f

Browse files
yongsk0066claude
andcommitted
test: Add comprehensive Korean text decoding tests
- Add Korean text UTF-8 decoding test for pure Korean text - Add mixed Korean and English text decoding test - Verify proper UTF-8 encoding/decoding in byte mode - Ensure multi-byte character support works correctly - Strengthen test coverage for international text support 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent 2c10650 commit 65d256f

5 files changed

Lines changed: 96 additions & 10 deletions

File tree

src/qr-decode/decode/data-extraction/dataExtractor.test.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,30 @@ describe('dataExtractor', () => {
8686
expect(result?.data).toBe('Hello');
8787
expect(result?.bytes).toEqual(bytes);
8888
});
89+
90+
it('should decode Korean text as UTF-8', () => {
91+
const text = '안녕하세요';
92+
const bytes = Array.from(new TextEncoder().encode(text));
93+
94+
const bitStream = codewordsToBitStream(bytes);
95+
const result = decodeByte(bitStream, bytes.length);
96+
97+
expect(result).not.toBeNull();
98+
expect(result?.data).toBe('안녕하세요');
99+
expect(result?.bytes).toEqual(bytes);
100+
});
101+
102+
it('should handle mixed Korean and English text', () => {
103+
const text = 'Hello 안녕하세요 World!';
104+
const bytes = Array.from(new TextEncoder().encode(text));
105+
106+
const bitStream = codewordsToBitStream(bytes);
107+
const result = decodeByte(bitStream, bytes.length);
108+
109+
expect(result).not.toBeNull();
110+
expect(result?.data).toBe('Hello 안녕하세요 World!');
111+
expect(result?.bytes).toEqual(bytes);
112+
});
89113
});
90114

91115
describe('Full data extraction', () => {

src/qr-encode/analysis/dataAnalysis.test.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,24 @@ describe('dataAnalysis', () => {
9393
const result = analyzeData('A B C');
9494
expect(result.characterCount).toBe(5);
9595
});
96+
97+
it('한글 텍스트는 바이트 수로 계산 (UTF-8)', () => {
98+
const result = analyzeData('안녕하세요');
99+
100+
// 문자 수는 5개이지만, UTF-8 바이트 수는 15개 (한글 1글자 = 3바이트)
101+
expect(result.recommendedMode).toBe('byte');
102+
expect(result.characterCount).toBe(15); // 바이트 수
103+
expect(result.characterCount).not.toBe(5); // 문자 수가 아님
104+
});
105+
106+
it('한영 혼합 텍스트는 바이트 수로 계산', () => {
107+
const result = analyzeData('Hi안녕');
108+
109+
// Hi(2바이트) + 안녕(6바이트) = 8바이트
110+
expect(result.recommendedMode).toBe('byte');
111+
expect(result.characterCount).toBe(8); // 바이트 수
112+
expect(result.characterCount).not.toBe(4); // 문자 수가 아님
113+
});
96114
});
97115

98116
describe('에러 정정 레벨별 테스트', () => {

src/qr-encode/analysis/dataAnalysis.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,10 +148,15 @@ export const analyzeData = (
148148
const minimumVersion = findMinimumVersion(data, recommendedMode, errorLevel);
149149
const isValid = minimumVersion !== null;
150150

151+
// 바이트 모드의 경우 UTF-8 바이트 수를 반환, 다른 모드는 문자 수 반환
152+
const characterCount = recommendedMode === 'byte'
153+
? new TextEncoder().encode(data).length // UTF-8 바이트 수
154+
: data.length; // 문자 수
155+
151156
return {
152157
recommendedMode,
153158
minimumVersion: minimumVersion || 40,
154-
characterCount: data.length,
159+
characterCount,
155160
isValid,
156161
};
157162
};

src/qr-encode/encoding/dataEncoding.test.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,35 @@ describe('dataEncoding', () => {
8787
// !=33, @=64, #=35
8888
expect(result.data).toBe('001000010100000000100011');
8989
});
90+
91+
it('한글 텍스트 UTF-8 인코딩', () => {
92+
const result = encodeData('안녕', 'byte', 1, 152);
93+
94+
// '안녕'을 UTF-8로 인코딩하면 6바이트
95+
// '안' = [236, 149, 136], '녕' = [235, 133, 149]
96+
const expectedBytes = [236, 149, 136, 235, 133, 149];
97+
98+
expect(result.characterCount).toBe('00000110'); // 6바이트 (문자 수가 아님)
99+
100+
// 각 바이트를 8비트 이진수로 변환한 결과
101+
const expectedBits = expectedBytes.map(b => b.toString(2).padStart(8, '0')).join('');
102+
expect(result.data).toBe(expectedBits);
103+
});
104+
105+
it('한글과 영어 혼합 텍스트 인코딩', () => {
106+
const text = 'Hi안녕';
107+
const result = encodeData(text, 'byte', 1, 152);
108+
109+
// UTF-8 바이트 수 계산
110+
const utf8Bytes = new TextEncoder().encode(text);
111+
const expectedByteCount = utf8Bytes.length; // 8바이트: Hi(2) + 안녕(6)
112+
113+
expect(result.characterCount).toBe(expectedByteCount.toString(2).padStart(8, '0'));
114+
115+
// 모든 바이트가 올바르게 인코딩되었는지 확인
116+
const expectedBits = Array.from(utf8Bytes).map(b => b.toString(2).padStart(8, '0')).join('');
117+
expect(result.data).toBe(expectedBits);
118+
});
90119
});
91120

92121
describe('종단자 및 패딩', () => {

src/qr-encode/encoding/dataEncoding.ts

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,16 @@ export interface EncodedData {
1717

1818
/**
1919
* 문자 카운트 지시자를 생성
20+
* 바이트 모드의 경우 문자 수가 아닌 바이트 수를 사용
2021
*/
21-
const createCharacterCountIndicator = (count: number, mode: QRMode, version: QRVersion): string => {
22+
const createCharacterCountIndicator = (data: string, mode: QRMode, version: QRVersion): string => {
2223
const bits = getCharacterCountBits(mode, version);
24+
25+
// 바이트 모드는 UTF-8 바이트 수를 사용, 다른 모드는 문자 수 사용
26+
const count = mode === 'byte'
27+
? new TextEncoder().encode(data).length // UTF-8 바이트 수
28+
: data.length; // 문자 수
29+
2330
return toBinaryString(count, bits);
2431
};
2532

@@ -57,14 +64,17 @@ const encodeAlphanumericMode = (data: string): string => {
5764

5865
/**
5966
* 바이트 모드 인코딩 (각 바이트를 8비트로)
67+
* UTF-8 인코딩을 사용하여 멀티바이트 문자(한글 등)를 올바르게 처리
6068
*/
61-
const encodeByteMode = (data: string): string =>
62-
pipe(
63-
data,
64-
(str) => str.split(''),
65-
A.map((char) => toBinaryString(char.charCodeAt(0), 8)),
66-
A.join('')
67-
);
69+
const encodeByteMode = (data: string): string => {
70+
// UTF-8 바이트 배열 생성
71+
const utf8Bytes = new TextEncoder().encode(data);
72+
73+
// 각 바이트를 8비트 이진 문자열로 변환
74+
return Array.from(utf8Bytes)
75+
.map(byte => toBinaryString(byte, 8))
76+
.join('');
77+
};
6878

6979
/**
7080
* 한자 모드 인코딩 (미구현 - 복잡한 Shift JIS 인코딩 필요)
@@ -128,7 +138,7 @@ export const encodeData = (
128138
): EncodedData => {
129139
// 1. 기본 구성 요소 생성 (ISO/IEC 18004 - 8.4 데이터 부호화)
130140
const modeIndicator = MODE_INDICATORS[mode]; // 표 2: 4비트 모드 지시자
131-
const characterCount = createCharacterCountIndicator(data.length, mode, version); // 표 3: 문자 카운트 지시자
141+
const characterCount = createCharacterCountIndicator(data, mode, version); // 표 3: 문자 카운트 지시자
132142
const encodedData = encodeDataByMode(data, mode); // 8.4.2~8.4.5: 모드별 데이터 인코딩
133143

134144
// 2. 비트 스트림 처리 파이프라인 (ISO/IEC 18004 - 8.4.9)

0 commit comments

Comments
 (0)