viernes, 28 de diciembre de 2018

Oracle JOB

Los JOB en oracle se pueden crear por script de base de datos

SYS.DBMS_JOB.SUBMIT
( job => X
,what => ''DECLARE
P_ANNYO NUMBER;
RETURN_VALUE NUMBER;

BEGIN
P_valor:= 0;
RETURN_VALUE := NULL;

XXXX.P_TUProdecmiento( P_valor, RETURN_VALUE );
dbms_output.put_line(RETURN_VALUE );

COMMIT;
END; ''
,next_date => to_date(''13/01/2019 09:00:00'',''dd/mm/yyyy hh24:mi:ss'')
,interval => ''TRUNC(SYSDATE+365)''
,no_parse => TRUE
);
SYS.DBMS_OUTPUT.PUT_LINE(''Job Number is: '' || to_char(x));



Si se ejecuta desde el esquema del SYSTEM. Si quieres que se ejecute con el usuario del esquema hay que añadir

select NLS_ENV into NLS from dba_jobs where job=x;
sys.DBMS_IJOB.change_env(x,''XXXX',''XXXX','XXXX' ,NLS);

viernes, 21 de diciembre de 2018

Pruebas unitarias Selenium

Para hacer pruebas unitarias de una aplicación de web, he usado el componente de Selenium.  Lo bueno es que son pruebas que se se pueden ejecutar una otra vez y que puedes hacer una traducción casi automática a cualquier lenguaje.

Pero yo quería código C# y que la traducción fuera lo más rápida posible. Desde el complemento del FireFox ( desde Chrome no me da esa opción).  Hay que ir a opciones y activar la carteristas experimental

Y cuando lo tienes ya puedes ver el código generado para para prueba 




El código es automático y funciona bastante bien pero no hay que retocar algunas cosas

- Si tienes un combo  (lista deplegable) . El generador de código pone  SelectElement. Para que compile hay que añadir el paquete del Selenium.Support

- Opciones invisibles. Yo tenia el típico menú que cuando el ratón se posiciona sobre la opción principal se se despliega las  sub opciones. Parece que cuando no esta visible no funciona el evento click.  

Actions builder = new Actions(driver);
builder.MoveToElement(driver.FindElement(By.LinkText("menu1"))).Build().Perform();
driver.FindElement(By.LinkText("subMenu1.1")).Click();

- Tiempos de espera. Mi aplicación, como casi todas de la actualidad, tiene llamadas asíncronas.  El código para aplicar un tiempo de espera hay que codificarlo  

WebDriverWait wait = new WebDriverWait(driver, new TimeSpan(0, 0, 5));
wait.Until(w => driver.FindElements(By.CssSelector("[type='submit']")).ToList().Any(o => o.Displayed));


- Ventanas/pestañas emergentes . En mi caso los informes salen todos en pestañas nuevas. Por supuesto no es posible saber si el informe sale correctamente. 

var wait = new WebDriverWait(driver, TimeSpan.FromSeconds(20));
ReadOnlyCollection<String> handles = null;
wait.Until((d) => (handles = driver.WindowHandles).Count > 1);
driver.SwitchTo().Window(handles[handles.IndexOf(driver.CurrentWindowHandle) ^ 1]);


Los paquetes necesarios para mi aplicación de test fueron 



Todo esto era cierto en las otras versiones del Selenimu. Pero ya no están disponibles

Opciones :
- https://www.seleniumhq.org/docs/05_selenium_rc.jsp
- https://www.katalon.com/download/

Y la mejor opción :
https://a9t9.com/howto/getseleniumide

Ojo desactiva la opciones de actualizar automáticamente o usa la versión portable

viernes, 30 de noviembre de 2018

Portátil nuevo, Windows 10

Vale lo reconozco tengo portátil personal nuevo. Total solo han pasado 10 años desde el ultimo.

Las cosas que he aprendido con mi nuevo portátil :

1 Se me ocurrió la feliz idea de instalar una maquina virtual. Pero por supuesto mi portátil lo impedía por la BIOS. Vale no pasa nada, total solo tengo que darle a la tecla en el momento del inicio. Eso seria fácil si no fuera porque tiene Windows 10 y un arranque tan rápido que es imposible hacerlo así.
Por supuesto mire en Internet y lo encontré . Windows trae la posibilitad de acceder a la BIOS desde Windows. Esta oculto pero funciona

https://www.xataka.com/basics/como-acceder-bios-tu-pc-windows-10

Esto por puesto te vale también si quieres arrancar desde USB o cualquier cosa que quieras hacer con arranque. Ojo: no usar sino tienes claro lo que quieres cambiar

2. Por supuesto mi nuevo portátil lo único que contenía la caja era el cargado y el portátil. Relax hay una forma sencilla de hacer un "discos" de recuperación.  Como hacerlo

3. Que el nuevo Windows te permite hacer shanshot. Que fuerte. Esta es la típica cosas que siempre hacen los de sistemas y piensa que útil una pena que en casa esto no sea posible. Seamos sinceros el desinstalar aplicaciones nunca funciona bien (ni en Windows, ni en móviles )

viernes, 27 de abril de 2018

Llamadas REST al TFS


El TFS se puede consultar por llamadas REST, puedes usar las librerías para tal efecto o puedes hacerlas tú las llamadas
Obtener una lista de proyectos seria

public ListofProjectsResponse.Projects GetAllProjects()
        {
            ListofProjectsResponse.Projects viewModel = null;
            using (HttpClient confClient = new HttpClient(GetCredential()))
            {
                confClient.BaseAddress = @”http://nametfs:8080/tfs/DefaultCollection/”;
                confClient.DefaultRequestHeaders.Accept.Clear();
                confClient.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
                HttpResponseMessage message = confClient.GetAsync("_apis/projects?stateFilter=All&api-version=1.1").Result;
                if (message.IsSuccessStatusCode)
                {
                     viewModel = message.Content.ReadAsAsync<ListofProjectsResponse.Projects>().Result;
                }
            }
            return viewModel;

}

La seguridad puede ser por un tokent del TFS o puede que no lo tengas así configurado y sea una configuración de Windows. Si ese es tu caso en USUARIO y PASSWORD tienes que poner un usuario con permisos sobre el TFS
 private WebRequestHandler GetCredential()
        {
            WebRequestHandler authtHandler = new WebRequestHandler()
            {
                Credentials = new NetworkCredential(USUARIO, PASSWORD)
            };
            return authtHandler;
        }



Si está configurado con autentificación Basic

public ListofProjectsResponse.Projects GetAllProjects()
        {
            ListofProjectsResponse.Projects viewModel = null;
            using (HttpClient confClient = new HttpClient())
            {
                confClient.BaseAddress = @”http:// nametfs:8080/tfs/DefaultCollection/”;
                confClient.DefaultRequestHeaders.Accept.Clear();
                confClient.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
                confClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", _credentials);
                HttpResponseMessage message = confClient.GetAsync("_apis/projects?stateFilter=All&api-version=1.1").Result;
                if (message.IsSuccessStatusCode)
                {
                     viewModel = message.Content.ReadAsAsync<ListofProjectsResponse.Projects>().Result;
                }
            }
            return viewModel;

}

Donde:  _credentials= Convert.ToBase64String(System.Text.ASCIIEncoding.ASCII.GetBytes(string.Format("{0}:{1}", "", PersonalAccessToken)))

PersonalAccessToken à este es un valor que tienes en el TFS

viernes, 20 de abril de 2018

Compartir ficheros entre proyectos

Tengo una proyecto asp webform .net del que tengo que hacer otro sitio con parte del código.
Necesito una web nueva, pero que comparta controles de usuario, paginas aspx de la 1 aplicación.  No quiero copiar  y pegar el código y tenerlo duplicado.
 Solución
Pasos
1.       Me creo un proyecto vacío
2.       Añado todo lo que necesito (aspx, ascx, ccs, js ) pero lo añado como link (nuevo elemento existente , y añadir como enlace)

Al añadir como link el código realmente no está en mi directorio, y eso hace que falle al ejecutar sobre el 
La solución es añadir esto al final del fichero del proyecto:

 <Target Name="CopyLinkedContentFiles" BeforeTargets="Build">
    <Copy SourceFiles="%(Content.Identity)" DestinationFiles="%(Content.Link)" SkipUnchangedFiles="true" OverwriteReadOnlyFiles="true" Condition="'%(Content.Link)' != ''" />
  </Target>  

Hace es una copia de todos los ficheros que son link a nuestro directorio  y ya funciona todo. 


viernes, 12 de enero de 2018

Doble-click en controles ListBox

Los controles ListBox no tiene un evento de servidor para el dobleclick
La solución que más consiste en capturar el doble click por JavaScript e invocar un sumit de un botón oculto.

No me gustaba mucho la idea.
Desde la base de

Hice el mío  propio,  
    public class MiListBox : ListBox, IPostBackEventHandler
    {
       
        #region IHttpHandler Members

        public bool IsReusable
        {
            
            get { return true; }
        }
       
        public void ProcessRequest(HttpContext context)
        {
            //Escriba aquí la implementación del controlador.
        }

        #endregion

        public event EventHandler DblClick;
        private const string _DOUBLE_CLICK = "dbl";
        protected virtual void OnDblClick(EventArgs e)
        {
            if (DblClick != null)
            {
                DblClick(this, e);
            }
        }
        protected override void OnInit(EventArgs e)
        {
            if (this.Page != null)
            {
                this.Page.RegisterRequiresControlState(this);
            }
            base.OnInit(e);
        }
        protected override void OnPreRender( EventArgs e)
        {
            string script = this.Page.ClientScript.GetPostBackEventReference(this, _DOUBLE_CLICK);
            this.Attributes.Add("ondblclick", script);
            base.OnPreRender(e);
        }
        public void RaisePostBackEvent(string eventArgument)
        {
            if (eventArgument == _DOUBLE_CLICK)
            {
                this.OnDblClick(EventArgs.Empty);
            }
        }
    }
Yo no necesitaba  datos, ni da por el estilo por eso  hereda de IPostBackEventHandler e implementar la función RaisePostBackEvent  

Si hubiera  necesitado datos tendrá  que haber heredado de  IPostBackDataHandler  e RaisePostBackData