* mock_cauta_alfa_dialog.prg - inlocuieste DOAR PROCEDURE cauta_alfa (COMUN\programe\cauta_alfa.prg, * linia 16), NU cauta_nom_articole/XML2ListaIDDescriere/do_adauga_articol - acelea raman REALE, * neatinse. Se incarca PRIMUL (inaintea "SET PROCEDURE TO cauta_alfa ADDITIVE") - la nume duplicat * de procedura VFP foloseste fisierul incarcat PRIMUL (vezi docs/testare-ui-vfp.md capcana j). * * De ce: cauta_alfa() reala populeaza cursorul din Oracle prin gencursor->ca_baza.afisare(), care * foloseste This.CursorFill() (CursorAdapter/conexiune reala) - nu goExecutor, deci nu poate fi * mock-uit ca restul infrastructurii (vezi COMUN\clase\decabaza.vc2:36-99). Acest shadow inlocuieste * DOAR sursa de date (Oracle -> cursor mock pre-populat de test) si bucla de asteptare modala * (WindowType=1, Show() blocheaza pana la Release -> WindowType=0 + actiuni conduse programatic * dupa Show(), vezi docs/testare-ui-vfp.md capcana g). Formularul e clasa REALA cauta_alfa_form * (COMUN\clase\cauta_alfa_forms.vcx), metodele apelate (do_alege, do_termin, do_renunt) sunt cele * REALE, neschimbate - doar interactiunea utilizatorului e simulata in loc de bucla de evenimente. * * IMPORTANT (capcana l, docs/testare-ui-vfp.md): CREATEOBJECT apelat DINTR-O PROCEDURA (nu din * programul principal) intoarce un obiect stricat in acest runtime headless (verificat empiric - * "OFORM_CAUTARE is not an object" la prima folosire). De aceea formularele NU se creeaza aici - * testul principal le PRE-CONSTRUIESTE inline (goDlgA/goDlgB/goDlgC) INAINTE sa apeleze * do_adauga_articol, iar acest shadow doar SELECTEAZA obiectul potrivit dupa gcTestScenariu si ii * apeleaza metodele reale (asta e simpla dispecerizare de metoda, nu CREATEOBJECT - functioneaza * din procedura fara probleme). * * Control test (setate de testul principal INAINTE de fiecare apel): * goDlgA / goDlgB / goDlgC - formularele REALE pre-construite (vezi test_picker_real_212.prg) * gcTestScenariu - 'A' (marcheaza BULDOEXCAVATOR + OK), 'B' (nimic marcat + OK), * 'C' (dublu-click pe denumire), altfel Cancel * Rezultat expus (citit de testul principal dupa apel): * gcTestGnButon, gcTestXML, gcTestLenXML, gcTestCAles, gcTestPcAles, gcTestRandiuriMarcate Procedure cauta_alfa Parameters tcselect,tcfiltru,tcschema,tcorder,tccoloana,tcTitlu,tcTitluColoane, ; tcNume_Proc,tl_AllInList,tcFiltruOriginal,tcPrimaColoana, tnPornire, tnTipReturn, ; tcIdColumn, tlDesktop, tcGroup, tcGridDynamicBackColor, tcGridToolTip, tlModParam, tcStringCriterii, ; tcProceduraVerifica, tcProceduraCopiaza,tcLocate LOCAL lcCursor, lcCursorXML, lcCAlesDupaMarcare LOCAL oForm_cautare, oReturnScattObj Private pcAles pcAles = "" gcTestRandiuriMarcate = 0 IF USED('crsReturnAlfa') USE IN ('crsReturnAlfa') ENDIF *-- === selecteaza obiectul PRE-CONSTRUIT (vezi capcana l mai sus - fara CREATEOBJECT aici) === DO CASE CASE gcTestScenariu == 'A' oForm_cautare = goDlgA CASE gcTestScenariu == 'B' oForm_cautare = goDlgB CASE gcTestScenariu == 'C' oForm_cautare = goDlgC OTHERWISE oForm_cautare = goDlgA ENDCASE lcCursor = oForm_cautare.crs_cursor *-- pcAles trebuie sa reflecte marcajul curent INAINTE de a incepe (formularul e deja afisat, *-- creat in main); il sincronizez manual cu cAles-ul formularului la pornire, exact cum face *-- BINDEVENT(Thisform,"lAles",...) + do_alege() in fluxul real (do_alege scrie in AMBELE, *-- Thisform.cAles si pcAles - vezi cauta_alfa_forms.vc2:405-418). pcAles = oForm_cautare.cAles *-- === FAZA 1: marcare - simuleaza interactiunea utilizatorului cu formularul REAL === *-- IMPORTANT: NU se atinge oForm_cautare dupa do_termin()/do_renunt() - acele metode fac *-- this.Release, care DISTRUGE efectiv formularul VFP (verificat empiric: accesarea unei *-- proprietati dupa Release da eroare 1924 "is not an object", chiar daca alta variabila *-- (goDlgA) inca "tine" referinta) - de-aia cauta_alfa.prg REAL insusi nu mai citeste nimic *-- de pe oForm_cautare dupa .Show() decat prin pcAles/gnButon (variabile libere, nu proprietati *-- de obiect). Orice diagnostic despre cAles trebuie capturat AICI, inainte de faza 2. DO CASE CASE gcTestScenariu == 'A' *-- marcheaza randul BULDOEXCAVATOR prin mecanismul real (echivalentul click pe denumire / *-- SPACE): do_alege() citeste RECNO() curent al cursorului si toggle-uie cAles la acea pozitie. SELECT (lcCursor) LOCATE FOR ALLTRIM(denumire) == 'BULDOEXCAVATOR' IF FOUND() oForm_cautare.do_alege() ENDIF lcCAlesDupaMarcare = oForm_cautare.cAles IF TYPE('gcUILog') = 'C' DO HarnessStep WITH 1, 'scenariul A: BULDOEXCAVATOR marcat (Thisform.cAles=[' + lcCAlesDupaMarcare + ']), inainte de OK real' ENDIF CASE gcTestScenariu == 'B' *-- nimic marcat SELECT (lcCursor) GO TOP lcCAlesDupaMarcare = oForm_cautare.cAles CASE gcTestScenariu == 'C' *-- "dublu-click pe denumire": in modul multi-select (lAles=.T., cazul cauta_nom_articole), *-- BindEvent(dblClick->do_termin) NU se armeaza (cauta_alfa_forms.vc2:652 "If !Thisform.lales"), *-- deci dublu-click = 2x acelasi Click -> do_alege() de 2 ori (marcheaza, apoi demarcheaza) - *-- NU exista submit rapid pe dublu-click in acest dialog. Simulez exact gestul (2 click-uri pe *-- Column1.Text1, handler-ul REAL) si documentez ca cursorul ramane nemarcat. SELECT (lcCursor) LOCATE FOR ALLTRIM(denumire) == 'BULDOEXCAVATOR' IF FOUND() oForm_cautare._GRID1.Column1.Text1.Click() oForm_cautare._GRID1.Column1.Text1.Click() ENDIF lcCAlesDupaMarcare = oForm_cautare.cAles IF TYPE('gcUILog') = 'C' DO HarnessLog WITH 'scenariul C: dupa 2x Click (dublu-click simulat) cAles=[' + lcCAlesDupaMarcare + '] (astept ramas needecis, fara submit automat)' ENDIF OTHERWISE lcCAlesDupaMarcare = oForm_cautare.cAles ENDCASE *-- diagnostic cerut de team lead: pcAles (variabila PRIVATE folosita mai jos in filtrul WHERE al *-- XML-ului) vs Thisform.cAles (marcajul vizual/albastrit vazut de Marius) - trebuie sa fie *-- SINCRONE la acest punct, INAINTE de faza 2 (inchidere), pentru ca acolo se pierde accesul. gcTestPcAlesInainte = pcAles gcTestCAlesInainte = lcCAlesDupaMarcare *-- === FAZA 2: inchidere - butonul OK/Cancel REAL (this.Release -> oForm_cautare devine inert) === DO CASE CASE gcTestScenariu == 'A' OR gcTestScenariu == 'B' OR gcTestScenariu == 'C' oForm_cautare.do_termin() && butonul OK REAL (_frm_base.do_termin: gnButon=1, Release) OTHERWISE oForm_cautare.do_renunt() ENDCASE DOEVENTS FORCE *-- === de aici incolo: cod IDENTIC cu cauta_alfa.prg original (COMUN\programe\cauta_alfa.prg, *-- liniile 218-249) - aceeasi conditie, acelasi filtru (pcAles), acelasi CURSORTOXML. NU se mai *-- atinge oForm_cautare (a fost Release-uit de do_termin/do_renunt mai sus). === lcCursorXML = "" SELECT (lcCursor) IF gnButon=1 Do Case Case tnTipReturn = 0 Scatter Name oReturnScattObj Memo Otherwise Select * From (lcCursor) With (Buffering = .T.) Where Substr(pcAles,Recno(),1) = 'X' ; INTO Cursor crsReturnAlfa Cursortoxml("crsReturnAlfa", "lcCursorXML", 2, 0+2+8, 0, "1") gcTestRandiuriMarcate = RECCOUNT('crsReturnAlfa') Use In crsReturnAlfa Endcase Else Do Case Case tnTipReturn = 0 Scatter Name oReturnScattObj Blank Otherwise lcCursorXML = "" Endcase Endif *-- expus pentru diagnostic in testul principal (cAles luat din snapshot-ul de dinainte de *-- Release - vezi FAZA 1 - NU de pe oForm_cautare, care e deja inert dupa do_termin/do_renunt) gcTestGnButon = gnButon gcTestXML = lcCursorXML gcTestLenXML = LEN(m.lcCursorXML) gcTestCAles = lcCAlesDupaMarcare gcTestPcAles = pcAles *-- NU dau Release aici (obiectul e deja Release-uit de do_termin/do_renunt mai sus) Use In (lcCursor) Do Case Case tnTipReturn = 0 Return oReturnScattObj Otherwise Return lcCursorXML Endcase Endproc && cauta_alfa (shadow test)