How can I test nested elements in JestJS?

Having the following HTML output:

<ul>
    <li>Menu 1</li>
    <li>Menu 2(Parent)
      <ul>
            <li>Child 1</li>
            <li>Child 2</li>
            <li>Child 3 (Parent 2)
            <ul>
                  <li>Child 4</li>
                  <li>Child 5</li>
            </ul>
            </li>
      </ul>
    </li>
</ul>

I need to test whether the elements exist and are properly nested. I can write a test as follows:

it('should render nested elements', () => {
    <MyComponent />
    expect(screen.getByText('Menu 1').toBeInDocument())
    expect(screen.getByText('Menu 2(Parent)').toBeInDocument())
    expect(screen.getByText('Child 3 (Parent 2)').toBeInDocument())
    expect(screen.getByText('Child 5').toBeInDocument())
}

and that will tell me it does exist in the DOM but this test will also pass for the following HTML and I do not want that:

<ul>
    <li>Menu 1</li>
    <li>Menu 2(Parent)</li>
   <li>Child 1</li>
   <li>Child 2</li>
   <li>Child 3 (Parent 2)</li>
   <li>Child 4</li>
   <li>Child 5</li>
</ul>

How can I test if the element exists and it is properly nested?

ID not setted with typeorm-fixtures-cli

with lib typeorm-fixtures-cli, is there a way to seed the entity with the specified id “1013”. When I’m trying, the id is not “1013” but “1”

entity: Product
items:
    product1013:
        id: 1013
        name: My product

My entity :

@Entity('products')
export class Product {
    @PrimaryGeneratedColumn() id: number

    @Column() name: string
}

tsx vs ts-node comparison for executing typescript

I was looking for a complete impartial comparison between tsx and ts-node, but I couldn’t find anything. What is the general difference between them, and do any of them come with caveats? It’s a very broad question, but it’s worth asking as there isn’t much information available.

How to assign individual ‘Paypal Add to Cart’ to individual html check boxes

I have a check box setup that changes an image dependant on which checkbox you click (displays a different colour).

I would like to assign a separate ‘PayPal Add to Cart’ to each checkbox, so the viewer chooses the colour, then clicks the PayPal button to buy the item selected.

The HTML code:

    <div class="colors">
    <div class="ColourLabel"><div class="c5"></div><span>Moonwalk<br>Grey</span></div>
    <div class="ColourLabel"><div class="c9"></div><span>Midnight<br>Black</span></div>
    <div class="ColourLabel"><div class="c10"></div><span>Volcanic<br>Orange</span></div>
    <div class="ColourLabel"><div class="c11"></div><span>Chili<br>Red</span></div>
    <div class="ColourLabel"><div class="c12"></div><span>Lapisluxury<br>Blue</span></div>
    <div class="ColourLabel"><div class="c13"></div><span>Thunder<br>Grey</span></div>
    <div class="ColourLabel"><div class="c7"></div><span>British Racing<br>Green</span></div>
    <div class="ColourLabel"><div class="c8"></div><span>Blazing<br>Red</span></div>
    <div class="ColourLabel"><div class="c2"></div><span>Pepper<br>White</span></div>
    <div class="ColourLabel"><div class="c3"></div><span>White<br>Silver</span></div>
    </div>

A snippet of the Script Code:

    $(".product2 .c5").click(function(){
    $(".product2 .c1").css("box-shadow","none");
    $(".product2 .c2").css("box-shadow","none");
    $(".product2 .c3").css("box-shadow","none");
    $(".product2 .c4").css("box-shadow","none");
    $(".product2 .c5").css("box-shadow","0 0 0 2px #0D1F2D, 0 0 0 3.5px #CB3843");
    $(".product2 .c6").css("box-shadow","none");
    $(".product2 .c7").css("box-shadow","none");
    $(".product2 .c8").css("box-shadow","none");
    $(".product2 .c9").css("box-shadow","none");
    $(".h2").animate({opacity:0},function(){
    $(".h2").attr("src","img/Ark/ARK MG.webp");
    });
    $(".h2").animate({opacity:1});
    });

Have tried assigning Paypal containers like so but it will only display the first in line:

    <div id="paypal-container-SOME-ID">
    <div class="ColourLabel"><div class="c5"></div><span>Moonwalk<br>Grey</span></div>
    </div>
    <div id="paypal-container-ANOTHER-ID">
    <div class="ColourLabel"><div class="c9"></div><span>Midnight<br>Black</span></div>
    </div>

And the Paypal Script like so:

    <script src="https://www.paypal.com/sdk/js?client-id=MY-ID&components=hosted-buttons&disable-funding=venmo&currency=GBP"></script>
    <script>
    paypal.HostedButtons({
    hostedButtonId: "SOME-ID",
    }).render("#paypal-container-SOME-ID")
    </script>
    <script>
    paypal.HostedButtons({
    hostedButtonId: "ANOTHER-ID",
    }).render("paypal-container-ANOTHER-ID")
    </script>

I am open to advice as a better way to work around this as it seems very messy for a user – selecting a checkbox to view the item – then having to use a dropdown menu (set up in Paypal buttons) to buy an item?

(I have Attached a screen shot of what I mean)

Thanks

Vue-Router render the component but doesn’t change the url

import { createMemoryHistory, createRouter } from "vue-router";
import { AuthUser } from "../../auth/user";

const routes = [
  {
    path: "/",
    component : () => import("../components/Home/Home.vue"),
    beforeEnter : (to, from, next)=>{
      if(!AuthUser()){
        next({path : "/signup"})
      }else{
        next()
        return ""
      }
    }
  },
  {
    path: "/signup",
    component : () => import("@/components/Signup/Signup.vue"),
  }
];

const router = createRouter({
  history: createMemoryHistory(),
  routes,
});

export default router
 

I don’t know why when I open “/” , the component signup it’s show but url “http://localhost:3000/ ” doesn’t change at all.

The component it’s show perfectly, it’s the url the problem.

AuthUser always return false for now.

How can I convert protobuff “map” type to object?

I have a next proto type:

message Test {
    map <string, string> values = 1;
}

Next, I’m making an object of this type:

const test = new Test().getValuesMap().set("test", "1")

And then, I’m trying to lead this type to an object:

console.log(JSON.stringify(test.toObject(), null, 4));

So, I’m getting this structure:

{
    valuesMap: [
        ["test", "1"]
    ]
}

But I’m expecting a structure like this:

{
    values: {
        test: "1"
    }
}

According to this file, the behaviour with “valuesMap” is valid. However, is there any way to convert a proto to an object as I’m expecting?

Also, the provided example is synthetic. In real case I have a recursive structure like this:

{
    "root": {
        "valuesMap": [
            [
                "key1",
                {
                    "name": "some-name"
                    "nested": {
                        "valuesMap": [
                            [
                                "key2",
                                {
                                    "name": "other-name"
...

So instead of using just res.toObject(), I need to write some recursive function on a client to transform this object.

JSX dynamic rendering with function binding

Hi I’m trying to write a react component that displays a component by parsing a string to JSX. I was able to do so using react-jsx-parser but it does not work when I pass functions as bindings. The data is displayed properly but the functions don’t seem to be working. I’ve a snippet of what I’m doing right now. Is there a way to pass functions like handleSearchChange below and make it work? My end goal to build a sandbox where users can edit Jsx in a textarea and execute it in real time(including the functions if any). Thank you.

  const handleSearchChange = (e) => {
    console.log("Function Called: handleSearchChange", e.target.value);
    // Additional function logic...
  };


  useEffect(() => {
    fetch(/api/get-jsx/${user})
      .then((res) => res.json())
      .then((data) => {
        setJsxTemplate(data.jsxTemplate); 
        setSandboxJsx(data.jsxTemplate); 
        setData(data);
      })
      .catch((error) => console.error("Failed to fetch shop details:", error));
  }, [user]);

  // Function to handle changes in the sandbox textarea
  const handleJsxChange = (event) => {
    setSandboxJsx(event.target.value);
  };
  const jsxTestString = 
  <input type="text" onChange="{handleSearchChange}" />
;

  return (
    <div>
      {/* Textarea for editing JSX (simple sandbox) /}
      <textarea
        value={sandboxJsx}
        onChange={handleJsxChange}
        style={{ width: "100%", height: "200px" }}
      />
      {/ Render the JSX using JsxParser */}
      {sandboxJsx !== "" && (
        <JsxParser
          jsx={jsxTemplate}
          components={{ Search }}
          bindings={{
            data,
            handleSearchChange: handleSearchChange,
          }}
          onError={(error) => console.error("JsxParser error:", error)}
        />
      )}
    </div>
  );
};

v-data-table-server not loading items | Vuetify & Vue 3

I’ve configured a server where I fetch data from an endpoint.
This data has been printed in a v-table component and working perfectly, but I’m having issues with v-data-table-server component.
There’s something wrong and I can’t figure out what it is.

<template>
  <v-container>
    <div class="d-flex mb-8">
      <div class="flex-1-1 mr-2">
        <h1 class="text-h4">Fieldeas Demo</h1>
        <p>Lorem ipsum dolor sit amet</p>
      </div>
      <div class="w-100" style="max-width:240px">
        <v-select
          :items="fetchOptions"
          v-model="selectedFetchOption"
          label="Base de datos"
          hide-details="auto"
          @update:modelValue="fetchData"
        ></v-select>
      </div>
    </div>
    <div class="d-flex align-center v-row mb-2 w-50">
      <div class="v-col">
        <v-text-field
          v-model="input_filter"
          hide-details="auto"
          label="Filtro"
          @update:modelValue="fetchData"
        ></v-text-field>
      </div>
      <div class="v-col">
        <v-text-field
          v-model="input_year"
          hide-details="auto"
          label="Año"
          type="number"
          hide-spin-buttons
          @update:modelValue="fetchData"
        ></v-text-field>
      </div>
    </div>
    <div>
      <v-alert v-if="error" type="error">{{ error }}</v-alert>
      <v-data-table-server
        v-if="data"
        v-model:items-per-page="itemsPerPage"
        :headers="data.fields"
        :items="data.rows"
        :items-length="data.rowCount"
        loading-text="Cargando... Por favor espera"
        loading
      >
      <template v-slot:headers="{ headers }">
        <tr>
          <th v-for="(header, index) in headers" :key="index">{{ header.name }}</th>
        </tr>
      </template>
      <template v-slot:tbody="{ items }">
        <tr v-for="(item, index) in items" :key="index">
          <td v-for="(value, i) in item" :key="i">{{ value }}</td>
        </tr>
      </template>
      </v-data-table-server>
    </div>
  </v-container>
</template>

<script>
  import { toRaw } from 'vue';
  import { useFetch } from '@/hooks/useFetch'

  export default {
    data() {
      return {
        data: null,
        error: null,
        loading: false,
        fetchOptions: [
          'fieldeas_tracktrace_pre',
          'gaa_report',
        ],
        selectedFetchOption: 'fieldeas_tracktrace_pre',
        sqlFile: 'test',
        input_filter: null,
        input_year: null,
        itemsPerPage: 10,
      }
    },
    async created() {
      await this.fetchData()
      console.log(this.data)
      console.log(toRaw(this.data))
    },
    methods: {
      async fetchData() {
        let url = `http://localhost:3000/api/queries/${this.selectedFetchOption}/sql/${this.sqlFile}`
        const params = []

        if (this.input_filter) params.push(`content_filter=${this.input_filter}`)
        if (this.input_year) params.push(`year=${this.input_year}`);
        if (params.length > 0) url += `?${params.join('&')}`

        const { data, error, loading } = await useFetch(url);

        this.data = data
        this.error = error
        this.loading = loading
      },
    },
  }
</script>

This is a screenshot of the data object

data object image

GameEnd Logic is not working in the second game

This game is a glass hitting game. First the bot creates a sequence. After that, we have to hit the glasses in the same order. In first game, the game works completely fine. But after clicking continue btn and selecting the mode, the bot also creates a sequence perfectly. But here there is no game end. It goes infinitely.

Github pages link : https://ka-hirithik.github.io/GlassSmashMemory/
Github link : https://github.com/KA-Hirithik/GlassSmashMemory

I tried chatGPT with different prompts. But still not working.

I think there is some problem in updating and verifying the sequences in gameEndLogic functions.

const startScreen = document.getElementById('startScreen');
const gameScreen = document.getElementById('gameScreen');
const endScreen = document.getElementById('endScreen');

let score = 0;
const scoreBox =  document.getElementById('scoreBox');
scoreBox.innerHTML = score;

let games = 0;
const gamesBox =  document.getElementById('gamesBox');
gamesBox.innerHTML = games;
const gamesContainer = document.getElementById('gamesContainer')
gamesContainer.style.visibility = 'hidden';

const totalGames =  document.getElementsByClassName('totalGames');

let difficulty;
let playedSequenceNO;

const glass1 = document.getElementById('glass1');
const glass2 = document.getElementById('glass2');
const glass3 = document.getElementById('glass3');
const glass4 = document.getElementById('glass4');
const glass5 = document.getElementById('glass5');

const sound1 = new Audio("./glass1.wav");
const sound2 = new Audio("./glass2.wav");
const sound3 = new Audio("./glass3.wav");
const sound4 = new Audio("./glass4.wav");
const sound5 = new Audio("./glass5.wav");

sound1.playbackRate = 1;
sound2.playbackRate = 1;
sound3.playbackRate = 1;
sound4.playbackRate = 1;
sound5.playbackRate = 1;

let glasses = ['glass1', 'glass2', 'glass3', 'glass4', 'glass5'];
let playerSequence = [];
let sequenceNumber = playedSequenceNO;

const easy = document.getElementById('easy');
const medium = document.getElementById('medium');
const hard = document.getElementById('hard');
const ContinueBtn = document.getElementById('continueBtn');

easy.addEventListener('click', () => {
  startGame('easy');
});
medium.addEventListener('click', () => {
  startGame('medium');
});
hard.addEventListener('click', () => {
  startGame('hard');
});

ContinueBtn.addEventListener('click', () => {
  startScreen.style.display = 'flex';
  gameScreen.style.display = 'none';
  endScreen.style.display = 'none';

  score = 0;
  scoreBox.innerHTML = score;
  games = 0;
  gamesBox.innerHTML = games; 
  gamesContainer.style.visibility = 'hidden';
  glasses = [ 'glass1', 'glass2', 'glass3', 'glass4', 'glass5' ];
  glassSequence = [];
  playerSequence = [];
  clearInterval(intervalId); // Clear the interval here
  clearInterval(intervalId2); // Also clear the intervalId2 if it's still running
});


const liquid1 = document.getElementById('liquid1');
const liquid2 = document.getElementById('liquid2');
const liquid3 = document.getElementById('liquid3');
const liquid4 = document.getElementById('liquid4');
const liquid5 = document.getElementById('liquid5');

function startGame(diff) {
  startScreen.style.display = 'none';
  gameScreen.style.display = 'block';
  endScreen.style.display = 'none';

  difficulty = diff;

  score = 0;
  scoreBox.innerHTML = score;
  games = 0;
  gamesBox.innerHTML = games; 
  gamesContainer.style.visibility = 'hidden';

  glasses = [ 'glass1', 'glass2', 'glass3', 'glass4', 'glass5' ];
  glassSequence = [];
  playerSequence = [];
  setPlayedSequenceNO();
  sequenceNumber = playedSequenceNO;
  createGlassSequence(glasses);
}

function setPlayedSequenceNO() {
  let totalGamesElements = document.getElementsByClassName('totalGames');
  if (difficulty === 'easy') {
    playedSequenceNO = 5;
    for (let i = 0; i < totalGamesElements.length; i++) {
      totalGamesElements[i].innerHTML = playedSequenceNO;
    }
  } else if (difficulty === 'medium') {
    playedSequenceNO = 7;
    for (let i = 0; i < totalGamesElements.length; i++) {
      totalGamesElements[i].innerHTML = playedSequenceNO;
    }
  } else if (difficulty === 'hard') {
    playedSequenceNO = 10;
    for (let i = 0; i < totalGamesElements.length; i++) {
      totalGamesElements[i].innerHTML = playedSequenceNO;
    }
  }
}

let glassSequence = [];

let sequenceGenerating = false;

// CreateGlassSequence()
function createGlassSequence(array) {
  sequenceGenerating = true; // Set the flag to true at the start of sequence generation
  const interval = setInterval(() => {
    if (sequenceNumber === 0 || array.length === 0) {
      clearInterval(interval); // Stop the interval if sequenceNumber is reached or if array is empty
      gamesContainer.style.visibility = 'visible';
      console.log("Sequence complete");
      sequenceGenerating = false; // Set the flag back to false when sequence generation completes
      return;
    }

    // Generate a random index
    const randomIndex = Math.floor(Math.random() * array.length);
    // Select the element at the random index
    const randomGlass = array[randomIndex];
    // Add the selected element to the sequence
    glassSequence.push(randomGlass);
    
    // Log the resulting sequence
    console.log(glassSequence);

    // Play sounds or perform other actions as needed
    switch (randomGlass) {
      case 'glass1':
        liquid1.innerHTML = particlesHTML;
        removeParticlesWithFade();
        sound1.play();
        break;
      case 'glass2':
        liquid2.innerHTML = particlesHTML;
        removeParticlesWithFade();
        sound2.play();
        break;
      case 'glass3':
        liquid3.innerHTML = particlesHTML;
        removeParticlesWithFade();
        sound3.play();
        break;
      case 'glass4':
        liquid4.innerHTML = particlesHTML;
        removeParticlesWithFade();
        sound4.play();
        break;
      case 'glass5':
        liquid5.innerHTML = particlesHTML;
        removeParticlesWithFade();
        sound5.play();
        break;
    }

    // Decrement sequenceNumber only if it's greater than 0
    if (sequenceNumber > 0) {
      sequenceNumber--;
    }
  }, 1600);
}

const particlesHTML = `
  <div class="particles" id="particle1"></div>
  <div class="particles" id="particle2"></div>
  <div class="particles" id="particle3"></div>
  <div class="particles" id="particle4"></div>
  <div class="particles" id="particle5"></div>
  <div class="particles" id="particle6"></div>
  <div class="particles" id="particle7"></div>
  <div class="particles" id="particle8"></div> 
`;

let clickAllowed = true; // Flag variable to indicate if clicking is allowed

function disableClickForInterval() {
  clickAllowed = false; // Disable clicking
  setTimeout(() => {
    clickAllowed = true; // Enable clicking after 500ms
  }, 500);
}

glass1.addEventListener('click', () => {

  if (!sequenceGenerating && clickAllowed) {
    disableClickForInterval(); 
    
    playerSequence.push('glass1');
    sound1.play(); 
    console.log(playerSequence);
  
    games++;
    gamesBox.innerHTML = games;
  
    liquid1.innerHTML = particlesHTML;
    removeParticlesWithFade();
  
    // checkSequences(glassSequence, playerSequence);
    console.log(checkSequences(glassSequence, playerSequence));
  }
});

glass2.addEventListener('click', () => {

  if (!sequenceGenerating && clickAllowed) {
    disableClickForInterval(); 

    playerSequence.push('glass2');
    sound2.play(); 
  
    games++
    gamesBox.innerHTML = games;
  
    liquid2.innerHTML = particlesHTML;
    removeParticlesWithFade();
  
    console.log(playerSequence);
    // checkSequences(glassSequence, playerSequence);
    console.log(checkSequences(glassSequence, playerSequence));
  }
});

glass3.addEventListener('click', () => {

  if (!sequenceGenerating && clickAllowed) {
    disableClickForInterval(); 

    playerSequence.push('glass3');
    sound3.play(); 
  
    games++
    gamesBox.innerHTML = games;
    console.log(playerSequence);
  
    liquid3.innerHTML = particlesHTML;
    removeParticlesWithFade();
  
    // checkSequences(glassSequence, playerSequence);
    console.log(checkSequences(glassSequence, playerSequence));
  }
});

glass4.addEventListener('click', () => {

  if (!sequenceGenerating && clickAllowed) {
    disableClickForInterval(); 

    playerSequence.push('glass4');
    sound4.play(); 
  
    games++
    gamesBox.innerHTML = games;
    console.log(playerSequence);
  
    liquid4.innerHTML = particlesHTML;
    removeParticlesWithFade();
  
    // checkSequences(glassSequence, playerSequence);
    console.log(checkSequences(glassSequence, playerSequence));
  }
});

glass5.addEventListener('click', () => {

  if (!sequenceGenerating && clickAllowed) {
    disableClickForInterval(); 

  playerSequence.push('glass5');
  sound5.play(); 

  games++
  gamesBox.innerHTML = games;

  liquid5.innerHTML = particlesHTML;
  removeParticlesWithFade();

  console.log(playerSequence);
  // checkSequences(glassSequence, playerSequence);
  console.log(checkSequences(glassSequence, playerSequence));

  }
});

function checkSequences(array1, array2) {
  let correctCount = 0;
  for (let i = 0; i < Math.min(array1.length, array2.length); i++) {
    if (array1[i] === array2[i]) {
      correctCount++;
    } else {
      break;
    }
  }
  return correctCount; 
}

let intervalId;
let intervalId2;

function gameEndLogic() {
  const correctChildren = checkSequences(glassSequence, playerSequence);
  if (playerSequence.length === playedSequenceNO) {

    intervalId2 = setInterval(gameEndStatement, 1000);

    scoreBox.innerHTML = correctChildren;
    // console.log("Number of correct children in the same order:", correctChildren);
    clearInterval(intervalId); 
  }
}

function gameEndStatement() {
  startScreen.style.display = 'none';
  gameScreen.style.display = 'none';
  endScreen.style.display = 'flex';
}

intervalId = setInterval(gameEndLogic, 1);

function removeParticlesWithFade() {

  void liquid1.offsetWidth;

  const particles = document.querySelectorAll('.particles');
  particles.forEach(particle => {
    particle.style.transition = 'opacity 0.8s ease';
    particle.style.opacity = '0';
  });


  setTimeout(() => {
    liquid1.innerHTML = '';
  }, 800); 
}

Storybook: add different script tags to head based on story tags

We have a storybook setup for the UI components we built – this is working great.

Now, we also want to have stories that are displaying more than a single component and some of them need to add HTML-tags to the header of the preview iframe. I know about the previewHead() function in the storybook-config, but I could only use this globally and not on a per-story-basis …

Ideally, I could add a tag to certain stories and then if the tag is present, add styles/scripts to the head. But as far as I can see, this is not possible… did I miss anything?

React Dev tools error. Unsupported hook in the react-debug-tools package: Missing method in Dispatcher: useHostTransitionStatus

I am building a NextJs app with form inputs. On one of my pages i am getting this error in the components tab of dev tools. Has anyone ever come across this and know how to fix it?
enter image description here

i checked the console for error and i have none except a warning:
Multiple GoTrueClient instances detected in the same browser context. It is not an error, but this should be avoided as it may produce undefined behavior when used concurrently under the same storage key.

How do I change a shape file feature styles before rendering?

The shape file content are:
bbox = array[4]
features = array[97]
|_feature[0] -> [97]
   |_geometry (polygon)
      |_coordinates = array[110] points

None of the polygons have any style assigned.
The layer to which the feature vector is assigned has a default StyleFunction.

What I try to do is to set fill colors to each polygon and to disable the layer default style.

If I comment out the two lines under “Disable default style” all plygon gets the default style. Otherwise, no polygons are drawn at all. What should I do to make it work?

This is my code:

loadshp({
        url: filename,
        encoding: 'UTF-8',
        EPSG: 3857
    },
    function(data) {
        let features = new ol.format.GeoJSON().readFeatures(data, {
            featureProjection: 'EPSG:3857'
        });
        
        /* Assign style to each feature */
        for (let i = 0; i < features.length; i++) {
            let fill = new ol.style.Fill({
                color: 'rgba(100,255,255,0.8)'
            });
            let stroke = new ol.style.Stroke({
                color: '#3399CC',
                width: 1.25
            });
            features[i]['style_'] = new ol.style.Style({
                image: new ol.style.Circle({
                    radius: 5,
                    fill: fill,
                    stroke: stroke
                }),
                fill: fill,
                stroke: stroke,
            });
        }

        let layer = new ol.layer.Vector({
            source: new ol.source.Vector({
                features: features
            })
        });
        
        /* Disable default style */
        layer['styleFunction_'] = undefined;
        layer['style_'] = undefined;

         map = new ol.Map({
            layers: [new ol.layer.Tile({
                        source: new ol.source.OSM()
                    })],
            target: 'map',
            view: new ol.View({})
        });
        
        let source = layer.getSource();
        let extent = source.getExtent();
        map.getView().fit(extent, map.getSize());
                    
        map.addLayer(layer);
    }
);

Regarding issues with VScode [closed]

I was working Web on the visual studio code. But don’t know suddenly when I try to run the code it works fine on the terminal but in the case of the browser it just did not triggered. I even tried to uninstall and install the VScode but nothing happened. Can somebody help me regarding this. I have been trying this for the last few days

This is what I am getting on the browser

Error when seeding a relationship using Prisma 5 and JavaScript

I am trying to seed my prisma db but am having trouble doing so with a user -> Payment relation.

Seeder Code:

export const userSeeder = async (prisma) => {
  const productIds = await getProductIds(prisma);
  const {
    gamingLaptopProductId,
    chairProductId,
    cologneProductId,
  } = productIds;

  console.log(chalk.blue('ABOUT TO RUN BOBBYS SEEDER'));
  const bobby = await prisma.user.upsert({
    where: { email: '[email protected]' },
    update: {},
    create: {
      username: 'bobby',
      email: '[email protected]',
      password: 'bob123',
      first_name: 'Bob',
      last_name: 'Brown',
      role: 'ADMIN',
      created_at: new Date().toISOString(),
      updated_at: new Date().toISOString(),
      deleted: false,
      UserAddress: {
        create: [
          {
            address_type: 'Shipping',
            address: {
              create: {
                address_type: 'Shipping',
                street_address: '123 Fake Street',
                city: 'New York',
                state: 'NY',
                zip_code: '12345',
                country: 'USA',
                created_at: new Date().toISOString(),
                updated_at: new Date().toISOString(),
                deleted: false,
              },
            },
            created_at: new Date().toISOString(),
            updated_at: new Date().toISOString(),
            deleted: false,
          },
          {
            address_type: 'Billing',
            address: {
              create: {
                address_type: 'Billing',
                street_address: '742 Evergreen Terrace',
                city: 'Springfield',
                state: 'OR',
                zip_code: '99898',
                country: 'USA',
                created_at: new Date().toISOString(),
                updated_at: new Date().toISOString(),
                deleted: false,
              },
            },
            created_at: new Date().toISOString(),
            updated_at: new Date().toISOString(),
            deleted: false,
          },
        ],
      },
      comments: {
        create: [
          {
            product_id: gamingLaptopProductId,
            content: 'This is a great Laptop!',
            created_at: new Date().toISOString(),
            updated_at: new Date().toISOString(),
            deleted: false,
          },
          {
            product_id: tshirtProductId,
            content: 'Such a nice shirt',
            created_at: new Date().toISOString(),
            updated_at: new Date().toISOString(),
            deleted: false,
          },
        ],
      },
      ratings: {
        create: [
          {
            product_id: cologneProductId,
            rating: 5,
            created_at: new Date().toISOString(),
            updated_at: new Date().toISOString(),
            deleted: false,
          },
          {
            product_id: tshirtProductId,
            rating: 3,
            created_at: new Date().toISOString(),
            updated_at: new Date().toISOString(),
            deleted: false,
          },
        ],
      },
    },
  });

  if (bobby) {
    console.log(chalk.green('Bobby was created successfully.'));

    await prisma.payment.create({
      data: {
        user: bobby,
        payment_method: 'Credit Card',
        exp_month: 0o1,
        exp_year: 2026,
        card_number: '1233-4567-8901-2292',
        payment_status: 'PENDING',
        created_at: new Date().toISOString(),
        updated_at: new Date().toISOString(),
        deleted: false,
        Order: {
          create: [
            {
              status: 'Shipped',
              total_price: 41.5,
              created_at: new Date().toISOString(),
              updated_at: new Date().toISOString(),
              deleted: false,
              OrderItem: {
                create: [
                  {
                    product_id: chairProductId,
                    quantity: 1,
                    price: 35.99,
                    created_at: new Date().toISOString(),
                    updated_at: new Date().toISOString(),
                    deleted: false,
                  },
                ],
              },
            },
          ],
        },
      },
    });

    console.log(chalk.green('Payment was created successfully.'));
  } else {
    console.error(chalk.red('Bobby was not found.'));
  }

  console.log('[Users w/ Addresses, Orders, Reviews, and Comments seeded successfully]');
};

Relevant Prisma Models:

model User {
  id          String        @id @default(uuid())
  username    String        @unique
  email       String        @unique
  password    String
  first_name  String
  last_name   String?
  created_at  DateTime      @default(now())
  updated_at  DateTime      @updatedAt
  deleted     Boolean       @default(false)
  role        String        @default("USER")
  comments    Comment[]
  ratings     Rating[]
  orders      Order[]
  UserAddress UserAddress[]
  payments    Payment[]
}


model Payment {
  id             String   @id @default(uuid())
  user           User     @relation(fields: [user_id], references: [id])
  user_id        String // Change type to String
  payment_method String // Mock payment method (e.g., "credit card")
  exp_month      Int? // Optional, month of expiration (e.g., 1 for January)
  exp_year       Int? // Optional, year of expiration (e.g., 2024)
  card_number    String? // Optional, masked card number (e.g., "XXXX XXXX XXXX XXXX")
  payment_status String   @default("PROCESSED") // Mock payment status (e.g., "success", "failure")
  created_at     DateTime @default(now())
  updated_at     DateTime @updatedAt
  deleted        Boolean  @default(false)
  Order          Order[]
}

model Order {
  id          String      @id @default(uuid())
  user        User        @relation(fields: [user_id], references: [id])
  user_id     String
  status      String
  total_price Float
  payment     Payment     @relation(fields: [payment_id], references: [id])
  payment_id  String
  created_at  DateTime    @default(now())
  updated_at  DateTime    @updatedAt
  deleted     Boolean     @default(false)
  OrderItem   OrderItem[]
}

model OrderItem {
  id         String   @id @default(uuid())
  order      Order    @relation(fields: [order_id], references: [id])
  order_id   String // Field will exist in db
  product    Product  @relation(fields: [product_id], references: [id])
  product_id String // Field will exist in db
  quantity   Int
  price      Float
  created_at DateTime @default(now())
  updated_at DateTime @updatedAt
  deleted    Boolean  @default(false)
}

All other relations (comments, ratings etc…) all get created properly, I am only having trouble with the payments creation on the user.

If I run npx prisma migrate reset this is the error I get:

ABOUT TO RUN BOBBYS SEEDER
Bobby was created successfully.
PrismaClientValidationError: 
Invalid `prisma.payment.create()` invocation:

{
  data: {
    user: {
      id: "81e533bf-dc27-4b1f-89a1-44384dfa13b1",
      ~~
      username: "bobby",
      email: "[email protected]",
      password: "bob123",
      first_name: "Bob",
      last_name: "Brown",
      created_at: new Date("2024-05-06T14:35:34.112Z"),
      updated_at: new Date("2024-05-06T14:35:34.112Z"),
      deleted: false,
      role: "ADMIN",
?     create?: UserCreateWithoutPaymentsInput | UserUncheckedCreateWithoutPaymentsInput,
?     connectOrCreate?: UserCreateOrConnectWithoutPaymentsInput,
?     connect?: UserWhereUniqueInput
    },
    payment_method: "Credit Card",
    exp_month: 1,
    exp_year: 2026,
    card_number: "1233-4567-8901-2292",
    payment_status: "PENDING",
    created_at: "2024-05-06T14:35:34.117Z",
    updated_at: "2024-05-06T14:35:34.117Z",
    deleted: false,
    Order: {
      create: [
        {
          status: "Shipped",
          total_price: 41.5,
          created_at: "2024-05-06T14:35:34.117Z",
          updated_at: "2024-05-06T14:35:34.117Z",
          deleted: false,
          OrderItem: {
            create: [
              {
                product_id: "581b8e88-080f-4d04-a55d-9db52d4be97a",
                quantity: 1,
                price: 35.99,
                created_at: "2024-05-06T14:35:34.117Z",
                updated_at: "2024-05-06T14:35:34.117Z",
                deleted: false
              }
            ]
          }
        }
      ]
    }
  }
}

Unknown argument `id`. Available options are marked with ?.

This is the error I get when replacing the user object with just the user_id:

ABOUT TO RUN BOBBYS SEEDER
Bobby was created successfully.
PrismaClientValidationError: 
Invalid `prisma.payment.create()` invocation:

{
  data: {
    user_id: "33891012-2c5a-4e8c-91e9-29007c29172b",
    payment_method: "Credit Card",
    exp_month: 1,
    exp_year: 2026,
    card_number: "1233-4567-8901-2292",
    payment_status: "PENDING",
    created_at: "2024-05-06T14:55:47.335Z",
    updated_at: "2024-05-06T14:55:47.335Z",
    deleted: false,
    Order: {
      create: [
        {
          status: "Shipped",
          total_price: 41.5,
          created_at: "2024-05-06T14:55:47.335Z",
          updated_at: "2024-05-06T14:55:47.335Z",
          deleted: false,
          OrderItem: {
            create: [
              {
                product_id: "89fbc564-1af8-494e-84c6-5e1f446f3e59",
                quantity: 1,
                price: 35.99,
                created_at: "2024-05-06T14:55:47.335Z",
                updated_at: "2024-05-06T14:55:47.335Z",
                deleted: false
              }
            ]
          }
        }
      ]
    }
  }
}

Argument `user` is missing.

So naturally I tried removing the id before the create but then it throws the same error about username, then email and so on…if I try to just pass user_id it says missing property user…which is why I am passing the entire bobby user.

I am not sure how to make this work…any ideas would help. Thanks!