Sails.js afterCreate() is passed the newlyCreatedRecord without instance methods - sails.js

The newlyInsertedRecord in afterCreate(newlyInsertedRecord, cb) {} is missing all instance methods.
1 /**
2 * Dog.js
3 *
4 * #description :: TODO: You might write a short summary of how this model works and what it represents here.
5 * #docs :: http://sailsjs.org/documentation/concepts/models-and-orm/models
6 */
7
8 module.exports = {
9
10 attributes: {
11 tail: 'string',
12 wag: function() {
13 console.log('wagging ', this.tail, 'tail')
14 }
15 },
16
17 afterCreate: function(dog, cb) {
18 dog.wag()
19 }
20 };
When executing Dog.create({tail:'green'}).exec(console.log), the following error and stack trace occurs:
sails> TypeError: dog.wag is not a function
at module.exports.afterCreate (/tmp/afterCreateTest/api/models/Dog.js:18:7)
at fn (/home/user/.npm-packages/lib/node_modules/sails/node_modules/waterline/lib/waterline/utils/callbacksRunner.js:60:10)
at /home/user/.npm-packages/lib/node_modules/sails/node_modules/waterline/node_modules/async/lib/async.js:181:20
at iterate (/home/user/.npm-packages/lib/node_modules/sails/node_modules/waterline/node_modules/async/lib/async.js:262:13)
at Object.async.forEachOfSeries.async.eachOfSeries (/home/user/.npm-packages/lib/node_modules/sails/node_modules/waterline/node_modules/async/lib/async.js:281:9)
at Object.async.forEachSeries.async.eachSeries (/home/user/.npm-packages/lib/node_modules/sails/node_modules/waterline/node_modules/async/lib/async.js:214:22)
at Object.runner.afterCreate (/home/user/.npm-packages/lib/node_modules/sails/node_modules/waterline/lib/waterline/utils/callbacksRunner.js:63:9)
at after (/home/user/.npm-packages/lib/node_modules/sails/node_modules/waterline/lib/waterline/query/dql/create.js:243:17)
at /home/user/.npm-packages/lib/node_modules/sails/node_modules/waterline/lib/waterline/query/dql/create.js:230:68
at wrapper (/home/user/.npm-packages/lib/node_modules/sails/node_modules/lodash/index.js:3592:19)
at applyInOriginalCtx (/home/user/.npm-packages/lib/node_modules/sails/node_modules/waterline/lib/waterline/utils/normalize.js:421:80)
at wrappedCallback (/home/user/.npm-packages/lib/node_modules/sails/node_modules/waterline/lib/waterline/utils/normalize.js:324:18)
at callback.success (/home/user/.npm-packages/lib/node_modules/sails/node_modules/waterline/node_modules/switchback/lib/normalize.js:33:31)
at _switch (/home/user/.npm-packages/lib/node_modules/sails/node_modules/waterline/node_modules/switchback/lib/factory.js:58:28)
at afterwards (/home/user/.npm-packages/lib/node_modules/sails/node_modules/waterline/lib/waterline/adapter/dql.js:89:19)
at wrapper (/home/user/.npm-packages/lib/node_modules/sails/node_modules/lodash/index.js:3592:19)
Not sure if the answer to Sails.js model saved to session loses custom instance methods? applies?

afterCreate() Lifecycle callback only returns the value added in database, i.e. the JSON. Example:
{
tail: "green",
createdAt: "...",
updatedAt: "...",
id: "173c69cbdc4810b70dd4fb73"
}
In this moment you have only access to JSON, not object with methods.

Related

How to check for level in react-testing-library?

I have a heading <h4>Big offer!</h4> on the page, when I first ran my tests I got:
Expected: "Big offer!"
Received: <h4>Big offer!</h4>
35 | const switchToggle = screen.getByRole('checkbox');
36 | expect(switchToggle.checked).toEqual(true);
> 37 | expect(titleEl).toEqual(title);
Ok, it get's correct file, so I changed my code to actually check heading level and text, but it failed:
Expected: "Big offer!"
Received: undefined
35 | const switchToggle = screen.getByRole('checkbox');
36 | expect(switchToggle.checked).toEqual(true);
> 37 | expect(titleEl.name).toEqual(title);
| ^
38 | expect(titleEl.level).toEqual(4);
I always thought that .name is equal to getByText(). I commented out a line and tried checking for level, and it failed again:
Expected: 4
Received: undefined
36 | expect(switchToggle.checked).toEqual(true);
37 | //expect(titleEl.name).toEqual(title);
> 38 | expect(titleEl.level).toEqual(4);
I don't understand why my test cases failed. Code for test was:
const title = 'Big offer!';
render(<Component title={title}/>);
const titleEl = screen.getByRole('heading');
expect(titleEl).toEqual(title);
expect(titleEl.level).toEqual(4);
It wont work because screen.getByRole (or others querys) returns an HTMLElement (in your case returns a HTMLHeadingElement that inherits HTMLElement). And it doesnt have name or level properties. You can check more here.
To check the text rendered you should use:
expect(titleEl).toHaveTextContent(title);
And for h4 type check you just need to filter it on query:
const titleEl = screen.getByRole('heading', { level: 4 });
The full test:
it('test search input', async () => {
const title = 'Big offer!';
render(<SearchBox title={title} />);
const titleEl = screen.getByRole('heading', { level: 4 });
expect(titleEl).toBeInTheDocument();
expect(titleEl).toHaveTextContent(title);
});

Jenkins - Having issues with PostBuild Email notifications

Trying to use the following piece of code to trigger email notifications for a multi-branch pipeline job:
1 def emailNotification() {
2 def to = emailextrecipients([[$class: 'CulpritsRecipientProvider'],
3 [$class: 'DevelopersRecipientProvider'],
4 [$class: 'RequesterRecipientProvider']])
5
6 //def to = "firstname.lastname#domain.com"
7 //String currentResult = currentBuild.result
8 String currentResult = manager.build.getResult()
9 echo "CurrentResult1=${currentResult}"
10 echo "CurrentResult2=${manager.build.getResult()}"
11 echo "CurrentResult3=${manager.build.result}"
12 String previousResult = currentBuild.getPreviousBuild().result
13
14 def causes = currentBuild.rawBuild.getCauses()
15 // E.g. 'started by user', 'triggered by scm change'
16 def cause = null
17 if (!causes.isEmpty()) {
18 cause = causes[0].getShortDescription()
19 }
20
21 // Ensure we don't keep a list of causes, or we get
22 // "java.io.NotSerializableException: hudson.model.Cause$UserIdCause"
23 // see http://stackoverflow.com/a/37897833/509706
25 causes = null
26
27 String subject = "${env.JOB_NAME} ${env.BUILD_NUMBER}: ${currentResult}"
28
29 String body = """
30 <p>Triggered by: <b>${cause}</b></p>
31
32 <p>Last build result: <b>${previousResult}</b></p>
33
34
35 <p>Build <b>${env.BUILD_NUMBER}</b> ran on <b>${env.NODE_NAME}</b> and terminated with <b>${currentResult}</b>.
36 </p>
37
38 <p>See: ${env.BUILD_URL}</p>
39
40 """
41
42 String log = currentBuild.rawBuild.getLog(40).join('\n')
43 if (currentBuild != 'SUCCESS') {
44 body = body + """
45 <h2>Last lines of output</h2>
46 <pre>${log}</pre>
47 """
48 }
49
50 if (to != null && !to.isEmpty()) {
51 // Email on any failures, and on first success.
52 if (currentResult != 'SUCCESS' || currentResult != previousResult) {
53 mail to: to, subject: subject, body: body, mimeType: "text/html"
54 }
55 echo 'Sent email notification'
56 }
57 }
Now, the problems that I'm facing:
def to = emailextrecipients... is not working. I found this and this Jenkins Jira issues that this may be the causes, but no workaround. Although it seems weird that if the build is started manually, say by me a user authenticated through Github Oauth, the mail can be sent. If the Github is starting the build through the webhook, I'm getting this in the Jenkins logs:
Not sending mail to user firstname.lastname#domain.com with no
permission to view
The second issue that I'm seeing is with the PostBuild email trigger.
The Pipeline looks like this:
def emailNotification() {
//the one from above
}
try {
stage('Stage1') {
/*
creating multiple nodes based on an array provided
each node will execute:
checkout scm
buildSolution() //custom method defined
*/
parallel <stuff_above>
}
stage('Stage2') {
//do other stuff
parallel <other_stuff_above>
}
} finally {
emailNotification()
}
The echoes from above (rows 9-11) are all showing null
CurrentResult1=null
CurrentResult2=null
CurrentResult3=null
Using currentBuild.currentResult will show me only SUCCESS or FAILED, but not UNSTABLE, in case some of the tests failed.
Any ideas where the problem is?
Build status is null until something sets it or until the job finishes. Are you using any unit test steps that would cause the build to be unstable?
You don't need to use emailextrecipients instead use.
emailext body: body, mimeType: 'text/html', recipientProviders: [
[$class: 'CulpritsRecipientProvider'],
[$class: 'DevelopersRecipientProvider'],
[$class: 'RequesterRecipientProvider']], subject: subject
Not sending mail to user firstname.lastname#domain.com with no
permission to view
Means that either no jenkins user has this email address associated or the user it is associated with does not have permission to the job
Also for causes put that logic inside a different function and add #NonCPS annotation which will stop jenkins trying to serialise state while that function is running, as you currently have it there is a small chance it will still break with that exception, see https://stackoverflow.com/a/38439681/963402

Using TNT4J, activity statistics are not coming properly

I want to log a activity which starts in the scope of a different class and ends in the scope of another class. Using TrackingLogger.getCurrentActivity() throws an exception as there is no activity in memory.Now if I try to store the activity in static HashMap in singleton Class and retrieve it in the other class, the snapshot of activity is showing confusing values. Here is what I am trying to do :
In first Class :
TrackingLogger tracker = TrackingLogger.getInstance(this.getClass()) ;
TrackingActivity activity = tracker.newActivity(); //
activity.start();
CacheUtil.addTrackingActivity("logger",activity); // Store it in static Hashmap in singleton class
In Second Class :
TrackingLogger tracker = TrackingLogger.getInstance(this.getClass());
TrackingActivity activity = CacheUtil.getTrackingActivity("logger");
activity.stop();
tracker.tnt(activity);
this is the snapshot generated :
18:37:39,780 INFO [Nastel TNT4J] {status: 'END' | time: '2014-07-30 13:07:39.778000 UTC' | sev: 'INFO' | type: 'ACTIVITY' | name: 'NOOP' | usec: '72827000' | wait.usec: '21000' | start.time: '2014-07-30 18:36:26.196000 IST' | end.time: '2014-07-30 18:37:39.023000 IST' | pid: '8092' | tid: '90' | id-count: '0' | snap-count: '6' | source: 'APPL=Nastel TNT4J#JVM=8092#FACH13140035#SERVER=FACH13140035#NETADDR=172.25.19.28#DATACENTER=default#GEOADDR=unknown' | track-id: '09d708c4-a6a9-4200-a70f-25c1da838c11'
Snapshot(CPU#Java) {
Count: 4
TotalCpuUsec: 46800.3
TotalCpuUserUsec: 46800.3
}
Snapshot(Thread#Java) {
Count: 69
DaemonCount: 46
StartedCount: 85
PeakCount: 69
BlockedCount: 7
WaitedCount: 0
BlockedUsec: 21000
WaitUsec: 0
}
Snapshot(Memory#Java) {
MaxBytes: 532742144
TotalBytes: 512499712
FreeBytes: 216341712
UsedBytes: 296158000
Usage: 57
}
Snapshot(Copy#GarbageCollector) {
Count: 477
Time: 1940
isValid: true
}
Snapshot(MarkSweepCompact#GarbageCollector) {
Count: 13
Time: 4652
isValid: true
}
Snapshot(Activity#Java) {
TotalCpuUsec: -1778411.4
SlackUsec: 74584411
WallUsec: -1757411.4
BlockedCount: -24
WaitedCount: -1
BlockedUsec: 21000
WaitUsec: 0
OverheadUsec: 24290.215
}}
Am I missing something?? Pls help ..
TrackingLogger.getCurrentActivity() will only return a valid activity if executed within the same thread. The activity handle is stored in thread local. so you most likely calling TrackingLogger.getCurrentActivity() from a different thread and therefore get an exception.
I am not exactly clear where the confusing values are. Can you elaborate?

How can a document claim it's persisted, when a count on the class returns 0?

How can a document claim foo.persisted? == true, when foo.class.count == 0?
More importantly, how can I get the document to truly persist?
Update: calling Mongo::Foo.create() from the controller does increment the count. That is expected. Calling create, or new and save, from within a separate module/class does not increment the count.
Update: I have tried changing new/save calls to create
Update: I have also tried #foo_class.with(collection: "mongo_foos").create
[42] pry(#<FoosController>)> foo.class
=> Mongo::Foo
[43] pry(#<FoosController>)> foo.persisted?
=> true
[44] pry(#<FoosController>)> Mongo::Foo.count
=> 0
[47] pry(#<FoosController>)> foo.id
=> "5081a1a786ddc8e035000021"
[48] pry(#<FoosController>)> foo
=> #<Mongo::Foo _id: 5081a1a786ddc8e035000021, _type: nil, foo_daddy_id: nil, old_foo_daddy_id: 219, member_id: "F008AR", unix_time: nil, date_time: 2012-10-19 13:50:54 UTC, submitted: nil, json: nil>
Here's how the document class is defined:
module Mongo
class Foo
include Mongoid::Document
field :foo_daddy_id
field :old_foo_daddy_id, type: Integer
field :member_id, type: String
field :unix_time, type: Integer
field :date_time, type: DateTime
field :submitted, type: Integer
field :json, type: Hash
belongs_to :foo_daddy, class_name: "Mongo::FooDaddy"
embeds_many :foo_dumplings, class_name: "Mongo::FooDumpling"
end
end
The doc is being created with foo.new(params); foo.save:
module FooThingy
module Foo
class Create < ::FooThingy::Base
def initialize(options)
# Sets instance variables used below
end
def execute!
#foo = #foo_class.new({
date_time: DateTime.strptime(#params["submitted_timestamp"], "%m-%d-%Y %H:%M:%S"),
member_id: (#params[:member_id].present? ? #params[:member_id] : nil),
old_foo_daddy_id: #params[:old_foo_daddy_id]
})
embed_foo_dumplings
if #foo.save
return FooThingy::Result.new(success: true, data: { foo: #foo })
else
return FooThingy::Result.new(success: false, data: { foo: #foo })
end
end
private
def embed_foo_dumplings
# Embeds foo_dumplings
end
end
end
end
Here's where I call that module to create the document:
class FoosController < ApplicationController
def create
foo_creator = FooThingy::Foo::Create.new(params: params, foo_class: Mongo::Foo)
foo = foo_creator.execute!
foo = foo.data[:foo]
binding.pry
end
end
This problem, I think, is less interesting than it appears. I've modified my config/mongoid.yml to specify a new database, and everything behaves as expected. Problem was likely due to limitations on 32-bit MongoDB installations.

Is it possible to pass a javascript function in the scope parameter of the Collection.map_reduce in pymongo?

Given:
jstrMap = """
function() {
print("isPointInside = " + isPointInside);
print("polygon = " + polygon);
emit(this._id, this);
}
"""
jstrReduce = """
function(key, values) {
return values[0];
}
"""
def readJSCodeFromFile(filePath):
with open(filePath) as f:
return Code(f.read())
jsIsPointInside = readJSCodeFromFile(path.join(path.dirname(__file__), 'IsPointInside.js'))
IsPointInside.js:
function(pt, poly) {
}
And I invoke map_reduce like this:
mycoll.map_reduce(jstrMap, jstrReduce, 'results',
scope = {'isPointInside': jsIsPointInside, 'polygon': [[-77, 39], [-77,38], [-78,38], [-78,39]]})
Here is what I get on the client console:
db assertion failure, assertion: 'map invoke failed: JS Error: TypeError: isPointInside is not a function nofile_b:3', assertionCode: 9014
And the server output is:
isPointInside = null
polygon = -77,39,-77,38,-78,38,-78,39
Sun Apr 01 16:29:14 [conn11] JS Error: TypeError: isPointInside is not a function nofile_b:3
Sun Apr 01 16:29:14 [conn11] mr failed, removing collection :: caused by :: 9014 map invoke failed: JS Error: TypeError: isPointInside is not a function nofile_b:3
Debugging the python code reveals that jsIsPointInside is of type Code, as expected. str(jsIsPointInside) returns the function text, i.e. 'function(pt, poly) {\n}\n'
I do not want to populate the system.js collection, I'd like to pass the function in the scope. Is it possible at all?
Thanks.
Scope is an object where the fields are placed in the MapReduce scope as variables w/ the field name.
If you'd like to put a function in scope, you need to make it a value a field e.g.
scope = {
myFunc: function() { return "Foo";}
}