How to override a mocked method in a jest.mock’d module in an e2e test with jest.spyOn

I have a mock prisma service in the the __mocks__ folder and am using it in unit tests like this, which works as expected.

// __mocks__/prisma.service.ts

@Injectable()
export class PrismaService {
  foo = {
    findUnique: jest.fn().mockResolvedValue({ name: 'foo-mock' })
  }
}
// foo.service.spec.ts

jest.mock('path/to/prisma.service.ts');

...

it('', async () => {
  const actual = await fooService.findOne(123);
  expect(actual).toEqual({ name: 'foo-mock' });
});

it('', async () => {
  jest.spyOn(prismaService.foo, 'findUnique').mockResolvedValue({ name: 'foo-spy' });
  const actual = await fooService.findOne(123);
  expect(actual).toEqual({ name: 'foo-spy' });
});

However, when I do this in an e2e test, the implementation in mocks doesn’t get overridden with the spyOn like it does in unit tests.

// foo.service.e2e-spec.ts

jest.mock('path/to/prisma.service.ts');

beforeEach(async () => {
  const module = await Test.createTestingModule({
    imports: [AppModule]
  }).compile();

  app = module.createNestApplication();
  await app.init();

  prismaServie = app.get<PrismaService>(PrismaService);
  
});

// Fails because name is still 'foo-mock'
it('', () => {
  jest.spyOn(prismaService.foo, 'findUnique').mockResolvedValue({ name: 'foo-spy' });

  return request(app.getHttpServer())
    .get('/foo/123')
    .expect(({ body }) => {
      expect(body).toEqual({ name: 'foo-spy' })
    });
});

Why does it not behave the same as in the unit tests?

Ghost AI not moving through intersections (Phaser 3, PacMan)

I am trying to make a pac_man game with Phaser 3. I have implemented the pac_man movement, however, I really need help with the ghost AI. The ghost is moving my its self, however, it is not passing through any intersections. Like, it only moves in a different direction when it collides with something else. I am trying to fix this, and yet I don’t know how. I am using physics, with arcade. Here is some of the code:

newDirections(sprite) {
        let directions = ['left', 'right', 'down', 'up']
        let object = sprite.body.blocked
        let keys = Object.keys(object)
        let new_directions = []
        for (let i = 1; i < keys.length; i++) {
            if (object[keys[i]] == false ) {
                new_directions.push(keys[i])
            }
        }
        return new_directions
    }

This function is supposed to see any other paths the ghost can take. I am highly depended on sprite.body.blocked for this (especially since I am using tiles), but it only reads when the sprite is colliding with something else. Any help will be heavily appreciated. Thank you so much in advance!

webpack indiscriminately bundling files that are not used

I have a React app that imports a library.

In the imported library, there is a function, foo, that has this line of code:

require(`./folder/${file_name}`)

The problem is, this function foo is never called and will never be called.

Yet, all of the files inside of ./folder is bundled anyways, which needlessly increases the bundle size.

How can I get webpack to not bundle the files in this folder?

Do elements positioned with percentage does not have transition effect?

I have literally taken days to understand percentPosition given in the article Masonry. I am still not sure if I understood it correctly or not. It is mentioned in article that

Sets item positions in percent values, rather than pixel values.
percentPosition: true works well with percent-width items, as items
will not transition their position on resize.

What I clearly understood is that items positioned with percent values works well when items width are set through percent. Now the the following part where I was struggling to understand which is

as items will not transition their position on resize

After reading and experimenting a lot, I have understood that transition does not happen when elements are positioned with percentage while with elements position with pixel values transition do happen (not aware of the reason)

I have just written a small code to demonstrate my understanding. Please let me know If my understanding aligned with the article and it is correct or not.

Basically there are three divs: bigdiv(parent div), rel-div(positioned with percent values) and fix-div(positioned with pixel). When parent div‘s width is 600px or greater,I relocated fix-div to new position and we can see transition effect on this pixel positioned element. While there is no transition effect no matter what width I set for parent width through input.

o      = document.querySelector(".bigdiv")
fixDiv = document.querySelector(".fix-div")
inp    = document.querySelector("#inp")
inp.addEventListener('change', e => {
  o.style.width = e.target.value + "px"
})
const resizeObserver = new ResizeObserver(() => {
  console.log('Width:', o.offsetWidth, 'Height:', o.offsetHeight);
  if (o.offsetWidth >= 600) {
    fixDiv.style.left = "120px"
  } else {
    fixDiv.style.left = "20px"
  }
});
resizeObserver.observe(o)
.bigdiv {
  height: 200px;
  width: 200px;
  overflow: auto;
  resize: horizontal;
  position: relative;
  background-color: aqua;
}

.rel-div {
  position: absolute;
  top: 10%;
  left: 20%;
  height: 50px;
  background-color: red;
  width: 50px;
  transition: left ease 1s;
}

.fix-div {
  position: absolute;
  top: 20px;
  left: 20px;
  height: 50px;
  background-color: blue;
  width: 50px;
  transition: left ease 1s;
}
<div class="bigdiv">
  <div class="fix-div"></div>
  <div class="rel-div"></div>
</div>
<br>
<lable>Width:</lable>
<input type="number" name="" id="inp">

I was going through Masonry JS article. I percentPosition

CSS @import causing race condition with SVG Text dimensions

  • I have a scenario where I’m dynamically adding elements to the DOM
  • The elements being added are SVG elements (of various types)
  • In the case of SVGTextElements, I have layout code which is going to look at the bounding box of the text (getBBox()) to determine where it should be positioned
  • I am also using external Fonts, imported in CSS using @import

It seems that the font download is completing after the initial page load, so the bounding box of the SVGTextElement is returning incorrect values.

I have tried all sorts of combinations of waiting for load and DOMContentLoaded in the HTML, but these don’t appear to encompass css downloaded using @import.

I have a working repro of the issue here:

https://codepen.io/jasonpolites/pen/PwYKOyo?editors=1111

If you click the link in the codepen sample, it will load the sample in a new window. This initial “new window” load will display bounding box data that is incorrect. That is, it’s (probably) correct for the font data at the time the measurement is taken, but ultimately incorrect based on the imported font. If you then just refresh the page, it will show the correct values.

I could download the font files and serve them locally, but I’m hoping there’s a solution which means I don’t have to do that.

Are there any tricks to ensure @import statements are fully resolved prior to code executing?

Apps Script bundling operations in a prescribed way using flush()

There’s a apps script function I wrote, loadAccount() that moves data within multiple sheets, however Apps Script is bundling the operations in a way not optimal for user experience. Essentially what happens is that apps script is bundling everything up until the first categorySheet.getRange() call at the end. I noticed this in testing by undoing the script operation and observing that more than one undo is required to revert the changes. I want only one undo to be required to undo all changes in this function. Calling SpreadsheetApp.flush() at the end does not resolve this issue. I have another function, importData() that does not have this problem. I plan on adding more sheet operations for loadAccount() so I’d like to get to the bottom of this issue.

Why is the problem I’m observing in loadAccount() not happenning in importData()?

How can this be addressed?

function loadAccount() {
  let account2Load = "Acc1";
  if (account2Load == "") { return "<span style="font-weight: bold; color: red">Account Not Selected!</span>"; }
  if (!isNaN(account2Load)) { return "<span style="font-weight: bold; color: red">Account Must Be A Word!</span>";}
  if (!_account_contains(account2Load)) { return "<span style="font-weight: bold; color: red">Account Doesn't Exists!</span>"; }  
  
  const summarySheet          = commonFields().summarySheet;
  const transactionSheet      = commonFields().transactionSheet;
  const categorySheet         = getAllCategories().sheet
  const billSheet             = getAllBills().sheet;
  const targetSheet           = getAllTargets().sheet;
  const debtSheet             = getAllDebts().sheet;
  const creditSheet           = getAllCredits().sheet;
  const archiveSheet          = getAllArchives().sheet;
  const noteSheet             = getAllNotes().sheet;
  const summaryStartRow       = _summary_start_row();
  const summaryStartColumn    = _summary_start_column();
  const categoryColumn        = _category_start_column();
  const categoryElements      = _category_num_elements();
  const transactionColumn     = _transaction_start_column();
  const transactionElements   = _transaction_num_elements();
  const startRow              = commonFields().startRow;
  const accountRange          = commonFields().accountRange;
  const accountTitleRange     = commonFields().accountTitleRange;
  const transactionRange      = commonFields().transactionRange;
  const startBalanceRange     = commonFields().startBalanceRange;
  const inflowCarryoverRange  = commonFields().inflowCarryoverRange;
  const inflowAdjustRange     = commonFields().inflowAdjustRange;
  const categoryRange         = getAllCategories().categorySheetRange;
  const numAccounts           = callGetAllAccountVals().length;
  const startBalance          = summarySheet.getRange(startBalanceRange).getValue();
  const inflows               = summarySheet.getRange(commonFields().inflows).getValues(); //REMEMBER TO REFACTOR INFLOWS ELSEWHERE!!!!!!!!!!
  const accountTitle          = summarySheet.getRange(accountTitleRange).getValue();
  const transactions          = transactionSheet.getRange(transactionRange).getValues();
  const categories            = categorySheet.getRange(categoryRange).getValues();
  let accounts                = summarySheet.getRange(accountRange).getValues().filter(account => account[0] != "");
  let index2Load              = accounts.map(row => row[0]).indexOf(account2Load);
  let transactionsPerAccount  = transactionSheet.getRange(startRow, transactionColumn, transactionSheet.getMaxRows() - startRow + 1, transactionElements * numAccounts).getValues();
  let categoriesPerAccount    = categorySheet.getRange(startRow, categoryColumn, categorySheet.getMaxRows() - startRow + 1, categoryElements * numAccounts).getValues();
 
  const startBalance2Load       = accounts[index2Load][1];
  const inflowCarryover2Load    = accounts[index2Load][2];
  const inflowAdjustment2Load   = accounts[index2Load][3];
  const transactions2Load       = transactionsPerAccount.map(row => row.splice(index2Load * transactionElements, transactionElements));
  const categories2Load         = categoriesPerAccount.map(row => row.splice(index2Load * categoryElements, categoryElements));

  accounts.splice(index2Load, 1); 
  accounts.push([accountTitle, startBalance, inflows[0], inflows[2]]);
  for (let i = 0; i < transactionsPerAccount.length; i++) { transactionsPerAccount[i].push(...transactions[i]); }
  for (let i = 0; i < categoriesPerAccount.length; i++) { categoriesPerAccount[i].push(...categories[i]); }

  summarySheet.getRange(accountTitleRange).setValue(account2Load);
  summarySheet.getRange(startBalanceRange).setValue(startBalance2Load);
  summarySheet.getRange(inflowCarryoverRange).setValue(inflowCarryover2Load);
  summarySheet.getRange(inflowAdjustRange).setValue(inflowAdjustment2Load);
  summarySheet.getRange(summaryStartRow, summaryStartColumn, accounts.length, accounts[0].length).setValues(accounts); 
  transactionSheet.getRange(transactionRange).setValues(transactions2Load);
  transactionSheet.getRange(startRow, transactionColumn, transactionsPerAccount.length, transactionsPerAccount[0].length).setValues(transactionsPerAccount);
  categorySheet.getRange(categoryRange).setValues(categories2Load);
  categorySheet.getRange(startRow, categoryColumn, categoriesPerAccount.length, categoriesPerAccount[0].length).setValues(categoriesPerAccount);

  SpreadsheetApp.flush();
  
  return "<span style="font-weight: bold">" + '"'+  account2Load + "" Account Loaded</span>";
}

This one works as intended:

function importData() {
  let ui = SpreadsheetApp.getUi();

  let result = ui.alert(
    "Please confirm",
    "Are you sure you want to import?",
    ui.ButtonSet.YES_NO,
  );

  // Process the user's response.
  if (result == ui.Button.NO) {
    // User clicked "No".
    ui.alert("Import cancelled.");
    return;
  }

  const destSummarySheet      = commonFields().summarySheet;
  const destCategoriesSheet   = getAllCategories().sheet;
  const destBillsSheet        = getAllBills().sheet;
  const destTargetsSheet      = getAllTargets().sheet;
  const destCreditsSheet      = getAllCredits().sheet;
  const destDebtsSheet        = getAllDebts().sheet;
  const destArchiveSheet      = getAllArchives().sheet;
  const destNoteSheet         = getAllNotes().sheet;
  const sourceIDRange         = commonFields().sourceIDRange;
  const sourceSheetID         = destSummarySheet.getRange(sourceIDRange).getValue();

  if (sourceSheetID == "") { ui.alert("Copy destination ID into source ID for import!"); return; }
  
  const source                = SpreadsheetApp.openById(sourceSheetID);
  const sourceSummarySheet    = source.getSheets().find(sheet => sheet.getSheetName() == "Summary");
  const sourceCategoriesSheet = source.getSheets().find(sheet => sheet.getSheetName() == "Categories");
  const sourceBillsSheet      = source.getSheets().find(sheet => sheet.getSheetName() == "Monthly Bills");
  const sourceTargetsSheet    = source.getSheets().find(sheet => sheet.getSheetName() == "Savings Targets");
  const sourceCreditsSheet    = source.getSheets().find(sheet => sheet.getSheetName() == "Credit Accounts");
  const sourceDebtsSheet      = source.getSheets().find(sheet => sheet.getSheetName() == "Debts");
  const sourceNotesSheet      = source.getSheets().find(sheet => sheet.getSheetName() == "Notes");

  const startRow                      = commonFields().startRow;
  const startColumn                   = commonFields().startColumn;
  const startBalanceRange             = commonFields().startBalanceRange;
  const endBalanceRange               = commonFields().endBalanceRange;
  const accountTitleRange             = commonFields().accountTitleRange;
  const inflowAdjustRange             = commonFields().inflowAdjustRange;
  const adjustmentRange               = commonFields().adjustmentRange;
  const categorySheetRange            = getAllCategories().categorySheetRange;
  const catOverflowValsRange          = getAllCategories().overflowValsRange;
  const billSheetRange                = getAllBills().billSheetRange;
  const billOverflowValsRange         = getAllBills().overflowValsRange;
  const targetSheetRange              = getAllTargets().targetSheetRange;
  const targetOverflowValsRange       = getAllTargets().overflowValsRange;
  const creditSheetRange              = getAllCredits().creditSheetRange;
  const creditBalanceRange            = getAllCredits().creditBlanceRange;
  const debtSheetRange                = getAllDebts().debtSheetRange;
  const debtRemainingBalanceValsRange = getAllDebts().remainingBalanceRange;
  const archiveCategoryRange          = getAllArchives().categoryArchiveRange;
  const archiveBillRange              = getAllArchives().billArchiveRange;
  const archiveTargetRange            = getAllArchives().targetArchiveRange;
  const archiveCreditRange            = getAllArchives().creditArchiveRange;
  const archiveDebtRange              = getAllArchives().debtArchiveRange;
  const notesCategoryRange            = getAllNotes().categoryRange;
  const notesBillRange                = getAllNotes().billRange;
  const notesTargetRange              = getAllNotes().targetRange;
  const notesCreditRange              = getAllNotes().creditRange;
  let creditBillRange                 = getAllBills().creditRange;
  let creditTargetRange               = getAllTargets().creditRange;
  let billRule                        = destBillsSheet.getRange(creditBillRange).getDataValidation();
  let targetRule                      = destTargetsSheet.getRange(creditTargetRange).getDataValidation();

  let sourceEndBalance              = sourceSummarySheet.getRange(endBalanceRange).getValue();
  let sourceTitle                   = sourceSummarySheet.getRange(accountTitleRange).getValue();
  let sourceCarryoverAdjustment     = sourceSummarySheet.getRange(inflowAdjustRange).getValue();
  let sourceLumpAdjustment          = sourceSummarySheet.getRange(adjustmentRange).getValue();

  let sourceTransactionCategories   = sourceCategoriesSheet.getRange(categorySheetRange).getValues().filter(category => category[0] != "");
  let sourceCatOverflowVals         = sourceCategoriesSheet.getRange(catOverflowValsRange).getValues().filter(overflow => overflow != "").flat();
  let catZeros                      = Array(sourceTransactionCategories.length).fill().map(() => Array(1).fill(0)).flat(); //Fill allocation amounts with zeros

  for (let i = 0; i < sourceTransactionCategories.length; i++) { 
    sourceTransactionCategories[i][1] = sourceCatOverflowVals[i];
    sourceTransactionCategories[i][2] = catZeros[i];
  }
  
  let sourceTransactionBills  = sourceBillsSheet.getRange(billSheetRange).getValues().filter(bill => bill[0] != "");
  let sourceBillOverflowVals  = sourceBillsSheet.getRange(billOverflowValsRange).getValues().filter(overflow => overflow != "").flat();
  let billZeros               = Array(sourceTransactionBills.length).fill().map(() => Array(1).fill(0)).flat(); //Fill allocation amounts with zeros

  for (let i = 0; i < sourceTransactionBills.length; i++) { 
    sourceTransactionBills[i][3] = sourceBillOverflowVals[i];
    sourceTransactionBills[i][4] = billZeros[i];
  }

  let sourceTransactionTargets  = sourceTargetsSheet.getRange(targetSheetRange).getValues().filter(target => target[0] != "");
  let sourceTargetOverflowVals  = sourceTargetsSheet.getRange(targetOverflowValsRange).getValues().filter(overflow => overflow != "").flat();
  let targetZeros               = Array(sourceTransactionTargets.length).fill().map(() => Array(1).fill(0)).flat(); //Fill allocation amounts with zeros

  for (let i = 0; i < sourceTransactionTargets.length; i++) { 
    sourceTransactionTargets[i][5] = sourceTargetOverflowVals[i];
    sourceTransactionTargets[i][6] = targetZeros[i];
  }

  let sourceCreditAccounts  = sourceCreditsSheet.getRange(creditSheetRange).getValues().filter(credit => credit[0] != "");
  let sourceCreditBalances  = sourceCreditsSheet.getRange(creditBalanceRange).getValues().filter(balance => balance[0].toString().length > 0); 
  let creditZeros           = Array(sourceCreditAccounts.length).fill().map(() => Array(1).fill(0)).flat(); //Fill allocation amounts with zeros
  let sourceAdjustmentSum   = sourceCreditAccounts.map(row => row[2]).reduce((accum, curr) => accum + curr, 0);

  for (let i = 0; i < sourceCreditAccounts.length; i++) {
    sourceCreditAccounts[i][4] = sourceCreditBalances[i][3];
    sourceCreditAccounts[i][3] = sourceCreditAccounts[i][3] + sourceCreditBalances[i][0] - sourceCreditAccounts[i][2];
    sourceCreditAccounts[i][2] = creditZeros[i];
  }

  let sourceNoteCats    = sourceNotesSheet.getRange(notesCategoryRange).getDisplayValues();
  let sourceNoteBills   = sourceNotesSheet.getRange(notesBillRange).getDisplayValues();
  let sourceNoteTargets = sourceNotesSheet.getRange(notesTargetRange).getDisplayValues();
  let sourceNoteCredits = sourceNotesSheet.getRange(notesCreditRange).getDisplayValues();

  let sourceDebts                 = sourceDebtsSheet.getRange(debtSheetRange).getValues().filter(debt => debt[0] != "");
  let sourceRemainingBalanceVals  = sourceDebtsSheet.getRange(debtRemainingBalanceValsRange).getValues().filter(endBalance => endBalance != "").flat();

  for (let i = 0; i < sourceDebts.length; i++) { sourceDebts[i][2] = sourceRemainingBalanceVals[i]; }

  destBillsSheet.getRange(creditBillRange).setDataValidation(null);
  destTargetsSheet.getRange(creditTargetRange).setDataValidation(null);
  destCategoriesSheet.getRange(categorySheetRange).clearContent();
  destBillsSheet.getRange(billSheetRange).clearContent();
  destTargetsSheet.getRange(targetSheetRange).clearContent();
  destCreditsSheet.getRange(creditSheetRange).clearContent();
  destDebtsSheet.getRange(debtSheetRange).clearContent();
  destArchiveSheet.getRange(archiveCategoryRange).clearContent();
  destArchiveSheet.getRange(archiveBillRange).clearContent();
  destArchiveSheet.getRange(archiveTargetRange).clearContent();
  destArchiveSheet.getRange(archiveCreditRange).clearContent();
  destArchiveSheet.getRange(archiveDebtRange).clearContent();
  destNoteSheet.getRange(notesCategoryRange).clearContent();
  destNoteSheet.getRange(notesBillRange).clearContent();
  destNoteSheet.getRange(notesTargetRange).clearContent();

  destSummarySheet.getRange(accountTitleRange).setValue(sourceTitle);
  destSummarySheet.getRange(startBalanceRange).setValue(sourceEndBalance);
  destSummarySheet.getRange(inflowAdjustRange).setValue(parseFloat(sourceCarryoverAdjustment) + parseFloat(sourceLumpAdjustment) - parseFloat(sourceAdjustmentSum));
  
  if (sourceTransactionCategories.length > 0) {
    destCategoriesSheet.getRange(startRow, startColumn, sourceTransactionCategories.length, sourceTransactionCategories[0].length).setValues(sourceTransactionCategories);
  }
  if (sourceTransactionBills.length > 0) {
    destBillsSheet.getRange(startRow, startColumn, sourceTransactionBills.length, sourceTransactionBills[0].length).setValues(sourceTransactionBills);
  }
  if (sourceTransactionTargets.length > 0) {
    destTargetsSheet.getRange(startRow, startColumn, sourceTransactionTargets.length, sourceTransactionTargets[0].length).setValues(sourceTransactionTargets);
  }
  if (sourceCreditAccounts.length > 0) {
    destCreditsSheet.getRange(startRow, startColumn, sourceCreditAccounts.length, sourceCreditAccounts[0].length).setValues(sourceCreditAccounts);
  }
  if (sourceDebts.length > 0) {
    destDebtsSheet.getRange(startRow, startColumn, sourceDebts.length, sourceDebts[0].length).setValues(sourceDebts);
  }
  
  destNoteSheet.getRange(notesCategoryRange).setValues(sourceNoteCats);
  destNoteSheet.getRange(notesBillRange).setValues(sourceNoteBills);
  destNoteSheet.getRange(notesTargetRange).setValues(sourceNoteTargets);
  destNoteSheet.getRange(notesCreditRange).setValues(sourceNoteCredits);
  destBillsSheet.getRange(creditBillRange).setDataValidation(billRule);
  destTargetsSheet.getRange(creditTargetRange).setDataValidation(targetRule);
  SpreadsheetApp.flush();
  ui.alert("Import successful!");

  return;
}

How to render inline svg element with TailwindCSS

I’ve defined a background image in tailwind.config.ts called hero:

backgroundImage: {
        hero: `url('data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 600 600'%3E%3Cfilter id='a'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='2' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23a)'/%3E%3C/svg%3E')`,
},

I tried using it in global.css like this:

.fill-grain {
    @apply before:bg-hero;
}

But it throws an error saying Failed to compile:

failed-to-compile-sc

How can I use an inline svg with TailwindCSS?

AWS S3 SignatureDoesNotMatch Presigned Request

I am implementing image upload to AWS S3 storage, currently I can’t solve the “SingatureDoesNotMatch” error when uploading using the pre-signed URL.

My frontend call looks like this, I retrieve the pre-signed URL but when I try to use it for upload I get the 403 forbidden.

const uploadImageToS3 = async (file, leagueId) => {
  const backendUrl = process.env.REACT_APP_BACKEND_URL || 'http://localhost:8080';
  const jwtToken = Cookies.get('jwtToken');
  const objectKey = `-event-${file.name}`;
  const url = `${backendUrl}/aws/generate-presigned-url?fileName=${objectKey}&contentType=image/jpeg`;

  try {
    const authOptions = {
      method: 'GET',
      headers: {
        'Authorization': `Bearer ${jwtToken}`,
        'Content-Type': 'application/json'
      }
    };

    // Fetch the presigned URL from your backend
    const response = await fetchWithAuth(url, authOptions, () => console.log('Logout or handle auth failure'));

    if (!response.ok) {
      throw new Error('Failed to obtain presigned URL');
    }

    let presignedUrl = await response.text();

    // Use the presigned URL to upload the file to S3
    const result = await fetch(presignedUrl, {
      method: 'PUT',
      headers: {
        'Content-Type': "image/jpeg",
      },
      body: file
    });

    if (!result.ok) {
      throw new Error('Failed to upload image to S3');
    }

    console.log('Uploaded successfully!');
    return objectKey;
  } catch (error) {
    console.error('Error uploading image to S3:', error);
    throw error;
  }
};

Backend method (bucket name and credentials are correct):

@GetMapping("/generate-presigned-url")
    public ResponseEntity<?> generatePresignedUrl(@RequestParam String fileName, @RequestParam String contentType) {
        System.out.println(contentType + " filename: " + fileName);
        try {
            // Set the expiry time. Adjust based on your needs.
            Date expiration = new Date();
            long expTimeMillis = Instant.now().toEpochMilli();
            expTimeMillis += 1000 * 60 * 5;
            expiration.setTime(expTimeMillis);

            // Generate the pre-signed URL.
            GeneratePresignedUrlRequest generatePresignedUrlRequest =
                    new GeneratePresignedUrlRequest(bucketName, fileName)
                            .withMethod(HttpMethod.PUT)
                            .withExpiration(expiration)
                            .withContentType(contentType);

            URL url = amazonS3.generatePresignedUrl(generatePresignedUrlRequest);

            return ResponseEntity.ok(url.toString());
        } catch (Exception e) {
            return ResponseEntity.internalServerError().body("Error generating URL: " + e.getMessage());
        }
    }

not getting header in reactjs from springboot application

Below is reactjs code

  import { apiSlice } from './apiSlice.js';

const AUTH_URL = '/auth';

export const authApiSlice = apiSlice.injectEndpoints({
    endpoints: (builder) => ({
        login: builder.mutation({
            query: (credentials) => ({
                url: `${AUTH_URL}/login`,
                method: 'POST',
                body: credentials,
            }),
        }),
    }),
    overrideExisting: false,
});

export const { useLoginMutation } = authApiSlice;
const baseQuery = fetchBaseQuery({
    baseUrl: 'http://localhost:8080',
    prepareHeaders: (headers) => {
        headers.set('Content-Type', 'application/json');
        return headers;
    },
})

export const apiSlice = createApi({
    baseQuery,
    tagTypes: ['Auth'],
    endpoints: (builder) => ({})
})
import { configureStore, Tuple } from '@reduxjs/toolkit';
import authReducer from './authSlice';
import {apiSlice} from '../slices/apiSlice.js'


const store = configureStore({
    reducer: {
        auth: authReducer,
        [apiSlice.reducerPath]: apiSlice.reducer,
    },
    middleware: (getDefaultMiddleware) =>
        getDefaultMiddleware().concat(apiSlice.middleware),
    devTools: true
});

export default store;

below is the handler in which api is being called and getting response, response is good, but not able to fetch or see headers in logs or console in chrome, i can see headers in postman/insomnia

const handleLogin = async () => {
        if (!username || !password) {
            setError('Please fill in all fields');
            return;
        }
        setError(``)
        try {
            const response = await login({ username, password }).unwrap();
            console.log(response)
            const token = response.headers.get('Authorization');
            if (token) {
                localStorage.setItem('token', token);
            }
            dispatch(setCredentials(response.data));
            navigate('/dashboard');
        } catch (err) {
            console.log(err)
            {err.data && err.data['message'] ? setError('Login failed: ' + err.data['message']) : setError('Login failed: ' + err.status)}
        }
    };

Below is server’s endpoint, here i’m binding header with response and send to the client

@PostMapping("/login")
public ResponseEntity<ApiResponse> loginUser(@RequestBody User user) {
    User existingUser = userService.findByUsernameAndPassword(user.getUsername());
    if (existingUser == null) {
        return ResponseEntity.status(401).body(new ApiResponse("User not found", null));
    }
    if (passwordEncoder.matches(user.getPassword(), existingUser.getPassword())) {
        if (existingUser.isVerified()) {
            String token = jwtUtil.generateToken(existingUser.getUsername(), existingUser.getRole());
            UserDTO userDTO = userEntityToUserDTO.mapToDTO(existingUser);
            HttpHeaders headers = new HttpHeaders();
            headers.set("Authorization", "Bearer " + token);
            return ResponseEntity.ok().headers(headers).body(new ApiResponse("Login successful", userDTO));
        } else {
            return ResponseEntity.status(401).body(new ApiResponse("User not verified", null));
        }
    } else {
        return ResponseEntity.status(401).body(new ApiResponse("Invalid credentials", null));
    }
}

Change to an input field in a JavaScript Datatable autochange the value of another field in the datatable?

I am working on a DOT Net MVC project. My Razor code has a datatable with input field Points and 2 other fields DaysAssigned and DaysRemaining. The value of DaysRemaining field changes according to this formula :
DaysRemaining = DaysAssigned – (Points /10)
My code is working for only the 1st row of the datatable. Changes to the Points field in any row of the datatable updates DaysRemaining field in the 1st row only.

Here is my code :

$('.Points').on("keyup", function() {
        var points = $(this).val().trim();  //get the value entered          
        var daysassign = $("#DaysAssigned").val().trim();                     
        let total = daysassign - (points / 10);
        $("#DaysRemaining").val(total);       
    });

I am new to javascript. Will appreciate any help while I keep working on this issue.
Thanks,

I have tried to find the Row index of Points field in the datatable and to update the corresponding DaysRemaining field but have been unsuccessful. Maybe there is another solution out there I am not aware of.

“Translate is not a constructor” Error using google translate

I am trying to implement the google translate api into my program however I keep getting the error “TypeError: Translate is not a constructor”. I have tried the v2 import and I am not sure where I went wrong as I followed the google documentation. This is being done in javascript. Below is the error I am getting and my code

import { ImageAnnotatorClient } from '@google-cloud/vision';

import pkg from '@google-cloud/translate';
const {Translate} = pkg;

const client = new ImageAnnotatorClient();

const fileName = 'images/toga.jpg';
const translate = new Translate();

async function getText(fileName){
    const [result] = await client.textDetection(fileName);
    const detections = result.textAnnotations;
    console.log('Text: ');
    detections.slice(1).forEach(text => console.log(text.description));
    console.log(detections.description);
return detections.description;
} 

const text = "Hello"
const target = "es";

async function translateText(){
    
    let [translations] = await translate.translate(text, target);
    translations = Array.isArray(translations) ? translations : [translations];
    console.log("Translations: ");
    translations.forEach((translations, i) => {
        console.log('${text[i]} => (${target}) ${translation}');
    });
}


getText(fileName);
translateText();

I am not able to print the token Id of the other users in my Zoom clone (Peer to Peer)

my videos list (i am storing users token id) is still empty and i am not getting any errors in my console screen of window as well

I have done all spell check (i had made some) and syntax checks, and I am still trying to find out what was the error, it seems that i cant find it even though i was comparing it with the source code of the project, my socketManager.js has no errors and i am sure about that in backend

Any ideas what can be wrong?

TechRadar | the technology experts

Technology refers to the application of scientific knowledge for practical purposes, particularly in industry. It encompasses a wide range of tools, machines, systems, and methods used to solve problems, improve efficiency, and enhance the quality of life. Technology can include everything from simple tools and devices to advanced digital systems and artificial intelligence. It plays a crucial role in various fields, including communication, healthcare, transportation, and education.hthh

For Knowing New Things!!

Why I still cannot receive email from website? [closed]

Everything was okay at the start, but only after I click my web “send message”, email send alert I haven’t received the email from web and the page become error. HTTP ERROR 405

I had tried [Update Service], and it is working. I can receive the email from Emailjs but only cannot from the website.

Pls help me to find how is it happens and fix it. I need to receive the email from website and without error page.