Cypress graphql apollo call gives no result and retries automatically - graphql

The problem is that instead of mocked I got a loading screen with unresolved query, Cypress make several attempts to re-query it again, and there is no error messages.
I'm using Cypress from Quasar-testing harness. I'd like to mock graphql call.
In my component I have an apollo query:
apollo: {
assetsOverview: {
query: ASSETS_OVERVIEW,
loadingKey: 'loading'
}
}
For that purpose I'm using fixtures in such way:
cy.intercept('POST', api, req => {
if (req.body.operationName === 'getAssetOverview') {
// This condition works just fine
req.reply({
fixture: 'asset-table.json'
})
}
})
My fixture looks like this:
{
"assetsOverview": {
"assetMetrics": [
{
"assetId": "todo-conveyor",
"assetName": "Conveyor belts",
"childAssetIds": null,
"oeeMetrics": {
"availability": null,
"oee": null,
"performance": null,
"quality": null,
"__typename": "AssetOeeMetrics"
},
"stateMetrics": {
"blocked": null,
"failed": null,
"idle": null,
"running": null,
"stopped": null,
"__typename": "AssetStateMetrics"
},
"__typename": "AssetMetrics"
}
],
"__typename": "AssetMetricsOverview"
}
}

Figured out that I have to wrap my fixtures object within data.
Like this:
{
"data": {
"assetsOverview": {
"assetMetrics": [
...
]
}
}
}

Related

Parse.Query.Exclude() function not excluding the given values

I am trying to write cloud code that excludes certain values from a query. I have tried using both select() and exclude() to limit what values come back in a query. Here is what my code looks like
Parse.Cloud.beforeFind(Parse.User, (request) => {
return request.query.select('email');
});
For reference, here is the curl command that I am using to test my cloud code:
curl --location --request GET 'https://<parse-server>.b4a.io/parse/users' \
--header 'X-Parse-Application-Id: <app-id>' \
--header 'X-Parse-REST-API-Key: <api-key>' \
--header 'X-Parse-Session-Token: <token>'
In theory, the response to this command should look something like this:
{
results:[{'email':'123#example.com'},{'email':'456#example.com'}']
}
Instead what I get is the following(all of the user information I would normally get if I did nothing):
{
"results": [
{
"objectId": "jKXYLgeB6x",
"username": "cperryoh",
"email": "123#example.com",
"isBanned": false,
"emailVerified": true,
"createdAt": "2022-07-25T17:09:37.963Z",
"updatedAt": "2022-07-27T16:34:54.186Z",
"chunksOwned": {
"__type": "Relation",
"className": "chunk"
},
"ACL": {
"jKXYLgeB6x": {
"read": true,
"write": true
},
"*": {
"read": true
}
}
},
{
"objectId": "ykJJhvNuPh",
"username": "testUser",
"email":"456#example.com"
"isBanned": false,
"emailVerified": true,
"createdAt": "2022-07-25T19:39:02.854Z",
"updatedAt": "2022-07-27T16:20:48.083Z",
"chunksOwned": {
"__type": "Relation",
"className": "chunk"
},
"ACL": {
"*": {
"read": true
},
"ykJJhvNuPh": {
"read": true,
"write": true
}
}
}
]
}
To further add to the confusion, in the cloud-code/parse-SDK documentation, there is no reference to the beforeFind trigger. So I am not even sure what the return type of lambda/function is supposed to be. The only thing I have that is telling me I can return a query object is an example in the cloud code guide here. In one of the examples, they return the result of Parse.Query.or() which does return an object of type Query. Am I using .select() incorrectly or is it not meant for what I am trying to do? Thanks for the help!
Try just:
Parse.Cloud.beforeFind(Parse.User, (request) => {
request.query.select('email');
});

How can i perform batch update in graphQl

I have a user schema and have a update mutation
mutation MyMutation {
updateUser(input: {Order: 47, id: "981f3cb8-a369-4f0f-8d3d-28d159a3eace"}) {
firstname
id
}
}
Now i have to update multiple list of id with their respective list of order
mutation MyMutation($id: [String!] = ["981f3cb8-a369-4f0f-8d3d-28d159a3eace","0b2cb7d2-8dd9-4b11-846c-6370d003f6f9"], $Order: [Int] =
[47,48]) {
updateUser(input: {id: $id, Order: $Order}) {
firstname
}
}
But i'm getting below error in console
{
"data": {
"updateUser": null
},
"errors": [
{
"path": [
"updateUser"
],
"data": null,
"errorType": "MappingTemplate",
"errorInfo": null,
"locations": [
{
"line": 2,
"column": 3,
"sourceName": null
}
],
"message": "Value for field '$[key][id][S]' must be text."
}
]
}
Option 1: Use a For Loop
async function update(e) {
for (const item of array) {
try {
await API.graphql({
query: createImage,
variables: {
input: {
id: id, },
},
authMode: "AMAZON_COGNITO_USER_POOLS",
});
} catch (err) {
console.log(err)
}
}
}
}
Option Two, create a custom batch resolver:
https://docs.aws.amazon.com/appsync/latest/devguide/tutorial-dynamodb-batch.html
https://docs.amplify.aws/cli/graphql/examples-and-solutions/#batch-put-custom-resolver

Are transactions in a batch serialized?

if I send a transaction with 2 contract fn calls, does the 2nd gets executed if the 1st fails?
sample code:
const actions = [
TX.functionCall("select_staking_pool", { staking_pool_account_id: stakingPool }, this.BASE_GAS.muln(3), new BN(0)),
TX.functionCall("deposit_and_stake", { amount: near.ntoy(amountNear) }, this.BASE_GAS.muln(5), new BN(0))
]
return near.broadcast_tx_commit_actions(actions, sender, lockupContract, privateKey)
I did execute this batch, but the result gives me no clear answer: https://explorer.testnet.near.org/transactions/DcchgGdzAVEvNqRReHkjsmrTr5PoaMoibs3fyKoKBYSe
The 1st fn call code uses cross-contract calls and a callback code to check if the contract is whitelisted, but I can't see the callback's log code in the receipt logs. I assume the 1st call fails because the second fails with the error: "staking pool is not selected"
Here's the full result:
{
"status": {
"Failure": {
"ActionError": {
"index": 1,
"kind": {
"FunctionCallError": {
"HostError": {
"GuestPanic": {
"panic_msg": "panicked at 'Staking pool is not selected', src/internal.rs:90:9"
}
}
}
}
}
}
},
"transaction": {
"signer_id": "lucio.testnet",
"public_key": "ed25519:Cvqie7SJ6xmLNA5KoTAYoUAkhD25KaJLG6N9oSmzT9FK",
"nonce": 33,
"receiver_id": "274e981786efcabbe87794f20348c1b2af6e7963.lockupy.testnet",
"actions": [
{
"FunctionCall": {
"method_name": "select_staking_pool",
"args": "eyJzdGFraW5nX3Bvb2xfYWNjb3VudF9pZCI6Im5vcnRoZXJubGlnaHRzLnN0YWtpbmdwb29sIn0=",
"gas": 75000000000000,
"deposit": "0"
}
},
{
"FunctionCall": {
"method_name": "deposit_and_stake",
"args": "eyJhbW91bnQiOiIxMDk0OTkwMDAwMDAwMDAwMDAwMDAwMDAwMDAwIn0=",
"gas": 125000000000000,
"deposit": "0"
}
}
],
"signature": "ed25519:gzCsrcobVtjuD6FE4qDhgo9zdk2feBp6dfa66NZYLPTnwypF7g8mDM7yubcnkVcF1sPzEFeEfJtQ4hwwnhrxTa6",
"hash": "EjiQBjzF6Ea74wSHkjmZMkhTGwgYxbUdeVKUvzaA8X7k"
},
"transaction_outcome": {
"proof": [],
"block_hash": "3xEuw43E1W4FP2q1Un6XLsDSbhRc7c7FMtGWWL6i3KJj",
"id": "EjiQBjzF6Ea74wSHkjmZMkhTGwgYxbUdeVKUvzaA8X7k",
"outcome": {
"logs": [],
"receipt_ids": [
"75pJCVuheYCjX82RspQzoKm5v7NSG1QNUaPK7DRzZYNt"
],
"gas_burnt": 4748079879222,
"tokens_burnt": "474807987922200000000",
"executor_id": "lucio.testnet",
"status": {
"SuccessReceiptId": "75pJCVuheYCjX82RspQzoKm5v7NSG1QNUaPK7DRzZYNt"
}
}
},
"receipts_outcome": [
{
"proof": [
{
"hash": "55YXLhqDc63f8n4MdZNwi6TdmtFkaYp18wKwm7qFmDo5",
"direction": "Left"
}
],
"block_hash": "DB3p49tiSBfRLv5diDUStajtDiMNs2KroKfRcr2cQDnV",
"id": "75pJCVuheYCjX82RspQzoKm5v7NSG1QNUaPK7DRzZYNt",
"outcome": {
"logs": [
"Selecting staking pool #northernlights.stakingpool. Going to check whitelist first."
],
"receipt_ids": [
"HXStMQuf5aWKVpWDM1Hf4EdA3S4FLTGjmYaF2WAYRcUz"
],
"gas_burnt": 20291176638173,
"tokens_burnt": "2029117663817300000000",
"executor_id": "274e981786efcabbe87794f20348c1b2af6e7963.lockupy.testnet",
"status": {
"Failure": {
"ActionError": {
"index": 1,
"kind": {
"FunctionCallError": {
"HostError": {
"GuestPanic": {
"panic_msg": "panicked at 'Staking pool is not selected', src/internal.rs:90:9"
}
}
}
}
}
}
}
}
},
{
"proof": [],
"block_hash": "2kua8s7vjix2MiMHZ7Rzbrhyv8UbGFEpvWeT67H2qCYM",
"id": "HXStMQuf5aWKVpWDM1Hf4EdA3S4FLTGjmYaF2WAYRcUz",
"outcome": {
"logs": [],
"receipt_ids": [],
"gas_burnt": 0,
"tokens_burnt": "0",
"executor_id": "lucio.testnet",
"status": {
"SuccessValue": ""
}
}
}
]
}
Edit: PS. It looks like the 1st function call was failing silently (regarding Tx result). I tested the same calls as 2 separate transactions and the 1st one (select_staking_pool) succeeded.
All later actions after the first failed action are not executed. And their execution fees are refunded. All the changes that were successfully executed before, will be reverted and all the promises will not be scheduled and executed either.
Your case is more complicated, because the first action succeeds by returning a promise. The resulting promise later will fails in the callback, but the second action fails immediately, because the staking pool is not selected yet due to async execution. So the first promise doesn't get scheduled.
EDIT 1.
Once a transaction or a receipt succeeds (finishes all actions) it doesn't rollback anything. So if any future promises fail they are going to be independently executing from each other. Also only the last action in a batch of actions returns the result for the entire receipt.

apollo-link-state add field with default value to type

Here's what I'm trying to accomplish:
I have a graphql API endpoint that returns me a Project object like this(unrelated fields removed):
{
"data": {
"Project": {
"id": "cjp4b84wkochq0167gpu8oa7h",
"requests": [
{
"id": "cjpbb6jcdpwj00167y4acl5a1",
"__typename": "Request"
},
{
"id": "cjpbbhlaxpwlx01675jzfyb0j",
"__typename": "Request"
},
{
"id": "cjpbbifg7pwmg0167s0ob1bm6",
"__typename": "Request"
},
],
"__typename": "Project"
}
}
}
I want to use apollo-link-state to add a client-side field to all of these Request objects like this:
{
"data": {
"Project": {
"id": "cjp4b84wkochq0167gpu8oa7h",
"requests": [
{
"id": "cjpbb6jcdpwj00167y4acl5a1",
"expanded": false,
"__typename": "Request"
},
{
"id": "cjpbbhlaxpwlx01675jzfyb0j",
"expanded": false,
"__typename": "Request"
},
{
"id": "cjpbbifg7pwmg0167s0ob1bm6",
"expanded": false,
"__typename": "Request"
},
],
"__typename": "Project"
}
}
}
This would allow me to remove local state from my Component that renders these requests. The problem is that when I define defaults for my ApolloClient clientState as follows:
const client = new ApolloClient({
clientState: {
defaults: {
Project: {
__typename: 'Project',
requests: [{ __typename: 'Request', expanded: false }],
},
},
},
});
Apollo adds it as a new Project object instead of adding it to the existing one(which has an id):
ROOT_QUERY
Project: Project
requests: [Request]
0:
expanded: false
Project({"id":"cjp4b84wkochq0167gpu8oa7h"}): Project
▾Project:cjp4b84wkochq0167gpu8oa7h
when I give it the id it adds the "hi" field to the correct project but the requests are still missing the expanded field. And giving the id only works for a specific project obviously.
const client = new ApolloClient({
clientState: {
defaults: {
'Project({"id":"cjp4b84wkochq0167gpu8oa7h"})': {
__typename: 'Project',
hi: true,
requests: [{ __typename: 'Request', expanded: false }],
},
},
},
});
ROOT_QUERY
Project({"id":"cjp4b84wkochq0167gpu8oa7h"}): Project
▾Project:cjp4b84wkochq0167gpu8oa7h
hi: true
requests: [Request]
0:▾Request:cjpbb6jcdpwj00167y4acl5a1
...unrelated fields
1:▾Request:cjpbbhlaxpwlx01675jzfyb0j
2:▾Request:cjpbbifg7pwmg0167s0ob1bm6
I also tried using the typeDefs field on the clientState object like this:
typeDefs: [`
schema {
query: RootQuery
}
type RootQuery {
Project($id: ID): Project
}
type Project {
id: ID!
requests: [Request]
}
type Request {
id: ID!
expanded: Boolean
}
`],
but this doesn't seem to change anything on the cache and I don't know if I can even give it a default value like this.
Maybe I'm misunderstanding how apollo-link-state works (or even how graphql works) any answer to point me in the right direction is appreciated. I'm very much a beginner when it comes to graphql or apollo.
You need to provide a client side resolver to your clientState configuration.
const clientState = {
resolvers: {
Project {
expanded: () => false
}
}
}
And then you'd pass this into your ApolloClient like so
const apolloClient = new ApolloClient({ clientState });

Integrating AngularJS into Spring Application

I currently have a method in my controller which does this:
#RequestMapping(value="/angular", produces="application/json")
public #ResponseBody Page handleAngularRequest(Model model, HttpServletRequest httpRequest){
return pageObject;
}
This returns all json data to the page like so:
{
"pageId": null,
"organizationId": null,
"pageModule": "browse",
"pageTitle": null,
"pkId": null,
"templateId": null,
"dataMap": null,
"pageEventList": null,
"pageElementList": null,
"tableId": null,
"elementId": null,
"elementDictionaryList": null,
"elementDictionaryEventList": null,
"elementIds": null,
"pageDataMap": {
"pageObjectId": "",
"module": "REQUISITION",
"mailId": "test#example.com",
"sessionId": "9d538ba3-2d41-4d5b-9f0d-4ac467f5e62e",
"requestId": "21061c6c-2868-46c7-bd31-bbebfb2eee4e",
"userId": "JHUBBARD0000000",
"pages": "",
"systemId": "9d538ba3-2d41-4d5b-9f0d-4ac467f5e62e",
"service": "",
"formatHeader": "Y",
"extrinsic": {
"pageObjectId": "",
"module": "REQUISITION",
"mailId": "test#example.com",
"sessionId": "9d538ba3-2d41-4d5b-9f0d-4ac467f5e62e",
"requestId": "21061c6c-2868-46c7-bd31-bbebfb2eee4e",
"userId": "test",
"pages": "",
"systemId": "9d538ba3-2d41-4d5b-9f0d-4ac467f5e62e",
"service": "",
"formatHeader": "Y"
},
"header": {
"RequisitionHeader_icReqHeader": ""
}
}
}
My question is: How do I get this data into an AngularJS controller/workflow so I can start bindding it and putting it onto a page?
A quick start-up would be like this:
http://plnkr.co/edit/uUj4MV3RvZB2P4uJt35H?p=preview
This will show the page.pageDataMap.mailId property from the JSON response.
app.js
angular.module('app', [])
.service('ApiService', ['$http', '$q', function($http, $q) {
return {
query: function() {
var deferred = $q.defer();
$http.get('/angular')
.success(function(data) {
deferred.resolve(data);
});
return deferred.promise;
}
};
}])
.controller('Controller', ['ApiService', '$scope', function(ApiService, $scope) {
$scope.page = {};
$scope.refresh = function() {
ApiService.query()
.then(function(data) {
$scope.page = data;
});
};
$scope.refresh();
}])
index.html
<div ng-app="app" ng-controller="Controller">
<div ng-bind="page.pageDataMap.mailId"></div>
</div>

Resources