Why is ic-ajax not defined within certain functions in Ember CLI? - ember-cli

Forgive my ignorance, but I can't get ic-ajax working inside of certain
functions.
Specifically, I'd like to get a test like this working, but for Ember CLI:
e.g. http://coderberry.herokuapp.com/testing-your-ember-application#30
I can call ajax inside Ember.Object.Extend and outside of functions and object definitions, but not in modules, tests, or Ember.Route's model function.
Am I misunderstanding something or is there a misconfiguration in my app?
I've figured out that within functions I can do:
ajax = require('ic-ajax')['default'];
defineFixture = require('ic-ajax')['defineFixture'];
but I'm pretty sure import at the top of the file is supposed to work.
I'm experiencing this on Ember 0.40.0 (both in my existing app and a fresh app). See below for more specifics where I'm finding it undefined. Setting var ajax = icAjaxRaw outside of the functions does not work either. I'm at a bit of a loose end so any help you could give in this regard would be great.
users-test.js:
import ajax from 'ic-ajax';
import { raw as icAjaxRaw } from 'ic-ajax';
import { defineFixture as icAjaxDefineFixture } from 'ic-ajax';
debugger;
---> icAjaxDefineFixture IS defined here
module('Users', {
setup: function() {
App = startApp();
debugger;
icAjaxDefineFixture --> UNDEFINED
},
teardown: function() {
Ember.run(App, App.destroy);
}
});
test("Sign in", function() {
icAjaxDefineFixture --> UNDEFINED
expect(1);
visit('/users/sign-in').then(function() {
equal(find('form').length, 1, "Sign in page contains a form");
});
});
Brocfile.js (I don't think these are actually needed with the new ember-cli-ic-ajax addon):
app.import('vendor/ic-ajax/dist/named-amd/main.js', {
exports: {
'ic-ajax': [
'default',
'defineFixture',
'lookupFixture',
'raw',
'request',
]
}
});

Had the same problem. Turns out it is a Chrome debugger optimization issue, checkout this blog post http://johnkpaul.com/blog/2013/04/03/javascript-debugger-surprises/
While debugging, if you try to use a variable from a closure scope in the console, that wasn’t actually used in the source, you’ll be surprised by ReferenceErrors. This is because JavaScript debuggers optimize the hell out of your code and will remove variables from the Lexical Environment of a function if they are unused.
To play around in debugger, I've just typed ajax; inside of the closure and variable magically appeared.

Related

"Import" doesn't work on the spec file on Cypress

If someone could help me on this please.
I have created page objects with the following code:
class Login {
username(){
return cy.get('#UserName').type('test1')
}
password(){
return cy.get('#password-field').type('test2')
}
loginbtn(){
return cy.get('.btn').click()
}
}
export default Login
Here I have created class Login and imported on the spec file as:
import Login from '../support/PageObjects/Login'
beforeEach('Login to shipment page',() => {
cy.Login()
})
This was working before but now this is not working and I get the error (on hover) telling "Login is declared but it's value is never read." I have changed nothing. I am facing this issue many times but never got the proper solution for this.
The login is not needed to be imported when you have a custom command like cy.Login().
That is why the error occurs:
'Login' is declared but it's value is never read.
Custom commands are global to all tests and never need importing. The Login page is being added to the tests via cy.Login() and you can remove the import without affecting it.
This has to be something to do with your custom command cy.Login(), I imagine the code for it to be something like below:
// cypress/support/commands.js
const login = new require('../PageObjects/Login.js')
Cypress.Commands.add('Login', () => {
login.username()
login.password()
login.loginbtn()
})
Now that of course needs to be imported into cypress/support/e2e.js, but that is the default - check it anyway.
// cypress/support/e2e.js
import './commands.js'
If you are using the Typescript, options are similar.
By the way, what is the file you are having the error from? I suspect that will give a clue.
You have to create an object of the class Login and using that you can access the different methods. So your code should look like this:
import Login from '../support/PageObjects/Login'
const login = new Login()
beforeEach('Login to shipment page', () => {
login.username()
login.password()
login.loginbtn()
})

Office JavaScript API: selecting a range in Word for Mac

I'm working on a side project using the Microsoft Office JavaScript APIs. I have some functionality working to select a range in order to scroll to a particular position within a document. This works as expected in Office for the web, but in Office for Mac I get the following error when calling context.sync().then():
Unhandled Promise Rejection: RichApi.Error: ItemNotFound
I can't find any documentation on that particular error, and I'm not sure how to troubleshoot what I might be doing wrong. What am I missing? Like I said, this works in the web interface.
Here is minimal sample of code that demonstrates the problem:
function UI(context) {
this.context = context;
}
UI.prototype.initialize = function() {
var paragraphs = this.context.document.body.paragraphs;
this.context.load(paragraphs);
document.querySelector('button').addEventListener('click', () => {
this.context.sync().then(() => {
this.goToRange(paragraphs.items[0]);
});
});
};
UI.prototype.goToRange = function(range) {
range.select();
this.context.sync();
};
document.addEventListener('DOMContentLoaded', () => {
Office.onReady(() => {
Word.run(context => {
return context.sync().then(() => {
new UI(context).initialize();
});
});
});
});
The only thing I can think of is that maybe the reference to the paragraph client object becomes "stale" in some sense, perhaps based on some resource limits that are lower in the Mac application than in the online interface? (That would be counterintuitive to me, but it's the only thing that comes to mind.)
I think I figured out the problem. I stumbled upon a hint while putting together the minimum code sample in the question; I removed a little too much code at first and encountered the following error:
Unhandled Promise Rejection: RichApi.Error: The batch function passed
to the ".run" method didn't return a promise. The function must return
a promise, so that any automatically-tracked objects can be released
at the completion of the batch operation.
I believe the issue is that, at least in Word for Mac, you can't use the context object provided by Word.run in an asynchronous event listener. I'm guessing this is because, as the above error states, some state has been released after resolving the promise returned. I can get the code to work by adding a dedicated call to Word.run (and using the fresh context provided) inside the event listener.
It is still a little odd that it works just fine in the browser. Presumably, the same state is not released as aggressively in the browser-based version.

How to get karma to run a init function first?

Ive got a weird problem, Ive got a JS library I pull down from a CDN, and before I can use it I need to run an init function on it, and then run my tests. Anyone got any ideas how I can do that?
In my actual project I call the init function first, then call the rest of my code from the inits callback, but I just cant figure out how to do this for a test
You can list CDNs in your karma config:
files : [
'http://theurl.totheserver/thelibrary.js',
Then assuming the library has initialization function that takes a callback function as a parameter:
describe("My tests", function() {
before(function(done) {
myLibrary.initialization(done);
});
describe("My test cases", function() {
However I would consider using Bower to manage your front end dependencies rather than relying on CDNs.

IPython/Jupyter Installing Extensions

I'm having troubles installing extensions in IPython. The problem is that i can't get the extensions load automatically, i have followed the instructions in the github page but it just doesn't work. According the the homepage i need to modify the custom.js file by adding some lines. I want to install the codefolding, hide_input_all and runtools extensions. This is how my custom.js file looks:
// activate extensions only after Notebook is initialized
require(["base/js/events"], function (events) {
$([IPython.events]).on("app_initialized.NotebookApp", function () {
/* load your extension here */
IPython.load_extensions('usability/codefolding/codefolding')
IPython.load_extensions('usability/runtools/runtools')
require(['/static/custom/hide_input_all.js'])
});
});
The extensions work well if i call them manually, for example, if i type
%%javascript
IPython.load_extensions('usability/runtools/runtools/main');
the runtools appear and works perfectly, but i want the extensions to be loaded automatically and not to have to call them manually every time. Could someone tell me where is my mistake?
There's been a little change to the syntax. Nowadays, $ might not be defined by the time your custom.js loads, so instead of something like
$([IPython.events]).on("app_initialized.NotebookApp", function () {
IPython.load_extensions("whatever");
});
you should do something like
require(['base/js/namespace', 'base/js/events'], function(IPython, events) {
events.on('app_initialized.NotebookApp', function(){
IPython.load_extensions("whatever");
})
});
with the appropriate changes to braces and parentheses. For me, the former will work more often than not, but certainly not always; it fails maybe ~1/3 of the time.
If that doesn't do it for you, open up Developer Tools (or whatever is relevant for your browser) and look at the javascript console for errors. That'll help figure out what's going wrong.

CKEditor: how to remove a plugin that has been added?

I'm just beginning to use CKEditor, but have a hard time understanding the plugins system.
I was able to add a simple button that says 'Test' when you click on it with :
var myplugin_function = function () {
alert('Test');
}
var plugin_name='myplugin';
CKEDITOR.plugins.add(plugin_name,
{
init:function(c) {
c.addCommand(plugin_name,myplugin_function);
c.ui.addButton(plugin_name,
{
label:'This is my plugin',
command:plugin_name,
icon:this.path+'myplugin.png'
});
}
});
I know this code should be executed only once, for example in a plugin.js, but that's not how I use it. The CKEditor instance, including my plugin code is executed each time the Ajax-page is loaded.
That's why I use this to remove the instance, if it exists :
if (CKEDITOR.instances['mytextarea']) {
CKEDITOR.remove(CKEDITOR.instances['mytextarea']);
}
Then I use the jquery way to create the ckeditor from a textarea:
$('#mytextarea').ckeditor();
But the 2nd time the ajax-page loads, I get an error about the plugin already being registered. So I need a way to remove the plugin and be able to add it again.
Is this even possible?
UPDATE
This seems to work :
I now check if the plugin is already registered with :
if (!CKEDITOR.plugins.registered[plugin_name]) {
}
around the CKEDITOR.plugins.add(b, ... part
You are not showing how you are adding the plugin, so it's hard to tell what's your exact problem; but from the code that you have provided I can suggest that you use variable names better than "a", "b" and "c". It's quite harder to understand the code this way.
Also, CKEDITOR.remove just removes the instance from the instances array, but it doesn't really clear the used resources, you should use CKEDITOR.instances['mytextarea'].destroy( true ) instead