Extend Office JavaScript API with own Browser Control - vsto

I'm trying to write a VSTO-Add-In with a System.Windows.Forms.WebBrowser-Control enabling something similar to the Office-JS-Add-In model.
The WebBrowser-control would show some HTML/JS-Page and be able to call C#-functions in the VSTO-Add-In from JavaScript via window.external and the ObjectForScripting-property of the WebBrowser-object.
That is in JS the call would be
window.external.DoFancyStuffToMyDocument(withTheseParams)
while there had to be some
class MyFunctionProxy() {
public void DoFancyStuffToMyDocument(string theParam) {
//code here
}
}
in the C#-Code an this would be attached to the WebBrowser
myWebBrowser.ObjectForScripting = new MyFunctionProxy();
So far so good. Now comes the catch. I want my HTML/JS-Code be able to also utilize the office.js code and functions like
Word.run(function (context) {
var thisDocument = context.document;
var range = thisDocument.getSelection();
range.insertText('"Hitch your wagon to a star."\n', Word.InsertLocation.replace);
//...
}
Does anyone see a way of getting this to work?
My initial guess was that the OfficeJS-taskpane-add-ins in Word on-prem use some some similar methode as above with a class derived from WebBrowser and the appropriate ObjectForScripting. This would then suggest that there must be a (hopefully accessible) class which is assigned to the ObjectForScripting-property handling the function calls from office.js. Then I could proxy this ObjectForScripting-class and add my own functions like 'DoFancyStuffToMyDocument()'.

Related

How do I get Xtext's model from a different plugin?

I've written an Xtext-based plugin for some language. I'm now interested in creating a new independent view (as a separate plugin, though it requires my first plugin), which will interact with the currently-active DSL document - and specifically, interact with the model Xtext parsed (I think it's called the Ecore model?). How do I approach this?
I saw I can get an instance of XtextEditor if I do something like this when initializing my view:
getSite().getPage().addPartListener(new MyListener());
And then, in MyListener, override partActivated and partInputChanged to get an IWorkbenchPartReference, which is a reference to the XtextEditor. But what do I do from here? Is this even the right approach to this problem? Should I instead use some notification functionality from the Xtext side?
Found it out! First, you need an actual document:
IXtextDocument doc = editor.getDocument();
Then, if you want to access the model:
doc.modify(new IUnitOfWork.Void<XtextResource>() { // Can also use just IUnitOfWork
#Override public void process(XtextResource state) throws Exception {
...
}
});
And if you want to get live updates whenever it changes:
doc.addModelListener(new IXtextModelListener() {
#Override public void modelChanged(XtextResource resource) {
for (EObject model : resource.getContent()) {
...
}
}
});

TDD Best Practice In Using Restful Api in Yii application

I'm constantly looking for the best way to use TDD in Yii app development. Nowday most web app are composed by a fronted, an API layer (usually JSON) to provide async calls to the server and a backend. By my side, most used test in this of app are unit tests and functional ones. The latter the most widely showed in guides and books leverage PHPUnit + Selenium, but Behat + Mink seems very cool too (but I'm not really confident with it yet)
If you ever used functional tests that use a browser (like Selenium) you know that the less you have to run them the better you feel. This cause they're slower, harder to maintain and sometimes (like the popup FB Login using JS SDK) are painful.
When working with a single web page application I care about testing JSON output of my apis. I'd like to test these functionalities with a unit test like approach in order to have faster tests that are easier to maintain. Considering that most of my Controller's action are availaible to Logged only user using accessControl filter I wondered on the best ways to have my tests up and running.
At this moment I think to have two ways to accomplish this
use cUrl toward the desired enpoint to get the JSON directly invoke
the controller's function
In the first scenario I can use fixtures but I got no way to mock CWebUser class (to emulate a logged user), using Apache when the cUrl comes it gets executed by an instance of my CWebApplication that is not the one executed by PHPUnit. I can get rid of this problem by making all my API calls stateless and, as a consequence, removing accessControl filter.
In the second one the only way I found to mock CWebUser class is to override it in the test class that I'm executing. This approach pays until I dont need to test use cases requiring different type of user, and I got no way to change at runtime (or at setup time) my webuser mock. The only way I found to mock my webuser is the one you can find below, this cause $this->getMock('WebUser') doesnt affect anyway CWebApplication's WebUser (read-only) singleton defined in the configuration file.
Here comes a concrete example:
class UserControllerTest extends CDbTestCase
{
public $fixtures=array(
/* NEEDED FIXTURES*/
);
public function testUserCanGetFavouriteStore() {
$controller = new UserController(1);
$result = json_decode($controller->actionAjaxGetFavStore());
$this->assertInternalType('array', $result->data);
$model = $result->data[0];
$this->assertEquals($model->name, "Nome dello Store");
}
}
class WebUser extends CWebUser {
public function getId() {
return 1;
}
public function getIsGuest() {
return false;
}
};
I was wondering if being able to authenticate with the api interface, either by an API key or a user/password combo could be useful.
This is ok if I move toward a almost stateless API integration, but most of the time I just have controller's actions (permitted to logged user only) that returns Json data to populate the frontend.
Anyone can suggest me a better method? Maybe it's just useless to test this kind of JSON output?
Best Regards
Maybe I'm oversimplifying your problem. It sounds like you want to emulate user logins before running the test? If that's the case, why not just create a User object in your fixture and actually log them in before running a test, and log them out after?
Something like:
/**
* Sets up before each test method runs.
* This mainly sets the base URL for the test application.
*/
protected function setUp()
{
parent::setUp();
// login as registered user
$loginForm = new UserLoginForm();
$loginForm->email = USER_EMAIL; // use your fixture
$loginForm->password = USER_PASSWORD; // use your fixture
if(!$loginForm->login()) {
throw new Exception("Could not login in setup");
}
}
protected function tearDown()
{
parent::tearDown();
Yii::app()->user->logout(true);
}
Ok actually the only solution that me and my team found is creating a stub WebUser class.
Rewriting WebUser class in this way you can authenticate a user without having Yii relying on the session.
class WebUserMock extends WebUser {
public function login($identity,$duration=0)
{
$id=$identity->getId();
$states=$identity->getPersistentStates();
if($this->beforeLogin($id,$states,false))
{
$this->changeIdentity($id,$identity->getName(),$states);
$duration = 0;
if($duration>0)
{
if($this->allowAutoLogin)
$this->saveToCookie($duration);
else
throw new CException(Yii::t('yii','{class}.allowAutoLogin must be set true in order to use cookie-based authentication.',
array('{class}'=>get_class($this))));
}
$this->afterLogin(false);
}
return !$this->getIsGuest();
}
public function changeIdentity($id,$name,$states)
{
$this->setId($id);
$this->setName($name);
$this->loadIdentityStates($states);
}
// Load user model.
protected function loadUser() {
$id = Yii::app()->user->id;
if ($id!==null)
$this->_model=User::model()->findByPk($id);
return $this->_model;
}
};
In the setUp method of your test class you can login any user (in this case leveraging my fixtures)
//a piece of your setUp() method....
$identity = new UserIdentity($this->users('User_2')->email, md5('demo'));
$identity->authenticate();
if($identity->errorCode===UserIdentity::ERROR_NONE)
Yii::app()->user->login($identity);
As a final thing to do just override the user component in the test configuration file and tell him to use this one:
protected/config/test.php
'user'=>array(
'class' => 'application.tests.mock.WebUserMock',
'allowAutoLogin'=>false,
),
Still not sure that this is the best way to handle it but seems to work fine

Node.js prevent function inspection (toString)

When javascript is run in the browser there is no need to try and hide function code because it is downloaded and viewable in source.
When run on the server the situation changes. There are use cases such as api where you want to provide users with functions to call without allowing them to view the code that which is run.
On our specific case we want to execute user submitted javascript inside node. We are able to sandbox node.js api however we would like to add our own api to this sandbox without users being able to toString the function to view the code which is run.
Does anyone have a pattern or know of a way of preventing users from outputting a functions code?
Update:
Here is a full solution (i believe) based on the accepted answer below. Please note that although this is demonstrated using client side code. You would not use this client side as someone can see the contents of your hidden function by simply reading the downloaded code (although it may provide some basic slow down to inspect the code if you have used a minify).
This is meant for server side use where you want to allow users to run api code within a sandbox env but not allow them to view what the api's do. The sandbox in this code is only to demonstrate the point. It is not an actual sandbox implementation.
// function which hides another function by returning an anonymous
// function which calls the hidden function (ie. places the hidden
// function in a closure to enable access when the wraped function is passed to the sandbox)
function wrapFunc(funcToHide) {
var shownFunc = function() {
funcToHide();
};
return shownFunc;
}
// function whose contents you want to hide
function secretFunc() {
alert('hello');
}
// api object (will be passed to the sandbox to enable access to
// the hidden function)
var apiFunc = wrapFunc(secretFunc);
var api = {};
api.apiFunc = apiFunc;
// sandbox (not an actual sandbox implementation - just for demo)
(function(api) {
console.log(api);
alert(api.apiFunc.toString());
api.apiFunc();
})(api);
If you wrap a callback in a function, you can use another function in that scope which is actually hidden from the callback scope, thus:
function hideCall(funcToHide) {
var hiddenFunc = funcToHide;
var shownFunc = function() {
hiddenFunc();
};
return shownFunc;
}
Then run thusly
var shtumCallBack = hideCall(secretSquirrelFunc);
userCode.tryUnwindingThis(shtumCallBack);
The userCode scope will not be able to access secretSquirrelFunc except to call it, because the scope it would need is that of the hideCall function which is not available.

How can I set up expectations for event registration on a multimock

I am using RhinoMocks 3.6 and would like to use the multimock feature to implement both a class and a interface.
var mocks = new MockRepository();
var project = mocks.StrictMultiMock(
typeof(Project),
typeof(INotifyCollectionChanged));
using (mocks.Record())
{
((INotifyCollectionChanged)project).CollectionChanged += null;
LastCall.Constraints(Is.NotNull()).Repeat.Any();
}
The LastCall is working though. I get this message :
System.InvalidOperationException : Invalid call, the last call has been used or no call has been made (make sure that you are calling a virtual (C#) / Overridable (VB) method).
What am I doing wrong here??
Have you actually checked that the Project class has methods you can override as the error message indicates? I'll assume you have. :-)
I'd suggest you switch to using the AAA syntax instead of record/replay as shown here:
I assume you're wanting to know if the class under test reacts the right way when the CollectionChanged event is fired? If that's the case, you can do it something like this:
var project = MockRepository.GenerateMock<Project, INotifyPropertyChanged>();
project.Expect(p => p.SomeMethod())
.Repeat.Any()
.Raise(p => ((INotifyCollectionChanged)p).CollectionChanged += null,p,new NotifyCollectionChangedEventArgs());

How do you set a custom session when unit testing with wicket?

I'm trying to run some unit tests on a wicket page that only allows access after you've logged in. In my JUnit test I cannot start the page or render it without setting the session.
How do you set the session? I'm having problems finding any documentation on how to do this.
WicketTester tester = new WicketTester(new MyApp());
((MyCustomSession)tester.getWicketSession()).setItem(MyFactory.getItem("abc"));
//Fails to start below, no session seems to be set
tester.startPage(General.class);
tester.assertRenderedPage(General.class);
What I frequently do is to provide a fake WebApplication with overrides for things that I want to mock or stub.
Among the things I override is the method
public abstract Session newSession(Request request, Response response);
which allows you to return a fake session setup with anything you want.
This is in Wicket 1.3 - if you're using 1.4, some of this may have changed, and as noted in another response, it may be related to a wicket bug.
But assuming the interface hasn't changed too much, overriding this method may also be another way of working around the issue in WICKET-1215.
You may be running into WICKET-1215. Otherwise what you're doing looks fine. For example, I have a Junit4 setup method that looks like:
#Before
public void createTester() {
tester = new WicketTester( new MyApp() );
// see http://issues.apache.org/jira/browse/WICKET-1215
tester.setupRequestAndResponse();
MyAppSession session = (MyAppSession) tester.getWicketSession();
session.setLocale(Locale.CANADA);
session.setUser(...);
}
Using Wicket 1.4, I use my normal WebApplication and WebSession implementations, called NewtEditor and NewtSession in my app. I override newSession, where I do the same than in the regular app code, except that I sign in right away. I also override newSessionStore for performance reasons, I copied this trick from WicketTesters code.
tester = new WicketTester(new NewtEditor()
{
#Override
public Session newSession(Request request, Response response)
{
NewtSession session = new NewtSession(request);
session.signIn(getTestDao());
return session;
}
#Override
protected ISessionStore newSessionStore()
{
// Copied from WicketTester: Don't use a filestore, or we spawn lots of threads,
// which makes things slow.
return new HttpSessionStore(this);
}
});