I'm trying to write a test with testcafe that could generate conflicts in a document. For this I would need to be logged in with 2 different users in 2 different browser sessions (One being an incognito window) and open up the documents editor with each user and edit the same text. It is important that both users are in the editor when editing the content in order to generate conflicts.
Is there a way to open multiple browser sessions in 1 testcafe test? Or an alternative solution for manipulating a doc with the 2 different user roles at the same time?
How the test would look like:
Open browser window
Log in with User1
Navigate to document editor (Tinymce)
Open incognito browser (without closing the 1st window)
Log in with User2
Navigate to document editor
With User1 edit "text" to "purple" then save
With User2 edit "text" to "gold" then save
Assert that conflict happens
I made an example for you of how you can run multiple TestCafe tests and synchronize them using promises: https://github.com/DevExpress/testcafe-example-multiuser-scenario
Clone this repository: git clone https://github.com/DevExpress/testcafe-example-multiuser-scenario.git
install the packages: npm install and run the tests with npm run test.
If you use this approach, your tests will look like this:
test('Some test', async t => {
await stage('First stage');
//do somthing
await stage('Second stage');
//do anything else
stage('End');
});
And the script that will drive the stages:
await user1.runStage('First stage'); //will run the 'First stage' in the test and wait for the next stage request
await user1.runStage('Second stage'); //will run the 'Second stage'
user1.runStage('End');
Related
So I'm currently trying to automate uploading a profile photo on an Electron App using Playwright and I'm running into issues with 'filechooser' event.
await windowA.click('data-testid');
const [fileChooser] = await Promise.all([
windowA.waitForEvent('filechooser'),
// windowA.locator('text=Edit').click(),
windowA.waitForTimeout(3000),
windowA.locator(selector).click(),
]);
The element used to upload a photo isn't an input type so I'm using
await fileChooser.setFiles(
[filepath],
{ timeout: 1000 }
);
The issue is trying to get playwright to select an image from the input dialog box that pops up and it just won't select any files. I've also been trying to get playwright to select an image in my fixtures folder, which is in a relative path to the test, but haven't had success in either case.
The error that Playwright is displaying is
page.waitForEvent: Timeout while waiting for event "filechooser"
waiting for event "filechooser"
Any know what the issue is?
My slippers told me that if you are using the window.showOpenFilePicker() to get a file from the user, you won't get the filechooser event at all. This is because internally, the showOpenFilePicker is not triggering an event as it is still a WIP.
More infos can be found there but I don't think there is a workaround for now
https://githubmemory.com/repo/microsoft/playwright/issues/8850
Pupetter has actually the same issue: https://github.com/puppeteer/puppeteer/issues/5210`
One fix would be to not use the showOpenFilePicker() at all, but instead rely on the <input> element to gather the file. This is a bit more cumbersome for the dev but is more supported and should trigger the 'filechooser' event.
Another fix could be to add a function you can override when running in test move for it to not even need to open the file chooser. Something like
getFileFromPicker() => {
if(!isRunningInTest) {
// do the showOpenFilePicker logic as usual in the app and the user will need to choose a file from it
} else {
// provide synchronously a buffer to use as file content, and so do not even show the picker to the testing user.
}
Is there any way to switch from headless to headed in the middle of a task in Selenium?
For example, I'm running some workflow headless, but in the middle I want the user to be able to push a button to see what the actual browser window looks like. How do I do that?
Not possible.
But it is possible to hide browser window from the screen :) :
driver.Manage().Window.Position =new Point(-2000, 0);
Unfortunately, switching between UI (headed) and HeadLess execution through selenium is not possible.
For example, Selenium creates an instance of browser of type WebDriver (either Firefox/Chrome/IE/HtmlUnit). Selenium can operate only on the instance it has created, and during creation time it will be defined if it is a UI test (Firefox/Chrome/IE) or Headless (HtmlUnit).
So, the design of Selenium prevents to switch between headless/UI execution in the middle of the test, as per your requirement.
Using xvfb you can do this. You can develop your tests using any driver, so, after configured the xvfb, you just need to use
xvfb-run tests
to run headless and if you don't want, you can run the tests without xvfb parameter.
A linux machine is required to use xvfb.
I've done this for one of my daily tasks - signin into firewall. It was a 2FA process, which required combo of browser interaction and a (random generated) token. For the first part a simple powershell script was running in headless mode, so when the site prompts for your token, it turns IE to visible and waits for user input. If such is provided, again switches to headless and finishes the process. The user is informed for success/fail of the operation with dialog message box.
You can start with such simple IE automation and optimize your .ps1 script later. The solution I was using back in the days:
$ie = new-object -ComObject "InternetExplorer.Application"
$requestUri = http://-your-site-here
# switch the browser headless mode on/off
#$ie.visible = $true
$ie.silent = $true
$ie.navigate($requestUri)
while($ie.Busy) { Start-Sleep -Milliseconds 100 }
# get DOM in order to interact
$doc = $ie.Document
$userInputId = "your-uname-id-here"
$doc.getElementsByTagName("input") | % {
if ($_.id -ne $null){
if ($_.id.Contains($userInputId)) { $_.value = "your-username-here" }
}
}
# can call JS events on elements
# like $btn.click()
Write-Verbose "Login Complete"
I'm trying to automate a scenario where I login to a site with two users on two different browsers where further interaction will then occur in the same test. It runs up to the point where Chrome has launched the URL and the recorded steps fail giving an error that web page cannot be accessed. The recorded steps do work on Chrome if they were separated out into its testmethod of its own.
BrowserWindow window;
window = BrowserWindow.Launch(new Uri("http://example.com"));
this.UIMap.ClickOnSignInLink();
this.UIMap.TypeInValidUserCredential();
this.UIMap.ClickOnSignInButton();
this.UIMap.AssertUserIsLoggedIn();
BrowserWindow window2;
BrowserWindow.CurrentBrowser = "Chrome";
window2 = BrowserWindow.Launch(new Uri("http://example.com"));
this.UIMap.ClickOnSignInLink();
this.UIMap.TypeInValidUserCredential();
this.UIMap.ClickOnSignInButton();
Test method FeaturesTest.LiveBidding threw exception:
Microsoft.VisualStudio.TestTools.UITest.Extension.UITestControlNotAvailableException: The web page could not be accessed. If the page is refreshing, please wait until the page refreshes and then perform actions on it.
Only way i managed to do this is by closing the first browser. To do this you can do either of these below. Add this after IE job is finished and you want to switch to Chrome.
window.Close();
or initialize a new playback
if (Playback.IsInitialized)
{
Playback.Cleanup();
Playback.Initialize();
}
Right now i have grunt setup to watch for file changes and feed them to mocha, and mocha runs the tests. The problem is when modules include something like "nw.gui" the test case cannot find them. Is there any way to get around that, some way that i can include it?
//indexeddb.spec.js
var assert = require("assert");
var IndexedDB = require("../scripts/indexeddb");
db = new IndexedDB();
console.log(db);
describe('IndexedDB', function(){
describe('initialize', function(){
it('Should throw an error when the paramaters are null', function(){
expect(db.initialize()).to.throwError();
});
});
});
//indexeddb.js
module.exports = exports = function(){
var indexedDB = require("nw.gui").Window.get().window.indexedDB;
var _ = require("../bower_components/underscore/underscore.js")
this.initialize = function(databaseName,version,schema) {
}
}
Should i do this differently? I did think about running the tests in a gui window in webkit, but that would require that i include all the spec file's on the page and reload the page every time i wanted to run the test. With grunt and watch i was trying to get it to run the test for each file when i edited either the spec or the src file.
I will also need to test the html/js/backbone pages that i open in a webkit window.
Thanks for any insight.
Code example at https://github.com/varunvairavan/node-webkit-unit-testing
Found a way to run test's on node webkit, with a watch to reload the page on file changes.
I was going through this post https://github.com/visionmedia/mocha/issues/960 when i found a link to https://github.com/BenoitZugmeyer/chwitt/tree/5f9bc6c0b8c0328f1dc06a554e9fdd3a969c36ae/tests
The way it works is, create a new node webkit app in your test directory, it then includes all the files in that directory that end with .spec.js and runs the tests in them. It also does a page reload on file changes in the source/test folder.
I had my files in sub directories in the test folder so i used the walk function from node.js fs.readdir recursive directory search to find all the files ending with ".spec.js".
the popup window is only happening if I use the Fire Fox browser otherwise, is there a way to fix this problem? I have to enter userid/password every time the i use FF as my browser.
currently, I am entering every time i run my test which is very painful but looking to make it more automated....
I have goggled and found two links here and here but no avail
http://username:password#xyz.com
This worked for me (xyz.com being the site name)
After spending hours reading I finally found the solution which works pretty well and I hope this will help others too. - Enjoy!!
First - follow this steps:
1) Open the FireFox browser
2) Type the following `about:config`
3) Look for `network.http.phishy-userpass-length` if you don't find then create a new Integer key
Create a new Integer key (right-click->New->Integer): `network.http.phishy-userpass-length` with value `255`
Second: You need to create a Firefox driver with the following:
FirefoxProfile profile = new FirefoxProfile();
profile.SetPreference("network.http.phishy-userpass-length", 255);
profile.SetPreference("network.automatic-ntlm-auth.trusted-uris", "YOUR HOST ADDRESS HERE");
_driver = new FirefoxDriver(profile);
let me know if you have any questions.
If this is a windows user account & password, then you need to enable the integrated windows login by setting
network.negotiate-auth.delegation-uris: MyIISServer.domain.com
network.automatic-ntlm-auth.trusted-uris: MyIISServer.domain.com
network.automatic-ntlm-auth.allow-proxies: True
network.negotiate-auth.allow-proxies: True
in the Firefox profile that WebDriver starts. Once you have the profile created and saved (run "Firefox -P" when no other instances are running to select a profile), you can do this in the code:
File profileDir = new File("C:/wherever/SeleniumFirefoxProfile");
FirefoxProfile profile = new FirefoxProfile(profileDir);
profile.setEnableNativeEvents(true);
driver = new FirefoxDriver(profile);
I have had to handle these a few times, but my approach is using a script outside Selenium. Are you working on Windows?
Basically what you do is this:
1) Prior to loading the page, clicking the URL, etc that causes that dialog to appear:
-- Launch an asynchronous script to handle the login
2) Then load the page, click the link, etc
-- Selenium will block until your asynch script completes
The async script:
-- Sleep for a few seconds
-- Activate the dialog
-- Send the username
-- Send a TAB
-- Send the password
-- Send a TAB
-- Send the Enter Key
If you are working on windows, I can post sample scripts to handle this. I've done it with Java and C#, but I would guess that basically the same thing would work regardless of how you are writing your tests (unless you are strictly using the FF plugin, in which case this won't work).
Let me know if you'd like more details.
You can use a FF plugin "autoauth". Download this plugin and create Firefox instance by the following way:
FirefoxProfile firefoxProfile = new ProfilesIni().getProfile("default");
File pluginAutoAuth = new File("D:\\autoauth-2.1-fx+fn.xpi");
firefoxProfile.addExtension(pluginAutoAuth);
driver = new FirefoxDriver(firefoxProfile);
I used "autoauth-2.1-fx+fn.xpi"