I have written some test case using CasperJS.
var baseUrl = "http://cng20018241:9090";
var require = patchRequire(require);
casper.options.viewportSize = {
width: 1024,
height: 800
}
casper.test.begin('Connecting to site', function suite(test) {
casper.start(baseUrl, function() {
this.wait(5000, function() {
this.echo("I've waited for 5 seconds.");
});
})
.then(function(){
this.captureSelector('c:\\temp\\screenshot.png', 'html')}
)
.run(function() {
casper.echo("TESTS COMPLETED", "GREEN_BAR");
casper.exit();
});
});
var partial = function(func /*, 0..n args */) {
var args = Array.prototype.slice.call(arguments, 1);
return function() {
var allArguments = args.concat(Array.prototype.slice.call(arguments));
return func.apply(this, allArguments);
};
};
The above code is capturing the screen shot for a site developed using meteor. But if I change the url to a site developed using ExtJs, casperjs only produce screenshot which is black. it does not capture the actual screen.
Both the sites are internal sites. The site developed using ExtJs (not working) uses windows authentication.
What options do I have now?
After registering various events, I am getting following error:
ResourceError: {
"errorCode": 5,
"errorString": "Operation canceled",
"id": 0,
"url": "http://cng20018241:9090/"
}
Related
I have implemented the google analytics embedded api in angularjs app it is working fine for the first time when refresh the page but after go to another route and coming back to the analytics page not showing the data.
the flowing image is the result after reloading the page.
when open the route without reload not showing the details this is screenshot of page in this time
this is my code at the header of the page
(function(w, d, s, g, js, fs) {
g = w.gapi || (w.gapi = {});
g.analytics = {
q: [],
ready: function(f) {
this.q.push(f);
}
};
js = d.createElement(s);
fs = d.getElementsByTagName(s)[0];
js.src = 'https://apis.google.com/js/platform.js?96543238954346785456789';
js.id = "googleCache";
js.async = 1;
// js.defer = true;
fs.parentNode.insertBefore(js, fs);
js.onload = function() {
g.load('analytics');
};
}(window, document, 'script'));
this the code which I have in controller
gapi.analytics.ready(function() {
// Step 3: Authorize the user.
var CLIENT_ID = "544116918374-r7mlqhknk2oj4mp5ia9ffss96e6ats6s.apps.googleusercontent.com";
gapi.analytics.auth.authorize({
clientid: CLIENT_ID,
container: 'auth-button'
})
// Step 4: Create the view selector.
var viewSelector = new gapi.analytics.ViewSelector({
container: 'view-selector'
});
// // Step 5: Create the timeline chart.
var timeline = new gapi.analytics.googleCharts.DataChart({
reportType: 'ga',
query: {
'dimensions': 'ga:date',
'metrics': 'ga:sessions',
'start-date': '30daysAgo',
'end-date': 'today',
},
chart: {
type: 'LINE',
container: 'timeline',
options: {
title: 'Visits per day',
}
}
});
// Step 6: Hook up the components to work together.
gapi.analytics.auth.on('success', function(response) {
viewSelector.execute();
});
viewSelector.on('change', function(ids) {
// console.log(ids);
var newIds = {
query: {
ids: ids
}
}
timeline.set(newIds).execute();
});
});
The Google analytics embedded api is based upon the Google APIs JavaScript client library. JavaScript is a client sided langue.
Refresh tokens are not supported in this authorization method.
I have seen something in the past where something like node.js was used to request a new access token using the refresh token and this was then set to the front end JS code. This is a little Hacky imo.
We're currently developing a Office UI addin using React. The addin should make a connection with a backend api and authenticate the user using bearer tokens. The backend api is protected by Azure AD.
We based our solution on the example that is offered by Microsoft: https://github.com/OfficeDev/PnP-OfficeAddins/tree/master/Samples/auth/Office-Add-in-Microsoft-Graph-React This uses msal.js for the authentication.
The login dialog is opened like so:
await Office.context.ui.displayDialogAsync(dialogLoginUrl, { height: 40, width: 30 }, result => {
if (result.status === Office.AsyncResultStatus.Failed) {
displayError(`${result.error.code} ${result.error.message}`);
} else {
loginDialog = result.value;
loginDialog.addEventHandler(Office.EventType.DialogMessageReceived, processLoginMessage);
loginDialog.addEventHandler(Office.EventType.DialogEventReceived, processLoginDialogEvent);
}
});
And the following code runs within the dialog:
import { UserAgentApplication } from "msal";
(() => {
// The initialize function must be run each time a new page is loaded
Office.initialize = () => {
const config = {
auth: {
clientId: "",
authority: "",
redirectUri: "https://localhost:3000/login.html",
navigateToLoginRequestUrl: false
},
cache: {
cacheLocation: "localStorage",
storeAuthStateInCookie: false
}
};
const userAgentApp = new UserAgentApplication(config);
const authCallback = (error, response) => {
if (!error) {
if (response.tokenType === "id_token") {
localStorage.setItem("loggedIn", "yes");
} else {
// The tokenType is access_token, so send success message and token.
Office.context.ui.messageParent(JSON.stringify({ status: "success", result: response.accessToken }));
}
} else {
const errorData = `errorCode: ${error.errorCode}
message: ${error.errorMessage}
errorStack: ${error.stack}`;
Office.context.ui.messageParent(JSON.stringify({ status: "failure", result: errorData }));
}
};
userAgentApp.handleRedirectCallback(authCallback);
const request = {
scopes: ["api://..."]
};
if (localStorage.getItem("loggedIn") === "yes") {
userAgentApp.acquireTokenRedirect(request);
} else {
// This will login the user and then the (response.tokenType === "id_token")
// path in authCallback below will run, which sets localStorage.loggedIn to "yes"
// and then the dialog is redirected back to this script, so the
// acquireTokenRedirect above runs.
userAgentApp.loginRedirect(request);
}
};
})();
Unfortunately this doesn't seem lead to a stable addin. The authentication dialog sometimes works as expected, but sometimes it doesn't. In Outlook on macOS it seems to work fine, but in Outlook on Windows the handling of the callback is not always working correctly. Also in the web version of Outlook it doesn't work as expected.
The question is whether someone has a working solution using React and msal.js in a Outlook addin.
I am currently using ApplicationInsights-JS in my progressive web app. It works in my react components as I can import what I need from the relevant npm packages.
In my service worker however, I can only import logic using importScripts.
I did manage to find a CDN for ApplicationInsights-JS on their Github page however it seems that in order to initialise app insights using this library you need to have access to window in order to store the appinsights, which you cannot do from a service worker.
I tried to use the web snippet approach since the CDN seemed to be
related to that particular library, but I can't use window and am not sure how else to implement this solution.
This is a copy paste of the suggested snippet to init the app insights object from: https://github.com/Microsoft/ApplicationInsights-JS
importScripts('https://az416426.vo.msecnd.net/beta/ai.2.min.js');
const sdkInstance = 'appInsightsSDK';
window[sdkInstance] = 'appInsights';
const aiName = window[sdkInstance];
const aisdk =
window[aiName] ||
(function(e) {
function n(e) {
i[e] = function() {
const n = arguments;
i.queue.push(function() {
i[e](...n);
});
};
}
let i = { config: e };
i.initialize = !0;
const a = document;
const t = window;
setTimeout(function() {
const n = a.createElement('script');
(n.src = e.url || 'https://az416426.vo.msecnd.net/next/ai.2.min.js'),
a.getElementsByTagName('script')[0].parentNode.appendChild(n);
});
try {
i.cookie = a.cookie;
} catch (e) {}
(i.queue = []), (i.version = 2);
for (
const r = [
'Event',
'PageView',
'Exception',
'Trace',
'DependencyData',
'Metric',
'PageViewPerformance'
];
r.length;
)
n(`track${r.pop()}`);
n('startTrackPage'), n('stopTrackPage');
const o = `Track${r[0]}`;
if (
(n(`start${o}`),
n(`stop${o}`),
!(
!0 === e.disableExceptionTracking ||
(e.extensionConfig &&
e.extensionConfig.ApplicationInsightsAnalytics &&
!0 ===
e.extensionConfig.ApplicationInsightsAnalytics
.disableExceptionTracking)
))
) {
n(`_${(r = 'onerror')}`);
const s = t[r];
(t[r] = function(e, n, a, t, o) {
const c = s && s(e, n, a, t, o);
return (
!0 !== c &&
i[`_${r}`]({
message: e,
url: n,
lineNumber: a,
columnNumber: t,
error: o
}),
c
);
}),
(e.autoExceptionInstrumented = !0);
}
return i;
})({ instrumentationKey: 'xxx-xxx-xxx-xxx-xxx' });
(window[aiName] = aisdk),
aisdk.queue && aisdk.queue.length === 0 && aisdk.trackPageView({});
I get window is not defined which is expected, but I'm not sure how else I can make use of this library from the service worker.
Has anyone else had a similar implementation in which they successfully logged telemetry using ApplicationInsights from a service worker?
I realised that I was over complicating this.
Since I only needed to track a custom event, and didn't need all the automated page tracking etc that appInsights does, I ended up doing a fetch from my service worker.
I just copied the header and body format from the requests that I made using my react pages.
The below successfully logged telemetry to my app insights dashboard:
fetch(url, {
method: 'post',
headers: {
'Content-type': 'application/json'
},
body: JSON.stringify([
{
time: '2019-05-02T15:56:37.589Z',
iKey: 'INSTRUMENTATION_KEY',
name:
'Microsoft.ApplicationInsights.INSTRUMENTATION_KEY.Event',
tags: {
'ai.user.id': 'l6Tey',
'ai.session.id': 'TL+Ry',
'ai.device.id': 'browser',
'ai.device.type': 'Browser',
'ai.operation.id': 'HUfNE',
SampleRate: '100',
// eslint-disable-next-line no-script-url
'ai.internal.sdkVersion': 'javascript:2.0.0-rc4'
},
data: {
baseType: 'EventData',
baseData: {
ver: 2,
name: 'Testing manual event',
properties: {},
measurements: {}
}
}
}
])
})
.then(json)
.then(function(data) {
})
.catch(function(error) {
});
I've almost managed to use Microsoft Application Insights in our app's service worker.
The key parts are:
Using the lightweight version of appInsights (see this small remark at 4th step) with importScripts('https://az416426.vo.msecnd.net/next/aib.2.min.js').
Initialize an appInsights object:
appInsights = new Microsoft.AppInsights.AppInsights({ instrumentationKey: "[replace with your own key]" });
when track needed (during onpush event or onnotificationclick), go for appInsight.track({ eventItemFields }) then appInsights.flush().
I've said "almost" because the flush part seems to not working, I've got: "Sender was not initialized" internal error after enabling debugging.
I will publish here a working sample code if I successfully manage this issue.
References:
https://github.com/Azure-Samples/applicationinsights-web-sample1/blob/master/testlightsku.html
This response to the question: How to add analytics for Push notifications.
Using the Web SDK in a service worker is troublesome. The full version depends on a window object, while the basic SDK depends on Beacon or XmlHttpRequest for sending the messages (in file https://github.com/microsoft/ApplicationInsights-JS/blob/master/channels/applicationinsights-channel-js/src/Sender.ts):
if (!_self._senderConfig.isBeaconApiDisabled() && Util.IsBeaconApiSupported()) {
_self._sender = _beaconSender;
} else {
if (typeof XMLHttpRequest !== undefined) {
const xhr:any = getGlobalInst("XMLHttpRequest");
if(xhr) {
const testXhr = new xhr();
if ("withCredentials" in testXhr) {
_self._sender = _xhrSender;
_self._XMLHttpRequestSupported = true;
} else if (typeof XDomainRequest !== undefined) {
_self._sender = _xdrSender; // IE 8 and 9
}
}
}
}
At the moment Application Insights SDK does not seem to support service workers. Rajars solution seems to be the best option for now.
Update: There is an issue in the Github Repo about this: https://github.com/microsoft/ApplicationInsights-JS/issues/1436
A suggestion that works is by using the basic/lightweight version of Application Insights (as mentioned by Rajar) and adding a XMLHttpRequest polyfill (that uses the fetch api) before inititializing Application Insights. After that you can use the lightweight version.
An example can be found here: https://github.com/Pkiri/pwa-ai
I was trying to use AppInsightsSDK in E2E tests environment (pupeteer) and when I tried to log event or metric I got with "Sender was not initialized" error.
As #Pkiri mentioned one would need XMLHttpRequest polyfill to solve the issue. Although my scenario is not directly related to Service worker I wanted to mention that #Pkiri answer is not entirely true, because one can also use globalThis, self, window or global to get the same result according to SDK source code function getGlobalInst("XMLHttpRequest"); resolves to
function getGlobal() {
if (typeof globalThis !== strShimUndefined && globalThis) {
return globalThis;
}
if (typeof self !== strShimUndefined && self) {
return self;
}
if (typeof window !== strShimUndefined && window) {
return window;
}
if (typeof global !== strShimUndefined && global) {
return global;
}
return null;
}
And for my scenario this was a valid solution
const appInsights = new ApplicationInsights({
config: {
instrumentationKey: 'AppInsights_InstrumentationKey',
},
});
global.XMLHttpRequest = require("xmlhttprequest").XMLHttpRequest;
global.appInsights = appInsights.loadAppInsights();
I've searched a lot for this problem that I'm stuck on for a week.
I have an Ionic PWA project that receive some notifications from firebase, I can receive the notifications with no problem and can get the payload on foreground (app is open), but I cant get the payload when the app is closed and I don't figure out what is goning on, so I came here to ask the masters to help me.
messaging.setBackgroundMessageHandler(function(payload) {
var notificationTitle = 'Teste';
var notificationOptions = {
body: 'Background Message body.',
tag: 'campanhas',
data: payload.data,
icon: 'https://firebasestorage.googleapis.com/v0/b/hemotomobile-edeb9.appspot.com/o/logo.png?alt=media&token=4a9fc487-b8cf-4d3c-875c-774454ff6f50'
};
return self.registration.showNotification(notificationTitle,
notificationOptions);
});
self.addEventListener('notificationclick', function(event) {
event.notification.close();
event.waitUntil(clients.matchAll({
type: "window"
}).then(function(clientList) {
for (var i = 0; i < clientList.length; i++) {
var client = clientList[i];
if (client.url == '/' && 'focus' in client)
return client.focus();
}
if (clients.openWindow)
return clients.openWindow('/');
}));
});
and on my provider for the notifications, I use this code:
public receiveMessage() {
console.log('notification')
this.messaging.onMessage((payload) => {
console.log('payload',payload)
});
}
I call this provider on my tabs-page:
ionViewDidLoad(){
this.notification.receiveMessage()
}
So, can anyone help me to get the payload when the PWA is closed?
have you tried by initializing firebase in the service worker and using it ,
self.addEventListener("notificationclick", (event) => {
//your code
});
importScripts("https://www.gstatic.com/firebasejs/4.7.0/firebase.js")
importScripts("https://www.gstatic.com/firebasejs/4.7.0/firebase-messaging.js")
// Initialize Firebase
firebase.initializeApp({
'messagingSenderId': 'your sender id'
});
const messaging = firebase.messaging();
messaging.setBackgroundMessageHandler(function(payload) {
//your code
});
this.messaging.onMessage((payload) => {
//your code
});
self.addEventListener('notificationclose', function (event) {
self.registration.getNotifications().then(function (notifications) {
notifications.forEach(function (notification) {
notification.close()
})
});
})
I have tried by using above code in the service worker and it is showing notification when the application is closed , if you want to show the notification when the browser is closed make sure you have enabled the Continue running background apps when Google Chrome is closed option in chrome settings.
When i use my cordova app in the home page, i need to display message to user to ask him if he really want to exit app or not.
Than i need to exit app if user select "yes".
To do it, i use this code :
document.addEventListener('backbutton', function() {
$rootScope.back();
$rootScope.$apply();
}, false);
$rootScope.back = function(execute) {
var path = $location.$$path;
if (path !== '/') {
$location.path(path.split('/').slice(0, -1).join('/'));
} else {
$rootScope.exitApp();
}
}.bind(this);
$rootScope.exitApp = function() {
$rootScope.$emit('showPopover', {
message: $rootScope.LABELS.QUIT_APP,
confirmCallback: function() {
if (typeof navigator.app !== 'undefined') {
navigator.app.exitApp();
}
},
cancelCallback: doNothing
});
};
It's working in android and iOS, but not in Windows 10 app.
In W10, navigator.app is undefined.
I read that i'm supposed to suspend app and not exit it, so i tried this windows quirkswritten in cordova doc (https://cordova.apache.org/docs/en/latest/cordova/events/events.html#backbutton) :
$rootScope.exitApp = function() {
$rootScope.$emit('showPopover', {
message: $rootScope.LABELS.QUIT_APP,
confirmCallback: function() {
if (typeof navigator.app !== 'undefined') {
navigator.app.exitApp();
}
else if (platformUtils.isWindows()) {
throw new Error('Exit'); // This will suspend the app
}
},
cancelCallback: doNothing
});
};
throw new Error('Exit') is called and display error in logs, but app is not suspended.
Maybe because i'm in a angular app?
Does any one has an idea?
You could also use this:
if (device.platform.toLowerCase() === "windows") {
//this closes the app and leaves a message in the windows system eventlog if error object is provided
MSApp.terminateApp();
} else {
navigator.app.exitApp()
}
Problem is due to $emit used to display popover.
If i throw error on popover callback, this error is not returned to backbutton event callback.
But, on windows platform, we are not supposed to display popover to ask if user is sure to want to leave app, so if I add it to "back" function, it's working.
Final code used to Windows 10 app is :
document.addEventListener('backbutton', function() {
$rootScope.back();
$rootScope.$apply();
}, false);
$rootScope.back = function(execute) {
var path = $location.$$path;
if (path !== '/') {
$location.path(path.split('/').slice(0, -1).join('/'));
} else {
if (window.device.platform.toLowerCase() === 'windows') {
throw new Error('Exit'); // This will suspend the app
} else {
$rootScope.exitApp();
}
}
}.bind(this);