Background:
I've created a Dynamo DB table and populated it. I have some code to read an item in a file called readItem.js which works when I run it stand-alone but does NOT work when I run it as a Mocha test case.
Any ideas why the code is not running properly inside of an it() test case?
For standalone, I run the app like this:
node readItem.js
readItem.js:
var AWS = require("aws-sdk");
AWS.config.update({
region: "us-west-2",
endpoint: "http://localhost:8000"
});
var docClient = new AWS.DynamoDB.DocumentClient();
var table = "Movies";
var year = 2015;
var title = "The Big New Movie";
var params = {
TableName: table,
Key:{
"year": year,
"title": title
}
};
docClient.get(params, function(err, data) {
if (err) {
console.error("Unable to read item. Error JSON:", JSON.stringify(err, null, 2));
} else {
console.log("GetItem succeeded:", JSON.stringify(data, null, 2));
}
});
However, when I run it inside of a Mocha test case, the callback function on docClient.get() call is not being invoke, i.e.:
docClient.get(params, function(err, data) { ...// Not being invoked });
Here is how I have the code structured as a test case. I invoke the test with:
npm run test
Where "test" is defined in my package.json as:
"scripts": {
"test": "./node_modules/.bin/mocha --recursive --reporter spec --ui bdd test/"
}
Test Case code:
const AWS = require('aws-sdk');
AWS.config.update({
region: "us-west-2",
endpoint: "http://localhost:8000"
});
var docClient = new AWS.DynamoDB.DocumentClient({apiVersion: '2012-08-10'});
let table = "Movies";
let year = 2015;
let title = "The Big New Movie";
let params = {
TableName: table,
Key:{
"year": year,
"title": title
}
};
describe('DynamoDB Tests', function() {
it("Read Item", function() {
try {
docClient.get(params, function (err,data) {
if (err) {
console.error("Unable to read item. Error JSON:", JSON.stringify(err, null, 2));
} else {
console.log("GetItem succeeded:", JSON.stringify(data, null, 2));
}
});
} catch (err) {
console.log("ERROR:"+ err);
}
});
});
I was using older version of mocha:
"mocha": "^3.5.3"
Upgrading fixed it
"mocha": "^6.1.4"
Related
I am trying to get the data where the product name is same and implementing the code by using nodejs.`
AWS.config.update({region : "us-east-1"});
var docClient = new AWS.DynamoDB.DocumentClient();
var params = {
TableName: "ProductLocation",
FilterExpression: "#pn = :a",
ExpressionAttributeNames: {
"#pn": "Product_Name",
},
ExpressionAttributeValues: {
":a" : "rava"
}
};
console.log("Scanning Product_Name table.");
docClient.scan(params, onScan);
function onScan(err, data) {
if (err) {
console.error("Unable to scan the table. Error JSON:", JSON.stringify(err, null, 2));
} else {
// print all the movies
console.log("Scan succeeded.");
console.log(data);
}
}
Below is my dynamodb data
Your ExpressionAttributeValues should be:
{":a" : {S:"rava"}}
i.e. include the data type
Reference: see the complete example
I am trying to access a table in DynamoDB which is hosted in Europe (Ireland) eu-west-1, from a lambda endpoint which is hosted in US East (N. Virginia) us-east-1 - however, I am always getting the error:
{
"message": "Requested resource not found",
"code": "ResourceNotFoundException",
"time": "2020-07-05T22:13:17.145Z",
"requestId": "6SGPGDFVN6AE4QMC5A8LG2RJ0JVV4KQNSO5AEMVJF66Q9ASUAAJG",
"statusCode": 400,
"retryable": false,
"retryDelay": 27.110475966612935
}
this is my code my code to call the DB:
class DynamoDB {
constructor() {
this.region = 'eu-west-1';
this.endpoint = 'https://dynamodb.eu-west-1.amazonaws.com';
this.tableName = 'MyTableName';
this.docClient = new AWS.DynamoDB.DocumentClient();
}
getUser(userId) {
return new Promise((resolve, reject) => {
const params = {
TableName: this.tableName,
Key: {
"id": userId,
}
}
this.docClient.get(params, function(err, data) {
if (err || !data.Item) {
console.error("Unable to read item. Error JSON:", JSON.stringify(err, null, 2));
return reject(JSON.stringify(err, null, 2))
} else {
console.log("GetItem data succeeded:", JSON.stringify(data, null, 2));
resolve(data.Item);
}
});
});
}
}
const DynamoDB = require("../Libraries/DynamoDB");
const $ = new DynamoDB;
const Interceptor = {
async process(session) {
return $.getUser(session.id).then(data => {
console.log(`User gotten! ${JSON.stringify(data, null, 2)}`);
}).catch(err => {
console.log(`Failure getting user... ${err}`);
};
}).finally(async () => {
await InitGameSettings();
});
}
When I attempt this using an endpoint that is hosted in the same region as the DynamoDB table - it works fine! Only when I try this using different regions does it break. Why is this?
Looks like the SDK is not using the DDB region and endpoint that you configured. Could you try replacing the constructor() with the following code snippet?
constructor() {
this.region = 'eu-west-1';
this.endpoint = 'https://dynamodb.eu-west-1.amazonaws.com';
this.tableName = 'MyTableName';
this.ddbService = new AWS.DynamoDB({
apiVersion: '2012-08-10',
endpoint: this.endpoint,
region: this.region
});
this.docClient = new AWS.DynamoDB.DocumentClient({
service: this.ddbService
});
}
I'm having trouble with the AWS DynamoDb JS SDK v2.4.9. I want to use the DocumentClient class as opposed to the lower level DynamoDb class, but can't get it working.
This works:
function testPutItem( callback ) {
var tableName = 'todos';
var params = {
TableName: tableName,
Item: {
user_id: { S : userId },
id: { N : msFromEpoch }, // ms from epoch
title: { S : makeRandomStringWithLength(16) },
completed: { BOOL: false }
}
};
var dynamodb = new AWS.DynamoDB();
dynamodb.putItem(params, function(err, data) {
if (err) console.log(err, err.stack); // an error occurred
else {
console.log(data); // successful response
if (callback) callback(data);
}
});
}
This does not work and gives the error InvalidParameterType: Expected params.Item[attribute] to be a structure for each attribute--as if DocumentClient is expecting the same input as DynamoDb:
function testPutItem( callback ) {
var tableName = 'todos';
var params = {
TableName: tableName,
Item: {
user_id: userId,
id: msFromEpoch,
title: makeRandomStringWithLength(16),
completed: false
}
};
console.log(params);
var docClient = new AWS.DynamoDB.DocumentClient({region: 'us-east-1'});
docClient.put(params, function(err, data) {
if (err) console.log(err, err.stack); // an error occurred
else {
console.log(data); // successful response
if (callback) callback(data);
}
});
}
Does anyone have any idea what I am doing wrong?
I used to have the same issue,
please try with a simple object first, cause it's due to some special characters in your attributes, see my example :
this generates the error
InvalidParameterType: Expected params.Item[attribute] to be a structure
var Item = {
domain: "knewtone.com",
categorie: "<some HTML Object stuff>",
title: "<some HTML stuff>",
html: "<some HTML stuff>""
};
but when i replace the HTML stuff with a formated Html, simple characters , it works
var Item = {
domain: "knewtone.com",
categorie: $(categorie).html(),
title: $(title).html(),
html: $(html).html()
};
I am new to ionic.I want to add data into SQLite which is coming from remote server. I have successfully populated data into list.so how can i store this data into sqlite. here is my code. how do i pass this data to query.I am unable to do this.
service.js
angular.module('starter.service',[]).
factory('userServices',['$http',function($http){
var users = [];
return {
get: function(){
return $http.get("http://xxxxxxxxx-info").then(function(response){
users = response.data;
return users;
});
},
remove:function(content){
users.splice(users.indexOf(content),1);
},
getUser:function(chatId)
{
for(var i=0; i<users.length;i++){
if(users[i].content_id === parseInt(chatId)){
return users[i];
}
}
return null;
}
}
}]);
controller.js
angular.module('shoppingPad.controller', [])
.controller('ChatCtrl', function ($scope, userServices, $ionicModal, $cordovaSQLite) {
console.log('inside controller');
userServices.get().then(function (users) {
//users is an array of user objects
$scope.contents = users;
console.log($scope.contents);
var query = "INSERT INTO content (content_id, display_name) VALUES (?,?)";
$cordovaSQLite.execute(db, query, [users.content_id, users.display_name]).then(function (res) {
alert(res);
alert('Inserted');
}, function (e) {
alert('Error:' + e.message);
});
});
Where did you define db? It's necessary to wait until device is ready.
$ionicPlatform.ready(function () {
var db = $cordovaSQLite.openDB({ name: "my.db" });
// just first time you need to define content table
$cordovaSQLite.execute(db,"CREATE TABLE content (content_id integer, display_name text)");
userServices.get().then(function (users) {
//users is an array of user objects
$scope.contents = users;
console.log($scope.contents);
var query = "INSERT INTO content (content_id, display_name) VALUES (?,?)";
$cordovaSQLite.execute(db, query, [users.content_id, users.display_name]).then(function (res) {
alert(res);
alert('Inserted');
}, function (e) {
alert('Error:' + e.message);
});
});
});
Are you sure, that your object users look like
{
"content_id":12,
"display_name":"hello world"
}
and not like
[
{
"content_id":12,
"display_name":"hello world"
},
{
"content_id":13,
"display_name":"stackoverflow"
},
...
]
I just ask, because users sounds like more than one entry.
I've been modifying the example meteor app at http://meteor.com/examples/leaderboard. As you can see in the code bellow, I'm trying to update the score of players upon someone hitting the reset button. This updated fine on the client side but in my console I noticed the error "update failed: 500 -- Internal server error". Upon further inspection I saw that indeed, the server side database was not being updated. Any thoughts? (relevant code is in the reset function but I've posted the rest here just in case)
// Set up a collection to contain player information. On the server,
// it is backed by a MongoDB collection named "players."
Players = new Meteor.Collection("players");
var SORT_OPTIONS = {
name: {name: 1, score: -1},
score: {score: -1, name: 1}
}
var NAMES = [ "Ada Lovelace",
"Grace Hopper",
"Marie Curie",
"Carl Friedrich Gauss",
"Nikola Tesla",
"Claude Shannon" ];
function reset(options) {
if (options && options['seed'] === true) {
for (var i = 0; i < NAMES.length; i++) {
Players.insert({ name: NAMES[i], score: Math.floor(Math.random()*10)*5 });
}
}
if (options && options['restart'] === true) {
Players.update( {},
{ $set: { score: Math.floor(Math.random()*10)*5 } },
{multi: true});
}
}
if (Meteor.is_client) {
Template.leaderboard.players = function () {
var sort_by = SORT_OPTIONS[Session.get("sort_by")]
return Players.find({}, {sort: sort_by});
};
Template.leaderboard.selected_name = function () {
var player = Players.findOne(Session.get("selected_player"));
return player && player.name;
};
Template.player.selected = function () {
return Session.equals("selected_player", this._id) ? "selected" : '';
};
Template.leaderboard.events = {
'click input.inc': function () {
Players.update(Session.get("selected_player"), {$inc: {score: 5}});
},
'click input.sort': function () {
Session.get("sort_by") == "score" ? Session.set("sort_by", "name") : Session.set("sort_by", "score");
},
'click input.reset': function () {
reset({'restart': true});
}
};
Template.player.events = {
'click': function () {
Session.set("selected_player", this._id);
}
};
}
// On server startup, create some players if the database is empty.
if (Meteor.is_server) {
Meteor.startup(function () {
if (Players.find().count() === 0) {
reset({'seed': true});
}
});
}
This also happened to me, but checking the server log, the problem I had was that the $inc modifier requires a number for the argument for the update method, so I made sure it got it with
Number()
Time went by and it now works :) I guess it was some server issue on their demo deploy site.