Overriding function "it" in WDIO - testing

I want to override a function "it". I can do it?
old_it = it
it = (name, foo) ->
console.log('111')
old_it(name, foo)
console.log('222')
When I run this code, a message is output to the console that "it = undefined"

You need to correct the properties beforeTest and afterTest in the file wdio.conf.js
...
beforeTest: function (test, context) {
console.log('start test ' + test.title)
},
...
afterTest: function(test, context, { error, result, duration, passed, retries }) {
console.log('finish test ' + test.title)
},
...

Related

Call SQL linter's API from Codemirror with Typescript

I am trying to call an API to lint a SQL query written in Codemirror (actually I use Angular and the wrapper ngx-codemirror)
Unfortunately, I could not call the API because this is considered undefined:
data-analyzer.component.html:81 ERROR TypeError: Cannot read property 'analyzerService' of undefined
at testA (data-analyzer.component.ts:624)
at lintAsync (lint.js:134)
at startLinting (lint.js:152)
at Object.lint (lint.js:248)
at new CodeMirror (codemirror.js:7885)
at CodeMirror (codemirror.js:7831)
at Function.fromTextArea (codemirror.js:9682)
at ctrl-ngx-codemirror.js:64
at ZoneDelegate.invoke (zone-evergreen.js:365)
at Zone.run (zone-evergreen.js:124)
My code is as follow:
<ngx-codemirror
#ref
name="query"
[options]="config"
[(ngModel)]="item.query"
(keypress)="CMonKeyPress($event)"
>
</ngx-codemirror>
config = {
mode: 'text/x-mysql',
showHint: true,
lint: {
lintOnChange: true,
getAnnotations: this.lintSQL
},
gutters: [
'CodeMirror-linenumbers',
'CodeMirror-lint-markers'
]
};
constructor(
private analyzerService: DataAnalyzerService
) {}
lintSQL(a: string, b: LintStateOptions, cm: Editor) {
const found: Annotation[] = [];
// The error occurs here
this.analyzerService.lint(this.item.query).subscribe(
(r: any) => {
console.log(r.data);
},
(err) => {
console.log(err);
}
);
// So far I return an empty array, the focus is to get the results from the service
return found;
}
I would like to know how could I access to the service in the linting function.
Found from this question, the solution is to bind (this) as follow:
getAnnotations: this.lintSQL.bind(this)

How to spyOn a service function within the link of a directive?

I have a directive that uses a service function like so:
angular.module('testModule',
['serviceBeingUsed'])
.directive('testDirective', function(serviceBeingUsed) {
return {
restrict: 'AE',
templateUrl: 'testTemplate.tpl.html',
scope: {
boundVar1: "="
},
link: function(scope) {
scope.getRequiredData = function(data){
//gether data using service
serviceBeingUsed.fetchRequiredData(data).then(
function(result){
scope.requiredData = result;
}
);
};
}
};
});
In the above directive I inject the service I wish to use and this service function gets used within the scope function "getRequiredData()" which is inside the "link" of this directive.
I have my test suite set up like so:
describe('test suite', function () {
var scope,
$rootScope,
$compile,
$q,
element,
isoScope,
serviceBeingUsed;
beforeEach(module('testModule'));
beforeEach( inject( function(_$rootScope_,
_$q_,
_$compile_,
_serviceBeingUsed_) {
$rootScope = _$rootScope_;
$compile = _$compile_;
serviceBeingUsed = _serviceBeingUsed_;
$q = _$q_;
//This is where we create the directive and it's options.
element = angular.element('<test-directive bound-var1="blabla"></test-directive>');
//We create a new scope from the rootScope.
scope = $rootScope.$new();
//Now we compile the HTML with the rootscope
$compile(element)(scope);
//digest the changes
scope.$digest();
//We retrieve the isolated scope scope of the directive
isoScope = element.isolateScope();
}));
Now I have a test which runs and passes wherby I can spyOn the isolated scope function "getRequiredData()", this test looks like so:
it('getRequiredData runs', inject(function () {
spyOn(isoScope,"getRequiredData");
isoScope.getRequiredData();
expect(isoScope.getRequiredData).toHaveBeenCalled();
}));
This proves that the link functions CAN be tested however when trying to test if the service function is called the test fails and I have no idea why, the test for the service looks like this:
it('serviceFunction runs', inject(function () {
spyOn(serviceBeingUsed, "serviceFunction").and.callFake(function() {
var deferred = $q.defer();
var data = "returnedDataDummy";
deferred.resolve(data);
return deferred.promise;
});
isoScope.getRequiredData();
expect(serviceBeingUsed.serviceFunction).toHaveBeenCalled();
}));
How can I successfully test if the service function has been called here?
In writing this example I have solved my issue. In my actual code, inside the test "serviceFunction runs" I had also included a spyOn(isoScope,"getRequiredData)"
This has the effect of blocking the inner functionality of the function
getRequiredData()
which meant the the service function inside getRequiredData could never run.
To resolve this issue I needed to edit the spy for the outer function
from:
spyOn(isoScope,"getRequiredData");
to:
spyOn(isoScope,"getRequiredData").and.callThrough();
this simple change means that the function being spied on will also run its inner code and not just register that it has been called.
However one important lesson that I have learned is to not do too much inside each test and to separate the tests as much as possible.
So just to clarify, my original test which failed looked like this:
it('getRequiredData runs', inject(function () {
spyOn(serviceBeingUsed, "serviceFunction").and.callFake(function() {
var deferred = $q.defer();
var data = "returnedDataDummy";
deferred.resolve(data);
return deferred.promise;
});
spyOn(isoScope,"getRequiredData");
isoScope.getRequiredData();
expect(serviceBeingUsed.fetchRequiredData).toHaveBeenCalled();
expect(isoScope.getRequiredData).toHaveBeenCalled();
}));
the fix for this test which passes:
it('getRequiredData runs', inject(function () {
spyOn(serviceBeingUsed, "serviceFunction").and.callFake(function() {
var deferred = $q.defer();
var data = "returnedDataDummy";
deferred.resolve(data);
return deferred.promise;
});
spyOn(isoScope,"getRequiredData").and.callThrough();
isoScope.getRequiredData();
expect(serviceBeingUsed.fetchRequiredData).toHaveBeenCalled();
expect(isoScope.getRequiredData).toHaveBeenCalled();
}));

CasperJS - access JS property

I want to test that the value of mns.core is set in CasperJS. I have tried the following:
casper.test.begin('Upholstery contains stuff', 3, function (test) {
casper.start('http://127.0.0.1/layouts/en_gb/page-upholstery.php', function () {
var mns = this.evaluate(function(){
return mns;
});
console.log(typeof mns.core);
test.assert(typeof mns.core == "object","mns has properties");
});
casper.run(function() {
test.done();
});
});
mns is set as an object in casperJS, and when loaded via a browser mns.core is an object, however it fails this test, as it's showing as undefined.
Also, I think it's easier to use test.assertEval() than this.evaluate() + another test.assert, it does the same, so :
this.test.assertEval(function() {
return typeof mns.core === 'object';
},"mns has properties");

How to check if function throw an error in DOH?

I'm trying to check if a function throws error, and made this:
define([
'doh/runner',
'app/Obj'
], function(
doh,
Obj
){
doh.register('Test Obj exception', [
function () {
try {
new Obj(); // should throw error
} catch(e) {
doh.t(e, 'should give an error if no parameters given');
}
}
]);
Obj.js file:
...
constructor: function (args){
if (!args) { throw 'Error' }
...
}
...
But maybe where is some right method for this thing in Doh ? Can someone explain? Thanks
You want doh.assertError()
Example:
doh.assertError(TypeError, this.field, "setValue",
[{
CreatedOn: "March 10th, 2014"
}],
"setValue() on an invalid format should throw a TypeError");
This example test shows that DOH catches and displays an error correctly.
This gist is the test, and contains this code:
var Obj = function () {
if (arguments.length < 1) {
throw 'Error - There are ' + arguments.length + ' arguments';
}
};
define(["doh/runner"], function(doh){
var tests = [
function () {
new Obj(); // wrong call
}
];
doh.register('Test Obj exception', tests);
});
The screenshot shows the 1 error, and the error msg from the Error thrown:

keeping one instance of a dojo module

Is there a way to have a static variable in a dojo (1.8) module so that I can retain state?
Example, say I set some value in some/module
require([
'some/module'
], function (module) {
module.setSomeValue(3);
});
.. and then want to retrieve it later
define([
'some/module'
], function(module) {
return {
start: function() {
var x = module.getSomeValue();
}
};
});
A solution that works but seems like a hack,
acompany = window.acompany || {};
acompany.project = acompany.project || {
};
require([
], function() {
var debug = false;
acompany.project.module = {
/* static variables and functions here */
};
});
define([
], function () {
return acompany.project.module;
});
Actually there is always only single instance of AMD module, because (source):
define has two additional important characteristics that may not be immediately obvious:
Module creation is lazy and asynchronous, and does not occur immediately when define is called. This means that factory is not executed, and any dependencies of the module will not be resolved, until some running code actually requires the module.
Once a module value has been entered into the module namespace, it is not recomputed each time it is demanded. On a practical level, this means that factory is only invoked once, and the returned value is cached and shared among all code that uses a given module. (Note: the dojo loader includes the nonstandard function require.undef, which undefines a module value.)
In addition you do not have to provide just factory function, you can provide an object literal as well:
define("some/module", {
someValue: "some",
otherValue: "other"
});
Then somewhere else in your code:
require(["some/module"], function(module) {
console.log("module.someValue", module.someValue); // some
module.someValue = "some changed";
});
require(["some/module"], function(module) {
console.log("module.someValue", module.someValue); // some changed
});
More robust solution includes an instance of dojo/Stateful, so you can watch for changes and define custom setters and getters:
define("some/stateful-module", ["dojo/Stateful"], function(Stateful){
var stateful = new Stateful({
someValue: "some",
otherValue: "other"
});
return stateful;
});
Then somewhere else in your code:
require(["some/stateful-module"], function(module) {
console.log("stateful-module.someValue:", module.get("someValue"));
module.watch(function(name, oldValue, newValue) {
console.log("stateful-module: property"
, name
, "changed from"
, "'" + oldValue + "'"
, "to"
, "'" + newValue + "'"
);
});
});
require(["some/stateful-module"], function(module) {
module.set("someValue", "some changed");
});​
See how it works at jsFiddle: http://jsfiddle.net/phusick/fHvZf/. It's in a single file there, but it will work the same way across the whole application unless you require.undef(mid) the module.
There are multiple files in Dojo like dojo/date/locale that define static variables and functions and not widgets/classes using dojo.declare.
Define the module
define([
'dojo/_base/lang/',
'some/module'
], function(lang, module) {
var m = lang.getObject('some.module', true);
m.x = 0;
m.doSomething = function(){
// doSomething
};
return m;
});
Use the module
require([
'some/module'
], function(someModule) {
var debug = false;
/* someModule - static variables and functions here */
if(someModule.x == 0){
}
});