Bootstrap V5 Modal not hiding via Javascript Unless Window Method - javascript

I'm currently developing a react app and using normal bootstrap.The command to show a modal and toggle to one works fine; however the hide command doesn't hide the modal unless I make it a property on window.
For example:
const triggerSecondModalScreen = () => {
const element = document.getElementById("signUpModal2");
const currElement = document.getElementById("signUpModal");
if (element && currElement) {
const currentModal = new bootstrap.Modal(currElement);
const secondModal = new bootstrap.Modal(element);
setLoading(false);
// #ts-expect-error
window.modal.hide(); // works fine
// second.modal.hide() doesn't work
new bootstrap.Modal(element).show();
resetForm();
}
}
However, I notice that on Chrome dev tools the _isShown is changing correctly to false

I was able to figure out a fix. The solution for anyone encountering this in the future is to not use the 'new bootstrap.Modal()' constructor syntax but to use the getInstance method on the modal.
Changing my code to the below caused it to work completely fine and without the use for creating a function on the window.
const triggerSecondModalScreen = () => {
const element = document.getElementById("signUpModal2");
const currElement = document.getElementById("signUpModal");
if (element && currElement) {
const currentModal = bootstrap.Modal.getInstance(currElement);
setLoading(false);
currentModal?.hide()
bootstrap.Modal.getInstance(element)?.show();
resetForm();
}
}

Related

How to handle new tabs with the page object model with Playwright

I want to know how to handle a tab or multiple tabs when using Page object model.
My test runs successfully if i don't use the page object model function to run it.
Basically when i click and navigate to the new tab i am using this on the normal test without the POM:
const [newPage] = await Promise.all([
page.waitForEvent('popup'),
page.locator(button...).click();
]);
and then using the newPage as my new tab and it's working.
await newPage.locator(field).fill(testing);
...SNIP..
When using the POM I cant do that and I am not able to continue with the rest of the test, it doesnt recognise the new tab as i cant declare the new page in the POM.
Can someone point me in the right direction ?
How can i implement the same logic using the POM ?
Thanks
Maybe this will help. I also puzzled over how to do it.
constructor(page) {
this.page = page;
this.wait_for_event = page.waitForEvent('popup');
this.your_button = page.locator(button...);
}
async f(){
const [newPage] = await Promise.all([
this.wait_for_event,
this.your_button.click(),
]);
await newPage.getByPlaceholder or another method('placeholder text').fill('');
}
In my case something like this works:
import { test } from '#playwright/test';
import { LoginPage } from '../../pages/LoginPage';
import { ProductsPage } from '../../pages/ProductsPage';
const purchasedProduct = 'Sauce Labs Backpack';
test.beforeEach(async ({ page }) => {
const loginPage = new LoginPage(page);
await loginPage.goTo('inventory.html');
});
test('As a user I want to open a new tab and visit it', async ({
page,
context,
}) => {
const productsPage = new ProductsPage(page);
const [newPage] = await Promise.all([
context.waitForEvent('page'),
productsPage.openNewTabWithProduct(purchasedProduct),
]);
await newPage.locator('text=Sauce Labs Onesie').click();
});
The crucial part is you have to put "context" instead of page as your test attribute. Then just use your newly created page

Chrome Extension: How can I access the new document on page changes?

I'm trying to amend the DOM using a chrome extension. Unfortunately I fail with accessing the new page after some of the actions cause a page change. My code looks like this:
content_script.js
(async () => {
try {
execute_edit = async () => {
console.log(document.title)
const el = document.getElementsByClassName("icon")
const first_el = el[0]
first_el.click()
}
change_element = async () => {
console.log(document.title)
const el = document.querySelector("element")
console.log(el.innerHTML)
}
await execute_edit()
await change_element()
} catch (e) {
console.log(e)
}
})();
I'm getting the error that the "el" in "change_element" does not exist. This is obviously caused by the fact that both "document.title" are identical i.e. the second function still tries to access the original DOM and not the new page.
Any suggestions on how I can have the second function "change_element" access the new page's DOM?

Testing form reset on Vue with Jest

Testing a form built with Vue using Jest for unit tests. Among the elements I have a reset button (type=reset), which works fine and once clicked it removes all the values already introduced.
However, when unit testing, the button click doesn't seem to clear the values. I don't have a handler for the click, just using the default reset function of the form.
I've also tried using wrapper.emmited('reset'); to no avail, and wrapper.emmitedByOrder(); returns an empty array.
How do I test that the reset button is generated correctly and works as expected?
test('Assert Form Components', async () => {
const wrapper = mount(FormElement, {
propsData: {
message: sampleJSON.formJSON
}
})
let resetBtn = wrapper.find('.form-reset');
let requiredInput = wrapper.find('.required-input');
....
requiredInput.setValue('test');
expect(requiredInput.element).toHaveValue('test'); //This passes
await resetBtn.trigger('click');
expect(requiredInput.element).not.toHaveValue('test') //This fails
....
Apparently there were two things missing. First, as #AlexMA suggested, allowing for another tick to let the DOM settle. Second, I needed to attach the wrapper to the DOM. The final code look something like this:
test('Assert Form Components', async () => {
const wrapper = mount(FormElement, {
propsData: {
message: sampleJSON.formJSON
},
attachTo: document.body
})
let resetBtn = wrapper.find('.form-reset');
let requiredInput = wrapper.find('.required-input');
....
requiredInput.setValue('test');
expect(requiredInput.element).toHaveValue('test'); //This passes
await resetBtn.trigger('click');
await wrapper.vm.$nextTick()
expect(requiredInput.element).not.toHaveValue('test') //This works now!
....

Dynamically add all components in a folder

So I'm currently building a tutorial, where the number of pages will continuously expand as more features are added, currently I am manually adding each file to the displaying file, i.e.
const Page0 = () => import("../../components/tutorial/Page0/index.vue");
const Page1 = () => import("../../components/tutorial/Page1/index.vue");
but obviously if this isn't very well handled once it gets really big i.e.
const Page0 = () => import("../../components/tutorial/Page0/index.vue");
...
const Page100 = () => import("../../components/tutorial/Page100/index.vue");
So I was wondering if there was a way to know let vue.js know that it should be fetching all files/folders in a certain folder and render each of them as a component with 'Page' + number name.
Ordering matters.
full code sandbox here https://codesandbox.io/s/serene-curie-it7xo?file=/pages/tutorial/_page.vue:102-247
use dynamic loading then.
in your _page.vue
function mapComponents() {
let components = {};
for (let i = 0; i < 2; i++) { // 2 should be your pages amount
components["Page" + i] = () =>
import(`../../components/tutorial/Page${i}/index.vue`);
}
return components;
}
export default {
components: mapComponents(),
computed: {
current() {
//.... other code
in your tutorial.vue
data() {
return {
pages: [...Array(2).keys()] // same here, 2 should be your pages amount
};
},
maybe just use another function to get the amount of the page, but you got the idea :)
working sample : https://codesandbox.io/s/clever-feynman-vgm93?file=/pages/tutorial.vue:280-347

ShowOpenDialog not working on recent versions of electron-js

I'm new on electronjs and developing a small application that reads a json file and build a small html form and return the values entered by the user.
So I've developed small scripts in javascript that link to html 'button' tags to call dialogs so that a user can enter directories, files and save the final form. Everything works nicely... on electronjs "^3.1.13". But if I'm updating to a recent version of the lib ("^8.2.5"), then all my cool ShowOpenDialog don't work at all. Any clue of what happens?
Here is the script to open a folder if it helps:
{
let myName = document.currentScript.getAttribute('name');
const ipc = require('electron').ipcRenderer;
let asyncBtn = document.querySelector('#folder-selector-'+myName);
let replyField = document.querySelector('#folder-selector-content-'+myName);
let onButtonClick = function() {
const { dialog } = require('electron').remote;
let dialogOptions = {
title: "Choisir un dossier:",
properties: ['openDirectory','promptToCreate'],
};
dialog.showOpenDialog(
dialogOptions,
fileNames => {
if (fileNames === undefined) {
console.log("No file selected");
} else {
console.log('file:', fileNames[0]);
replyField.value = fileNames[0];
}
})
};
asyncBtn.addEventListener("click", onButtonClick);
}
Thanks a lot for any help.
Apart from the fact that the call to dialog.showOpenDialog has indeed been updated in recent versions of Electron, and returns a promise instead of making use of a callback function, there is another flaw in your updated code: reading the above-mentioned documentation page shows that getCurrentWindow() is not a method of dialog; it can be obtained from remote instead, so you have to add it explicitely:
const { dialog, getCurrentWindow } = require('electron').remote;
then simply call it from inside dialog.showOpenDialog:
dialog.showOpenDialog( getCurrentWindow(), dialogOptions).then(result => {
but this is an error you could have caught yourself by looking at the DevTools's console, which would display:
TypeError: dialog.getCurrentWindow is not a function
Recent version of showOpenDialog receives two arguments: optional BrowserWindow, and options as second argument. It returns promise and not requires callback.
https://github.com/electron/electron/blob/8-x-y/docs/api/dialog.md#dialogshowopendialogbrowserwindow-options
So you need to change you callback logic to promises.
let onButtonClick = function() {
const { dialog } = require('electron').remote;
let dialogOptions = {
title: "Choisir un dossier:",
properties: ['openDirectory','promptToCreate'],
};
dialog.showOpenDialog(
dialogOptions
).then((fileNames)=>{
if (fileNames === undefined) {
console.log("No file selected");
} else {
console.log('file:', fileNames[0]);
replyField.value = fileNames[0];
}
}).catch(err=>console.log('Handle Error',err))
};
asyncBtn.addEventListener("click", onButtonClick);
thanks a lot Vladimir. So I've tried to update my code as explained, updating electron package to version 8.2.5 and modifying the script as you explained but it's not going any better. If I got it well, this code should be correct, but doesn't work on electron 8.2.5. Any error you still see on this?
{
let myName = document.currentScript.getAttribute('name');
const ipc = require('electron').ipcRenderer;
let asyncBtn = document.querySelector('#folder-selector-'+myName);
let replyField = document.querySelector('#folder-selector-content-'+myName);
let onButtonClick = function() {
const { dialog } = require('electron').remote;
let dialogOptions = {
title: "Choisir un dossier:",
properties: ['openDirectory','promptToCreate']
};
dialog.showOpenDialog( dialog.getCurrentWindow(), dialogOptions).then(result => {
if(!result.canceled) {
replyField.value = result.filePaths[0];
}
}).catch(err => {
console.log(err)
})
};
asyncBtn.addEventListener("click", onButtonClick);
}
Ok, finally got it. Apart from the most appreciated help I had, I missed
"webPreferences": {
nodeIntegration: true
}
in the main.js to make it work.
The discovering of the Developer Tools were of great help as well :)
Now everything is fine again. Thanks a lot!

Categories