Today I was trying to debug my application directly on my HuaWei Honor 6, because the android emulator is really slow and that’s a lot more fun on a brand new phone 🙂
I had some difficulties so I thought I would explain here.
Continue reading
Today I was trying to debug my application directly on my HuaWei Honor 6, because the android emulator is really slow and that’s a lot more fun on a brand new phone 🙂
I had some difficulties so I thought I would explain here.
Continue reading
Selenium does not allow dropping external files on an element. However it may be mandatory for your test if you want to cover every functionality. We will see how to make it work with Firefox 28+ and Chrome. I haven’t tested that on other browsers. We will see three work around:
This is a mostly a JavaScript workaround, the files and the drop event are created in JavaScript, that’s why the browser matters.
First a simple version where you don’t want file from your file system, this is enough in most situation:
public void dropFiles(List<String> names, WebElement target) throws IOException { final JavascriptExecutor exec = (JavascriptExecutor) BrowserDriver.getCurrentDriver(); String inputId = "seleniumDragAndDropInput"; // Create the FileList exec.executeScript(inputId + "_files = [];"); for (String name: names) { exec.executeScript(inputId + "_files.push(new File([new Blob(['This is my content'], {type: 'text/plain'})], '" + name + "'));"); } String targetId = target.getAttribute("id"); // Add an id if the target doesn't have one if (targetId == null || targetId.isEmpty()) { targetId = "seleniumDragAndDropInput_target"; exec.executeScript("sId=function(e, i){e.id = i;};sId(arguments[0], arguments[1]);", target, targetId); } // Add the item function the the FileList // Create the drop event and dispatch it on the target String initEventJS = inputId + "_files.item = function (i) {return this[i];};" + "var eve=document.createEvent(\"HTMLEvents\");" + "eve.initEvent(\"drop\", true, true);" + "eve.dataTransfer = {files:seleniumDragAndDropInput_files};" + "eve.preventDefault = function () {};" + "eve.type = \"drop\";" + "document.getElementById('" + targetId + "').dispatchEvent(eve);"; exec.executeScript(initEventJS); if (targetId == "seleniumDragAndDropInput_target") { exec.executeScript("document.getElementById('seleniumDragAndDropInput_target').id = null"); } }
The File creation works only with Firefox 28+, with earlier version it says “operation is unsecure”.
And now an other example where we are using file from the machine running the Selenium tests. However be careful because it is not really smart and file’s content needs to be without special characters or it will break the JavaScript. You should escape the content if you need more advanced content. I didn’t because I usually using the first solution and code my content. This is enough in most situation where a bit of plain text or xml are enough for my tests.
public void dropFiles(List<File> files, WebElement target) throws IOException { final JavascriptExecutor exec = (JavascriptExecutor) BrowserDriver.getCurrentDriver(); String inputId = "seleniumDragAndDropInput"; // Create the FileList exec.executeScript(inputId + "_files = [];"); for (File file : files) { exec.executeScript(inputId + "_files.push(new File([new Blob(['" + readFile(file) + "'], {type: '" + Files.probeContentType(file.toPath()) + "'})], '" + file.getName() + "'));"); } String targetId = target.getAttribute("id"); // Add an id if the target doesn't have one if (targetId == null || targetId.isEmpty()) { targetId = "seleniumDragAndDropInput_target"; exec.executeScript("sId=function(e, i){e.id = i;};sId(arguments[0], arguments[1]);", target, targetId); } // Add the item function the the FileList // Create the drop event and dispatch it on the target String initEventJS = inputId + "_files.item = function (i) {return this[i];};" + "var eve=document.createEvent(\"HTMLEvents\");" + "eve.initEvent(\"drop\", true, true);" + "eve.dataTransfer = {files:seleniumDragAndDropInput_files};" + "eve.preventDefault = function () {};" + "eve.type = \"drop\";" + "document.getElementById('" + targetId + "').dispatchEvent(eve);"; exec.executeScript(initEventJS); if (targetId == "seleniumDragAndDropInput_target") { exec.executeScript("document.getElementById('seleniumDragAndDropInput_target').id = null"); } } private String readFile( File file ) throws IOException { BufferedReader reader = new BufferedReader( new FileReader (file)); String line = null; StringBuilder stringBuilder = new StringBuilder(); String ls = System.getProperty("line.separator"); while( ( line = reader.readLine() ) != null ) { stringBuilder.append( line ); stringBuilder.append( ls ); } reader.close(); return stringBuilder.toString(); }
Here is a solution to actually drop any file from the file system. We have to use an input (type=file) and since we can not set its value via JavaScript (for security reason, or we could upload any file from our visitor 🙂 ), we need to set the value with Selenium with sendKeys. But in order for this to work, the input needs to be visible. That’s why I set the form with a position fixed. We need to delete it once done.
final JavascriptExecutor exec = (JavascriptExecutor) BrowserDriver.getCurrentDriver(); WebElement target = browseContainer.contentListGrid; String targetId = target.getAttribute("id"); // Add an id if the target doesn't have one if (targetId == null || targetId.isEmpty()) { targetId = "seleniumDragAndDropInput_target"; exec.executeScript("sId=function(e, i){e.id = i;};sId(arguments[0], arguments[1]);", target, targetId); } exec.executeScript( "var f=dojo.create('form', {id: 'seleniumDragAndDropInput_form', style: {position: 'fixed', left: 0, top: 0, width:'100px', height: '100px'}}, dojo.body());" + "dojo.create('input', { type: 'file', id: 'seleniumDragAndDropInput' }, f);"); WebElement input = BrowserDriver.getCurrentDriver().findElement(By.id("seleniumDragAndDropInput")); input.sendKeys(path); exec.executeScript( "var files=dojo.byId(\"seleniumDragAndDropInput\").files;" + "var eve=document.createEvent(\"HTMLEvents\");" + "eve.initEvent(\"drop\", true, true);" + "eve.dataTransfer = {files:files};" + "eve.type = \"drop\";document.getElementById('" + targetId + "').dispatchEvent(eve);"); exec.executeScript("dojo.destroy('seleniumDragAndDropInput_form');"); if (targetId == "seleniumDragAndDropInput_target") { exec.executeScript("document.getElementById('seleniumDragAndDropInput_target').id = null"); }
You may need to change a bit if you are not using dojo and replace the byId, create and destroy but I an sure you have that with your favorite javascript framework.
With Chrome, you could use almost the same code that the previous one. The only thing to do is to set the input as ‘multiple’ and split paths with a \n.
public static void dropFile(String[] paths, WebElement target) { StringBuffer b = new StringBuffer(); for (int i = 0; i < paths.length; i++) { File f = new File(paths[i]); if (!f.isFile()) { Assert.fail(paths[i] + " is not a valid file path."); } b.append(f.getAbsolutePath()); if (i < paths.length - 1) { b.append("\n"); } } final JavascriptExecutor exec = (JavascriptExecutor) BrowserDriver.getCurrentDriver(); String targetId = target.getAttribute("id"); // Add an id if the target doesn't have one if (targetId == null || targetId.isEmpty()) { targetId = "seleniumDragAndDropInput_target"; exec.executeScript("sId=function(e, i){e.id = i;};sId(arguments[0], arguments[1]);", target, targetId); } exec.executeScript( "var f=dojo.create('form', {id: 'seleniumDragAndDropInput_form', style: {position: 'fixed', left: 0, top: 0, width:'100px', height: '100px'}}, dojo.body());" + "dojo.create('input', { type: 'file', id: 'seleniumDragAndDropInput', multiple: 'multiple' }, f);"); WebElement input = BrowserDriver.getCurrentDriver().findElement(By.id("seleniumDragAndDropInput")); input.sendKeys(b.toString()); exec.executeScript( "var files=dojo.byId(\"seleniumDragAndDropInput\").files;" + "var eve=document.createEvent(\"HTMLEvents\");" + "eve.initEvent(\"drop\", true, true);" + "eve.dataTransfer = {files:files};" + "eve.type = \"drop\";document.getElementById('" + targetId + "').dispatchEvent(eve);"); exec.executeScript("dojo.destroy('seleniumDragAndDropInput_form');"); if (targetId == "seleniumDragAndDropInput_target") { exec.executeScript("document.getElementById('seleniumDragAndDropInput_target').id = null"); } }
However, it does not work with Firefox because it does not accept multiple files in one input separated by \n. That’s why we need to use several inputs and then gather files from all inputs in a FileList to be used in the event. Here is the code.
public static void dropFile(String[] paths, WebElement target) { for (int i = 0; i < paths.length; i++) { File f = new File(paths[i]); if (!f.isFile()) { Assert.fail(paths[i] + " is not a valid file path."); } paths[i] = f.getAbsolutePath(); } final JavascriptExecutor exec = (JavascriptExecutor) BrowserDriver.getCurrentDriver(); String targetId = target.getAttribute("id"); // Add an id if the target doesn't have one if (targetId == null || targetId.isEmpty()) { targetId = "seleniumDragAndDropInput_target"; exec.executeScript("sId=function(e, i){e.id = i;};sId(arguments[0], arguments[1]);", target, targetId); } // Using one input with multiple file separated by \n does not work with Firefox // We need to use several input StringBuffer createInputs = new StringBuffer(); // Create form createInputs.append("var f=dojo.create('form', {id: 'seleniumDragAndDropInput_form', style: {position: 'fixed', left: 0, top: 0, width:'100px', height: '100px'}}, dojo.body());"); // Create inputs for (int i = 0; i < paths.length; i++) { createInputs.append("dojo.create('input', { type: 'file', id: 'seleniumDragAndDropInput" + i + "'}, f);"); } exec.executeScript(createInputs.toString()); // Then set file for each input for (int i = 0; i < paths.length; i++) { WebElement input = BrowserDriver.getCurrentDriver().findElement(By.id("seleniumDragAndDropInput" + i)); input.sendKeys(paths[i]); } // Write code to gather all inputs files in one array; StringBuffer gatherInputs = new StringBuffer(); gatherInputs.append("var seleniumDragAndDropFiles = [];"); // Need to add the item method to stick to FileList API gatherInputs.append("seleniumDragAndDropFiles.item = function (i) { return seleniumDragAndDropFiles[i]};"); for (int i = 0; i < paths.length; i++) { gatherInputs.append("seleniumDragAndDropFiles.push(dojo.byId(\"seleniumDragAndDropInput" + i + "\").files[0]);"); } // Init event with our file exec.executeScript( gatherInputs.toString() + "var eve=document.createEvent(\"HTMLEvents\");" + "eve.initEvent(\"drop\", true, true);" + "eve.dataTransfer = {files:seleniumDragAndDropFiles};" + "eve.type = \"drop\";document.getElementById('" + targetId + "').dispatchEvent(eve);"); exec.executeScript("dojo.destroy('seleniumDragAndDropInput_form');"); if (targetId == "seleniumDragAndDropInput_target") { exec.executeScript("document.getElementById('seleniumDragAndDropInput_target').id = null"); } }
There are times where you need to know the URL of a ressource within your plug-in. An example is when you want to embedded an applet and add it to your page, or get the link to an image. In order to do that, you can use the following code:
Request.getPluginResourceUrl("PluginName", "myFolderWithingWebContentFolder/path");
An example if you want to embedded an applet:
var appletHTML = '<applet alt="MyApplet" name="MyApplet" width="1px" height="1px" code="my.package.MyClass.class" codebase="' + Request.getPluginResourceUrl('PluginName', 'applets') + '" archive="MyApplet.jar" mayscript="true">'; appletHTML = appletHTML + '</applet>'; appletDiv = document.createElement("div"); appletDiv.innerHTML = appletHTML; applet = appletDiv.firstChild; document.body.appendChild(applet);
That can be convenient .
After a CPIT installation, you will still have to create an Object Store in order to have a fully functional platform. Luckily, when using the CPIT installer, IBM already provides the database and datasources for one more Object Store, They also pre-set the database connection in the Administrative Console for Content Engine (ACCE). So the procedure is really easy, we only have to create the Object Store using the pre-set database connection.
Here are the procedure in pictures:
Continue reading
I was reading a few posts on ecmplace today and I saw that some persons are struggling with starting and stopping the FileNet platform after they got their CPIT installation done. So here are two scripts to start and stop all components. They start in order (and stop in reverse order) the following components:
To start the platform (I include the iptables config but if you saved it once for all you don’t need those lines):
#!/bin/bash iptables -I INPUT 4 -i eth0 -p tcp --dport 9080 -m state --state NEW,ESTABLISHED -j ACCEPT iptables -I INPUT 4 -i eth0 -p tcp --dport 9043 -m state --state NEW,ESTABLISHED -j ACCEPT iptables -I INPUT 4 -i eth0 -p tcp --dport 2809 -m state --state NEW,ESTABLISHED -j ACCEPT iptables -I INPUT 4 -i eth0 -p tcp --dport 9100 -m state --state NEW,ESTABLISHED -j ACCEPT iptables -I INPUT 4 -i eth0 -p tcp --dport 9403 -m state --state NEW,ESTABLISHED -j ACCEPT # DB2 su - dsrdbm01 -c db2start # TDS admin server /opt/ibm/ldap/V6.3/sbin/idsdiradm -I dsrdbm01 # TDS instance /opt/ibm/ldap/V6.3/sbin/ibmslapd -n -I dsrdbm01 # WAS /opt/ibm/WebSphere/AppServer/bin/startServer.sh server1
To stop the platform:
#!/bin/bash # WAS /opt/ibm/WebSphere/AppServer/bin/stopServer.sh server1 -username P8Admin -password PASSWORD # TDS instance /opt/ibm/ldap/V6.3/sbin/ibmslapd -I dsrdbm01 -k # TDS admin server /opt/ibm/ldap/V6.3/sbin/idsdiradm -I dsrdbm01 -k # DB2 su - dsrdbm01 -c db2stop
Hopefully it will help someone.
I had some issues lately when migrating to Java 7. As you may know if you read this blog, I’ve been playing these past few weeks with test framework and more precisely PowerMock. I also had to mess with the bytecode a bit myself because some libraries from ICN have dependencies missing and can not be hot recompiled by PowerMock (rebuilding the byte code during Runtime).
Well what I did with the bytecode didn’t work with Java 7. After some researches, I discovered than the byte code verification has been enforced with Java 7, to avoid injection of malicious code via bytecode modification. This is good for production, but in test when we like to mess with bytecode to allow us some tricks, that’s not really helpful. Anyway after a while I discovered the option to disabled this bytecode verification. Of course I wouldn’t recommend using that in production, but it can be useful for test.
For IBM JDK, I didn’t find yet a way to fall back to the old verification engine, so for now I just disable it. Add this to your JVM arguments when running test.
-Xverify:none
For SUN JDK, there is an option to fall back to the old verification engine. Alternatively you can also disable the verification the same way that we do for IBM JDK. Here is the option:
-XX:-UseSplitVerifier
Last post of a three posts series about testing, after Unit Testing and Integration Testing, let’s talk about UI testing.
Selenium is a Browser driver, basically it does what you would do if you were manually testing, i.e. clicking, looking for elements, selecting, scrolling…, except it does it alone, and can do it for hours without a break, every night…
How it works is quite simple, you are targeting DOM elements (or node, or WebElement, or any name you would like to call them) with selectors, and then you can do various operations on those like a user would do: wait for them to be present, to be visible, to be clickable, click on them, drag and drop something, enter information in a text field, …
Keep in mind that Selenium does the same thing that you would do. So if an element is not visible on the page and you would scroll to catch it before clicking, you have to do the same with Selenium, or it will throw an exception saying the element is not clickable because it is out of the view, which makes sense.
This article is an introduction to Selenium, if you want more applied examples for ICN and Dojo, you can read this post, but I would recommend you to read this one first to get familiar with Selenium.
In its version 1.0, IBM CMIS was shipped as a separate application. But now, where can you get it and how can you install IBM CMIS? If you are looking for it in the Software Catalog from IBM, you won’t find it. And that’s normal because it is now part of IBM Content Navigator.
We’ll see how to install CMIS. You can follow this procedure when you install ICN, upgrade ICN, or even if you have already installed it, just re-open the configuration tool. The procedure start when you are starting the IBM Content Navigator Configuration and Deployment Tool. If you are installing/upgrading ICN, it will start by itself. If you have ICN already installed, you can launch this tool by running:
Continue reading
If like me, you are a really clumsy person, you may delete the entire Object Store on a stupid mistake. Don’t laugh, it happened to me. I was working with the FEM and I clicked without reading twice :). From the FileNet knowledge center, this is supposed to be an irreversible action. The truth is it’s not, thanks god because i could have been in real trouble! So if you don’t have snapshot of the platform before, or your backup is hard to restore, or you will loose to much data since the last backup, here is another solution.
This is a really nice trick to recover a deleted object store really easily. It can save you a lot of troubles too. It is really well explained in the link, but here is the procedure summarized.
Actually the deletion of an object store is an update like every other updates, therefore it can be undone by updating the FNGCD table of the GCD database, which store the last 100 updates. You just have to set he last_epoch_id of the line with the id 0, to the the value of the update before the deletion.
I have to thank so much my colleague for finding and then sharing this trick with me!
Lately I’ve been writing about test, and to finish this series of post, after unit tests and integration tests, I would like to talk about UI test. UI is not easy to test, because it requires a lot of user interactions. This is really important though, because UI tests make sure the final result, i.e. what the user sees, is what we want him to see. And as we all know, users remember mostly the UI defects 🙂
Update: I actually wrote an introduction on how to use Selenium, this post is meant more to give example of uses of Selenium applied to ICN and indirectly Dojo.
Not long ago, to test web application, we were writing test cases and you or any other unlucky tester was validating all of them one by one, and it was taking ages. Thanks god, there is nowadays better solutions, meaning lazy automatic solution. I will introduce in this post how to use a Web Browser automation tool to test ICN and your plug-in. We will use Selenium, which I think is a great tool. This will be applied to ICN, you can find plenty of Selenium tutorials on the web anyway, We will see how to automate basic action, like login, logout, create a folder, a document, file a document, accept message dialog. Then it will be up to you to adapt all this to your plug-ins.
Here is a quick video to give you an idea of what can be done with Selenium and ICN.