Grails events-push plugin fails to respond to events - javascript

I am trying to move from events-push:1.0.M7 (latest released official version) to events-push:1.0.0.BUILD-SNAPSHOT. To obtain the latter version I cloned the https://github.com/smaldini/grails-events-push repo and built the plugin locally. The supposed advantage of the later version of the Grails plugin is that it uses newer versions of Atmosphere JavaScript and Java libraries.
In the README file the plugin refers to the GrailsTodos application at https://github.com/smaldini/grailsTodos. However the configuration and the code in the Todos application has nothing in common with the events-push usage information provided in its README file.
Instead, I am trying to use another sample written to demonstrate events-push plugin: https://www.dropbox.com/s/378bqmbu3ad4fnt/GrailsEventsPush.zip. This is an application running in Grails 2.3.7 and using events-push:1.0.M7. It works correctly out of the box with the released version (M7) of the events-push plugin.
Here are the steps I made to make it compile and run with events-push:1.0.0.BUILD-SNAPSHOT (which I installed locally using 'grails maven-install'):
In BuildConfig.groovy
grails.servlet.version = "3.0"
grails.tomcat.nio = true
...
dependencies {
compile 'org.grails.plugins:events:1.0.0.BUILD-SNAPSHOT'
}
plugins {
...
//compile ":events-push:1.0.M7"
compile ":events-push:1.0.0.BUILD-SNAPSHOT"
}
In MyEvents.groovy
events = {
'bagsUpdated' namespace: 'browser', browser:true // allows browser push on this topic
}
In the EventTestingController:
def updateBags() {
Thread.sleep(3000)
event([namespace: 'browser', topic: 'bagsUpdated']) // will trigger registered browsers on 'bagsUpdated' topic
render "OK"
}
I did not change index.gsp:
<script type="text/javascript">
try {
var grailsEvents = new grails.Events("${createLink(uri:'')}", {transport: "sse"});
grailsEvents.on('bagsUpdated', function (data) {
window.console && console.log("GOT bags!");
$("#waiting").html("Event fired!");
});
} catch (error) {
console.log("ERROR: " + error.toString());
}
$(function () {
// Call controller method that emits event when its done
$.ajax({
url: "${createLink(action:'updateBags')}",
success: function () {
console.log("Event should have been already fired...");
},
error: function () {
console.log("Ops something went wrong... ");
}
});
});
</script>
The code that worked correctly with 1.0.M7 version of the plugin does not work with 1.0.0.BUILD-SNAPSHOT version. Here is what I see in the Chrome console:
defer connecting topic: eventsbus grailsEvents.js:108
defer connecting topic: bagsUpdated grailsEvents.js:108
XHR finished loading: POST "http://localhost:8080/GrailsEventsPush/g-eventsbus/eventsbus?X-Atmosphere-t…sport=polling&X-Cache-Date=0&Content-Type=application/json&_=1416503898595". jquery.atmosphere.js:1691
XHR finished loading: POST "http://localhost:8080/GrailsEventsPush/g-eventsbus/eventsbus?X-Atmosphere-t…sport=polling&X-Cache-Date=0&Content-Type=application/json&_=1416503898598". jquery.atmosphere.js:1691
XHR finished loading: GET "http://localhost:8080/GrailsEventsPush/eventTesting/updateBags". jquery-1.11.0.min.js:4
Event should have been already fired... index:32
There are no errors - the browser simply does not get the event fired by the controller, which would produce "GOT bags!" and "Event fired!" statements in the Console.
The application I am trying to upgrade exhibits the same behavior - the server side events do not reach the browser. What am I missing?

Related

Can't get localhost mode to work in split.io

According to the documentation on split.io I should be able to create a Split client in 'localhost' mode, i.e. it will work offline. Here is the link: https://help.split.io/hc/en-us/articles/360020448791-JavaScript-SDK#localhost-mode
But nothing happens when I run this code:
// Import the SDK
var SplitFactory = require("#splitsoftware/splitio").SplitFactory;
// Instantiate the SDK
var factory = SplitFactory({
core: {
authorizationKey: "localhost",
},
features: {
"my-feature": "on",
},
});
// Get the client instance you'll use
var client = factory.client();
console.log("created the client");
// Set a callback to listen for the SDK_READY event, to make sure the SDK is properly loaded before asking for a treatment
client.on(client.Event.SDK_READY, function () {
console.log("SDK_READY");
var treatment = client.getTreatment("CUSTOMER_ID", "my-feature");
console.log(treatment);
});
client.on(client.Event.SDK_UPDATE, () => {
console.log("SDK_UPDATE");
});
client.once(client.Event.SDK_READY_TIMED_OUT, () => {
console.log("SDK_READY_TIMED_OUT");
});
client.once(client.Event.SDK_READY_FROM_CACHE, () => {
console.log("SDK_READY_FROM_CACHE");
});
"created the client" is logged but then nothing after that. How do I get SDK_READY to fire? It works fine if I give it a real API key.
I also put the code in a github project: https://github.com/philipbeber/splitlocalhost
It turns out that the Split SDK behaves differently if you are running from nodejs rather than in the browser. So if you use jest with its default settings then you need to reference different docs: https://help.split.io/hc/en-us/articles/360020564931-Node-js-SDK
There is no way to force the Split module to "client mode" which is infuriating.

Microsoft.Office.WebExtension not working when I use the Excel JavaScript API to build an add-in

I'm using the Office JS library to create an Excel add-in, and the Microsoft object is not being recognized. All the other classes from the library seem to to work fine, but when I call dialog.addEventHandler(Microsoft.Office.WebExtension.EventType.DialogMessageReceived,processMessage the Microsoft object is not evaluated properly. This is despite every other object from this library working fine.
I'm following this tutorial https://learn.microsoft.com/en-us/office/dev/add-ins/tutorials/excel-tutorial
I'm using CDN from this link: https://appsforoffice.microsoft.com/lib/1.1/hosted/office.js
The method that calls Microsoft.Office.WebExtension fails, and I knew it would because WebStorm tells me its not recognized.
All of the other objects from Office JS work fine though...here's an example of working code:
function sortTable() {
Excel.run(function (context) {
// Queue commands to sort the table by merchant name
var currentWorkbook = context.workbook.worksheets.getActiveWorksheet();
var expensesTable = currentWorkbook.tables.getItem('ExpensesTable');
var sortFields = [
{
key: 1,
ascending: false,
}
];
expensesTable.sort.apply(sortFields);
return context.sync();
}).catch(function (error) {
console.log("Error" + error);
if (error instanceof OfficeExtension.Error) {
console.log("Debug info: " + JSON.stringify(error.debugInfo));
}
});
}
I've review in detail the Office JavaScript API documentation: https://learn.microsoft.com/en-us/office/dev/add-ins/reference/overview/excel-add-ins-reference-overview
I've reviewed that there is an older common API: https://learn.microsoft.com/en-us/javascript/api/office?view=word-js-preview
I have suspected that I need access to this older common API, but the only documentation I've found says that you are just supposed to use the office.js library I've linked above.
Here's the whole function I'm trying to use:
function openDialog() {
//Call the Office Common API that opens a dialog
Office.context.ui.displayDialogAsync(
'https://localhost:3000/popup.html',
{height: 45, width:55},
function (result) {
dialog = result.value;
dialog.addEventHandler(Microsoft.Office.WebExtension.EventType.DialogMessageReceived,processMessage);
}
)
}
It does in fact open a dialog box as the Office.context.ui.displayDialogAsync method works. But as soon as you get to Microsoft.Office.WebExtension.EventType.DialogMessageReceived WebStorm tells me that the element Microsoft is an unresolved reference.
And here's the function it should call if it worked, processMessage. Because it does not get this far, the element does not get updated, and the dialog box does not close. I'm near 100% certain the issue is not with the function below, but I'm not ruling it out yet.
function processMessage(arg) {
console.log("made it inside processMessage")
document.getElementById("user-name").innerHTML = arg.message;
console.log("made ti just before dialog.close")
dialog.close();
}
The full name has been shortened to Office.EventType.DialogMessageReceived. Here's the GitHub issue: https://github.com/OfficeDev/office-js-docs-pr/issues/1710

Retrieve html content of a page several seconds after it's loaded

I'm coding a script in nodejs to automatically retrieve data from an online directory.
Knowing that I had never done this, I chose javascript because it is a language I use every day.
I therefore from the few tips I could find on google use request with cheerios to easily access components of dom of the page.
I found and retrieved all the necessary information, the only missing step is to recover the link to the next page except that the one is generated 4 seconds after loading of page and link contains a hash so that this step Is unavoidable.
What I would like to do is to recover dom of page 4-5 seconds after its loading to be able to recover the link
I looked on the internet, and much advice to use PhantomJS for this manipulation, but I can not get it to work after many attempts with node.
This is my code :
#!/usr/bin/env node
require('babel-register');
import request from 'request'
import cheerio from 'cheerio'
import phantom from 'node-phantom'
phantom.create(function(err,ph) {
return ph.createPage(function(err,page) {
return page.open(url, function(err,status) {
console.log("opened site? ", status);
page.includeJs('http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js', function(err) {
//jQuery Loaded.
//Wait for a bit for AJAX content to load on the page. Here, we are waiting 5 seconds.
setTimeout(function() {
return page.evaluate(function() {
var tt = cheerio.load($this.html())
console.log(tt)
}, function(err,result) {
console.log(result);
ph.exit();
});
}, 5000);
});
});
});
});
but i get this error :
return ph.createPage(function (page) {
^
TypeError: ph.createPage is not a function
Is what I am about to do is the best way to do what I want to do? If not what is the simplest way? If so, where does my error come from?
If You dont have to use phantomjs You can use nightmare to do it.
It is pretty neat library to solve problems like yours, it uses electron as web browser and You can run it with or without showing window (You can also open developer tools like in Google Chrome)
It has only one flaw if You want to run it on server without graphical interface that You must install at least framebuffer.
Nightmare has method like wait(cssSelector) that will wait until some element appears on website.
Your code would be something like:
const Nightmare = require('nightmare');
const nightmare = Nightmare({
show: true, // will show browser window
openDevTools: true // will open dev tools in browser window
});
const url = 'http://hakier.pl';
const selector = '#someElementSelectorWitchWillAppearAfterSomeDelay';
nightmare
.goto(url)
.wait(selector)
.evaluate(selector => {
return {
nextPage: document.querySelector(selector).getAttribute('href')
};
}, selector)
.then(extracted => {
console.log(extracted.nextPage); //Your extracted data from evaluate
});
//this variable will be injected into evaluate callback
//it is required to inject required variables like this,
// because You have different - browser scope inside this
// callback and You will not has access to node.js variables not injected
Happy hacking!

Mocha framework to test outbound client request

My usecase:
Implement an automation test to capture onbound client request after opening a page in browser. For example, open http://foo.com that later makes beacon call to http://bar.com with few parameters.
Question:
How do I test whether foo.com has initiated a call to bar.com? Can mocha do this?
Answering my own question.
I found a way to capture all requests being made by a page using phantomjs, it has a node module called phantom (https://www.npmjs.com/package/phantom) that can open a page and a listener would give all resources being requested.
Sample javascript code,
var phantom = require('phantom');
phantom.create(function (ph) {
ph.createPage(function (page) {
page.open("http://ramcountry.yahoo.com", function (status) {
console.log("opened site? ", status);
});
page.set('onResourceRequested', function(requestData, networkRequest) {
console.log("requested: ", requestData.url);
});
page.set('onResourceReceived', function(requestData, networkRequest) {
console.log("received: ", requestData.url);
});
});
});
Mocha (by design) doesn't provide this kind of thing, but can integrate with other tools (as you noted in your other answer) to provide test benefits. However your answer didn't display any testing, so I'm going to drop a few frameworks in here specifically designed for testing:
http://nightwatchjs.org/
http://www.cypress.io/
http://webdriver.io/

How to throw an exception from JavaScript's callback if it is executed via Selenium's executeAsyncScript

I'm using Selenium WebDriver to automate some scripts. Most of the functionality is executed using JavaScript endpoints and I could not move this logic to Python:
// Python Selenium script
data = self.driver.execute_async_script('selenium.get_data(arguments)')
// JavaScript placed somewhere on the page tested
selenium.get_data = function(args) {
$.ajax({
url:'http://servername/ajax_data',
success: function(data) {
args[0](data);
},
error: function(data) {
// here I would like to notify selenium that everything is broken
}
});
};
There is usually some point in the JavaScript where I know that everything is already broken and I would like to raise exception in Selenium script.
Of course I could wait for timeout, but my scripts' timeouts are pretty long and I could not provide additional debug information in the error message.
I've already checked documentation (http://selenium.googlecode.com/svn/trunk/docs/api/java/org/openqa/selenium/JavascriptExecutor.html) and tests' source code (http://code.google.com/p/selenium/source/browse/trunk/java/client/test/org/openqa/selenium/ExecutingAsyncJavascriptTest.java?r=15810).
For now I'm using workaround, that just does not seem good:
error: function(data) {
window.alert(JSON.stringify(data));
}
Do you know any better solutions?

Categories