I have a JSON based test data, how can I iterate over this test data for the test to run for each cred object?
cred: {
nameValue: 'ant',
emailValue: 'ant#gmail.com',
passwordValue: 'ant',
},
cred: {
nameValue: 'bat',
emailValue: 'bat#gmail.com',
passwordValue: 'bat',
},
your test data JSON file should be like this,
[
{
"nameValue": "ant",
"emailValue": "ant#gmail.com",
"passwordValue": "ant"
},
{
"nameValue": "bat",
"emailValue": "bat#gmail.com",
"passwordValue": "bat"
}
]
Now you can access them by index ( as in an array )
const testDataObject = require("path to testData json");
// to loop on all elements
testDataObject.forEach(function(element) {
it(' test case def ', function() {
console.log("nameValue "+ element['nameValue']+ "emailValue
"+element['emailValue'] + "passwordValue "+element[passwordValue]);
});
});
// to select any particular index
it(' test case def ', function() {
console.log("nameValue "+ testDataObject[1]['nameValue']+ "emailValue
"+testDataObject[1]['emailValue'] + "passwordValue "+testDataObject[1][passwordValue]);
});
});
And name your testData file name as Credentials_Valid.json ( best practice )
or
you can do in this way
{
"cred1":
{
"nameValue": "ant",
"emailValue": "ant#gmail.com",
"passwordValue": "ant",
},
"cred2":
{
"nameValue": "bat",
"emailValue": "bat#gmail.com",
"passwordValue": "bat",
}
}
and access the test data in nodejs code by
console.log( `${testDataObject['cred1']["nameValue"]}` );
console.log( `${testDataObject['cred1']["emailValue"]}` );
console.log( `${testDataObject['cred1']["passwordValue"]}` );
Related
I'm using Strapi 4, and I try to add computed field to my custom resolver. (I'm not a graphql expert). I've followed this tutorial to do it.
https://www.theitsolutions.io/blog/how-to-add-custom-graphql-query-to-strapi-v4
I’m also using the “toEntityResponseCollection” methods to send the datas and display it in graphql playground.
But, when I send it back, I get a null result.
Here is my custom resolver
"use strict";
module.exports =
(strapi, toEntityResponseCollection, toEntityResponse) =>
({ nexus }) => ({
typeDefs: `
type PopularityResponse {
id: ImpressionEntityResponseCollection
startDate: String
endDate: String
branding: String
}
extend type Query {
popularity(id: ID!, startDate: String, endDate: String, branding: String): PopularityResponse
}
`,
resolvers: {
Query: {
popularity: {
resolve: async (parent, args, context) => ({
id: args.id,
startDate: args.startDate,
endDate: args.endDate,
branding: args.branding,
}),
},
},
PopularityResponse: {
id: {
resolve: async (parent, args) => {
let query = {
value: await strapi.entityService.findMany(
"api::impression.impression",
{
filters: {
googleid: {
id: {
$eq: parent.id,
},
},
date_debut: {
$gte: parent.startDate,
},
date_fin: {
$lte: parent.endDate,
},
},
},
args
),
};
console.log(query.value);
console.log(parent);
let aggregate = query.value.reduce(
(acc, key) => {
// vérifie si la campagne est dans la liste
if (
[parent.branding].some((elem) => {
let reg = new RegExp(elem);
return reg.test(key.campaignName);
})
) {
let brandingIndex = acc.branding.findIndex(
(el) => el.date_debut == key.date_debut
);
if (brandingIndex !== -1) {
// si on a un élément
acc.branding[brandingIndex].search_impression_share +=
parseInt(key.search_impression_share);
} else {
acc.branding.push({
search_impression_share: parseInt(
key.search_impression_share
),
date_debut: key.date_debut,
});
}
} else {
let nobrandingIndex = acc.nobranding.findIndex(
(el) => el.date_debut == key.date_debut
);
if (nobrandingIndex !== -1) {
// si on a un élément
acc.nobranding[nobrandingIndex].search_impression_share +=
parseInt(key.search_impression_share);
} else {
acc.nobranding.push({
search_impression_share: parseInt(
key.search_impression_share
),
date_debut: key.date_debut,
});
}
}
return acc;
},
{ branding: [], nobranding: [] }
);
console.log("==========>>>>",aggregate);
let y = [query.value[0]];
return toEntityResponseCollection([aggregate]);
},
},
},
},
resolversConfig: {
"Query.popularity": {
auth: {
scope: [
"api::impression.impression.findOne",
"api::impression.impression.find",
],
},
},
},
});
Here is my graphql query
query GetPopularity {
popularity(id: "37", startDate:"2022-06-13",endDate:"2022-07-15",branding:"brand") {
myData {
data {
attributes {
googleid {
data {
attributes {
g_customer_id
}
}
}
}
}
}
}
}
When I log the result ssr, I get my computed datas, but when I look at grapql Playground, I get null.
{
"data": {
"popularity": {
"id": {
"data": [
{
"attributes": {
"search_impression_share": null,
"search_top_impression_share": null
}
}
]
}
}
}
}
I don't know what to do to make it work.
I do it like this, because I need to fetch a huge amount of datas. I know that strapi has a 100 limit result from graphql. Even if I can manualy increase it in the config file, I understand it's not a good practice.
If you have any idea how to solve this, please let me know.
Thanks
Fabien
I found how to solve my issue.
I’ve created a specific type which aggregate the datas.
Now I’m able to fetch my computed elements.
"use strict";
module.exports =
(strapi, toEntityResponseCollection, toEntityResponse) =>
({ nexus }) => ({
typeDefs: `
type PopularityResponse {
id: ImpressionEntityResponseCollection
startDate: String
endDate: String
branding: String
aggregated: aggregateInput
}
type aggregateInput {
brand: [singleAggregate]
nobrand: [singleAggregate]
}
type singleAggregate {
date_debut: String
search_impression_share: Int
}
extend type Query {
popularity(id: ID!, startDate: String, endDate: String, branding: String): PopularityResponse
}
`,
resolvers: {
Query: {
popularity: {
resolve: async (parent, args, context) => ({
id: args.id,
startDate: args.startDate,
endDate: args.endDate,
branding: args.branding,
}),
},
},
PopularityResponse: {
aggregated: {
resolve: async (parent, args, ctx) => {
let compile = await strapi.entityService.findMany(
"api::impression.impression",
{
filters: {
googleid: {
id: {
$eq: parent.id,
},
},
date_debut: {
$gte: parent.startDate,
},
date_fin: {
$lte: parent.endDate,
},
},
},
args
);
// console.log(compile);
let aggregate = compile.reduce(
(acc, key) => {
// vérifie si la campagne est dans la liste
if (
[parent.branding].some((elem) => {
let reg = new RegExp(elem);
return reg.test(key.campaignName);
})
) {
let brandingIndex = acc.branding.findIndex(
(el) => el.date_debut == key.date_debut
);
if (brandingIndex !== -1) {
// si on a un élément
acc.branding[brandingIndex].search_impression_share +=
parseInt(key.search_impression_share);
} else {
acc.branding.push({
search_impression_share: parseInt(
key.search_impression_share
),
date_debut: key.date_debut,
});
}
} else {
let nobrandingIndex = acc.nobranding.findIndex(
(el) => el.date_debut == key.date_debut
);
if (nobrandingIndex !== -1) {
// si on a un élément
acc.nobranding[nobrandingIndex].search_impression_share +=
parseInt(key.search_impression_share);
} else {
acc.nobranding.push({
search_impression_share: parseInt(
key.search_impression_share
),
date_debut: key.date_debut,
});
}
}
return acc;
},
{ branding: [], nobranding: [] }
);
return {
brand: aggregate.branding,
nobrand: () => {
return aggregate.nobranding;
},
};
},
},
},
},
resolversConfig: {
"Query.popularity": {
auth: {
scope: [
"api::impression.impression.findOne",
"api::impression.impression.find",
],
},
},
},
});
````
I'd love to implement nested pagination within my application. I have been reading the docs and looking at several other examples but I just can't get this to work - any help is appreciated! Thanks!
React component:
I am clicking the button to run the fetchMore function provided by the useQuery hook (apollo). The network request is going through and the new products are merged into the cache... but no new products render on the page.
export const FilterableKit = () => {
const selectedKitId = useReactiveVar(selectedKitIdVar);
const [
getKitProducts,
{ data: getKitProductsData, loading: getKitProductsLoading, fetchMore },
] = useGetKitProductsLazyQuery();
useEffect(() => {
if (selectedKitId) {
getKitProducts({
variables: {
getKitsInput: {
_id: {
string: selectedKitId,
filterBy: "OBJECTID" as StringFilterByEnum,
},
},
getProductsInput: {
config: {
pagination: {
reverse: true,
limit: 3,
},
},
},
},
});
}
}, [getKitProducts, selectedKitId]);
const kitProducts = getKitProductsData?.getKits.data?.find(
(kit) => kit?._id === selectedKitId
)?.products.data;
const handleLoadMore = () => {
if (kitProducts && kitProducts?.length > 0) {
const remaining =
getKitProductsData?.getKits.data[0]?.products.stats?.remaining;
if (remaining && remaining > 0) {
const cursor =
kitProducts[kitProducts.length - 1] &&
kitProducts[kitProducts.length - 1]?.createdAt;
fetchMore({
variables: {
getProductsInput: {
config: {
pagination: {
reverse: true,
createdAt: cursor,
},
},
},
},
});
}
}
};
return (
<CContainer>
<KitItemCards products={kitProducts} loading={getKitProductsLoading} />
<CContainer className="d-flex justify-content-center my-3">
<CButton color="primary" className="w-100" onClick={handleLoadMore}>
Load More
</CButton>
</CContainer>
</CContainer>
);
};
Type Policies: I define the "Kit" typePolicy to merge products into the correct field.
export const cache: InMemoryCache = new InMemoryCache({
typePolicies: {
Kit: {
fields: {
products: {
keyArgs: false,
merge(existing = [] as Product[], incoming: GetProductsResponse) {
if (!incoming) return existing;
if (!existing) return incoming;
const { data: products, ...rest } = incoming;
let result: any = rest;
result = [...existing, ...(products ?? [])];
return result;
},
},
},
},
});
Thanks for any pointers in the right direction! Let me know if there is something else you'd like to see.
I see this related solution D3js Force Directed Graph Link not found
yet I get the error in the title - "VM2128 d3-force-3d:2 Uncaught Error: node not found: golfing_4_1"
function setNodeId(node) {
return node.id; }
Graph.d3Force('link', d3.forceLink(graphData.links)
.id( (d,i) => setNodeId(d) )
// .strength( d => linkStrength(d) )
);
apparently(?) using version 2.1.1 of d3-force. Perhaps not even d3 itself
the minimally reproducible code:
const graphData = {
nodes: [{
id: "Alice"
},
{
id: "Bob"
},
{
id: "George"
}
],
links: [{
source: "Alice",
target: "George"
},
{
source: "George",
target: "Bob"
}
]
};
const elem = document.getElementById('3d-graph');
const Graph = ForceGraph3D()(elem)
.graphData(graphData);
function setNodeId(node) {
return node.id;
}
function linkStrength(link) {
return (1 / link.sourceLevel);
}
Graph.d3Force('link', d3.forceLink(graphData.links)
.id((d, i) => setNodeId(d))
// .distance(200)
// .strength( d => linkStrength(d) )
);
<script src="https://unpkg.com/d3-force-3d"></script>
<script src="https://unpkg.com/3d-force-graph"></script>
<div id="3d-graph"></div>
The underlying problem was that you needed to pass the entire graphData to your d3.forceLink function, not just graphData.link. However, I think the following solution is cleaner:
From the documentation of 3d-force-graph for Graph.d3Force():
Getter/setter for the internal forces that control the d3 simulation engine. Follows the same interface as d3-force-3d's simulation.force. Three forces are included by default: 'link' (based on forceLink), 'charge' (based on forceManyBody) and 'center' (based on forceCenter).
This means that you can call the function with only a string 'link' and you get an object of type d3-force-3d.forceLink, which is automatically applied and thus automatically has access to the right graphData. Then, you can set forceLink.id just like you did, but you can also set it later.
const graphData = {
nodes: [{
id: "Alice"
},
{
id: "Bob"
},
{
id: "George"
}
],
links: [{
source: "Alice",
target: "George"
},
{
source: "George",
target: "Bob"
}
]
};
const elem = document.getElementById('3d-graph');
const Graph = ForceGraph3D()(elem)
.graphData(graphData);
function setNodeId(node) {
return node.id;
}
const linkForce = Graph.d3Force('link')
.id((d, i) => setNodeId(d));
<script src="https://unpkg.com/d3-force-3d#2.2.0/dist/d3-force-3d.js"></script>
<script src="https://unpkg.com/3d-force-graph#1.67.3/dist/3d-force-graph.js"></script>
<div id="3d-graph"></div>
I have this object in my dynamodb table which looks like
{
"id": "b31de483"
}
I want to add another object that looks like
{
"id": "b31de483",
"players": [{"playerId": "1234"}]
}
This is my code
const addPlayerToGame = async (gameId, playerId) => {
const params = {
TableName: process.env.DYNAMODB_GAMES_TABLE,
Key: {
id: gameId
},
UpdateExpression: 'set players = list_append(if_not_exists(players, :players)',
ExpressionAttributeValues: {
':players': {
"L": [
{ "S": playerId }
]
}
}
};
return await documentClient.update(params);
}
This throws an error but I cannot understand how to fix it. I am looking at documentation here
Figured it out
const addPlayerToGame = async (gameId, playerId) => {
const params = {
TableName: process.env.DYNAMODB_GAMES_TABLE,
Key: {
id: gameId
},
UpdateExpression: 'set players = list_append(players, :players)',
ExpressionAttributeValues: {
':players': [{
"playerId": playerId
}]
}
};
return await documentClient.update(params).promise();
}
Hi Guys I'm trying to filter post with data json format field?
"categoryList": ["cat", "cat1"]
For anyone still looking for a solution, this is what I have done for a json type field called tags of a collection type called Articles.
I have two articles in the database with one article having the following values set:
title: "lorem ipsum 1",
tags: [
"test",
"rest"
]
The other article has the following values set:
title: "lorem ipsum 2",
tags: [
"test",
"graphql"
]
My graphql query looks like this:
query {
articlesByTag(limit: 2, where: {tags_include: ["test", "rest"]}, start: 0, sort: "title:asc") {
title,
tags
}
}
While my rest query looks like this:
http://localhost:1337/articlesByTag?limit=2&tags_include[]=test&tags_include[]=rest
This is my articles.js service file:
const { convertRestQueryParams, buildQuery } = require('strapi-utils');
const _ = require('lodash');
const { convertToParams, convertToQuery } = require('../../../node_modules/strapi-plugin-graphql/services/utils');
module.exports = {
async findByTag(ctx) {
let tags_include;
if (ctx.where && ctx.where.tags_include && ctx.where.tags_include.length > 0) {
tags_include = ctx.where.tags_include;
delete ctx.where.tags_include;
} else if (ctx.query && ctx.query.tags_include && ctx.query.tags_include.length > 0) {
tags_include = ctx.query.tags_include;
delete ctx.query.tags_include;
}
if (!Array.isArray(tags_include)) {
tags_include = [tags_include];
}
let filters = null;
if (ctx.query) {
filters = convertRestQueryParams({
...convertToParams(ctx.query)
});
} else {
filters = convertRestQueryParams({
...convertToParams(_.pick(ctx, ['limit', 'start', 'sort'])),
...convertToQuery(ctx.where),
});
}
const entities = await strapi.query('articles').model.query(qb => {
buildQuery({ model: strapi.query('articles').model, filters: filters })(qb);
if (tags_include.length > 0) {
tags_include.forEach((tag) => {
if (tag && tag.length > 0) {
const likeStr = `%"${tag}"%`;
qb.andWhere('tags', 'like', likeStr);
}
});
}
}).fetchAll();
return entities;
},
};
This is the entry needed in routes.js
{
"method": "GET",
"path": "/articlesByTag",
"handler": "articles.findByTag",
"config": {
"policies": []
}
}
This is the controller articles.js
const { sanitizeEntity } = require('strapi-utils');
module.exports = {
async findByTag(ctx) {
const entities = await strapi.services.articles.findByTag(ctx);
return entities.map(entity => sanitizeEntity(entity, { model: strapi.models.articles }));
},
};
And finally this is the schema.graphql.js
module.exports = {
query: `
articlesByTag(sort: String, limit: Int, start: Int, where: JSON): [Articles]
`,
resolver: {
Query: {
articlesByTag: {
description: 'Return articles filtered by tag',
resolverOf: 'application::articles.articles.findByTag',
resolver: async (obj, options, ctx) => {
return await strapi.api.articles.controllers.articles.findByTag(options);
},
},
},
},
};
There is not currently a way to filter the JSON fields yet as of beta.17.8 (latest)
Probably something like that?
strapi.query('cool_model').find({ categoryList: { $all: [ "cat" , "cat1" ] } })