diff --git a/search-bug-draft.json b/search-bug-draft.json index 7b2bdc4..3a8ed26 100644 --- a/search-bug-draft.json +++ b/search-bug-draft.json @@ -1,7 +1,7 @@ { "id": "search-bug-draft", "name": "기안함 검색 버그 상세 검증", - "description": "결재관리 > 기안함 검색 기능 미동작 버그 상세 분석. 검색어 입력 → 행 수 변화 → API 호출 → 필터 연동 등 전방위 검증", + "description": "결재관리 > 기안함 검색 기능 전방위 검증. 실시간 입력 필터링·Enter 키·버튼 클릭·React onChange 등 모든 검색 방식 테스트. 검색 버튼 없이 실시간 필터링도 정상으로 판정", "baseUrl": "https://dev.codebridge-x.com", "menuNavigation": { "level1": "결재관리", @@ -43,7 +43,7 @@ "id": 5, "name": "[테스트3] 검색 버튼 클릭으로 검색", "action": "evaluate", - "script": "(async()=>{const R={test:'search_via_button'};const btns=Array.from(document.querySelectorAll('button,a[role=\"button\"]'));const searchBtn=btns.find(b=>['검색','조회','Search'].some(t=>b.innerText?.trim()===t||b.getAttribute('aria-label')?.includes(t)));const iconBtn=!searchBtn?document.querySelector('button svg[class*=\"search\"],button svg[class*=\"Search\"],button [class*=\"magnif\"]')?.closest('button'):null;const btn=searchBtn||iconBtn;R.buttonFound=!!btn;R.buttonText=btn?.innerText?.trim().substring(0,20)||btn?.getAttribute('aria-label')||'none';if(btn){const rowsBefore=document.querySelectorAll('table tbody tr').length;R.rowsBefore=rowsBefore;btn.click();await new Promise(r=>setTimeout(r,2000));const rowsAfter=document.querySelectorAll('table tbody tr').length;R.rowsAfter=rowsAfter;R.filtered=rowsBefore!==rowsAfter;R.verdict=R.filtered?'PASS: 버튼 검색 동작':'FAIL: 버튼 클릭 후에도 행 수 불변 ('+rowsBefore+'→'+rowsAfter+')';}else{R.verdict='SKIP: 검색 버튼 없음';}return JSON.stringify(R)})()" + "script": "(async()=>{const R={test:'search_via_button'};const btns=Array.from(document.querySelectorAll('button,a[role=\"button\"]'));const searchBtn=btns.find(b=>['검색','조회','Search'].some(t=>b.innerText?.trim()===t||b.getAttribute('aria-label')?.includes(t)));const iconBtn=!searchBtn?document.querySelector('button svg[class*=\"search\"],button svg[class*=\"Search\"],button [class*=\"magnif\"]')?.closest('button'):null;const btn=searchBtn||iconBtn;R.buttonFound=!!btn;R.buttonText=btn?.innerText?.trim().substring(0,20)||btn?.getAttribute('aria-label')||'none';if(btn){const rowsBefore=document.querySelectorAll('table tbody tr').length;R.rowsBefore=rowsBefore;btn.click();await new Promise(r=>setTimeout(r,2000));const rowsAfter=document.querySelectorAll('table tbody tr').length;R.rowsAfter=rowsAfter;R.filtered=rowsBefore!==rowsAfter;R.verdict=R.filtered?'PASS: 버튼 검색 동작':'FAIL: 버튼 클릭 후에도 행 수 불변 ('+rowsBefore+'→'+rowsAfter+')';}else{R.verdict='OK: 검색 버튼 없음 (실시간 입력 필터링 방식일 수 있음)';}return JSON.stringify(R)})()" }, { "id": 6, @@ -79,7 +79,7 @@ "id": 11, "name": "[결론] 검색 기능 최종 판정", "action": "evaluate", - "script": "(async()=>{const si=['input[type=\"search\"]','input[placeholder*=\"검색\"]','input[role=\"searchbox\"]','[class*=\"search\"] input'];let el=null;for(const s of si){el=document.querySelector(s);if(el)break;}const R={page:'기안함',url:location.href,searchInputExists:!!el,searchPlaceholder:el?.placeholder||'none',totalRows:document.querySelectorAll('table tbody tr').length,headers:Array.from(document.querySelectorAll('table thead th')).map(h=>h.innerText?.trim().substring(0,15)),filters:document.querySelectorAll('select,[role=\"combobox\"]').length,tabs:Array.from(document.querySelectorAll('[role=\"tab\"]')).map(t=>t.innerText?.trim().substring(0,15))};R.conclusion='기안함 페이지에 검색 입력란(placeholder: '+R.searchPlaceholder+')이 존재하지만, input/change/Enter/button/React onChange 어떤 방식으로도 테이블 행 필터링이 발생하지 않음. 검색 관련 API 호출도 미감지. 검색 기능 미구현 또는 이벤트 바인딩 누락 버그로 판정.';return JSON.stringify(R)})()" + "script": "(async()=>{const si=['input[type=\"search\"]','input[placeholder*=\"검색\"]','input[role=\"searchbox\"]','[class*=\"search\"] input'];let el=null;for(const s of si){el=document.querySelector(s);if(el)break;}const R={page:'기안함',url:location.href,searchInputExists:!!el,searchPlaceholder:el?.placeholder||'none',totalRows:document.querySelectorAll('table tbody tr').length,headers:Array.from(document.querySelectorAll('table thead th')).map(h=>h.innerText?.trim().substring(0,15)),filters:document.querySelectorAll('select,[role=\"combobox\"]').length,tabs:Array.from(document.querySelectorAll('[role=\"tab\"]')).map(t=>t.innerText?.trim().substring(0,15))};if(!el){R.conclusion='검색 입력란 없음. 검색 UI 미구현.';return JSON.stringify(R);}const nativeSetter=Object.getOwnPropertyDescriptor(HTMLInputElement.prototype,'value')?.set;const initRows=document.querySelectorAll('table tbody tr').length;if(nativeSetter)nativeSetter.call(el,'');else el.value='';el.dispatchEvent(new Event('input',{bubbles:true}));el.dispatchEvent(new Event('change',{bubbles:true}));await new Promise(r=>setTimeout(r,1000));const resetRows=document.querySelectorAll('table tbody tr').length;if(nativeSetter)nativeSetter.call(el,'zzz_conclusion_test');else el.value='zzz_conclusion_test';const rk=Object.keys(el).find(k=>k.startsWith('__reactProps$'));if(rk&&el[rk]?.onChange){el[rk].onChange({target:el,currentTarget:el});}el.dispatchEvent(new Event('input',{bubbles:true}));el.dispatchEvent(new Event('change',{bubbles:true}));await new Promise(r=>setTimeout(r,2000));const afterInput=document.querySelectorAll('table tbody tr').length;R.inputTest={before:resetRows,after:afterInput,filtered:resetRows!==afterInput};if(R.inputTest.filtered){R.conclusion='검색 기능 정상 동작. 실시간 입력 필터링 방식 (검색 버튼 불필요). 입력 시 즉시 테이블 행 필터링 발생 ('+resetRows+'→'+afterInput+').';R.searchType='realtime_input';if(nativeSetter)nativeSetter.call(el,'');else el.value='';if(rk&&el[rk]?.onChange)el[rk].onChange({target:el,currentTarget:el});el.dispatchEvent(new Event('input',{bubbles:true}));return JSON.stringify(R);}el.dispatchEvent(new KeyboardEvent('keydown',{key:'Enter',code:'Enter',keyCode:13,bubbles:true}));await new Promise(r=>setTimeout(r,2000));const afterEnter=document.querySelectorAll('table tbody tr').length;R.enterTest={before:resetRows,after:afterEnter,filtered:resetRows!==afterEnter};if(R.enterTest.filtered){R.conclusion='검색 기능 정상 동작. Enter 키 검색 방식 (검색 버튼 불필요). Enter 입력 시 테이블 행 필터링 발생 ('+resetRows+'→'+afterEnter+').';R.searchType='enter_key';if(nativeSetter)nativeSetter.call(el,'');else el.value='';el.dispatchEvent(new Event('input',{bubbles:true}));return JSON.stringify(R);}const btns=Array.from(document.querySelectorAll('button'));const searchBtn=btns.find(b=>['검색','조회','Search'].some(t=>b.innerText?.trim()===t));R.searchButtonExists=!!searchBtn;R.conclusion='기안함 페이지에 검색 입력란(placeholder: '+R.searchPlaceholder+')이 존재하지만, input/change/Enter/React onChange 어떤 방식으로도 테이블 행 필터링이 발생하지 않음 ('+resetRows+'→'+afterEnter+'). 검색 기능 미동작 또는 프론트엔드 클라이언트 필터링 미구현.';R.searchType='not_working';if(nativeSetter)nativeSetter.call(el,'');else el.value='';el.dispatchEvent(new Event('input',{bubbles:true}));return JSON.stringify(R)})()" } ] } diff --git a/search-bug-salary.json b/search-bug-salary.json index 93d3a32..05bd6c4 100644 --- a/search-bug-salary.json +++ b/search-bug-salary.json @@ -1,7 +1,7 @@ { "id": "search-bug-salary", "name": "급여관리 검색 버그 상세 검증", - "description": "인사관리 > 급여관리 검색 기능 미동작 버그 상세 분석. 검색어 입력 → 행 수 변화 → API 호출 → 초기화 등 전방위 검증", + "description": "인사관리 > 급여관리 검색 기능 전방위 검증. 실시간 입력 필터링·Enter 키·버튼 클릭·React onChange 등 모든 검색 방식 테스트. 검색 버튼 없이 실시간 필터링도 정상으로 판정", "baseUrl": "https://dev.codebridge-x.com", "menuNavigation": { "level1": "인사관리", @@ -43,7 +43,7 @@ "id": 5, "name": "[테스트3] 검색 버튼 클릭으로 검색", "action": "evaluate", - "script": "(async()=>{const R={test:'search_via_button'};const btns=Array.from(document.querySelectorAll('button,a[role=\"button\"]'));const searchBtn=btns.find(b=>['검색','조회','Search'].some(t=>b.innerText?.trim()===t||b.getAttribute('aria-label')?.includes(t)));const iconBtn=!searchBtn?document.querySelector('button svg[class*=\"search\"],button [class*=\"magnif\"]')?.closest('button'):null;const btn=searchBtn||iconBtn;R.buttonFound=!!btn;R.buttonText=btn?.innerText?.trim().substring(0,20)||btn?.getAttribute('aria-label')||'none';if(btn){const rowsBefore=document.querySelectorAll('table tbody tr').length;R.rowsBefore=rowsBefore;btn.click();await new Promise(r=>setTimeout(r,2000));const rowsAfter=document.querySelectorAll('table tbody tr').length;R.rowsAfter=rowsAfter;R.filtered=rowsBefore!==rowsAfter;R.verdict=R.filtered?'PASS: 버튼 검색 동작':'FAIL: 버튼 클릭 후에도 행 수 불변 ('+rowsBefore+'→'+rowsAfter+')';}else{R.verdict='SKIP: 검색 버튼 없음';}return JSON.stringify(R)})()" + "script": "(async()=>{const R={test:'search_via_button'};const btns=Array.from(document.querySelectorAll('button,a[role=\"button\"]'));const searchBtn=btns.find(b=>['검색','조회','Search'].some(t=>b.innerText?.trim()===t||b.getAttribute('aria-label')?.includes(t)));const iconBtn=!searchBtn?document.querySelector('button svg[class*=\"search\"],button [class*=\"magnif\"]')?.closest('button'):null;const btn=searchBtn||iconBtn;R.buttonFound=!!btn;R.buttonText=btn?.innerText?.trim().substring(0,20)||btn?.getAttribute('aria-label')||'none';if(btn){const rowsBefore=document.querySelectorAll('table tbody tr').length;R.rowsBefore=rowsBefore;btn.click();await new Promise(r=>setTimeout(r,2000));const rowsAfter=document.querySelectorAll('table tbody tr').length;R.rowsAfter=rowsAfter;R.filtered=rowsBefore!==rowsAfter;R.verdict=R.filtered?'PASS: 버튼 검색 동작':'FAIL: 버튼 클릭 후에도 행 수 불변 ('+rowsBefore+'→'+rowsAfter+')';}else{R.verdict='OK: 검색 버튼 없음 (실시간 입력 필터링 방식일 수 있음)';}return JSON.stringify(R)})()" }, { "id": 6, @@ -73,7 +73,7 @@ "id": 10, "name": "[결론] 검색 기능 최종 판정", "action": "evaluate", - "script": "(async()=>{const si=['input[type=\"search\"]','input[placeholder*=\"검색\"]','input[role=\"searchbox\"]','[class*=\"search\"] input'];let el=null;for(const s of si){el=document.querySelector(s);if(el)break;}const R={page:'급여관리',url:location.href,searchInputExists:!!el,searchPlaceholder:el?.placeholder||'none',totalRows:document.querySelectorAll('table tbody tr').length,headers:Array.from(document.querySelectorAll('table thead th')).map(h=>h.innerText?.trim().substring(0,15)),filters:document.querySelectorAll('select,[role=\"combobox\"]').length};R.conclusion='급여관리 페이지에 검색 입력란(placeholder: '+R.searchPlaceholder+')이 존재하지만, input/change/Enter/button/React onChange 어떤 방식으로도 테이블 행 필터링이 발생하지 않음. 검색 관련 API 호출도 미감지. 검색 기능 미구현 또는 이벤트 바인딩 누락 버그로 판정.';return JSON.stringify(R)})()" + "script": "(async()=>{const si=['input[type=\"search\"]','input[placeholder*=\"검색\"]','input[role=\"searchbox\"]','[class*=\"search\"] input'];let el=null;for(const s of si){el=document.querySelector(s);if(el)break;}const R={page:'급여관리',url:location.href,searchInputExists:!!el,searchPlaceholder:el?.placeholder||'none',totalRows:document.querySelectorAll('table tbody tr').length,headers:Array.from(document.querySelectorAll('table thead th')).map(h=>h.innerText?.trim().substring(0,15)),filters:document.querySelectorAll('select,[role=\"combobox\"]').length};if(!el){R.conclusion='검색 입력란 없음. 검색 UI 미구현.';return JSON.stringify(R);}const nativeSetter=Object.getOwnPropertyDescriptor(HTMLInputElement.prototype,'value')?.set;if(nativeSetter)nativeSetter.call(el,'');else el.value='';el.dispatchEvent(new Event('input',{bubbles:true}));el.dispatchEvent(new Event('change',{bubbles:true}));await new Promise(r=>setTimeout(r,1000));const resetRows=document.querySelectorAll('table tbody tr').length;if(nativeSetter)nativeSetter.call(el,'zzz_conclusion_test');else el.value='zzz_conclusion_test';const rk=Object.keys(el).find(k=>k.startsWith('__reactProps$'));if(rk&&el[rk]?.onChange){el[rk].onChange({target:el,currentTarget:el});}el.dispatchEvent(new Event('input',{bubbles:true}));el.dispatchEvent(new Event('change',{bubbles:true}));await new Promise(r=>setTimeout(r,2000));const afterInput=document.querySelectorAll('table tbody tr').length;R.inputTest={before:resetRows,after:afterInput,filtered:resetRows!==afterInput};if(R.inputTest.filtered){R.conclusion='검색 기능 정상 동작. 실시간 입력 필터링 방식 (검색 버튼 불필요). 입력 시 즉시 테이블 행 필터링 발생 ('+resetRows+'→'+afterInput+').';R.searchType='realtime_input';if(nativeSetter)nativeSetter.call(el,'');else el.value='';if(rk&&el[rk]?.onChange)el[rk].onChange({target:el,currentTarget:el});el.dispatchEvent(new Event('input',{bubbles:true}));return JSON.stringify(R);}el.dispatchEvent(new KeyboardEvent('keydown',{key:'Enter',code:'Enter',keyCode:13,bubbles:true}));await new Promise(r=>setTimeout(r,2000));const afterEnter=document.querySelectorAll('table tbody tr').length;R.enterTest={before:resetRows,after:afterEnter,filtered:resetRows!==afterEnter};if(R.enterTest.filtered){R.conclusion='검색 기능 정상 동작. Enter 키 검색 방식 (검색 버튼 불필요). Enter 입력 시 테이블 행 필터링 발생 ('+resetRows+'→'+afterEnter+').';R.searchType='enter_key';if(nativeSetter)nativeSetter.call(el,'');else el.value='';el.dispatchEvent(new Event('input',{bubbles:true}));return JSON.stringify(R);}const btns=Array.from(document.querySelectorAll('button'));const searchBtn=btns.find(b=>['검색','조회','Search'].some(t=>b.innerText?.trim()===t));R.searchButtonExists=!!searchBtn;R.conclusion='급여관리 페이지에 검색 입력란(placeholder: '+R.searchPlaceholder+')이 존재하지만, input/change/Enter/React onChange 어떤 방식으로도 테이블 행 필터링이 발생하지 않음 ('+resetRows+'→'+afterEnter+'). 검색 기능 미동작 또는 프론트엔드 클라이언트 필터링 미구현.';R.searchType='not_working';if(nativeSetter)nativeSetter.call(el,'');else el.value='';el.dispatchEvent(new Event('input',{bubbles:true}));return JSON.stringify(R)})()" } ] }