Switch with object.keys always return default value

i have a problem with a method, i am trying to get the value of a field errors in Angular forms, and then return a string if there is an error.

  public getFieldError(form: FormGroup, field:string):string | null{

    if(!form) return null

    const errors = form.controls[field].errors || {}
    
      for(const key in Object.keys(errors)) {
        console.log(Object.keys(errors))
        switch(key){
          case 'required':
            return 'required error';
          case 'minlength':
            return 'minlength error';
          default:
            return 'hi' 
        }
      
    }

    return null
  }

when i test the form, console.log(Object.keys(errors)) returns [‘minlength’], so i think the second case, key == ‘minlength’ should activate, but it always returns the default value. Can you tell me what i am doing wrong? Thank you

Issue in creaating react jest test case when using chart.js

I have below test case. Please dont read entire code. (Its not necessary). what i am trying to say i wrote atleast 100times, checked with chatgpt, google bard still not able to make this test case successful. for all the other component all the test cases are becoming successful.
below is my code.(just for reference).

import React, { useEffect, useRef, useState } from 'react';
import { Chart, ChartConfiguration, registerables } from 'chart.js';
import './EmailLineChart.styles.css';
import { useUser } from '../../common/context/context';

const DataLineChart: React.FC = () => {
    const chartRef = useRef<HTMLCanvasElement>(null);
    const chartInstanceRef = useRef<Chart | null>(null);
    const [data, setData] = useState<{ month: string; success: number; failed: number; processing?: number }[]>([]);
    const [downloadFormat, setDownloadFormat] = useState<string>('chart');
    const [filterMonth, setFilterMonth] = useState<string>('');
    const [chartType, setChartType] = useState<'line'|'bar'>('line');

   
    const baseUrl = process.env.REACT_APP_BASE_URL;

    let url = `${baseUrl}/email/reports/count?type=year&tag=${tag}&service_name=${servicename}`;
    const tenantData = useUser();
  

    useEffect(() => {
        const fetchData = async () => {
            try {
                const response = await fetch(url);
                const apiData = await response.json();
                const monthlyReports = apiData.monthlyReports;
            

                if (!monthlyReports) {
                    console.error('No monthlyReports data in API response');
                    return;  // Early return if no monthlyReports data
                }

                const chartData = Object.keys(monthlyReports).map((month) => ({
                    month,
                    success: monthlyReports[month].SUCCESS,
                    failed: monthlyReports[month].FAILED,
                    processing: monthlyReports[month].PROCESSING || 0,
                }));
                // Sort data by month
                chartData.sort((a, b) => new Date(a.month).getTime() - new Date(b.month).getTime());
                setData(chartData);
            } catch (error) {
                console.error('Error fetching data:', error);
            }
        };
        fetchData();
    }, []);
    useEffect(() => {
        if (chartInstanceRef.current) {
            chartInstanceRef.current.destroy();
        }
        if (chartRef.current && downloadFormat === 'chart') {
            Chart.register(...registerables);
            const ctx = chartRef.current.getContext('2d');
            const filteredData = filterMonth ? data.filter((item) => item.month === filterMonth) : data;
            if (ctx) {
                const gradient1 = ctx.createLinearGradient(0, 0, 0, 400);
                gradient1.addColorStop(0, 'rgba(75, 192, 192, 0.6)');
                gradient1.addColorStop(1, 'rgba(75, 192, 192, 0)');
              
                const gradient2 = ctx.createLinearGradient(0, 0, 0, 400);
                gradient2.addColorStop(0, 'rgba(255, 99, 132, 0.6)');
                gradient2.addColorStop(1, 'rgba(255, 99, 132, 0)');
                
                const config: ChartConfiguration<'line'|'bar'> = {
                    type: chartType,
                    data: {
                        labels: filteredData.map((item) => item.month),
                        datasets: [
                            {
                                label: 'Success',
                                data:  filteredData.map((item) => item.success),
                                borderColor:  'rgba(75, 192,198, 0.9)',
                                fill: true,
                                backgroundColor:'rgba(75, 192, 192, 0.3)',
                                pointBackgroundColor: 'rgba(75, 192, 192, 0.9)',
                                pointBorderColor:'rgba(75, 250, 192, 0.9)',
                                pointHoverBackgroundColor: 'rgba(75, 350, 192, 0.9)',
                                pointHoverBorderColor: 'rgba(75, 350, 192, 0.9)',
                                pointHoverRadius: 8,
                                pointHoverBorderWidth: 5,
                                tension: 0.1,
                            },
                            {
                                label: 'Failed',
                                data:  filteredData.map((item) => item.failed),
                                borderColor: 'rgba(255, 99, 132, 0.4)',
                                fill: true,
                                backgroundColor: 'rgba(255, 99, 132, 0.2)',
                                pointBackgroundColor: 'rgba(255, 99, 132, 0.3)',
                                pointBorderColor: 'rgba(255, 99, 132, 0.9)',
                                pointHoverBackgroundColor: 'rgba(255, 99, 132, 0.3)',
                                pointHoverBorderColor: 'rgba(255, 99, 132, 0.3)',
                                pointHoverRadius: 8,
                                pointHoverBorderWidth: 5,
                                tension: 0.1,
                            },
                        ],
                    },
                    options: {
                        responsive: true,
                        animation: {
                            duration: 2000,
                            easing: 'easeInOutBounce',
                        },
                        scales: {
                            x: {
                                title: {
                                    display: true,
                                    text: 'Month',
                                },
                                grid: {
                                    color: 'gray', // change this as needed
                                    display: false,
                                },
                                ticks: {
                                    color: 'black', // change this as needed
                                    font: {
                                        size: 10,
                                    }
                                },
                                stacked:true
                            },
                            y: {
                                title: {
                                    display: true,
                                    text: 'Number of Emails',
                                },
                                ticks: {
                                    color: 'black', // change this as needed
                                    font: {
                                        size: 10,
                                    }
                                },
                                grid: {
                                    color: 'gray', // change this as needed
                                    display: false,
                                },
                                stacked:true,
                            },
                        }
                    }
                    ,                      
                };
                chartInstanceRef.current = new Chart(ctx, config);
            }
        }
          
          
    }, [downloadFormat, data, filterMonth]); 
  
    useEffect(() => {
        if (chartInstanceRef.current) {
            const chart = chartInstanceRef.current;
            chart.data.labels = data.map((item) => item.month);
            chart.data.datasets[0].data = data.map((item) => item.success||0);
            chart.data.datasets[1].data = data.map((item) => item.failed||0);
            chart.update();
        }
    }, [data]);


    
    const filteredData = filterMonth ? data.filter((item) => item.month === filterMonth) : data;
    const isChartSelected = downloadFormat === 'chart';


    return (
        <div className='chart'>
                <canvas ref={chartRef} className='chart-wrapper'></canvas>           
        </div>
    );
};
export default DataLineChart;

Since my code uses custom hook and chart.js so became difficult to write the case, but it is giving error on render only. I could not move forward at all.

I wrote below test case.

import React from 'react';
import { render } from '@testing-library/react';
import { Chart, registerables } from 'chart.js'; // Import Chart.js as usual
import DataLineChart from './DataLineChart';

jest.mock('../../common/context/context', () => ({
  useUser: jest.fn(() => ({ tenantData: { tenantId: 'mockedTenantId' } })),
}));

jest.mock('chart.js')

describe('DataLineChart', () => {
  it('renders without errors', () => {
    render(<DataLineChart />);
  });
});

but error is coming

"TypeError: undefined is not iterable (cannot read property Symbol(symbol.iterator)"

Basically error comes in this line . Chart.register(...registerables); . can anyone of you guide how to mock chart.js. how to do testing of these type of component? I have 95% code coverage and struggling badly for last 10 days. I used many ways to mock chart.js but nothing worked. chart.js I am using 3.9.1 version. if any suggestion to modify code or test case that would be really helpful. I am using jest. i can also provide full version of code if it is helpful in anyway.

Unhandled rejection TypeError: domain.enter is not a function

Unhandled rejection TypeError: domain.enter is not a function
at Child.emit (domain.js:536:10)
at /mnt/c/src/NodeiDocData/server/node_modules/bookshelf/lib/base/events.js:75:17
at Array.forEach ()
at Child.trigger (/mnt/c/src/NodeiDocData/server/node_modules/bookshelf/lib/base/events.js:74:29)
at Builder. (/mnt/c/src/NodeiDocData/server/node_modules/bookshelf/lib/bookshelf.js:544:47)
at Builder.emit (events.js:400:28)
at Builder.emit (domain.js:475:12)
at Runner.query (/mnt/c/src/NodeiDocData/server/node_modules/knex/lib/runner.js:131:18)
at /mnt/c/src/NodeiDocData/server/node_modules/knex/lib/runner.js:40:23
at /mnt/c/src/NodeiDocData/server/node_modules/knex/lib/runner.js:260:24
at processTicksAndRejections (internal/process/task_queues.js:95:5)

getting this error while creating the appointment,
node version:14.21.3
“bluebird”: “^3.5.5”,
“bookshelf”: “^1.2.0”,
“knex”: “^0.20.11”,
“pg”: “^8.3.0”,

code is using the class components in react, we are updating the node 8 to 14 and the some packages

while creating the appointment, the details need to be inserted into the database(postgresql).,
instead of that getting the unhandled error: domain.enter() is not a function.

What is the difference between the following two code blocks

   function greet(name){
  
  let hours = 11;
  let time = "";

if(hours >= 4 && hours < 12 ){
  time = "Good Morning";
} else {
  time = "hi";
}

return `${time}, ${name}`
}

greet("Ali");

The output is correct. It output is “Good morning, Ali”

But when I change the the return statement, just like below. It return ” , Ali”. Even though it should work still work. Could anyone please explain this!

function greet(name){
  
  let hours = 11;
  
  let time = "";

let result = `${time}, ${name}`;

if(hours >= 4 && hours < 12 ){
  time = "Good Morning";
} else {
  time = "hi";
}

return result
  
}

greet("Ali");

Getting “TypeError: Cannot read properties of undefined (reading ‘getProvider’)” when creating a checkout session with Firebase and Stripe

I’m encountering an issue when trying to create a checkout session in my Firebase and Stripe integration. I keep getting the error message “TypeError: Cannot read properties of undefined (reading ‘getProvider’)” in my code.

This is the code that’s responsible for creating the checkout

const {
  createCheckoutSession,
  getStripePayments,
} = require("@stripe/firestore-stripe-payments");
const { getFunctions, httpsCallable } = require("@firebase/functions");
const app = require("../firebase/init.js");

const payments = getStripePayments(app, {
  productsCollection: "products",
  customersCollection: "customers",
});

const loadCheckout = async (priceId) => {
  await createCheckoutSession(payments, {
    price: priceId,
    success_url: window.location.origin,
    cancel_url: window.location.origin,
  })
    .then((snapshot) => window.location.assign(snapshot.url))
    .catch((error) => console.warn(error));
};

const goToBillingPortal = async () => {
  const instance = getFunctions(app, "europe-west");
  const functionRef = httpsCallable(
    instance,
    "ext-firestore-stripe-payments-createPortalLink"
  );

  await functionRef({
    returnUrl: `${window.location.origin}/account`,
  })
    .then(({ data }) => window.location.assign(data.url))
    .catch((error) => console.log(error.message));
};

module.exports = { loadCheckout, goToBillingPortal, payments };

How to Ensure that no Two Adjacent Cells Have Same Color?

I am trying to build a small shuffle the question book app thing. Where I take the input of number of rows and columns along with quantity of each color question book.

What I want is to distribute the colors in a way that no two adjacent cells have same colors and are shuffled enough. What I have now won’t be considering the adjacent cells before placing any color. Can someone please help?

Here is the Fiddle Link https://jsfiddle.net/8h4erzpu/

Here is the JS Code

function distributeBooks() {
  const rows = parseInt(document.getElementById("rows").value);
  const cols = parseInt(document.getElementById("cols").value);
  const whiteCount = parseInt(document.getElementById("whiteCount").value);
  const pinkCount = parseInt(document.getElementById("pinkCount").value);
  const greenCount = parseInt(document.getElementById("greenCount").value);
  const yellowCount = parseInt(document.getElementById("yellowCount").value);

  const totalStudents = rows * cols;
  const colors = [];

  for (let i = 0; i < whiteCount; i++) colors.push("white");
  for (let i = 0; i < pinkCount; i++) colors.push("pink");
  for (let i = 0; i < greenCount; i++) colors.push("green");
  for (let i = 0; i < yellowCount; i++) colors.push("yellow");

  if (colors.length < totalStudents) {
    alert("Not enough colors to distribute to all students!");
    return;
  }

  // Shuffle the colors array to add randomness
  for (let i = colors.length - 1; i > 0; i--) {
    const j = Math.floor(Math.random() * (i + 1));
    [colors[i], colors[j]] = [colors[j], colors[i]];
  }

  const table = document.getElementById("distributionTable");
  table.innerHTML = "";

  for (let row = 0; row < rows; row++) {
    const tr = document.createElement("tr");

    for (let col = 0; col < cols; col++) {
      const td = document.createElement("td");
      td.className = colors.pop();
      tr.appendChild(td);
    }

    table.appendChild(tr);
  }
}

Scroll to top of the chat on whatsapp web using javascript

Im trying to build a chrome extension which scrolls to the top of a whatsapp web chat.

Chat image

This chat has around 100 more messages.

I tried writing this code to scroll to top in the console of the browser, but this code is not working.

var a = document.getElementsByClassName("qh5tioqs")[0]
a.scrollTop = 0;

When I checked value of a.scrollTop, it was already 0.

Issue with “undefined” in URL when working with Cloudinary and MongoDB

I’m currently working on a project using Express.js for the back-end and React for the front-end. The project involves uploading images to Cloudinary, and the Cloudinary URLs are then saved in a MongoDB database. However, I’m encountering an issue where the Cloudinary URL stored in the database contains an “undefined” string at the beginning.

Problem Description:

Here’s the sequence of steps in my project:

Front-end: I select an image to upload, and I correctly obtain the Cloudinary URL for the image using the Cloudinary API.

Back-end (Express.js): I send the Cloudinary URL from the front-end to the server and store it in the MongoDB database.

However, when I later retrieve the Cloudinary URL from the database, it appears as
“undefined” followed by the actual Cloudinary URL
(e.g: “undefinedhttp://res.cloudinary.com/…”).

enter image description here

Backend:

// Back-end code for handling image upload
const express = require('express');
const router = express.Router();
const cloudinary = require('../utils/cloudinary');

// ... (other imports and middleware)

// POST /upload/image
// Upload product images
// Protected route (isAuth middleware checks authentication)

router.post('/image', isAuth, upload.single('image'), async (req, res) => {
  try {
    const file = req.file.path;

    // Upload the image to Cloudinary
    const result = await cloudinary.uploader.upload(file);

    // Check if the image was successfully uploaded to Cloudinary
    if (!result || !result.url) {
      return res.status(500).json({ errors: { msg: 'Image upload failed' } });
    }

    // If the image was uploaded successfully, save the Cloudinary URL in the database
    const imagePath = result.url;

    // ... (other code for saving imagePath to MongoDB)

    res.status(200).json({ imagePath });
  } catch (error) {
    console.error(error);
    res.status(500).json({ errors: { msg: 'Server error' } });
  }
});

// ... (other routes)

Frontend

const uploadImage = async () => {
  // ... (other code)

  try {
    const res = await axios.post(
      `${process.env.REACT_APP_API_BASE_URL}/upload/image`,
      formData,
      { headers: { 'Content-Type': 'multipart/form-data' } }
    );

    // ... (other code)

    return res.data.imagePath;
  } catch (error) {
    // ... (error handling code)
  }
};

Context:

  • The code for handling image uploads to Cloudinary and saving the URL
    to MongoDB appears to be functioning as expected, but the issue
    arises when the URL is retrieved from the database later.

  • The imagePath variable is correctly populated with the Cloudinary URL
    before saving it in the database, and there are no issues when
    sending the URL to the front-end after the image upload.

API return Object Promise and I don’t know how to use it

I need and API that returns a string, but it returns an Object Promise, and I don’t understand and know what to do. Here’s my piece of code. Thank you very much.

This is the API

<?php
    session_start();
    include '../dbconn.php';
    
    $request = file_get_contents('php://input');
    $usuario = $_SESSION['usuario'];
    $query = "SELECT sal FROM usuarios WHERE (usuario = '$usuario' OR email = '$usuario')";
    $result = mysqli_query($conn, $query) or die (mysqli_error($conn));
    $row = mysqli_fetch_array($result);
    echo $row[0];
    $request .= $row[0]; // Concatenamos la contraseña introducida con la sal
    $request = hash('sha512', $request);

    return $request;

This is the JS code:

contrasena = document.getElementById("InputPasswordSignup").value.trim();
        if (contrasena != ""){
            contrasena = hashContrasena(contrasena);
            alert(contrasena);
            sql = sql.concat(" contraseña = '", contrasena).concat("',");
        }

async function hashContrasena(pass){
    res = await fetch('/api/hash_input.php', {
        method: 'POST',
        body: pass
    })
    res = await res.text();
    /*if (res != 'success') {
        alert(res);
    }else{
        alert("Actualización realizada con éxito");
        window.location.reload();
    }*/
    return res;
}

Made an image spoiler button — it functions, but it won’t accept any CSS styling

I followed a tutorial by ABitOfAccess.com on creating an image spoiler for my website. The JS and HTML looks like the following:

<script>
    function unspoiler(spoiler) {
    spoiler.parentNode.classList.add('nospoiler');
    }
</script>

<div class="spoiler">                           
    <button class="spoilerbutton" onclick="unspoiler(this)">Show 18+ Image</button>
    <img src="link" class="artprev">
</div>

CSS:

/*Image spoilering*/
        div.spoiler{
            overflow: hidden;
        position: relative;
        margin: 0;
        padding: 0;
    }
    div.spoiler img {
        vertical-align: bottom;
        filter: blur(20px) grayscale(100%); /*the percentage here is the transition time*/
        transition: 0.3s;
    }
    button.spoilerbutton  {
        position: absolute;
        top: 50%;
        height: 3%;
        line-height: 3%;
        width: 50%;
        padding: 0;
        font-size: 1%;
        margin: 0;
        background-color: #684652;
        color: #260813;
        text-align: center;
        border-radius: 2px;
        cursor: pointer;
    }
    /*hides checkbox*/
    div.spoiler input {
        width: 0;
        height: 0;
    }
/*To remove the filter effect on the image when the checkbox is checked.*/
    div.spoiler input:checked ~ img { 
        filter: none; /* The ~ operator targets images preceded by a checked checkbox in div.spoiler*/
    }
    /*hide our label and checkbox*/
    div.spoiler input:checked, div.spoiler input:checked ~ label {
        display: none;
    }
    div.nospoiler img {
        filter: none;
    }
    div.nospoiler button {
        display: none;
    }

I feel like I’m losing my mind, I can’t tell why anything but the button.spoilerbutton CSS would affect it, and I see nothing in there that would break it.

I’ve modified all of the values, added and removed lines. Nothing changed, just looks like a regular default button. I’ve also tried adding !important after each statement and reordering the CSS.

Broken code in “Secrets of the JavaScript Ninja – 2nd ed.”

Searching for [javascript] “javascript ninja” fragment only gives one result which addresses a later part of the chapter. I think I’m a bit stuck earlier, with the following example (I’ve put together listings 12.3 and 12.4):

<div id="test"><b>Hello</b>, I'm a ninja!</div>
<div id="test2"></div>
<script>
  function getNodes(htmlString, doc, fragment){
    const map = {
"<td":[3,"<table><tbody><tr>","</tr></tbody></table>"],
"<th":[3,"<table><tbody><tr>","</tr></tbody></table>"],
"<tr":[2,"<table><thead>","</thead></table>"],
"<option":[1,"<select multiple>","</select>"],
"<optgroup":[1,"<select multiple>","</select>"],
"<legend":[1,"<fieldset>","</fieldset>"],
"<thead":[1,"<table>","</table>"],
"<tbody":[1,"<table>","</table>"],
"<tfoot":[1,"<table>","</table>"],
"<colgroup":[1,"<table>","</table>"],
"<caption":[1,"<table>","</table>"],
"<col":[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],
    };
    const tagName = htmlString.match(/<w+/);
    let mapEntry = tagName ? map[tagName[0]] : null;
    if (!mapEntry) { mapEntry = [0, " "," " ];}
    let div = (doc || document).createElement("div");
    div.innerHTML = mapEntry[1] + htmlString + mapEntry[2];
    while (mapEntry[0]--) { div = div.lastChild;}
    if (fragment) {
      while (div.firstChild) {
        fragment.appendChild(div.firstChild);
      }
    }
    return div.childNodes;
  }
  document.addEventListener("DOMContentLoaded", () => {
    function insert(elems, args, callback) {
      if (elems.length) {
        const doc = elems[0].ownerDocument || elems[0],
          fragment = doc.createDocumentFragment(),
          scripts = getNodes(args, doc, fragment),
          first = fragment.firstChild;
        if (first) {
          for (let i = 0; elems[i]; i++) {
            callback.call(root(elems[i], first),
              i > 0 ? fragment.cloneNode(true) : fragment);
          }
        }
      }
    }
    const divs = document.querySelectorAll("div");
    insert(divs, "<b>Name:</b>", function (fragment) {
      this.appendChild(fragment);
    });
    insert(divs, "<span>First</span> <span>Last</span>",
      function (fragment) {
        this.parentNode.insertBefore(fragment, this);
      });
  });
</script>

There’s a few things which are unclear to me:

  1. The code doesn’t work because root, used in callback.call(root(elems[i], first), i > 0 ? fragment.cloneNode(true) : fragment); has never been defined.
  2. From appendChild‘s documentation, from some experiment, a from the simple fact that the while (div.firstChild) loop would otherwise run endlessly, I deduce that div has no children by the time it gets to return div.childNodes;, so was that line maybe meant to be return fragment;?
  3. scripts is defined but never used/mentined in the example whatsoever, so why is it there? Can I just get rid of it? Or was it meant to be used in some way?

How can I fix the code?

How to intercept/mock a function called by an eventListener

I am learning about unit testing and I have been implementing it into my current project with success somewhat, using vitest.

But I don’t really know how to tackle this situation, let’s say that I have a listener on a button that on clicking, would fire a function:

    $('.dropdown-item.dataItem').on('click', function() {showData(retrievedData, $(this).text().trim())});

This is part of a bigger function, but I already tested the other parts of it successfully. For this part, I wanted to be sure that “should fire showData when user clicks on it”.

So I wrote this on my test file:

// The only way I managed to intercept top functions imported was this
const optionsFunctions = await import('../../options.js');

test('should call showData when a new dataItem is selected', ()=> {
        // Arrange
        const spyShowData = vi.spyOn(optionsFunctions, 'showData');

        // Act 
        console.log($('.dropdown-item.dataItem')[0].click());
        console.log(spyshowData.mock.calls);

    });

With this, I get 0 calls from the mocked function (but it is executed on the actual file, so I get duplicated). I’m not sure the correct approach in this cases, should I not bother with testing this stuff?
And in case I should, how am I supposed to be sure it’s being correctly implemented? maybe I have to intercept the clicking function itself? but that would be changing too much the test itself.

if I execute addLanguages() directly, the spy gets the call count, but if it happens with the event listener, it doesn’t, why is that?

Thanks

Why isn’t my ore generator generating ore [Minecraft 1.20]

Here is the code I have currently:

ModConfiguredFeatures.java:

package net.KaiHallow.magicalcraft.worldgen;

import net.KaiHallow.magicalcraft.block.ModBlocks;
import net.minecraft.core.registries.Registries;
import net.minecraft.data.worldgen.BootstapContext;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.tags.BlockTags;
import net.minecraft.world.level.levelgen.feature.ConfiguredFeature;
import net.minecraft.world.level.levelgen.feature.Feature;
import net.minecraft.world.level.levelgen.feature.configurations.FeatureConfiguration;
import net.minecraft.world.level.levelgen.feature.configurations.OreConfiguration;
import net.minecraft.world.level.levelgen.structure.templatesystem.RuleTest;
import net.minecraft.world.level.levelgen.structure.templatesystem.TagMatchTest;

import java.util.List;

//This is just to be able to use the variable in a way that keeps the code cleaner and less confusing
import static net.KaiHallow.magicalcraft.MagicalCraft.MOD_ID;

public class ModConfiguredFeatures
{
    public static final ResourceKey<ConfiguredFeature<?,?>> LIGHTNING_CRYSTAL_ORE = registerKey("lightning_crystal_ore");
    public static final ResourceKey<ConfiguredFeature<?,?>> DEEPSLATE_LIGHTNING_CRYSTAL_ORE = registerKey("deepslate_lightning_crystal_ore");

    public static ResourceKey<ConfiguredFeature<?,?>> registerKey(String name)
    {
        return ResourceKey.create(Registries.CONFIGURED_FEATURE, new ResourceLocation(MOD_ID, name));
    }

    public static void bootstrap(BootstapContext<ConfiguredFeature<?, ?>> context)
    {
        RuleTest stonereplaceables = new TagMatchTest(BlockTags.STONE_ORE_REPLACEABLES);
        RuleTest deepslatereplaceables = new TagMatchTest(BlockTags.DEEPSLATE_ORE_REPLACEABLES);
        register(context, LIGHTNING_CRYSTAL_ORE, Feature.ORE, new OreConfiguration(stonereplaceables, ModBlocks.LIGHTNING_CRYSTAL_ORE.get().defaultBlockState(), 8, 0.2F));
        register(context, DEEPSLATE_LIGHTNING_CRYSTAL_ORE, Feature.ORE, new OreConfiguration(deepslatereplaceables, ModBlocks.DEEPSLATE_LIGHTNING_CRYSTAL_ORE.get().defaultBlockState(), 8, 0.5F));
    }

    public static <FC extends FeatureConfiguration, F extends Feature<FC>> void register(BootstapContext<ConfiguredFeature<?, ?>> context,
                                                                                         ResourceKey<ConfiguredFeature<?, ?>> key, F feature, FC config) {
        context.register(key, new ConfiguredFeature<>(feature, config));
    }
}

ModPlacementFeatures.java:

package net.KaiHallow.magicalcraft.worldgen;

import net.minecraft.core.Holder;
import net.minecraft.core.HolderGetter;
import net.minecraft.core.registries.Registries;
import net.minecraft.data.worldgen.BootstapContext;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.level.levelgen.VerticalAnchor;
import net.minecraft.world.level.levelgen.feature.ConfiguredFeature;
import net.minecraft.world.level.levelgen.placement.*;

import java.util.List;

import static net.KaiHallow.magicalcraft.MagicalCraft.MOD_ID;

public class ModPlacementFeatures
{
    public static final ResourceKey<PlacedFeature> LIGHTNING_CRYSTAL_ORE_UPPER = registerKey("lightning_crystal_ore_upper");
    public static final ResourceKey<PlacedFeature> LIGHTNING_CRYSTAL_ORE_MIDDLE = registerKey("lightning_crystal_ore_middle");
    public static final ResourceKey<PlacedFeature> LIGHTNING_CRYSTAL_ORE_LOWER = registerKey("lightning_crystal_ore_lower");

    private static List<PlacementModifier> orePlacement(PlacementModifier count, PlacementModifier heightRange) {
        return List.of(count, InSquarePlacement.spread(), heightRange, BiomeFilter.biome());
    }

    private static List<PlacementModifier> commonOrePlacement(int pCount, PlacementModifier pHeightRange) {
        return orePlacement(CountPlacement.of(pCount), pHeightRange);
    }

    private static List<PlacementModifier> rareOrePlacement(int pChance, PlacementModifier pHeightRange) {
        return orePlacement(RarityFilter.onAverageOnceEvery(pChance), pHeightRange);
    }

    public static void bootstrap(BootstapContext<PlacedFeature> context)
    {
        HolderGetter<ConfiguredFeature<?,?>> holderGetter = context.lookup(Registries.CONFIGURED_FEATURE);

        register(context, LIGHTNING_CRYSTAL_ORE_UPPER, holderGetter.getOrThrow(ModConfiguredFeatures.LIGHTNING_CRYSTAL_ORE), commonOrePlacement(90, HeightRangePlacement.triangle(VerticalAnchor.absolute(150), VerticalAnchor.absolute(319))));
        register(context, LIGHTNING_CRYSTAL_ORE_MIDDLE, holderGetter.getOrThrow(ModConfiguredFeatures.LIGHTNING_CRYSTAL_ORE), commonOrePlacement(40, HeightRangePlacement.triangle(VerticalAnchor.absolute(0), VerticalAnchor.absolute(150))));
        register(context, LIGHTNING_CRYSTAL_ORE_LOWER, holderGetter.getOrThrow(ModConfiguredFeatures.DEEPSLATE_LIGHTNING_CRYSTAL_ORE), commonOrePlacement(15, HeightRangePlacement.triangle(VerticalAnchor.absolute(-63), VerticalAnchor.absolute(-1))));
    }

    public static ResourceKey<PlacedFeature> registerKey(String name)
    {
        return ResourceKey.create(Registries.PLACED_FEATURE, new ResourceLocation(MOD_ID, name));
    }

    public static void register(BootstapContext<PlacedFeature> context, ResourceKey<PlacedFeature> key, Holder<ConfiguredFeature<?, ?>> configuredFeature, List<PlacementModifier> placements) {
        context.register(key, new PlacedFeature(configuredFeature, List.copyOf(placements)));
    }

    public static void register(BootstapContext<PlacedFeature> context, ResourceKey<PlacedFeature> key, Holder<ConfiguredFeature<?, ?>> configuredFeatures, PlacementModifier... placements) {
        register(context, key, configuredFeatures, List.of(placements));
    }
}

ModWorldGenerator.java

package net.KaiHallow.magicalcraft.datagen;

import net.KaiHallow.magicalcraft.worldgen. ModConfiguredFeatures;
import net.KaiHallow.magicalcraft.worldgen. ModPlacementFeatures;
import net.minecraft.core.HolderLookup;
import net.minecraft.core.RegistrySetBuilder;
import net.minecraft.core.registries.Registries;
import net.minecraft.data.PackOutput;
import net.minecraftforge.common.data.DatapackBuiltinEntriesProvider;

import java.util.Set;
import java.util.concurrent.CompletableFuture;

import static net.KaiHallow.magicalcraft.MagicalCraft.MOD_ID;

public class ModWorldGenerator extends DatapackBuiltinEntriesProvider
{
    public static final RegistrySetBuilder BUILDER = new RegistrySetBuilder()
            .add(Registries.CONFIGURED_FEATURE, ModConfiguredFeatures::bootstrap)
            .add(Registries.PLACED_FEATURE, ModPlacementFeatures::bootstrap);
    public ModWorldGenerator(PackOutput output, CompletableFuture<HolderLookup.Provider> registries) {
        super(output, registries, BUILDER, Set.of(MOD_ID));
    }
}

My problem is while it creates the json files, everything with said json files being as they should be, the ore refuses to generate, however just in case there is something wrong in them here they are:

worldgen > configured_feature > lightning_crystal_ore.json

{
  "type": "minecraft:ore",
  "config": {
    "discard_chance_on_air_exposure": 0.2,
    "size": 8,
    "targets": [
      {
        "state": {
          "Name": "magicalcraft:lightning_crystal_ore"
        },
        "target": {
          "predicate_type": "minecraft:tag_match",
          "tag": "minecraft:stone_ore_replaceables"
        }
      }
    ]
  }
}

worldgen > configured_feature > deepslate_lightning_crystal_ore.json

{
  "type": "minecraft:ore",
  "config": {
    "discard_chance_on_air_exposure": 0.5,
    "size": 8,
    "targets": [
      {
        "state": {
          "Name": "magicalcraft:deepslate_lightning_crystal_ore"
        },
        "target": {
          "predicate_type": "minecraft:tag_match",
          "tag": "minecraft:deepslate_ore_replaceables"
        }
      }
    ]
  }
}

worldgen > placed_feature > lightning_crystal_ore_upper.json

{
  "feature": "magicalcraft:lightning_crystal_ore",
  "placement": [
    {
      "type": "minecraft:count",
      "count": 90
    },
    {
      "type": "minecraft:in_square"
    },
    {
      "type": "minecraft:height_range",
      "height": {
        "type": "minecraft:trapezoid",
        "max_inclusive": {
          "absolute": 319
        },
        "min_inclusive": {
          "absolute": 150
        }
      }
    },
    {
      "type": "minecraft:biome"
    }
  ]
}

worldgen > placed_feature > lightning_crystal_ore_middle.json

{
  "feature": "magicalcraft:lightning_crystal_ore",
  "placement": [
    {
      "type": "minecraft:count",
      "count": 40
    },
    {
      "type": "minecraft:in_square"
    },
    {
      "type": "minecraft:height_range",
      "height": {
        "type": "minecraft:trapezoid",
        "max_inclusive": {
          "absolute": 150
        },
        "min_inclusive": {
          "absolute": 0
        }
      }
    },
    {
      "type": "minecraft:biome"
    }
  ]
}

worldgen > placed_feature > lightning_crystal_ore_lower.json

{
  "feature": "magicalcraft:deepslate_lightning_crystal_ore",
  "placement": [
    {
      "type": "minecraft:count",
      "count": 15
    },
    {
      "type": "minecraft:in_square"
    },
    {
      "type": "minecraft:height_range",
      "height": {
        "type": "minecraft:trapezoid",
        "max_inclusive": {
          "absolute": -1
        },
        "min_inclusive": {
          "absolute": -63
        }
      }
    },
    {
      "type": "minecraft:biome"
    }
  ]
} 

can someone tell me what is wrong, why it won’t generate? (Note: I have the blocks registered and tags, models, and blockstates made for them and everything, I followed a tutorial for all that) I’ve looked everywhere but I cannot seem to find a solution, there are no errors, game boots up just fine without a hitch, and the ore just will not generate.

I’ve tried this, I’ve tried messing with the registration where the blocks get registered, I’ve tried messing with the tags, and nothing. As the question states, this was supposed to make my custom ore generate in the world but it won’t generate, it exists in the creative inventory and can be placed and destroyed, but it won’t generate.