How to statically validate JS construction statement by statement - javascript

I have JS as defined below (JS File). On push to a repo I want to statically validate things defined below (Validate This). I've been researching this and my first idea is to validate items 1-4 using https://www.npmjs.com/package/espree. Appreciate it if someone can confirm if this would do the job (be the best method) and if so an example validating the returned AST.
Validating item 5 is a little more interesting I need to extract the contents that w.abc.myobj is set which will effectively always equate to JSON and validate it's contents against rules using something like https://www.npmjs.com/package/ajv. Appreciate any insights on how best to do this as well especially the extraction of the JSON from the static code file.
Validate This
/*
1. Is the first statement a try/catch block
2. Is the first statement within the try/catch block an anonymous function with a "w" arg
3. Is the second statement what is shown
4. Is the anonymous function called with the window object
5. Next i'd like to grab w.abc.myobj and validate it using schema validation.
*/
JS File
try {
(function (w) {
w.abc = w.abc || {};
w.abc.myobj = {
"prop1": {
"enabled": true,
"type": "non-fiction",
"params: {
"serverInfo": {
"url": "{arg} ? https://www.url1.com : https://www.url2.com",
"path": "/some/directory"
},
"accountInfo: {
"user": "someUser1"
}
}
},
"prop2: {
"enabled": true,
"type": "fiction",
"params": {
"serverInfo": {
"url": "https://www.url2.com",
"path": "/some/directory"
},
"accountInfo: {
"user": "someUser2"
}
}
}
};
})(window);
} catch (e) { /* do nothing */ }

EsLint is built on top of the packages you mention, so you could make your life easier by writing an eslint plugin for each of your tests.

Related

Read Content from a JSON file to be able to complement my url search within cypress

I'm currently working with some testing files that will be looking into some records that will provide me some data to be able to do a web search. However, I just want to read a specific input from my file. For the same reason, I added the following:
describe('Search', function () {
beforeEach(() => {
cy.login()
cy.fixture('latestLead.json').then(function (lead) {
this.lead = lead
})
it('Convert Lead to an Opportunity', () => {
cy.readFile('cypress/fixture/latestLead.json').then(r => {
r.forEach((item: any) => {
cy.log(item.Id);
});
});
})
})
My json file is the following:
{
"status": 0,
"result": {
"totalSize": 1,
"done": true,
"records": [
{
"attributes": {
"type": "Lead",
"url": "/services/data/v51.0/sobjects/Test/11111111"
},
"Id": "1111111111111",
"Name": "Andres Test Test"
}
]
}
}
The main issues issue is telling me that 'any' is not right, and my cypress will not run. However, I would like to see if it is a better way to get the 'Id' from my json file. Does anyone have a better idea of how to do this?
I would probably assign the fixture an alias and call that in the tests and have the execution within the cy.get() for the fixture. A few things to note with using fixtures: they are only loaded once, even if data changes.
describe('Search', function () {
cy.fixture('latestLead.json').as('latestLead')
it('Convert Lead to an Opportunity', () => {
cy.get('#latestLead').then((data) => {
var ids = []
data.result.records.forEach((record) => {
ids.push(record.Id)
})
// whatever you need to do with the ids
})
})
})
If you will only ever have the one object in the records array, you could bypass the .forEach() and just reference the variable directly (data.results.records[0].Id).
Also, are you using types anywhere else? I'm not sure why you would set item: any unless you were using types.

Get the JSON object that matches a specific value

I'm building a little web-app to practice and learn Vue.js and working with APIs.
For a particular problem I want to solve, I would like to return the object that has the matching uuid that I request.
With my current knowledge, I understand I can do this by implementing some sorts and loops logic.
However I'm still new with JS, Vue.js, so I'm not sure if there is a better way to approach this.
Is there a built in function, or some form of "best practice" to approach this?
methods: {
fetchItem(row) {
// row.target_uuid -- this is the UUID I want
// this.$props.todoItems; -- this contains the json objects
// return this.$props.todoItems[i] where this.$props.todoItems[i]['uuid'] == row.target_uuid
},
This is a snippet of my $props.todoItems for context
[
{
"title": "Install Maris",
"uuid": "9ec9ea6b-0efc-4f6a-be2e-143be5748d3a",
"field_completed": "False"
},
{
"title": "Figure out why VS Code sucks",
"uuid": "85120da5-ee59-4947-a40f-648699365c73",
"field_completed": "False"
},
{
"title": "Start designing portfolio",
"uuid": "243c1960-7ade-4a68-9a74-0ccc4afa3e36",
"field_completed": "False"
},
{
"title": "Meal Prep",
"uuid": "85b64b18-9110-44d8-bd2d-8f818b0a810f",
"field_completed": "False"
},
{
"title": "Sharpen knives",
"uuid": "8a7ac5f6-8180-4f20-b886-628fd3bcfc85",
"field_completed": "False"
},
{
"title": "Set up SSH keys",
"uuid": "f879c441-8c05-4f24-9226-125c62576297",
"field_completed": "False"
}
]
If you know you're looking for exactly one item (or the first item that matches) you should take a closer look at the Array.find() method provided by JS. (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/find)
Also take a look at all the other methods the Array prototype provides, most of them are fairly descriptive and solve most of the basic problems you'll encounter.
To use this in your Vue app you can either have a method that returns your todo based on a provided uid like this
todoByUid(uidToFind) {
return this.todos.find(todo => todo.uid == uidToFind)
}
If you only care about a currently selected item a computed value as Jacob mentioned is the way to go:
computed() {
selectedTodo() {
return this.todos.find(todo => todo.uid == this.selectedUid)
}
}

Trouble getting Alexa slot value is AWS Lamba function

I have created an intent in Alexa console and corresponding function in AWS Lambda (Javascript) and it's working for the most part as expected. However I can't seem to gather the slot values.
exports.handler = function (event, context, callback) {
const alexa = Alexa.handler(event, context, callback);
alexa.APP_ID = APP_ID;
let config = new Map();
let character = this.event.request.intent.slots.character.value;
if (!character)
character = 'default';
let handlers = getHandlers(config);
alexa.registerHandlers(handlers);
alexa.execute();
};
The error I'm receiving in the Alexa test is mostly not helpful and I'm generally finding debugging Alexa quite painful. I have tried testing directly from within Lambda and passing a JSON payload but I'm unsure if this would work anyway.
Can someone comment on whether this.event.request.intent.slots.character.value; would be correct? I can't see this on official AWS pages but in other peoples' examples.
Lastly, the payload from Alexa test has this included:
"request": {
"type": "IntentRequest",
"requestId": "amzn1.echo-api.request.43808260-5aaa-4837-9f28-4eaccb7c9b3c",
"timestamp": "2018-05-31T00:49:08Z",
"locale": "en-AU",
"intent": {
"name": "playSeinfeldQuoteIntent",
"confirmationStatus": "NONE",
"slots": {
"character": {
"name": "character",
"confirmationStatus": "NONE"
},
"position": {
"name": "position",
"confirmationStatus": "NONE"
}
}
}
}
I would have expected it to have the values on the slots included here but they're not so this may be the issue.
Any suggestions would be really helpful.
Edit: I found that I was capturing the values OK but the first letter of each variable was being capitalised. I guess because they are peoples' names Alexa is capitalising them. I hadn't considered that.

JSON, node.js: access classes via its name (String)

Here's my situation, I have a JSON that looks somewhat like this:
{
"items": [{
"type": "condition",
"data": {
"type": "comparison",
"value1": {
"source": "MyType1",
"component": "Attribute1"
},
"value2": {
"source": "MyType2",
"component": "Attribute2"
},
"operator": "gt"
}
},
{
"type": "then",
"data": {
"result": "failed",
"message": "value1 is too high"
}
}
]
}
and would want it to translate to:
if (MyType1.Attribute1 > MyType2.Attribute2) {
result = "failed";
console.log("value1 is too high");
}
Now my problem is, I don't know how I would translate the entries of value1 and value2 to actual code, or rather, how I could access the Object MyType1(maybe through something like getAttribute("MyType1")).
Since I am going to have a whole bunch of sources which each have different components, I cant really write a huge dictionary. Or I would like to avoid it.
The goal is to allow creating if - then - statements via some interactive UI, and I figured it'd be best to save that code as .json files. (Think rule management system).
So, TL,DR, How would I access a Class Attribute this.MyType, if I only have a String MyType to go from? And how would I access the value this.MyType.MyValue, if I get another String MyValue?
Thanks in advance.
Edit:
I'd really like to avoid using eval, for obvious reasons. And if I have to - I guess I would need to create Dictionaries for possible JSON Values, to validate the input?
You need some kind of parser. At first we need some way to store variables and maybe flags:
const variables = {};
var in = false;
Then we go through the code and execute it:
for(const command of items){
switch( command.type ){
case "condition":
//...
case "then":
//...
}
}
To access a variable we can simply do
var current = variables[ identifier ];
To store its the other way round:
variables[ identifier ] = current;

Limiting fields returned by mongo dynamically

I use Meteor to query a mongo collection. It has for example the following entry:
{
"_id": "uCfwxKXyZygcWQeiS",
"gameType": "foobar",
"state": "starting",
"hidden": {
"correctAnswer": "secret",
"someOtherStuff": "foobar"
},
"personal": {
"Y73uBhuDq2Bhk4d8W": {
"givenAnswer": "another secret",
},
"hQphob8s92gbEMXbY": {
"givenAnswer": "i have no clue"
}
}
}
What I am trying to do now is:
don't return the values behind "hidden"
from the "personal" embedded document only return the values for the asking user
In code it would look something like this:
Meteor.publish('game', function() {
this.related(function(user) {
var fields = {};
fields.hidden = 0;
fields.personal = 0;
fields['personal.' + this.userId] = 1;
return Games.find({}, {fields: fields});
}, Meteor.users.find(this.userId, {fields: {'profile.gameId': 1}}));
}
Obviously this won't work, because MongoDB won't allow mixed includes and excludes. On the other hand, I cannot switch to "specify only the included fields", because they can vary from gameType to gameType and it would become a large list.
I really hope that you can help me out of this. What can I do to solve the problem?
Typical example of where to use the directly controlled publication features (the this.added/removed/changed methods).
See the second example block a bit down the page at http://docs.meteor.com/api/pubsub.html#Meteor-publish.
With this pattern you get complete control of when and what to publish.

Categories