How are dot relative paths and rootDir paths treated differently in my projects jest configuration?

Problem Description

I have a question about the jest.config.ts that I am setting up.
There I use a moduleNameMapper, so that imports a la import ... from "@base/..." also work in the tests. For this I use a function of ts-jest, which returns the corresponding regular expressions from the tsconfig.json.compilerOptions.paths. tsconfig.json is a json file which I am importing with typescript’s resolveJsonModule option. See here for the documentation on moduleNameMapper.

The function from ts-jest returns one of the following two objects to be used as the moduleNameWrapper, depending on other parameters passed. How that works is not relevant for the question, as I am also able to just enter the keys and values directly, not using the ts-jest function.

First Object: { '^@base/(.*)$': './src/$1' }
Second Object: { '^@base/(.*)$': '<rootDir>/src/$1' }
The first does not work (the modules are then not resolved), the second works correctly.

Question

Hence my question: What does . mean as a path for jest? What is the difference with <rootDir>? Why do they both not point to the same directory? My jest config is in the root directory of the project, so I would assume that both . and <rootDir would point to the root directory (the folder where the jest config is located). Also see the documentation for rootDir.

What I’ve tried so far

I tried putting both objects in as moduleNameWrapper in the jest.config, but only the one with rootDir worked. I would have expected ./src/$1 to have worked as well, but it did not.

The rootDir solution is unsatisfying, as producing the object including <rootDir> requires an additional options parameter, which sets a prefix. This prefix is hard coded, and could e.g. result in problems further in this project or when using this project as a foundation for the next.

This is the call to create the moduleNameMapper object via ts-jest:

pathsToModuleNameMapper(compilerOptions.paths, {prefix: "<rootDir>/src/"}),

If the second parameter is omitted, then the dot version is produced, which does not work.

Thanks.

Problem with Formidable Error : Request aborted

I have an application with Node.js, Express.js , MongoDB and Javascript for front-end. I want to create file upload to add image . I use formidable and use AWS like cloud platform to save images too.

The problem is :
In my application , I have a form for add information about a car , for example: mark, model, year, location ,price, Choose image button and Submit button. When I fill the fields with data and choose image , then click on Submit button, in the console it write this:

Error: Request aborted
    at IncomingMessage.<anonymous> (C:Users201217040DocumentsCarRentalnode_modulesformidablelibincoming_form.js:122:19)
    at IncomingMessage.emit (node:events:369:20)
    at IncomingMessage.emit (node:domain:470:12)
    at abortIncoming (node:_http_server:598:9)
    at socketOnClose (node:_http_server:589:3)
    at Socket.emit (node:events:381:22)
    at Socket.emit (node:domain:470:12)
    at TCP.<anonymous> (node:net:666:12)

I put part of app.js :

const express = require('express');
const exphbs = require('express-handlebars');
const mongoose = require('mongoose');
const bodyParser = require('body-parser');
const session = require('express-session');
const cookieParser = require('cookie-parser');
const passport = require('passport');
const bcrypt = require('bcryptjs');
const formidable = require('formidable');
const socketIO = require('socket.io')

// init app
const app = express();

// setup body parser
app.use(bodyParser.urlencoded({extended:false}));
app.use(bodyParser.json());

// configuration for autthentication
app.use(cookieParser());
app.use(session({
    secret: 'mysecret',
    resave: true,
    saveUninitialized: true
}));
app.use(passport.initialize());
app.use(passport.session());

// load helpers
const {requireLogin, ensureGuest} = require('./helpers/authHelper');
const {upload} = require('./helpers/aws');

// load passports
require('./passport/local');
require('./passport/facebook.js');

// receive image
app.post('/uploadImage',requireLogin,upload.any(),(req,res)=>{
    const form = new formidable.IncomingForm();
    form.on('file',(field,file)=>{
        console.log(file);
    });
    form.on('error',(err)=>{
        console.log(err);
    });
    form.on('end',()=>{
        console.log('Image received successfully.');
    });
    form.parse(req);
});

Here is where I add “upload” in aws.js :

const aws = require('aws-sdk');
const multer = require('multer');
const multers3 = require('multer-s3');
const keys = require('../config/keys');

aws.config.update({
    accessKeyId:keys.AWSAccessID,
    secretAccessKey: keys.AWSSecretKey,
    region: 'eu-north-1'
});

const s3 = new aws.S3({});

const upload = multer({
    storage: multers3({
        s3:s3,
        bucket: 'car-rental-application',
        ac1:'public-read',
        metadata:(req,file,cb)=>{
            cb(null,{fieldName:file.fieldname});
        }, 
        key: (req,file,cb)=>{
            cb(null,file.originalname);
        },
        rename: (fieldName,fileName) =>{
            return fileName.replace(/W+/g, '-').toLowerCase();
        }
    })
});
exports.upload = upload;

And here is html form:

<div class="row">
    <div class="col-sm"></div>

    <div class="col-sm-5">
            <form action="/listCar2" method="POST">
            <input type="hidden" name="carID" value="{{car._id}}">
            <div class="form-group">
                <label for="pricePerHour">Price per hour</label>
                <input type="number" name="pricePerHour" id="pricePerhour" class="form-control" required>
            </div>
            <div class="form-group">
                <label for="pricePerWeek">Price per week</label>
                <input type="number" name="pricePerWeek" id="pricePerWeek" class="form-control" required>
            </div>
            <div class="form-group">
                <label for="location">Location</label>
                <input type="text" name="location" id="location" class="form-control" placeholder="street, city, state and zipcode " required>
            </div>
            <div class="form-group">
                <button class="btn btn-info upload-btn" type="button">Choose image</button>
                <input type="file" name="image" id="upload-input" style="display: none;" required>
            </div>
            <div class="form-group">
                <button type="submit" class="btn btn-primary">List a car</button>
            </div>
            </form>
    </div>

    <div class="col-sm"></div>
</div>
<script src="https://code.jquery.com/jquery-3.6.4.js" integrity="sha256-a9jBBRygX1Bh5lt8GZjXDzyOB+bWve9EiO7tROUtj/E=" crossorigin="anonymous"></script>
<script>
    // fetch location using javascript
function initMap(){
    var location = document.getElementById('location');
    var Autocomplete = new google.maps.places.Autocomplete(location);
}

// jquery code starts here
$(document).ready(function(){
    $('.upload-btn').on('click',function(){
        $('#upload-input').click();
    });
    $('#upload-input').on('change', function(){
        var uploadInput = $('#upload-input');
        if(uploadInput.val() != ''){
            var formData = new FormData();
            formData.append('image', uploadInput[0].files[0]);
            
            // make ajax request to send image to database
            $.ajax({
                url: '/uploadImage',
                type: 'POST',
                data: formData,
                processData: false,
                contentType: false,
                success: function() {
                    uploadInput.val('');
                }
            })
         }
    })
})

</script>
<script async
    src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCZa44WBMahTn9Zf2z9x6fKiZTMQQh3vbw&libraries=places&callback=initMap"></script>

How can I fix this problem?

Cypress API testing : How to access data generated from it block to another it block

How can I access the token generated from 1st it block to 2nd it block.

here is the code:

1st it block

      it('Login using new user', () => {
        cy.api({
          method: "POST",
          url:    "https://api-stg.sample.com/v1/user/login",
          body: 
          {
          "mobile_number": "+9912345678"
          "password": "p@ssword"  
          }

        })
          .then((response) => {
            expect(response.status).to.eq(200)
        })
          .then((response) => {
            const bearer_token = response.body.data.user.access_token.token // 
*in here where I get and put the token in var bearer_token*

            cy.log("Bearer token: " + token )
        })
      })

2nd it block

     it('Create New Mobile', () => {
        cy.api({
          method: "POST",
          url:    "https://api-stg.sample.com/v1/user/add_new_mobile_numbers",
          headers: {
            'Authorization': 'Bearer ' + token // *in here where I put the token*
          },
          body: 
          {
            "mobile_prefix": "+991",
            "mobile_number": "9912345679"
          }
})

I login from 1st block, then i need to use the token to add new mobile num in 2nd block.
in cypress dashboard it returns an error:
token is not defined

await this.showPopup(”); don’t show the Popup

I wanted to show the CreateOrderPopup in Odoo15 BUT it’s not showing and there is no error message.
I created 2 logs : ffffffff and QQQQQ
the fffffffff is shown in the logs but the QQQQQ which is after calling ” await this.showPopup(‘CreateOrderPopup’); ” it’s not being shown.

I have this in the JS file :

odoo.define("point_of_sale.CreateOrderButton", function (require) {
    "use strict";

    const PosComponent = require("point_of_sale.PosComponent");
    const ProductScreen = require("point_of_sale.ProductScreen");
    const Registries = require("point_of_sale.Registries");
   
    class CreateOrderButton extends PosComponent {
        async onClick() {
            console.log("ffffffffffffffffffff");
           await this.showPopup('CreateOrderPopup');
            console.log('QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ');
        };
        
    }
    CreateOrderButton.template = "CreateOrderButton";
    
    ProductScreen.addControlButton({
        
        component: CreateOrderButton,
        condition: function () {
            return (
                this.env.pos.config.iface_create_sale_order &&
                this.env.pos.get_order().get_client() &&
                this.env.pos.get_order().get_orderlines().length !== 0
                
            );
        },
    });

    Registries.Component.add(CreateOrderButton);
});

But the CreateOrderPopup is not showing when I click on the button. Also the QQQQ logs don’t get shown

For the CreateOrderPopUp i have :

odoo.define("point_of_sale.CreateOrderPopup", function (require) {
    "use strict";

    const AbstractAwaitablePopup = require("point_of_sale.AbstractAwaitablePopup");
    const Registries = require("point_of_sale.Registries");
    const framework = require("web.framework");

    class CreateOrderPopup extends AbstractAwaitablePopup {
        setup() {
            super.setup();
            this.createOrderClicked = false;
        }

        async createDraftSaleOrder() {
            await this._createSaleOrder("draft");
        }

        async createConfirmedSaleOrder() {
            await this._createSaleOrder("confirmed");
        }

        async createDeliveredSaleOrder() {
            await this._createSaleOrder("delivered");
        }

        async createInvoicedSaleOrder() {
            await this._createSaleOrder("invoiced");
        }

        async _createSaleOrder(order_state) {
            var current_order = this.env.pos.get_order();

            framework.blockUI();

            await this.rpc({
                model: "sale.order",
                method: "create_order_from_pos",
                args: [current_order.export_as_JSON(), order_state],
            })
                .catch(function (error) {
                    throw error;
                })
                .finally(function () {
                    framework.unblockUI();
                });

            // Delete current order
            this.env.pos.removeOrder(current_order);
            this.env.pos.add_new_order();

            // Close popup
            return await super.confirm();
        }
    }

    CreateOrderPopup.template = "CreateOrderPopup";
    Registries.Component.add(CreateOrderPopup);

    return CreateOrderPopup;
});

both templates are created and they are all called like this in the manifest file :

  "assets": {
        "point_of_sale.assets": [
            "pos_order_to_sale_order/static/src/css/pos.css",
            "pos_order_to_sale_order/static/src/js/CreateOrderPopup.js",
            "pos_order_to_sale_order/static/src/js/CreateOrderButton.js",
        ],
        'web.assets_qweb': [
            "pos_order_to_sale_order/static/src/xml/CreateOrderPopup.xml",
            "pos_order_to_sale_order/static/src/xml/CreateOrderButton.xml",

        ],

Why does the PopUp stops the QQQQ log from showing in the logs and itself in the POS

Install npm project A which has dependency to project B in project B but use current project B’s index.js file instead of original project B’s version

I have such case:

  1. I created npm project A which has peer dependency to project B
{
  "name": "project-A",
  "peerDependencies": {
    "project-B": "*"
  }
}
  1. I want to test project A inside project B without the need of installing specific version of project B inside project A
  2. I want to install project A inside project B and resolve project A’s dependency to project B’s index.js file which exports all the needed modules.

Is it achievable?

Currently I need to release project A with dependency to specific version of project B and install it like so in project B to test it. Obviously, if there are some changes in project B, project A becomes incompatible.

{
  "name": "project-A",
  "dependencies": {
    "project-B": "1.0.0"
  }
}

Tooltips overlap in vueform slider

I’m using this slider (https://github.com/vueform/slider#multiple-slider) in one of my form field and for some reasons, both the tooltips are stuck at one place.

Template Code of the slider component:

<template>
  <div class="input-container">
    <label class="input-label">{{ label }}</label>
    <div class="input-field">
      <Slider 
        v-model="value"
        :min="0"
        :max="4500"
        :showTooltip="always"
        :format="formatTooltip"
        class="slider-red"
        />
    </div>
  </div>
</template>

Script:

<script>

import Slider from '@vueform/slider'
import '@vueform/slider/themes/default.css';

export default {
  name: 'RangeSlider',
  components: {
    Slider,
  },
  props: {
    label: String,
  },
  data() {
    return {
      value: [0, 4500],
    }
  },
  watch: {
    activeButton(newValue) {
      this.activeButtonValue = newValue
    },
  },
  methods: {
    formatTooltip(val) {
      return `$${val}`
    },
  },
}
</script>

<style scoped>
.input-label {
  position: absolute;
  top: -10px;
  left: 10px;
  color: #d7c8f1;
  padding: 0 5px;
  text-decoration-color: white;
}

.input-field {
  padding-top: 20px;
  padding-bottom: 20px;
  border: 1px solid var(--secondary-color);
  color: white;
  cursor: pointer;
  display: flex;
  flex-direction: row;
  align-items: center;
  justify-content: center;
}

.space-right {
  margin-right: 16px;
}

.active {
  border: 1px solid var(--secondary-color);
  padding: 4px !important;
  border-radius: 12px !important;
  color: #101828 !important;
  background-color: #f9fafb;
}

.button {
  border: none;
  color: var(--primary-color);
  font-weight: 500;
  font: inherit;
  cursor: pointer;
  padding: 0px;
  border-radius: 8px;
}
.content-button {
  padding-left: 12px;
  padding-right: 12px;
  padding-top: 6px;
  padding-bottom: 6px;
  border-radius: 8px;
  border: 1px solid var(--secondary-color);
}

.slider-red {
  --slider-connect-bg: #EF4444;
  --slider-tooltip-bg: #EF4444;
  --slider-handle-ring-color: #EF444430;
}

</style>


I have tried formatting the width/height of the class, but it doesn’t seem to work.

The problem state:

enter image description here

How to display content for x seconds? [closed]

How do I display the drivers wins/podiums/points depending on what the user chooses below the drivers name after the user guesses?
How can I display the wins/podiums/points so it counts to it?
Then if the user guesses right it will take the user to the next round like my code does and if the user guesses wrong then the game ends that my code does as well.
CodePen: https://codepen.io/BobbyJackson19/pen/qBJbrWP.

// Define F1 driver data
const f1Drivers = [{
    name: 'Lewis Hamilton',
    wins: 103,
    podiums: 192,
    points: 4443.5
  },
  {
    name: 'George Russel',
    wins: 1,
    podiums: 9,
    points: 312
  },
  {
    name: 'Michael Schumacher',
    wins: 91,
    podiums: 155,
    points: 1566
  },
  {
    name: 'Sebastian Vettel',
    wins: 53,
    podiums: 122,
    points: 3098
  },
  {
    name: 'Alain Prost',
    wins: 51,
    podiums: 106,
    points: 798.5
  },
  {
    name: 'Ayrton Senna',
    wins: 41,
    podiums: 80,
    points: 614
  },
  {
    name: 'Nigel Mansell',
    wins: 31,
    podiums: 59,
    points: 482
  },
  {
    name: 'Jim Clark',
    wins: 25,
    podiums: 32,
    points: 274.5
  },
  {
    name: 'Juan Manuel Fangio',
    wins: 24,
    podiums: 35,
    points: 277.64
  },
  {
    name: 'Niki Lauda',
    wins: 25,
    podiums: 54,
    points: 420.5
  },
  {
    name: 'Jack Brabham',
    wins: 14,
    podiums: 31,
    points: 261
  },
  {
    name: 'Fernando Alonso',
    wins: 32,
    podiums: 101,
    points: 2106
  },
  {
    name: 'Max Verstappen',
    wins: 37,
    podiums: 80,
    points: 2080.5
  },
  {
    name: 'Nico Rosberg',
    wins: 23,
    podiums: 57,
    points: 1594.5
  },
  {
    name: 'Kimi Raikkonen',
    wins: 21,
    podiums: 103,
    points: 1873
  },
  {
    name: 'Mika Hakkinen',
    wins: 20,
    podiums: 51,
    points: 420
  },
  {
    name: 'Jenson Button',
    wins: 15,
    podiums: 50,
    points: 1235
  },
  {
    name: 'Jackie Stewart',
    wins: 27,
    podiums: 43,
    points: 359
  },
  {
    name: 'Damon Hill',
    wins: 22,
    podiums: 42,
    points: 360
  },
  {
    name: 'Felipe Massa',
    wins: 11,
    podiums: 41,
    points: 1167
  },
  {
    name: 'Valtteri Bottas',
    wins: 10,
    podiums: 67,
    points: 1791
  },
  {
    name: 'Mark Webber',
    wins: 9,
    podiums: 50,
    points: 1235
  },
  {
    name: 'Daniel Ricciardo',
    wins: 8,
    podiums: 32,
    points: 1311
  },
  {
    name: 'Charles Leclerc',
    wins: 5,
    podiums: 24,
    points: 874
  },
  {
    name: 'Sergio Perez',
    wins: 5,
    podiums: 28,
    points: 1255
  },
];

// Get HTML elements
const difficultySelect = document.getElementById('difficulty-select');
const startGameButton = document.querySelector('button');
const gameContainer = document.getElementById('game-container');
const higherButton = document.getElementById('higher-button');
const lowerButton = document.getElementById('lower-button');
const resultContainer = document.getElementById('result-container');
const playAgainButton = document.getElementById('play-again-button');
const frontImage = document.getElementById('bikar');
const easy = document.getElementById('easy_level');
const normal = document.getElementById('normal_level');
const hard = document.getElementById('hard_level');
const diff = document.getElementById('diff-text');



let currentDriverIndex;
let previousDriverIndex;
let currentDifficulty;
let score;


// Add event listener to the "Start Game" button
startGameButton.addEventListener('click', startGame);

function startGame() {
  startGameButton.style.display = 'none'
  frontImage.style.display = 'none';
  easy.style.display = 'none';
  normal.style.display = 'none';
  hard.style.display = 'none';
  difficultySelect.style.display = 'none'
  diff.style.display = 'none'


  currentDifficulty = difficultySelect.value;

  // Show the type of data to be guessed by the user
  const dataTypeElement = document.getElementById('data-type');
  if (currentDifficulty === 'easy') {
    dataTypeElement.textContent = 'Guess the driver with more wins';
  } else if (currentDifficulty === 'normal') {
    dataTypeElement.textContent = 'Guess the driver with more podiums';
  } else if (currentDifficulty === 'hard') {
    dataTypeElement.textContent = 'Guess the driver with more points';
  }

  higherButton.addEventListener('click', onHigherButtonClicked);
  lowerButton.addEventListener('click', onLowerButtonClicked);

  score = 0;

  // Hide the result container and play again button
  resultContainer.textContent = '';
  playAgainButton.style.display = 'none';

  // Show the first driver
  currentDriverIndex = previousDriverIndex = null;
  showNextDriver();
}


function onHigherButtonClicked() {
  checkAnswer('higher');
}

function onLowerButtonClicked() {
  checkAnswer('lower');
}

let lastDriverIndex;

function showNextDriver() {
  // Clear the previous driver's data
  gameContainer.innerHTML = '';

  // Pick two random drivers from the list
  if (currentDriverIndex === null) {
    currentDriverIndex = getRandomDriverIndex();
  }

  if (previousDriverIndex === null) {
    previousDriverIndex = getRandomDriverIndex(currentDriverIndex);
  }

  // Create and append elements to display the two drivers and their data
  const currentDriverElement = document.createElement('div');
  const previousDriverElement = document.createElement('div');
  const currentDriverDataElement = document.createElement('ul');
  const previousDriverDataElement = document.createElement('ul');
  const vsElement = document.createElement('div');

  currentDriverElement.classList.add('driver');
  previousDriverElement.classList.add('driver');
  vsElement.textContent = "Vs";

  currentDriverElement.innerHTML = `
            <h2>${f1Drivers[currentDriverIndex].name}</h2>
            <img src="driver-images/${f1Drivers[currentDriverIndex].name.toLowerCase().replace(' ', '-')}.png">
          `;
  previousDriverElement.innerHTML = `
            <h2>${f1Drivers[previousDriverIndex].name}</h2>
            <img src="driver-images/${f1Drivers[previousDriverIndex].name.toLowerCase().replace(' ', '-')}.png">
          `;

  currentDriverElement.appendChild(currentDriverDataElement);
  previousDriverElement.appendChild(previousDriverDataElement);
  gameContainer.appendChild(currentDriverElement);
  gameContainer.appendChild(vsElement);
  gameContainer.appendChild(previousDriverElement);

  // Show the "Higher or Lower" buttons
  const buttonContainer = document.getElementById('button-container');
  buttonContainer.style.display = 'block';
}

function getRandomDriverIndex(excludeIndex) {
  let index;
  do {
    index = Math.floor(Math.random() * f1Drivers.length);
  } while (index === excludeIndex);
  return index;
}


function checkAnswer(guess) {;
  const previousDriver = f1Drivers[previousDriverIndex];
  const currentDriver = f1Drivers[currentDriverIndex];
  let previousData, currentData;
  if (currentDifficulty === 'easy') {
    previousData = previousDriver.wins;
    currentData = currentDriver.wins;
  } else if (currentDifficulty === 'normal') {
    previousData = previousDriver.podiums;
    currentData = currentDriver.podiums;
  } else if (currentDifficulty === 'hard') {
    previousData = previousDriver.points;
    currentData = currentDriver.points;
  }

  const answerIsCorrect =
    (guess === 'higher' && currentData <= previousData) ||
    (guess === 'lower' && currentData >= previousData);


  if (answerIsCorrect) {
    score++;
    currentDriverIndex = previousDriverIndex;
    previousDriverIndex = null;
    showNextDriver();
  } else {
    endGame();
  }
}


function endGame() {
  // Remove event listeners from the buttons
  higherButton.removeEventListener('click', onHigherButtonClicked);
  lowerButton.removeEventListener('click', onLowerButtonClicked);

  let message = "";
  if (score <= 1) {
    const messages = [
      "You may need to get a new pit crew - they're clearly not feeding you the right information!",
      "That answer is a bit like a car stuck in the gravel trap - not quite what we were hoping for!",
      "Looks like you need to spend less time watching the races and more time studying the history books!",
      "Looks like you need some more practice laps before you get the hang of this."
    ];
    const randomIndex = Math.floor(Math.random() * messages.length);
    message = `${messages[randomIndex]} ${message}`;
  } else if (score <= 4) {
    const messages = [
      "Let's just say, if you were driving in the F1, you'd be lapped by now.",
      "Very Bad - You might want to stick to bumper cars!",
      "Don't worry, even the best drivers have their off days. Maybe you'll do better next time.",
      "Well, that answer was definitely not pole position material."
    ];
    const randomIndex = Math.floor(Math.random() * messages.length);
    message = `${messages[randomIndex]} ${message}`;
  } else if (score <= 10) {
    const messages = [
      "You're like a midfield driver - solid, but not quite podium material.",
      "You're doing okay, but maybe you should watch a few more races before playing again.",
      "You're not exactly setting the track on fire, but you're not stalling out either.",
      "Not bad, not bad at all! You're definitely on the right track to becoming an F1 expert."
    ];
    const randomIndex = Math.floor(Math.random() * messages.length);
    message = `${messages[randomIndex]} ${message}`;
  } else {
    const messages = [
      "I think we need to do a doping test on you because that score is unreal!",
      "Congratulations! You just set a new lap record for F1 trivia. Absolutely amazing!",
      "Wow, you're like the Lewis Hamilton of F1 trivia! Impressive!",
      "Hold on, let me check if you're not secretly connected to the FIA. Your knowledge is on another level!"
    ];
    const randomIndex = Math.floor(Math.random() * messages.length);
    message = `${messages[randomIndex]} ${message}`;
  }

  // Display the user's score and message
  resultContainer.textContent = `Game over! You got ${score} correct. ${message}`;
  playAgainButton.style.display = 'block';
  playAgainButton.addEventListener('click', startGame);
}
.home {
  color: black;
  /* Change the color to black */
  text-decoration: none;
  /* Remove the underline */
}

body {
  background-color: #adadad;
}

#difficulty-select {
  width: 120px;
  height: 30px;
  border: 1px solid #999;
  font-size: 18px;
  color: #1c87c9;
  background-color: #eee;
  border-radius: 5px;
  box-shadow: 4px 4px #ccc;
}

title {
  text-align: center;
}

.info {
  display: none;
  text-align: center;
  top: 5;
}

.icon:hover~.info {
  display: block;
}

#info-hover {
  width: 4%;
  position: absolute;
  top: 4;
  right: 1;
}


/* Style the header */

header {
  background-color: #fff;
  color: rgb(0, 0, 0);
  padding: 10px;
  display: flex;
  justify-content: space-between;
}


/* Style the game container */

#game-container {
  margin: 20px;
  font-size: 24px;
  text-align: center;
}


/* Style the button container */

#button-container {
  display: flex;
  justify-content: center;
  margin-bottom: 20px;
}


/* Style the result container */

#result-container {
  font-size: 24px;
  text-align: center;
}

#start-game-button {
  margin: 0;
  position: absolute;
  top: 15%;
  left: 50%;
  -ms-transform: translate(-50%, -50%);
  transform: translate(-50%, -50%);
}


/* Style the footer */

footer {
  background-color: #333;
  color: white;
  padding: 10px;
  text-align: center;
  position: fixed;
  bottom: 0;
  width: 100%;
}


/* Style the "Higher" and "Lower" buttons */

button {
  font-size: 24px;
  margin: 0 10px;
  padding: 10px 20px;
  border-radius: 5px;
  background-color: #005eff;
  color: white;
  cursor: pointer;
}


/*
        #button-container {
            margin: 0;
            position: absolute;
            top: 70%;
            left: 75%;
            -ms-transform: translate(-50%, -50%);
            transform: translate(-50%, -50%);
        }*/

#play-again-button {
  margin: 0;
  position: absolute;
  top: 90%;
  left: 50%;
  -ms-transform: translate(-50%, -50%);
  transform: translate(-50%, -50%);
}

#resault-container {
  margin: 0;
  position: absolute;
  top: 50%;
  left: 50%;
  -ms-transform: translate(-50%, -50%);
  transform: translate(-50%, -50%);
}


/* Style the selected difficulty option */

#difficulty option:checked {
  background-color: #4CAF50;
  color: white;
}

.home {
  font-family: Impact, Haettenschweiler, 'Arial Narrow Bold', sans-serif;
}

.title {
  font-family: Impact, Haettenschweiler, 'Arial Narrow Bold', sans-serif;
  font-size: 4em;
}

#easy_level {
  font-family: Impact, Haettenschweiler, 'Arial Narrow Bold', sans-serif;
  font-size: 3em;
}

#normal_level {
  font-family: Impact, Haettenschweiler, 'Arial Narrow Bold', sans-serif;
  font-size: 3em;
}

#hard_level {
  font-family: Impact, Haettenschweiler, 'Arial Narrow Bold', sans-serif;
  font-size: 3em;
}

#data-type {
  font-family: Impact, Haettenschweiler, 'Arial Narrow Bold', sans-serif;
}

#bikar {
  display: block;
  margin-left: auto;
  margin-right: auto;
  width: 40%;
}

#higher-button {
  background-color: #4CAF50;
  margin: 0;
  position: absolute;
  top: 80%;
  left: 75%;
  -ms-transform: translate(-50%, -50%);
  transform: translate(-50%, -50%);
}

#lower-button {
  background-color: #ff0000;
  margin: 0;
  position: absolute;
  top: 87%;
  left: 75%;
  -ms-transform: translate(-50%, -50%);
  transform: translate(-50%, -50%);
}

#game-container {
  font-family: Impact, Haettenschweiler, 'Arial Narrow Bold', sans-serif;
}

header {
  width: 100%;
  padding: 0;
}

.contact {
  display: flex;
  justify-content: center;
  background-color: #262626;
  padding: 10px 0;
  position: fixed;
  bottom: 0;
  width: 100%;
}

#contact {
  color: #fff;
  font-family: Impact, Haettenschweiler, 'Arial Narrow Bold', sans-serif;
}

#privacy {
  color: #fff;
  font-family: Impact, Haettenschweiler, 'Arial Narrow Bold', sans-serif;
}
<header>
  <h1 class="title">Higher or Lower F1 Game</h1>

  <button id="start-game-button">Start Game</button>
</header>
<label id="diff-text" for="difficulty-select" style="text-align: center;  font-family: Impact, Haettenschweiler, 'Arial Narrow Bold', sans-serif; font-size: 3em;">Choose difficulty level:</label>
<select id="difficulty-select">
  <option value="easy">Easy</option>
  <option value="normal">Normal</option>
  <option value="hard">Hard</option>
</select>
<div class="icon"><img id="info-hover" src="info.png"></div>
<div class="info" style="font-family: Impact, Haettenschweiler, 'Arial Narrow Bold', sans-serif; font-size: 3em;">Guess if the driver below has more wins/podiums/points</div>
<h2 id="easy_level" style="text-align:center">Easy: Higher or Lower Wins</h2>
<h2 id="normal_level" style="text-align:center">Normal: Higher or Lower Podiums</h2>
<h2 id="hard_level" style="text-align:center">Hard: Higher or Lower Points</h2>
<img id="bikar" src="bikar.png">
<main>
  <div id="data-type" style="text-align:center; font-size: 3em;"></div>
  <div id="game-container" style="font-size: 4em; display: flex; justify-content: center; align-items: center; ">

    <!-- Display F1 driver data here -->
  </div>
  <div id="button-container" style="display: none;">
    <button id="higher-button">Higher</button>
    <button id="lower-button">Lower</button>
  </div>
  <div id="result-container" style="font-family: Impact, Haettenschweiler, 'Arial Narrow Bold', sans-serif;  position: relative; top: 150px; ">
    <!-- Display game result here -->
  </div>
  <button id="play-again-button" style="display:none">Play Again</button>
</main>
<!--<footer>
          <p>Created by Kristjan Jakob</p>
        </footer>-->

instead of triggering a download, I am getting gibberish text in response

I want to download the zip file without loading it into the browser. However, when I hit the endpoint, instead of triggering a download, I am getting gibberish text in response.

This is my API endpoint.

[HttpGet("downloadfile")]
public async Task<IActionResult> Downloadfile(string userId, CancellationToken ct)
    {
        string docId = $"tinyurl:{userId}";
        DocumentResponse response1 = await blobManager.GetCustomUrlByUserId(docId, ct);
        TinyUrl tinyUrl = JsonConvert.DeserializeObject<TinyUrl>(response1.Content);

      
        var response = await wc.GetAsync(tinyUrl.ActualUrl, HttpCompletionOption.ResponseHeadersRead, ct);

        if (!response.IsSuccessStatusCode)
        {
            return NotFound();
        }
        var contentStream = await response.Content.ReadAsStreamAsync();
        var fileName = "file.zip";
        return new FileStreamResult(contentStream, "application/octet-stream")
        {
            FileDownloadName = fileName
        };
    }

This is my react code


    export const DownloadZip = async (uri) => {
      const method = 'GET';
      const headers = await auth.getTokenHeader(true);
      headers.append('Accept', 'application/octet-stream');
      return retryFetch(uri, { method, headers });
};

How popstate works based on browser back button

I am confused on the working fuction of popstate.

Example.com (Clicked href) -> Google.com (Pressed Back) -> Yahoo.com

(OR)

Example.com (Clicked href) -> Google.com (Pressed Back) -> Example.com
(Quick redirect automatically) -> Yahoo.com

My code

// Listen for the popstate event
window.addEventListener('popstate', function(event) {
  // Redirect the user to Yahoo.com
  window.location.href = 'https://www.yahoo.com';
});

// When a link is clicked, update the URL to include the current URL as a parameter
var links = document.getElementsByTagName('a');
for (var i = 0; i < links.length; i++) {
  links[i].addEventListener('click', function(event) {
    var currentUrl = encodeURIComponent(window.location.href);
    var href = this.getAttribute('href');
    this.setAttribute('href', href + '?prev=' + currentUrl);
  });
}

VS Code – don’t see variables when debugging JS

I’m trying to debug a simple program in JS:

var a = [1,2,2,2,3];
        var b = [2];
        function arrayDiff(a, b) {
            console.log(a,b);
            for(var i = 0; i < b.length; i++) {
                if(a.includes(b[i])){
                    a.splice(b[i]);
                    console.log(a,b);
                }
            }
            return a,b;
        }
        
        var array1 = [1,1,2];
        var array2 = [1];
        console.log(arrayDiff(array1,array2));

and see how the variables act. I have a HTML file connected to this, downloaded Debugger for Firefox and created the following launch.json file:

{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [

    {
        "name": "Launch index.html",
        "type": "firefox",
        "request": "launch",
        "reAttach": true,
        "file": "${workspaceFolder}/index.html"
    },
    {
        "name": "Launch localhost",
        "type": "firefox",
        "request": "launch",
        "reAttach": true,
        "url": "http://localhost/index.html",
        "webRoot": "${workspaceFolder}"
    },
    {
        "name": "Attach",
        "type": "firefox",
        "request": "attach"
    },
    {
        "name": "Launch WebExtension",
        "type": "firefox",
        "request": "launch",
        "reAttach": true,
        "addonPath": "${workspaceFolder}"
    }
]}

However I still cannot see the variables when I put breakpoints and so on… I’ve tried everything from reinstalling the extension, setting up Firefox browser itself with the values recommended in the extension’s readme, localhost, attach, or opening directly the index.html file. Looked through stack overflow and none of the solutions have helped yet…

Running Pop!_OS 22.04 LTS.

Thanks!

How do I pass down props to another function using TypeScript?

I am not proficient with TypeScript but I am trying to pass down the {product.picture} which is a string to the function saveInfo() once the user clicked save. I can display the picture but I could not post it to the server once I clicked the save button. The error stated “Cannot find product”.

Appreciate any help on this.

function App() {
    
    const saveInfo = async (product) => {
    let response = await axios.post('https://localhost:3000', {
      data: {
        image: `https://image/${product.picture}.png`,
      },
    });

  return (
    <div className="App">
            <div>
                products.map((product: any) => (
                  <div className="product" key={product.id}>
                    <h5>{product.name}</h5>
                    <img
                      src={`https://image/${
                        product.picture as string
                      }.png`}
                      alt="symbol"
                    />
                  </div>
                ))
            </div>
            <button onClick={() => saveInfo(product)}>Save</button>
    </div>
  );
}

How do I authorize to work with Google forms?

When I want to get authorization data I get this error:

Error: listen EADDRINUSE: address already in use :::3200

This port is not busy. The error occurs only when it starts executing this request.

The request is executed at the address: http://localhost:3200/api/run

What am I doing wrong?

const path = require('path');
const { authenticate } = require('@google-cloud/local-auth');


module.exports.runSample = async function () {
    const auth = await authenticate({
        keyfilePath: path.join(__dirname, 'credentials.json'),
        scopes: 'https://www.googleapis.com/auth/forms.responses.readonly',
    });
    console.log(auth)
}

credentials.json:

{
    "web": {
...
        "redirect_uris": [
            "http://localhost:3200/oauth2callback/"
        ]
    }
}

chrome.tabs.onUpdated.addListener gives “Could not establish connection”-error

I’m learning how to make Chrome-extensions (manifest v3) and I’m trying to understand how “addListener” works, more specifically “chrome.tabs.onUpdated.addListener”.

One thing I don’t understand is why Chrome throws this error at me all the time:

*Uncaught (in promise) Error: Could not establish connection. Receiving end does not exist.
*

I feel that I’m missing something very important on how messages work between backgrounds.js and content.js. Any suggestions?

In backgrounds.js I have this code:

chrome.tabs.onUpdated.addListener ( function (tabId, changeInfo, tab) {

  if (changeInfo.status === 'complete' && tab.status === 'complete' && tab.url) {
    chrome.tabs.sendMessage(tab.id, { type: "RELOADED" });
    
  }
});

And in my content.js I have this code:

chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
  if (message.type === "RELOADED") {

    let prismicUrl = document.location.href;
    
    const prismicUrlMustExist = /~b/; // Normal
    const prismicUrlMustExist2 = /&b=/; // Efter sökning
    const articleUrlMustExist = /--ec/;
   
    if (prismicUrlMustExist.test(prismicUrl) || prismicUrlMustExist2.test(prismicUrl)) {
      console.info("Hittade artikel. Väntar en sekund.");
      setTimeout(() => {  initiate(); }, 1000);
      console.info("Försöker hitta sidebar.");
    } else if (articleUrlMustExist.test(prismicUrl)) {
      console.info("Hittaden artikel på sajten.");
      setTimeout(() => {  initiate_article(); }, 1000);
    } else {
      console.warn("Error: hittade ingen kompatibel sida.");
    }
  }
});```

Feel free highlight any improvements I can make to do this in a more effective way, or tell if you need more information about the code.


Well, I'm stuck. I have tried reading on the subject and understand how to do it differently, but I didn't find anything that stuck well enough for me.

How to call my function inside another function

Im currently trying to implement functionality that deletes all translations within a project when a user deletes a project. However, when i try to call my deleteTranslations function within my deleteProject function, it says deleteTranslations is not defined.

deleteTranslations: async ({ user, projectId, trkeys }) => {
      const deletePromises = trkeys.map(async (trkey) => {
        const params = {
          ...getBaseParams(),
          Key: {
            PK: getPK('trans', user, projectId),
            SK: getSK('trans', user, projectId, trkey),
          },
        };
        return doDelete(params);
      });
      return Promise.all(deletePromises);
    },

    deleteProject: async ({ user, project }) => {
      const translationsParams = {
        user,
        projectId: project,
        trkeys: [],
      };
      await deleteTranslations(translationsParams);      // the problem is here

      const params = {
        TableName: table,
        Key: {
          PK: getPK('project', user),
          SK: getSK('project', user, project),
        },
      };
      return doDelete(params);
    },

Ive tried to implement this in a few ways but i cant wrap my head around this.