From 0019d02ab94fd53a88b9495912bc7aa4f01b2ef3 Mon Sep 17 00:00:00 2001 From: minsoo kim Date: Wed, 2 Aug 2023 16:17:19 +0900 Subject: [PATCH 1/4] =?UTF-8?q?[=EC=8B=A4=EC=8A=B5]=20=EC=97=B0=EC=8A=B5?= =?UTF-8?q?=EB=AC=B8=EC=A0=9C=20week1/URL/addQuery=20=EC=A0=9C=EC=B6=9C?= =?UTF-8?q?=ED=95=A9=EB=8B=88=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../addQuery/__submit__/minsoo-web.test.ts | 83 +++++++++++++++++++ .../URL/addQuery/__submit__/minsoo-web.ts | 64 ++++++++++++++ 2 files changed, 147 insertions(+) create mode 100644 packages/example/src/1week/URL/addQuery/__submit__/minsoo-web.test.ts create mode 100644 packages/example/src/1week/URL/addQuery/__submit__/minsoo-web.ts diff --git a/packages/example/src/1week/URL/addQuery/__submit__/minsoo-web.test.ts b/packages/example/src/1week/URL/addQuery/__submit__/minsoo-web.test.ts new file mode 100644 index 0000000..fd26184 --- /dev/null +++ b/packages/example/src/1week/URL/addQuery/__submit__/minsoo-web.test.ts @@ -0,0 +1,83 @@ +import { addQuery, replaceKeyValue, splitHashPart } from './minsoo-web' + +describe('splitHashPart', () => { + it('case 1', () => { + expect(splitHashPart('minsoo#foo')).toEqual({ + nonHash: 'minsoo', + hash: '#foo', + }) + }) + + it('case 2', () => { + expect(splitHashPart('http://www.minsoo#foo')).toEqual({ + nonHash: 'http://www.minsoo', + hash: '#foo', + }) + }) + + it('case 3', () => { + expect(splitHashPart('http://www.minsoo')).toEqual({ + nonHash: 'http://www.minsoo', + hash: '', + }) + }) + + it('case 4: 일반적이진 않지만, 의도치 않게 해시가 여러개 들어가있는 경우', () => { + expect(splitHashPart('http://www.minsoo#foo#minsoo')).toEqual({ + nonHash: 'http://www.minsoo', + hash: '#foo#minsoo', + }) + }) +}) + +describe('replaceKeyValue', () => { + it('case 1', () => { + expect(replaceKeyValue('minsoo?key=foo', 'key', 'bar')).toBe( + 'minsoo?key=bar', + ) + }) + + it('case 2', () => { + expect(replaceKeyValue('minsoo?foo=foo', 'key', 'bar')).toBe( + 'minsoo?foo=foo', + ) + }) +}) + +describe('addQuery', () => { + test('case 0: URL 형식이 굳이 아니여도 동작', () => { + expect(addQuery('www.linkedin.com/?name=elon#top', 'name', 'musk')).toBe( + 'www.linkedin.com/?name=musk#top', + ) + }) + + test('case 1', () => { + expect(addQuery('https://www.linkedin.com/', 'key', 'value')).toBe( + 'https://www.linkedin.com/?key=value', + ) + }) + + test('case 2: 기존 URL에 이미 쿼리가 있는 경우', () => { + expect( + addQuery('https://www.linkedin.com/?name=elon', 'key', 'value'), + ).toBe('https://www.linkedin.com/?name=elon&key=value') + }) + + test('case 3: 기존 URL에 hash가 있는 경우', () => { + expect( + addQuery('https://www.linkedin.com/?name=elon#top', 'key', 'value'), + ).toBe('https://www.linkedin.com/?name=elon&key=value#top') + }) + + test('case 4: 기존 쿼리와 추가하려는 쿼리의 key가 동일한 경우', () => { + const URL = 'https://www.linkedin.com/?name=elon#top' + + expect(addQuery(URL, 'name', 'musk')).toBe( + 'https://www.linkedin.com/?name=musk#top', + ) + + expect(addQuery(URL, 'name', 'musk')).toBe( + 'https://www.linkedin.com/?name=musk#top', + ) + }) +}) diff --git a/packages/example/src/1week/URL/addQuery/__submit__/minsoo-web.ts b/packages/example/src/1week/URL/addQuery/__submit__/minsoo-web.ts new file mode 100644 index 0000000..d31cacd --- /dev/null +++ b/packages/example/src/1week/URL/addQuery/__submit__/minsoo-web.ts @@ -0,0 +1,64 @@ +const hasIncludes = (url: string, value: string): boolean => url.includes(value) + +export const splitHashPart = ( + text: string, +): { nonHash: string; hash: string } => { + const indexOfHash = text.indexOf('#') + + if (indexOfHash >= 0) { + return { + nonHash: text.slice(0, indexOfHash), + hash: text.slice(indexOfHash), + } + } + + return { + nonHash: text, + hash: '', + } +} + +export const replaceKeyValue = ( + url: string, + key: string, + newValue: string | number, +) => { + const regExp = new RegExp(`${key}=([^&]*)`, 'i') + if (url.match(regExp)) { + return url.replace(regExp, `${key}=${newValue}`) + } + + return url +} + +/** + * 출제자: 예진님 (yejineee) + * URL의 쿼리스트링 관련 유틸 함수를 계산 을 최대한 이용하여 만들기 + * + * - 해쉬가 있다면, 유지해야 함 + * - 기존 쿼리가 있다면, 유지해야 함 + * - 기존 쿼리와 추가하려는 쿼리의 key가 동일하다면, 기존 쿼리가 대체됨 + */ + +export const addQuery = ( + originURL: string, + key: string, + value: string | number, +) => { + const { nonHash, hash } = splitHashPart(originURL) + + let returnUrl = nonHash + let connector = '?' + + if (hasIncludes(originURL, '?')) { + connector = '&' + } + + returnUrl += `${connector}${key}=${value}` + + if (hasIncludes(originURL, `?${key}`)) { + returnUrl = replaceKeyValue(nonHash, key, value) + } + + return returnUrl + hash +} From 361e50b7eae01fc86d315387a50ea36778b29dbe Mon Sep 17 00:00:00 2001 From: minsoo kim Date: Wed, 2 Aug 2023 16:24:04 +0900 Subject: [PATCH 2/4] =?UTF-8?q?feat:=20hasIncludes=20=EA=B0=9C=EC=84=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/1week/URL/addQuery/__submit__/minsoo-web.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/packages/example/src/1week/URL/addQuery/__submit__/minsoo-web.ts b/packages/example/src/1week/URL/addQuery/__submit__/minsoo-web.ts index d31cacd..183a12c 100644 --- a/packages/example/src/1week/URL/addQuery/__submit__/minsoo-web.ts +++ b/packages/example/src/1week/URL/addQuery/__submit__/minsoo-web.ts @@ -1,4 +1,5 @@ -const hasIncludes = (url: string, value: string): boolean => url.includes(value) +const hasIncludes = (url: string, value: string): 'YES' | 'NO' => + url.includes(value) ? 'YES' : 'NO' export const splitHashPart = ( text: string, @@ -50,13 +51,13 @@ export const addQuery = ( let returnUrl = nonHash let connector = '?' - if (hasIncludes(originURL, '?')) { + if (hasIncludes(originURL, '?') === 'YES') { connector = '&' } returnUrl += `${connector}${key}=${value}` - if (hasIncludes(originURL, `?${key}`)) { + if (hasIncludes(originURL, `?${key}`) === 'YES') { returnUrl = replaceKeyValue(nonHash, key, value) } From fe7ec2e29c36ccc5d4cc0de18eb8f2b50c1e5d35 Mon Sep 17 00:00:00 2001 From: minsoo kim Date: Wed, 2 Aug 2023 16:27:28 +0900 Subject: [PATCH 3/4] =?UTF-8?q?feat:=20=EC=BF=BC=EB=A6=AC=EA=B0=80=20?= =?UTF-8?q?=EC=97=AC=EB=9F=AC=20=EA=B0=9C=EC=9D=BC=20=EA=B2=BD=EC=9A=B0=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../URL/addQuery/__submit__/minsoo-web.test.ts | 18 ++++++++++++++++++ .../URL/addQuery/__submit__/minsoo-web.ts | 2 +- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/packages/example/src/1week/URL/addQuery/__submit__/minsoo-web.test.ts b/packages/example/src/1week/URL/addQuery/__submit__/minsoo-web.test.ts index fd26184..dc70c1d 100644 --- a/packages/example/src/1week/URL/addQuery/__submit__/minsoo-web.test.ts +++ b/packages/example/src/1week/URL/addQuery/__submit__/minsoo-web.test.ts @@ -42,6 +42,12 @@ describe('replaceKeyValue', () => { 'minsoo?foo=foo', ) }) + + it('case 3', () => { + expect(replaceKeyValue('minsoo?key=foo&key=baz', 'key', 'bar')).toBe( + 'minsoo?key=bar&key=bar', + ) + }) }) describe('addQuery', () => { @@ -80,4 +86,16 @@ describe('addQuery', () => { 'https://www.linkedin.com/?name=musk#top', ) }) + + test('case 5: 기존 쿼리와 추가하려는 쿼리의 key가 동일한 경우', () => { + const URL = 'https://www.linkedin.com/?name=elon&name=minsoo#top' + + expect(addQuery(URL, 'name', 'musk')).toBe( + 'https://www.linkedin.com/?name=musk&name=musk#top', + ) + + expect(addQuery(URL, 'name', 'musk')).toBe( + 'https://www.linkedin.com/?name=musk&name=musk#top', + ) + }) }) diff --git a/packages/example/src/1week/URL/addQuery/__submit__/minsoo-web.ts b/packages/example/src/1week/URL/addQuery/__submit__/minsoo-web.ts index 183a12c..47d5e68 100644 --- a/packages/example/src/1week/URL/addQuery/__submit__/minsoo-web.ts +++ b/packages/example/src/1week/URL/addQuery/__submit__/minsoo-web.ts @@ -24,7 +24,7 @@ export const replaceKeyValue = ( key: string, newValue: string | number, ) => { - const regExp = new RegExp(`${key}=([^&]*)`, 'i') + const regExp = new RegExp(`${key}=([^&]*)`, 'g') if (url.match(regExp)) { return url.replace(regExp, `${key}=${newValue}`) } From 647b616edd01c3590bd5e8c7ce5b47dcc57d248c Mon Sep 17 00:00:00 2001 From: minsoo kim Date: Fri, 4 Aug 2023 07:01:35 +0900 Subject: [PATCH 4/4] review: change prefix split -> get --- .../1week/URL/addQuery/__submit__/minsoo-web.test.ts | 12 ++++++------ .../src/1week/URL/addQuery/__submit__/minsoo-web.ts | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/example/src/1week/URL/addQuery/__submit__/minsoo-web.test.ts b/packages/example/src/1week/URL/addQuery/__submit__/minsoo-web.test.ts index dc70c1d..e2624e9 100644 --- a/packages/example/src/1week/URL/addQuery/__submit__/minsoo-web.test.ts +++ b/packages/example/src/1week/URL/addQuery/__submit__/minsoo-web.test.ts @@ -1,29 +1,29 @@ -import { addQuery, replaceKeyValue, splitHashPart } from './minsoo-web' +import { addQuery, getHashPart, replaceKeyValue } from './minsoo-web' -describe('splitHashPart', () => { +describe('getHashPart', () => { it('case 1', () => { - expect(splitHashPart('minsoo#foo')).toEqual({ + expect(getHashPart('minsoo#foo')).toEqual({ nonHash: 'minsoo', hash: '#foo', }) }) it('case 2', () => { - expect(splitHashPart('http://www.minsoo#foo')).toEqual({ + expect(getHashPart('http://www.minsoo#foo')).toEqual({ nonHash: 'http://www.minsoo', hash: '#foo', }) }) it('case 3', () => { - expect(splitHashPart('http://www.minsoo')).toEqual({ + expect(getHashPart('http://www.minsoo')).toEqual({ nonHash: 'http://www.minsoo', hash: '', }) }) it('case 4: 일반적이진 않지만, 의도치 않게 해시가 여러개 들어가있는 경우', () => { - expect(splitHashPart('http://www.minsoo#foo#minsoo')).toEqual({ + expect(getHashPart('http://www.minsoo#foo#minsoo')).toEqual({ nonHash: 'http://www.minsoo', hash: '#foo#minsoo', }) diff --git a/packages/example/src/1week/URL/addQuery/__submit__/minsoo-web.ts b/packages/example/src/1week/URL/addQuery/__submit__/minsoo-web.ts index 47d5e68..46a6496 100644 --- a/packages/example/src/1week/URL/addQuery/__submit__/minsoo-web.ts +++ b/packages/example/src/1week/URL/addQuery/__submit__/minsoo-web.ts @@ -1,7 +1,7 @@ const hasIncludes = (url: string, value: string): 'YES' | 'NO' => url.includes(value) ? 'YES' : 'NO' -export const splitHashPart = ( +export const getHashPart = ( text: string, ): { nonHash: string; hash: string } => { const indexOfHash = text.indexOf('#') @@ -46,7 +46,7 @@ export const addQuery = ( key: string, value: string | number, ) => { - const { nonHash, hash } = splitHashPart(originURL) + const { nonHash, hash } = getHashPart(originURL) let returnUrl = nonHash let connector = '?'