I have a coffeescript file called archive.spec.coffee.
It begins with:
describe 'Archive', ->
and all tests are within the describe.
I want to check for a software version using a http call and depending on what that is, I'd like to either execute or skip the tests.
I think I need to do something like this but so far it isn't working:
req = https.get {host: "https://path/to/endpoint"}
if(req.version == 1.2.3)
this.skip
else
describe 'Archive', ->
Can anybody tell me how to correctly do this?
Additional info
I've came up with this:
beforeEach ->
req = request.get {
url: 'https://path/to/endpoint',
auth: {
user: 'admin',
pass: 'password'
},
json: true
},
(err, res, body) ->
version = body.responseData.devices[0].versions[0].version
if (version.indexOf('1.2.3') == -1)
done()
else
this.skip()
describe 'Archive', ->
My problem now is that if version is 1.2.3, version.indexOf('1.2.3') returns 0, the else is entered but the tests are not skipped.
Latest update
Now I've come up with this:
before (done) ->
req = request.get {
url: 'https://path/to/endpoint',
auth: {
user: 'admin',
pass: 'password'
},
json: true
},
(err, res, body) ->
version = body.responseData.devices[0].versions[0].version
if (version.indexOf('1.2.3') != -1)
skip = true
done()
else
done()
describe 'Archive', ->
it 'my_test', ->
if (skip)
this.skip()
If I test this with version 1.2.3 I can see that the skip is set to true in the before function. done() returns to my_test but if (skip) is false. Obviously this is because skip is set to true in a different function. How do I get it so that the before returns the value of skip to my test?
I have a json formatted config file so I added a version key which takes an environment variable containing the version. Once in the config I can then use it as I like.
Related
I am using the default code from https://www.npmjs.com/package/priority-web-sdk
var configuration = {
username: '<username>',
password: '<password>',
url: '<app server url>',
tabulaini: 'tabula.ini',
language: 3,
company: 'demo'
};
priority.login(configuration)
.then(()=> priority.formStart('CUSTOMERS', null, null, 'demo', 1))
.then(form=> form.getRows(1))
.then(rows=> console.log(rows))
.catch(err=> console.log(err));
if i run the code with my config i get no result however if i remove form.getRows(1) and pass the result of formStart i then get a response and the form info is logged to the console i just can't seam to get any more data?
I am using node but if i include the script on the client side and run it that way then it works fine but this is insecure so not a solution.
the soloution was to check if the window is undefined in my code
if it is then we should set it.
if (typeof window === 'undefined') {
global.window = {}
}
I have the following code in my Model.js file.
Model.observe('loaded', (ctx, next) => {
const {
data,
options: {
user
}
} = ctx;
const owner = (user && data && user.uid === data.userId) || false;
console.log(
`${data.id}: loaded - access by ${user && user.name}, owner:${owner}`
);
if (!owner) {
delete data.testProp1;
}
console.log('returning: ', ctx.data);
next();
});
When I make a request, I see the following log output (server logs):
f3f9ffd6-14dc-42e5-94ba-503aa3426faa: loaded - access by User1, owner:false
returning:
{
testProp2: true,
id: 'f3f9ffd6-14dc-42e5-94ba-503aa3426faa',
userId: 'sfeywkKSuBTlf0DwE4ZOFd8RX5E3'
}
But then in the actual response the browser receives I actually get:
{
testProp1: true,
testProp2: true,
id: 'f3f9ffd6-14dc-42e5-94ba-503aa3426faa',
userId: 'sfeywkKSuBTlf0DwE4ZOFd8RX5E3'
}
Is there something in the documentation I am missing? Deleting the property is exactly what it shows in the Loopback docs here. Also, I actually see the modified data as the data property on the ctx object before calling next(). Anyone run into this issue or know some caveat to the docs that isn't explicitly stated?
I'm right now working on a web API with expressjs, kotlin and PostgreSQL. I organized my project in an object oriented way. I also created a class for the database that makes all frequently called queries available as a function. Example:
fun addUser(firstName: String, lastName: String, password: String, classId: Int){
client.query("INSERT INTO users(first_name, last_name, password, class_id) values($1, $2, $3, $4)", arrayOf(firstName, lastName, password, classId));
}
This doesn't work however when I'm trying to issue a SELECT query and return the dataset to the function caller since queries are asynchronous. I already tried assigning the result to an attribute of the database object and using it as soon as the value is assigned, but it seems that the value can't be assigned when I'm checking its value permanently. Does anyone know how I could return the value to the function caller?
Thanks in advance for your answers.
Assuming you are using nodejs and the pg module.
As you said since query function is async you cannot return the result to the caller directly. Traditionally in nodejs the caller passes a callback function to handle the result or the error if there is one.
In Kotlin this would look like:
client.query(MY_QUERY_TEMPLATE, params) { err, result ->
if (err != null) {
// do something with the error
} else {
// do something with the result
}
}
To make this a bit neater you could put your result handler in its own function
fun handleResult(err: dynamic, result: dynamic) {
// put your code here
}
And use it like this:
client.query(MY_QUERY_TEMPLATE, params, ::handleResult)
If you don't like this you have another option. The pg library can return Promise. This abstraction allows you to use method chaining like this:
app.get("/promiseStyle") { req, res ->
val params = arrayOf(42) // or something...
fun handleSuccess(result: dynamic) {
for (row in result.rows) {
res.write(row.someField)
}
res.end()
}
fun handleError(error: dynamic) {
res.status(500).send("Something went wrong");
}
client.query(MY_QUERY_TEMPLATE, params)
.then(::handleSuccess)
.catch(::handleError)
}
You may find the following declaration useful for accessing the various pg client functionality:
#JsModule("pg")
external object pg {
class Client {
fun query(query: String, params: Array<Any>): dynamic
fun query(
query: String, params: Array<Any>, cb: (dynamic, dynamic) -> Unit
)
fun connect()
}
}
The postgres client can then be initialized as follows:
val client = pg.Client()
client.connect()
I have used the Meteor Ionic Demo code to create my new application. Now, instead of signing up with an e-mail address, I want to use usernames.
I used this code (source):
// server/methods.js
if (Meteor.isServer){
Meteor.methods({
"userExists": function(username){
return !!Meteor.users.findOne({username: username});
},
});
}
// lib/config/at_config.js
AccountsTemplates.addField({
_id: 'username',
type: 'text',
required: true,
func: function(value){
if (Meteor.isClient) {
console.log("Validating username...");
var self = this;
Meteor.call("userExists", value, function(err, userExists){
if (!userExists)
self.setSuccess();
else
self.setError(userExists);
self.setValidating(false);
});
return;
}
// Server
return Meteor.call("userExists", value);
},
errStr: "Bad username"
});
Now the problem is, if the username already exists, how can I display an error message?
Currently, it displays only the ionic error icon, but not the errStr:
I think the problem is that I should return userExists in func, but how can I wait on the userExists method server call?
The function passed to Meteor.call("userExists", value, function(err, userExists){ is the callback that will be called when the server method returns a response, so you are already waiting for it to finish.
From the source code of meteor-useraccounts/core, it seems that errStr is only used when func returns true. In your case, because the call to server is async, func is returning undefined which is considered 'no error'.
Also, what is shown next to the icon is the status of the field, and that status is modified by setError.
If you pass the error message to setError, it will be displayed correctly.
The solution is to change:
self.setError(userExists);
to:
self.setError("Bad username");
I'm looking for a way to determine if Meteor.user() is set in a function that can be called both from the server and client side, without raising an error when it is not.
In my specific case I use Meteor server's startup function to create some dummy data if none is set. Furthermore I use the Collection2-package's autoValue -functions to create some default attributes based on the currently logged in user's profile, if they are available.
So I have this in server-only code:
Meteor.startup(function() {
if (Tags.find().fetch().length === 0) {
Tags.insert({name: "Default tag"});
}
});
And in Tags-collection's schema:
creatorName: {
type: String,
optional: true,
autoValue: function() {
if (Meteor.user() && Meteor.user().profile.name)
return Meteor.user().profile.name;
return undefined;
}
}
Now when starting the server, if no tags exist, an error is thrown: Meteor.userId can only be invoked in method calls. Use this.userId in publish functions.
So in other words calling Meteor.user() on the server startup throws an error instead of returning undefined or null or something. Is there a way to determine whether it will do so prior to calling it?
I cannot solve this simply by wrapping the call with if (Meteor.isServer) within the autoValue function, as the autoValue functions are normally called from server side even when invoked by the user, and in these cases everything in my code works fine.
Note that this is related to How to get Meteor.user() to return on the server side?, but that does not address checking if Meteor.user() is available in cases where calling it might or might not result in an error.
On the server, Meteor.users can only be invoked within the context of a method. So it makes sense that it won't work in Meteor.startup. The warning message is, unfortunately, not very helpful. You have two options:
try/catch
You can modify your autoValue to catch the error if it's called from the wrong context:
autoValue: function() {
try {
var name = Meteor.user().profile.name;
return name;
} catch (_error) {
return undefined;
}
}
I suppose this makes sense if undefined is an acceptable name in your dummy data.
Skip generating automatic values
Because you know this autoValue will always fail (and even if it didn't, it won't add a useful value), you could skip generating automatic values for those inserts. If you need a real name for the creator, you could pick a random value from your existing database (assuming you had already populated some users).
Been stuck with this for two days, this is what finally got mine working:
Solution: Use a server-side session to get the userId to prevent
"Meteor.userId can only be invoked in method calls. Use this.userId in publish functions."
error since using this.userId returns null.
lib/schemas/schema_doc.js
//automatically appended to other schemas to prevent repetition
Schemas.Doc = new SimpleSchema({
createdBy: {
type: String,
autoValue: function () {
var userId = '';
try {
userId = Meteor.userId();
} catch (error) {
if (is.existy(ServerSession.get('documentOwner'))) {
userId = ServerSession.get('documentOwner');
} else {
userId = 'undefined';
}
}
if (this.isInsert) {
return userId;
} else if (this.isUpsert) {
return {$setOnInsert: userId};
} else {
this.unset();
}
},
denyUpdate: true
},
// Force value to be current date (on server) upon insert
// and prevent updates thereafter.
createdAt: {
type: Date,
autoValue: function () {
if (this.isInsert) {
return new Date;
} else if (this.isUpsert) {
return {$setOnInsert: new Date};
} else {
this.unset();
}
},
denyUpdate: true
},
//other fields here...
});
server/methods.js
Meteor.methods({
createPlant: function () {
ServerSession.set('documentOwner', documentOwner);
var insertFieldOptions = {
'name' : name,
'type' : type
};
Plants.insert(insertFieldOptions);
},
//other methods here...
});
Note that I'm using the ff:
https://github.com/matteodem/meteor-server-session/ (for
ServerSession)
http://arasatasaygin.github.io/is.js/ (for is.existy)