Pixi JS Dynamic Color Changes (version 8)

I’m trying to change a Graphics object color after it has been rendered in Pixi JS and I’m struggling way more than I should be. There doesn’t seem to be any examples for this, and the examples for other functions are outdated (API changed since version 8). The only method that seems to work is the tint, but it also doesn’t seem to be a good replacement for color.

I am experienced with Canvas API, so I generally understand the process, and it seems that Pixi is trying to mimic Canvas API with version 8. I need to know the convention for dynamically making updates to Graphics objects, like changing their color and line width.

// JavaScript

import { Application, Graphics, Container } from 'pixi.js';


//
// Application() setup here and init() called
//


// Works:
const object = new Graphics();
object.setStrokeStyle({ color: "#000" });
object.moveTo(50, 50);
object.lineTo(500, 500);
object.stroke();

// Does not work:
object.setStrokeStyle({ color: "#00f" });
object.stroke();

Why is the count incrementing 3 times?

    audioUpdationFunction: function(){        // RE-WRITE THIS AGAIN
        mainFunction.currentSong.songAudio.addEventListener("timeupdate", ()=>{
            audioSlider.max = mainFunction.currentSong.songDuration
            audioSlider.value = mainFunction.currentSong.songAudio.currentTime
            console.log(audioSlider.value)
            
            // Audio-End detection
            let intAudio = parseInt(audioSlider.value)
            if(mainFunction.currentSong.songDuration === intAudio){
                mainFunction.count++                
            }
        })
        
        audioSlider.addEventListener("input", ()=>{
            mainFunction.currentSong.songAudio.currentTime = audioSlider.value
        })
    },

was trying to make a spotify clone, and this here is my function to update the audio and keep the tracker or the music-slider in sync with the song. this function is triggered when the user presses play, next or previous as when which means when the audio is starting to play these event listeners help to keep them in sync for also when the next song is played or the previous one.
Everything works fine but when the audio ends the count is incremented 3 times.
This code is written in oop mainly objects and not any class. And excuse me if the code looks shit i’m just a 18 newbie doing all by myself..
Thankyou:)

I tried doing chatgpt it gave the correct code but it doesn’t expand on the cause of the problem. Here is the solution. I can give the whole code for better understanding.
here is the chatgpt answer

audioUpdationFunction: function() {
    // Remove any existing listeners to avoid duplicates
    mainFunction.currentSong.songAudio.removeEventListener("timeupdate", mainFunction.handleTimeUpdate);

    // Define the handler as a named function for proper removal
    mainFunction.handleTimeUpdate = () => {
        audioSlider.max = mainFunction.currentSong.songDuration;
        audioSlider.value = mainFunction.currentSong.songAudio.currentTime;

        let intAudio = parseInt(audioSlider.value);
        if (mainFunction.currentSong.songDuration === intAudio) {
            console.log("Song ended");
            mainFunction.count++;
            console.log("Count:", mainFunction.count);
            if (mainFunction.count >= mainFunction.songQueue.length) {
                mainFunction.count = 0; // Loop back to the first song if needed
            }
            mainFunction.currentSong = mainFunction.songQueue[mainFunction.count];
            mainFunction.currentSong.songAudio.play();
            mainFunction.audioUpdationFunction(); // Reattach for the new song
        }
    };

    // Attach the cleaned-up listener
    mainFunction.currentSong.songAudio.addEventListener("timeupdate", mainFunction.handleTimeUpdate);

    // Slider manual input handling
    audioSlider.addEventListener("input", () => {
        mainFunction.currentSong.songAudio.currentTime = audioSlider.value;
    });
}

What is the encoding used by `String.fromCharCode`?

I’m using btoa to encode a Uint8Array to a base 64 string. And I hit a strange case. This works:

export function toBase64(data: Uint8Array): string {
    return btoa(String.fromCharCode(...data))
}

Whereas this does not (btoa will often complain about an unknown character):

export function toBase64(data: Uint8Array): string {
    return btoa(new TextDecoder('latin1').decode(data))
}

Question

What encoding should I use with TextDecoder to produce the same string as via fromCharCode?

Background

Peacing together various documentation the following should be true:

  • btoa expects a latin1 encoding
  • String.fromCharCode will convert individual integers to the respective utf16 character
  • for the first 256 characters latin1 and utf16 overlap

Test

Doing some experiments it is clear the two approaches yield different strings. With this setup:

const array = Array.from({ length: 256 }, (_, i) => I);
const d = new Uint8Array(array);

Running:

String.fromCharCode(...d)

will yield

x00x01x02x03x04x05x06x07btnvfrx0Ex0Fx10x11x12x13x14x15x16x17x18x19x1Ax1Bx1Cx1Dx1Ex1F !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~x7Fx80x81x82x83x84x85x86x87x88x89x8Ax8Bx8Cx8Dx8Ex8Fx90x91x92x93x94x95x96x97x98x99x9Ax9Bx9Cx9Dx9Ex9F ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ

Whereas running:

(new TextDecoder('latin1')).decode(d)

will yield

x00x01x02x03x04x05x06x07btnvfrx0Ex0Fx10x11x12x13x14x15x16x17x18x19x1Ax1Bx1Cx1Dx1Ex1F !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~x7F€x81‚ƒ„…†‡ˆ‰Š‹Œx8DŽx8Fx90‘’“”•–—˜™š›œx9DžŸ ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ

Where they substantially differ in the range 7F-9F (copied below for clearity)

x7Fx80x81x82x83x84x85x86x87x88x89x8Ax8Bx8Cx8Dx8Ex8Fx90x91x92x93x94x95x96x97x98x99x9Ax9Bx9Cx9Dx9Ex9F

x7F€x81‚ƒ„…†‡ˆ‰Š‹Œx8DŽx8Fx90‘’“”•–—˜™š›œx9DžŸ

How can I create Recurring Transactions Invoice using quick books API

I can’t find the way how can I creata Recurring Transactions Invoice using Quick books api , and is there a way to update or create it using API

I have the customer ID and want to get the Recurring Transactions Invoice template by that ID, if I also have the Recurring Transactions Invoice template ID but I cant find the way how can I get the template using its ID

.d.ts errors in the build package after lazy loading got introduced

I’m working on the React package for a design system and noticed that some of the components using have all the .svg in the built package output. Because of that my package size was 4mb.

I introduced lazy loading of the icons in the Icon component. That was the only change. Thanks to that now the package is no 1mb.

enter image description here

Surprisingly, since then, when I bump to the new version in my consuming app I get tons of errors complaining about .d.ts files.

ERROR in
./node_modules/@company/package/dist/components/radio/icons/index.d.ts
1:0-54 Module not found: Error: Can’t resolve ‘./radio-off.svg’ in
‘PATH_TO_PACKAGE’ Did you miss the leading dot in
‘resolve.extensions’? Did you mean
‘[“.“,”.wasm”,”.mjs”,”.js”,”.jsx”,”.json”,”.ts”,”.tsx”]’ instead of
‘[“
“,”.wasm”,”.mjs”,”.js”,”.jsx”,”.json”,”.ts”,”.tsx”]’?
ERROR in
./node_modules/@company/mypackagename/dist/types/data-activation-api.d.ts
5:7 Module parse failed: Unexpected token (5:7) You may need an
appropriate loader to handle this file type, currently no loaders are
configured to process this file. See
https://webpack.js.org/concepts#loaders | * Do not make direct
changes to the file. | */

export interface paths { | ‘/organization/{orgId}/data-set/{dataSetId}/traversal/{traversalId}/status’:
{ | parameters: {

ERROR in
./node_modules/@company/mypackagename/dist/types/data-catalog-api.d.ts
5:7 Module parse failed: Unexpected token (5:7) You may need an
appropriate loader to handle this file type, currently no loaders are
configured to process this file. See
https://webpack.js.org/concepts#loaders | * Do not make direct
changes to the file. | */

export interface paths { | ‘/organization/{organizationId}/entity/{entityId}/data-fields/{fieldId}’:
{ | parameters: {

ERROR in
./node_modules/@company/mypackagename/dist/types/data-integration-api.d.ts
5:7 Module parse failed: Unexpected token (5:7) You may need an
appropriate loader to handle this file type, currently no loaders are
configured to process this file. See
https://webpack.js.org/concepts#loaders | * Do not make direct
changes to the file. | */

export interface paths { | ‘/api/v1/integrations/datasources’: { | parameters: {

ERROR in
./node_modules/@company/mypackagename/dist/types/theme-interfaces.d.ts
2:12 Module parse failed: Unexpected token (2:12) You may need an
appropriate loader to handle this file type, currently no loaders are
configured to process this file. See
https://webpack.js.org/concepts#loaders | import
‘@mui/material/styles’;

import type { spacingScale, unitsScale } from ‘theme’; | declare module ‘@mui/material/styles’ { | interface TypeText {

Again, the only changes that happened was the lazy loading from the screenshot changelog in the Icon.tsx.

My tsconfig

{
  "compilerOptions": {
    "baseUrl": ".",
    "target": "es6",
    "lib": ["dom", "dom.iterable", "esnext"],
    "allowJs": true,
    "skipLibCheck": true,
    "strict": true,
    "declaration": true,
    "outDir": "./dist",
    "rootDir": ".",
    "declarationDir": "./dist",
    "forceConsistentCasingInFileNames": true,
    "esModuleInterop": true,
    "module": "esnext",
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "sourceMap": true,
    "declarationMap": true,
    "jsx": "react-jsx",
    "incremental": false,
    "paths": {
      "components/*": ["components/*"],
      "images/*": ["images/*"],
      "theme/*": ["theme/*"],
      "types/*": ["types/*"],
      "utils/*": ["utils/*"],
    },
    "plugins": []
  },
  "include": ["**/*.ts", "**/*.tsx"],
  "exclude": ["node_modules", "dist"]
}

And webpack config:

const path = require('path');
const glob = require('glob');
const TerserPlugin = require('terser-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const { getEntries } = require('./getEntries');

module.exports = {
  entry: getEntries(),
  mode: 'production',
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: (pathData) => {
      const name = pathData.chunk.name;
      if (name === 'theme') {
        return 'theme/index.js';
      }

      return `${name}.js`;
    },
    libraryTarget: 'module',
    globalObject: 'this',
  },
  module: {
    rules: [
      {
        test: /.(ts|tsx)$/,
        exclude: /node_modules/,
        use: {
          loader: 'babel-loader',
        },
      },
      {
        test: /.css$/,
        use: ['style-loader', 'css-loader'],
      },
      {
        test: /.svg$/,
        use: [
          {
            loader: '@svgr/webpack',
            options: {
              typescript: true,
              ref: true,
              svgProps: {
                role: 'img',
                width: '24',
                height: '24',
                fill: 'currentColor',
              },
            },
          },
        ],
      },
    ],
  },
  resolve: {
    extensions: ['.ts', '.tsx', '.js', '.jsx'],
    alias: {
      components: path.resolve(__dirname, 'components'),
      theme: path.resolve(__dirname, 'theme'),
      images: path.resolve(__dirname, 'images'),
      types: path.resolve(__dirname, 'types'),
    },
  },
  externals: {
    react: 'react',
    'react-dom': 'react-dom',
    '@mui/material': '@mui/material',
    '@mui/material/styles': '@mui/material/styles',
    '@emotion/react': '@emotion/react',
    '@emotion/styled': '@emotion/styled',
    next: 'next',
  },
  optimization: {
    minimizer: [
      new TerserPlugin(),
    ],
  },
  plugins: [new CleanWebpackPlugin()],
  experiments: {
    outputModule: true,
  },
};

I’m completely lost why such change could introduce so many (300+ errors). What is more – my consuming app works, it’s just about the CI errors when I run it, but when I open it in the browser all is good. The errors are from the terminal.

I know I could fix in the consuming app by doing:

{
  test: /.d.ts$/,
  loader: 'ignore-loader',
},

But I don’t want to force customers of the package to do such workarounds and special configs.

How to make JSON.parse work with a double-quoted string?

I’m trying to understand this behaviour around single/double quotes with JSON.parse, and how I can work around it.

pref1 = '{"foo":true}'
pref2 = "{'foo':true}"
JSON.parse(pref1)
  => {foo: true}
JSON.parse(pref2)
  => VM2021:1 Uncaught SyntaxError: Expected property name or '}' in JSON at position 1 (line 1 column 2)

Even if I escape the single quotes in pref2 with a then i still get the same error. Why does it only work as a single-quoted string? And is there a way to convert prefs2 into a format that JSON.parse will be happy with?

thanks

How to change Navmenu’s text color while scrolling?

I’m developing a website on Webflow and the fixed Navmenu should change the font color (black or white) according to the section’s background (light or dark). I’m using a custom JS code:

<script>
  /* Changing Colors and Logo by Section */
  function checkSectionTheme() {
    var pos = $(window).scrollTop();

    $('.theme-white, .theme-dark').each(function () {
      var pos_top = $(this).offset().top; // Use offset() for more accuracy
      var pos_bottom = pos_top + $(this).outerHeight();
      var class_name = $(this).hasClass("theme-white") ? "white" : "color";

      // Debugging positions
      console.log({
        currentScroll: pos,
        sectionTop: pos_top,
        sectionBottom: pos_bottom,
        sectionClass: class_name
      });

      if (pos >= pos_top && pos < pos_bottom) {
        if (class_name === "white") {
          $("body").removeClass("color").addClass("white");
        } else {
          $("body").removeClass("white").addClass("color");
        }
      }
    });
  }

  // Run function on page load and scroll
  $(document).ready(function () {
    checkSectionTheme();
    $(window).on("scroll", checkSectionTheme);
  });
</script>

It is partially working: the theme-dark (should have black font) only gets it right when we stop scrolling. While we scroll the font gets white like the theme-white sections. For the theme-white sections it works perfectly.

What am I missing here?

The first time I tried this exact code it was working perfectly. I’m assuming it stopped working correctly because I added a lot of content into this same section (to stick with the same seamless background), but the JS code should recalculate the height.

Find dynamic rendered HTML Object using Vitest

Im currently writing Unit test for a Vue component. The component renders the floorplan of a office. For that it generates an svg with the tables of the office. These are saved in a json.

The Vue component (FYI: Table refers to a desk):

import { onMounted, ref, watch } from 'vue';
import { json2SVG } from '@/converter/DbObjects2SvgParser';
import { useWallStore } from '@/stores/walls';
import { usePlaceStore } from '@/stores/tables';
import type { Wall } from '@/stores/walls';
import type { Place } from '@/stores/tables';

const wallsStore = useWallStore();
const wallsFromStore = ref<Wall[]>([]);
const tablesStore = usePlaceStore();
const tablesFromStore = ref<Place[]>([]);

let tables: HTMLCollectionOf<Element> = document.getElementsByClassName('main');
const selectedTable = ref<HTMLTableElement | null>(null);

const testSvg = ref<SVGElement>();
const mapContainer = ref<HTMLDivElement>();

const imageHeight = ref(585);
const imageWidth = ref(1200);

const emit = defineEmits(['tableSelected']);
const props = defineProps(['placeIdFromButton']);


function placeClick(event: Event) {
  const target = event.target as HTMLTableElement;
  changeSelectedTable(target);
  emit('tableSelected', target.id);
}

function changeSelectedTable(targetTable: HTMLTableElement) {
  if (selectedTable.value) {
    selectedTable.value.style.fill = ''; // Reset the previous selected table
  }
  targetTable.style.fill = 'white';
  selectedTable.value = targetTable;
}

watch(props, () => {
  console.log('watcher')
  for (let i = 0; i < tables.length; i++) {
    const table = tables[i];
    if (table.id == props.placeIdFromButton) {
      changeSelectedTable(table as HTMLTableElement);
    }
  }
});

onMounted(async () => {
    await wallsStore.fetchWalls();
    wallsFromStore.value = wallsStore.walls;

    await tablesStore.fetchPlaces();
    tablesFromStore.value = tablesStore.places;

  /*                  parsing from json to DB                       */
  //                  TODO should be moved into architect-app
  //const parsingWalls = walls2DBParser(plan, "http://localhost:3000/walls")
  //const parsingTables = tables2DBParser(plan, "http://localhost:3000/tables")

  if (testSvg.value instanceof SVGElement) {
    if (typeof document !== 'undefined'){
    json2SVG(testSvg.value, wallsFromStore.value, tablesFromStore.value);
    }
  } else {
    console.error('The element with ID "testSvg" is not an SVG element or does not exist.');
  }

  if (mapContainer.value) {
    imageHeight.value = mapContainer.value.clientHeight - 10;
    // imageWidth.value = mapContainer.clientWidth;
  } else {
    console.error('The element with ID "map-container" does not exist.');
  }

  tables = document.getElementsByClassName('table');
  for (const table of tables) {
    table.addEventListener('click', placeClick);
  }

});
</script>

<template>
  <div class="container" id="test">
    <div class="map-container" id="map-container" ref="mapContainer">
      <!--Map class="svgmap"/-->
      <svg class="svg-field" id="testSvg" ref="testSvg"
           :width="imageWidth" :height="imageHeight"
           viewBox='-75 -50 193 150'
           style="background: white"
      >
        <line class="testline1"
              x1="-50" y1="-50"
              x2="100" y2="100"
              stroke="green"
        ></line>
        <!--circle id="99" cx="-120" cy="-10" r="3" onclick="$setup.testClick($event.target.id)" ></circle>
        <circle id="99" cx="-110" cy="-20" r="3" onclick="{console.log($ event.target)}" ></circle-->
      </svg>
    </div>
  </div>
</template>

<style lang="scss">
@use '@/assets/themes/itemisVariables';

.svgmap {
  object-fit: cover;
  width: 100%;
  height: 100%;
}

.map-container {
  overflow: auto;
  border-style: solid;
  border-color: itemisVariables.$itemisGrey;
}

.svg-field {
  background-color: itemisVariables.$itemisGrey;
}

.testline {
  stroke: yellow;
}

.wall {
  stroke: itemisVariables.$itemisDarkBlue;
}

.table {
  stroke: itemisVariables.$itemisDarkBlue;
  fill: itemisVariables.$itemisBlue;
  r: 5;
  transition: fill 0.5s ease;

}

.table:hover {
  fill: itemisVariables.$itemisGrey;
  animation: pulse-color 1s infinite;
}

@keyframes pulse {
  0% {
    fill: itemisVariables.$itemisGrey;
  }
  50% {
    fill: itemisVariables.$itemisBlue;
    opacity: 0.7;
  }
  100% {
    fill: itemisVariables.$itemisGrey;
  }
}
</style> 

My test:

import { describe, it, expect, beforeEach, vi } from 'vitest';
import { flushPromises, mount, shallowMount } from '@vue/test-utils';
import { nextTick } from 'vue';
import ImagePart03 from '@/views/NewReservation_03/ImagePart03.vue';
import { createPinia, setActivePinia } from 'pinia';

beforeEach(async () => {
  setActivePinia(createPinia());
  await nextTick();
})

describe('TagesberichteTag', () => {



  const shallowMountCut = () => {
    const cut = shallowMount(ImagePart03);

    return {
      findMapContainer: () => cut.find('.map-container'),
      findFirstTable: () => cut.find('[id="1"]'),
      findHeader: () => cut.find('.header'),
      findPhrase: () => cut.find('.phrase')
    };
  };

  it('renders map container', () => {
    const { findMapContainer } = shallowMountCut();

    expect(findMapContainer().exists()).toBe(true);
  });

  it('renders table', async () => {
    await flushPromises()
    await nextTick()
    const { findFirstTable } = shallowMountCut();
    await nextTick()
    await flushPromises()
    expect(findFirstTable().exists()).toBe(true);
  });
});

Db2Objects2SvgParser.ts:

import type { Wall } from '@/stores/walls';
import type { Place } from '@/stores/tables';

const SCALE = 10;

export const json2SVG = (svg: SVGElement, wallsFromDB: Wall[], tablesFromDB: Place[]): SVGElement => {
  const svgWalls = wallObjectsIntoSVGElementSParser(wallsFromDB);
  svg.append(svgWalls);
  const svgTables = tableObjectsIntoSVGElementSParser(tablesFromDB);
  svg.append(svgTables);

  return svg;
};

export const wallObjectsIntoSVGElementSParser = (wallsFromDB: Wall[]) => {
  const sgvWallsGroup: SVGElement = document.createElementNS('http://www.w3.org/2000/svg', 'g');
  sgvWallsGroup.setAttribute('id', 'walls');

  for (const wall of wallsFromDB) {
    const svgWall = svgWallFromDBWallcreate(wall);
    sgvWallsGroup.appendChild(svgWall);
  }

  return sgvWallsGroup;
};
export const svgWallFromDBWallcreate = (wall: Wall) => {
  const wallElement = document.createElementNS('http://www.w3.org/2000/svg', 'line');

  wallElement.setAttribute('x1', (wall.coordsA.x * SCALE).toString());
  wallElement.setAttribute('y1', (wall.coordsA.y * SCALE).toString());
  wallElement.setAttribute('x2', (wall.coordsB.x * SCALE).toString());
  wallElement.setAttribute('y2', (wall.coordsB.y * SCALE).toString());
  wallElement.setAttribute('stroke', 'green');

  wallElement.setAttribute('class', 'wall');

  return wallElement;
};
export const tableObjectsIntoSVGElementSParser = (tablesFromDB: Place[]) => {
  const svgTablesGroup: SVGElement = document.createElementNS('http://www.w3.org/2000/svg', 'g');
  svgTablesGroup.setAttribute('id', 'tables');

  let tableIndex = 0;

  for (const table of tablesFromDB) {
    const svgTable = svgTableFromDBTableCreate(table);
    tableIndex++;
    const tableIndexString = tableIndex.toString();
    svgTable.setAttribute('id', tableIndexString);
    svgTablesGroup.appendChild(svgTable);
  }

  return svgTablesGroup;
};

export const svgTableFromDBTableCreate = (table: Place) => {
  const tableElement = document.createElementNS('http://www.w3.org/2000/svg', 'circle');


  tableElement.setAttribute('r', '2');
  tableElement.setAttribute('cx', (table.pos.x * SCALE).toString());
  tableElement.setAttribute('cy', (table.pos.y * SCALE).toString());
  tableElement.setAttribute('fill', 'red');
  tableElement.setAttribute('stroke', 'green');
  tableElement.setAttribute('stroke-width', '1');

  tableElement.setAttribute('class', table.type);

  //tableElement.setAttribute("onclick", "console.log($event.target)");

  return tableElement;
};

Using intelliJ’s debugger I’ve found this error and I think this is the reason why im not able to find the table using its Id in my test:

ReferenceError: __vite_ssr_import_2__ is not defined
    at eval (eval at json2SVG (/Users/userName/IdeaProjects/rare/Frontend/src/converter/DbObjects2SvgParser.ts:12:3), <anonymous>:1:1)
    at Module.json2SVG (/Users/userName/IdeaProjects/rare/Frontend/src/converter/DbObjects2SvgParser.ts:12:3)
    at /Users/userName/IdeaProjects/rare/Frontend/src/views/NewReservation_03/ImagePart03.vue:65:5
    at processTicksAndRejections (node:internal/process/task_queues:95:5)

How to find undefined class methods in JS without hovering

Assume the following example:

export default class TestClass{
    constructor (){
        this.init();
        this.doOtherStuff();
        this.doMoreStuff();
    }
    init(){
        //do stuff
    }
}

This displays in VS Code as:

enter image description here

If I Ctrl+hover over the method calls, I can see that init is defined, while the other 2 are not.

I am looking for either an option to color differently the other 2 functions, or the reverse of the “Outline” panel.

enter image description here

“Outline” panel shows methods defined, I want to see methods which are called, but not defined.

Mock working in test file but not in tested file

I’m trying to migrate a project from Jest to Vitest and I’m having issues with mocks. I can’t figure out why, when mocking a third party module and using mock implementations/mock returned values, these do work inside the test file, but not inside the tested file (where I want the mocked values to actually return). This works without issues with Jest but not with Vitest. Here’s some of the code I have currently:

import internalService from '@internal/js-service'
import idUtil from '@internal/js-service/lib/idUtil'

vi.mock('@internal/js-service', () => {
    return {
      default: {
        init: vi.fn().mockReturnValue('1),
        identify: vi.fn(),
      },
    }
  })

vi.mock('@internal/js-service/lib/idUtil', () => ({
    default: vi.fn().mockReturnValue('123'),
  }))

test('should initialize the internal service with the expected params',  () => {
    console.log('test', internalService.init(), idUtil())

    initializeInternalService({email: '[email protected]'})

    expect(internalService.init).toHaveBeenCalledTimes(1)
    expect(internalService.init).toHaveBeenCalledWith(
      {
        email: '[email protected]',
        unique_id: '1',
      },
    )
  })

and the tested file:

import internalService from '@internal/js-service'
import idUtil from '@internal/js-service/lib/idUtil'

export const initializeInternalService = (user: User) => {
  internalService.init(
    {
      unique_id: idUtil(),
      email: user.email,
    },
  )
}

When the console.log runs inside the test, the code returns the mocked values ('1' and '123') as expected, but when running the code in the tested file it seems like the original implementations are run, not the mocked ones, and I don’t understand why.

MFE React app shows white page for certain domains

I have an MFE React app that renders a UI with various differences based on the desired brand. Differences between brands are mainly theme/colour related. But these different brands also are hosted at different URLs, with Akamai dealing with that side of things. So you’ll have something like:

www.brand1.com.au renders the react app with brand1 as an MFE parameter

www.brand2.com.au renders the react app with brand2 as an MFE parameter

and so on. Now the actual compiled app is the same, it’s built once in Bamboo then served from various different domains, with the brand just being an MFE parameter passed in as a prop to the React app. However, for some brands the page gives the React white screen of death (white screen, no console/network errors, no error boundary errors, nothing). And I’ve narrowed it down to coming from React router.

The part that’s causing the white page is when I try to render the app’s routes in the router, I’m using react-router-dom: ^6.8.1 and I have something like:

import { BrowserRouter as Router, Route, Routes } from 'react-router-dom';
...
return (
  <Router>
    <Routes>
      ...
      <Route path="/dashboard" element={<p>test</p>} />
    <Routes/>

  <Router/>
);

Trying to render this react router stuff causes the white page for some brands. I tried a hash router, running yarn upgrade, various other white page react router fixes but the problem persists. My questions is, given that the built app is the same across brands/domains, but the white page issue only exists for some of them, where would the issue persist? Would it be a hosting/Akamai issue? Would it be related to out UI’s build config (I wouldn’t thing so, since that’s brand agnostic)?

Any insight would be greatly appreciated

React doesn’t show changes

When I create a new react project like this:

npx create-react-app my-app
cd ./my-app
npm uninstall react react-dom
npm install react@18 react-dom@18
npm install web-vitals
npm start

The loading is really slow.

also when i edit /src/app.js and changed the text there(for example, added <p>hey</p> to the default project) I don’t see the changes when I refresh the browser(tried to change browsers and be in incognito).

I work on WSL but the project is in C drive.

For example:
I run without lines 7,13.
The added them and made refresh and don’t see the changes in the tab.
enter image description here

How to detect words sent by a bot in twitch

I run two bots, one from streamlabs and another script (using tmi.js) that I run locally.

For the script, I found this code by Ma3x from this source: cooldown for twitch bot (portion of the code shown below) and added it on my script. It was able to detect the messages sent by the chatters.
However, it does not detect the messages sent by the streamlabs bot. I tried a lot of changes to the code but to no avail. What should I do to make the script detect the words sent by a bot.

Here’s the code:

 let lastHelpTime = 0
 client.on('message', (channel, tags, message, self) => {

 const send = message === "This is the message sent by a bot"

if ( !send ) return;
 
const timeNow = new Date().getTime()

if (timeNow - lastHelpTime > 60 * 1000) {
    
lastHelpTime = timeNow
    
client.say(channel, `This is the reply`)
}

Thanks in advance!

Why are files downloading sequentially instead of concurrently using Promise.all() in Electron (Node.js)

I’m working on an Electron app, and I’m trying to download multiple files concurrently from a folder structure using fs.promises.writeFile() inside an async function, but the files are downloading sequentially instead of concurrently, even though I’m using Promise.all(). Here’s my implementation:

const fs = require('fs');
const path = require('path');

async function downloadFolder(folderName, folderStructure, destinationPath) {
  const folderPath = path.join(destinationPath, folderName);

  if (!fs.existsSync(folderPath)) {
    try {
      fs.mkdirSync(folderPath, { recursive: true });
    } catch (err) {
      throw new Error(`Failed to create folder at ${folderPath}: ${err.message}`);
    }
  }

  try {
    const downloadPromises = folderStructure.map((item) => {
      const itemPath = path.join(folderPath, item.name);

      console.log(`Starting download for: ${itemPath}`);

      if (item.type === 'file') {
        return fs.promises.writeFile(itemPath, item.content)
          .then(() => console.log(`Downloaded: ${itemPath}`))
          .catch((err) => {
            throw new Error(`Failed to write file at ${itemPath}: ${err.message}`);
          });
      } else if (item.type === 'folder') {
        return downloadFolder(item.name, item.children, folderPath); // Recurse for subfolder
      }
    });

    // Wait for all download promises to resolve concurrently
    await Promise.all(downloadPromises);
    console.log(`All items in ${folderName} downloaded successfully!`);
  } catch (err) {
    throw new Error(`Error processing folder ${folderName}: ${err.message}`);
  }
}

However, when testing with a folder that only contains files (no nested folders) or with folders having nested folders, the downloads are happening sequentially, one after the other. Here’s an example of the folder structure I’m testing with:

folderStructure = [
  { name: '100-mb-example-jpg.jpg', type: 'file', content: /* file data */ },
  { name: '50mb.jpg', type: 'file', content: /* file data */ },
  { name: '70mb.iso', type: 'file', content: /* file data */ }
];

I expect the files to be downloaded concurrently, but they seem to be downloaded sequentially in the network. How can I fix this to download the files in parallel?

How to automatically remove an event from my web page the device viewpoint change in JavaScript

I am trying to expand the size of an element when an event is clicked at view width of 992px and below and want it to be automatically removed when the view width is above 993px. Please guide me on How to go about it?

if (sidebarbtn_div.style.display == 'flex') {
  const changesidebarbtn = () => {
    sidebarbtn.forEach(item => {
      item.classList.remove('active')
    })
  };
  sidebarbtn.forEach(disbtn => {
    disbtn.addEventListener('click', () => {
      changesidebarbtn();
      if (disbtn.classList.contains('close_left')) {
        document.querySelector('.dis_left').classList.add('active');
        document.querySelector('#class_middle').style.width = '96vw';
        sidebar.style.display = 'none'
      } else if (disbtn.classList.contains('dis_left')) {
        document.querySelector('.close_left').classList.add('active');
        document.querySelector('#class_middle').style.width = '100%';
        sidebar.style.display = 'block'
      };
    })
  })
} else if (sidebarbtn_div.style.display == 'none') {
  document.querySelector('#class_middle').style.width = '100%';
  sidebar.style.display = 'block'
}

This is the HTML it the event button

<div class="sidebar_button d-flex d-lg-none justify-content-center align-items-center z-3">
  <span class="close_left active p-2 py-3 rounded-circle" title="Close_left">&times;</span>
  <span class="dis_left p-2 py-3 rounded-circle" title="Dis_left">&#8827;</span>
</div>