Javascript calculator - el test 9 no pasa

Hola, estaba haciendo el proyecto de la calculadora, y me encontré con que el text 9 no lo pasa, y no encuentro donde está el fallo.

Me puse a mirar en el fichero de los test para ver en que consiste el test 9. Para dicho test tiene que realizar dos expresiones simples, pero solo pasa la primera.

Aquí está el código en javascript:

//funcion para limpiar el display  
const clearDisplay = () => {
  $(document).ready(function(){
    $("#display").html("0");
  });
}

let op = false;

$(document).ready(function(){
  // jQuery para introducir numeros en el display, tambien está implementado el que no haya numeros que empiecen por multiples zeros
  $(".btn-primary").click(function(){
   if($("#display").html() === "0" | op){
    $("#display").html($("#" + this.id).html());
    op = false;
   } else {
    $("#display").append($("#" + this.id).html());
   }
    
   });
  
 //Bloque p de codigo para las operaciones, implementado para que solo se pueda poner un simbolo despues de un numero
 
  $(".btn-secondary").click(function(){
   let x = $("#display").html(); 
   let pattern = /.*\d$/;
   if(pattern.test(x)){
    $("#display").append($("#" + this.id).html());
     op = false;
   }
   
   });
  
   //Bloque de codigo para el resultado
  $("#equals").click(function(){
   let x = $("#display").html();
   $("#display").html(eval(x));
   op = true;
  });
 
  
});

Y el Html:

<div class="calculator container-md py-1">
  <!--<div class="row px-1">
    <p class="col-12 text-end result">01234567890</p>
  </div>-->
  <div class="row px-1">
    <p id="display" class="col-12 text-end current">0</p>
  </div>
  <div class="row px-1">
   <button id="clear" class="col-6 btn btn-danger" onclick="clearDisplay()">AC</button>
   <button id="divide" class="col-3 btn btn-secondary ">/</button>
   <button id="multiply" class="col-3 btn btn-secondary">*</button>
  </div>
  <div class="row px-1">
    <button id="seven" class="col-3 btn btn-primary">7</button>
    <button id="eight" class="col-3 btn btn-primary" >8</button>
    <button id="nine" class="col-3 btn btn-primary">9</button>
    <button id="subtract" class="col-3 btn btn-secondary">-</button>
  </div>
  <div class="row px-1">
    <button id="four" class="col-3 btn btn-primary">4</button>
    <button id="five" class="col-3 btn btn-primary" >5</button>
    <button id="six" class="col-3 btn btn-primary">6</button>
    <button id="add" class="col-3 btn btn-secondary">+</button>
  </div>
  <div class="row px-1">
    <div class="col-9">
      <div class="row">
        <button id="one" class="col-4 btn btn-primary">1</button>
        <button id="two" class="col-4 btn btn-primary" >2</button>
        <button id="three" class="col-4 btn btn-primary">3</button>
      </div>
      <div class="row">
        <button id="zero" class="col-8 btn btn-primary">0</button>
        <button id="decimal" class="col-4 btn btn-primary">.</button>
      </div>
    </div>
    <button id="equals" class="col-3 btn btn-success">=</button>
  </div>
</div>

Y el projecto: https://codepen.io/rafaelmartinezhuertas/full/XWEGLNq

Nota: estoy usando Bootstrap y jQuery.

This is the test that is failing:

      it(`In any order, I should be able to add, subtract, multiply
      and divide a chain of numbers of any length, and when I hit "=", the
      correct result should be shown in the element with the id of "display"`, async function () {
        clickButtonsByIdWithDelay(
          [_3, _plus, _5, _x, _6, _min, _2, _div, _4, _eq],
          CLICK_DELAY
        );
        await timeout(DELAY);
        assert(
          getInputValue(document.getElementById('display')) === '32.5' ||
            getInputValue(document.getElementById('display')) === '11.5',
          `The expression 3 + 5 * 6 - 2 / 4 should produce 32.5 or 11.5 as an
          answer, depending on the logic your calculator uses
          (formula vs. immediate execution) `
        );
        clearDisplay();
        clickButtonsByIdWithDelay([_5, _min, _9, _plus, _5, _eq], CLICK_DELAY);
        await timeout(DELAY);
        assert(
          getInputValue(document.getElementById('display')) === '1',
          'The expression 5 - 9 + 5 should produce a result of 1 '
        );
      });

If I type in those values myself (3 + 5 * …) for both problems, I get the right result, 32.5 then 1.

If I “listen” while the test is running by changing your code:

   //Bloque de codigo para el resultado
  $("#equals").click(function(){
   let x = $("#display").html();
   $("#display").html(eval(x));
   console.log('equals', document.getElementById('display').innerText)
   op = true;
  });

I can look at console and see:

equals 102
equals 32.5
equals -4
equals 5
equals 0
equals 25
equals 3
equals 1.5
equals 5
equals 8
equals 0.2857142857142857

Notice that the second an third entry are the test we are after. The first one is right (32.5) but the second one is off (-4). It’s almost like there is a race condition there? Like the buttons are coming too fast? It looks like the test is waiting 10ms between clicks.

That is all I have time to look into right now - see what you can do with that. Maybe I can dig deeper this weekend.

2 Likes

Thank you! I will keep looking into it.

1 Like

Ok, i found the problem, it works now after changing the beginning of the js from this:

//funcion para limpiar el display  
const clearDisplay = () => {
  $(document).ready(function(){
    $("#display").html("0");
  });
}

let op = false;

$(document).ready(function(){
  // jQuery para introducir numeros en el display, tambien está implementado el que no haya numeros que empiecen por multiples zeros
  $(".btn-primary").click(function(){
   if($("#display").html() === "0" | op){
    $("#display").html($("#" + this.id).html());
    op = false;
   } else {
    $("#display").append($("#" + this.id).html());
   }
    
   });
  
 //Bloque p de codigo para las operaciones, implementado para que solo se pueda poner un simbolo despues de un numero
 
  $(".btn-secondary").click(function(){
   let x = $("#display").html(); 
   let pattern = /.*\d$/;
   if(pattern.test(x)){
    $("#display").append($("#" + this.id).html());
     op = false;
   }
   
   });
  
   //Bloque de codigo para el resultado
  $("#equals").click(function(){
   let x = $("#display").html();
   $("#display").html(eval(x));
   op = true;
  });
 
  
});

To this:



let op = false;

//funcion para limpiar el display
$(document).ready(function(){
  
  $("#clear").click(function(){
    $("#display").html("0");
  });
  
  // jQuery para introducir numeros en el display, tambien está implementado el que no haya numeros que empiecen por multiples zeros
  $(".btn-primary").click(function(){
   if($("#display").html() === "0" | op){
    $("#display").html($("#" + this.id).html());
    op = false;
   } else {
    $("#display").append($("#" + this.id).html());
   }
    
   });
  
 //Bloque p de codigo para las operaciones, implementado para que solo se pueda poner un simbolo despues de un numero
 
  $(".btn-secondary").click(function(){
   let x = $("#display").html(); 
   let pattern = /.*\d$/;
   if(pattern.test(x)){
    $("#display").append($("#" + this.id).html());
     op = false;
   }
   
   });
  
   //Bloque de codigo para el resultado
  $("#equals").click(function(){
   let x = $("#display").html();
   console.log('operation', document.getElementById('display').innerText)
   $("#display").html(eval(x));
   op = true;
  });
 
  
});

Not a good idea to have the AC logic with his own $(document).ready(function(){…

1 Like