I have a model in Django with the following two variables for an Event model:
notification = models.BooleanField(default=False)
priority_int = models.IntegerField(blank=True, default=0) # low priority
I get the data from the user using a controller called new-event.controller.js, and then I call create() in events.service.js like this:
Events.create(notification, priority_int).then(createEventSuccessFn, createEventErrorFn);
new-event.controller.js also broadcasts the following:
$rootScope.$broadcast('event.created', {
notification: notification,
priority_int: priority_int,
author: {
username: Authentication.getAuthenticatedAccount().username
}
});
My data is being saved correctly in the database, using the angular factory defined in events.service.js - factory is named Events
function create(notification, priority_int){
return $http.post('/api/v1/events/', {
notification: notification,
priority_int: priority_int
});}
I have an account.controller.js that is injected with Events and $scope, account.controller.js catches the broadcast with:
$scope.$on('event.created', function (event, pud) {
Events.get(username).then(eventsSuccessFn, eventsErrorFn);
});
function eventsSuccessFn(data, status, headers, config) {
console.log('event success: ');
vm.events = data.data; //already correctly instantiated
}
I have an events.directive.js, which has the controller events.controller.js. Inside events.controller.js, I am watching for the changes to vm.events with:
$scope.$watchCollection(function () {
return $scope.events;
}, render);
$scope.$watch(function () {
return $(window).width();
}, render);
This is the render function inside events.controller.js:
function render(current, original) {}
current refers to the array of events. Inside the render function, for created events and newly created events, if I retrieve each one's notification value, I receive the correct boolean value (the value that was entered by the user and saved in the database). But if I try to retrieve the priority_int value for any event, I get undefined, despite the database saving the user-inputted value correctly.
I'm incredibly confused. Any help is appreciated.
Here is my events.service.js:
(function () {
'use strict';
angular
.module('app.events.services')
.factory('Events', Events);
Events.$inject = ['$http'];
/**
* #namespace Events
* #returns {Factory}
*/
function Events($http) {
var Events = {
all: all,
create: create,
get: get
};
return Events;
//functions all, create and get below
Here is my events.directive.js:
(function () {
' use strict';
angular
.module('app.events.directives')
.directive('events', events);
/**
* #namespace events
*/
function events() {
console.log('in events directive');
/**
* #name directive
* #desc The directive to be returned
* #memberOf app.events.directives.Events
*/
var directive = {
controller: 'EventsController',
controllerAs: 'vm',
restrict: 'E',
scope: {
events: '='
},
templateUrl: '/static/templates/events/events.html'
};
return directive;
}
})();
Related
I have two databases that I need to interact with in my code. I have a simple function that takes an object and writes it to my PostgreSQL database using Prisma. I've tested the function with Postman, and it works perfectly, but when I try to execute it using a Jest mock (using the singleton pattern found in the Prisma unit testing guide), it returns undefined indicating that it didn't interact with the database and create the new record. Here's my code:
/prisma/clinical-schema.prisma
generator client {
provider = "prisma-client-js"
output = "./generated/clinical"
}
datasource clinicalDatabase {
provider = "postgresql"
url = "postgresql://postgres:postgres#localhost:5432/clinical-data?schema=public"
}
model pcc_webhook_update {
id Int #id #default(autoincrement())
event_type String
organization_id Int
facility_id Int
patient_id Int
resource_id String?
webhook_date DateTime #default(now()) #clinicalDatabase.Timestamptz(6)
status pcc_webhook_update_status #default(pending)
status_changed_date DateTime? #clinicalDatabase.Timestamptz(6)
error_count Int #default(0)
##unique([organization_id, facility_id, patient_id, resource_id, event_type, status])
}
enum pcc_webhook_update_status {
pending
processing
processed
error
}
/prisma/clinical-client.ts
import { PrismaClient } from './generated/clinical';
const prismaClinical = new PrismaClient();
export default prismaClinical;
/testing/prisma-clinical-mock.ts
import { PrismaClient } from '../prisma/generated/clinical';
import { mockDeep, mockReset, DeepMockProxy } from 'jest-mock-extended';
import prisma from '../prisma/clinical-client';
jest.mock('../prisma/clinical-client', () => ({
__esModule: true,
default: mockDeep<PrismaClient>()
}));
beforeEach(() => {
mockReset(prismaClinicalMock);
});
export const prismaClinicalMock = prisma as unknown as DeepMockProxy<PrismaClient>;
Everything up to this point follows the conventions outlined by the Prisma unit testing docs. The only modification I made was to make it database specific. Below is my function and tests. The request object in handle-pcc-webhooks.ts is a sample http request object, the body of which contains the webhook data I care about.
/functions/handle-pcc-webhooks/handler.ts
import prismaClinical from '../../../prisma/clinical-client';
import { pcc_webhook_update } from '../../../prisma/generated/clinical';
import { requestObject } from './handler.types';
export const handlePccWebhook = async (request: requestObject) => {
try {
const webhook = JSON.parse(request.body);
// if the webhook doesn't include a resource id array, set it to an array with an empty string to ensure processing and avoid violating
// the multi-column unique constraint on the table
const { resourceId: resourceIds = [''] } = webhook;
let records = [];
for (const resourceId of resourceIds) {
// update an existing record if one exists in the pending state, otherwise create a new entry
const record: pcc_webhook_update = await prismaClinical.pcc_webhook_update.upsert({
where: {
organization_id_facility_id_patient_id_resource_id_event_type_status: {
organization_id: webhook.orgId,
facility_id: webhook.facId,
patient_id: webhook.patientId,
resource_id: resourceId,
event_type: webhook.eventType,
status: 'pending'
}
},
update: {
webhook_date: new Date()
},
create: {
event_type: webhook.eventType,
organization_id: webhook.orgId,
facility_id: webhook.facId,
patient_id: webhook.patientId,
resource_id: resourceId,
status: 'pending' // not needed
}
});
records.push(record);
}
return records;
} catch (error) {
console.error(error);
}
};
/functions/handle-pcc-webhooks/handler.spec.ts
import fs from 'fs';
import path from 'path';
import MockDate from 'mockdate';
import { prismaClinicalMock } from '../../../testing/prisma-clinical-mock';
import { createAllergyAddRecord } from './__mocks__/allergy';
import { requestObject } from './handler.types';
import { handlePccWebhook } from './handler';
describe('allergy.add', () => {
let requestObject: requestObject;
let allergyAddRecord: any;
beforeAll(() => {
requestObject = getRequestObject('allergy.add');
});
beforeEach(() => {
MockDate.set(new Date('1/1/2022'));
allergyAddRecord = createAllergyAddRecord(new Date());
});
afterEach(() => {
MockDate.reset();
});
test('should create an allergy.add database entry', async() => {
prismaClinicalMock.pcc_webhook_update.create.mockResolvedValue(allergyAddRecord);
// this is where I would expect handlePccWebhook to return the newly created database
// record, but instead it returns undefined. If I run the function outside of this
// unit test, with the same input value, it functions perfectly
await expect(handlePccWebhook(requestObject)).resolves.toEqual([allergyAddRecord]);
});
});
// This just builds a request object with the current webhook being tested
function getRequestObject(webhookType: string) {
// read the contents of request object file as a buffer, then convert it to JSON
const rawRequestObject = fs.readFileSync(path.resolve(__dirname, '../../sample-data/handle-pcc-webhook-request.json'));
const requestObject: requestObject = JSON.parse(rawRequestObject.toString());
// read the contents of the webhook file as a buffer, then convert it to a string
const rawWebhook = fs.readFileSync(path.resolve(__dirname, `../../sample-data/${webhookType}.json`));
const webhookString = rawWebhook.toString();
// set the body of the request object to the contents of the target webhook
requestObject.body = webhookString;
return requestObject;
}
Finally, here is the result of running the unit test:
So after banging my had against the wall for a few hours, I figured out the issue. In my handler.spec.ts file, I had the following line:
prismaClinicalMock.pcc_webhook_update.create.mockResolvedValue(allergyAddRecord);
what that does is mock the value returned for any create functions run using Prisma. The issue is that my function is using an upsert function, which I wasn't explicitly mocking, thus returning undefined. I changed the above line to
prismaClinicalMock.pcc_webhook_update.upsert.mockResolvedValue(allergyAddRecord);
and it started working.
I have two intents:
This is the chat bot now:
After this there will be a confirmation whether he wants to invest in equity or not. If he says Yes then another intent must be started without him typing anything.
How do I achieve this?
Here is my Lambda function:
// --------------- Intents -----------------------
var type;
/**
* Called when the user specifies an intent for this skill.
*/
function dispatch(intentRequest, callback) {
// console.log(JSON.stringify(intentRequest, null, 2));
console.log(`dispatch userId=${intentRequest.userId}, intent=${intentRequest.currentIntent.name}`);
const name = intentRequest.currentIntent.name;
// Dispatch to your skill's intent handlers
if (name === 'FinancialType') {
return getFinancialType(intentRequest,callback);
}
throw new Error(`Intent with name ${name} not supported`);
}
// --------------- Main handler -----------------------
function loggingCallback(response, originalCallback) {
// console.log(JSON.stringify(response, null, 2));
originalCallback(null, response);
}
// Route the incoming request based on intent.
// The JSON body of the request is provided in the event slot.
exports.handler = (event, context, callback) => {
try {
// By default, treat the user request as coming from the America/New_York time zone.
process.env.TZ = 'America/New_York';
console.log(`event.bot.name=${event.bot.name}`);
/**
* Uncomment this if statement and populate with your Lex bot name and / or version as
* a sanity check to prevent invoking this Lambda function from an undesired Lex bot or
* bot version.
*/
/*
if (event.bot.name !== 'MakeAppointment') {
callback('Invalid Bot Name');
}
*/
dispatch(event, (response) => loggingCallback(response, callback));
} catch (err) {
callback(err);
}
};
function close(fulfillmentState, message) {
return {
dialogAction: {
type: 'Close',
fulfillmentState,
message,
},
};
}
function elicitSlot(intentName, slots, slotToElicit, message) {
return {
dialogAction: {
type: 'ElicitSlot',
intentName,
slots,
slotToElicit,
message,
},
};
}
function buildValidationResult(isValid, violatedSlot, messageContent) {
return {
isValid,
violatedSlot,
message: { contentType: 'PlainText', content: messageContent },
};
}
function getFinancialType(intentRequest,callback){
var age = intentRequest.currentIntent.slots.age;
var amount = intentRequest.currentIntent.slots.amount;
const source = intentRequest.invocationSource;
if(amount >= 10000){
type = 'Equity';
}
callback(close('Fulfilled',{contentType: 'PlainText',
content: `You have choosen to invest ` + amount + ' in ' + type }));
}
There is an option in the AWS Console for Lex to include a confirmation message. You can ask the user for confirmation there.
Documentation: http://docs.aws.amazon.com/lex/latest/dg/howitworks-manage-prompts.html#msg-prompts-context-for-msgs
Quick and shortly I have following problem:
I have following two actions within a component in Ember:
createData: function(user) {
let collection = [];
for (let i = 0; i < user.posts.length; i++) {
let data = this.send('createSingleData',user.posts[i], user, 'post');
console.log(data);
collection.push(data);
}
return collection;
},
createSingleData: function(data, user, type) {
let entitySkeleton = {
name: data.place.name,
belongsTo: user.id,
position: {
data.place.location.longitude,
data.place.location.latitude
}
};
console.log(entitySkeleton);
return entitySkeleton;
}
the first log - within createSingleData, right before returning the logged value - writes the entitySkeleton as Object into the console - as expected.
However, the console.log(data) - within createData - writes 'undefined' to the console.
Is there any aspect of asynchrounosity I didn't respect?
P.S.:
I also logged any paramater within createSingleData, they are all set properly.
The variable collection also only gets pushed 'undefined'.
You cannot return the value from action, instead you can set property from the action.
how to return values from actions in emberjs
actions: {
PrintSomething: function() {
let obj = [{a: 'raj'}, {a: 'Prudvi'}, {a : 'thimappa'}]
console.log('before', obj);
this.send('returnSomething', obj);
console.log('after calling action', this.get('returnvalue'));
},
returnSomething: function(obj) {
obj.push({a: 'FSDFSDF'})
var data = obj;
this.set('returnvalue', data);
}
}
I have a requirement to include remarks from user in the payload whenever he tries to delete an item. So far, I have this:
let remarks = this.get('remarks');
let id = this.get('itemID');
this.store.findRecord('item', id).then(function (selectedItem) {
// TODO - DELETE doesn't accept payload in body?
selectedItem.destroyRecord({remarks:remarks}).then(function(response){
Ember.debug('delete successful:'+JSON.stringify(response));
Ember.$('#confirmDelete').modal('hide');
Ember.$('#remarks').val('');
context.set('successful', true);
context.set('message', context.get('i18n').t('success.role.delete'));
}).catch(function(error){
Ember.debug('delete failed:'+JSON.stringify(error));
Ember.$('#confirmDelete').modal('hide');
Ember.$('#remarks').val('');
context.send('showErrors', error);
});
});
It doesn't work. So does setting the remarks value in the model like:
...
this.store.findRecord('item', id).then(function (selectedItem) {
selectedItem.set('remarks', remarks);
selectedItem.destroyRecord().then(function(response){
...
I am trying to override the deleteRecord but I don't know where to start or how to do it.
Anyone have ideas? Thanks!
You can easily achieve this kind of behaviour by extending your application adapter with the following mixin:
/* app/mixins/delete-with-playload.js */
import Ember from 'ember';
export default Ember.Mixin.create({
deleteRecord(store, type, snapshot) {
var id = snapshot.id;
var data = {};
var serializer = store.serializerFor(type.modelName);
serializer.serializeIntoHash(data, type, snapshot);
return this.ajax(this.buildURL(type.modelName, id, snapshot, 'deleteRecord'), "DELETE", {
data
});
}
});
Then just add it to your application adapter
/* app/adapters/application.js */
import RestAdapter from 'ember-data/adapters/rest';
import DeleteWithPayloadMixin from '../mixins/delete-with-payload';
export default RestAdapter.extend(DeleteWithPayloadMixin);
This will result a payload identical to the payload of PUT method, meaning a payload of the form:
{
"<model-name>": {
// model's serialized attributes
}
}
Now all you have to do is to set the desired attributes on the record before deleting, and destroy the record.
model.setProperties({
deleteReason: 'whatever'
});
model.destroyRecord();
/*
results a DELETE request when requestBody is "{
"<model-name>": {
...
"deleteReason": "whatever"
...
}
}"
*/
I need to test my own angular provider, and I need to test it in both config and run phase to check that config methods work and that the instantiated provider is indeed configured with the correct parameters.
When I ask dependancy injection for the provider, it can't find the APIResourceFactoryProvider, only the APIResourceFactory, and I haven't found any examples of this on the repositories I've looked trough so far.
It's actually a lot simpler than it would at first seem to test a provider in AngularJS:
describe('Testing a provider', function() {
var provider;
beforeEach(module('plunker', function( myServiceProvider ) {
provider = myServiceProvider;
}));
it('should return true on method call', inject(function () {
expect( provider.method() ).toBeTruthy();
}));
});
```
The proof is in the Plunker: http://plnkr.co/edit/UkltiSG8sW7ICb9YBZSH
Just in case you'd like to have a minification-proof version of your provider, things become slightly more complicated.
Here is the provider code:
angular
.module('core.services')
.provider('storageService', [function () {
function isLocalStorageEnabled(window) {
return true;
}
this.$get = ['$window', 'chromeStorageService', 'html5StorageService',
function($window, chromeStorageService, html5StorageService) {
return isLocalStorageEnabled($window) ? html5StorageService : chromeStorageService;
}];
}]);
The test case:
describe('Storage.Provider', function() {
var chrome = {engine: 'chrome'};
var html5 = {engine: 'html5'};
var storageService, provider;
beforeEach(module('core.services'));
beforeEach(function () {
module(function (storageServiceProvider) {
provider = storageServiceProvider;
});
});
beforeEach(angular.mock.module(function($provide) {
$provide.value('html5StorageService', html5);
$provide.value('chromeStorageService', chrome);
}));
// the trick is here
beforeEach(inject(function($injector) {
storageService = $injector.invoke(provider.$get);
}));
it('should return Html5 storage service being run in a usual browser', function () {
expect(storageService).toBe(html5);
});
});
In this case $get is an array and you can't just call it as a usual function providing dependencies as arguments. The solution is to use $injector.invoke().
That's strange that most tutorials and samples miss this detail.
here is a little helper that properly encapsulates fetching providers, hence securing isolation between individual tests:
/**
* #description request a provider by name.
* IMPORTANT NOTE:
* 1) this function must be called before any calls to 'inject',
* because it itself calls 'module'.
* 2) the returned function must be called after any calls to 'module',
* because it itself calls 'inject'.
* #param {string} moduleName
* #param {string} providerName
* #returns {function} that returns the requested provider by calling 'inject'
* usage examples:
it('fetches a Provider in a "module" step and an "inject" step',
function() {
// 'module' step, no calls to 'inject' before this
var getProvider =
providerGetter('module.containing.provider', 'RequestedProvider');
// 'inject' step, no calls to 'module' after this
var requestedProvider = getProvider();
// done!
expect(requestedProvider.$get).toBeDefined();
});
*
it('also fetches a Provider in a single step', function() {
var requestedProvider =
providerGetter('module.containing.provider', 'RequestedProvider')();
expect(requestedProvider.$get).toBeDefined();
});
*/
function providerGetter(moduleName, providerName) {
var provider;
module(moduleName,
[providerName, function(Provider) { provider = Provider; }]);
return function() { inject(); return provider; }; // inject calls the above
}
the process of fetching the provider is fully encapsulated: no need for closure variables that compromise isolation between tests.
the process can be split in two steps, a 'module' step and an 'inject' step, which can be appropriately grouped with other calls to 'module' and 'inject' within a unit test.
if splitting is not required, retrieving a provider can simply be done in a single command!